[llvm-commits] [llvm] r62263 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/cast-sext-zext.ll

Evan Cheng evan.cheng at apple.com
Thu Jan 15 09:01:23 PST 2009


Author: evancheng
Date: Thu Jan 15 11:01:23 2009
New Revision: 62263

URL: http://llvm.org/viewvc/llvm-project?rev=62263&view=rev
Log:
- 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.

Added:
    llvm/trunk/test/Transforms/InstCombine/cast-sext-zext.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=62263&r1=62262&r2=62263&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jan 15 11:01:23 2009
@@ -395,7 +395,7 @@
 
     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 @@
 /// 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 @@
       // casts first.
       if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse())
         ++NumCastsRemoved;
+      if (isa<TruncInst>(I))
+        SeenTrunc = true;
       return true;
     }
   }
@@ -7527,7 +7530,8 @@
   // 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 @@
   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 @@
       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 @@
             APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) &&
           CI->getLimitedValue(BitWidth) < BitWidth) {
         return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
-                                          NumCastsRemoved);
+                                          NumCastsRemoved, SeenTrunc);
       }
     }
     break;
@@ -7573,22 +7577,27 @@
     // 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 @@
   // 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 @@
   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 @@
 }
 
 
-
 /// 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 @@
 
   // 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 @@
       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 @@
         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 @@
 FunctionPass *llvm::createInstructionCombiningPass() {
   return new InstCombiner();
 }
-
-

Added: llvm/trunk/test/Transforms/InstCombine/cast-sext-zext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast-sext-zext.ll?rev=62263&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/cast-sext-zext.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/cast-sext-zext.ll Thu Jan 15 11:01:23 2009
@@ -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
+}





More information about the llvm-commits mailing list