Fix PR2267, by allowing indirect outputs to be intermixed
[oota-llvm.git] / lib / VMCore / ConstantFold.cpp
index ffc8f027805f55471fb28379261e40677a13e46b..0913c481ad80dbb5d3846290a66ed9ed91a2c616 100644 (file)
@@ -332,10 +332,10 @@ Constant *llvm::ConstantFoldExtractElementInstruction(const Constant *Val,
   
   if (const ConstantVector *CVal = dyn_cast<ConstantVector>(Val)) {
     if (const ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx)) {
-      return const_cast<Constant*>(CVal->getOperand(CIdx->getZExtValue()));
+      return CVal->getOperand(CIdx->getZExtValue());
     } else if (isa<UndefValue>(Idx)) {
       // ee({w,x,y,z}, undef) -> w (an arbitrary value).
-      return const_cast<Constant*>(CVal->getOperand(0));
+      return CVal->getOperand(0);
     }
   }
   return 0;
@@ -401,7 +401,7 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
 /// return the specified element value.  Otherwise return null.
 static Constant *GetVectorElement(const Constant *C, unsigned EltNo) {
   if (const ConstantVector *CV = dyn_cast<ConstantVector>(C))
-    return const_cast<Constant*>(CV->getOperand(EltNo));
+    return CV->getOperand(EltNo);
   
   const Type *EltTy = cast<VectorType>(C->getType())->getElementType();
   if (isa<ConstantAggregateZero>(C))
@@ -447,6 +447,21 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1,
   return ConstantVector::get(&Result[0], Result.size());
 }
 
+Constant *llvm::ConstantFoldExtractValue(const Constant *Agg,
+                                         Constant* const *Idxs,
+                                         unsigned NumIdx) {
+  // FIXME: implement some constant folds
+  return 0;
+}
+
+Constant *llvm::ConstantFoldInsertValue(const Constant *Agg,
+                                        const Constant *Val,
+                                        Constant* const *Idxs,
+                                        unsigned NumIdx) {
+  // FIXME: implement some constant folds
+  return 0;
+}
+
 /// EvalVectorOp - Given two vector constants and a function pointer, apply the
 /// function pointer to each element pair, producing a new ConstantVector
 /// constant. Either or both of V1 and V2 may be NULL, meaning a
@@ -571,7 +586,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
           
           if (GVAlign > 1) {
             unsigned DstWidth = CI2->getType()->getBitWidth();
-            unsigned SrcWidth = std::min(SrcWidth, Log2_32(GVAlign));
+            unsigned SrcWidth = std::min(DstWidth, Log2_32(GVAlign));
             APInt BitsNotSet(APInt::getLowBitsSet(DstWidth, SrcWidth));
 
             // If checking bits we know are clear, return zero.
@@ -599,44 +614,12 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     }
   }
   
-  if (isa<ConstantExpr>(C1)) {
-    // 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 if (isa<ConstantExpr>(C2)) {
-    // If C2 is a constant expr and C1 isn't, flop them around and fold the
-    // other way if possible.
-    switch (Opcode) {
-    case Instruction::Add:
-    case Instruction::Mul:
-    case Instruction::And:
-    case Instruction::Or:
-    case Instruction::Xor:
-      // No change of opcode required.
-      return ConstantFoldBinaryInstruction(Opcode, C2, C1);
-
-    case Instruction::Shl:
-    case Instruction::LShr:
-    case Instruction::AShr:
-    case Instruction::Sub:
-    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.
-      return 0;
-    }
-  }
-
-  // At this point we know neither constant is an UndefValue nor a ConstantExpr
-  // so look at directly computing the value.
+  // At this point we know neither constant is an UndefValue.
   if (const ConstantInt *CI1 = dyn_cast<ConstantInt>(C1)) {
     if (const ConstantInt *CI2 = dyn_cast<ConstantInt>(C2)) {
       using namespace APIntOps;
-      APInt C1V = CI1->getValue();
-      APInt C2V = CI2->getValue();
+      const APInt &C1V = CI1->getValue();
+      const APInt &C2V = CI2->getValue();
       switch (Opcode) {
       default:
         break;
@@ -672,30 +655,27 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
         return ConstantInt::get(C1V | C2V);
       case Instruction::Xor:
         return ConstantInt::get(C1V ^ C2V);
-      case Instruction::Shl:
-        if (uint32_t shiftAmt = C2V.getZExtValue()) {
-          if (shiftAmt < C1V.getBitWidth())
-            return ConstantInt::get(C1V.shl(shiftAmt));
-          else
-            return UndefValue::get(C1->getType()); // too big shift is undef
-        }
-        return const_cast<ConstantInt*>(CI1); // Zero shift is identity
-      case Instruction::LShr:
-        if (uint32_t shiftAmt = C2V.getZExtValue()) {
-          if (shiftAmt < C1V.getBitWidth())
-            return ConstantInt::get(C1V.lshr(shiftAmt));
-          else
-            return UndefValue::get(C1->getType()); // too big shift is undef
-        }
-        return const_cast<ConstantInt*>(CI1); // Zero shift is identity
-      case Instruction::AShr:
-        if (uint32_t shiftAmt = C2V.getZExtValue()) {
-          if (shiftAmt < C1V.getBitWidth())
-            return ConstantInt::get(C1V.ashr(shiftAmt));
-          else
-            return UndefValue::get(C1->getType()); // too big shift is undef
-        }
-        return const_cast<ConstantInt*>(CI1); // Zero shift is identity
+      case Instruction::Shl: {
+        uint32_t shiftAmt = C2V.getZExtValue();
+        if (shiftAmt < C1V.getBitWidth())
+          return ConstantInt::get(C1V.shl(shiftAmt));
+        else
+          return UndefValue::get(C1->getType()); // too big shift is undef
+      }
+      case Instruction::LShr: {
+        uint32_t shiftAmt = C2V.getZExtValue();
+        if (shiftAmt < C1V.getBitWidth())
+          return ConstantInt::get(C1V.lshr(shiftAmt));
+        else
+          return UndefValue::get(C1->getType()); // too big shift is undef
+      }
+      case Instruction::AShr: {
+        uint32_t shiftAmt = C2V.getZExtValue();
+        if (shiftAmt < C1V.getBitWidth())
+          return ConstantInt::get(C1V.ashr(shiftAmt));
+        else
+          return UndefValue::get(C1->getType()); // too big shift is undef
+      }
       }
     }
   } else if (const ConstantFP *CFP1 = dyn_cast<ConstantFP>(C1)) {
@@ -769,7 +749,38 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     }
   }
 
-  // We don't know how to fold this
+  if (isa<ConstantExpr>(C1)) {
+    // 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 if (isa<ConstantExpr>(C2)) {
+    // If C2 is a constant expr and C1 isn't, flop them around and fold the
+    // other way if possible.
+    switch (Opcode) {
+    case Instruction::Add:
+    case Instruction::Mul:
+    case Instruction::And:
+    case Instruction::Or:
+    case Instruction::Xor:
+      // No change of opcode required.
+      return ConstantFoldBinaryInstruction(Opcode, C2, C1);
+      
+    case Instruction::Shl:
+    case Instruction::LShr:
+    case Instruction::AShr:
+    case Instruction::Sub:
+    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;
+    }
+  }
+  
+  // We don't know how to fold this.
   return 0;
 }
 
@@ -1226,9 +1237,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
     if (const ConstantVector *CP2 = dyn_cast<ConstantVector>(C2)) {
       if (pred == FCmpInst::FCMP_OEQ || pred == FCmpInst::FCMP_UEQ) {
         for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
-          Constant *C= ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
-              const_cast<Constant*>(CP1->getOperand(i)),
-              const_cast<Constant*>(CP2->getOperand(i)));
+          Constant *C = ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
+                                              CP1->getOperand(i),
+                                              CP2->getOperand(i));
           if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
             return CB;
         }
@@ -1237,8 +1248,8 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
       } else if (pred == ICmpInst::ICMP_EQ) {
         for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
           Constant *C = ConstantExpr::getICmp(ICmpInst::ICMP_EQ,
-              const_cast<Constant*>(CP1->getOperand(i)),
-              const_cast<Constant*>(CP2->getOperand(i)));
+                                              CP1->getOperand(i),
+                                              CP2->getOperand(i));
           if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
             return CB;
         }
@@ -1412,8 +1423,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
     const PointerType *Ptr = cast<PointerType>(C->getType());
     const Type *Ty = GetElementPtrInst::getIndexedType(Ptr,
                                                        (Value **)Idxs,
-                                                       (Value **)Idxs+NumIdx,
-                                                       true);
+                                                       (Value **)Idxs+NumIdx);
     assert(Ty != 0 && "Invalid indices for GEP!");
     return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace()));
   }
@@ -1430,8 +1440,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
       const PointerType *Ptr = cast<PointerType>(C->getType());
       const Type *Ty = GetElementPtrInst::getIndexedType(Ptr,
                                                          (Value**)Idxs,
-                                                         (Value**)Idxs+NumIdx,
-                                                         true);
+                                                         (Value**)Idxs+NumIdx);
       assert(Ty != 0 && "Invalid indices for GEP!");
       return 
         ConstantPointerNull::get(PointerType::get(Ty,Ptr->getAddressSpace()));