[llvm-commits] [llvm] r92962 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombineCasts.cpp test/Transforms/InstCombine/cast.ll

Chris Lattner sabre at nondot.org
Thu Jan 7 15:41:01 PST 2010


Author: lattner
Date: Thu Jan  7 17:41:00 2010
New Revision: 92962

URL: http://llvm.org/viewvc/llvm-project?rev=92962&view=rev
Log:
Enhance instcombine to reason more strongly about promoting computation
that feeds into a zext, similar to the patch I did yesterday for sext.
There is a lot of room for extension beyond this patch.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/trunk/test/Transforms/InstCombine/cast.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=92962&r1=92961&r2=92962&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Thu Jan  7 17:41:00 2010
@@ -167,7 +167,8 @@
 static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
                                        unsigned CastOpc,
                                        unsigned &NumCastsRemoved) {
-  assert(CastOpc == Instruction::ZExt || CastOpc == Instruction::Trunc);
+  // FIXME: Eliminate CastOpc
+  assert(CastOpc == Instruction::Trunc);
   
   // We can always evaluate constants in another type.
   if (isa<Constant>(V))
@@ -293,6 +294,111 @@
   return false;
 }
 
+/// GetLeadingZeros - Compute the number of known-zero leading bits.
+static unsigned GetLeadingZeros(Value *V, const TargetData *TD) {
+  unsigned Bits = V->getType()->getScalarSizeInBits();
+  APInt KnownZero(Bits, 0), KnownOne(Bits, 0);
+  ComputeMaskedBits(V, APInt::getAllOnesValue(Bits), KnownZero, KnownOne, TD);
+  return KnownZero.countLeadingOnes();
+}
+
+/// CanEvaluateZExtd - Determine if the specified value can be computed in the
+/// specified wider type and produce the same low bits.  If not, return -1.  If
+/// it is possible, return the number of high bits that are known to be zero in
+/// the promoted value.
+static int CanEvaluateZExtd(Value *V, const Type *Ty,unsigned &NumCastsRemoved,
+                            const TargetData *TD) {
+  const Type *OrigTy = V->getType();
+
+  if (isa<Constant>(V)) {
+    unsigned Extended = Ty->getScalarSizeInBits()-OrigTy->getScalarSizeInBits();
+
+    // Constants can always be zero ext'd, even if it requires a ConstantExpr.
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
+      return Extended + CI->getValue().countLeadingZeros();
+    return Extended;
+  }
+  
+  Instruction *I = dyn_cast<Instruction>(V);
+  if (!I) return -1;
+  
+  // If the input is a truncate from the destination type, we can trivially
+  // eliminate it, and this will remove a cast overall.
+  if (isa<TruncInst>(I) && I->getOperand(0)->getType() == 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)) && I->hasOneUse())
+      ++NumCastsRemoved;
+    
+    // Figure out the number of known-zero bits coming in.
+    return GetLeadingZeros(I->getOperand(0), TD);
+  }
+  
+  // We can't extend or shrink something that has multiple uses: doing so would
+  // require duplicating the instruction in general, which isn't profitable.
+  if (!I->hasOneUse()) return -1;
+  
+  int Tmp1, Tmp2;
+  unsigned Opc = I->getOpcode();
+  switch (Opc) {
+  case Instruction::And:
+    Tmp1 = CanEvaluateZExtd(I->getOperand(0), Ty, NumCastsRemoved, TD);
+    if (Tmp1 == -1) return -1;
+    Tmp2 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
+    if (Tmp2 == -1) return -1;
+    return std::max(Tmp1, Tmp2);
+  case Instruction::Or:
+  case Instruction::Xor:
+    Tmp1 = CanEvaluateZExtd(I->getOperand(0), Ty, NumCastsRemoved, TD);
+    if (Tmp1 == -1) return -1;
+    Tmp2 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
+    return std::min(Tmp1, Tmp2);
+
+  case Instruction::Add:
+  case Instruction::Sub:
+  case Instruction::Mul:
+    Tmp1 = CanEvaluateZExtd(I->getOperand(0), Ty, NumCastsRemoved, TD);
+    if (Tmp1 == -1) return -1;
+    Tmp2 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
+    if (Tmp2 == -1) return -1;
+    return 0;
+      
+  //case Instruction::Shl:
+  //case Instruction::LShr:
+  case Instruction::ZExt:
+    // zext(zext(x)) -> zext(x).  Since we're replacing it, it isn't eliminated.
+    Tmp1 = Ty->getScalarSizeInBits()-OrigTy->getScalarSizeInBits();
+    return GetLeadingZeros(I, TD)+Tmp1;
+      
+  //case Instruction::SExt:  zext(sext(x)) -> sext(x) with no upper bits known.
+  //case Instruction::Trunc:
+  case Instruction::Select:
+    Tmp1 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
+    if (Tmp1 == -1) return -1;
+    Tmp2 = CanEvaluateZExtd(I->getOperand(2), Ty, NumCastsRemoved, TD);
+    return std::min(Tmp1, Tmp2);
+      
+  case Instruction::PHI: {
+    // We can change a phi if we can change all operands.  Note that we never
+    // get into trouble with cyclic PHIs here because we only consider
+    // instructions with a single use.
+    PHINode *PN = cast<PHINode>(I);
+    int Result = CanEvaluateZExtd(PN->getIncomingValue(0), Ty,
+                                  NumCastsRemoved, TD);
+    for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) {
+      if (Result == -1) return -1;
+      Tmp1 = CanEvaluateZExtd(PN->getIncomingValue(i), Ty, NumCastsRemoved, TD);
+      Result = std::min(Result, Tmp1);
+    }
+    return Result;
+  }
+  default:
+    // TODO: Can handle more cases here.
+    return -1;
+  }
+}
+
 /// CanEvaluateSExtd - Return true if we can take the specified value
 /// and return it as type Ty without inserting any new casts and without
 /// changing the value of the common low bits.  This is used by code that tries
@@ -585,29 +691,55 @@
   if (!isa<VectorType>(DestTy) && !ShouldChangeType(SrcTy, DestTy))
     return 0;
   
+  uint32_t SrcBitSize = SrcTy->getScalarSizeInBits();
+  uint32_t DestBitSize = DestTy->getScalarSizeInBits();
+      
   // Attempt to propagate the cast into the instruction for int->int casts.
   unsigned NumCastsRemoved = 0;
   switch (CI.getOpcode()) {
   default: assert(0 && "not an integer cast");
-  case Instruction::Trunc:
+  case Instruction::Trunc: {
     if (!CanEvaluateInDifferentType(Src, DestTy,
                                     Instruction::Trunc, NumCastsRemoved))
       return 0;
       
     // If this cast is a truncate, evaluting in a different type always
     // eliminates the cast, so it is always a win.
-    break;
-  case Instruction::ZExt:
-    if (!CanEvaluateInDifferentType(Src, DestTy,
-                                    Instruction::ZExt, NumCastsRemoved))
-      return 0;
-      
+    DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type"
+          " to avoid cast: " << CI);
+    Value *Res = EvaluateInDifferentType(Src, DestTy, false);
+    assert(Res->getType() == DestTy);
+    return ReplaceInstUsesWith(CI, Res);
+  }
+  case Instruction::ZExt: {
+    int BitsZExt = CanEvaluateZExtd(Src, DestTy, NumCastsRemoved, TD);
+    if (BitsZExt == -1) return 0;
+
     // 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 (NumCastsRemoved < 1)
+    // top-part of the computation.  If we know the result will be zero 
+    // extended enough already, we don't need the and.
+    if (NumCastsRemoved < 1 &&
+        unsigned(BitsZExt) < DestBitSize-SrcBitSize)
       return 0;
-    break;
+
+    // Okay, we can transform this!  Insert the new expression now.
+    DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type"
+          " to avoid zero extend: " << CI);
+    Value *Res = EvaluateInDifferentType(Src, DestTy, false);
+    assert(Res->getType() == DestTy);
+
+    // If the high bits are already filled with zeros, just replace this
+    // cast with the result.
+    if (unsigned(BitsZExt) >= DestBitSize-SrcBitSize ||
+        MaskedValueIsZero(Res, APInt::getHighBitsSet(DestBitSize,
+                                                     DestBitSize-SrcBitSize)))
+      return ReplaceInstUsesWith(CI, Res);
+
+    // We need to emit an AND to clear the high bits.
+    Constant *C = ConstantInt::get(CI.getContext(), 
+                             APInt::getLowBitsSet(DestBitSize, SrcBitSize));
+    return BinaryOperator::CreateAnd(Res, C);
+  }
   case Instruction::SExt: {
     // Check to see if we can do this transformation, and if so, how many bits
     // of the promoted expression will be known copies of the sign bit in the
@@ -616,9 +748,6 @@
     if (NumBitsSExt == 0)
       return 0;
 
-    uint32_t SrcBitSize = SrcTy->getScalarSizeInBits();
-    uint32_t DestBitSize = DestTy->getScalarSizeInBits();
-
     // Because this is a sign extension, we can always transform it by inserting
     // two new shifts (to do the extension).  However, this is only profitable
     // if we've eliminated two or more casts from the input.  If we know the
@@ -644,42 +773,6 @@
     return new SExtInst(Builder->CreateTrunc(Res, Src->getType()), DestTy);
   }
   }
-  
-  DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type"
-        " to avoid cast: " << CI);
-  Value *Res = EvaluateInDifferentType(Src, DestTy, false);
-  assert(Res->getType() == DestTy);
-
-  uint32_t SrcBitSize = SrcTy->getScalarSizeInBits();
-  uint32_t DestBitSize = DestTy->getScalarSizeInBits();
-  switch (CI.getOpcode()) {
-  default: assert(0 && "Unknown cast type!");
-  case Instruction::Trunc:
-    // Just replace this cast with the result.
-    return ReplaceInstUsesWith(CI, Res);
-  case Instruction::ZExt: {
-    // If the high bits are already zero, just replace this cast with the
-    // result.
-    APInt Mask(APInt::getBitsSet(DestBitSize, SrcBitSize, DestBitSize));
-    if (MaskedValueIsZero(Res, Mask))
-      return ReplaceInstUsesWith(CI, Res);
-
-    // We need to emit an AND to clear the high bits.
-    Constant *C = ConstantInt::get(CI.getContext(), 
-                             APInt::getLowBitsSet(DestBitSize, SrcBitSize));
-    return BinaryOperator::CreateAnd(Res, C);
-  }
-  case Instruction::SExt: {
-    // If the high bits are already filled with sign bit, just replace this
-    // cast with the result.
-    unsigned NumSignBits = ComputeNumSignBits(Res);
-    if (NumSignBits > (DestBitSize - SrcBitSize))
-      return ReplaceInstUsesWith(CI, Res);
-
-    // We need to emit a cast to truncate, then a cast to sext.
-    return new SExtInst(Builder->CreateTrunc(Res, Src->getType()), DestTy);
-  }
-  }
 }
 
 Instruction *InstCombiner::visitTrunc(TruncInst &CI) {

Modified: llvm/trunk/test/Transforms/InstCombine/cast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=92962&r1=92961&r2=92962&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/cast.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/cast.ll Thu Jan  7 17:41:00 2010
@@ -392,3 +392,14 @@
 ; CHECK-NEXT: %B = add i64 %A, -1
 ; CHECK-NEXT: ret i64 %B
 }
+
+define i64 @test44(i8 %T) {
+ %A = zext i8 %T to i16
+ %B = or i16 %A, 1234
+ %C = zext i16 %B to i64
+ ret i64 %C
+; CHECK: @test44
+; CHECK-NEXT: %A = zext i8 %T to i64
+; CHECK-NEXT: %B = or i64 %A, 1234
+; CHECK-NEXT: ret i64 %B
+}





More information about the llvm-commits mailing list