It's a bool, so treat it like one. Fixes a MSVC warning.
[oota-llvm.git] / lib / Analysis / ConstantFolding.cpp
index 5fae1ea0a75e50951b8669ee97eaca1aaa12d610..109eaad4584e4537b1737e5bf89bc33bd8cefbec 100644 (file)
@@ -129,16 +129,19 @@ static Constant *SymbolicallyEvaluateGEP(Constant* const* Ops, unsigned NumOps,
   Constant *Ptr = Ops[0];
   if (!TD || !cast<PointerType>(Ptr->getType())->getElementType()->isSized())
     return 0;
-  
-  uint64_t BasePtr = 0;
+
+  unsigned BitWidth = TD->getTypeSizeInBits(TD->getIntPtrType(Context));
+  APInt BasePtr(BitWidth, 0);
   bool BaseIsInt = true;
   if (!Ptr->isNullValue()) {
     // If this is a inttoptr from a constant int, we can fold this as the base,
     // otherwise we can't.
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
       if (CE->getOpcode() == Instruction::IntToPtr)
-        if (ConstantInt *Base = dyn_cast<ConstantInt>(CE->getOperand(0)))
-          BasePtr = Base->getZExtValue();
+        if (ConstantInt *Base = dyn_cast<ConstantInt>(CE->getOperand(0))) {
+          BasePtr = Base->getValue();
+          BasePtr.zextOrTrunc(BitWidth);
+        }
     
     if (BasePtr == 0)
       BaseIsInt = false;
@@ -150,12 +153,13 @@ static Constant *SymbolicallyEvaluateGEP(Constant* const* Ops, unsigned NumOps,
     if (!isa<ConstantInt>(Ops[i]))
       return 0;
   
-  uint64_t Offset = TD->getIndexedOffset(Ptr->getType(),
-                                         (Value**)Ops+1, NumOps-1);
+  APInt Offset = APInt(BitWidth,
+                       TD->getIndexedOffset(Ptr->getType(),
+                                            (Value**)Ops+1, NumOps-1));
   // If the base value for this address is a literal integer value, fold the
   // getelementptr to the resulting integer value casted to the pointer type.
   if (BaseIsInt) {
-    Constant *C = ConstantInt::get(TD->getIntPtrType(Context), Offset+BasePtr);
+    Constant *C = ConstantInt::get(Context, Offset+BasePtr);
     return ConstantExpr::getIntToPtr(C, ResultTy);
   }
 
@@ -165,38 +169,56 @@ static Constant *SymbolicallyEvaluateGEP(Constant* const* Ops, unsigned NumOps,
   // Also, this helps GlobalOpt do SROA on GlobalVariables.
   const Type *Ty = Ptr->getType();
   SmallVector<Constant*, 32> NewIdxs;
-  for (unsigned Index = 1; Index != NumOps; ++Index) {
+  do {
     if (const SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
+      // The only pointer indexing we'll do is on the first index of the GEP.
+      if (isa<PointerType>(ATy) && !NewIdxs.empty())
+        break;
       // Determine which element of the array the offset points into.
-      uint64_t ElemSize = TD->getTypeAllocSize(ATy->getElementType());
+      APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType()));
       if (ElemSize == 0)
         return 0;
-      uint64_t NewIdx = Offset / ElemSize;
+      APInt NewIdx = Offset.udiv(ElemSize);
       Offset -= NewIdx * ElemSize;
       NewIdxs.push_back(ConstantInt::get(TD->getIntPtrType(Context), NewIdx));
       Ty = ATy->getElementType();
     } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
-      // Determine which field of the struct the offset points into.
+      // Determine which field of the struct the offset points into. The
+      // getZExtValue is at least as safe as the StructLayout API because we
+      // know the offset is within the struct at this point.
       const StructLayout &SL = *TD->getStructLayout(STy);
-      unsigned ElIdx = SL.getElementContainingOffset(Offset);
+      unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue());
       NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Context), ElIdx));
-      Offset -= SL.getElementOffset(ElIdx);
+      Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx));
       Ty = STy->getTypeAtIndex(ElIdx);
     } else {
-      return 0;
+      // We've reached some non-indexable type.
+      break;
     }
-  }
+  } while (Ty != cast<PointerType>(ResultTy)->getElementType());
+
+  // If we haven't used up the entire offset by descending the static
+  // type, then the offset is pointing into the middle of an indivisible
+  // member, so we can't simplify it.
+  if (Offset != 0)
+    return 0;
 
   // If the base is the start of a GlobalVariable and all the array indices
   // remain in their static bounds, the GEP is inbounds. We can check that
   // all indices are in bounds by just checking the first index only
   // because we've just normalized all the indices.
-  if (isa<GlobalVariable>(Ptr) && NewIdxs[0]->isNullValue())
-    return ConstantExpr::getInBoundsGetElementPtr(Ptr,
-                                                  &NewIdxs[0], NewIdxs.size());
+  Constant *C = isa<GlobalVariable>(Ptr) && NewIdxs[0]->isNullValue() ?
+    ConstantExpr::getInBoundsGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size()) :
+    ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size());
+  assert(cast<PointerType>(C->getType())->getElementType() == Ty &&
+         "Computed GetElementPtr has unexpected type!");
 
-  // Otherwise it may not be inbounds.
-  return ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size());
+  // If we ended up indexing a member with a type that doesn't match
+  // the type of what the original indices indexed, add a cast.
+  if (Ty != cast<PointerType>(ResultTy)->getElementType())
+    C = ConstantExpr::getBitCast(C, ResultTy);
+
+  return C;
 }
 
 /// FoldBitCast - Constant fold bitcast, symbolically evaluating it with