aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-05-07 14:24:56 +0000
committerDan Gohman <gohman@apple.com>2009-05-07 14:24:56 +0000
commit704b6980b8d45d5b6b981850bd82634d2d91e4c4 (patch)
tree8cbb099520398571d7f9fd7db1af5f30c86325ae /lib/Analysis/ConstantFolding.cpp
parentecb403a9d3a340009c266d05cfca2bd778c7b156 (diff)
Constant-fold ptrtoint+add+inttoptr to gep when the pointer is an
array and the add is within range. This helps simplify expressions expanded by ScalarEvolutionExpander. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71158 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ConstantFolding.cpp')
-rw-r--r--lib/Analysis/ConstantFolding.cpp40
1 files changed, 36 insertions, 4 deletions
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index ac2670a163..7c99325b2d 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -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"
@@ -383,12 +384,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 PaddedSize = TD->getTypePaddedSize(ElTy);
+ APInt PSA(L->getValue().getBitWidth(), PaddedSize);
+ 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);