[llvm] [SPIR-V] Propagate intrinsic param attributes to generated helper functions (PR #206061)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 05:03:32 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/206061

>From d61b502d58fa97384add989049ff968abaf20fde Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 26 Jun 2026 15:37:33 +0200
Subject: [PATCH 1/2] [SPIR-V] Propagate intrinsic param attributes to
 generated helper functions

---
 llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp    |  5 ++++-
 .../CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll  | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 04cce9915e0da..52a7fae059b1c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -145,7 +145,6 @@ static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic,
     Intrinsic->setCalledFunction(F);
     return true;
   }
-  // TODO copy arguments attributes: nocapture writeonly.
   FunctionCallee FC =
       M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
   auto IntrinsicID = Intrinsic->getIntrinsicID();
@@ -154,6 +153,10 @@ static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic,
   F = dyn_cast<Function>(FC.getCallee());
   assert(F && "Callee must be a function");
 
+  AttributeList Attrs = Intrinsic->getAttributes();
+  for (unsigned I = 0, E = Intrinsic->arg_size(); I != E; ++I)
+    F->addParamAttrs(I, AttrBuilder(F->getContext(), Attrs.getParamAttrs(I)));
+
   switch (IntrinsicID) {
   case Intrinsic::memset: {
     auto *MSI = static_cast<MemSetInst *>(Intrinsic);
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
index 2d022f5d9b17e..91ba08d682015 100644
--- a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
@@ -25,6 +25,14 @@ define i32 @fshr_i32(i32 %a, i32 %b, i32 %c) {
   ret i32 %r
 }
 
+; Parameter attributes of the original intrinsic are propagated
+; to the generated SPIR-V.
+define void @memset_attrs(ptr %p, i8 %v, i32 %n) {
+; CHECK-LABEL: define void @memset_attrs(
+  call void @llvm.memset.p0.i32(ptr nocapture writeonly %p, i8 %v, i32 %n, i1 false)
+  ret void
+}
+
 ; The bswap helper is materialized with the standard shift/mask/or unrolling.
 ; CHECK-LABEL: define i32 @spirv.llvm_bswap_i32(i32 %0)
 ; CHECK-DAG:   shl i32 %0, 24
@@ -54,6 +62,12 @@ define i32 @fshr_i32(i32 %a, i32 %b, i32 %c) {
 ; CHECK:       %[[#OR:]]  = or i32 %[[#A]], %[[#B]]
 ; CHECK:       ret i32 %[[#OR]]
 
+; The memset helper definition carries the destination attributes propagated
+; from the original @llvm.memset intrinsic.
+; CHECK-LABEL: define void @spirv.llvm_memset_p0_i32(
+; CHECK-SAME:    ptr writeonly {{.*}}captures(none) %dest,
+
+declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1)
 declare i32 @llvm.bswap.i32(i32)
 declare i32 @llvm.fshl.i32(i32, i32, i32)
 declare i32 @llvm.fshr.i32(i32, i32, i32)

>From f75560ad32174ecfc1292d561bcd0d08fa84eb96 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 29 Jun 2026 14:01:30 +0200
Subject: [PATCH 2/2] Address review comments

---
 llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 52a7fae059b1c..2b07f23e717d5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -149,13 +149,8 @@ static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic,
       M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
   auto IntrinsicID = Intrinsic->getIntrinsicID();
   Intrinsic->setCalledFunction(FC);
-
-  F = dyn_cast<Function>(FC.getCallee());
-  assert(F && "Callee must be a function");
-
-  AttributeList Attrs = Intrinsic->getAttributes();
-  for (unsigned I = 0, E = Intrinsic->arg_size(); I != E; ++I)
-    F->addParamAttrs(I, AttrBuilder(F->getContext(), Attrs.getParamAttrs(I)));
+  F = cast<Function>(FC.getCallee());
+  F->setAttributes(Intrinsic->getAttributes());
 
   switch (IntrinsicID) {
   case Intrinsic::memset: {



More information about the llvm-commits mailing list