[llvm] [AMDGPU] Add verification for amdgcn.init.exec.from.input (PR #128172)

Robert Imschweiler via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 21 12:01:30 PST 2025


https://github.com/ro-i updated https://github.com/llvm/llvm-project/pull/128172

>From dda8be4f0c7229d670e7e5e3058b28d7eebfc59a Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 21 Feb 2025 07:05:04 -0600
Subject: [PATCH 1/5] [AMDGPU] Add verification for amdgcn.init.exec.from.input

Check that the input register is an inreg argument to the parent
function. (See the comment in `IntrinsicsAMDGPU.td`.)

This LLVM defect was identified via the AMD Fuzzing project.
---
 llvm/lib/IR/Verifier.cpp                      | 15 +++++++++++
 .../intrinsic-amdgpu-init-exec-from-input.ll  | 27 +++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8432779c107de..55923fd56a109 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -6369,6 +6369,21 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
           "VGPR arguments must not have the `inreg` attribute", &Call);
     break;
   }
+  case Intrinsic::amdgcn_init_exec_from_input: {
+    const Value *InputVal = Call.getOperand(0);
+    bool InRegArgFound = false;
+    for (const Argument &Arg : Call.getCaller()->args()) {
+      if (Arg.hasInRegAttr() && &Arg == InputVal) {
+        InRegArgFound = true;
+        break;
+      }
+    }
+    Check(InRegArgFound,
+          "only inreg arguments to the parent function are valid as inputs to "
+          "this intrinsic",
+          &Call);
+    break;
+  }
   case Intrinsic::amdgcn_set_inactive_chain_arg: {
     auto CallerCC = Call.getCaller()->getCallingConv();
     switch (CallerCC) {
diff --git a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
new file mode 100644
index 0000000000000..5e4a6638dc170
--- /dev/null
+++ b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
@@ -0,0 +1,27 @@
+; RUN: sed -e '/^; MARK$/,$d' %s | not llc -mtriple=amdgcn -mcpu=gfx942 2>&1 | FileCheck %s
+; RUN: sed -e '1,/^; MARK$/d' %s | llc -mtriple=amdgcn -mcpu=gfx942 -filetype=null
+
+; Function Attrs: convergent nocallback nofree nounwind willreturn
+declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
+attributes #0 = { convergent nocallback nofree nounwind willreturn }
+
+; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
+; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 0, i32 0)
+define amdgpu_ps void @init_exec_from_input_fail_immarg(i32 inreg %a, i32 %b) {
+  call void @llvm.amdgcn.init.exec.from.input(i32 0, i32 0)
+  ret void
+}
+
+; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
+; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
+define amdgpu_ps void @init_exec_from_input_fail_not_inreg(i32 inreg %a, i32 %b) {
+  call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
+  ret void
+}
+
+; MARK
+
+define amdgpu_ps void @init_exec_from_input_success(i32 inreg %a, i32 %b) {
+  call void @llvm.amdgcn.init.exec.from.input(i32 %a, i32 0)
+  ret void
+}

>From c6f3b88f44f1c364282b8836c09f12ebf8dbe7c7 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 21 Feb 2025 08:42:07 -0600
Subject: [PATCH 2/5] implement feedback

---
 llvm/lib/IR/Verifier.cpp                              | 11 ++---------
 .../AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll   | 10 +---------
 2 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 55923fd56a109..a19de550d092a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -6370,15 +6370,8 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     break;
   }
   case Intrinsic::amdgcn_init_exec_from_input: {
-    const Value *InputVal = Call.getOperand(0);
-    bool InRegArgFound = false;
-    for (const Argument &Arg : Call.getCaller()->args()) {
-      if (Arg.hasInRegAttr() && &Arg == InputVal) {
-        InRegArgFound = true;
-        break;
-      }
-    }
-    Check(InRegArgFound,
+    const Argument *Arg = dyn_cast<Argument>(Call.getOperand(0));
+    Check(Arg && Arg->hasInRegAttr(),
           "only inreg arguments to the parent function are valid as inputs to "
           "this intrinsic",
           &Call);
diff --git a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
index 5e4a6638dc170..cea12cdae9498 100644
--- a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
+++ b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
@@ -1,5 +1,4 @@
-; RUN: sed -e '/^; MARK$/,$d' %s | not llc -mtriple=amdgcn -mcpu=gfx942 2>&1 | FileCheck %s
-; RUN: sed -e '1,/^; MARK$/d' %s | llc -mtriple=amdgcn -mcpu=gfx942 -filetype=null
+; RUN: not llvm-as -o /dev/null 2>&1 %s | FileCheck %s
 
 ; Function Attrs: convergent nocallback nofree nounwind willreturn
 declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
@@ -18,10 +17,3 @@ define amdgpu_ps void @init_exec_from_input_fail_not_inreg(i32 inreg %a, i32 %b)
   call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
   ret void
 }
-
-; MARK
-
-define amdgpu_ps void @init_exec_from_input_success(i32 inreg %a, i32 %b) {
-  call void @llvm.amdgcn.init.exec.from.input(i32 %a, i32 0)
-  ret void
-}

>From aa34d1e661c27af2d293ab7609f246279d054be9 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 21 Feb 2025 09:17:06 -0600
Subject: [PATCH 3/5] implement feedback

---
 .../AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll    | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
index cea12cdae9498..cd2773d68e936 100644
--- a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
+++ b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
@@ -1,4 +1,4 @@
-; RUN: not llvm-as -o /dev/null 2>&1 %s | FileCheck %s
+; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s
 
 ; Function Attrs: convergent nocallback nofree nounwind willreturn
 declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
@@ -17,3 +17,11 @@ define amdgpu_ps void @init_exec_from_input_fail_not_inreg(i32 inreg %a, i32 %b)
   call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
   ret void
 }
+
+; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
+; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 %c, i32 0)
+define amdgpu_ps void @init_exec_from_input_fail_constant(i32 inreg %a, i32 %b) {
+  %c = add i32 %a, %b
+  call void @llvm.amdgcn.init.exec.from.input(i32 %c, i32 0)
+  ret void
+}

>From 7d2779ee3af41c36238d315bcccfd5800b85fa62 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 21 Feb 2025 09:34:20 -0600
Subject: [PATCH 4/5] implement feedback

---
 .../AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll         | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
index cd2773d68e936..3a619f6ea13af 100644
--- a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
+++ b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
@@ -6,21 +6,21 @@ attributes #0 = { convergent nocallback nofree nounwind willreturn }
 
 ; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
 ; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 0, i32 0)
-define amdgpu_ps void @init_exec_from_input_fail_immarg(i32 inreg %a, i32 %b) {
+define void @init_exec_from_input_fail_immarg(i32 inreg %a, i32 %b) {
   call void @llvm.amdgcn.init.exec.from.input(i32 0, i32 0)
   ret void
 }
 
 ; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
 ; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
-define amdgpu_ps void @init_exec_from_input_fail_not_inreg(i32 inreg %a, i32 %b) {
+define void @init_exec_from_input_fail_not_inreg(i32 inreg %a, i32 %b) {
   call void @llvm.amdgcn.init.exec.from.input(i32 %b, i32 0)
   ret void
 }
 
 ; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
 ; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 %c, i32 0)
-define amdgpu_ps void @init_exec_from_input_fail_constant(i32 inreg %a, i32 %b) {
+define void @init_exec_from_input_fail_constant(i32 inreg %a, i32 %b) {
   %c = add i32 %a, %b
   call void @llvm.amdgcn.init.exec.from.input(i32 %c, i32 0)
   ret void

>From f291bc6a35181ff176296af81aa2ef6949e69977 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 21 Feb 2025 14:01:15 -0600
Subject: [PATCH 5/5] implement feedback

---
 .../Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll  | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
index 3a619f6ea13af..0c35ed13a5a15 100644
--- a/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
+++ b/llvm/test/Verifier/AMDGPU/intrinsic-amdgpu-init-exec-from-input.ll
@@ -1,8 +1,6 @@
 ; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s
 
-; Function Attrs: convergent nocallback nofree nounwind willreturn
-declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
-attributes #0 = { convergent nocallback nofree nounwind willreturn }
+declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg)
 
 ; CHECK: only inreg arguments to the parent function are valid as inputs to this intrinsic
 ; CHECK-NEXT: call void @llvm.amdgcn.init.exec.from.input(i32 0, i32 0)



More information about the llvm-commits mailing list