forked from OSchip/llvm-project
[InstCombining] Refactor checks for TryToSinkInstruction. NFC
Moved out the checks for profitability of TryToSinkInstructions into a lambda function. This will also allow us to easily add checks for bailing out if the transform is not profitable. Tests-Run: instCombine tests.
This commit is contained in:
parent
9d359f6c73
commit
b4e787d8f4
|
@ -3813,51 +3813,62 @@ bool InstCombinerImpl::run() {
|
||||||
|
|
||||||
// See if we can trivially sink this instruction to its user if we can
|
// See if we can trivially sink this instruction to its user if we can
|
||||||
// prove that the successor is not executed more frequently than our block.
|
// prove that the successor is not executed more frequently than our block.
|
||||||
if (EnableCodeSinking)
|
// Return the UserBlock if successful.
|
||||||
if (Use *SingleUse = I->getSingleUndroppableUse()) {
|
auto getOptionalSinkBlockForInst =
|
||||||
BasicBlock *BB = I->getParent();
|
[this](Instruction *I) -> Optional<BasicBlock *> {
|
||||||
Instruction *UserInst = cast<Instruction>(SingleUse->getUser());
|
if (!EnableCodeSinking)
|
||||||
BasicBlock *UserParent;
|
return None;
|
||||||
|
Use *SingleUse = I->getSingleUndroppableUse();
|
||||||
|
if (!SingleUse)
|
||||||
|
return None;
|
||||||
|
|
||||||
// Get the block the use occurs in.
|
BasicBlock *BB = I->getParent();
|
||||||
if (PHINode *PN = dyn_cast<PHINode>(UserInst))
|
Instruction *UserInst = cast<Instruction>(SingleUse->getUser());
|
||||||
UserParent = PN->getIncomingBlock(*SingleUse);
|
BasicBlock *UserParent;
|
||||||
else
|
|
||||||
UserParent = UserInst->getParent();
|
|
||||||
|
|
||||||
// Try sinking to another block. If that block is unreachable, then do
|
// Get the block the use occurs in.
|
||||||
// not bother. SimplifyCFG should handle it.
|
if (PHINode *PN = dyn_cast<PHINode>(UserInst))
|
||||||
if (UserParent != BB && DT.isReachableFromEntry(UserParent)) {
|
UserParent = PN->getIncomingBlock(*SingleUse);
|
||||||
// See if the user is one of our successors that has only one
|
else
|
||||||
// predecessor, so that we don't have to split the critical edge.
|
UserParent = UserInst->getParent();
|
||||||
bool ShouldSink = UserParent->getUniquePredecessor() == BB;
|
|
||||||
// Another option where we can sink is a block that ends with a
|
// Try sinking to another block. If that block is unreachable, then do
|
||||||
// terminator that does not pass control to other block (such as
|
// not bother. SimplifyCFG should handle it.
|
||||||
// return or unreachable). In this case:
|
if (UserParent == BB || !DT.isReachableFromEntry(UserParent))
|
||||||
// - I dominates the User (by SSA form);
|
return None;
|
||||||
// - the User will be executed at most once.
|
|
||||||
// So sinking I down to User is always profitable or neutral.
|
auto *Term = UserParent->getTerminator();
|
||||||
if (!ShouldSink) {
|
// See if the user is one of our successors that has only one
|
||||||
auto *Term = UserParent->getTerminator();
|
// predecessor, so that we don't have to split the critical edge.
|
||||||
ShouldSink = isa<ReturnInst>(Term) || isa<UnreachableInst>(Term);
|
// Another option where we can sink is a block that ends with a
|
||||||
}
|
// terminator that does not pass control to other block (such as
|
||||||
if (ShouldSink) {
|
// return or unreachable). In this case:
|
||||||
assert(DT.dominates(BB, UserParent) &&
|
// - I dominates the User (by SSA form);
|
||||||
"Dominance relation broken?");
|
// - the User will be executed at most once.
|
||||||
// Okay, the CFG is simple enough, try to sink this instruction.
|
// So sinking I down to User is always profitable or neutral.
|
||||||
if (TryToSinkInstruction(I, UserParent)) {
|
if (UserParent->getUniquePredecessor() == BB ||
|
||||||
LLVM_DEBUG(dbgs() << "IC: Sink: " << *I << '\n');
|
(isa<ReturnInst>(Term) || isa<UnreachableInst>(Term))) {
|
||||||
MadeIRChange = true;
|
assert(DT.dominates(BB, UserParent) && "Dominance relation broken?");
|
||||||
// We'll add uses of the sunk instruction below, but since sinking
|
return UserParent;
|
||||||
// can expose opportunities for it's *operands* add them to the
|
|
||||||
// worklist
|
|
||||||
for (Use &U : I->operands())
|
|
||||||
if (Instruction *OpI = dyn_cast<Instruction>(U.get()))
|
|
||||||
Worklist.push(OpI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto OptBB = getOptionalSinkBlockForInst(I);
|
||||||
|
if (OptBB) {
|
||||||
|
auto *UserParent = *OptBB;
|
||||||
|
// Okay, the CFG is simple enough, try to sink this instruction.
|
||||||
|
if (TryToSinkInstruction(I, UserParent)) {
|
||||||
|
LLVM_DEBUG(dbgs() << "IC: Sink: " << *I << '\n');
|
||||||
|
MadeIRChange = true;
|
||||||
|
// We'll add uses of the sunk instruction below, but since
|
||||||
|
// sinking can expose opportunities for it's *operands* add
|
||||||
|
// them to the worklist
|
||||||
|
for (Use &U : I->operands())
|
||||||
|
if (Instruction *OpI = dyn_cast<Instruction>(U.get()))
|
||||||
|
Worklist.push(OpI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we have an instruction, try combining it to simplify it.
|
// Now that we have an instruction, try combining it to simplify it.
|
||||||
Builder.SetInsertPoint(I);
|
Builder.SetInsertPoint(I);
|
||||||
|
|
Loading…
Reference in New Issue