From: Dan Gohman Date: Thu, 7 May 2009 14:24:56 +0000 (+0000) Subject: Constant-fold ptrtoint+add+inttoptr to gep when the pointer is an X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=704b6980b8d45d5b6b981850bd82634d2d91e4c4;p=oota-llvm.git 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 --- diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index ac2670a163e..7c99325b2dd 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(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(CE->getOperand(0))) + if (ConstantExpr *R = dyn_cast(CE->getOperand(1))) + if (R->getOpcode() == Instruction::PtrToInt) + if (GlobalVariable *GV = + dyn_cast(R->getOperand(0))) { + const PointerType *GVTy = cast(GV->getType()); + if (const ArrayType *AT = + dyn_cast(GVTy->getElementType())) { + const Type *ElTy = AT->getElementType(); + uint64_t PaddedSize = TD->getTypePaddedSize(ElTy); + APInt PSA(L->getValue().getBitWidth(), PaddedSize); + if (ElTy == cast(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); diff --git a/test/Transforms/InstCombine/constant-fold-ptr-casts.ll b/test/Transforms/InstCombine/constant-fold-ptr-casts.ll new file mode 100644 index 00000000000..27c46068918 --- /dev/null +++ b/test/Transforms/InstCombine/constant-fold-ptr-casts.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i32 2143034560} + +; Instcombine should be able to completely fold this code. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i686-apple-darwin8" + +@bar = constant [3 x i64] [i64 9220983451228067448, i64 9220983451228067449, i64 9220983450959631991], align 8 + +define i32 @foo() nounwind { +entry: + %tmp87.2 = load i64* inttoptr (i32 add (i32 16, i32 ptrtoint ([3 x i64]* @bar to i32)) to i64*), align 8 + %t0 = bitcast i64 %tmp87.2 to double + %tmp9192.2 = fptrunc double %t0 to float + %t1 = bitcast float %tmp9192.2 to i32 + ret i32 %t1 +} +