Skip to content

Conversation

Keenuts
Copy link
Contributor

@Keenuts Keenuts commented Apr 10, 2025

Those instructions require the Kernel capability, which is not available when targeting Vulkan.

Those instructions require the Kernel capability, which is not
available when targeting Vulkan.
@llvmbot
Copy link
Member

llvmbot commented Apr 10, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Nathan Gauër (Keenuts)

Changes

Those instructions require the Kernel capability, which is not available when targeting Vulkan.


Full diff: https://github.com/llvm/llvm-project/pull/135166.diff

2 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp (+11-7)
  • (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll (+47-24)
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 628688d83a314..bd039871dec44 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -380,6 +380,7 @@ static bool toSpvOverloadedIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID,
 // or calls to proper generated functions. Returns True if F was modified.
 bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
   bool Changed = false;
+  const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
   for (BasicBlock &BB : *F) {
     for (Instruction &I : BB) {
       auto Call = dyn_cast<CallInst>(&I);
@@ -400,19 +401,22 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
         Changed = true;
         break;
       case Intrinsic::assume:
-      case Intrinsic::expect: {
-        const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
+      case Intrinsic::expect:
         if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
           lowerExpectAssume(II);
         Changed = true;
-      } break;
+        break;
       case Intrinsic::lifetime_start:
-        Changed |= toSpvOverloadedIntrinsic(
-            II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1});
+        if (STI.isOpenCLEnv()) {
+          Changed |= toSpvOverloadedIntrinsic(
+              II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1});
+        }
         break;
       case Intrinsic::lifetime_end:
-        Changed |= toSpvOverloadedIntrinsic(
-            II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1});
+        if (STI.isOpenCLEnv()) {
+          Changed |= toSpvOverloadedIntrinsic(
+              II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1});
+        }
         break;
       case Intrinsic::ptr_annotation:
         lowerPtrAnnotation(II);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
index 45683585d6514..2d2ffe36d97bd 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll
@@ -1,24 +1,35 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CL
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CL
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan1.3-compute %s -o - | FileCheck %s --check-prefixes=CHECK,VK
+
+; FIXME(135165) Alignment capability emitted for Vulkan.
+; FIXME: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan1.3-compute %s -o - -filetype=obj | spirv-val %}
+
 ; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
 ; CHECK-DAG: %[[#PtrChar:]] = OpTypePointer Function %[[#Char]]
 
 %tprange = type { %tparray }
 %tparray = type { [2 x i64] }
 
-; CHECK: OpFunction
-; CHECK: %[[#FooVar:]] = OpVariable
-; CHECK: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
-; CHECK: OpLifetimeStart %[[#Casted1]], 72
-; CHECK: OpCopyMemorySized
-; CHECK: OpBitcast
-; CHECK: OpInBoundsPtrAccessChain
-; CHECK: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
-; CHECK: OpLifetimeStop %[[#Casted2]], 72
+; CL:      OpFunction
+; CL:      %[[#FooVar:]] = OpVariable
+; CL-NEXT: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
+; CL-NEXT: OpLifetimeStart %[[#Casted1]], 72
+; CL-NEXT: OpCopyMemorySized
+; CL-NEXT: OpBitcast
+; CL-NEXT: OpInBoundsPtrAccessChain
+; CL-NEXT: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
+; CL-NEXT: OpLifetimeStop %[[#Casted2]], 72
+
+; VK:      OpFunction
+; VK:      %[[#FooVar:]] = OpVariable
+; VK-NEXT: OpCopyMemorySized
+; VK-NEXT: OpInBoundsAccessChain
+; VK-NEXT: OpReturn
 define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
   %RoundedRangeKernel = alloca %tprange, align 8
   call void @llvm.lifetime.start.p0(i64 72, ptr nonnull %RoundedRangeKernel)
@@ -28,13 +39,19 @@ define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange)
   ret void
 }
 
-; CHECK: OpFunction
-; CHECK: %[[#BarVar:]] = OpVariable
-; CHECK: OpLifetimeStart %[[#BarVar]], 0
-; CHECK: OpCopyMemorySized
-; CHECK: OpBitcast
-; CHECK: OpInBoundsPtrAccessChain
-; CHECK: OpLifetimeStop %[[#BarVar]], 0
+; CL: OpFunction
+; CL: %[[#BarVar:]] = OpVariable
+; CL-NEXT: OpLifetimeStart %[[#BarVar]], 0
+; CL-NEXT: OpCopyMemorySized
+; CL-NEXT: OpBitcast
+; CL-NEXT: OpInBoundsPtrAccessChain
+; CL-NEXT: OpLifetimeStop %[[#BarVar]], 0
+
+; VK:      OpFunction
+; VK:      %[[#BarVar:]] = OpVariable
+; VK-NEXT: OpCopyMemorySized
+; VK-NEXT: OpInBoundsAccessChain
+; VK-NEXT: OpReturn
 define spir_func void @bar(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
   %RoundedRangeKernel = alloca %tprange, align 8
   call void @llvm.lifetime.start.p0(i64 -1, ptr nonnull %RoundedRangeKernel)
@@ -44,12 +61,18 @@ define spir_func void @bar(ptr noundef byval(%tprange) align 8 %_arg_UserRange)
   ret void
 }
 
-; CHECK: OpFunction
-; CHECK: %[[#TestVar:]] = OpVariable
-; CHECK: OpLifetimeStart %[[#TestVar]], 1
-; CHECK: OpCopyMemorySized
-; CHECK: OpInBoundsPtrAccessChain
-; CHECK: OpLifetimeStop %[[#TestVar]], 1
+; CL: OpFunction
+; CL: %[[#TestVar:]] = OpVariable
+; CL-NEXT: OpLifetimeStart %[[#TestVar]], 1
+; CL-NEXT: OpCopyMemorySized
+; CL-NEXT: OpInBoundsPtrAccessChain
+; CL-NEXT: OpLifetimeStop %[[#TestVar]], 1
+
+; VK:      OpFunction
+; VK:      %[[#Test:]] = OpVariable
+; VK-NEXT: OpCopyMemorySized
+; VK-NEXT: OpInBoundsAccessChain
+; VK-NEXT: OpReturn
 define spir_func void @test(ptr noundef align 8 %_arg) {
   %var = alloca i8, align 8
   call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %var)

@Keenuts Keenuts merged commit 476c1c5 into llvm:main Apr 11, 2025
12 checks passed
@Keenuts Keenuts deleted the lifetime-emit branch April 11, 2025 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants