diff options
author | Chris Lattner <sabre@nondot.org> | 2011-01-06 06:19:46 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2011-01-06 06:19:46 +0000 |
commit | 8cd4efb6a5e51b4e77039c17338f290ca3a8ee92 (patch) | |
tree | ae17d657a282344d56741b227bebecd9246785e7 | |
parent | 255874ff521bb81b294ec861a5d9a99d8198448c (diff) |
implement constant folding support for an exotic constant expr:
ret i64 ptrtoint (i8* getelementptr ([1000 x i8]* @X, i64 1, i64 sub (i64 0, i64 ptrtoint ([1000 x i8]* @X to i64))) to i64)
to "ret i64 1000". This allows us to correctly compute the trip count
on a loop in PR8883, which occurs with std::fill on a char array. This
allows us to transform it into a memset with a constant size.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122950 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/ConstantFolding.cpp | 20 | ||||
-rw-r--r-- | test/Transforms/InstCombine/constant-fold-gep.ll | 19 |
2 files changed, 38 insertions, 1 deletions
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index ded1d0767c..6c5b75502f 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -575,8 +575,26 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // If this is a constant expr gep that is effectively computing an // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' for (unsigned i = 1; i != NumOps; ++i) - if (!isa<ConstantInt>(Ops[i])) + if (!isa<ConstantInt>(Ops[i])) { + + // If this is "gep i8* Ptr, (sub 0, V)", fold this as: + // "inttoptr (sub (ptrtoint Ptr), V)" + if (NumOps == 2 && + cast<PointerType>(ResultTy)->getElementType()->isIntegerTy(8)) { + ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[1]); + if (CE && CE->getOpcode() == Instruction::Sub && + isa<ConstantInt>(CE->getOperand(0)) && + cast<ConstantInt>(CE->getOperand(0))->isZero()) { + Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType()); + Res = ConstantExpr::getSub(Res, CE->getOperand(1)); + Res = ConstantExpr::getIntToPtr(Res, ResultTy); + if (ConstantExpr *ResCE = dyn_cast<ConstantExpr>(Res)) + Res = ConstantFoldConstantExpression(ResCE, TD); + return Res; + } + } return 0; + } APInt Offset = APInt(BitWidth, TD->getIndexedOffset(Ptr->getType(), diff --git a/test/Transforms/InstCombine/constant-fold-gep.ll b/test/Transforms/InstCombine/constant-fold-gep.ll index 4be1a9c838..c679226d4a 100644 --- a/test/Transforms/InstCombine/constant-fold-gep.ll +++ b/test/Transforms/InstCombine/constant-fold-gep.ll @@ -53,3 +53,22 @@ define void @frob() { store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 19), align 8 ret void } + + +; PR8883 - Constant fold exotic gep subtract +; CHECK: @test2 +@X = global [1000 x i8] zeroinitializer, align 16 + +define i64 @test2() { +entry: + %A = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 1, i64 0) to i8* + %B = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 0, i64 0) to i8* + + %B2 = ptrtoint i8* %B to i64 + %C = sub i64 0, %B2 + %D = getelementptr i8* %A, i64 %C + %E = ptrtoint i8* %D to i64 + + ret i64 %E + ; CHECK: ret i64 1000 +} |