bool isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
DominatorTree &DT,
const PostDominatorTree *PDT = nullptr,
- DependenceInfo *DI = nullptr);
+ DependenceInfo *DI = nullptr,
+ bool CheckForEntireBlock = false);
/// Return true if all instructions (except the terminator) in \p BB can be
/// safely moved before \p InsertPoint.
bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
DominatorTree &DT, const PostDominatorTree *PDT,
- DependenceInfo *DI) {
+ DependenceInfo *DI, bool CheckForEntireBlock) {
// Skip tests when we don't have PDT or DI
if (!PDT || !DI)
return false;
return false;
if (!DT.dominates(&I, &InsertPoint))
for (const Value *Op : I.operands())
- if (auto *OpInst = dyn_cast<Instruction>(Op))
- if (&InsertPoint == OpInst || !DT.dominates(OpInst, &InsertPoint))
+ if (auto *OpInst = dyn_cast<Instruction>(Op)) {
+ if (&InsertPoint == OpInst)
+ return false;
+ // If OpInst is an instruction that appears earlier in the same BB as
+ // I, then it is okay to move since OpInst will still be available.
+ if (CheckForEntireBlock && I.getParent() == OpInst->getParent() &&
+ DT.dominates(OpInst, &I))
+ continue;
+ if (!DT.dominates(OpInst, &InsertPoint))
return false;
+ }
DT.updateDFSNumbers();
const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint);
if (BB.getTerminator() == &I)
return true;
- return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI);
+ return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI,
+ /*CheckForEntireBlock=*/true);
});
}
br label %for.latch
for.latch:
%cmp = icmp slt i64 %inc, %N
+ %add = add i64 100, %N
+ %add2 = add i64 %add, %N
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
DependenceInfo &DI) {
Instruction *IncInst = getInstructionByName(F, "inc");
Instruction *CmpInst = getInstructionByName(F, "cmp");
+ BasicBlock *BB0 = getBasicBlockByName(F, "for.body");
+ BasicBlock *BB1 = getBasicBlockByName(F, "for.latch");
// Can move as the incoming block of %inc for %i (%for.latch) dominated
// by %cmp.
EXPECT_TRUE(isSafeToMoveBefore(*IncInst, *CmpInst, DT, &PDT, &DI));
+
+ // Can move as the operands of instructions in BB1 either dominate
+ // InsertPoint or appear before that instruction, e.g., %add appears
+ // before %add2 although %add does not dominate InsertPoint.
+ EXPECT_TRUE(
+ isSafeToMoveBefore(*BB1, *BB0->getTerminator(), DT, &PDT, &DI));
});
}