diff --git a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp index 6a2dae5bab68e..ac106e4aa2a39 100644 --- a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp +++ b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp @@ -336,9 +336,22 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, if (isReachedBefore(&I, &InsertPoint, &DT, PDT)) for (const Use &U : I.uses()) - if (auto *UserInst = dyn_cast(U.getUser())) - if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) + if (auto *UserInst = dyn_cast(U.getUser())) { + // If InsertPoint is in a BB that comes after I, then we cannot move if + // I is used in the terminator of the current BB. + if (I.getParent() == InsertPoint.getParent() && + UserInst == I.getParent()->getTerminator()) return false; + if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) { + // If UserInst is an instruction that appears later in the same BB as + // I, then it is okay to move since I will still be available when + // UserInst is executed. + if (CheckForEntireBlock && I.getParent() == UserInst->getParent() && + DT.dominates(&I, UserInst)) + continue; + return false; + } + } if (isReachedBefore(&InsertPoint, &I, &DT, PDT)) for (const Value *Op : I.operands()) if (auto *OpInst = dyn_cast(Op)) { diff --git a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp index 8554d1a33cade..dbc1e21527855 100644 --- a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp @@ -673,6 +673,11 @@ TEST(CodeMoverUtils, IsSafeToMoveTest4) { // Can move as %add2 and %sub2 are control flow equivalent, // although %add2 does not strictly dominate %sub2. EXPECT_TRUE(isSafeToMoveBefore(*SubInst2, *AddInst2, DT, &PDT, &DI)); + + BasicBlock *BB0 = getBasicBlockByName(F, "if.then.first"); + BasicBlock *BB1 = getBasicBlockByName(F, "if.then.second"); + EXPECT_TRUE( + isSafeToMoveBefore(*BB0, *BB1->getTerminator(), DT, &PDT, &DI)); }); }