[PATCH] [InstCombine] Don't fold bitcast into store if it would need addrspacecast
Matt Arsenault
Matthew.Arsenault at amd.com
Wed Mar 19 10:40:21 PDT 2014
On 03/19/2014 06:11 AM, Richard Osborne wrote:
> Previously the code didn't check if the before and after types for the
> store were pointers to different address spaces. This resulted in
> instcombine using a bitcast to convert between pointers to different
> address spaces, causing an assertion due to the invalid cast.
>
> It is not be appropriate to use addrspacecast this case because it is
> not guaranteed to be a no-op cast. Instead bail out and do not do the
> transformation.
>
> http://llvm-reviews.chandlerc.com/D3117
>
> Files:
> lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
> test/Transforms/InstCombine/bitcast-store.ll
>
> Index: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
> ===================================================================
> --- lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
> +++ lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
> @@ -517,27 +517,35 @@
> IC.getDataLayout()->getTypeSizeInBits(DestPTy))
> return 0;
>
> + // Don't introduce casts between pointers to different address spaces. We
> + // can't use the addrspacecast instruction in this case since, depending on
> + // the target, addrspacecast may not be a no-op cast.
> + if (SrcPTy->isPointerTy() && DestPTy->isPointerTy() &&
> + cast<PointerType>(SrcPTy)->getAddressSpace() !=
> + cast<PointerType>(DestPTy)->getAddressSpace())
> + return 0;
> +
There is getPointerAddressSpace() instead of needing to use the cast,
but I think it's cleaner to just use dyn_cast instead of checking if
it's a pointer and then casting to pointer.
Right above here is a check leftover from when bitcast was allowed if
the pointers were the same size. You should update that and replace it
with this.
> // Okay, we are casting from one integer or pointer type to another of
> // the same size. Instead of casting the pointer before
> // the store, cast the value to be stored.
> Value *NewCast;
> - Value *SIOp0 = SI.getOperand(0);
> Instruction::CastOps opcode = Instruction::BitCast;
> - Type* CastSrcTy = SIOp0->getType();
> + Type* CastSrcTy = DestPTy;
> Type* CastDstTy = SrcPTy;
> if (CastDstTy->isPointerTy()) {
> if (CastSrcTy->isIntegerTy())
> opcode = Instruction::IntToPtr;
> } else if (CastDstTy->isIntegerTy()) {
> - if (SIOp0->getType()->isPointerTy())
> + if (CastSrcTy->isPointerTy())
> opcode = Instruction::PtrToInt;
> }
>
> // SIOp0 is a pointer to aggregate and this is a store to the first field,
> // emit a GEP to index into its first field.
> if (!NewGEPIndices.empty())
> CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices);
>
> + Value *SIOp0 = SI.getOperand(0);
> NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy,
> SIOp0->getName()+".c");
> SI.setOperand(0, NewCast);
> Index: test/Transforms/InstCombine/bitcast-store.ll
> ===================================================================
> --- test/Transforms/InstCombine/bitcast-store.ll
> +++ test/Transforms/InstCombine/bitcast-store.ll
> @@ -3,19 +3,33 @@
> ; Instcombine should preserve metadata and alignment while
> ; folding a bitcast into a store.
>
> -; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0
> -
> target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
>
> %struct.A = type { i32 (...)** }
>
> @G = external constant [5 x i8*]
>
> +; CHECK-LABEL: @foo
> +; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0
> define void @foo(%struct.A* %a) nounwind {
> entry:
> %0 = bitcast %struct.A* %a to i8***
> store i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2), i8*** %0, align 16, !tag !0
> ret void
> }
>
> !0 = metadata !{metadata !"hello"}
> +
> +; Check instcombine doesn't try and fold the following bitcast into the store.
> +; This transformation would not be safe since we would need to use addrspacecast
> +; and addrspacecast is not guaranteed to be a no-op cast.
> +
> +; CHECK-LABEL: @bar
> +; CHECK: %cast = bitcast i8** %b to i8 addrspace(1)**
> +; CHECK: store i8 addrspace(1)* %a, i8 addrspace(1)** %cast
> +define void @bar(i8 addrspace(1)* %a, i8** %b) nounwind {
> +entry:
> + %cast = bitcast i8** %b to i8 addrspace(1)**
> + store i8 addrspace(1)* %a, i8 addrspace(1)** %cast
> + ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140319/1214523e/attachment.html>
More information about the llvm-commits
mailing list