aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-01-15 17:01:23 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-01-15 17:01:23 +0000
commitf35fd547ac2de1146707a8683e725d6e15a0538a (patch)
tree4cd7326b4acaa4084a9489388bf7dee16df2a160
parente9530ecae4897fe8157bd4d7616043bd8c0484e2 (diff)
downloadexternal_llvm-f35fd547ac2de1146707a8683e725d6e15a0538a.zip
external_llvm-f35fd547ac2de1146707a8683e725d6e15a0538a.tar.gz
external_llvm-f35fd547ac2de1146707a8683e725d6e15a0538a.tar.bz2
- Teach CanEvaluateInDifferentType of this xform: sext (zext ty1), ty2 -> zext ty2
- Looking at the number of sign bits of the a sext instruction to determine whether new trunc + sext pair should be added when its source is being evaluated in a different type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62263 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp73
-rw-r--r--test/Transforms/InstCombine/cast-sext-zext.ll11
2 files changed, 62 insertions, 22 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index f640915..d6419d6 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -395,7 +395,7 @@ namespace {
bool CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
unsigned CastOpc,
- int &NumCastsRemoved);
+ int &NumCastsRemoved, bool &SeenTrunc);
unsigned GetOrEnforceKnownAlignment(Value *V,
unsigned PrefAlign = 0);
@@ -7497,9 +7497,10 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
/// 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) {
+bool
+InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
+ unsigned CastOpc,
+ int &NumCastsRemoved, bool &SeenTrunc){
// We can always evaluate constants in another type.
if (isa<ConstantInt>(V))
return true;
@@ -7519,6 +7520,8 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
// casts first.
if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse())
++NumCastsRemoved;
+ if (isa<TruncInst>(I))
+ SeenTrunc = true;
return true;
}
}
@@ -7527,7 +7530,8 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
// require duplicating the instruction in general, which isn't profitable.
if (!I->hasOneUse()) return false;
- switch (I->getOpcode()) {
+ unsigned Opc = I->getOpcode();
+ switch (Opc) {
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
@@ -7536,9 +7540,9 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
case Instruction::Xor:
// These operators can all arbitrarily be extended or truncated.
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
- NumCastsRemoved) &&
+ NumCastsRemoved, SeenTrunc) &&
CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
- NumCastsRemoved);
+ NumCastsRemoved, SeenTrunc);
case Instruction::Shl:
// If we are truncating the result of this SHL, and if it's a shift of a
@@ -7548,7 +7552,7 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
if (BitWidth < OrigTy->getBitWidth() &&
CI->getLimitedValue(BitWidth) < BitWidth)
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
- NumCastsRemoved);
+ NumCastsRemoved, SeenTrunc);
}
break;
case Instruction::LShr:
@@ -7563,7 +7567,7 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) &&
CI->getLimitedValue(BitWidth) < BitWidth) {
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
- NumCastsRemoved);
+ NumCastsRemoved, SeenTrunc);
}
}
break;
@@ -7573,22 +7577,27 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
// If this is the same kind of case as our original (e.g. zext+zext), we
// can safely replace it. Note that replacing it does not reduce the number
// of casts in the input.
- if (I->getOpcode() == CastOpc)
+ if (Opc == CastOpc)
+ return true;
+
+ // sext (zext ty1), ty2 -> zext ty2
+ if (CastOpc == Instruction::SExt && Opc == Instruction::ZExt &&
+ I->hasOneUse())
return true;
break;
case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(I);
return CanEvaluateInDifferentType(SI->getTrueValue(), Ty, CastOpc,
- NumCastsRemoved) &&
+ NumCastsRemoved, SeenTrunc) &&
CanEvaluateInDifferentType(SI->getFalseValue(), Ty, CastOpc,
- NumCastsRemoved);
+ NumCastsRemoved, SeenTrunc);
}
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))
+ NumCastsRemoved, SeenTrunc))
return false;
return true;
}
@@ -7611,7 +7620,8 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
// Otherwise, it must be an instruction.
Instruction *I = cast<Instruction>(V);
Instruction *Res = 0;
- switch (I->getOpcode()) {
+ unsigned Opc = I->getOpcode();
+ switch (Opc) {
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
@@ -7623,8 +7633,7 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
case Instruction::Shl: {
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);
+ Res = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
break;
}
case Instruction::Trunc:
@@ -7808,7 +7817,6 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) {
}
-
/// Only the TRUNC, ZEXT, SEXT, and BITCAST can both operand and result as
/// integer types. This function implements the common transforms for all those
/// cases.
@@ -7838,16 +7846,18 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
// Attempt to propagate the cast into the instruction for int->int casts.
int NumCastsRemoved = 0;
+ bool SeenTrunc = false;
if (!isa<BitCastInst>(CI) &&
CanEvaluateInDifferentType(SrcI, cast<IntegerType>(DestTy),
- CI.getOpcode(), NumCastsRemoved)) {
+ CI.getOpcode(), NumCastsRemoved, SeenTrunc)) {
// If this cast is a truncate, evaluting in a different type always
// eliminates the cast, so it is always a win. If this is a zero-extension,
// we need to do an AND to maintain the clear top-part of the computation,
// so we require that the input have eliminated at least one cast. If this
// is a sign extension, we insert two new casts (to do the extension) so we
// require that two casts have been eliminated.
- bool DoXForm;
+ bool DoXForm = false;
+ bool JustReplace = false;
switch (CI.getOpcode()) {
default:
// All the others use floating point so we shouldn't actually
@@ -7858,11 +7868,28 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
break;
case Instruction::ZExt:
DoXForm = NumCastsRemoved >= 1;
+ // TODO: Check if we need to insert an AND.
break;
- case Instruction::SExt:
+ case Instruction::SExt: {
DoXForm = NumCastsRemoved >= 2;
+ if (!SeenTrunc) {
+ // Do we have to emit a truncate to SrcBitSize followed by a sext?
+ //
+ // It's not safe to eliminate the trunc + sext pair if one of the
+ // eliminated cast is a truncate. e.g.
+ // t2 = trunc i32 t1 to i16
+ // t3 = sext i16 t2 to i32
+ // !=
+ // i32 t1
+ unsigned NumSignBits = ComputeNumSignBits(&CI);
+ if (NumSignBits > (DestBitSize - SrcBitSize)) {
+ DoXForm = true;
+ JustReplace = true;
+ }
+ }
break;
}
+ }
if (DoXForm) {
Value *Res = EvaluateInDifferentType(SrcI, DestTy,
@@ -7882,6 +7909,10 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
return BinaryOperator::CreateAnd(Res, C);
}
case Instruction::SExt:
+ if (JustReplace)
+ // Just replace this cast with the result.
+ return ReplaceInstUsesWith(CI, Res);
+
// We need to emit a cast to truncate, then a cast to sext.
return CastInst::Create(Instruction::SExt,
InsertCastBefore(Instruction::Trunc, Res, Src->getType(),
@@ -12420,5 +12451,3 @@ bool InstCombiner::runOnFunction(Function &F) {
FunctionPass *llvm::createInstructionCombiningPass() {
return new InstCombiner();
}
-
-
diff --git a/test/Transforms/InstCombine/cast-sext-zext.ll b/test/Transforms/InstCombine/cast-sext-zext.ll
new file mode 100644
index 0000000..da5e7fa
--- /dev/null
+++ b/test/Transforms/InstCombine/cast-sext-zext.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sext
+
+define zeroext i16 @t(i8 zeroext %on_off, i16* nocapture %puls) nounwind readonly {
+entry:
+ %0 = zext i8 %on_off to i32
+ %1 = add i32 %0, -1
+ %2 = sext i32 %1 to i64
+ %3 = getelementptr i16* %puls, i64 %2
+ %4 = load i16* %3, align 2
+ ret i16 %4
+}