[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:
Anna Thomas 2021-09-12 15:11:26 -04:00
parent 9d359f6c73
commit b4e787d8f4
1 changed files with 53 additions and 42 deletions

View File

@ -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);