[JumpThreading] Split select that has constant conditions coming from the PHI node

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 expand the select into a branch structure. This later enables
jump-threading over bb in this pass.

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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257198 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Haicheng Wu 2016-01-08 19:39:39 +00:00
parent 3bd93089a9
commit 1d3fb4f736
2 changed files with 100 additions and 0 deletions

View File

@ -163,6 +163,7 @@ namespace {
bool SimplifyPartiallyRedundantLoad(LoadInst *LI);
bool TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB);
bool TryToUnfoldSelectInCurrBB(BasicBlock *BB);
private:
BasicBlock *SplitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
@ -736,6 +737,9 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
}
}
if (TryToUnfoldSelectInCurrBB(BB))
return true;
// What kind of constant we're looking for.
ConstantPreference Preference = WantInteger;
@ -1903,3 +1907,62 @@ bool JumpThreading::TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB) {
}
return false;
}
/// 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 expand the select into a branch structure. This later enables
/// jump-threading over bb in this pass.
///
/// 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 JumpThreading::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;
// 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 (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 false;
}

View File

@ -250,3 +250,40 @@ if.end: ; preds = %if.then, %cond.end4
; CHECK: br i1 %cmp6, label %if.then, label %if.end
; CHECK: br label %if.end
}
define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
entry:
%add3 = add nsw i32 %j, 2
%cmp.i = icmp slt i32 %u, %v
br i1 %cmp.i, label %.exit, label %cond.false.i
cond.false.i: ; preds = %entry
%cmp4.i = icmp sgt i32 %u, %v
br i1 %cmp4.i, label %.exit, label %cond.false.6.i
cond.false.6.i: ; preds = %cond.false.i
%cmp8.i = icmp slt i32 %w, %x
br i1 %cmp8.i, label %.exit, label %cond.false.10.i
cond.false.10.i: ; preds = %cond.false.6.i
%cmp13.i = icmp sgt i32 %w, %x
br i1 %cmp13.i, label %.exit, label %cond.false.15.i
cond.false.15.i: ; preds = %cond.false.10.i
%phitmp = icmp sge i32 %y, %z
br label %.exit
.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
%cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ]
%j.add3 = select i1 %cond23.i, i32 %j, i32 %add3
ret i32 %j.add3
; CHECK-LABEL: @unfold3
; CHECK: br i1 %cmp.i, label %.exit.thread2, label %cond.false.i
; CHECK: br i1 %cmp4.i, label %.exit.thread, label %cond.false.6.i
; CHECK: br i1 %cmp8.i, label %.exit.thread2, label %cond.false.10.i
; CHECK: br i1 %cmp13.i, label %.exit.thread, label %.exit
; CHECK: br i1 %phitmp, label %.exit.thread, label %.exit.thread2
; CHECK: br label %.exit.thread2
}