For PR786:
[oota-llvm.git] / lib / VMCore / ConstantFold.cpp
index ad9a33f845eda22fbfa5f2bcc7c878a13c19be69..055d41c063d2f85b2f6dbe79c2d388c66f0108f5 100644 (file)
@@ -40,8 +40,12 @@ namespace {
     virtual Constant *add(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *sub(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0;
-    virtual Constant *div(const Constant *V1, const Constant *V2) const = 0;
-    virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *urem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *srem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *frem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *udiv(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *sdiv(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *fdiv(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_and(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_or (const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_xor(const Constant *V1, const Constant *V2) const = 0;
@@ -106,11 +110,23 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
   virtual Constant *mul(const Constant *V1, const Constant *V2) const {
     return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);
   }
-  virtual Constant *div(const Constant *V1, const Constant *V2) const {
-    return SubClassName::Div((const ArgType *)V1, (const ArgType *)V2);
+  virtual Constant *udiv(const Constant *V1, const Constant *V2) const {
+    return SubClassName::UDiv((const ArgType *)V1, (const ArgType *)V2);
   }
-  virtual Constant *rem(const Constant *V1, const Constant *V2) const {
-    return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2);
+  virtual Constant *sdiv(const Constant *V1, const Constant *V2) const {
+    return SubClassName::SDiv((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *fdiv(const Constant *V1, const Constant *V2) const {
+    return SubClassName::FDiv((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *urem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::URem((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *srem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::SRem((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *frem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::FRem((const ArgType *)V1, (const ArgType *)V2);
   }
   virtual Constant *op_and(const Constant *V1, const Constant *V2) const {
     return SubClassName::And((const ArgType *)V1, (const ArgType *)V2);
@@ -178,16 +194,20 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
   // Default "noop" implementations
   //===--------------------------------------------------------------------===//
 
-  static Constant *Add(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Sub(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Mul(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Div(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Rem(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *And(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Or (const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Xor(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Shl(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Shr(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Add (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Sub (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Mul (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *SDiv(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *UDiv(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *FDiv(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *URem(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *SRem(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *FRem(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *And (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Or  (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Xor (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Shl (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *Shr (const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *LessThan(const ArgType *V1, const ArgType *V2) {
     return 0;
   }
@@ -373,11 +393,23 @@ struct VISIBILITY_HIDDEN ConstantPackedRules
   static Constant *Mul(const ConstantPacked *V1, const ConstantPacked *V2) {
     return EvalVectorOp(V1, V2, ConstantExpr::getMul);
   }
-  static Constant *Div(const ConstantPacked *V1, const ConstantPacked *V2) {
-    return EvalVectorOp(V1, V2, ConstantExpr::getDiv);
+  static Constant *UDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getUDiv);
+  }
+  static Constant *SDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getSDiv);
+  }
+  static Constant *FDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getFDiv);
+  }
+  static Constant *URem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getURem);
   }
-  static Constant *Rem(const ConstantPacked *V1, const ConstantPacked *V2) {
-    return EvalVectorOp(V1, V2, ConstantExpr::getRem);
+  static Constant *SRem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getSRem);
+  }
+  static Constant *FRem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getFRem);
   }
   static Constant *And(const ConstantPacked *V1, const ConstantPacked *V2) {
     return EvalVectorOp(V1, V2, ConstantExpr::getAnd);
@@ -493,24 +525,37 @@ struct VISIBILITY_HIDDEN DirectIntRules
   DEF_CAST(Double, ConstantFP , double)
 #undef DEF_CAST
 
-  static Constant *Div(const ConstantInt *V1, const ConstantInt *V2) {
-    if (V2->isNullValue()) return 0;
+  static Constant *UDiv(const ConstantInt *V1, const ConstantInt *V2) {
+    if (V2->isNullValue())                   // X / 0
+      return 0;
+    BuiltinType R = (BuiltinType)(V1->getZExtValue() / V2->getZExtValue());
+    return ConstantInt::get(*Ty, R);
+  }
+
+  static Constant *SDiv(const ConstantInt *V1, const ConstantInt *V2) {
+    if (V2->isNullValue())                   // X / 0
+      return 0;
     if (V2->isAllOnesValue() &&              // MIN_INT / -1
-        (BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
+        (BuiltinType)V1->getSExtValue() == -(BuiltinType)V1->getSExtValue())
       return 0;
-    BuiltinType R = 
-      (BuiltinType)V1->getZExtValue() / (BuiltinType)V2->getZExtValue();
+    BuiltinType R = (BuiltinType)(V1->getSExtValue() / V2->getSExtValue());
     return ConstantInt::get(*Ty, R);
   }
 
-  static Constant *Rem(const ConstantInt *V1,
+  static Constant *URem(const ConstantInt *V1,
                         const ConstantInt *V2) {
     if (V2->isNullValue()) return 0;         // X / 0
-    if (V2->isAllOnesValue() &&              // MIN_INT / -1
-        (BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
+    BuiltinType R = (BuiltinType)(V1->getZExtValue() % V2->getZExtValue());
+    return ConstantInt::get(*Ty, R);
+  }
+
+  static Constant *SRem(const ConstantInt *V1,
+                        const ConstantInt *V2) {
+    if (V2->isNullValue()) return 0;         // X % 0
+    if (V2->isAllOnesValue() &&              // MIN_INT % -1
+        (BuiltinType)V1->getSExtValue() == -(BuiltinType)V1->getSExtValue())
       return 0;
-    BuiltinType R = 
-      (BuiltinType)V1->getZExtValue() % (BuiltinType)V2->getZExtValue();
+    BuiltinType R = (BuiltinType)(V1->getSExtValue() % V2->getSExtValue());
     return ConstantInt::get(*Ty, R);
   }
 
@@ -609,13 +654,13 @@ struct VISIBILITY_HIDDEN DirectFPRules
   DEF_CAST(Double, ConstantFP , double)
 #undef DEF_CAST
 
-  static Constant *Rem(const ConstantFP *V1, const ConstantFP *V2) {
+  static Constant *FRem(const ConstantFP *V1, const ConstantFP *V2) {
     if (V2->isNullValue()) return 0;
     BuiltinType Result = std::fmod((BuiltinType)V1->getValue(),
                                    (BuiltinType)V2->getValue());
     return ConstantFP::get(*Ty, Result);
   }
-  static Constant *Div(const ConstantFP *V1, const ConstantFP *V2) {
+  static Constant *FDiv(const ConstantFP *V1, const ConstantFP *V2) {
     BuiltinType inf = std::numeric_limits<BuiltinType>::infinity();
     if (V2->isExactlyValue(0.0)) return ConstantFP::get(*Ty, inf);
     if (V2->isExactlyValue(-0.0)) return ConstantFP::get(*Ty, -inf);
@@ -764,7 +809,7 @@ Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
   if (V->getType() == DestTy) return (Constant*)V;
 
   // Cast of a global address to boolean is always true.
-  if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+  if (isa<GlobalValue>(V)) {
     if (DestTy == Type::BoolTy)
       // FIXME: When we support 'external weak' references, we have to prevent
       // this transformation from happening.  This code will need to be updated
@@ -917,7 +962,7 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
   const ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx);
   if (!CIdx) return 0;
   uint64_t idxVal = CIdx->getZExtValue();
-  if (const UndefValue *UVal = dyn_cast<UndefValue>(Val)) {
+  if (isa<UndefValue>(Val)) { 
     // Insertion of scalar constant into packed undef
     // Optimize away insertion of undef
     if (isa<UndefValue>(Elt))
@@ -935,8 +980,7 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
     }
     return ConstantPacked::get(Ops);
   }
-  if (const ConstantAggregateZero *CVal =
-      dyn_cast<ConstantAggregateZero>(Val)) {
+  if (isa<ConstantAggregateZero>(Val)) {
     // Insertion of scalar constant into packed aggregate zero
     // Optimize away insertion of zero
     if (Elt->isNullValue())
@@ -1224,8 +1268,12 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
   case Instruction::Add:     C = ConstRules::get(V1, V2).add(V1, V2); break;
   case Instruction::Sub:     C = ConstRules::get(V1, V2).sub(V1, V2); break;
   case Instruction::Mul:     C = ConstRules::get(V1, V2).mul(V1, V2); break;
-  case Instruction::Div:     C = ConstRules::get(V1, V2).div(V1, V2); break;
-  case Instruction::Rem:     C = ConstRules::get(V1, V2).rem(V1, V2); break;
+  case Instruction::UDiv:    C = ConstRules::get(V1, V2).udiv(V1, V2); break;
+  case Instruction::SDiv:    C = ConstRules::get(V1, V2).sdiv(V1, V2); break;
+  case Instruction::FDiv:    C = ConstRules::get(V1, V2).fdiv(V1, V2); break;
+  case Instruction::URem:    C = ConstRules::get(V1, V2).urem(V1, V2); break;
+  case Instruction::SRem:    C = ConstRules::get(V1, V2).srem(V1, V2); break;
+  case Instruction::FRem:    C = ConstRules::get(V1, V2).frem(V1, V2); break;
   case Instruction::And:     C = ConstRules::get(V1, V2).op_and(V1, V2); break;
   case Instruction::Or:      C = ConstRules::get(V1, V2).op_or (V1, V2); break;
   case Instruction::Xor:     C = ConstRules::get(V1, V2).op_xor(V1, V2); break;
@@ -1307,26 +1355,29 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     case Instruction::Mul:
     case Instruction::And:
       return Constant::getNullValue(V1->getType());
-    case Instruction::Div:
-    case Instruction::Rem:
-      if (!isa<UndefValue>(V2))     // undef/X -> 0
+    case Instruction::UDiv:
+    case Instruction::SDiv:
+    case Instruction::FDiv:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
+      if (!isa<UndefValue>(V2))                    // undef / X -> 0
         return Constant::getNullValue(V1->getType());
-      return const_cast<Constant*>(V2);                // X/undef -> undef
-    case Instruction::Or:           // X|undef -> -1
+      return const_cast<Constant*>(V2);            // X / undef -> undef
+    case Instruction::Or:                          // X | undef -> -1
       return ConstantInt::getAllOnesValue(V1->getType());
     case Instruction::Shr:
-      if (!isa<UndefValue>(V2)) {
+      if (!isa<UndefValue>(V2)) {      
         if (V1->getType()->isSigned())
-          return const_cast<Constant*>(V1);  // undef >>s X -> undef
+          return const_cast<Constant*>(V1);        // undef >>s X -> undef
         // undef >>u X -> 0
       } else if (isa<UndefValue>(V1)) {
-        return const_cast<Constant*>(V1);   //  undef >> undef -> undef
+        return const_cast<Constant*>(V1);          // undef >> undef -> undef
       } else {
         if (V1->getType()->isSigned())
-          return const_cast<Constant*>(V1);  // X >>s undef -> X
-        // X >>u undef -> 0
+          return const_cast<Constant*>(V1);        // X >>s undef -> X
       }
-      return Constant::getNullValue(V1->getType());
+      return Constant::getNullValue(V1->getType());// X >>u undef -> 0
 
     case Instruction::Shl:
       // undef << X -> 0   X << undef -> 0
@@ -1335,14 +1386,10 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
   }
 
   if (const ConstantExpr *CE1 = dyn_cast<ConstantExpr>(V1)) {
-    if (const ConstantExpr *CE2 = dyn_cast<ConstantExpr>(V2)) {
+    if (isa<ConstantExpr>(V2)) {
       // There are many possible foldings we could do here.  We should probably
       // at least fold add of a pointer with an integer into the appropriate
       // getelementptr.  This will improve alias analysis a bit.
-
-
-
-
     } else {
       // Just implement a couple of simple identities.
       switch (Opcode) {
@@ -1358,15 +1405,17 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
           if (CI->getZExtValue() == 1)
             return const_cast<Constant*>(V1);                     // X * 1 == X
         break;
-      case Instruction::Div:
+      case Instruction::UDiv:
+      case Instruction::SDiv:
         if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
           if (CI->getZExtValue() == 1)
             return const_cast<Constant*>(V1);                     // X / 1 == X
         break;
-      case Instruction::Rem:
+      case Instruction::URem:
+      case Instruction::SRem:
         if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
           if (CI->getZExtValue() == 1)
-            return Constant::getNullValue(CI->getType()); // X % 1 == 0
+            return Constant::getNullValue(CI->getType());         // X % 1 == 0
         break;
       case Instruction::And:
         if (cast<ConstantIntegral>(V2)->isAllOnesValue())
@@ -1394,7 +1443,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
       }
     }
 
-  } else if (const ConstantExpr *CE2 = dyn_cast<ConstantExpr>(V2)) {
+  } else if (isa<ConstantExpr>(V2)) {
     // If V2 is a constant expr and V1 isn't, flop them around and fold the
     // other way if possible.
     switch (Opcode) {
@@ -1419,8 +1468,12 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     case Instruction::Shl:
     case Instruction::Shr:
     case Instruction::Sub:
-    case Instruction::Div:
-    case Instruction::Rem:
+    case Instruction::SDiv:
+    case Instruction::UDiv:
+    case Instruction::FDiv:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     default:  // These instructions cannot be flopped around.
       break;
     }