Do not form ldrd / strd if the two dests / srcs are the same. Code clean up.
[oota-llvm.git] / lib / Analysis / ConstantFolding.cpp
index ac2670a163efc192f6227124e9221edb8734a2d9..261c635feb4a2db8c3edd86d51bcd83cfbb7cbf6 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/ADT/SmallVector.h"
@@ -76,7 +77,7 @@ static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
         Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue());
       } else {
         const SequentialType *SQT = cast<SequentialType>(*GTI);
-        Offset += TD.getTypePaddedSize(SQT->getElementType())*CI->getSExtValue();
+        Offset += TD.getTypeAllocSize(SQT->getElementType())*CI->getSExtValue();
       }
     }
     return true;
@@ -259,7 +260,7 @@ static Constant *FoldBitCast(Constant *C, const Type *DestTy,
         }
       }
       
-      return ConstantVector::get(&Result[0], Result.size());
+      return ConstantVector::get(Result.data(), Result.size());
     }
   }
   
@@ -305,10 +306,10 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) {
 
   if (const CmpInst *CI = dyn_cast<CmpInst>(I))
     return ConstantFoldCompareInstOperands(CI->getPredicate(),
-                                           &Ops[0], Ops.size(), TD);
+                                           Ops.data(), Ops.size(), TD);
   else
     return ConstantFoldInstOperands(I->getOpcode(), I->getType(),
-                                    &Ops[0], Ops.size(), TD);
+                                    Ops.data(), Ops.size(), TD);
 }
 
 /// ConstantFoldConstantExpression - Attempt to fold the constant expression
@@ -316,18 +317,16 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) {
 /// result is returned, if not, null is returned.
 Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE,
                                                const TargetData *TD) {
-  assert(TD && "ConstantFoldConstantExpression requires a valid TargetData.");
-
   SmallVector<Constant*, 8> Ops;
   for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i)
     Ops.push_back(cast<Constant>(*i));
 
   if (CE->isCompare())
     return ConstantFoldCompareInstOperands(CE->getPredicate(),
-                                           &Ops[0], Ops.size(), TD);
+                                           Ops.data(), Ops.size(), TD);
   else 
     return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(),
-                                    &Ops[0], Ops.size(), TD);
+                                    Ops.data(), Ops.size(), TD);
 }
 
 /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
@@ -383,12 +382,43 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy,
     // the int size is >= the ptr size.  This requires knowing the width of a
     // pointer, so it can't be done in ConstantExpr::getCast.
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[0])) {
-      if (TD && CE->getOpcode() == Instruction::PtrToInt &&
+      if (TD &&
           TD->getPointerSizeInBits() <=
           CE->getType()->getPrimitiveSizeInBits()) {
-        Constant *Input = CE->getOperand(0);
-        Constant *C = FoldBitCast(Input, DestTy, *TD);
-        return C ? C : ConstantExpr::getBitCast(Input, DestTy);
+        if (CE->getOpcode() == Instruction::PtrToInt) {
+          Constant *Input = CE->getOperand(0);
+          Constant *C = FoldBitCast(Input, DestTy, *TD);
+          return C ? C : ConstantExpr::getBitCast(Input, DestTy);
+        }
+        // If there's a constant offset added to the integer value before
+        // it is casted back to a pointer, see if the expression can be
+        // converted into a GEP.
+        if (CE->getOpcode() == Instruction::Add)
+          if (ConstantInt *L = dyn_cast<ConstantInt>(CE->getOperand(0)))
+            if (ConstantExpr *R = dyn_cast<ConstantExpr>(CE->getOperand(1)))
+              if (R->getOpcode() == Instruction::PtrToInt)
+                if (GlobalVariable *GV =
+                      dyn_cast<GlobalVariable>(R->getOperand(0))) {
+                  const PointerType *GVTy = cast<PointerType>(GV->getType());
+                  if (const ArrayType *AT =
+                        dyn_cast<ArrayType>(GVTy->getElementType())) {
+                    const Type *ElTy = AT->getElementType();
+                    uint64_t AllocSize = TD->getTypeAllocSize(ElTy);
+                    APInt PSA(L->getValue().getBitWidth(), AllocSize);
+                    if (ElTy == cast<PointerType>(DestTy)->getElementType() &&
+                        L->getValue().urem(PSA) == 0) {
+                      APInt ElemIdx = L->getValue().udiv(PSA);
+                      if (ElemIdx.ult(APInt(ElemIdx.getBitWidth(),
+                                            AT->getNumElements()))) {
+                        Constant *Index[] = {
+                          Constant::getNullValue(CE->getType()),
+                          ConstantInt::get(ElemIdx)
+                        };
+                        return ConstantExpr::getGetElementPtr(GV, &Index[0], 2);
+                      }
+                    }
+                  }
+                }
       }
     }
     return ConstantExpr::getCast(Opcode, Ops[0], DestTy);