implement PR4895, by making FoldOpIntoPhi handle select conditions

that are phi nodes.  Also tighten up FoldOpIntoPhi to treat constantexpr
operands to phis just like other variables, avoiding moving constantexpr
computations around.

Patch by Daniel Dunbar.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82913 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-09-27 19:57:57 +00:00
parent cec545097c
commit 5d1704ddbf
2 changed files with 64 additions and 11 deletions

View File

@ -384,9 +384,10 @@ namespace {
Value *SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
APInt& UndefElts, unsigned Depth = 0);
// FoldOpIntoPhi - Given a binary operator or cast instruction which has a
// PHI node as operand #0, see if we can fold the instruction into the PHI
// (which is only possible if all operands to the PHI are constants).
// FoldOpIntoPhi - Given a binary operator, cast instruction, or select
// which has a PHI node as operand #0, see if we can fold the instruction
// into the PHI (which is only possible if all operands to the PHI are
// constants).
Instruction *FoldOpIntoPhi(Instruction &I);
// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
@ -1938,20 +1939,23 @@ static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
}
/// FoldOpIntoPhi - Given a binary operator or cast instruction which has a PHI
/// node as operand #0, see if we can fold the instruction into the PHI (which
/// is only possible if all operands to the PHI are constants).
/// FoldOpIntoPhi - Given a binary operator, cast instruction, or select which
/// has a PHI node as operand #0, see if we can fold the instruction into the
/// PHI (which is only possible if all operands to the PHI are constants).
Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
PHINode *PN = cast<PHINode>(I.getOperand(0));
unsigned NumPHIValues = PN->getNumIncomingValues();
if (!PN->hasOneUse() || NumPHIValues == 0) return 0;
// Check to see if all of the operands of the PHI are constants. If there is
// one non-constant value, remember the BB it is. If there is more than one
// or if *it* is a PHI, bail out.
// Check to see if all of the operands of the PHI are simple constants
// (constantint/constantfp/undef). If there is one non-constant value,
// remember the BB it is. If there is more than one or if *it* is a PHI, bail
// out. We don't do arbitrary constant expressions here because moving their
// computation can be expensive without a cost model.
BasicBlock *NonConstBB = 0;
for (unsigned i = 0; i != NumPHIValues; ++i)
if (!isa<Constant>(PN->getIncomingValue(i))) {
if (!isa<Constant>(PN->getIncomingValue(i)) ||
isa<ConstantExpr>(PN->getIncomingValue(i))) {
if (NonConstBB) return 0; // More than one non-const value.
if (isa<PHINode>(PN->getIncomingValue(i))) return 0; // Itself a phi.
NonConstBB = PN->getIncomingBlock(i);
@ -1978,7 +1982,26 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
NewPN->takeName(PN);
// Next, add all of the operands to the PHI.
if (I.getNumOperands() == 2) {
if (SelectInst *SI = dyn_cast<SelectInst>(&I)) {
// We only currently try to fold the condition of a select when it is a phi,
// not the true/false values.
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV = 0;
if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i))) {
if (InC->isNullValue())
InV = SI->getFalseValue();
else
InV = SI->getTrueValue();
} else {
assert(PN->getIncomingBlock(i) == NonConstBB);
InV = SelectInst::Create(PN->getIncomingValue(i),
SI->getTrueValue(), SI->getFalseValue(),
"phitmp", NonConstBB->getTerminator());
Worklist.Add(cast<Instruction>(InV));
}
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
} else if (I.getNumOperands() == 2) {
Constant *C = cast<Constant>(I.getOperand(1));
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV = 0;
@ -9422,6 +9445,14 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
return FoldI;
}
// See if we can fold the select into a phi node. The true/false values have
// to be live in the predecessor blocks.
if (isa<PHINode>(SI.getCondition()) &&
isa<Constant>(SI.getTrueValue()) &&
isa<Constant>(SI.getFalseValue()))
if (Instruction *NV = FoldOpIntoPhi(SI))
return NV;
if (BinaryOperator::isNot(CondVal)) {
SI.setOperand(0, BinaryOperator::getNotArgument(CondVal));
SI.setOperand(1, FalseVal);

View File

@ -202,3 +202,25 @@ define i1 @test24(i1 %a, i1 %b) {
ret i1 %c
}
define i32 @test25() {
entry:
br i1 false, label %jump, label %ret
jump:
br label %ret
ret:
%a = phi i1 [true, %jump], [false, %entry]
%b = select i1 %a, i32 10, i32 20
ret i32 %b
}
define i32 @test26() {
entry:
br i1 false, label %jump, label %ret
jump:
%c = or i1 false, false
br label %ret
ret:
%a = phi i1 [true, %jump], [%c, %entry]
%b = select i1 %a, i32 10, i32 20
ret i32 %b
}