forked from OSchip/llvm-project
Revert "[JumpThreading] Unfold selects that depend on the same condition"
This reverts commit ac54d0066c478a09c7cd28d15d0f9ff8af984afc. llvm-svn: 286976
This commit is contained in:
parent
5f782bb048
commit
4f80c93a2e
|
@ -129,8 +129,6 @@ private:
|
|||
BasicBlock *NewBB, BasicBlock *SuccBB);
|
||||
/// Check if the block has profile metadata for its outgoing edges.
|
||||
bool doesBlockHaveProfileData(BasicBlock *BB);
|
||||
SelectInst *getSelectFedByPhi(PHINode *PN);
|
||||
void expandSelect(SelectInst *SI);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -1963,100 +1963,61 @@ bool JumpThreadingPass::TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// GetSelectFedByPhi - Look for PHI/Select in the same BB of the form
|
||||
/// TryToUnfoldSelectInCurrBB - Look for PHI/Select in the same BB of the form
|
||||
/// bb:
|
||||
/// %p = phi [false, %bb1], [true, %bb2], [false, %bb3], [true, %bb4], ...
|
||||
/// %s = select p, trueval, falseval
|
||||
///
|
||||
/// And return the select. Unfolding it into a branch structure later enables
|
||||
/// And expand the select into a branch structure. This later enables
|
||||
/// jump-threading over bb in this pass.
|
||||
///
|
||||
/// Using the similar approach of SimplifyCFG::FoldCondBranchOnPHI(), return
|
||||
/// select if the associated PHI has at least one constant.
|
||||
SelectInst *JumpThreadingPass::getSelectFedByPhi(PHINode *PN) {
|
||||
|
||||
unsigned NumPHIValues = PN->getNumIncomingValues();
|
||||
if (NumPHIValues == 0 || !PN->hasOneUse())
|
||||
return nullptr;
|
||||
|
||||
SelectInst *SI = dyn_cast<SelectInst>(PN->user_back());
|
||||
BasicBlock *BB = PN->getParent();
|
||||
if (!SI || SI->getParent() != BB)
|
||||
return nullptr;
|
||||
|
||||
Value *Cond = SI->getCondition();
|
||||
if (!Cond || Cond != PN || !Cond->getType()->isIntegerTy(1))
|
||||
return nullptr;
|
||||
|
||||
for (unsigned i = 0; i != NumPHIValues; ++i) {
|
||||
if (PN->getIncomingBlock(i) == BB)
|
||||
return nullptr;
|
||||
if (isa<ConstantInt>(PN->getIncomingValue(i)))
|
||||
return SI;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// ExpandSelect - Expand a select into an if-then-else construct.
|
||||
void JumpThreadingPass::expandSelect(SelectInst *SI) {
|
||||
|
||||
BasicBlock *BB = SI->getParent();
|
||||
TerminatorInst *Term =
|
||||
SplitBlockAndInsertIfThen(SI->getCondition(), SI, false);
|
||||
PHINode *NewPN = PHINode::Create(SI->getType(), 2, "", SI);
|
||||
NewPN->addIncoming(SI->getTrueValue(), Term->getParent());
|
||||
NewPN->addIncoming(SI->getFalseValue(), BB);
|
||||
SI->replaceAllUsesWith(NewPN);
|
||||
SI->eraseFromParent();
|
||||
}
|
||||
|
||||
/// TryToUnfoldSelectInCurrBB - Unfold selects that could be jump-threaded were
|
||||
/// they if-then-elses. If the unfolded selects are not jump-threaded, it will
|
||||
/// be folded again in the later optimizations.
|
||||
/// Using the similar approach of SimplifyCFG::FoldCondBranchOnPHI(), unfold
|
||||
/// select if the associated PHI has at least one constant. If the unfolded
|
||||
/// select is not jump-threaded, it will be folded again in the later
|
||||
/// optimizations.
|
||||
bool JumpThreadingPass::TryToUnfoldSelectInCurrBB(BasicBlock *BB) {
|
||||
|
||||
// If threading this would thread across a loop header, don't thread the edge.
|
||||
// See the comments above FindLoopHeaders for justifications and caveats.
|
||||
if (LoopHeaders.count(BB))
|
||||
return false;
|
||||
|
||||
bool Changed = false;
|
||||
for (auto &I : *BB) {
|
||||
|
||||
// Look for a Phi/Select pair in the same basic block. The Phi feeds the
|
||||
// condition of the Select and at least one of the incoming values is a
|
||||
// constant.
|
||||
PHINode *PN;
|
||||
SelectInst *SI;
|
||||
if ((PN = dyn_cast<PHINode>(&I)) && (SI = getSelectFedByPhi(PN))) {
|
||||
expandSelect(SI);
|
||||
Changed = true;
|
||||
// Look for a Phi/Select pair in the same basic block. The Phi feeds the
|
||||
// condition of the Select and at least one of the incoming values is a
|
||||
// constant.
|
||||
for (BasicBlock::iterator BI = BB->begin();
|
||||
PHINode *PN = dyn_cast<PHINode>(BI); ++BI) {
|
||||
unsigned NumPHIValues = PN->getNumIncomingValues();
|
||||
if (NumPHIValues == 0 || !PN->hasOneUse())
|
||||
continue;
|
||||
|
||||
SelectInst *SI = dyn_cast<SelectInst>(PN->user_back());
|
||||
if (!SI || SI->getParent() != BB)
|
||||
continue;
|
||||
|
||||
Value *Cond = SI->getCondition();
|
||||
if (!Cond || Cond != PN || !Cond->getType()->isIntegerTy(1))
|
||||
continue;
|
||||
|
||||
bool HasConst = false;
|
||||
for (unsigned i = 0; i != NumPHIValues; ++i) {
|
||||
if (PN->getIncomingBlock(i) == BB)
|
||||
return false;
|
||||
if (isa<ConstantInt>(PN->getIncomingValue(i)))
|
||||
HasConst = true;
|
||||
}
|
||||
|
||||
if (I.getType()->isIntegerTy(1)) {
|
||||
|
||||
SmallVector<SelectInst *, 4> Selects;
|
||||
|
||||
// Look for scalar booleans used in selects as conditions. If there are
|
||||
// several selects that use the same boolean, they are candidates for jump
|
||||
// threading and therefore we should unfold them.
|
||||
for (Value *U : I.users())
|
||||
if (auto *SI = dyn_cast<SelectInst>(U))
|
||||
Selects.push_back(SI);
|
||||
if (Selects.size() <= 1)
|
||||
continue;
|
||||
|
||||
// Remove duplicates
|
||||
std::sort(Selects.begin(), Selects.end());
|
||||
auto NewEnd = std::unique(Selects.begin(), Selects.end());
|
||||
|
||||
Changed = true;
|
||||
for (auto SI = Selects.begin(); SI != NewEnd; ++SI)
|
||||
expandSelect(*SI);
|
||||
if (HasConst) {
|
||||
// Expand the select.
|
||||
TerminatorInst *Term =
|
||||
SplitBlockAndInsertIfThen(SI->getCondition(), SI, false);
|
||||
PHINode *NewPN = PHINode::Create(SI->getType(), 2, "", SI);
|
||||
NewPN->addIncoming(SI->getTrueValue(), Term->getParent());
|
||||
NewPN->addIncoming(SI->getFalseValue(), BB);
|
||||
SI->replaceAllUsesWith(NewPN);
|
||||
SI->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
; RUN: opt < %s -jump-threading -instcombine -simplifycfg -S | FileCheck %s
|
||||
|
||||
; The three selects are jump-threaded so that instcombine can optimize, and
|
||||
; simplifycfg should turn the result into a single select.
|
||||
define i32 @f(i32 %a, i32 %b) {
|
||||
; CHECK: select
|
||||
; CHECK-NOT: select
|
||||
entry:
|
||||
%0 = and i32 %a, 1
|
||||
%1 = and i32 %b, 1
|
||||
%xor = xor i32 %1, %a
|
||||
%shr32 = lshr i32 %a, 1
|
||||
%cmp10 = icmp eq i32 %xor, 1
|
||||
%2 = xor i32 %b, 12345
|
||||
%b.addr.1 = select i1 %cmp10, i32 %2, i32 %b
|
||||
%shr1633 = lshr i32 %b.addr.1, 1
|
||||
%3 = or i32 %shr1633, 54321
|
||||
%b.addr.2 = select i1 %cmp10, i32 %3, i32 %shr1633
|
||||
%shr1634 = lshr i32 %b.addr.2, 2
|
||||
%4 = or i32 %shr1634, 54320
|
||||
%b.addr.3 = select i1 %cmp10, i32 %4, i32 %shr1634
|
||||
ret i32 %b.addr.3
|
||||
}
|
||||
|
||||
; Case where the condition is not only used as condition but also as the
|
||||
; true or false value in at least one of the selects.
|
||||
define i1 @g(i32 %a, i32 %b) {
|
||||
; CHECK: select
|
||||
; CHECK-NOT: select
|
||||
entry:
|
||||
%0 = and i32 %a, 1
|
||||
%1 = and i32 %b, 1
|
||||
%xor = xor i32 %1, %a
|
||||
%shr32 = lshr i32 %a, 1
|
||||
%cmp10 = icmp eq i32 %xor, 1
|
||||
%2 = xor i32 %b, 12345
|
||||
%b.addr.1 = select i1 %cmp10, i32 %2, i32 %b
|
||||
%shr1633 = lshr i32 %b.addr.1, 1
|
||||
%3 = or i32 %shr1633, 54321
|
||||
%b.addr.2 = select i1 %cmp10, i32 %3, i32 %shr1633
|
||||
%shr1634 = lshr i32 %b.addr.2, 2
|
||||
%4 = icmp eq i32 %shr1634, 54320
|
||||
%b.addr.3 = select i1 %cmp10, i1 %4, i1 %cmp10
|
||||
ret i1 %b.addr.3
|
||||
}
|
Loading…
Reference in New Issue