[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Feb 23 00:39:05 PST 2004


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.159 -> 1.160

---
Log message:

Refactor some code.  In the mul - setcc folding case, we really care about 
whether this is the sign bit or not, so check unsigned comparisons as well.


---
Diffs of the changes:  (+63 -32)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.159 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.160
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.159	Mon Feb 23 00:00:11 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Mon Feb 23 00:38:22 2004
@@ -116,12 +116,13 @@
     // InsertNewInstBefore - insert an instruction New before instruction Old
     // in the program.  Add the new instruction to the worklist.
     //
-    void InsertNewInstBefore(Instruction *New, Instruction &Old) {
+    Value *InsertNewInstBefore(Instruction *New, Instruction &Old) {
       assert(New && New->getParent() == 0 &&
              "New instruction already inserted into a basic block!");
       BasicBlock *BB = Old.getParent();
       BB->getInstList().insert(&Old, New);  // Insert inst
       WorkList.push_back(New);              // Add to worklist
+      return New;
     }
 
   public:
@@ -173,6 +174,31 @@
   return V->hasOneUse() || isa<Constant>(V);
 }
 
+// getSignedIntegralType - Given an unsigned integral type, return the signed
+// version of it that has the same size.
+static const Type *getSignedIntegralType(const Type *Ty) {
+  switch (Ty->getPrimitiveID()) {
+  default: assert(0 && "Invalid unsigned integer type!"); abort();
+  case Type::UByteTyID:  return Type::SByteTy;
+  case Type::UShortTyID: return Type::ShortTy;
+  case Type::UIntTyID:   return Type::IntTy;
+  case Type::ULongTyID:  return Type::LongTy;
+  }
+}
+
+// getPromotedType - Return the specified type promoted as it would be to pass
+// though a va_arg area...
+static const Type *getPromotedType(const Type *Ty) {
+  switch (Ty->getPrimitiveID()) {
+  case Type::SByteTyID:
+  case Type::ShortTyID:  return Type::IntTy;
+  case Type::UByteTyID:
+  case Type::UShortTyID: return Type::UIntTy;
+  case Type::FloatTyID:  return Type::DoubleTy;
+  default:               return Ty;
+  }
+}
+
 // SimplifyCommutative - This performs a few simplifications for commutative
 // operators:
 //
@@ -557,6 +583,26 @@
   return 0;
 }
 
+/// isSignBitCheck - Given an exploded setcc instruction, return true if it is
+/// really just returns true if the most significant (sign) bit is set.
+static bool isSignBitCheck(unsigned Opcode, Value *LHS, ConstantInt *RHS) {
+  if (RHS->getType()->isSigned()) {
+    // True if source is LHS < 0 or LHS <= -1
+    return Opcode == Instruction::SetLT && RHS->isNullValue() ||
+           Opcode == Instruction::SetLE && RHS->isAllOnesValue();
+  } else {
+    ConstantUInt *RHSC = cast<ConstantUInt>(RHS);
+    // True if source is LHS > 127 or LHS >= 128, where the constants depend on
+    // the size of the integer type.
+    if (Opcode == Instruction::SetGE)
+      return RHSC->getValue() == 1ULL<<(RHS->getType()->getPrimitiveSize()*8-1);
+    if (Opcode == Instruction::SetGT)
+      return RHSC->getValue() ==
+        (1ULL << (RHS->getType()->getPrimitiveSize()*8-1))-1;
+  }
+  return false;
+}
+
 Instruction *InstCombiner::visitMul(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
   Value *Op0 = I.getOperand(0);
@@ -616,23 +662,28 @@
       Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1);
       const Type *SCOpTy = SCIOp0->getType();
 
-      // If the source is X < 0 or X <= -1, and X is a signed integer type,
-      // convert this multiply into a shift/and combination.
-      if (SCOpTy->isSigned() && isa<ConstantInt>(SCIOp1) &&
-          ((SCI->getOpcode() == Instruction::SetLT &&
-            cast<Constant>(SCIOp1)->isNullValue()) ||
-           (SCI->getOpcode() == Instruction::SetLE &&
-            cast<ConstantInt>(SCIOp1)->isAllOnesValue()))) {
+      // If the setcc is true iff the sign bit of X is set, then convert this
+      // multiply into a shift/and combination.
+      if (isa<ConstantInt>(SCIOp1) &&
+          isSignBitCheck(SCI->getOpcode(), SCIOp0, cast<ConstantInt>(SCIOp1))) {
         // Shift the X value right to turn it into "all signbits".
         Constant *Amt = ConstantUInt::get(Type::UByteTy,
                                           SCOpTy->getPrimitiveSize()*8-1);
-        Value *V = new ShiftInst(Instruction::Shr, SCIOp0, Amt,
-                                 BoolCast->getName()+".mask", &I);
+        if (SCIOp0->getType()->isUnsigned()) {
+          const Type *NewTy = getSignedIntegralType(SCIOp0->getType());
+          SCIOp0 = InsertNewInstBefore(new CastInst(SCIOp0, NewTy,
+                                                    SCIOp0->getName()), I);
+        }
+
+        Value *V =
+          InsertNewInstBefore(new ShiftInst(Instruction::Shr, SCIOp0, Amt,
+                                            BoolCast->getOperand(0)->getName()+
+                                            ".mask"), I);
 
         // If the multiply type is not the same as the source type, sign extend
         // or truncate to the multiply type.
         if (I.getType() != V->getType())
-          V = new CastInst(V, I.getType(), V->getName(), &I);
+          V = InsertNewInstBefore(new CastInst(V, I.getType(), V->getName()),I);
         
         Value *OtherOp = Op0 == BoolCast ? I.getOperand(1) : Op0;
         return BinaryOperator::create(Instruction::And, V, OtherOp);
@@ -1314,14 +1365,7 @@
               Value *X = BO->getOperand(0);
               // If 'X' is not signed, insert a cast now...
               if (!BOC->getType()->isSigned()) {
-                const Type *DestTy;
-                switch (BOC->getType()->getPrimitiveID()) {
-                case Type::UByteTyID:  DestTy = Type::SByteTy; break;
-                case Type::UShortTyID: DestTy = Type::ShortTy; break;
-                case Type::UIntTyID:   DestTy = Type::IntTy;   break;
-                case Type::ULongTyID:  DestTy = Type::LongTy;  break;
-                default: assert(0 && "Invalid unsigned integer type!"); abort();
-                }
+                const Type *DestTy = getSignedIntegralType(BOC->getType());
                 CastInst *NewCI = new CastInst(X,DestTy,X->getName()+".signed");
                 InsertNewInstBefore(NewCI, I);
                 X = NewCI;
@@ -1827,19 +1871,6 @@
 //
 Instruction *InstCombiner::visitInvokeInst(InvokeInst &II) {
   return visitCallSite(&II);
-}
-
-// getPromotedType - Return the specified type promoted as it would be to pass
-// though a va_arg area...
-static const Type *getPromotedType(const Type *Ty) {
-  switch (Ty->getPrimitiveID()) {
-  case Type::SByteTyID:
-  case Type::ShortTyID:  return Type::IntTy;
-  case Type::UByteTyID:
-  case Type::UShortTyID: return Type::UIntTy;
-  case Type::FloatTyID:  return Type::DoubleTy;
-  default:               return Ty;
-  }
 }
 
 // visitCallSite - Improvements for call and invoke instructions.





More information about the llvm-commits mailing list