1ae8a8c2dSTsang Whitney W.H //===- CodeMoverUtils.cpp - CodeMover Utilities ----------------------------==// 2ae8a8c2dSTsang Whitney W.H // 3ae8a8c2dSTsang Whitney W.H // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ae8a8c2dSTsang Whitney W.H // See https://llvm.org/LICENSE.txt for license information. 5ae8a8c2dSTsang Whitney W.H // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ae8a8c2dSTsang Whitney W.H // 7ae8a8c2dSTsang Whitney W.H //===----------------------------------------------------------------------===// 8ae8a8c2dSTsang Whitney W.H // 9ae8a8c2dSTsang Whitney W.H // This family of functions perform movements on basic blocks, and instructions 10ae8a8c2dSTsang Whitney W.H // contained within a function. 11ae8a8c2dSTsang Whitney W.H // 12ae8a8c2dSTsang Whitney W.H //===----------------------------------------------------------------------===// 13ae8a8c2dSTsang Whitney W.H 14ae8a8c2dSTsang Whitney W.H #include "llvm/Transforms/Utils/CodeMoverUtils.h" 1578dc6498SWhitney Tsang #include "llvm/ADT/Optional.h" 16ae8a8c2dSTsang Whitney W.H #include "llvm/ADT/Statistic.h" 17ae8a8c2dSTsang Whitney W.H #include "llvm/Analysis/DependenceAnalysis.h" 18ae8a8c2dSTsang Whitney W.H #include "llvm/Analysis/PostDominators.h" 19ae8a8c2dSTsang Whitney W.H #include "llvm/Analysis/ValueTracking.h" 20ae8a8c2dSTsang Whitney W.H #include "llvm/IR/Dominators.h" 21ae8a8c2dSTsang Whitney W.H 22ae8a8c2dSTsang Whitney W.H using namespace llvm; 23ae8a8c2dSTsang Whitney W.H 24ae8a8c2dSTsang Whitney W.H #define DEBUG_TYPE "codemover-utils" 25ae8a8c2dSTsang Whitney W.H 26ae8a8c2dSTsang Whitney W.H STATISTIC(HasDependences, 27ae8a8c2dSTsang Whitney W.H "Cannot move across instructions that has memory dependences"); 28ae8a8c2dSTsang Whitney W.H STATISTIC(MayThrowException, "Cannot move across instructions that may throw"); 29ae8a8c2dSTsang Whitney W.H STATISTIC(NotControlFlowEquivalent, 30ae8a8c2dSTsang Whitney W.H "Instructions are not control flow equivalent"); 31ae8a8c2dSTsang Whitney W.H STATISTIC(NotMovedPHINode, "Movement of PHINodes are not supported"); 32ae8a8c2dSTsang Whitney W.H STATISTIC(NotMovedTerminator, "Movement of Terminator are not supported"); 33ae8a8c2dSTsang Whitney W.H 3478dc6498SWhitney Tsang namespace { 3578dc6498SWhitney Tsang /// Represent a control condition. A control condition is a condition of a 3678dc6498SWhitney Tsang /// terminator to decide which successors to execute. The pointer field 3778dc6498SWhitney Tsang /// represents the address of the condition of the terminator. The integer field 3878dc6498SWhitney Tsang /// is a bool, it is true when the basic block is executed when V is true. For 3978dc6498SWhitney Tsang /// example, `br %cond, bb0, bb1` %cond is a control condition of bb0 with the 4078dc6498SWhitney Tsang /// integer field equals to true, while %cond is a control condition of bb1 with 4178dc6498SWhitney Tsang /// the integer field equals to false. 4278dc6498SWhitney Tsang using ControlCondition = PointerIntPair<Value *, 1, bool>; 4378dc6498SWhitney Tsang #ifndef NDEBUG 4478dc6498SWhitney Tsang raw_ostream &operator<<(raw_ostream &OS, const ControlCondition &C) { 4578dc6498SWhitney Tsang OS << "[" << *C.getPointer() << ", " << (C.getInt() ? "true" : "false") 4678dc6498SWhitney Tsang << "]"; 4778dc6498SWhitney Tsang return OS; 4878dc6498SWhitney Tsang } 4978dc6498SWhitney Tsang #endif 5078dc6498SWhitney Tsang 5178dc6498SWhitney Tsang /// Represent a set of control conditions required to execute ToBB from FromBB. 5278dc6498SWhitney Tsang class ControlConditions { 5378dc6498SWhitney Tsang using ConditionVectorTy = SmallVector<ControlCondition, 6>; 5478dc6498SWhitney Tsang 5578dc6498SWhitney Tsang /// A SmallVector of control conditions. 5678dc6498SWhitney Tsang ConditionVectorTy Conditions; 5778dc6498SWhitney Tsang 5878dc6498SWhitney Tsang public: 5978dc6498SWhitney Tsang /// Return a ControlConditions which stores all conditions required to execute 6078dc6498SWhitney Tsang /// \p BB from \p Dominator. If \p MaxLookup is non-zero, it limits the 6178dc6498SWhitney Tsang /// number of conditions to collect. Return None if not all conditions are 6278dc6498SWhitney Tsang /// collected successfully, or we hit the limit. 639c54b423SMichael Liao static const Optional<ControlConditions> 6478dc6498SWhitney Tsang collectControlConditions(const BasicBlock &BB, const BasicBlock &Dominator, 6578dc6498SWhitney Tsang const DominatorTree &DT, 6678dc6498SWhitney Tsang const PostDominatorTree &PDT, 6778dc6498SWhitney Tsang unsigned MaxLookup = 6); 6878dc6498SWhitney Tsang 6978dc6498SWhitney Tsang /// Return true if there exists no control conditions required to execute ToBB 7078dc6498SWhitney Tsang /// from FromBB. 7178dc6498SWhitney Tsang bool isUnconditional() const { return Conditions.empty(); } 7278dc6498SWhitney Tsang 7378dc6498SWhitney Tsang /// Return a constant reference of Conditions. 7478dc6498SWhitney Tsang const ConditionVectorTy &getControlConditions() const { return Conditions; } 7578dc6498SWhitney Tsang 7678dc6498SWhitney Tsang /// Add \p V as one of the ControlCondition in Condition with IsTrueCondition 7778dc6498SWhitney Tsang /// equals to \p True. Return true if inserted successfully. 7878dc6498SWhitney Tsang bool addControlCondition(ControlCondition C); 7978dc6498SWhitney Tsang 8078dc6498SWhitney Tsang /// Return true if for all control conditions in Conditions, there exists an 8178dc6498SWhitney Tsang /// equivalent control condition in \p Other.Conditions. 8278dc6498SWhitney Tsang bool isEquivalent(const ControlConditions &Other) const; 8378dc6498SWhitney Tsang 8478dc6498SWhitney Tsang /// Return true if \p C1 and \p C2 are equivalent. 8578dc6498SWhitney Tsang static bool isEquivalent(const ControlCondition &C1, 8678dc6498SWhitney Tsang const ControlCondition &C2); 8778dc6498SWhitney Tsang 8878dc6498SWhitney Tsang private: 8978dc6498SWhitney Tsang ControlConditions() = default; 9078dc6498SWhitney Tsang 9178dc6498SWhitney Tsang static bool isEquivalent(const Value &V1, const Value &V2); 9278dc6498SWhitney Tsang static bool isInverse(const Value &V1, const Value &V2); 9378dc6498SWhitney Tsang }; 9478dc6498SWhitney Tsang } // namespace 9578dc6498SWhitney Tsang 96e71c7b59SSharmaRithik static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, 97e71c7b59SSharmaRithik const Instruction *InstB) { 98e71c7b59SSharmaRithik // Use ordered basic block in case the 2 instructions are in the same 99e71c7b59SSharmaRithik // block. 100e71c7b59SSharmaRithik if (InstA->getParent() == InstB->getParent()) 101e71c7b59SSharmaRithik return InstA->comesBefore(InstB); 102e71c7b59SSharmaRithik 103e71c7b59SSharmaRithik DomTreeNode *DA = DT->getNode(InstA->getParent()); 104e71c7b59SSharmaRithik DomTreeNode *DB = DT->getNode(InstB->getParent()); 105e71c7b59SSharmaRithik return DA->getLevel() < DB->getLevel(); 106e71c7b59SSharmaRithik } 107e71c7b59SSharmaRithik 1089c54b423SMichael Liao const Optional<ControlConditions> ControlConditions::collectControlConditions( 10978dc6498SWhitney Tsang const BasicBlock &BB, const BasicBlock &Dominator, const DominatorTree &DT, 11078dc6498SWhitney Tsang const PostDominatorTree &PDT, unsigned MaxLookup) { 11178dc6498SWhitney Tsang assert(DT.dominates(&Dominator, &BB) && "Expecting Dominator to dominate BB"); 11278dc6498SWhitney Tsang 11378dc6498SWhitney Tsang ControlConditions Conditions; 11478dc6498SWhitney Tsang unsigned NumConditions = 0; 11578dc6498SWhitney Tsang 11678dc6498SWhitney Tsang // BB is executed unconditional from itself. 11778dc6498SWhitney Tsang if (&Dominator == &BB) 11878dc6498SWhitney Tsang return Conditions; 11978dc6498SWhitney Tsang 12078dc6498SWhitney Tsang const BasicBlock *CurBlock = &BB; 12178dc6498SWhitney Tsang // Walk up the dominator tree from the associated DT node for BB to the 12278dc6498SWhitney Tsang // associated DT node for Dominator. 12378dc6498SWhitney Tsang do { 12478dc6498SWhitney Tsang assert(DT.getNode(CurBlock) && "Expecting a valid DT node for CurBlock"); 12578dc6498SWhitney Tsang BasicBlock *IDom = DT.getNode(CurBlock)->getIDom()->getBlock(); 12678dc6498SWhitney Tsang assert(DT.dominates(&Dominator, IDom) && 12778dc6498SWhitney Tsang "Expecting Dominator to dominate IDom"); 12878dc6498SWhitney Tsang 12978dc6498SWhitney Tsang // Limitation: can only handle branch instruction currently. 13078dc6498SWhitney Tsang const BranchInst *BI = dyn_cast<BranchInst>(IDom->getTerminator()); 13178dc6498SWhitney Tsang if (!BI) 13278dc6498SWhitney Tsang return None; 13378dc6498SWhitney Tsang 13478dc6498SWhitney Tsang bool Inserted = false; 13578dc6498SWhitney Tsang if (PDT.dominates(CurBlock, IDom)) { 13678dc6498SWhitney Tsang LLVM_DEBUG(dbgs() << CurBlock->getName() 13778dc6498SWhitney Tsang << " is executed unconditionally from " 13878dc6498SWhitney Tsang << IDom->getName() << "\n"); 13978dc6498SWhitney Tsang } else if (PDT.dominates(CurBlock, BI->getSuccessor(0))) { 14078dc6498SWhitney Tsang LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 14178dc6498SWhitney Tsang << *BI->getCondition() << "\" is true from " 14278dc6498SWhitney Tsang << IDom->getName() << "\n"); 14378dc6498SWhitney Tsang Inserted = Conditions.addControlCondition( 14478dc6498SWhitney Tsang ControlCondition(BI->getCondition(), true)); 14578dc6498SWhitney Tsang } else if (PDT.dominates(CurBlock, BI->getSuccessor(1))) { 14678dc6498SWhitney Tsang LLVM_DEBUG(dbgs() << CurBlock->getName() << " is executed when \"" 14778dc6498SWhitney Tsang << *BI->getCondition() << "\" is false from " 14878dc6498SWhitney Tsang << IDom->getName() << "\n"); 14978dc6498SWhitney Tsang Inserted = Conditions.addControlCondition( 15078dc6498SWhitney Tsang ControlCondition(BI->getCondition(), false)); 15178dc6498SWhitney Tsang } else 15278dc6498SWhitney Tsang return None; 15378dc6498SWhitney Tsang 15478dc6498SWhitney Tsang if (Inserted) 15578dc6498SWhitney Tsang ++NumConditions; 15678dc6498SWhitney Tsang 15778dc6498SWhitney Tsang if (MaxLookup != 0 && NumConditions > MaxLookup) 15878dc6498SWhitney Tsang return None; 15978dc6498SWhitney Tsang 16078dc6498SWhitney Tsang CurBlock = IDom; 16178dc6498SWhitney Tsang } while (CurBlock != &Dominator); 16278dc6498SWhitney Tsang 16378dc6498SWhitney Tsang return Conditions; 16478dc6498SWhitney Tsang } 16578dc6498SWhitney Tsang 16678dc6498SWhitney Tsang bool ControlConditions::addControlCondition(ControlCondition C) { 16778dc6498SWhitney Tsang bool Inserted = false; 16879748addSSimon Pilgrim if (none_of(Conditions, [&](ControlCondition &Exists) { 16978dc6498SWhitney Tsang return ControlConditions::isEquivalent(C, Exists); 17078dc6498SWhitney Tsang })) { 17178dc6498SWhitney Tsang Conditions.push_back(C); 17278dc6498SWhitney Tsang Inserted = true; 17378dc6498SWhitney Tsang } 17478dc6498SWhitney Tsang 17578dc6498SWhitney Tsang LLVM_DEBUG(dbgs() << (Inserted ? "Inserted " : "Not inserted ") << C << "\n"); 17678dc6498SWhitney Tsang return Inserted; 17778dc6498SWhitney Tsang } 17878dc6498SWhitney Tsang 17978dc6498SWhitney Tsang bool ControlConditions::isEquivalent(const ControlConditions &Other) const { 18078dc6498SWhitney Tsang if (Conditions.empty() && Other.Conditions.empty()) 18178dc6498SWhitney Tsang return true; 18278dc6498SWhitney Tsang 18378dc6498SWhitney Tsang if (Conditions.size() != Other.Conditions.size()) 18478dc6498SWhitney Tsang return false; 18578dc6498SWhitney Tsang 18679748addSSimon Pilgrim return all_of(Conditions, [&](const ControlCondition &C) { 18779748addSSimon Pilgrim return any_of(Other.Conditions, [&](const ControlCondition &OtherC) { 18878dc6498SWhitney Tsang return ControlConditions::isEquivalent(C, OtherC); 18978dc6498SWhitney Tsang }); 19078dc6498SWhitney Tsang }); 19178dc6498SWhitney Tsang } 19278dc6498SWhitney Tsang 19378dc6498SWhitney Tsang bool ControlConditions::isEquivalent(const ControlCondition &C1, 19478dc6498SWhitney Tsang const ControlCondition &C2) { 19578dc6498SWhitney Tsang if (C1.getInt() == C2.getInt()) { 19678dc6498SWhitney Tsang if (isEquivalent(*C1.getPointer(), *C2.getPointer())) 19778dc6498SWhitney Tsang return true; 19878dc6498SWhitney Tsang } else if (isInverse(*C1.getPointer(), *C2.getPointer())) 19978dc6498SWhitney Tsang return true; 20078dc6498SWhitney Tsang 20178dc6498SWhitney Tsang return false; 20278dc6498SWhitney Tsang } 20378dc6498SWhitney Tsang 20478dc6498SWhitney Tsang // FIXME: Use SCEV and reuse GVN/CSE logic to check for equivalence between 20578dc6498SWhitney Tsang // Values. 20678dc6498SWhitney Tsang // Currently, isEquivalent rely on other passes to ensure equivalent conditions 20778dc6498SWhitney Tsang // have the same value, e.g. GVN. 20878dc6498SWhitney Tsang bool ControlConditions::isEquivalent(const Value &V1, const Value &V2) { 20978dc6498SWhitney Tsang return &V1 == &V2; 21078dc6498SWhitney Tsang } 21178dc6498SWhitney Tsang 21278dc6498SWhitney Tsang bool ControlConditions::isInverse(const Value &V1, const Value &V2) { 21378dc6498SWhitney Tsang if (const CmpInst *Cmp1 = dyn_cast<CmpInst>(&V1)) 21478dc6498SWhitney Tsang if (const CmpInst *Cmp2 = dyn_cast<CmpInst>(&V2)) { 21578dc6498SWhitney Tsang if (Cmp1->getPredicate() == Cmp2->getInversePredicate() && 21678dc6498SWhitney Tsang Cmp1->getOperand(0) == Cmp2->getOperand(0) && 21778dc6498SWhitney Tsang Cmp1->getOperand(1) == Cmp2->getOperand(1)) 21878dc6498SWhitney Tsang return true; 21978dc6498SWhitney Tsang 22078dc6498SWhitney Tsang if (Cmp1->getPredicate() == 22178dc6498SWhitney Tsang CmpInst::getSwappedPredicate(Cmp2->getInversePredicate()) && 22278dc6498SWhitney Tsang Cmp1->getOperand(0) == Cmp2->getOperand(1) && 22378dc6498SWhitney Tsang Cmp1->getOperand(1) == Cmp2->getOperand(0)) 22478dc6498SWhitney Tsang return true; 22578dc6498SWhitney Tsang } 22678dc6498SWhitney Tsang return false; 22778dc6498SWhitney Tsang } 22878dc6498SWhitney Tsang 229ae8a8c2dSTsang Whitney W.H bool llvm::isControlFlowEquivalent(const Instruction &I0, const Instruction &I1, 230ae8a8c2dSTsang Whitney W.H const DominatorTree &DT, 231ae8a8c2dSTsang Whitney W.H const PostDominatorTree &PDT) { 232aaf7f05aSWhitney Tsang return isControlFlowEquivalent(*I0.getParent(), *I1.getParent(), DT, PDT); 233aaf7f05aSWhitney Tsang } 234aaf7f05aSWhitney Tsang 235aaf7f05aSWhitney Tsang bool llvm::isControlFlowEquivalent(const BasicBlock &BB0, const BasicBlock &BB1, 236aaf7f05aSWhitney Tsang const DominatorTree &DT, 237aaf7f05aSWhitney Tsang const PostDominatorTree &PDT) { 238aaf7f05aSWhitney Tsang if (&BB0 == &BB1) 239aaf7f05aSWhitney Tsang return true; 240aaf7f05aSWhitney Tsang 24178dc6498SWhitney Tsang if ((DT.dominates(&BB0, &BB1) && PDT.dominates(&BB1, &BB0)) || 24278dc6498SWhitney Tsang (PDT.dominates(&BB0, &BB1) && DT.dominates(&BB1, &BB0))) 24378dc6498SWhitney Tsang return true; 24478dc6498SWhitney Tsang 24578dc6498SWhitney Tsang // If the set of conditions required to execute BB0 and BB1 from their common 24678dc6498SWhitney Tsang // dominator are the same, then BB0 and BB1 are control flow equivalent. 24778dc6498SWhitney Tsang const BasicBlock *CommonDominator = DT.findNearestCommonDominator(&BB0, &BB1); 24878dc6498SWhitney Tsang LLVM_DEBUG(dbgs() << "The nearest common dominator of " << BB0.getName() 24978dc6498SWhitney Tsang << " and " << BB1.getName() << " is " 25078dc6498SWhitney Tsang << CommonDominator->getName() << "\n"); 25178dc6498SWhitney Tsang 2529c54b423SMichael Liao const Optional<ControlConditions> BB0Conditions = 25378dc6498SWhitney Tsang ControlConditions::collectControlConditions(BB0, *CommonDominator, DT, 25478dc6498SWhitney Tsang PDT); 25578dc6498SWhitney Tsang if (BB0Conditions == None) 25678dc6498SWhitney Tsang return false; 25778dc6498SWhitney Tsang 2589c54b423SMichael Liao const Optional<ControlConditions> BB1Conditions = 25978dc6498SWhitney Tsang ControlConditions::collectControlConditions(BB1, *CommonDominator, DT, 26078dc6498SWhitney Tsang PDT); 26178dc6498SWhitney Tsang if (BB1Conditions == None) 26278dc6498SWhitney Tsang return false; 26378dc6498SWhitney Tsang 26478dc6498SWhitney Tsang return BB0Conditions->isEquivalent(*BB1Conditions); 265ae8a8c2dSTsang Whitney W.H } 266ae8a8c2dSTsang Whitney W.H 267ae8a8c2dSTsang Whitney W.H static bool reportInvalidCandidate(const Instruction &I, 268ae8a8c2dSTsang Whitney W.H llvm::Statistic &Stat) { 269ae8a8c2dSTsang Whitney W.H ++Stat; 270ae8a8c2dSTsang Whitney W.H LLVM_DEBUG(dbgs() << "Unable to move instruction: " << I << ". " 271ae8a8c2dSTsang Whitney W.H << Stat.getDesc()); 272ae8a8c2dSTsang Whitney W.H return false; 273ae8a8c2dSTsang Whitney W.H } 274ae8a8c2dSTsang Whitney W.H 275ae8a8c2dSTsang Whitney W.H /// Collect all instructions in between \p StartInst and \p EndInst, and store 276ae8a8c2dSTsang Whitney W.H /// them in \p InBetweenInsts. 277ae8a8c2dSTsang Whitney W.H static void 278ae8a8c2dSTsang Whitney W.H collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst, 279ae8a8c2dSTsang Whitney W.H SmallPtrSetImpl<Instruction *> &InBetweenInsts) { 280ae8a8c2dSTsang Whitney W.H assert(InBetweenInsts.empty() && "Expecting InBetweenInsts to be empty"); 281ae8a8c2dSTsang Whitney W.H 282ae8a8c2dSTsang Whitney W.H /// Get the next instructions of \p I, and push them to \p WorkList. 283ae8a8c2dSTsang Whitney W.H auto getNextInsts = [](Instruction &I, 284ae8a8c2dSTsang Whitney W.H SmallPtrSetImpl<Instruction *> &WorkList) { 285ae8a8c2dSTsang Whitney W.H if (Instruction *NextInst = I.getNextNode()) 286ae8a8c2dSTsang Whitney W.H WorkList.insert(NextInst); 287ae8a8c2dSTsang Whitney W.H else { 288ae8a8c2dSTsang Whitney W.H assert(I.isTerminator() && "Expecting a terminator instruction"); 289ae8a8c2dSTsang Whitney W.H for (BasicBlock *Succ : successors(&I)) 290ae8a8c2dSTsang Whitney W.H WorkList.insert(&Succ->front()); 291ae8a8c2dSTsang Whitney W.H } 292ae8a8c2dSTsang Whitney W.H }; 293ae8a8c2dSTsang Whitney W.H 294ae8a8c2dSTsang Whitney W.H SmallPtrSet<Instruction *, 10> WorkList; 295ae8a8c2dSTsang Whitney W.H getNextInsts(StartInst, WorkList); 296ae8a8c2dSTsang Whitney W.H while (!WorkList.empty()) { 297ae8a8c2dSTsang Whitney W.H Instruction *CurInst = *WorkList.begin(); 298ae8a8c2dSTsang Whitney W.H WorkList.erase(CurInst); 299ae8a8c2dSTsang Whitney W.H 300ae8a8c2dSTsang Whitney W.H if (CurInst == &EndInst) 301ae8a8c2dSTsang Whitney W.H continue; 302ae8a8c2dSTsang Whitney W.H 303ae8a8c2dSTsang Whitney W.H if (!InBetweenInsts.insert(CurInst).second) 304ae8a8c2dSTsang Whitney W.H continue; 305ae8a8c2dSTsang Whitney W.H 306ae8a8c2dSTsang Whitney W.H getNextInsts(*CurInst, WorkList); 307ae8a8c2dSTsang Whitney W.H } 308ae8a8c2dSTsang Whitney W.H } 309ae8a8c2dSTsang Whitney W.H 310ae8a8c2dSTsang Whitney W.H bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, 311082e3952SSharmaRithik DominatorTree &DT, const PostDominatorTree *PDT, 312*751be2a0SCongzhe Cao DependenceInfo *DI, bool CheckForEntireBlock) { 313082e3952SSharmaRithik // Skip tests when we don't have PDT or DI 314082e3952SSharmaRithik if (!PDT || !DI) 315082e3952SSharmaRithik return false; 316082e3952SSharmaRithik 317ae8a8c2dSTsang Whitney W.H // Cannot move itself before itself. 318ae8a8c2dSTsang Whitney W.H if (&I == &InsertPoint) 319ae8a8c2dSTsang Whitney W.H return false; 320ae8a8c2dSTsang Whitney W.H 321ae8a8c2dSTsang Whitney W.H // Not moved. 322ae8a8c2dSTsang Whitney W.H if (I.getNextNode() == &InsertPoint) 323ae8a8c2dSTsang Whitney W.H return true; 324ae8a8c2dSTsang Whitney W.H 325ae8a8c2dSTsang Whitney W.H if (isa<PHINode>(I) || isa<PHINode>(InsertPoint)) 326ae8a8c2dSTsang Whitney W.H return reportInvalidCandidate(I, NotMovedPHINode); 327ae8a8c2dSTsang Whitney W.H 328ae8a8c2dSTsang Whitney W.H if (I.isTerminator()) 329ae8a8c2dSTsang Whitney W.H return reportInvalidCandidate(I, NotMovedTerminator); 330ae8a8c2dSTsang Whitney W.H 331ae8a8c2dSTsang Whitney W.H // TODO remove this limitation. 332082e3952SSharmaRithik if (!isControlFlowEquivalent(I, InsertPoint, DT, *PDT)) 333ae8a8c2dSTsang Whitney W.H return reportInvalidCandidate(I, NotControlFlowEquivalent); 334ae8a8c2dSTsang Whitney W.H 335eadf2959SRithik Sharma if (!DT.dominates(&InsertPoint, &I)) 33636bdc3dcSWhitney Tsang for (const Use &U : I.uses()) 33736bdc3dcSWhitney Tsang if (auto *UserInst = dyn_cast<Instruction>(U.getUser())) 33836bdc3dcSWhitney Tsang if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) 339ae8a8c2dSTsang Whitney W.H return false; 340eadf2959SRithik Sharma if (!DT.dominates(&I, &InsertPoint)) 341ae8a8c2dSTsang Whitney W.H for (const Value *Op : I.operands()) 342*751be2a0SCongzhe Cao if (auto *OpInst = dyn_cast<Instruction>(Op)) { 343*751be2a0SCongzhe Cao if (&InsertPoint == OpInst) 344ae8a8c2dSTsang Whitney W.H return false; 345*751be2a0SCongzhe Cao // If OpInst is an instruction that appears earlier in the same BB as 346*751be2a0SCongzhe Cao // I, then it is okay to move since OpInst will still be available. 347*751be2a0SCongzhe Cao if (CheckForEntireBlock && I.getParent() == OpInst->getParent() && 348*751be2a0SCongzhe Cao DT.dominates(OpInst, &I)) 349*751be2a0SCongzhe Cao continue; 350*751be2a0SCongzhe Cao if (!DT.dominates(OpInst, &InsertPoint)) 351*751be2a0SCongzhe Cao return false; 352*751be2a0SCongzhe Cao } 353ae8a8c2dSTsang Whitney W.H 354eadf2959SRithik Sharma DT.updateDFSNumbers(); 355e71c7b59SSharmaRithik const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint); 356ae8a8c2dSTsang Whitney W.H Instruction &StartInst = (MoveForward ? I : InsertPoint); 357ae8a8c2dSTsang Whitney W.H Instruction &EndInst = (MoveForward ? InsertPoint : I); 358ae8a8c2dSTsang Whitney W.H SmallPtrSet<Instruction *, 10> InstsToCheck; 359ae8a8c2dSTsang Whitney W.H collectInstructionsInBetween(StartInst, EndInst, InstsToCheck); 360ae8a8c2dSTsang Whitney W.H if (!MoveForward) 361ae8a8c2dSTsang Whitney W.H InstsToCheck.insert(&InsertPoint); 362ae8a8c2dSTsang Whitney W.H 363ae8a8c2dSTsang Whitney W.H // Check if there exists instructions which may throw, may synchonize, or may 364ae8a8c2dSTsang Whitney W.H // never return, from I to InsertPoint. 365ae8a8c2dSTsang Whitney W.H if (!isSafeToSpeculativelyExecute(&I)) 366df812115SKazu Hirata if (llvm::any_of(InstsToCheck, [](Instruction *I) { 367ae8a8c2dSTsang Whitney W.H if (I->mayThrow()) 368ae8a8c2dSTsang Whitney W.H return true; 369ae8a8c2dSTsang Whitney W.H 370ae8a8c2dSTsang Whitney W.H const CallBase *CB = dyn_cast<CallBase>(I); 371ae8a8c2dSTsang Whitney W.H if (!CB) 372ae8a8c2dSTsang Whitney W.H return false; 373ae8a8c2dSTsang Whitney W.H if (!CB->hasFnAttr(Attribute::WillReturn)) 374ae8a8c2dSTsang Whitney W.H return true; 375ae8a8c2dSTsang Whitney W.H if (!CB->hasFnAttr(Attribute::NoSync)) 376ae8a8c2dSTsang Whitney W.H return true; 377ae8a8c2dSTsang Whitney W.H 378ae8a8c2dSTsang Whitney W.H return false; 379ae8a8c2dSTsang Whitney W.H })) { 380ae8a8c2dSTsang Whitney W.H return reportInvalidCandidate(I, MayThrowException); 381ae8a8c2dSTsang Whitney W.H } 382ae8a8c2dSTsang Whitney W.H 383ae8a8c2dSTsang Whitney W.H // Check if I has any output/flow/anti dependences with instructions from \p 384ae8a8c2dSTsang Whitney W.H // StartInst to \p EndInst. 385df812115SKazu Hirata if (llvm::any_of(InstsToCheck, [&DI, &I](Instruction *CurInst) { 386082e3952SSharmaRithik auto DepResult = DI->depends(&I, CurInst, true); 387df812115SKazu Hirata if (DepResult && (DepResult->isOutput() || DepResult->isFlow() || 388ae8a8c2dSTsang Whitney W.H DepResult->isAnti())) 389ae8a8c2dSTsang Whitney W.H return true; 390ae8a8c2dSTsang Whitney W.H return false; 391ae8a8c2dSTsang Whitney W.H })) 392ae8a8c2dSTsang Whitney W.H return reportInvalidCandidate(I, HasDependences); 393ae8a8c2dSTsang Whitney W.H 394ae8a8c2dSTsang Whitney W.H return true; 395ae8a8c2dSTsang Whitney W.H } 39636bdc3dcSWhitney Tsang 397da58e68fSWhitney Tsang bool llvm::isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, 398082e3952SSharmaRithik DominatorTree &DT, const PostDominatorTree *PDT, 399082e3952SSharmaRithik DependenceInfo *DI) { 400da58e68fSWhitney Tsang return llvm::all_of(BB, [&](Instruction &I) { 401da58e68fSWhitney Tsang if (BB.getTerminator() == &I) 402da58e68fSWhitney Tsang return true; 403da58e68fSWhitney Tsang 404*751be2a0SCongzhe Cao return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI, 405*751be2a0SCongzhe Cao /*CheckForEntireBlock=*/true); 406da58e68fSWhitney Tsang }); 407da58e68fSWhitney Tsang } 408da58e68fSWhitney Tsang 40978dc6498SWhitney Tsang void llvm::moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB, 41078dc6498SWhitney Tsang DominatorTree &DT, 41178dc6498SWhitney Tsang const PostDominatorTree &PDT, 41278dc6498SWhitney Tsang DependenceInfo &DI) { 41336bdc3dcSWhitney Tsang for (auto It = ++FromBB.rbegin(); It != FromBB.rend();) { 41436bdc3dcSWhitney Tsang Instruction *MovePos = ToBB.getFirstNonPHIOrDbg(); 41536bdc3dcSWhitney Tsang Instruction &I = *It; 41636bdc3dcSWhitney Tsang // Increment the iterator before modifying FromBB. 41736bdc3dcSWhitney Tsang ++It; 41836bdc3dcSWhitney Tsang 419082e3952SSharmaRithik if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 42036bdc3dcSWhitney Tsang I.moveBefore(MovePos); 42136bdc3dcSWhitney Tsang } 42236bdc3dcSWhitney Tsang } 423da58e68fSWhitney Tsang 424da58e68fSWhitney Tsang void llvm::moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB, 425da58e68fSWhitney Tsang DominatorTree &DT, 426da58e68fSWhitney Tsang const PostDominatorTree &PDT, 427da58e68fSWhitney Tsang DependenceInfo &DI) { 428da58e68fSWhitney Tsang Instruction *MovePos = ToBB.getTerminator(); 429da58e68fSWhitney Tsang while (FromBB.size() > 1) { 430da58e68fSWhitney Tsang Instruction &I = FromBB.front(); 431082e3952SSharmaRithik if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI)) 432da58e68fSWhitney Tsang I.moveBefore(MovePos); 433da58e68fSWhitney Tsang } 434da58e68fSWhitney Tsang } 435