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" 15480093f4SDimitry Andric #include "llvm/ADT/Statistic.h" 16480093f4SDimitry Andric #include "llvm/Analysis/DependenceAnalysis.h" 17480093f4SDimitry Andric #include "llvm/Analysis/PostDominators.h" 18480093f4SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 19480093f4SDimitry Andric #include "llvm/IR/Dominators.h" 20480093f4SDimitry Andric 21480093f4SDimitry Andric using namespace llvm; 22480093f4SDimitry Andric 23480093f4SDimitry Andric #define DEBUG_TYPE "codemover-utils" 24480093f4SDimitry Andric 25480093f4SDimitry Andric STATISTIC(HasDependences, 26480093f4SDimitry Andric "Cannot move across instructions that has memory dependences"); 27480093f4SDimitry Andric STATISTIC(MayThrowException, "Cannot move across instructions that may throw"); 28480093f4SDimitry Andric STATISTIC(NotControlFlowEquivalent, 29480093f4SDimitry Andric "Instructions are not control flow equivalent"); 30480093f4SDimitry Andric STATISTIC(NotMovedPHINode, "Movement of PHINodes are not supported"); 31480093f4SDimitry Andric STATISTIC(NotMovedTerminator, "Movement of Terminator are not supported"); 32480093f4SDimitry Andric 335ffd83dbSDimitry Andric namespace { 345ffd83dbSDimitry Andric /// Represent a control condition. A control condition is a condition of a 355ffd83dbSDimitry Andric /// terminator to decide which successors to execute. The pointer field 365ffd83dbSDimitry Andric /// represents the address of the condition of the terminator. The integer field 375ffd83dbSDimitry Andric /// is a bool, it is true when the basic block is executed when V is true. For 385ffd83dbSDimitry Andric /// example, `br %cond, bb0, bb1` %cond is a control condition of bb0 with the 395ffd83dbSDimitry Andric /// integer field equals to true, while %cond is a control condition of bb1 with 405ffd83dbSDimitry Andric /// the integer field equals to false. 415ffd83dbSDimitry Andric using ControlCondition = PointerIntPair<Value *, 1, bool>; 425ffd83dbSDimitry Andric #ifndef NDEBUG 435ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ControlCondition &C) { 445ffd83dbSDimitry Andric OS << "[" << *C.getPointer() << ", " << (C.getInt() ? "true" : "false") 455ffd83dbSDimitry Andric << "]"; 465ffd83dbSDimitry Andric return OS; 475ffd83dbSDimitry Andric } 485ffd83dbSDimitry Andric #endif 495ffd83dbSDimitry Andric 505ffd83dbSDimitry Andric /// Represent a set of control conditions required to execute ToBB from FromBB. 515ffd83dbSDimitry Andric class ControlConditions { 525ffd83dbSDimitry Andric using ConditionVectorTy = SmallVector<ControlCondition, 6>; 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric /// A SmallVector of control conditions. 555ffd83dbSDimitry Andric ConditionVectorTy Conditions; 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric public: 585ffd83dbSDimitry Andric /// Return a ControlConditions which stores all conditions required to execute 595ffd83dbSDimitry Andric /// \p BB from \p Dominator. If \p MaxLookup is non-zero, it limits the 60bdd1243dSDimitry Andric /// number of conditions to collect. Return std::nullopt if not all conditions 61bdd1243dSDimitry Andric /// are collected successfully, or we hit the limit. 62bdd1243dSDimitry Andric static const std::optional<ControlConditions> 635ffd83dbSDimitry Andric collectControlConditions(const BasicBlock &BB, const BasicBlock &Dominator, 645ffd83dbSDimitry Andric const DominatorTree &DT, 655ffd83dbSDimitry Andric const PostDominatorTree &PDT, 665ffd83dbSDimitry Andric unsigned MaxLookup = 6); 675ffd83dbSDimitry Andric 685ffd83dbSDimitry Andric /// Return true if there exists no control conditions required to execute ToBB 695ffd83dbSDimitry Andric /// from FromBB. 705ffd83dbSDimitry Andric bool isUnconditional() const { return Conditions.empty(); } 715ffd83dbSDimitry Andric 725ffd83dbSDimitry Andric /// Return a constant reference of Conditions. 735ffd83dbSDimitry Andric const ConditionVectorTy &getControlConditions() const { return Conditions; } 745ffd83dbSDimitry Andric 755ffd83dbSDimitry Andric /// Add \p V as one of the ControlCondition in Condition with IsTrueCondition 765ffd83dbSDimitry Andric /// equals to \p True. Return true if inserted successfully. 775ffd83dbSDimitry Andric bool addControlCondition(ControlCondition C); 785ffd83dbSDimitry Andric 795ffd83dbSDimitry Andric /// Return true if for all control conditions in Conditions, there exists an 805ffd83dbSDimitry Andric /// equivalent control condition in \p Other.Conditions. 815ffd83dbSDimitry Andric bool isEquivalent(const ControlConditions &Other) const; 825ffd83dbSDimitry Andric 835ffd83dbSDimitry Andric /// Return true if \p C1 and \p C2 are equivalent. 845ffd83dbSDimitry Andric static bool isEquivalent(const ControlCondition &C1, 855ffd83dbSDimitry Andric const ControlCondition &C2); 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric private: 885ffd83dbSDimitry Andric ControlConditions() = default; 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric static bool isEquivalent(const Value &V1, const Value &V2); 915ffd83dbSDimitry Andric static bool isInverse(const Value &V1, const Value &V2); 925ffd83dbSDimitry Andric }; 935ffd83dbSDimitry Andric } // namespace 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, 965ffd83dbSDimitry Andric const Instruction *InstB) { 975ffd83dbSDimitry Andric // Use ordered basic block in case the 2 instructions are in the same 985ffd83dbSDimitry Andric // block. 995ffd83dbSDimitry Andric if (InstA->getParent() == InstB->getParent()) 1005ffd83dbSDimitry Andric return InstA->comesBefore(InstB); 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric DomTreeNode *DA = DT->getNode(InstA->getParent()); 1035ffd83dbSDimitry Andric DomTreeNode *DB = DT->getNode(InstB->getParent()); 1045ffd83dbSDimitry Andric return DA->getLevel() < DB->getLevel(); 1055ffd83dbSDimitry Andric } 1065ffd83dbSDimitry Andric 107bdd1243dSDimitry Andric const std::optional<ControlConditions> 108bdd1243dSDimitry Andric ControlConditions::collectControlConditions(const BasicBlock &BB, 109bdd1243dSDimitry Andric const BasicBlock &Dominator, 110bdd1243dSDimitry Andric const DominatorTree &DT, 111bdd1243dSDimitry Andric const PostDominatorTree &PDT, 112bdd1243dSDimitry Andric unsigned MaxLookup) { 1135ffd83dbSDimitry Andric assert(DT.dominates(&Dominator, &BB) && "Expecting Dominator to dominate BB"); 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric ControlConditions Conditions; 1165ffd83dbSDimitry Andric unsigned NumConditions = 0; 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric // BB is executed unconditional from itself. 1195ffd83dbSDimitry Andric if (&Dominator == &BB) 1205ffd83dbSDimitry Andric return Conditions; 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric const BasicBlock *CurBlock = &BB; 1235ffd83dbSDimitry Andric // Walk up the dominator tree from the associated DT node for BB to the 1245ffd83dbSDimitry Andric // associated DT node for Dominator. 1255ffd83dbSDimitry Andric do { 1265ffd83dbSDimitry Andric assert(DT.getNode(CurBlock) && "Expecting a valid DT node for CurBlock"); 1275ffd83dbSDimitry Andric BasicBlock *IDom = DT.getNode(CurBlock)->getIDom()->getBlock(); 1285ffd83dbSDimitry Andric assert(DT.dominates(&Dominator, IDom) && 1295ffd83dbSDimitry Andric "Expecting Dominator to dominate IDom"); 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric // Limitation: can only handle branch instruction currently. 1325ffd83dbSDimitry Andric const BranchInst *BI = dyn_cast<BranchInst>(IDom->getTerminator()); 1335ffd83dbSDimitry Andric if (!BI) 134bdd1243dSDimitry Andric return std::nullopt; 1355ffd83dbSDimitry Andric 1365ffd83dbSDimitry Andric bool Inserted = false; 1375ffd83dbSDimitry Andric if (PDT.dominates(CurBlock, IDom)) { 1385ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() 1395ffd83dbSDimitry Andric << " is executed unconditionally from " 1405ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1415ffd83dbSDimitry Andric } else if (PDT.dominates(CurBlock, BI->getSuccessor(0))) { 1425ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 1435ffd83dbSDimitry Andric << *BI->getCondition() << "\" is true from " 1445ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1455ffd83dbSDimitry Andric Inserted = Conditions.addControlCondition( 1465ffd83dbSDimitry Andric ControlCondition(BI->getCondition(), true)); 1475ffd83dbSDimitry Andric } else if (PDT.dominates(CurBlock, BI->getSuccessor(1))) { 1485ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 1495ffd83dbSDimitry Andric << *BI->getCondition() << "\" is false from " 1505ffd83dbSDimitry Andric << IDom->getName() << "\n"); 1515ffd83dbSDimitry Andric Inserted = Conditions.addControlCondition( 1525ffd83dbSDimitry Andric ControlCondition(BI->getCondition(), false)); 1535ffd83dbSDimitry Andric } else 154bdd1243dSDimitry Andric return std::nullopt; 1555ffd83dbSDimitry Andric 1565ffd83dbSDimitry Andric if (Inserted) 1575ffd83dbSDimitry Andric ++NumConditions; 1585ffd83dbSDimitry Andric 1595ffd83dbSDimitry Andric if (MaxLookup != 0 && NumConditions > MaxLookup) 160bdd1243dSDimitry Andric return std::nullopt; 1615ffd83dbSDimitry Andric 1625ffd83dbSDimitry Andric CurBlock = IDom; 1635ffd83dbSDimitry Andric } while (CurBlock != &Dominator); 1645ffd83dbSDimitry Andric 1655ffd83dbSDimitry Andric return Conditions; 1665ffd83dbSDimitry Andric } 1675ffd83dbSDimitry Andric 1685ffd83dbSDimitry Andric bool ControlConditions::addControlCondition(ControlCondition C) { 1695ffd83dbSDimitry Andric bool Inserted = false; 1705ffd83dbSDimitry Andric if (none_of(Conditions, [&](ControlCondition &Exists) { 1715ffd83dbSDimitry Andric return ControlConditions::isEquivalent(C, Exists); 1725ffd83dbSDimitry Andric })) { 1735ffd83dbSDimitry Andric Conditions.push_back(C); 1745ffd83dbSDimitry Andric Inserted = true; 1755ffd83dbSDimitry Andric } 1765ffd83dbSDimitry Andric 1775ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << (Inserted ? "Inserted " : "Not inserted ") << C << "\n"); 1785ffd83dbSDimitry Andric return Inserted; 1795ffd83dbSDimitry Andric } 1805ffd83dbSDimitry Andric 1815ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const ControlConditions &Other) const { 1825ffd83dbSDimitry Andric if (Conditions.empty() && Other.Conditions.empty()) 1835ffd83dbSDimitry Andric return true; 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric if (Conditions.size() != Other.Conditions.size()) 1865ffd83dbSDimitry Andric return false; 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric return all_of(Conditions, [&](const ControlCondition &C) { 1895ffd83dbSDimitry Andric return any_of(Other.Conditions, [&](const ControlCondition &OtherC) { 1905ffd83dbSDimitry Andric return ControlConditions::isEquivalent(C, OtherC); 1915ffd83dbSDimitry Andric }); 1925ffd83dbSDimitry Andric }); 1935ffd83dbSDimitry Andric } 1945ffd83dbSDimitry Andric 1955ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const ControlCondition &C1, 1965ffd83dbSDimitry Andric const ControlCondition &C2) { 1975ffd83dbSDimitry Andric if (C1.getInt() == C2.getInt()) { 1985ffd83dbSDimitry Andric if (isEquivalent(*C1.getPointer(), *C2.getPointer())) 1995ffd83dbSDimitry Andric return true; 2005ffd83dbSDimitry Andric } else if (isInverse(*C1.getPointer(), *C2.getPointer())) 2015ffd83dbSDimitry Andric return true; 2025ffd83dbSDimitry Andric 2035ffd83dbSDimitry Andric return false; 2045ffd83dbSDimitry Andric } 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric // FIXME: Use SCEV and reuse GVN/CSE logic to check for equivalence between 2075ffd83dbSDimitry Andric // Values. 2085ffd83dbSDimitry Andric // Currently, isEquivalent rely on other passes to ensure equivalent conditions 2095ffd83dbSDimitry Andric // have the same value, e.g. GVN. 2105ffd83dbSDimitry Andric bool ControlConditions::isEquivalent(const Value &V1, const Value &V2) { 2115ffd83dbSDimitry Andric return &V1 == &V2; 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric bool ControlConditions::isInverse(const Value &V1, const Value &V2) { 2155ffd83dbSDimitry Andric if (const CmpInst *Cmp1 = dyn_cast<CmpInst>(&V1)) 2165ffd83dbSDimitry Andric if (const CmpInst *Cmp2 = dyn_cast<CmpInst>(&V2)) { 2175ffd83dbSDimitry Andric if (Cmp1->getPredicate() == Cmp2->getInversePredicate() && 2185ffd83dbSDimitry Andric Cmp1->getOperand(0) == Cmp2->getOperand(0) && 2195ffd83dbSDimitry Andric Cmp1->getOperand(1) == Cmp2->getOperand(1)) 2205ffd83dbSDimitry Andric return true; 2215ffd83dbSDimitry Andric 2225ffd83dbSDimitry Andric if (Cmp1->getPredicate() == 2235ffd83dbSDimitry Andric CmpInst::getSwappedPredicate(Cmp2->getInversePredicate()) && 2245ffd83dbSDimitry Andric Cmp1->getOperand(0) == Cmp2->getOperand(1) && 2255ffd83dbSDimitry Andric Cmp1->getOperand(1) == Cmp2->getOperand(0)) 2265ffd83dbSDimitry Andric return true; 2275ffd83dbSDimitry Andric } 2285ffd83dbSDimitry Andric return false; 2295ffd83dbSDimitry Andric } 2305ffd83dbSDimitry Andric 231480093f4SDimitry Andric bool llvm::isControlFlowEquivalent(const Instruction &I0, const Instruction &I1, 232480093f4SDimitry Andric const DominatorTree &DT, 233480093f4SDimitry Andric const PostDominatorTree &PDT) { 234480093f4SDimitry Andric return isControlFlowEquivalent(*I0.getParent(), *I1.getParent(), DT, PDT); 235480093f4SDimitry Andric } 236480093f4SDimitry Andric 237480093f4SDimitry Andric bool llvm::isControlFlowEquivalent(const BasicBlock &BB0, const BasicBlock &BB1, 238480093f4SDimitry Andric const DominatorTree &DT, 239480093f4SDimitry Andric const PostDominatorTree &PDT) { 240480093f4SDimitry Andric if (&BB0 == &BB1) 241480093f4SDimitry Andric return true; 242480093f4SDimitry Andric 2435ffd83dbSDimitry Andric if ((DT.dominates(&BB0, &BB1) && PDT.dominates(&BB1, &BB0)) || 2445ffd83dbSDimitry Andric (PDT.dominates(&BB0, &BB1) && DT.dominates(&BB1, &BB0))) 2455ffd83dbSDimitry Andric return true; 2465ffd83dbSDimitry Andric 2475ffd83dbSDimitry Andric // If the set of conditions required to execute BB0 and BB1 from their common 2485ffd83dbSDimitry Andric // dominator are the same, then BB0 and BB1 are control flow equivalent. 2495ffd83dbSDimitry Andric const BasicBlock *CommonDominator = DT.findNearestCommonDominator(&BB0, &BB1); 2505ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "The nearest common dominator of " << BB0.getName() 2515ffd83dbSDimitry Andric << " and " << BB1.getName() << " is " 2525ffd83dbSDimitry Andric << CommonDominator->getName() << "\n"); 2535ffd83dbSDimitry Andric 254bdd1243dSDimitry Andric const std::optional<ControlConditions> BB0Conditions = 2555ffd83dbSDimitry Andric ControlConditions::collectControlConditions(BB0, *CommonDominator, DT, 2565ffd83dbSDimitry Andric PDT); 257bdd1243dSDimitry Andric if (BB0Conditions == std::nullopt) 2585ffd83dbSDimitry Andric return false; 2595ffd83dbSDimitry Andric 260bdd1243dSDimitry Andric const std::optional<ControlConditions> BB1Conditions = 2615ffd83dbSDimitry Andric ControlConditions::collectControlConditions(BB1, *CommonDominator, DT, 2625ffd83dbSDimitry Andric PDT); 263bdd1243dSDimitry Andric if (BB1Conditions == std::nullopt) 2645ffd83dbSDimitry Andric return false; 2655ffd83dbSDimitry Andric 2665ffd83dbSDimitry Andric return BB0Conditions->isEquivalent(*BB1Conditions); 267480093f4SDimitry Andric } 268480093f4SDimitry Andric 269480093f4SDimitry Andric static bool reportInvalidCandidate(const Instruction &I, 270480093f4SDimitry Andric llvm::Statistic &Stat) { 271480093f4SDimitry Andric ++Stat; 272480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "Unable to move instruction: " << I << ". " 273480093f4SDimitry Andric << Stat.getDesc()); 274480093f4SDimitry Andric return false; 275480093f4SDimitry Andric } 276480093f4SDimitry Andric 277480093f4SDimitry Andric /// Collect all instructions in between \p StartInst and \p EndInst, and store 278480093f4SDimitry Andric /// them in \p InBetweenInsts. 279480093f4SDimitry Andric static void 280480093f4SDimitry Andric collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst, 281480093f4SDimitry Andric SmallPtrSetImpl<Instruction *> &InBetweenInsts) { 282480093f4SDimitry Andric assert(InBetweenInsts.empty() && "Expecting InBetweenInsts to be empty"); 283480093f4SDimitry Andric 284480093f4SDimitry Andric /// Get the next instructions of \p I, and push them to \p WorkList. 285480093f4SDimitry Andric auto getNextInsts = [](Instruction &I, 286480093f4SDimitry Andric SmallPtrSetImpl<Instruction *> &WorkList) { 287480093f4SDimitry Andric if (Instruction *NextInst = I.getNextNode()) 288480093f4SDimitry Andric WorkList.insert(NextInst); 289480093f4SDimitry Andric else { 290480093f4SDimitry Andric assert(I.isTerminator() && "Expecting a terminator instruction"); 291480093f4SDimitry Andric for (BasicBlock *Succ : successors(&I)) 292480093f4SDimitry Andric WorkList.insert(&Succ->front()); 293480093f4SDimitry Andric } 294480093f4SDimitry Andric }; 295480093f4SDimitry Andric 296480093f4SDimitry Andric SmallPtrSet<Instruction *, 10> WorkList; 297480093f4SDimitry Andric getNextInsts(StartInst, WorkList); 298480093f4SDimitry Andric while (!WorkList.empty()) { 299480093f4SDimitry Andric Instruction *CurInst = *WorkList.begin(); 300480093f4SDimitry Andric WorkList.erase(CurInst); 301480093f4SDimitry Andric 302480093f4SDimitry Andric if (CurInst == &EndInst) 303480093f4SDimitry Andric continue; 304480093f4SDimitry Andric 305480093f4SDimitry Andric if (!InBetweenInsts.insert(CurInst).second) 306480093f4SDimitry Andric continue; 307480093f4SDimitry Andric 308480093f4SDimitry Andric getNextInsts(*CurInst, WorkList); 309480093f4SDimitry Andric } 310480093f4SDimitry Andric } 311480093f4SDimitry Andric 312480093f4SDimitry Andric bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, 3135ffd83dbSDimitry Andric DominatorTree &DT, const PostDominatorTree *PDT, 314349cc55cSDimitry Andric DependenceInfo *DI, bool CheckForEntireBlock) { 3155ffd83dbSDimitry Andric // Skip tests when we don't have PDT or DI 3165ffd83dbSDimitry Andric if (!PDT || !DI) 3175ffd83dbSDimitry Andric return false; 3185ffd83dbSDimitry Andric 319480093f4SDimitry Andric // Cannot move itself before itself. 320480093f4SDimitry Andric if (&I == &InsertPoint) 321480093f4SDimitry Andric return false; 322480093f4SDimitry Andric 323480093f4SDimitry Andric // Not moved. 324480093f4SDimitry Andric if (I.getNextNode() == &InsertPoint) 325480093f4SDimitry Andric return true; 326480093f4SDimitry Andric 327480093f4SDimitry Andric if (isa<PHINode>(I) || isa<PHINode>(InsertPoint)) 328480093f4SDimitry Andric return reportInvalidCandidate(I, NotMovedPHINode); 329480093f4SDimitry Andric 330480093f4SDimitry Andric if (I.isTerminator()) 331480093f4SDimitry Andric return reportInvalidCandidate(I, NotMovedTerminator); 332480093f4SDimitry Andric 333480093f4SDimitry Andric // TODO remove this limitation. 3345ffd83dbSDimitry Andric if (!isControlFlowEquivalent(I, InsertPoint, DT, *PDT)) 335480093f4SDimitry Andric return reportInvalidCandidate(I, NotControlFlowEquivalent); 336480093f4SDimitry Andric 337349cc55cSDimitry Andric if (isReachedBefore(&I, &InsertPoint, &DT, PDT)) 338480093f4SDimitry Andric for (const Use &U : I.uses()) 339*0fca6ea1SDimitry Andric if (auto *UserInst = dyn_cast<Instruction>(U.getUser())) { 340*0fca6ea1SDimitry Andric // If InsertPoint is in a BB that comes after I, then we cannot move if 341*0fca6ea1SDimitry Andric // I is used in the terminator of the current BB. 342*0fca6ea1SDimitry Andric if (I.getParent() == InsertPoint.getParent() && 343*0fca6ea1SDimitry Andric UserInst == I.getParent()->getTerminator()) 344480093f4SDimitry Andric return false; 345*0fca6ea1SDimitry Andric if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) { 346*0fca6ea1SDimitry Andric // If UserInst is an instruction that appears later in the same BB as 347*0fca6ea1SDimitry Andric // I, then it is okay to move since I will still be available when 348*0fca6ea1SDimitry Andric // UserInst is executed. 349*0fca6ea1SDimitry Andric if (CheckForEntireBlock && I.getParent() == UserInst->getParent() && 350*0fca6ea1SDimitry Andric DT.dominates(&I, UserInst)) 351*0fca6ea1SDimitry Andric continue; 352*0fca6ea1SDimitry Andric return false; 353*0fca6ea1SDimitry Andric } 354*0fca6ea1SDimitry Andric } 355349cc55cSDimitry Andric if (isReachedBefore(&InsertPoint, &I, &DT, PDT)) 356480093f4SDimitry Andric for (const Value *Op : I.operands()) 357349cc55cSDimitry Andric if (auto *OpInst = dyn_cast<Instruction>(Op)) { 358349cc55cSDimitry Andric if (&InsertPoint == OpInst) 359480093f4SDimitry Andric return false; 360349cc55cSDimitry Andric // If OpInst is an instruction that appears earlier in the same BB as 361349cc55cSDimitry Andric // I, then it is okay to move since OpInst will still be available. 362349cc55cSDimitry Andric if (CheckForEntireBlock && I.getParent() == OpInst->getParent() && 363349cc55cSDimitry Andric DT.dominates(OpInst, &I)) 364349cc55cSDimitry Andric continue; 365349cc55cSDimitry Andric if (!DT.dominates(OpInst, &InsertPoint)) 366349cc55cSDimitry Andric return false; 367349cc55cSDimitry Andric } 368480093f4SDimitry Andric 3695ffd83dbSDimitry Andric DT.updateDFSNumbers(); 3705ffd83dbSDimitry Andric const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint); 371480093f4SDimitry Andric Instruction &StartInst = (MoveForward ? I : InsertPoint); 372480093f4SDimitry Andric Instruction &EndInst = (MoveForward ? InsertPoint : I); 373480093f4SDimitry Andric SmallPtrSet<Instruction *, 10> InstsToCheck; 374480093f4SDimitry Andric collectInstructionsInBetween(StartInst, EndInst, InstsToCheck); 375480093f4SDimitry Andric if (!MoveForward) 376480093f4SDimitry Andric InstsToCheck.insert(&InsertPoint); 377480093f4SDimitry Andric 378480093f4SDimitry Andric // Check if there exists instructions which may throw, may synchonize, or may 379480093f4SDimitry Andric // never return, from I to InsertPoint. 380480093f4SDimitry Andric if (!isSafeToSpeculativelyExecute(&I)) 381e8d8bef9SDimitry Andric if (llvm::any_of(InstsToCheck, [](Instruction *I) { 382480093f4SDimitry Andric if (I->mayThrow()) 383480093f4SDimitry Andric return true; 384480093f4SDimitry Andric 385480093f4SDimitry Andric const CallBase *CB = dyn_cast<CallBase>(I); 386480093f4SDimitry Andric if (!CB) 387480093f4SDimitry Andric return false; 388480093f4SDimitry Andric if (!CB->hasFnAttr(Attribute::WillReturn)) 389480093f4SDimitry Andric return true; 390480093f4SDimitry Andric if (!CB->hasFnAttr(Attribute::NoSync)) 391480093f4SDimitry Andric return true; 392480093f4SDimitry Andric 393480093f4SDimitry Andric return false; 394480093f4SDimitry Andric })) { 395480093f4SDimitry Andric return reportInvalidCandidate(I, MayThrowException); 396480093f4SDimitry Andric } 397480093f4SDimitry Andric 398480093f4SDimitry Andric // Check if I has any output/flow/anti dependences with instructions from \p 399480093f4SDimitry Andric // StartInst to \p EndInst. 400e8d8bef9SDimitry Andric if (llvm::any_of(InstsToCheck, [&DI, &I](Instruction *CurInst) { 4015ffd83dbSDimitry Andric auto DepResult = DI->depends(&I, CurInst, true); 402e8d8bef9SDimitry Andric if (DepResult && (DepResult->isOutput() || DepResult->isFlow() || 403480093f4SDimitry Andric DepResult->isAnti())) 404480093f4SDimitry Andric return true; 405480093f4SDimitry Andric return false; 406480093f4SDimitry Andric })) 407480093f4SDimitry Andric return reportInvalidCandidate(I, HasDependences); 408480093f4SDimitry Andric 409480093f4SDimitry Andric return true; 410480093f4SDimitry Andric } 411480093f4SDimitry Andric 4125ffd83dbSDimitry Andric bool llvm::isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, 4135ffd83dbSDimitry Andric DominatorTree &DT, const PostDominatorTree *PDT, 4145ffd83dbSDimitry Andric DependenceInfo *DI) { 4155ffd83dbSDimitry Andric return llvm::all_of(BB, [&](Instruction &I) { 4165ffd83dbSDimitry Andric if (BB.getTerminator() == &I) 4175ffd83dbSDimitry Andric return true; 4185ffd83dbSDimitry Andric 419349cc55cSDimitry Andric return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI, 420349cc55cSDimitry Andric /*CheckForEntireBlock=*/true); 4215ffd83dbSDimitry Andric }); 4225ffd83dbSDimitry Andric } 4235ffd83dbSDimitry Andric 4245ffd83dbSDimitry Andric void llvm::moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB, 4255ffd83dbSDimitry Andric DominatorTree &DT, 4265ffd83dbSDimitry Andric const PostDominatorTree &PDT, 4275ffd83dbSDimitry Andric DependenceInfo &DI) { 428349cc55cSDimitry Andric for (Instruction &I : 429349cc55cSDimitry Andric llvm::make_early_inc_range(llvm::drop_begin(llvm::reverse(FromBB)))) { 430480093f4SDimitry Andric Instruction *MovePos = ToBB.getFirstNonPHIOrDbg(); 431480093f4SDimitry Andric 4325ffd83dbSDimitry Andric if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 4335f757f3fSDimitry Andric I.moveBeforePreserving(MovePos); 4345ffd83dbSDimitry Andric } 4355ffd83dbSDimitry Andric } 4365ffd83dbSDimitry Andric 4375ffd83dbSDimitry Andric void llvm::moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB, 4385ffd83dbSDimitry Andric DominatorTree &DT, 4395ffd83dbSDimitry Andric const PostDominatorTree &PDT, 4405ffd83dbSDimitry Andric DependenceInfo &DI) { 4415ffd83dbSDimitry Andric Instruction *MovePos = ToBB.getTerminator(); 4425ffd83dbSDimitry Andric while (FromBB.size() > 1) { 4435ffd83dbSDimitry Andric Instruction &I = FromBB.front(); 4445ffd83dbSDimitry Andric if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 4455f757f3fSDimitry Andric I.moveBeforePreserving(MovePos); 446480093f4SDimitry Andric } 447480093f4SDimitry Andric } 448349cc55cSDimitry Andric 449349cc55cSDimitry Andric bool llvm::nonStrictlyPostDominate(const BasicBlock *ThisBlock, 450349cc55cSDimitry Andric const BasicBlock *OtherBlock, 451349cc55cSDimitry Andric const DominatorTree *DT, 452349cc55cSDimitry Andric const PostDominatorTree *PDT) { 453349cc55cSDimitry Andric assert(isControlFlowEquivalent(*ThisBlock, *OtherBlock, *DT, *PDT) && 454349cc55cSDimitry Andric "ThisBlock and OtherBlock must be CFG equivalent!"); 455349cc55cSDimitry Andric const BasicBlock *CommonDominator = 456349cc55cSDimitry Andric DT->findNearestCommonDominator(ThisBlock, OtherBlock); 457349cc55cSDimitry Andric if (CommonDominator == nullptr) 458349cc55cSDimitry Andric return false; 459349cc55cSDimitry Andric 460349cc55cSDimitry Andric /// Recursively check the predecessors of \p ThisBlock up to 461349cc55cSDimitry Andric /// their common dominator, and see if any of them post-dominates 462349cc55cSDimitry Andric /// \p OtherBlock. 463349cc55cSDimitry Andric SmallVector<const BasicBlock *, 8> WorkList; 464349cc55cSDimitry Andric SmallPtrSet<const BasicBlock *, 8> Visited; 465349cc55cSDimitry Andric WorkList.push_back(ThisBlock); 466349cc55cSDimitry Andric while (!WorkList.empty()) { 467349cc55cSDimitry Andric const BasicBlock *CurBlock = WorkList.back(); 468349cc55cSDimitry Andric WorkList.pop_back(); 469349cc55cSDimitry Andric Visited.insert(CurBlock); 470349cc55cSDimitry Andric if (PDT->dominates(CurBlock, OtherBlock)) 471349cc55cSDimitry Andric return true; 472349cc55cSDimitry Andric 473bdd1243dSDimitry Andric for (const auto *Pred : predecessors(CurBlock)) { 474349cc55cSDimitry Andric if (Pred == CommonDominator || Visited.count(Pred)) 475349cc55cSDimitry Andric continue; 476349cc55cSDimitry Andric WorkList.push_back(Pred); 477349cc55cSDimitry Andric } 478349cc55cSDimitry Andric } 479349cc55cSDimitry Andric return false; 480349cc55cSDimitry Andric } 481349cc55cSDimitry Andric 482349cc55cSDimitry Andric bool llvm::isReachedBefore(const Instruction *I0, const Instruction *I1, 483349cc55cSDimitry Andric const DominatorTree *DT, 484349cc55cSDimitry Andric const PostDominatorTree *PDT) { 485349cc55cSDimitry Andric const BasicBlock *BB0 = I0->getParent(); 486349cc55cSDimitry Andric const BasicBlock *BB1 = I1->getParent(); 487349cc55cSDimitry Andric if (BB0 == BB1) 488349cc55cSDimitry Andric return DT->dominates(I0, I1); 489349cc55cSDimitry Andric 490349cc55cSDimitry Andric return nonStrictlyPostDominate(BB1, BB0, DT, PDT); 491349cc55cSDimitry Andric } 492