Beispiel #1
0
bool SpeculativeExecution::considerHoistingFromTo(BasicBlock &FromBlock,
                                                  BasicBlock &ToBlock) {
  SmallSet<const Instruction *, 8> NotHoisted;
  const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](User *U) {
    for (Value* V : U->operand_values()) {
      if (Instruction *I = dyn_cast<Instruction>(V)) {
        if (NotHoisted.count(I) > 0)
          return false;
      }
    }
    return true;
  };

  unsigned TotalSpeculationCost = 0;
  for (auto& I : FromBlock) {
    const unsigned Cost = ComputeSpeculationCost(&I, *TTI);
    if (Cost != UINT_MAX && isSafeToSpeculativelyExecute(&I) &&
        AllPrecedingUsesFromBlockHoisted(&I)) {
      TotalSpeculationCost += Cost;
      if (TotalSpeculationCost > SpecExecMaxSpeculationCost)
        return false;  // too much to hoist
    } else {
      NotHoisted.insert(&I);
      if (NotHoisted.size() > SpecExecMaxNotHoisted)
        return false; // too much left behind
    }
  }

  if (TotalSpeculationCost == 0)
    return false; // nothing to hoist

  for (auto I = FromBlock.begin(); I != FromBlock.end();) {
    // We have to increment I before moving Current as moving Current
    // changes the list that I is iterating through.
    auto Current = I;
    ++I;
    if (!NotHoisted.count(Current)) {
      Current->moveBefore(ToBlock.getTerminator());
    }
  }
  return true;
}