[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