Ejemplo n.º 1
0
void CSDataRando::findArgNodes(Module &M) {
  // Create function equivalence classes from the global equivalence classes.
  EquivalenceClasses<const GlobalValue*> &GlobalECs = DSA->getGlobalECs();
  EquivalenceClasses<const Function*> FunctionECs;

  for (auto ei = GlobalECs.begin(), ee = GlobalECs.end(); ei != ee; ei++) {
    // Ignore non-leader values.
    if (!ei->isLeader()) { continue; }

    const Function *Leader = nullptr;
    for (auto mi = GlobalECs.member_begin(ei), me = GlobalECs.member_end();
         mi != me;
         mi++) {
      // Only look at functions.
      if (const Function *F = dyn_cast<Function>(*mi)) {
        if (Leader) {
          FunctionECs.unionSets(Leader, F);
        } else {
          Leader = FunctionECs.getOrInsertLeaderValue(F);
        }
      }
    }
  }

  // Make sure all Functions are part of an equivalence class. This is important
  // since non-address taken functions may not appear in GlobalECs.
  for (Function &F : M) {
    if (!F.isDeclaration()) {
      FunctionECs.insert(&F);
    }
  }

  // Go through all equivalence classes and determine the additional
  // arguments.
  for (auto ei = FunctionECs.begin(), ee = FunctionECs.end();ei != ee; ei++) {
    if (ei->isLeader()) {
      NumFunctionECs++;
      std::vector<const Function*> Functions;
      Functions.insert(Functions.end(), FunctionECs.member_begin(ei), FunctionECs.member_end());

      // If we can't safely replace uses of the function's address with its
      // clone's address then we can't safely transform indirect calls to this
      // equivalence class. We still find the arg nodes for each function to
      // replace direct calls to these functions.
      if (!DSA->canReplaceAddress(ei->getData())) {
        NumFunECsWithExternal++;
        for (const Function *F : Functions) {
          if (!F->isDeclaration()) {
            findFunctionArgNodes(F);
            FunctionInfo[F].CanReplaceAddress = false;
          }
        }
      } else {
        findFunctionArgNodes(Functions);
      }
    }
  }
}
ObservationTable::EquivalenceClasses ObservationTable::_getEquivalenceClasses(bool ofK)
{
    EquivalenceClasses equivalenceClasses;
    StringSet& localK = ofK ? this->K : this->_KK;

    // Divide K into equivalence classes according to \equiv F
    for (string k : localK) {
        ContextSet distribution = this->_getDistributionByK(k);
        auto equivalenceClass = equivalenceClasses.find(distribution);

        if (equivalenceClass != equivalenceClasses.end()) { // Found
            equivalenceClass->second.insert(k);
        } else { // Not found
            StringSet ks; // set of k strings
            ks.insert(k);
            equivalenceClasses.insert({ distribution, ks });
        }
    }
    return equivalenceClasses;
}
Ejemplo n.º 3
0
bool AArch64A57FPLoadBalancing::runOnBasicBlock(MachineBasicBlock &MBB) {
  bool Changed = false;
  DEBUG(dbgs() << "Running on MBB: " << MBB << " - scanning instructions...\n");

  // First, scan the basic block producing a set of chains.

  // The currently "active" chains - chains that can be added to and haven't
  // been killed yet. This is keyed by register - all chains can only have one
  // "link" register between each inst in the chain.
  std::map<unsigned, Chain*> ActiveChains;
  std::set<Chain*> AllChains;
  unsigned Idx = 0;
  for (auto &MI : MBB)
    scanInstruction(&MI, Idx++, ActiveChains, AllChains);

  DEBUG(dbgs() << "Scan complete, "<< AllChains.size() << " chains created.\n");

  // Group the chains into disjoint sets based on their liveness range. This is
  // a poor-man's version of graph coloring. Ideally we'd create an interference
  // graph and perform full-on graph coloring on that, but;
  //   (a) That's rather heavyweight for only two colors.
  //   (b) We expect multiple disjoint interference regions - in practice the live
  //       range of chains is quite small and they are clustered between loads
  //       and stores.
  EquivalenceClasses<Chain*> EC;
  for (auto *I : AllChains)
    EC.insert(I);

  for (auto *I : AllChains) {
    for (auto *J : AllChains) {
      if (I != J && I->rangeOverlapsWith(J))
        EC.unionSets(I, J);
    }
  }
  DEBUG(dbgs() << "Created " << EC.getNumClasses() << " disjoint sets.\n");

  // Now we assume that every member of an equivalence class interferes
  // with every other member of that class, and with no members of other classes.

  // Convert the EquivalenceClasses to a simpler set of sets.
  std::vector<std::vector<Chain*> > V;
  for (auto I = EC.begin(), E = EC.end(); I != E; ++I) {
    std::vector<Chain*> Cs(EC.member_begin(I), EC.member_end());
    if (Cs.empty()) continue;
    V.push_back(Cs);
  }

  // Now we have a set of sets, order them by start address so
  // we can iterate over them sequentially.
  std::sort(V.begin(), V.end(),
            [](const std::vector<Chain*> &A,
               const std::vector<Chain*> &B) {
      return A.front()->startsBefore(B.front());
    });

  // As we only have two colors, we can track the global (BB-level) balance of
  // odds versus evens. We aim to keep this near zero to keep both execution
  // units fed.
  // Positive means we're even-heavy, negative we're odd-heavy.
  //
  // FIXME: If chains have interdependencies, for example:
  //   mul r0, r1, r2
  //   mul r3, r0, r1
  // We do not model this and may color each one differently, assuming we'll
  // get ILP when we obviously can't. This hasn't been seen to be a problem
  // in practice so far, so we simplify the algorithm by ignoring it.
  int Parity = 0;

  for (auto &I : V)
    Changed |= colorChainSet(I, MBB, Parity);

  for (auto *C : AllChains)
    delete C;

  return Changed;
}