forked from OSchip/llvm-project
Implement PR1777 by detecting dependent phis that
all compute the same value. llvm-svn: 43777
This commit is contained in:
parent
dd71a5c37b
commit
d8515f8e80
|
@ -8551,6 +8551,34 @@ static bool DeadPHICycle(PHINode *PN,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// PHIsEqualValue - Return true if this phi node is always equal to
|
||||
/// NonPhiInVal. This happens with mutually cyclic phi nodes like:
|
||||
/// z = some value; x = phi (y, z); y = phi (x, z)
|
||||
static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal,
|
||||
SmallPtrSet<PHINode*, 16> &ValueEqualPHIs) {
|
||||
// See if we already saw this PHI node.
|
||||
if (!ValueEqualPHIs.insert(PN))
|
||||
return true;
|
||||
|
||||
// Don't scan crazily complex things.
|
||||
if (ValueEqualPHIs.size() == 16)
|
||||
return false;
|
||||
|
||||
// Scan the operands to see if they are either phi nodes or are equal to
|
||||
// the value.
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||
Value *Op = PN->getIncomingValue(i);
|
||||
if (PHINode *OpPN = dyn_cast<PHINode>(Op)) {
|
||||
if (!PHIsEqualValue(OpPN, NonPhiInVal, ValueEqualPHIs))
|
||||
return false;
|
||||
} else if (Op != NonPhiInVal)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// PHINode simplification
|
||||
//
|
||||
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
|
||||
|
@ -8592,6 +8620,40 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
|
|||
}
|
||||
}
|
||||
|
||||
// We sometimes end up with phi cycles that non-obviously end up being the
|
||||
// same value, for example:
|
||||
// z = some value; x = phi (y, z); y = phi (x, z)
|
||||
// where the phi nodes don't necessarily need to be in the same block. Do a
|
||||
// quick check to see if the PHI node only contains a single non-phi value, if
|
||||
// so, scan to see if the phi cycle is actually equal to that value.
|
||||
{
|
||||
unsigned InValNo = 0, NumOperandVals = PN.getNumIncomingValues();
|
||||
// Scan for the first non-phi operand.
|
||||
while (InValNo != NumOperandVals &&
|
||||
isa<PHINode>(PN.getIncomingValue(InValNo)))
|
||||
++InValNo;
|
||||
|
||||
if (InValNo != NumOperandVals) {
|
||||
Value *NonPhiInVal = PN.getOperand(InValNo);
|
||||
|
||||
// Scan the rest of the operands to see if there are any conflicts, if so
|
||||
// there is no need to recursively scan other phis.
|
||||
for (++InValNo; InValNo != NumOperandVals; ++InValNo) {
|
||||
Value *OpVal = PN.getIncomingValue(InValNo);
|
||||
if (OpVal != NonPhiInVal && !isa<PHINode>(OpVal))
|
||||
break;
|
||||
}
|
||||
|
||||
// If we scanned over all operands, then we have one unique value plus
|
||||
// phi values. Scan PHI nodes to see if they all merge in each other or
|
||||
// the value.
|
||||
if (InValNo == NumOperandVals) {
|
||||
SmallPtrSet<PHINode*, 16> ValueEqualPHIs;
|
||||
if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs))
|
||||
return ReplaceInstUsesWith(PN, NonPhiInVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep {phi i32}
|
||||
; PR1777
|
||||
|
||||
declare i1 @rrr()
|
||||
|
||||
define i1 @zxcv() {
|
||||
entry:
|
||||
%a = alloca i32
|
||||
%i = ptrtoint i32* %a to i32
|
||||
%b = call i1 @rrr()
|
||||
br i1 %b, label %one, label %two
|
||||
|
||||
one:
|
||||
%x = phi i32 [%i, %entry], [%y, %two]
|
||||
%c = call i1 @rrr()
|
||||
br i1 %c, label %two, label %end
|
||||
|
||||
two:
|
||||
%y = phi i32 [%i, %entry], [%x, %one]
|
||||
%d = call i1 @rrr()
|
||||
br i1 %d, label %one, label %end
|
||||
|
||||
end:
|
||||
%f = phi i32 [ %x, %one], [%y, %two]
|
||||
; Change the %f to %i, and the optimizer suddenly becomes a lot smarter
|
||||
; even though %f must equal %i at this point
|
||||
%g = inttoptr i32 %f to i32*
|
||||
store i32 10, i32* %g
|
||||
%z = call i1 @rrr()
|
||||
ret i1 %z
|
||||
}
|
Loading…
Reference in New Issue