From d9904414c214ef94c480ce1cd76ebde0558403a0 Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Tue, 31 Jul 2018 15:53:03 +0000 Subject: [PATCH] Fix InstCombine address space assert Workaround bug where the InstCombine pass was asserting on the IR added in lit test, where we have a bitcast instruction after a GEP from an addrspace cast. The second bitcast in the test was getting combined into `bitcast <16 x i32>* %0 to <16 x i32> addrspace(3)*`, which looks like it should be an addrspace cast instruction instead. Otherwise if control flow is allowed to continue as it is now we create a GEP instruction ` = getelementptr inbounds <16 x i32>, <16 x i32>* %0, i32 0`. However because the type of this instruction doesn't match the address space we hit an assert when replacing the bitcast with that GEP. ``` void llvm::Value::doRAUW(llvm::Value*, bool): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed. ``` Differential Revision: https://reviews.llvm.org/D50058 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338395 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCasts.cpp | 6 ++++++ test/Transforms/InstCombine/gep-addrspace.ll | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index e8ea7396a96..fd59c3a7c0c 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2243,6 +2243,12 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { Type *DstElTy = DstPTy->getElementType(); Type *SrcElTy = SrcPTy->getElementType(); + // Casting pointers between the same type, but with different address spaces + // is an addrspace cast rather than a bitcast. + if ((DstElTy == SrcElTy) && + (DstPTy->getAddressSpace() != SrcPTy->getAddressSpace())) + return new AddrSpaceCastInst(Src, DestTy); + // If we are casting a alloca to a pointer to a type of the same // size, rewrite the allocation instruction to allocate the "right" type. // There is no need to modify malloc calls because it is their bitcast that diff --git a/test/Transforms/InstCombine/gep-addrspace.ll b/test/Transforms/InstCombine/gep-addrspace.ll index 1cd1e46251d..fadf2ae6bf6 100644 --- a/test/Transforms/InstCombine/gep-addrspace.ll +++ b/test/Transforms/InstCombine/gep-addrspace.ll @@ -65,3 +65,22 @@ define { i8, i8 } @inbounds_after_addrspacecast() { ret { i8, i8 } %insert } + +declare spir_func <16 x i32> @my_extern_func() + +; check that a bitcast is not generated when we need an addrspace cast +define void @bitcast_after_gep(<16 x i32>* %t0) { +; CHECK-LABEL: @bitcast_after_gep( +; CHECK-NEXT: [[T4:%.*]] = addrspacecast <16 x i32>* [[T0:%.*]] to <16 x i32> addrspace(3)* +; CHECK-NEXT: [[CALL:%.*]] = call spir_func <16 x i32> @my_extern_func() +; CHECK-NEXT: store <16 x i32> [[CALL]], <16 x i32> addrspace(3)* [[T4]], align 64 +; CHECK-NEXT: ret void +; + %t1 = bitcast <16 x i32>* %t0 to [16 x i32]* + %t2 = addrspacecast [16 x i32]* %t1 to [16 x i32] addrspace(3)* + %t3 = getelementptr inbounds [16 x i32], [16 x i32] addrspace(3)* %t2, i64 0, i64 0 + %t4 = bitcast i32 addrspace(3)* %t3 to <16 x i32> addrspace(3)* + %call = call spir_func <16 x i32> @my_extern_func() + store <16 x i32> %call, <16 x i32> addrspace(3)* %t4 + ret void +} -- 2.40.0