diff --git a/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h b/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h --- a/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h +++ b/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h @@ -38,14 +38,16 @@ /// Return true if \p I can be safely moved before \p InsertPoint. bool isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, - DominatorTree &DT, const PostDominatorTree &PDT, - DependenceInfo &DI); + DominatorTree *DT = nullptr, + const PostDominatorTree *PDT = nullptr, + DependenceInfo *DI = nullptr); /// Return true if all instructions (except the terminator) in \p BB can be /// safely moved before \p InsertPoint. bool isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, - DominatorTree &DT, const PostDominatorTree &PDT, - DependenceInfo &DI); + DominatorTree *DT = nullptr, + const PostDominatorTree *PDT = nullptr, + DependenceInfo *DI = nullptr); /// Move instructions, in an order-preserving manner, from \p FromBB to the /// beginning of \p ToBB when proven safe. diff --git a/llvm/lib/Transforms/Scalar/LoopFuse.cpp b/llvm/lib/Transforms/Scalar/LoopFuse.cpp --- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp +++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp @@ -743,8 +743,8 @@ } if (!isSafeToMoveBefore(*FC1->Preheader, - *FC0->Preheader->getTerminator(), DT, PDT, - DI)) { + *FC0->Preheader->getTerminator(), &DT, &PDT, + &DI)) { LLVM_DEBUG(dbgs() << "Fusion candidate contains unsafe " "instructions in preheader. Not fusing.\n"); reportLoopFusion(*FC0, *FC1, @@ -756,8 +756,8 @@ assert(FC1->GuardBranch && "Expecting valid FC1 guard branch"); if (!isSafeToMoveBefore(*FC0->ExitBlock, - *FC1->ExitBlock->getFirstNonPHIOrDbg(), DT, - PDT, DI)) { + *FC1->ExitBlock->getFirstNonPHIOrDbg(), &DT, + &PDT, &DI)) { LLVM_DEBUG(dbgs() << "Fusion candidate contains unsafe " "instructions in exit block. Not fusing.\n"); reportLoopFusion(*FC0, *FC1, @@ -767,8 +767,8 @@ if (!isSafeToMoveBefore( *FC1->GuardBranch->getParent(), - *FC0->GuardBranch->getParent()->getTerminator(), DT, PDT, - DI)) { + *FC0->GuardBranch->getParent()->getTerminator(), &DT, &PDT, + &DI)) { LLVM_DEBUG(dbgs() << "Fusion candidate contains unsafe " "instructions in guard block. Not fusing.\n"); diff --git a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp --- a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp +++ b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp @@ -297,8 +297,8 @@ } bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, - DominatorTree &DT, const PostDominatorTree &PDT, - DependenceInfo &DI) { + DominatorTree *DT, const PostDominatorTree *PDT, + DependenceInfo *DI) { // Cannot move itself before itself. if (&I == &InsertPoint) return false; @@ -313,23 +313,23 @@ if (I.isTerminator()) return reportInvalidCandidate(I, NotMovedTerminator); - // TODO remove this limitation. - if (!isControlFlowEquivalent(I, InsertPoint, DT, PDT)) - return reportInvalidCandidate(I, NotControlFlowEquivalent); + // Skip tests that need DT + if (!DT) + return false; - if (!DT.dominates(&InsertPoint, &I)) + if (!DT->dominates(&InsertPoint, &I)) for (const Use &U : I.uses()) if (auto *UserInst = dyn_cast(U.getUser())) - if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) + if (UserInst != &InsertPoint && !DT->dominates(&InsertPoint, U)) return false; - if (!DT.dominates(&I, &InsertPoint)) + if (!DT->dominates(&I, &InsertPoint)) for (const Value *Op : I.operands()) if (auto *OpInst = dyn_cast(Op)) - if (&InsertPoint == OpInst || !DT.dominates(OpInst, &InsertPoint)) + if (&InsertPoint == OpInst || !DT->dominates(OpInst, &InsertPoint)) return false; - OrderedInstructions OI(&DT); - DT.updateDFSNumbers(); + OrderedInstructions OI(DT); + DT->updateDFSNumbers(); const bool MoveForward = OI.domTreeLevelBefore(&I, &InsertPoint); Instruction &StartInst = (MoveForward ? I : InsertPoint); Instruction &EndInst = (MoveForward ? InsertPoint : I); @@ -359,11 +359,23 @@ return reportInvalidCandidate(I, MayThrowException); } + // Skip checks that require DT and PDT + if (!(DT && PDT)) + return true; + + // TODO remove this limitation. + if (!isControlFlowEquivalent(I, InsertPoint, *DT, *PDT)) + return reportInvalidCandidate(I, NotControlFlowEquivalent); + + // Skip DependenceInfo checks as we don't have DI + if (!DI) + return true; + // Check if I has any output/flow/anti dependences with instructions from \p // StartInst to \p EndInst. if (std::any_of(InstsToCheck.begin(), InstsToCheck.end(), [&DI, &I](Instruction *CurInst) { - auto DepResult = DI.depends(&I, CurInst, true); + auto DepResult = DI->depends(&I, CurInst, true); if (DepResult && (DepResult->isOutput() || DepResult->isFlow() || DepResult->isAnti())) @@ -376,8 +388,8 @@ } bool llvm::isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, - DominatorTree &DT, const PostDominatorTree &PDT, - DependenceInfo &DI) { + DominatorTree *DT, const PostDominatorTree *PDT, + DependenceInfo *DI) { return llvm::all_of(BB, [&](Instruction &I) { if (BB.getTerminator() == &I) return true; @@ -396,7 +408,7 @@ // Increment the iterator before modifying FromBB. ++It; - if (isSafeToMoveBefore(I, *MovePos, DT, PDT, DI)) + if (isSafeToMoveBefore(I, *MovePos, &DT, &PDT, &DI)) I.moveBefore(MovePos); } } @@ -408,7 +420,7 @@ Instruction *MovePos = ToBB.getTerminator(); while (FromBB.size() > 1) { Instruction &I = FromBB.front(); - if (isSafeToMoveBefore(I, *MovePos, DT, PDT, DI)) + if (isSafeToMoveBefore(I, *MovePos, &DT, &PDT, &DI)) I.moveBefore(MovePos); } } diff --git a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp --- a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp @@ -505,48 +505,50 @@ // Can move after CI_safecall, as it does not throw, not synchronize, or // must return. EXPECT_TRUE(isSafeToMoveBefore(*CI_safecall->getPrevNode(), - *CI_safecall->getNextNode(), DT, PDT, - DI)); + *CI_safecall->getNextNode(), &DT, &PDT, + &DI)); // Cannot move CI_unsafecall, as it may throw. EXPECT_FALSE(isSafeToMoveBefore(*CI_unsafecall->getNextNode(), - *CI_unsafecall, DT, PDT, DI)); + *CI_unsafecall, &DT, &PDT, &DI)); // Moving instruction to non control flow equivalent places are not // supported. - EXPECT_FALSE( - isSafeToMoveBefore(*SI_A5, *Entry->getTerminator(), DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*SI_A5, *Entry->getTerminator(), &DT, + &PDT, &DI)); // Moving PHINode is not supported. EXPECT_FALSE(isSafeToMoveBefore(PN, *PN.getNextNode()->getNextNode(), - DT, PDT, DI)); + &DT, &PDT, &DI)); // Cannot move non-PHINode before PHINode. - EXPECT_FALSE(isSafeToMoveBefore(*PN.getNextNode(), PN, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*PN.getNextNode(), PN, &DT, &PDT, &DI)); // Moving Terminator is not supported. EXPECT_FALSE(isSafeToMoveBefore(*Entry->getTerminator(), - *PN.getNextNode(), DT, PDT, DI)); + *PN.getNextNode(), &DT, &PDT, &DI)); // Cannot move %arrayidx_A after SI, as SI is its user. EXPECT_FALSE(isSafeToMoveBefore(*SI->getPrevNode(), *SI->getNextNode(), - DT, PDT, DI)); + &DT, &PDT, &DI)); // Cannot move SI before %arrayidx_A, as %arrayidx_A is its operand. - EXPECT_FALSE(isSafeToMoveBefore(*SI, *SI->getPrevNode(), DT, PDT, DI)); + EXPECT_FALSE( + isSafeToMoveBefore(*SI, *SI->getPrevNode(), &DT, &PDT, &DI)); // Cannot move LI2 after SI_A6, as there is a flow dependence. EXPECT_FALSE( - isSafeToMoveBefore(*LI2, *SI_A6->getNextNode(), DT, PDT, DI)); + isSafeToMoveBefore(*LI2, *SI_A6->getNextNode(), &DT, &PDT, &DI)); // Cannot move SI after LI1, as there is a anti dependence. - EXPECT_FALSE(isSafeToMoveBefore(*SI, *LI1->getNextNode(), DT, PDT, DI)); + EXPECT_FALSE( + isSafeToMoveBefore(*SI, *LI1->getNextNode(), &DT, &PDT, &DI)); // Cannot move SI_A5 after SI, as there is a output dependence. - EXPECT_FALSE(isSafeToMoveBefore(*SI_A5, *LI1, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*SI_A5, *LI1, &DT, &PDT, &DI)); // Can move LI2 before LI1, as there is only an input dependence. - EXPECT_TRUE(isSafeToMoveBefore(*LI2, *LI1, DT, PDT, DI)); + EXPECT_TRUE(isSafeToMoveBefore(*LI2, *LI1, &DT, &PDT, &DI)); }); } @@ -578,11 +580,11 @@ Instruction *SubInst = getInstructionByName(F, "sub"); // Cannot move as %user uses %add and %sub doesn't dominates %user. - EXPECT_FALSE(isSafeToMoveBefore(*AddInst, *SubInst, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*AddInst, *SubInst, &DT, &PDT, &DI)); // Cannot move as %sub_op0 is an operand of %sub and %add doesn't // dominates %sub_op0. - EXPECT_FALSE(isSafeToMoveBefore(*SubInst, *AddInst, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*SubInst, *AddInst, &DT, &PDT, &DI)); }); } @@ -611,7 +613,7 @@ // Can move as the incoming block of %inc for %i (%for.latch) dominated // by %cmp. - EXPECT_TRUE(isSafeToMoveBefore(*IncInst, *CmpInst, DT, PDT, DI)); + EXPECT_TRUE(isSafeToMoveBefore(*IncInst, *CmpInst, &DT, &PDT, &DI)); }); } @@ -643,10 +645,10 @@ Instruction *SubInst = getInstructionByName(F, "sub"); // Cannot move as %user uses %add and %sub doesn't dominates %user. - EXPECT_FALSE(isSafeToMoveBefore(*AddInst, *SubInst, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*AddInst, *SubInst, &DT, &PDT, &DI)); // Cannot move as %sub_op0 is an operand of %sub and %add doesn't // dominates %sub_op0. - EXPECT_FALSE(isSafeToMoveBefore(*SubInst, *AddInst, DT, PDT, DI)); + EXPECT_FALSE(isSafeToMoveBefore(*SubInst, *AddInst, &DT, &PDT, &DI)); }); }