diff options
author | Chris Lattner <sabre@nondot.org> | 2008-01-08 07:23:51 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-01-08 07:23:51 +0000 |
commit | 7c1626487614decfca94d042e97c8000a3bf5cff (patch) | |
tree | d2ef3637cba947df401cbe8b21ebd9036d28f05a | |
parent | e292b09d3ecb946ed792056d762698a0e944a746 (diff) | |
download | external_llvm-7c1626487614decfca94d042e97c8000a3bf5cff.zip external_llvm-7c1626487614decfca94d042e97c8000a3bf5cff.tar.gz external_llvm-7c1626487614decfca94d042e97c8000a3bf5cff.tar.bz2 |
Implement PR1795, an instcombine hack for forming GEPs with integer pointer arithmetic.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45745 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 56 | ||||
-rw-r--r-- | test/Transforms/InstCombine/add2.ll | 20 |
2 files changed, 73 insertions, 3 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 19f86f9..93fad0a 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -210,7 +210,7 @@ namespace { Instruction *visitUIToFP(CastInst &CI); Instruction *visitSIToFP(CastInst &CI); Instruction *visitPtrToInt(CastInst &CI); - Instruction *visitIntToPtr(CastInst &CI); + Instruction *visitIntToPtr(IntToPtrInst &CI); Instruction *visitBitCast(BitCastInst &CI); Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI); @@ -7148,8 +7148,58 @@ Instruction *InstCombiner::visitPtrToInt(CastInst &CI) { return commonPointerCastTransforms(CI); } -Instruction *InstCombiner::visitIntToPtr(CastInst &CI) { - return commonCastTransforms(CI); +Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) { + if (Instruction *I = commonCastTransforms(CI)) + return I; + + const Type *DestPointee = cast<PointerType>(CI.getType())->getElementType(); + if (!DestPointee->isSized()) return 0; + + // If this is inttoptr(add (ptrtoint x), cst), try to turn this into a GEP. + ConstantInt *Cst; + Value *X; + if (match(CI.getOperand(0), m_Add(m_Cast<PtrToIntInst>(m_Value(X)), + m_ConstantInt(Cst)))) { + // If the source and destination operands have the same type, see if this + // is a single-index GEP. + if (X->getType() == CI.getType()) { + // Get the size of the pointee type. + uint64_t Size = TD->getABITypeSizeInBits(DestPointee); + + // Convert the constant to intptr type. + APInt Offset = Cst->getValue(); + Offset.sextOrTrunc(TD->getPointerSizeInBits()); + + // If Offset is evenly divisible by Size, we can do this xform. + if (Size && !APIntOps::srem(Offset, APInt(Offset.getBitWidth(), Size))){ + Offset = APIntOps::sdiv(Offset, APInt(Offset.getBitWidth(), Size)); + return new GetElementPtrInst(X, ConstantInt::get(Offset)); + } + } + // TODO: Could handle other cases, e.g. where add is indexing into field of + // struct etc. + } else if (CI.getOperand(0)->hasOneUse() && + match(CI.getOperand(0), m_Add(m_Value(X), m_ConstantInt(Cst)))) { + // Otherwise, if this is inttoptr(add x, cst), try to turn this into an + // "inttoptr+GEP" instead of "add+intptr". + + // Get the size of the pointee type. + uint64_t Size = TD->getABITypeSize(DestPointee); + + // Convert the constant to intptr type. + APInt Offset = Cst->getValue(); + Offset.sextOrTrunc(TD->getPointerSizeInBits()); + + // If Offset is evenly divisible by Size, we can do this xform. + if (Size && !APIntOps::srem(Offset, APInt(Offset.getBitWidth(), Size))){ + Offset = APIntOps::sdiv(Offset, APInt(Offset.getBitWidth(), Size)); + + Instruction *P = InsertNewInstBefore(new IntToPtrInst(X, CI.getType(), + "tmp"), CI); + return new GetElementPtrInst(P, ConstantInt::get(Offset), "tmp"); + } + } + return 0; } Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll index ff89946..de1bbf4 100644 --- a/test/Transforms/InstCombine/add2.ll +++ b/test/Transforms/InstCombine/add2.ll @@ -1,6 +1,10 @@ ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \ ; RUN: grep -v OK | not grep add +;; Target triple for gep raising case below. +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" + define i64 @test1(i64 %A, i32 %B) { %tmp12 = zext i32 %B to i64 %tmp3 = shl i64 %tmp12, 32 @@ -9,3 +13,19 @@ define i64 @test1(i64 %A, i32 %B) { ret i64 %tmp6 } +; PR1795 +define void @test2(i32 %.val24) { +EntryBlock: + add i32 %.val24, -12 + inttoptr i32 %0 to i32* + store i32 1, i32* %1 + add i32 %.val24, -16 + inttoptr i32 %2 to i32* + getelementptr i32* %3, i32 1 + load i32* %4 + tail call i32 @callee( i32 %5 ) + ret void +} + +declare i32 @callee(i32) + |