bool SpeculativeExecutionPass::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;
}
//
// Check if instruction is invariant.
//
bool LicmPass::isInvariant(const Loop* loop,
                           Invariants& invariants, Instruction* instr) {

    // Must also satisfy these conditions to ensure safety of movement.
    if (!isSafeToSpeculativelyExecute(instr) ||
            instr->mayReadFromMemory() ||
            isa<LandingPadInst>(instr)) {
        return false;
    }

    // See if all operands are invariant.
    for (User::op_iterator OI = instr->op_begin(), OE = instr->op_end();
            OI != OE; ++OI) {
        Value *operand = *OI;
        if (!isInvariant(loop, invariants, operand)) {
            return false;
        }
    }

    // Satisfies all conditions.
    return true;
}