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

Reid Spencer reid at x10sys.com
Sat Oct 21 18:37:08 PDT 2006



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.520.2.4 -> 1.520.2.5
---
Log message:

Fixes to get the DIV -> S/UDIV change working. This now passes MultiSource.


---
Diffs of the changes:  (+157 -53)

 InstructionCombining.cpp |  210 +++++++++++++++++++++++++++++++++++------------
 1 files changed, 157 insertions(+), 53 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.4 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.5
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.4	Sat Oct 21 03:59:42 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sat Oct 21 20:36:52 2006
@@ -131,7 +131,8 @@
     Instruction *visitAdd(BinaryOperator &I);
     Instruction *visitSub(BinaryOperator &I);
     Instruction *visitMul(BinaryOperator &I);
-    Instruction *visitDiv(BinaryOperator &I);
+    Instruction *visitUDiv(BinaryOperator &I);
+    Instruction *visitSDiv(BinaryOperator &I);
     Instruction *visitRem(BinaryOperator &I);
     Instruction *visitAnd(BinaryOperator &I);
     Instruction *visitOr (BinaryOperator &I);
@@ -1822,7 +1823,9 @@
         return R;
   }
 
-  // add (cast *A to intptrtype) B -> cast (GEP (cast *A to sbyte*) B) -> intptrtype
+  // add (cast *A to intptrtype) B -> 
+  //   cast (GEP (cast *A to sbyte*) B) -> 
+  //     intptrtype
   {
     CastInst* CI = dyn_cast<CastInst>(LHS);
     Value* Other = RHS;
@@ -1975,7 +1978,8 @@
       }
 
       // 0 - (X sdiv C)  -> (X sdiv -C)
-      if (Op1I->getOpcode() == Instruction::SDiv)
+      if (Op1I->getOpcode() == Instruction::SDiv || 
+          Op1I->getOpcode() == Instruction::UDiv)
         if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
           if (CSI->isNullValue() && CSI->getType()->isSigned())
             if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
@@ -2156,7 +2160,7 @@
   return Changed ? &I : 0;
 }
 
-Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
+Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
 
   if (isa<UndefValue>(Op0))              // undef / X -> 0
@@ -2164,6 +2168,7 @@
   if (isa<UndefValue>(Op1))
     return ReplaceInstUsesWith(I, Op1);  // X / undef -> undef
 
+  // If right hand side is a constant intger ..
   if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
     // div X, 1 == X
     if (RHS->equalsInt(1))
@@ -2180,26 +2185,22 @@
         if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
           return BinaryOperator::create(
             Instruction::BinaryOps(LHS->getOpcode()), LHS->getOperand(0),
-                                          ConstantExpr::getMul(RHS, LHSRHS),"");
+                                          ConstantExpr::getMul(RHS, LHSRHS));
         }
 
     // Check to see if this is an unsigned division with an exact power of 2,
     // if so, convert to a right shift.
+    // X udiv C^2 -> X >> C
     if (ConstantInt *C = dyn_cast<ConstantInt>(RHS)) 
-      if (C->getType()->isUnsigned())
-        if (uint64_t Val = C->getZExtValue())    // Don't break X / 0
-          if (isPowerOf2_64(Val)) {
-            uint64_t C = Log2_64(Val);
-            return new ShiftInst(Instruction::Shr, Op0,
-                                 ConstantInt::get(Type::UByteTy, C));
-          }
-
-    // -X/C -> X/-C
-    if (RHS->getType()->isSigned())
-      if (Value *LHSNeg = dyn_castNegVal(Op0))
-        return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+      if (uint64_t Val = C->getZExtValue())    // Don't break X / 0
+        if (isPowerOf2_64(Val)) {
+          uint64_t C = Log2_64(Val);
+          return new ShiftInst(Instruction::Shr, Op0,
+                               ConstantInt::get(Type::UByteTy, C));
+        }
 
-    if (!RHS->isNullValue()) {
+  
+    if (!RHS->isNullValue()) { // avoid X udiv 0
       if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
         if (Instruction *R = FoldOpIntoSelect(I, SI, this))
           return R;
@@ -2268,41 +2269,22 @@
     if (LHS->equalsInt(0))
       return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
 
-  if (I.getType()->isSigned()) {
-    // If the sign bits of both operands are zero (i.e. we can prove they are
-    // unsigned inputs), turn this into a udiv.
-    uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
-    if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
-      const Type *NTy = Op0->getType()->getUnsignedVersion();
-      Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
-      InsertNewInstBefore(LHS, I);
-      Value *RHS;
-      if (Constant *R = dyn_cast<Constant>(Op1))
-        RHS = ConstantExpr::getCast(R, NTy);
-      else
-        RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
-      Instruction *Div = BinaryOperator::createUDiv(LHS, RHS, I.getName());
-      InsertNewInstBefore(Div, I);
-      return new CastInst(Div, I.getType());
-    }      
-  } else {
-    // Known to be an unsigned division.
-    if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
-      // Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
-      if (RHSI->getOpcode() == Instruction::Shl &&
-          isa<ConstantInt>(RHSI->getOperand(0)) &&
-          RHSI->getOperand(0)->getType()->isUnsigned()) {
-        uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
-        if (isPowerOf2_64(C1)) {
-          uint64_t C2 = Log2_64(C1);
-          Value *Add = RHSI->getOperand(1);
-          if (C2) {
-            Constant *C2V = ConstantInt::get(Add->getType(), C2);
-            Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
-                                                                "tmp"), I);
-          }
-          return new ShiftInst(Instruction::Shr, Op0, Add);
+  // Known to be an unsigned division.
+  if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
+    // Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
+    if (RHSI->getOpcode() == Instruction::Shl &&
+        isa<ConstantInt>(RHSI->getOperand(0)) &&
+        RHSI->getOperand(0)->getType()->isUnsigned()) {
+      uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
+      if (isPowerOf2_64(C1)) {
+        uint64_t C2 = Log2_64(C1);
+        Value *Add = RHSI->getOperand(1);
+        if (C2) {
+          Constant *C2V = ConstantInt::get(Add->getType(), C2);
+          Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
+                                                              "tmp"), I);
         }
+        return new ShiftInst(Instruction::Shr, Op0, Add);
       }
     }
   }
@@ -2310,6 +2292,128 @@
   return 0;
 }
 
+Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  if (isa<UndefValue>(Op0))              // undef / X -> 0
+    return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+  if (isa<UndefValue>(Op1))
+    return ReplaceInstUsesWith(I, Op1);  // X / undef -> undef
+
+  if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+    // div X, 1 == X
+    if (RHS->equalsInt(1))
+      return ReplaceInstUsesWith(I, Op0);
+
+    // div X, -1 == -X
+    if (RHS->isAllOnesValue())
+      return BinaryOperator::createNeg(Op0);
+
+    // (X / C1) / C2  -> X / (C1*C2)
+    if (Instruction *LHS = dyn_cast<Instruction>(Op0))
+      if (LHS->getOpcode() == Instruction::SDiv || 
+          LHS->getOpcode()==Instruction::UDiv)
+        if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
+          return BinaryOperator::create(
+            Instruction::BinaryOps(LHS->getOpcode()), LHS->getOperand(0),
+                                          ConstantExpr::getMul(RHS, LHSRHS));
+        }
+
+    // -X/C -> X/-C
+    if (Value *LHSNeg = dyn_castNegVal(Op0))
+      return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+
+    if (!RHS->isNullValue()) {
+      if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+        if (Instruction *R = FoldOpIntoSelect(I, SI, this))
+          return R;
+      if (isa<PHINode>(Op0))
+        if (Instruction *NV = FoldOpIntoPhi(I))
+          return NV;
+    }
+  }
+
+  // Handle div X, Cond?Y:Z
+  if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+    // div X, (Cond ? 0 : Y) -> div X, Y.  If the div and the select are in the
+    // same basic block, then we replace the select with Y, and the condition of
+    // the select with false (if the cond value is in the same BB).  If the
+    // select has uses other than the div, this allows them to be simplified
+    // also.
+    if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
+      if (ST->isNullValue()) {
+        Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+        if (CondI && CondI->getParent() == I.getParent())
+          UpdateValueUsesWith(CondI, ConstantBool::getFalse());
+        else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+          I.setOperand(1, SI->getOperand(2));
+        else
+          UpdateValueUsesWith(SI, SI->getOperand(2));
+        return &I;
+      }
+    // Likewise for: div X, (Cond ? Y : 0) -> div X, Y
+    if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
+      if (ST->isNullValue()) {
+        Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+        if (CondI && CondI->getParent() == I.getParent())
+          UpdateValueUsesWith(CondI, ConstantBool::getTrue());
+        else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+          I.setOperand(1, SI->getOperand(1));
+        else
+          UpdateValueUsesWith(SI, SI->getOperand(1));
+        return &I;
+      }
+
+    // If this is 'udiv X, (Cond ? C1, C2)' where C1&C2 are powers of two,
+    // transform this into: '(Cond ? (udiv X, C1) : (udiv X, C2))'.
+    if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
+      if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) 
+        if (STO->getType()->isUnsigned() && SFO->getType()->isUnsigned()) {
+          // STO == 0 and SFO == 0 handled above.
+          uint64_t TVA = STO->getZExtValue(), FVA = SFO->getZExtValue();
+          if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
+            unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
+            Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
+            Instruction *TSI = new ShiftInst(Instruction::Shr, Op0,
+                                             TC, SI->getName()+".t");
+            TSI = InsertNewInstBefore(TSI, I);
+
+            Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
+            Instruction *FSI = new ShiftInst(Instruction::Shr, Op0,
+                                             FC, SI->getName()+".f");
+            FSI = InsertNewInstBefore(FSI, I);
+            return new SelectInst(SI->getOperand(0), TSI, FSI);
+          }
+        }
+  }
+
+  // 0 / X == 0, we don't need to preserve faults!
+  if (ConstantInt *LHS = dyn_cast<ConstantInt>(Op0))
+    if (LHS->equalsInt(0))
+      return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+
+  // Known to be signed div
+  
+  // If the sign bits of both operands are zero (i.e. we can prove they are
+  // unsigned inputs), turn this into a udiv.
+  uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
+  if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
+    const Type *NTy = Op0->getType()->getUnsignedVersion();
+    Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
+    InsertNewInstBefore(LHS, I);
+    Value *RHS;
+    if (Constant *R = dyn_cast<Constant>(Op1))
+      RHS = ConstantExpr::getCast(R, NTy);
+    else
+      RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
+    Instruction *Div = BinaryOperator::createUDiv(LHS, RHS, I.getName());
+    InsertNewInstBefore(Div, I);
+    return new CastInst(Div, I.getType());
+  }      
+  
+  return 0;
+}
+
 
 /// GetFactor - If we can prove that the specified value is at least a multiple
 /// of some factor, return that factor.
@@ -4901,7 +5005,7 @@
   // shr int -1, X = -1   (for any arithmetic shift rights of ~0)
   if (!isLeftShift)
     if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
-      if (CSI->isAllOnesValue())
+      if (CSI->isAllOnesValue() && Op0->getType()->isSigned())
         return ReplaceInstUsesWith(I, CSI);
 
   // Try to fold constant and into select arguments.






More information about the llvm-commits mailing list