[llvm] [IR] Use immarg for preallocated intrinsics (NFC) (PR #155835)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 26 03:51:12 PDT 2025


https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/155835

>From 708c01845a8474943ebf464eba97780043dd9101 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 28 Aug 2025 15:28:59 +0200
Subject: [PATCH 1/2] [IR] Use immarg for preallocated intrinsics (NFC)

Mark the attributes as immarg to indicate that they require a
constant integer. This was previously enforced with a manual
verifier check.
---
 llvm/include/llvm/IR/Intrinsics.td         | 8 ++++++--
 llvm/lib/IR/Verifier.cpp                   | 8 ++------
 llvm/test/Verifier/preallocated-invalid.ll | 2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index dba44e7c3c506..5ca7d24c8aaa3 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -977,8 +977,12 @@ def int_instrprof_mcdc_tvbitmap_update : Intrinsic<[],
                                         [llvm_ptr_ty, llvm_i64_ty,
                                          llvm_i32_ty, llvm_ptr_ty]>;
 
-def int_call_preallocated_setup : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty]>;
-def int_call_preallocated_arg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_i32_ty]>;
+def int_call_preallocated_setup
+    : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty],
+                            [ImmArg<ArgIndex<0>>]>;
+def int_call_preallocated_arg
+    : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_i32_ty],
+                            [ImmArg<ArgIndex<1>>]>;
 def int_call_preallocated_teardown : DefaultAttrsIntrinsic<[], [llvm_token_ty]>;
 
 // This intrinsic is intentionally undocumented and users shouldn't call it;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b2e76cc7a8a90..27e78ecfa9288 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5869,9 +5869,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     break;
   }
   case Intrinsic::call_preallocated_setup: {
-    auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0));
-    Check(NumArgs != nullptr,
-          "llvm.call.preallocated.setup argument must be a constant");
+    auto *NumArgs = cast<ConstantInt>(Call.getArgOperand(0));
     bool FoundCall = false;
     for (User *U : Call.users()) {
       auto *UseCall = dyn_cast<CallBase>(U);
@@ -5879,9 +5877,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
             "Uses of llvm.call.preallocated.setup must be calls");
       Intrinsic::ID IID = UseCall->getIntrinsicID();
       if (IID == Intrinsic::call_preallocated_arg) {
-        auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1));
-        Check(AllocArgIndex != nullptr,
-              "llvm.call.preallocated.alloc arg index must be a constant");
+        auto *AllocArgIndex = cast<ConstantInt>(UseCall->getArgOperand(1));
         auto AllocArgIndexInt = AllocArgIndex->getValue();
         Check(AllocArgIndexInt.sge(0) &&
                   AllocArgIndexInt.slt(NumArgs->getValue()),
diff --git a/llvm/test/Verifier/preallocated-invalid.ll b/llvm/test/Verifier/preallocated-invalid.ll
index 38ed1067c497d..921fa69dcb23b 100644
--- a/llvm/test/Verifier/preallocated-invalid.ll
+++ b/llvm/test/Verifier/preallocated-invalid.ll
@@ -65,7 +65,7 @@ define void @preallocated_one_call() {
     ret void
 }
 
-; CHECK: must be a constant
+; CHECK: immarg operand has non-immediate parameter
 define void @preallocated_setup_constant() {
     %ac = call i32 @blackbox()
     %cs = call token @llvm.call.preallocated.setup(i32 %ac)

>From cd339d8239dca3549da3307b2411b09967540117 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 26 Sep 2025 12:50:14 +0200
Subject: [PATCH 2/2] Add test for call.preallocated.arg and restore check

---
 llvm/lib/IR/Verifier.cpp                   | 4 +++-
 llvm/test/Verifier/preallocated-invalid.ll | 8 ++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 27e78ecfa9288..8c03d6f809d50 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5877,7 +5877,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
             "Uses of llvm.call.preallocated.setup must be calls");
       Intrinsic::ID IID = UseCall->getIntrinsicID();
       if (IID == Intrinsic::call_preallocated_arg) {
-        auto *AllocArgIndex = cast<ConstantInt>(UseCall->getArgOperand(1));
+        auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1));
+        Check(AllocArgIndex != nullptr,
+              "llvm.call.preallocated.alloc arg index must be a constant");
         auto AllocArgIndexInt = AllocArgIndex->getValue();
         Check(AllocArgIndexInt.sge(0) &&
                   AllocArgIndexInt.slt(NumArgs->getValue()),
diff --git a/llvm/test/Verifier/preallocated-invalid.ll b/llvm/test/Verifier/preallocated-invalid.ll
index 921fa69dcb23b..2c5aff231e1bd 100644
--- a/llvm/test/Verifier/preallocated-invalid.ll
+++ b/llvm/test/Verifier/preallocated-invalid.ll
@@ -72,6 +72,14 @@ define void @preallocated_setup_constant() {
     ret void
 }
 
+; CHECK: llvm.call.preallocated.alloc arg index must be a constant
+define void @preallocated_arg_constant() {
+    %ac = call i32 @blackbox()
+    %cs = call token @llvm.call.preallocated.setup(i32 3)
+    call token @llvm.call.preallocated.arg(token %cs, i32 %ac)
+    ret void
+}
+
 ; CHECK: must be between 0 and corresponding
 define void @preallocated_setup_arg_index_in_bounds() {
     %cs = call token @llvm.call.preallocated.setup(i32 2)



More information about the llvm-commits mailing list