diff options
author | Chris Lattner <sabre@nondot.org> | 2008-06-18 04:00:49 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-06-18 04:00:49 +0000 |
commit | 4200c2066782bdd2c6def18cffeaad48210bf05a (patch) | |
tree | 5fa23cda7a9fc5a7b5c5aa8de0db1efef2075866 | |
parent | 651e1440ecdc0ae3e04c44b48aad501c5109563a (diff) | |
download | external_llvm-4200c2066782bdd2c6def18cffeaad48210bf05a.zip external_llvm-4200c2066782bdd2c6def18cffeaad48210bf05a.tar.gz external_llvm-4200c2066782bdd2c6def18cffeaad48210bf05a.tar.bz2 |
make truncate/sext elimination capable of changing phi's. This
implements rdar://6013816 and the testcase in Transforms/InstCombine/sext-misc.ll.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52440 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 40 | ||||
-rw-r--r-- | test/Transforms/InstCombine/sext-misc.ll | 17 |
2 files changed, 50 insertions, 7 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 2338e9c..4af9545 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -6838,6 +6838,16 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI, /// /// This is a truncation operation if Ty is smaller than V->getType(), or an /// extension operation if Ty is larger. +/// +/// If CastOpc is a truncation, then Ty will be a type smaller than V. We +/// should return true if trunc(V) can be computed by computing V in the smaller +/// type. If V is an instruction, then trunc(inst(x,y)) can be computed as +/// inst(trunc(x),trunc(y)), which only makes sense if x and y can be +/// efficiently truncated. +/// +/// If CastOpc is a sext or zext, we are asking if the low bits of the value can +/// bit computed in a larger type, which is then and'd or sext_in_reg'd to get +/// the final result. bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, unsigned CastOpc, int &NumCastsRemoved) { @@ -6858,7 +6868,7 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, // If the first operand is itself a cast, and is eliminable, do not count // this as an eliminable cast. We would prefer to eliminate those two // casts first. - if (!isa<CastInst>(I->getOperand(0))) + if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse()) ++NumCastsRemoved; return true; } @@ -6923,8 +6933,17 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, // of casts in the input. if (I->getOpcode() == CastOpc) return true; - break; + + case Instruction::PHI: { + // We can change a phi if we can change all operands. + PHINode *PN = cast<PHINode>(I); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, CastOpc, + NumCastsRemoved)) + return false; + return true; + } default: // TODO: Can handle more cases here. break; @@ -6957,7 +6976,7 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); Res = BinaryOperator::Create((Instruction::BinaryOps)I->getOpcode(), - LHS, RHS, I->getName()); + LHS, RHS); break; } case Instruction::Trunc: @@ -6969,16 +6988,27 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, if (I->getOperand(0)->getType() == Ty) return I->getOperand(0); - // Otherwise, must be the same type of case, so just reinsert a new one. + // Otherwise, must be the same type of cast, so just reinsert a new one. Res = CastInst::Create(cast<CastInst>(I)->getOpcode(), I->getOperand(0), - Ty, I->getName()); + Ty); break; + case Instruction::PHI: { + PHINode *OPN = cast<PHINode>(I); + PHINode *NPN = PHINode::Create(Ty); + for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { + Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, isSigned); + NPN->addIncoming(V, OPN->getIncomingBlock(i)); + } + Res = NPN; + break; + } default: // TODO: Can handle more cases here. assert(0 && "Unreachable!"); break; } + Res->takeName(I); return InsertNewInstBefore(Res, *I); } diff --git a/test/Transforms/InstCombine/sext-misc.ll b/test/Transforms/InstCombine/sext-misc.ll index 076f595..6985002 100644 --- a/test/Transforms/InstCombine/sext-misc.ll +++ b/test/Transforms/InstCombine/sext-misc.ll @@ -1,6 +1,4 @@ ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sext -; RUN: llvm-as < %s | llc -march=x86-64 | not grep movslq -; RUN: llvm-as < %s | llc -march=x86 | not grep sar declare i32 @llvm.ctpop.i32(i32) declare i32 @llvm.ctlz.i32(i32) @@ -50,3 +48,18 @@ define i32 @woo(i8 %a, i32 %f, i1 %p, i32* %z) { %n = sext i16 %s to i32 ret i32 %n } + +; rdar://6013816 +define i16 @test(i16 %t, i1 %cond) nounwind { +entry: + br i1 %cond, label %T, label %F +T: + %t2 = sext i16 %t to i32 + br label %F + +F: + %V = phi i32 [%t2, %T], [42, %entry] + %W = trunc i32 %V to i16 + ret i16 %W +} + |