[PATCH] IR: Don't constant fold GEP bitcasts between different address spaces
Meador Inge
meadori at codesourcery.com
Mon Feb 25 13:40:04 PST 2013
Ping.
On 02/21/2013 09:42 AM, Meador Inge wrote:
> PR15262 reported a bug where the following instruction:
>
> i8 getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @buf to i8*),
> i32 2
>
> was getting folded into:
>
> addrspace(12)* getelementptr inbounds ([4 x i8] addrspace(12)* @buf, i32 0,
> i32 2)
>
> This caused instcombine to crash because the original instruction and
> the folded instruction have different types. The issue was fixed by
> disallowing bitcasts between different address spaces to be folded away.
>
> OK?
> ---
> lib/IR/ConstantFold.cpp | 35 ++++++++++++++++++++++-------------
> test/Other/constant-fold-gep.ll | 20 ++++++++++++++++++++
> 2 files changed, 42 insertions(+), 13 deletions(-)
>
> diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
> index a5a9d9f..bf93d4f 100644
> --- a/lib/IR/ConstantFold.cpp
> +++ b/lib/IR/ConstantFold.cpp
> @@ -1971,21 +1971,30 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
> }
> }
>
> - // Implement folding of:
> - // i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
> - // i64 0, i64 0)
> - // To: i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
> + // Attempt to fold casts to the same type away. For example, folding:
> //
> + // i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
> + // i64 0, i64 0)
> + // into:
> + //
> + // i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
> + //
> + // Don't fold if the cast is changing address spaces.
> if (CE->isCast() && Idxs.size() > 1 && Idx0->isNullValue()) {
> - if (PointerType *SPT =
> - dyn_cast<PointerType>(CE->getOperand(0)->getType()))
> - if (ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
> - if (ArrayType *CAT =
> - dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
> - if (CAT->getElementType() == SAT->getElementType())
> - return
> - ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
> - Idxs, inBounds);
> + PointerType *SrcPtrTy =
> + dyn_cast<PointerType>(CE->getOperand(0)->getType());
> + PointerType *DstPtrTy = dyn_cast<PointerType>(CE->getType());
> + if (SrcPtrTy && DstPtrTy) {
> + ArrayType *SrcArrayTy =
> + dyn_cast<ArrayType>(SrcPtrTy->getElementType());
> + ArrayType *DstArrayTy =
> + dyn_cast<ArrayType>(DstPtrTy->getElementType());
> + if (SrcArrayTy && DstArrayTy
> + && SrcArrayTy->getElementType() == DstArrayTy->getElementType()
> + && SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
> + return ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
> + Idxs, inBounds);
> + }
> }
> }
>
> diff --git a/test/Other/constant-fold-gep.ll b/test/Other/constant-fold-gep.ll
> index 0224e9f..44b6628 100644
> --- a/test/Other/constant-fold-gep.ll
> +++ b/test/Other/constant-fold-gep.ll
> @@ -447,4 +447,24 @@ define i32* @fZ() nounwind {
> ret i32* %t
> }
>
> +; PR15262 - Check GEP folding with casts between address spaces.
> +
> + at p0 = global [4 x i8] zeroinitializer, align 1
> + at p12 = addrspace(12) global [4 x i8] zeroinitializer, align 1
> +
> +define i8* @different_addrspace() nounwind noinline {
> +; OPT: different_addrspace
> + %p = getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*),
> + i32 2
> + ret i8* %p
> +; OPT: ret i8* getelementptr (i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*), i32 2)
> +}
> +
> +define i8* @same_addrspace() nounwind noinline {
> +; OPT: same_addrspace
> + %p = getelementptr inbounds i8* bitcast ([4 x i8] * @p0 to i8*), i32 2
> + ret i8* %p
> +; OPT: ret i8* getelementptr inbounds ([4 x i8]* @p0, i32 0, i32 2)
> +}
> +
> ; CHECK: attributes #0 = { nounwind }
>
--
Meador Inge
CodeSourcery / Mentor Embedded
More information about the llvm-commits
mailing list