summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp53
-rw-r--r--test/Transforms/InstCombine/select.ll22
2 files changed, 64 insertions, 11 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 8d61fce4b4..be88d299de 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -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);
diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll
index 22fe57f237..fc4b82002d 100644
--- a/test/Transforms/InstCombine/select.ll
+++ b/test/Transforms/InstCombine/select.ll
@@ -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
+}