23#define DEBUG_TYPE "codemover-utils" 
   26          "Cannot move across instructions that has memory dependences");
 
   27STATISTIC(MayThrowException, 
"Cannot move across instructions that may throw");
 
   29          "Instructions are not control flow equivalent");
 
   30STATISTIC(NotMovedPHINode, 
"Movement of PHINodes are not supported");
 
   31STATISTIC(NotMovedTerminator, 
"Movement of Terminator are not supported");
 
   44  OS << 
"[" << *
C.getPointer() << 
", " << (
C.getInt() ? 
"true" : 
"false")
 
   51class ControlConditions {
 
   52  using ConditionVectorTy = SmallVector<ControlCondition, 6>;
 
   55  ConditionVectorTy Conditions;
 
   62  static const std::optional<ControlConditions>
 
   63  collectControlConditions(
const BasicBlock &BB, 
const BasicBlock &Dominator,
 
   64                           const DominatorTree &DT,
 
   65                           const PostDominatorTree &PDT,
 
   66                           unsigned MaxLookup = 6);
 
   70  bool isUnconditional()
 const { 
return Conditions.empty(); }
 
   73  const ConditionVectorTy &getControlConditions()
 const { 
return Conditions; }
 
   77  bool addControlCondition(ControlCondition 
C);
 
   81  bool isEquivalent(
const ControlConditions &
Other) 
const;
 
   84  static bool isEquivalent(
const ControlCondition &C1,
 
   85                           const ControlCondition &C2);
 
   88  ControlConditions() = 
default;
 
   90  static bool isEquivalent(
const Value &V1, 
const Value &V2);
 
   91  static bool isInverse(
const Value &V1, 
const Value &V2);
 
  104  return DA->getLevel() < DB->getLevel();
 
 
  107const std::optional<ControlConditions>
 
  108ControlConditions::collectControlConditions(
const BasicBlock &BB,
 
  112                                            unsigned MaxLookup) {
 
  113  assert(DT.
dominates(&Dominator, &BB) && 
"Expecting Dominator to dominate BB");
 
  115  ControlConditions Conditions;
 
  116  unsigned NumConditions = 0;
 
  119  if (&Dominator == &BB)
 
  126    assert(DT.
getNode(CurBlock) && 
"Expecting a valid DT node for CurBlock");
 
  129           "Expecting Dominator to dominate IDom");
 
  139                        << 
" is executed unconditionally from " 
  145      Inserted = Conditions.addControlCondition(
 
  151      Inserted = Conditions.addControlCondition(
 
  159    if (MaxLookup != 0 && NumConditions > MaxLookup)
 
  163  } 
while (CurBlock != &Dominator);
 
  168bool ControlConditions::addControlCondition(ControlCondition 
C) {
 
  170  if (
none_of(Conditions, [&](ControlCondition &Exists) {
 
  171        return ControlConditions::isEquivalent(
C, Exists);
 
  173    Conditions.push_back(
C);
 
  177  LLVM_DEBUG(
dbgs() << (Inserted ? 
"Inserted " : 
"Not inserted ") << 
C << 
"\n");
 
  181bool ControlConditions::isEquivalent(
const ControlConditions &
Other)
 const {
 
  182  if (Conditions.empty() && 
Other.Conditions.
empty())
 
  185  if (Conditions.size() != 
Other.Conditions.
size())
 
  188  return all_of(Conditions, [&](
const ControlCondition &
C) {
 
  189    return any_of(
Other.Conditions, [&](
const ControlCondition &OtherC) {
 
  190      return ControlConditions::isEquivalent(C, OtherC);
 
  195bool ControlConditions::isEquivalent(
const ControlCondition &C1,
 
  196                                     const ControlCondition &C2) {
 
  197  if (C1.getInt() == C2.getInt()) {
 
  198    if (isEquivalent(*C1.getPointer(), *C2.getPointer()))
 
  200  } 
else if (isInverse(*C1.getPointer(), *C2.getPointer()))
 
  210bool ControlConditions::isEquivalent(
const Value &V1, 
const Value &V2) {
 
  214bool ControlConditions::isInverse(
const Value &V1, 
const Value &V2) {
 
  217      if (Cmp1->getPredicate() == Cmp2->getInversePredicate() &&
 
  218          Cmp1->getOperand(0) == Cmp2->getOperand(0) &&
 
  219          Cmp1->getOperand(1) == Cmp2->getOperand(1))
 
  222      if (Cmp1->getPredicate() ==
 
  224          Cmp1->getOperand(0) == Cmp2->getOperand(1) &&
 
  225          Cmp1->getOperand(1) == Cmp2->getOperand(0))
 
  251                    << 
" and " << BB1.
getName() << 
" is " 
  252                    << CommonDominator->
getName() << 
"\n");
 
  254  const std::optional<ControlConditions> BB0Conditions =
 
  255      ControlConditions::collectControlConditions(BB0, *CommonDominator, DT,
 
  257  if (BB0Conditions == std::nullopt)
 
  260  const std::optional<ControlConditions> BB1Conditions =
 
  261      ControlConditions::collectControlConditions(BB1, *CommonDominator, DT,
 
  263  if (BB1Conditions == std::nullopt)
 
  266  return BB0Conditions->isEquivalent(*BB1Conditions);
 
 
  282  assert(InBetweenInsts.
empty() && 
"Expecting InBetweenInsts to be empty");
 
  288      WorkList.insert(NextInst);
 
  290      assert(
I.isTerminator() && 
"Expecting a terminator instruction");
 
  292        WorkList.insert(&Succ->front());
 
  297  getNextInsts(StartInst, WorkList);
 
  298  while (!WorkList.
empty()) {
 
  300    WorkList.
erase(CurInst);
 
  302    if (CurInst == &EndInst)
 
  305    if (!InBetweenInsts.
insert(CurInst).second)
 
  308    getNextInsts(*CurInst, WorkList);
 
 
  320  if (&
I == &InsertPoint)
 
  324  if (
I.getNextNode() == &InsertPoint)
 
  330  if (
I.isTerminator())
 
  338    for (
const Use &U : 
I.uses())
 
  342        if (
I.getParent() == InsertPoint.
getParent() &&
 
  343            UserInst == 
I.getParent()->getTerminator())
 
  345        if (UserInst != &InsertPoint && !DT.
dominates(&InsertPoint, U)) {
 
  349          if (CheckForEntireBlock && 
I.getParent() == UserInst->getParent() &&
 
  356    for (
const Value *
Op : 
I.operands())
 
  358        if (&InsertPoint == OpInst)
 
  362        if (CheckForEntireBlock && 
I.getParent() == OpInst->getParent() &&
 
  371  Instruction &StartInst = (MoveForward ? 
I : InsertPoint);
 
  376    InstsToCheck.
insert(&InsertPoint);
 
  388          if (!CB->
hasFnAttr(Attribute::WillReturn))
 
  401        auto DepResult = DI->
depends(&
I, CurInst);
 
  402        if (DepResult && (DepResult->isOutput() || DepResult->isFlow() ||
 
  403                          DepResult->isAnti()))
 
 
  433      I.moveBeforePreserving(MovePos);
 
 
  442  while (FromBB.
size() > 1) {
 
 
  454         "ThisBlock and OtherBlock must be CFG equivalent!");
 
  457  if (CommonDominator == 
nullptr)
 
  466  while (!WorkList.
empty()) {
 
  469    if (PDT->
dominates(CurBlock, OtherBlock))
 
  473      if (Pred == CommonDominator || Visited.
count(Pred))
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
static bool reportInvalidCandidate(const Instruction &I, llvm::Statistic &Stat)
 
static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, const Instruction *InstB)
 
static void collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst, SmallPtrSetImpl< Instruction * > &InBetweenInsts)
Collect all instructions in between StartInst and EndInst, and store them in InBetweenInsts.
 
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
 
#define STATISTIC(VARNAME, DESC)
 
LLVM Basic Block Representation.
 
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
 
const Instruction & front() const
 
InstListType::iterator iterator
Instruction iterators...
 
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
 
BasicBlock * getSuccessor(unsigned i) const
 
Value * getCondition() const
 
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
 
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
 
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
 
DependenceInfo - This class is the main dependence-analysis driver.
 
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
 
DomTreeNodeBase * getIDom() const
 
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
 
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
 
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
 
LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
 
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
 
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
 
PointerIntPair - This class implements a pair of a pointer and small integer.
 
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
 
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
 
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
 
bool erase(PtrType Ptr)
Remove pointer from the set.
 
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
 
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
 
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
 
void push_back(const T &Elt)
 
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
 
A Use represents the edge between a Value definition and its users.
 
LLVM Value Representation.
 
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
 
const ParentTy * getParent() const
 
self_iterator getIterator()
 
This class implements an extremely fast bulk output stream that can only output to a stream.
 
@ C
The default llvm calling convention, compatible with C.
 
@ BasicBlock
Various leaf nodes.
 
This is an optimization pass for GlobalISel generic memory operations.
 
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
 
FunctionAddr VTableAddr Value
 
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
auto successors(const MachineBasicBlock *BB)
 
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
 
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
 
LLVM_ABI void moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB, DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI)
Move instructions, in an order-preserving manner, from FromBB to the end of ToBB when proven safe.
 
LLVM_ABI bool isReachedBefore(const Instruction *I0, const Instruction *I1, const DominatorTree *DT, const PostDominatorTree *PDT)
 
DomTreeNodeBase< BasicBlock > DomTreeNode
 
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
 
auto reverse(ContainerTy &&C)
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
 
LLVM_ABI bool isControlFlowEquivalent(const Instruction &I0, const Instruction &I1, const DominatorTree &DT, const PostDominatorTree &PDT)
Return true if I0 and I1 are control flow equivalent.
 
LLVM_ABI bool nonStrictlyPostDominate(const BasicBlock *ThisBlock, const BasicBlock *OtherBlock, const DominatorTree *DT, const PostDominatorTree *PDT)
In case that two BBs ThisBlock and OtherBlock are control flow equivalent but they do not strictly do...
 
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
 
LLVM_ABI void moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB, DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI)
Move instructions, in an order-preserving manner, from FromBB to the beginning of ToBB when proven sa...
 
DWARFExpression::Operation Op
 
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
 
auto predecessors(const MachineBasicBlock *BB)
 
LLVM_ABI bool isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, DominatorTree &DT, const PostDominatorTree *PDT=nullptr, DependenceInfo *DI=nullptr, bool CheckForEntireBlock=false)
Return true if I can be safely moved before InsertPoint.