mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[CodeMoverUtils] Make specific analysis dependent checks optional
Summary: This patch makes code motion checks optional which are dependent on specific analysis example, dominator tree, post dominator tree and dependence info. The aim is to make the adoption of CodeMoverUtils easier for clients that don't use analysis which were strictly required by CodeMoverUtils. This will also help in diversifying code motion checks using other analysis example MSSA. Authored By: RithikSharma Reviewer: Whitney, bmahjour, etiotto Reviewed By: Whitney Subscribers: Prazek, hiraditya, george.burgess.iv, asbirlea, llvm-commits Tag: LLVM Differential Revision: https://reviews.llvm.org/D82566
This commit is contained in:
parent
a3a41cd01b
commit
ee7090c659
@ -38,14 +38,16 @@ bool isControlFlowEquivalent(const BasicBlock &BB0, const BasicBlock &BB1,
|
||||
|
||||
/// 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,
|
||||
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,
|
||||
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.
|
||||
|
@ -743,8 +743,8 @@ private:
|
||||
}
|
||||
|
||||
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<OptimizationRemarkMissed>(*FC0, *FC1,
|
||||
@ -757,7 +757,7 @@ private:
|
||||
|
||||
if (!isSafeToMoveBefore(*FC0->ExitBlock,
|
||||
*FC1->ExitBlock->getFirstNonPHIOrDbg(), DT,
|
||||
PDT, DI)) {
|
||||
&PDT, &DI)) {
|
||||
LLVM_DEBUG(dbgs() << "Fusion candidate contains unsafe "
|
||||
"instructions in exit block. Not fusing.\n");
|
||||
reportLoopFusion<OptimizationRemarkMissed>(*FC0, *FC1,
|
||||
@ -767,8 +767,8 @@ private:
|
||||
|
||||
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");
|
||||
|
@ -297,8 +297,12 @@ collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst,
|
||||
}
|
||||
|
||||
bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
|
||||
DominatorTree &DT, const PostDominatorTree &PDT,
|
||||
DependenceInfo &DI) {
|
||||
DominatorTree &DT, const PostDominatorTree *PDT,
|
||||
DependenceInfo *DI) {
|
||||
// Skip tests when we don't have PDT or DI
|
||||
if (!PDT || !DI)
|
||||
return false;
|
||||
|
||||
// Cannot move itself before itself.
|
||||
if (&I == &InsertPoint)
|
||||
return false;
|
||||
@ -314,7 +318,7 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
|
||||
return reportInvalidCandidate(I, NotMovedTerminator);
|
||||
|
||||
// TODO remove this limitation.
|
||||
if (!isControlFlowEquivalent(I, InsertPoint, DT, PDT))
|
||||
if (!isControlFlowEquivalent(I, InsertPoint, DT, *PDT))
|
||||
return reportInvalidCandidate(I, NotControlFlowEquivalent);
|
||||
|
||||
if (!DT.dominates(&InsertPoint, &I))
|
||||
@ -363,7 +367,7 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
|
||||
// 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 +380,8 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
|
||||
}
|
||||
|
||||
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 +400,7 @@ void llvm::moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB,
|
||||
// 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 +412,7 @@ void llvm::moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -505,48 +505,50 @@ TEST(CodeMoverUtils, IsSafeToMoveTest1) {
|
||||
// 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 @@ TEST(CodeMoverUtils, IsSafeToMoveTest2) {
|
||||
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 @@ TEST(CodeMoverUtils, IsSafeToMoveTest3) {
|
||||
|
||||
// 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 @@ TEST(CodeMoverUtils, IsSafeToMoveTest4) {
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user