[JumpThreading] Thread through guards
Summary:
This patch allows JumpThreading also thread through guards.
Virtually, guard(cond) is equivalent to the following construction:
if (cond) { do something } else {deoptimize}
Yet it is not explicitly converted into IFs before lowering.
This patch enables early threading through guards in simple cases.
Currently it covers the following situation:
if (cond1) {
// code A
} else {
// code B
}
// code C
guard(cond2)
// code D
If there is implication cond1 => cond2 or !cond1 => cond2, we can transform
this construction into the following:
if (cond1) {
// code A
// code C
} else {
// code B
// code C
guard(cond2)
}
// code D
Thus, removing the guard from one of execution branches.
Patch by Max Kazantsev!
Reviewers: reames, apilipenko, igor-laevsky, anna, sanjoy
Reviewed By: sanjoy
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D29620
llvm-svn: 294617
This commit is contained in:
@@ -747,3 +747,40 @@ Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
|
||||
|
||||
return NewLoop;
|
||||
}
|
||||
|
||||
/// \brief Duplicate non-Phi instructions from the beginning of block up to
|
||||
/// StopAt instruction into a split block between BB and its predecessor.
|
||||
BasicBlock *
|
||||
llvm::DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB,
|
||||
Instruction *StopAt,
|
||||
ValueToValueMapTy &ValueMapping) {
|
||||
// We are going to have to map operands from the original BB block to the new
|
||||
// copy of the block 'NewBB'. If there are PHI nodes in BB, evaluate them to
|
||||
// account for entry from PredBB.
|
||||
BasicBlock::iterator BI = BB->begin();
|
||||
for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
|
||||
ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB);
|
||||
|
||||
BasicBlock *NewBB = SplitEdge(PredBB, BB);
|
||||
NewBB->setName(PredBB->getName() + ".split");
|
||||
Instruction *NewTerm = NewBB->getTerminator();
|
||||
|
||||
// Clone the non-phi instructions of BB into NewBB, keeping track of the
|
||||
// mapping and using it to remap operands in the cloned instructions.
|
||||
for (; StopAt != &*BI; ++BI) {
|
||||
Instruction *New = BI->clone();
|
||||
New->setName(BI->getName());
|
||||
New->insertBefore(NewTerm);
|
||||
ValueMapping[&*BI] = New;
|
||||
|
||||
// Remap operands to patch up intra-block references.
|
||||
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
|
||||
if (Instruction *Inst = dyn_cast<Instruction>(New->getOperand(i))) {
|
||||
auto I = ValueMapping.find(Inst);
|
||||
if (I != ValueMapping.end())
|
||||
New->setOperand(i, I->second);
|
||||
}
|
||||
}
|
||||
|
||||
return NewBB;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user