1480093f4SDimitry Andric //===- CodeMoverUtils.cpp - CodeMover Utilities ----------------------------==// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This family of functions perform movements on basic blocks, and instructions 10480093f4SDimitry Andric // contained within a function. 11480093f4SDimitry Andric // 12480093f4SDimitry Andric //===----------------------------------------------------------------------===// 13480093f4SDimitry Andric 14480093f4SDimitry Andric #include "llvm/Transforms/Utils/CodeMoverUtils.h" 155ffd83dbSDimitry Andric #include "llvm/ADT/Optional.h" 16480093f4SDimitry Andric #include "llvm/ADT/Statistic.h" 17480093f4SDimitry Andric #include "llvm/Analysis/DependenceAnalysis.h" 18480093f4SDimitry Andric #include "llvm/Analysis/PostDominators.h" 19480093f4SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 20480093f4SDimitry Andric #include "llvm/IR/Dominators.h" 21480093f4SDimitry Andric 22480093f4SDimitry Andric using namespace llvm; 23480093f4SDimitry Andric 24480093f4SDimitry Andric #define DEBUG_TYPE "codemover-utils" 25480093f4SDimitry Andric 26480093f4SDimitry Andric STATISTIC(HasDependences, 27480093f4SDimitry Andric "Cannot move across instructions that has memory dependences"); 28480093f4SDimitry Andric STATISTIC(MayThrowException, "Cannot move across instructions that may throw"); 29480093f4SDimitry Andric STATISTIC(NotControlFlowEquivalent, 30480093f4SDimitry Andric "Instructions are not control flow equivalent"); 31480093f4SDimitry Andric STATISTIC(NotMovedPHINode, "Movement of PHINodes are not supported"); 32480093f4SDimitry Andric STATISTIC(NotMovedTerminator, "Movement of Terminator are not supported"); 33480093f4SDimitry Andric 345ffd83dbSDimitry Andric namespace { 355ffd83dbSDimitry Andric /// Represent a control condition. A control condition is a condition of a 365ffd83dbSDimitry Andric /// terminator to decide which successors to execute. The pointer field 375ffd83dbSDimitry Andric /// represents the address of the condition of the terminator. The integer field 385ffd83dbSDimitry Andric /// is a bool, it is true when the basic block is executed when V is true. For 395ffd83dbSDimitry Andric /// example, `br %cond, bb0, bb1` %cond is a control condition of bb0 with the 405ffd83dbSDimitry Andric /// integer field equals to true, while %cond is a control condition of bb1 with 415ffd83dbSDimitry Andric /// the integer field equals to false. 425ffd83dbSDimitry Andric using ControlCondition = PointerIntPair<Value *, 1, bool>; 435ffd83dbSDimitry Andric #ifndef NDEBUG 445ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ControlCondition &C) { 455ffd83dbSDimitry Andric OS << "[" << *C.getPointer() << ", " << (C.getInt() ? "true" : "false") 465ffd83dbSDimitry Andric << "]"; 475ffd83dbSDimitry Andric return OS; 485ffd83dbSDimitry Andric } 495ffd83dbSDimitry Andric #endif 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric /// Represent a set of control conditions required to execute ToBB from FromBB. 525ffd83dbSDimitry Andric class ControlConditions { 535ffd83dbSDimitry Andric using ConditionVectorTy = SmallVector<ControlCondition, 6>; 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric /// A SmallVector of control conditions. 565ffd83dbSDimitry Andric ConditionVectorTy Conditions; 575ffd83dbSDimitry Andric 585ffd83dbSDimitry Andric public: 595ffd83dbSDimitry Andric /// Return a ControlConditions which stores all conditions required to execute 605ffd83dbSDimitry Andric /// \p BB from \p Dominator. If \p MaxLookup is non-zero, it limits the 615ffd83dbSDimitry Andric /// number of conditions to collect. Return None if not all conditions are 625ffd83dbSDimitry Andric /// collected successfully, or we hit the limit. 635ffd83dbSDimitry Andric static const Optional<ControlConditions> 645ffd83dbSDimitry Andric collectControlConditions(const BasicBlock &BB, const BasicBlock &Dominator, 655ffd83dbSDimitry Andric const DominatorTree &DT, 665ffd83dbSDimitry Andric const PostDominatorTree &PDT, 675ffd83dbSDimitry Andric unsigned MaxLookup = 6); 685ffd83dbSDimitry Andric 695ffd83dbSDimitry Andric /// Return true if there exists no control conditions required to execute ToBB 705ffd83dbSDimitry Andric /// from FromBB. 715ffd83dbSDimitry Andric bool isUnconditional() const { return Conditions.empty(); } 725ffd83dbSDimitry Andric 735ffd83dbSDimitry Andric /// Return a constant reference of Conditions. 745ffd83dbSDimitry Andric const ConditionVectorTy &getControlConditions() const { return Conditions; } 755ffd83dbSDimitry Andric 765ffd83dbSDimitry Andric /// Add \p V as one of the ControlCondition in Condition with IsTrueCondition 775ffd83dbSDimitry Andric /// equals to \p True. Return true if inserted successfully. 785ffd83dbSDimitry Andric bool addControlCondition(ControlCondition C); 795ffd83dbSDimitry Andric 805ffd83dbSDimitry Andric /// Return true if for all control conditions in Conditions, there exists an 815ffd83dbSDimitry Andric /// equivalent control condition in \p Other.Conditions. 825ffd83dbSDimitry Andric bool isEquivalent(const ControlConditions &Other) const; 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric /// Return true if \p C1 and \p C2 are equivalent. 855ffd83dbSDimitry Andric static bool isEquivalent(const ControlCondition &C1, 865ffd83dbSDimitry Andric const ControlCondition &C2); 875ffd83dbSDimitry Andric 885ffd83dbSDimitry Andric private: 895ffd83dbSDimitry Andric ControlConditions() = default; 905ffd83dbSDimitry Andric 915ffd83dbSDimitry Andric static bool isEquivalent(const Value &V1, const Value &V2); 925ffd83dbSDimitry Andric static bool isInverse(const Value &V1, const Value &V2); 935ffd83dbSDimitry Andric }; 945ffd83dbSDimitry Andric } // namespace 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, 975ffd83dbSDimitry Andric const Instruction *InstB) { 985ffd83dbSDimitry Andric // Use ordered basic block in case the 2 instructions are in the same 995ffd83dbSDimitry Andric // block. 1005ffd83dbSDimitry Andric if (InstA->getParent() == InstB->getParent()) 1015ffd83dbSDimitry Andric return InstA->comesBefore(InstB); 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric DomTreeNode *DA = DT->getNode(InstA->getParent()); 1045ffd83dbSDimitry Andric DomTreeNode *DB = DT->getNode(InstB->getParent()); 1055ffd83dbSDimitry Andric return DA->getLevel() < DB->getLevel(); 1065ffd83dbSDimitry Andric } 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric const Optional<ControlConditions> ControlConditions::collectControlConditions( 1095ffd83dbSDimitry Andric const BasicBlock &BB, const BasicBlock &Dominator, const DominatorTree &DT, 1105ffd83dbSDimitry Andric const PostDominatorTree &PDT, unsigned MaxLookup) { 1115ffd83dbSDimitry Andric assert(DT.dominates(&Dominator, &BB) && "Expecting Dominator to dominate BB"); 1125ffd83dbSDimitry Andric 1135ffd83dbSDimitry Andric ControlConditions Conditions; 1145ffd83dbSDimitry Andric unsigned NumConditions = 0; 1155ffd83dbSDimitry Andric 1165ffd83dbSDimitry Andric // BB is executed unconditional from itself. 1175ffd83dbSDimitry Andric if (&Dominator == &BB) 1185ffd83dbSDimitry Andric return Conditions; 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric const BasicBlock *CurBlock = &BB; 1215ffd83dbSDimitry Andric // Walk up the dominator tree from the associated DT node for BB to the 1225ffd83dbSDimitry Andric // associated DT node for Dominator. 1235ffd83dbSDimitry Andric do { 1245ffd83dbSDimitry Andric assert(DT.getNode(CurBlock) && "Expecting a valid DT node for CurBlock"); 1255ffd83dbSDimitry Andric BasicBlock *IDom = DT.getNode(CurBlock)->getIDom()->getBlock(); 1265ffd83dbSDimitry Andric assert(DT.dominates(&Dominator, IDom) && 1275ffd83dbSDimitry Andric "Expecting Dominator to dominate IDom"); 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric // Limitation: can only handle branch instruction currently. 1305ffd83dbSDimitry Andric const BranchInst *BI = dyn_cast<BranchInst>(IDom->getTerminator()); 1315ffd83dbSDimitry Andric if (!BI) 1325ffd83dbSDimitry Andric return None; 1335ffd83dbSDimitry Andric 1345ffd83dbSDimitry Andric bool Inserted = false; 1355ffd83dbSDimitry Andric if (PDT.dominates(CurBlock, IDom)) { 1365ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() 1375ffd83dbSDimitry Andric << " is executed unconditionally from " 1385ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1395ffd83dbSDimitry Andric } else if (PDT.dominates(CurBlock, BI->getSuccessor(0))) { 1405ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 1415ffd83dbSDimitry Andric << *BI->getCondition() << "\" is true from " 1425ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1435ffd83dbSDimitry Andric Inserted = Conditions.addControlCondition( 1445ffd83dbSDimitry Andric ControlCondition(BI->getCondition(), true)); 1455ffd83dbSDimitry Andric } else if (PDT.dominates(CurBlock, BI->getSuccessor(1))) { 1465ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 1475ffd83dbSDimitry Andric << *BI->getCondition() << "\" is false from " 1485ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1495ffd83dbSDimitry Andric Inserted = Conditions.addControlCondition( 1505ffd83dbSDimitry Andric ControlCondition(BI->getCondition(), false)); 1515ffd83dbSDimitry Andric } else 1525ffd83dbSDimitry Andric return None; 1535ffd83dbSDimitry Andric 1545ffd83dbSDimitry Andric if (Inserted) 1555ffd83dbSDimitry Andric ++NumConditions; 1565ffd83dbSDimitry Andric 1575ffd83dbSDimitry Andric if (MaxLookup != 0 && NumConditions > MaxLookup) 1585ffd83dbSDimitry Andric return None; 1595ffd83dbSDimitry Andric 1605ffd83dbSDimitry Andric CurBlock = IDom; 1615ffd83dbSDimitry Andric } while (CurBlock != &Dominator); 1625ffd83dbSDimitry Andric 1635ffd83dbSDimitry Andric return Conditions; 1645ffd83dbSDimitry Andric } 1655ffd83dbSDimitry Andric 1665ffd83dbSDimitry Andric bool ControlConditions::addControlCondition(ControlCondition C) { 1675ffd83dbSDimitry Andric bool Inserted = false; 1685ffd83dbSDimitry Andric if (none_of(Conditions, [&](ControlCondition &Exists) { 1695ffd83dbSDimitry Andric return ControlConditions::isEquivalent(C, Exists); 1705ffd83dbSDimitry Andric })) { 1715ffd83dbSDimitry Andric Conditions.push_back(C); 1725ffd83dbSDimitry Andric Inserted = true; 1735ffd83dbSDimitry Andric } 1745ffd83dbSDimitry Andric 1755ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << (Inserted ? "Inserted " : "Not inserted ") << C << "\n"); 1765ffd83dbSDimitry Andric return Inserted; 1775ffd83dbSDimitry Andric } 1785ffd83dbSDimitry Andric 1795ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const ControlConditions &Other) const { 1805ffd83dbSDimitry Andric if (Conditions.empty() && Other.Conditions.empty()) 1815ffd83dbSDimitry Andric return true; 1825ffd83dbSDimitry Andric 1835ffd83dbSDimitry Andric if (Conditions.size() != Other.Conditions.size()) 1845ffd83dbSDimitry Andric return false; 1855ffd83dbSDimitry Andric 1865ffd83dbSDimitry Andric return all_of(Conditions, [&](const ControlCondition &C) { 1875ffd83dbSDimitry Andric return any_of(Other.Conditions, [&](const ControlCondition &OtherC) { 1885ffd83dbSDimitry Andric return ControlConditions::isEquivalent(C, OtherC); 1895ffd83dbSDimitry Andric }); 1905ffd83dbSDimitry Andric }); 1915ffd83dbSDimitry Andric } 1925ffd83dbSDimitry Andric 1935ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const ControlCondition &C1, 1945ffd83dbSDimitry Andric const ControlCondition &C2) { 1955ffd83dbSDimitry Andric if (C1.getInt() == C2.getInt()) { 1965ffd83dbSDimitry Andric if (isEquivalent(*C1.getPointer(), *C2.getPointer())) 1975ffd83dbSDimitry Andric return true; 1985ffd83dbSDimitry Andric } else if (isInverse(*C1.getPointer(), *C2.getPointer())) 1995ffd83dbSDimitry Andric return true; 2005ffd83dbSDimitry Andric 2015ffd83dbSDimitry Andric return false; 2025ffd83dbSDimitry Andric } 2035ffd83dbSDimitry Andric 2045ffd83dbSDimitry Andric // FIXME: Use SCEV and reuse GVN/CSE logic to check for equivalence between 2055ffd83dbSDimitry Andric // Values. 2065ffd83dbSDimitry Andric // Currently, isEquivalent rely on other passes to ensure equivalent conditions 2075ffd83dbSDimitry Andric // have the same value, e.g. GVN. 2085ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const Value &V1, const Value &V2) { 2095ffd83dbSDimitry Andric return &V1 == &V2; 2105ffd83dbSDimitry Andric } 2115ffd83dbSDimitry Andric 2125ffd83dbSDimitry Andric bool ControlConditions::isInverse(const Value &V1, const Value &V2) { 2135ffd83dbSDimitry Andric if (const CmpInst *Cmp1 = dyn_cast<CmpInst>(&V1)) 2145ffd83dbSDimitry Andric if (const CmpInst *Cmp2 = dyn_cast<CmpInst>(&V2)) { 2155ffd83dbSDimitry Andric if (Cmp1->getPredicate() == Cmp2->getInversePredicate() && 2165ffd83dbSDimitry Andric Cmp1->getOperand(0) == Cmp2->getOperand(0) && 2175ffd83dbSDimitry Andric Cmp1->getOperand(1) == Cmp2->getOperand(1)) 2185ffd83dbSDimitry Andric return true; 2195ffd83dbSDimitry Andric 2205ffd83dbSDimitry Andric if (Cmp1->getPredicate() == 2215ffd83dbSDimitry Andric CmpInst::getSwappedPredicate(Cmp2->getInversePredicate()) && 2225ffd83dbSDimitry Andric Cmp1->getOperand(0) == Cmp2->getOperand(1) && 2235ffd83dbSDimitry Andric Cmp1->getOperand(1) == Cmp2->getOperand(0)) 2245ffd83dbSDimitry Andric return true; 2255ffd83dbSDimitry Andric } 2265ffd83dbSDimitry Andric return false; 2275ffd83dbSDimitry Andric } 2285ffd83dbSDimitry Andric 229480093f4SDimitry Andric bool llvm::isControlFlowEquivalent(const Instruction &I0, const Instruction &I1, 230480093f4SDimitry Andric const DominatorTree &DT, 231480093f4SDimitry Andric const PostDominatorTree &PDT) { 232480093f4SDimitry Andric return isControlFlowEquivalent(*I0.getParent(), *I1.getParent(), DT, PDT); 233480093f4SDimitry Andric } 234480093f4SDimitry Andric 235480093f4SDimitry Andric bool llvm::isControlFlowEquivalent(const BasicBlock &BB0, const BasicBlock &BB1, 236480093f4SDimitry Andric const DominatorTree &DT, 237480093f4SDimitry Andric const PostDominatorTree &PDT) { 238480093f4SDimitry Andric if (&BB0 == &BB1) 239480093f4SDimitry Andric return true; 240480093f4SDimitry Andric 2415ffd83dbSDimitry Andric if ((DT.dominates(&BB0, &BB1) && PDT.dominates(&BB1, &BB0)) || 2425ffd83dbSDimitry Andric (PDT.dominates(&BB0, &BB1) && DT.dominates(&BB1, &BB0))) 2435ffd83dbSDimitry Andric return true; 2445ffd83dbSDimitry Andric 2455ffd83dbSDimitry Andric // If the set of conditions required to execute BB0 and BB1 from their common 2465ffd83dbSDimitry Andric // dominator are the same, then BB0 and BB1 are control flow equivalent. 2475ffd83dbSDimitry Andric const BasicBlock *CommonDominator = DT.findNearestCommonDominator(&BB0, &BB1); 2485ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "The nearest common dominator of " << BB0.getName() 2495ffd83dbSDimitry Andric << " and " << BB1.getName() << " is " 2505ffd83dbSDimitry Andric << CommonDominator->getName() << "\n"); 2515ffd83dbSDimitry Andric 2525ffd83dbSDimitry Andric const Optional<ControlConditions> BB0Conditions = 2535ffd83dbSDimitry Andric ControlConditions::collectControlConditions(BB0, *CommonDominator, DT, 2545ffd83dbSDimitry Andric PDT); 2555ffd83dbSDimitry Andric if (BB0Conditions == None) 2565ffd83dbSDimitry Andric return false; 2575ffd83dbSDimitry Andric 2585ffd83dbSDimitry Andric const Optional<ControlConditions> BB1Conditions = 2595ffd83dbSDimitry Andric ControlConditions::collectControlConditions(BB1, *CommonDominator, DT, 2605ffd83dbSDimitry Andric PDT); 2615ffd83dbSDimitry Andric if (BB1Conditions == None) 2625ffd83dbSDimitry Andric return false; 2635ffd83dbSDimitry Andric 2645ffd83dbSDimitry Andric return BB0Conditions->isEquivalent(*BB1Conditions); 265480093f4SDimitry Andric } 266480093f4SDimitry Andric 267480093f4SDimitry Andric static bool reportInvalidCandidate(const Instruction &I, 268480093f4SDimitry Andric llvm::Statistic &Stat) { 269480093f4SDimitry Andric ++Stat; 270480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "Unable to move instruction: " << I << ". " 271480093f4SDimitry Andric << Stat.getDesc()); 272480093f4SDimitry Andric return false; 273480093f4SDimitry Andric } 274480093f4SDimitry Andric 275480093f4SDimitry Andric /// Collect all instructions in between \p StartInst and \p EndInst, and store 276480093f4SDimitry Andric /// them in \p InBetweenInsts. 277480093f4SDimitry Andric static void 278480093f4SDimitry Andric collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst, 279480093f4SDimitry Andric SmallPtrSetImpl<Instruction *> &InBetweenInsts) { 280480093f4SDimitry Andric assert(InBetweenInsts.empty() && "Expecting InBetweenInsts to be empty"); 281480093f4SDimitry Andric 282480093f4SDimitry Andric /// Get the next instructions of \p I, and push them to \p WorkList. 283480093f4SDimitry Andric auto getNextInsts = [](Instruction &I, 284480093f4SDimitry Andric SmallPtrSetImpl<Instruction *> &WorkList) { 285480093f4SDimitry Andric if (Instruction *NextInst = I.getNextNode()) 286480093f4SDimitry Andric WorkList.insert(NextInst); 287480093f4SDimitry Andric else { 288480093f4SDimitry Andric assert(I.isTerminator() && "Expecting a terminator instruction"); 289480093f4SDimitry Andric for (BasicBlock *Succ : successors(&I)) 290480093f4SDimitry Andric WorkList.insert(&Succ->front()); 291480093f4SDimitry Andric } 292480093f4SDimitry Andric }; 293480093f4SDimitry Andric 294480093f4SDimitry Andric SmallPtrSet<Instruction *, 10> WorkList; 295480093f4SDimitry Andric getNextInsts(StartInst, WorkList); 296480093f4SDimitry Andric while (!WorkList.empty()) { 297480093f4SDimitry Andric Instruction *CurInst = *WorkList.begin(); 298480093f4SDimitry Andric WorkList.erase(CurInst); 299480093f4SDimitry Andric 300480093f4SDimitry Andric if (CurInst == &EndInst) 301480093f4SDimitry Andric continue; 302480093f4SDimitry Andric 303480093f4SDimitry Andric if (!InBetweenInsts.insert(CurInst).second) 304480093f4SDimitry Andric continue; 305480093f4SDimitry Andric 306480093f4SDimitry Andric getNextInsts(*CurInst, WorkList); 307480093f4SDimitry Andric } 308480093f4SDimitry Andric } 309480093f4SDimitry Andric 310480093f4SDimitry Andric bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, 3115ffd83dbSDimitry Andric DominatorTree &DT, const PostDominatorTree *PDT, 3125ffd83dbSDimitry Andric DependenceInfo *DI) { 3135ffd83dbSDimitry Andric // Skip tests when we don't have PDT or DI 3145ffd83dbSDimitry Andric if (!PDT || !DI) 3155ffd83dbSDimitry Andric return false; 3165ffd83dbSDimitry Andric 317480093f4SDimitry Andric // Cannot move itself before itself. 318480093f4SDimitry Andric if (&I == &InsertPoint) 319480093f4SDimitry Andric return false; 320480093f4SDimitry Andric 321480093f4SDimitry Andric // Not moved. 322480093f4SDimitry Andric if (I.getNextNode() == &InsertPoint) 323480093f4SDimitry Andric return true; 324480093f4SDimitry Andric 325480093f4SDimitry Andric if (isa<PHINode>(I) || isa<PHINode>(InsertPoint)) 326480093f4SDimitry Andric return reportInvalidCandidate(I, NotMovedPHINode); 327480093f4SDimitry Andric 328480093f4SDimitry Andric if (I.isTerminator()) 329480093f4SDimitry Andric return reportInvalidCandidate(I, NotMovedTerminator); 330480093f4SDimitry Andric 331480093f4SDimitry Andric // TODO remove this limitation. 3325ffd83dbSDimitry Andric if (!isControlFlowEquivalent(I, InsertPoint, DT, *PDT)) 333480093f4SDimitry Andric return reportInvalidCandidate(I, NotControlFlowEquivalent); 334480093f4SDimitry Andric 3355ffd83dbSDimitry Andric if (!DT.dominates(&InsertPoint, &I)) 336480093f4SDimitry Andric for (const Use &U : I.uses()) 337480093f4SDimitry Andric if (auto *UserInst = dyn_cast<Instruction>(U.getUser())) 338480093f4SDimitry Andric if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) 339480093f4SDimitry Andric return false; 3405ffd83dbSDimitry Andric if (!DT.dominates(&I, &InsertPoint)) 341480093f4SDimitry Andric for (const Value *Op : I.operands()) 342480093f4SDimitry Andric if (auto *OpInst = dyn_cast<Instruction>(Op)) 343480093f4SDimitry Andric if (&InsertPoint == OpInst || !DT.dominates(OpInst, &InsertPoint)) 344480093f4SDimitry Andric return false; 345480093f4SDimitry Andric 3465ffd83dbSDimitry Andric DT.updateDFSNumbers(); 3475ffd83dbSDimitry Andric const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint); 348480093f4SDimitry Andric Instruction &StartInst = (MoveForward ? I : InsertPoint); 349480093f4SDimitry Andric Instruction &EndInst = (MoveForward ? InsertPoint : I); 350480093f4SDimitry Andric SmallPtrSet<Instruction *, 10> InstsToCheck; 351480093f4SDimitry Andric collectInstructionsInBetween(StartInst, EndInst, InstsToCheck); 352480093f4SDimitry Andric if (!MoveForward) 353480093f4SDimitry Andric InstsToCheck.insert(&InsertPoint); 354480093f4SDimitry Andric 355480093f4SDimitry Andric // Check if there exists instructions which may throw, may synchonize, or may 356480093f4SDimitry Andric // never return, from I to InsertPoint. 357480093f4SDimitry Andric if (!isSafeToSpeculativelyExecute(&I)) 358*e8d8bef9SDimitry Andric if (llvm::any_of(InstsToCheck, [](Instruction *I) { 359480093f4SDimitry Andric if (I->mayThrow()) 360480093f4SDimitry Andric return true; 361480093f4SDimitry Andric 362480093f4SDimitry Andric const CallBase *CB = dyn_cast<CallBase>(I); 363480093f4SDimitry Andric if (!CB) 364480093f4SDimitry Andric return false; 365480093f4SDimitry Andric if (!CB->hasFnAttr(Attribute::WillReturn)) 366480093f4SDimitry Andric return true; 367480093f4SDimitry Andric if (!CB->hasFnAttr(Attribute::NoSync)) 368480093f4SDimitry Andric return true; 369480093f4SDimitry Andric 370480093f4SDimitry Andric return false; 371480093f4SDimitry Andric })) { 372480093f4SDimitry Andric return reportInvalidCandidate(I, MayThrowException); 373480093f4SDimitry Andric } 374480093f4SDimitry Andric 375480093f4SDimitry Andric // Check if I has any output/flow/anti dependences with instructions from \p 376480093f4SDimitry Andric // StartInst to \p EndInst. 377*e8d8bef9SDimitry Andric if (llvm::any_of(InstsToCheck, [&DI, &I](Instruction *CurInst) { 3785ffd83dbSDimitry Andric auto DepResult = DI->depends(&I, CurInst, true); 379*e8d8bef9SDimitry Andric if (DepResult && (DepResult->isOutput() || DepResult->isFlow() || 380480093f4SDimitry Andric DepResult->isAnti())) 381480093f4SDimitry Andric return true; 382480093f4SDimitry Andric return false; 383480093f4SDimitry Andric })) 384480093f4SDimitry Andric return reportInvalidCandidate(I, HasDependences); 385480093f4SDimitry Andric 386480093f4SDimitry Andric return true; 387480093f4SDimitry Andric } 388480093f4SDimitry Andric 3895ffd83dbSDimitry Andric bool llvm::isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, 3905ffd83dbSDimitry Andric DominatorTree &DT, const PostDominatorTree *PDT, 3915ffd83dbSDimitry Andric DependenceInfo *DI) { 3925ffd83dbSDimitry Andric return llvm::all_of(BB, [&](Instruction &I) { 3935ffd83dbSDimitry Andric if (BB.getTerminator() == &I) 3945ffd83dbSDimitry Andric return true; 3955ffd83dbSDimitry Andric 3965ffd83dbSDimitry Andric return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI); 3975ffd83dbSDimitry Andric }); 3985ffd83dbSDimitry Andric } 3995ffd83dbSDimitry Andric 4005ffd83dbSDimitry Andric void llvm::moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB, 4015ffd83dbSDimitry Andric DominatorTree &DT, 4025ffd83dbSDimitry Andric const PostDominatorTree &PDT, 4035ffd83dbSDimitry Andric DependenceInfo &DI) { 404480093f4SDimitry Andric for (auto It = ++FromBB.rbegin(); It != FromBB.rend();) { 405480093f4SDimitry Andric Instruction *MovePos = ToBB.getFirstNonPHIOrDbg(); 406480093f4SDimitry Andric Instruction &I = *It; 407480093f4SDimitry Andric // Increment the iterator before modifying FromBB. 408480093f4SDimitry Andric ++It; 409480093f4SDimitry Andric 4105ffd83dbSDimitry Andric if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 4115ffd83dbSDimitry Andric I.moveBefore(MovePos); 4125ffd83dbSDimitry Andric } 4135ffd83dbSDimitry Andric } 4145ffd83dbSDimitry Andric 4155ffd83dbSDimitry Andric void llvm::moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB, 4165ffd83dbSDimitry Andric DominatorTree &DT, 4175ffd83dbSDimitry Andric const PostDominatorTree &PDT, 4185ffd83dbSDimitry Andric DependenceInfo &DI) { 4195ffd83dbSDimitry Andric Instruction *MovePos = ToBB.getTerminator(); 4205ffd83dbSDimitry Andric while (FromBB.size() > 1) { 4215ffd83dbSDimitry Andric Instruction &I = FromBB.front(); 4225ffd83dbSDimitry Andric if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 423480093f4SDimitry Andric I.moveBefore(MovePos); 424480093f4SDimitry Andric } 425480093f4SDimitry Andric } 426