diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index 0c0c3c46207d2..6f753b1aeae54 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -1877,6 +1877,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, SPIRVLifetimeStart *LTStart = static_cast(BV); IRBuilder<> Builder(BB); auto *Var = transValue(LTStart->getObject(), F, BB); + Var = Var->stripPointerCasts(); CallInst *Start = Builder.CreateLifetimeStart(Var); return mapValue(BV, Start); } @@ -1885,6 +1886,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, SPIRVLifetimeStop *LTStop = static_cast(BV); IRBuilder<> Builder(BB); auto *Var = transValue(LTStop->getObject(), F, BB); + Var = Var->stripPointerCasts(); for (const auto &I : Var->users()) if (auto *II = getLifetimeStartIntrinsic(dyn_cast(I))) return mapValue(BV, Builder.CreateLifetimeEnd(II->getOperand(0))); diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index 668230c2c819d..d4a7eb23716c1 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -4872,8 +4872,16 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, unsigned PtrAS = cast(LLVMPtrOp->getType())->getAddressSpace(); auto *PtrOp = transValue(LLVMPtrOp, BB); - if (PtrAS == SPIRAS_Private) + // INTEL_CUSTOMIZATION begin + // Workaround to make older versions of SPIRVReader working with new + // rules of LLVM lifetime intrinsics. + // TODO: to remove the W/A. + if (PtrAS == SPIRAS_Private) { + auto *Int8PtrTy = + transPointerType(Type::getInt8Ty(M->getContext()), SPIRAS_Private); + PtrOp = BM->addUnaryInst(OpBitcast, Int8PtrTy, PtrOp, BB); return BM->addLifetimeInst(OC, PtrOp, Size, BB); + } // If pointer address space is Generic - use original allocation. BM->getErrorLog().checkError( PtrAS == SPIRAS_Generic, SPIRVEC_InvalidInstruction, II, @@ -4881,7 +4889,11 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, if (PtrOp->getOpCode() == OpPtrCastToGeneric) { auto *UI = static_cast(PtrOp); PtrOp = UI->getOperand(0); + auto *Int8PtrTy = + transPointerType(Type::getInt8Ty(M->getContext()), SPIRAS_Private); + PtrOp = BM->addUnaryInst(OpBitcast, Int8PtrTy, PtrOp, BB); } + // INTEL_CUSTOMIZATION end return BM->addLifetimeInst(OC, PtrOp, Size, BB); } // We don't want to mix translation of regular code and debug info, because diff --git a/llvm-spirv/test/llvm-intrinsics/lifetime.ll b/llvm-spirv/test/llvm-intrinsics/lifetime.ll index 03a2492c7e0b4..598bdecce2964 100644 --- a/llvm-spirv/test/llvm-intrinsics/lifetime.ll +++ b/llvm-spirv/test/llvm-intrinsics/lifetime.ll @@ -12,26 +12,35 @@ ; RUN: llvm-spirv -r %t.spv -o %t.spv.bc ; RUN: llvm-dis < %t.spv.bc | FileCheck %s --check-prefix=CHECK-LLVM -; CHECK-SPIRV-DAG: EntryPoint [[#]] [[#SimpleF:]] "lifetime_simple" -; CHECK-SPIRV-DAG: EntryPoint [[#]] [[#SizedF:]] "lifetime_sized" -; CHECK-SPIRV-DAG: EntryPoint [[#]] [[#GenericF:]] "lifetime_generic" +; CHECK-SPIRV-DAG: Name [[#SimpleF:]] "lifetime_simple" +; CHECK-SPIRV-DAG: Name [[#SizedF:]] "lifetime_sized" +; CHECK-SPIRV-DAG: Name [[#GenericF:]] "lifetime_generic" ; CHECK-SPIRV-DAG: TypeStruct [[#StructTy:]] [[#]] ; CHECK-SPIRV-DAG: TypePointer [[#PrivatePtrTy:]] 7 [[#StructTy]] +; INTEL_CUSTOMIZATION: ; CHECK-SPIRV: Function [[#]] [[#SimpleF:]] -; CHECK-SPIRV: LifetimeStart [[#Tmp:]] 0 -; CHECK-SPIRV: LifetimeStop [[#Tmp]] 0 +; CHECK-SPIRV: Variable [[#]] [[#Var:]] +; CHECK-SPIRV: Bitcast [[#]] [[#Cast1:]] [[#Var]] +; CHECK-SPIRV: LifetimeStart [[#Cast1]] 4 +; CHECK-SPIRV: Bitcast [[#]] [[#Cast2:]] [[#Var]] +; CHECK-SPIRV: LifetimeStop [[#Cast2]] 4 ; CHECK-SPIRV: Function [[#]] [[#SizedF:]] -; CHECK-SPIRV: LifetimeStart [[#Tmp:]] 1 -; CHECK-SPIRV: LifetimeStop [[#Tmp]] 1 +; CHECK-SPIRV: Variable [[#]] [[#Var:]] +; CHECK-SPIRV: Bitcast [[#]] [[#Cast1:]] [[#Var]] +; CHECK-SPIRV: LifetimeStart [[#Cast1]] 1 +; CHECK-SPIRV: Bitcast [[#]] [[#Cast2:]] [[#Var]] +; CHECK-SPIRV: LifetimeStop [[#Cast2]] 1 ; CHECK-SPIRV: Function [[#]] [[#GenericF:]] ; CHECK-SPIRV: Variable [[#PrivatePtrTy]] [[#Var:]] 7 -; CHECK-SPIRV: PtrCastToGeneric [[#]] [[#Cast1:]] [[#Var]] -; CHECK-SPIRV: LifetimeStart [[#Var]] 0 -; CHECK-SPIRV: FunctionCall [[#]] [[#]] [[#]] [[#Cast1]] -; CHECK-SPIRV: LifetimeStop [[#Var]] 0 +; CHECK-SPIRV: PtrCastToGeneric [[#]] [[#ASCast:]] [[#Var]] +; CHECK-SPIRV: Bitcast [[#]] [[#Cast1:]] [[#Var]] +; CHECK-SPIRV: LifetimeStart [[#Cast1]] 1 +; CHECK-SPIRV: FunctionCall [[#]] [[#]] [[#]] [[#ASCast]] +; CHECK-SPIRV: Bitcast [[#]] [[#Cast2:]] [[#Var]] +; CHECK-SPIRV: LifetimeStop [[#Cast2]] 1 ; CHECK-LLVM-LABEL: lifetime_simple ; CHECK-LLVM: %[[#Alloca:]] = alloca i32 @@ -49,6 +58,7 @@ ; CHECK-LLVM: call void @llvm.lifetime.start.p0(ptr %[[#Alloca]]) ; CHECK-LLVM: call spir_func void @boo(ptr addrspace(4) %[[#Cast1]]) ; CHECK-LLVM: call void @llvm.lifetime.end.p0(ptr %[[#Alloca]]) +; INTEL_CUSTOMIZATION end ; ModuleID = 'main' target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" @@ -57,44 +67,43 @@ target triple = "spir64-unknown-unknown" %class.anon = type { i8 } ; Function Attrs: nounwind -define spir_kernel void @lifetime_simple(i32 addrspace(1)* captures(none) %res, i32 addrspace(1)* captures(none) %lhs, i32 addrspace(1)* captures(none) %rhs) #0 !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_base_type !5 !kernel_arg_type_qual !4 { +define spir_kernel void @lifetime_simple(ptr addrspace(1) captures(none) %res, ptr addrspace(1) captures(none) %lhs, ptr addrspace(1) captures(none) %rhs) #0 !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_base_type !5 !kernel_arg_type_qual !4 { %1 = alloca i32 %2 = call spir_func i64 @_Z13get_global_idj(i32 0) #1 %3 = shl i64 %2, 32 %4 = ashr exact i64 %3, 32 - %5 = getelementptr inbounds i32, i32 addrspace(1)* %lhs, i64 %4 - %6 = load i32, i32 addrspace(1)* %5, align 4 - %7 = getelementptr inbounds i32, i32 addrspace(1)* %rhs, i64 %4 + %5 = getelementptr inbounds i32, ptr addrspace(1) %lhs, i64 %4 + %6 = load i32, ptr addrspace(1) %5, align 4 + %7 = getelementptr inbounds i32, ptr addrspace(1) %rhs, i64 %4 %8 = load i32, i32 addrspace(1)* %7, align 4 %9 = sub i32 %6, %8 - %10 = bitcast i32* %1 to i8* - call void @llvm.lifetime.start.p0i8(i64 -1, i8* %10) - store i32 %9, i32* %1 - %11 = load i32, i32* %1 - call void @llvm.lifetime.end.p0i8(i64 -1, i8* %10) - %12 = getelementptr inbounds i32, i32 addrspace(1)* %res, i64 %4 - store i32 %11, i32 addrspace(1)* %12, align 4 + call void @llvm.lifetime.start.p0(ptr %1) + store i32 %9, ptr %1 + %11 = load i32, ptr %1 + call void @llvm.lifetime.end.p0(ptr %1) + %12 = getelementptr inbounds i32, ptr addrspace(1) %res, i64 %4 + store i32 %11, ptr addrspace(1) %12, align 4 ret void } define spir_kernel void @lifetime_sized() #0 !kernel_arg_addr_space !8 !kernel_arg_access_qual !8 !kernel_arg_type !8 !kernel_arg_base_type !8 !kernel_arg_type_qual !8 { entry: %0 = alloca i8, align 1 - call void @llvm.lifetime.start.p0i8(i64 1, i8* %0) #0 - call spir_func void @goo(i8* %0) - call void @llvm.lifetime.end.p0i8(i64 1, i8* %0) #0 + call void @llvm.lifetime.start.p0(ptr %0) #0 + call spir_func void @goo(ptr %0) + call void @llvm.lifetime.end.p0(ptr %0) #0 ret void } -declare spir_func void @foo(%class.anon* %this) #0 +declare spir_func void @foo(ptr %this) #0 -declare spir_func void @goo(i8* %this) #0 +declare spir_func void @goo(ptr %this) #0 ; Function Attrs: nounwind -declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* captures(none)) #0 +declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 ; Function Attrs: nounwind -declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* captures(none)) #0 +declare void @llvm.lifetime.end.p0(ptr captures(none)) #0 ; Function Attrs: nounwind readnone declare spir_func i64 @_Z13get_global_idj(i32) #1 @@ -102,19 +111,19 @@ declare spir_func i64 @_Z13get_global_idj(i32) #1 define spir_kernel void @lifetime_generic() #0 !kernel_arg_addr_space !8 !kernel_arg_access_qual !8 !kernel_arg_type !8 !kernel_arg_base_type !8 !kernel_arg_type_qual !8 { entry: %0 = alloca %class.anon, align 1, addrspace(4) - call void @llvm.lifetime.start.p4i8(i64 -1, i8 addrspace(4)* %0) #0 - call spir_func void @boo(%class.anon addrspace(4)* %0) - call void @llvm.lifetime.end.p4i8(i64 -1, i8 addrspace(4)* %0) #0 + call void @llvm.lifetime.start.p4(ptr addrspace(4) %0) #0 + call spir_func void @boo(ptr addrspace(4) %0) + call void @llvm.lifetime.end.p4(ptr addrspace(4) %0) #0 ret void } -declare spir_func void @boo(%class.anon addrspace(4)* %this) #0 +declare spir_func void @boo(ptr addrspace(4) %this) #0 ; Function Attrs: nounwind -declare void @llvm.lifetime.start.p4i8(i64 immarg, i8 addrspace(4)* captures(none)) #0 +declare void @llvm.lifetime.start.p4(ptr addrspace(4) captures(none)) #0 ; Function Attrs: nounwind -declare void @llvm.lifetime.end.p4i8(i64 immarg, i8 addrspace(4)* captures(none)) #0 +declare void @llvm.lifetime.end.p4(ptr addrspace(4) captures(none)) #0 attributes #0 = { nounwind } diff --git a/llvm-spirv/test/llvm-intrinsics/memmove.ll b/llvm-spirv/test/llvm-intrinsics/memmove.ll index 0a9a8e502d83a..d5564bd082e5a 100644 --- a/llvm-spirv/test/llvm-intrinsics/memmove.ll +++ b/llvm-spirv/test/llvm-intrinsics/memmove.ll @@ -33,10 +33,12 @@ ; CHECK-SPIRV: Variable [[#]] [[#MEM:]] ; CHECK-SPIRV: Bitcast [[#]] [[#I8_ARG_IN:]] [[#ARG_IN]] ; CHECK-SPIRV: Bitcast [[#]] [[#I8_ARG_OUT:]] [[#ARG_OUT]] -; CHECK-SPIRV: LifetimeStart [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_1:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStart [[#MEM_CAST_1]] ; CHECK-SPIRV: CopyMemorySized [[#MEM]] [[#I8_ARG_IN]] [[#C128]] 2 64 ; CHECK-SPIRV: CopyMemorySized [[#I8_ARG_OUT]] [[#MEM]] [[#C128]] 2 64 -; CHECK-SPIRV: LifetimeStop [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_2:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStop [[#MEM_CAST_2]] ; CHECK-SPIRV-LABEL: [[#]] Function [[#]] ; CHECK-SPIRV: FunctionParameter [[#I8GLOBAL_PTR]] [[#ARG_IN:]] @@ -46,20 +48,24 @@ ; CHECK-SPIRV: Bitcast [[#]] [[#I8_ARG_IN:]] [[#ARG_IN]] ; CHECK-SPIRV: Bitcast [[#]] [[#I8_ARG_OUT_GENERIC:]] [[#ARG_OUT]] ; CHECK-SPIRV: GenericCastToPtr [[#]] [[#I8_ARG_OUT:]] [[#I8_ARG_OUT_GENERIC]] -; CHECK-SPIRV: LifetimeStart [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_1:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStart [[#MEM_CAST_1]] ; CHECK-SPIRV: CopyMemorySized [[#MEM]] [[#I8_ARG_IN]] [[#C68]] 2 64 ; CHECK-SPIRV: CopyMemorySized [[#I8_ARG_OUT]] [[#MEM]] [[#C68]] 2 64 -; CHECK-SPIRV: LifetimeStop [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_2:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStop [[#MEM_CAST_2]] ; CHECK-SPIRV-LABEL: [[#]] Function [[#]] ; CHECK-SPIRV: FunctionParameter [[#]] [[#ARG_IN:]] ; CHECK-SPIRV: FunctionParameter [[#]] [[#ARG_OUT:]] ; ; CHECK-SPIRV: Variable [[#]] [[#MEM:]] -; CHECK-SPIRV: LifetimeStart [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_1:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStart [[#MEM_CAST_1]] ; CHECK-SPIRV: CopyMemorySized [[#MEM]] [[#ARG_IN]] [[#C72]] 0 ; CHECK-SPIRV: CopyMemorySized [[#ARG_OUT]] [[#MEM]] [[#C72]] 0 -; CHECK-SPIRV: LifetimeStop [[#MEM]] +; CHECK-SPIRV: Bitcast [[#]] [[#MEM_CAST_2:]] [[#MEM]] +; CHECK-SPIRV: LifetimeStop [[#MEM_CAST_2]] ; xCHECK-SPIRV-LABEL: [[#]] Function [[#]] ;