[llvm] b6c9c76 - [Verifier] Add checks for range attribute on ImmArg (#140522)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 23 03:16:03 PDT 2025


Author: Durgadoss R
Date: 2025-05-23T15:45:59+05:30
New Revision: b6c9c7633abfe783244bf19b0290d82678b2c419

URL: https://github.com/llvm/llvm-project/commit/b6c9c7633abfe783244bf19b0290d82678b2c419
DIFF: https://github.com/llvm/llvm-project/commit/b6c9c7633abfe783244bf19b0290d82678b2c419.diff

LOG: [Verifier] Add checks for range attribute on ImmArg (#140522)

This patch implements verifier checks for range
attributes on ImmArg. This enables validation
of the range of ImmArg operands in intrinsics,
when the intrinsic definition includes the range
information.

Signed-off-by: Durgadoss R <durgadossr at nvidia.com>

Added: 
    llvm/test/Assembler/invalid-immarg4.ll
    llvm/test/Assembler/invalid-immarg5.ll

Modified: 
    llvm/lib/IR/Verifier.cpp
    llvm/test/Assembler/immarg-param-attribute.ll
    llvm/test/Assembler/invalid-immarg.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 73b4274a41ee6..fdb4ddaafbbcc 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1987,8 +1987,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
           V);
 
   if (Attrs.hasAttribute(Attribute::ImmArg)) {
-    Check(Attrs.getNumAttributes() == 1,
-          "Attribute 'immarg' is incompatible with other attributes", V);
+    unsigned AttrCount =
+        Attrs.getNumAttributes() - Attrs.hasAttribute(Attribute::Range);
+    Check(AttrCount == 1,
+          "Attribute 'immarg' is incompatible with other attributes except the "
+          "'range' attribute",
+          V);
   }
 
   // Check for mutually incompatible attributes.  Only inreg is compatible with
@@ -3680,6 +3684,20 @@ void Verifier::visitCallBase(CallBase &Call) {
       Value *ArgVal = Call.getArgOperand(i);
       Check(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),
             "immarg operand has non-immediate parameter", ArgVal, Call);
+
+      // If the imm-arg is an integer and also has a range attached,
+      // check if the given value is within the range.
+      if (Call.paramHasAttr(i, Attribute::Range)) {
+        if (auto *CI = dyn_cast<ConstantInt>(ArgVal)) {
+          const ConstantRange &CR =
+              Call.getParamAttr(i, Attribute::Range).getValueAsConstantRange();
+          Check(CR.contains(CI->getValue()),
+                "immarg value " + Twine(CI->getValue().getSExtValue()) +
+                    " out of range [" + Twine(CR.getLower().getSExtValue()) +
+                    ", " + Twine(CR.getUpper().getSExtValue()) + ")",
+                Call);
+        }
+      }
     }
 
     if (Call.paramHasAttr(i, Attribute::Preallocated)) {

diff  --git a/llvm/test/Assembler/immarg-param-attribute.ll b/llvm/test/Assembler/immarg-param-attribute.ll
index 940d1a7c02862..47ac6758e4e72 100644
--- a/llvm/test/Assembler/immarg-param-attribute.ll
+++ b/llvm/test/Assembler/immarg-param-attribute.ll
@@ -6,6 +6,9 @@ declare void @llvm.test.immarg.intrinsic.i32(i32 immarg)
 ; CHECK: declare void @llvm.test.immarg.intrinsic.f32(float immarg)
 declare void @llvm.test.immarg.intrinsic.f32(float immarg)
 
+; CHECK: declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
+declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
+
 ; CHECK-LABEL: @call_llvm.test.immarg.intrinsic.i32(
 define void @call_llvm.test.immarg.intrinsic.i32() {
   ; CHECK: call void @llvm.test.immarg.intrinsic.i32(i32 0)
@@ -37,3 +40,19 @@ define void @on_callsite_and_declaration() {
   call void @llvm.test.immarg.intrinsic.i32(i32 immarg 0)
   ret void
 }
+
+; CHECK-LABEL: @test_int_immarg_with_range(
+define void @test_int_immarg_with_range() {
+  ; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
+  call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
+
+  ; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
+  call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
+
+  ; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
+  call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
+
+  ; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
+  call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
+  ret void
+}

diff  --git a/llvm/test/Assembler/invalid-immarg.ll b/llvm/test/Assembler/invalid-immarg.ll
index eac48129c4751..df69a66c67332 100644
--- a/llvm/test/Assembler/invalid-immarg.ll
+++ b/llvm/test/Assembler/invalid-immarg.ll
@@ -1,34 +1,34 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.byval(ptr byval(i32) immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.inalloca(ptr inalloca(i32) immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.inreg(i32 inreg immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.nest(ptr nest immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.sret(ptr sret(i32) immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.zeroext(i32 zeroext immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.signext(i32 signext immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.returned(i32 returned immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.noalias(ptr noalias immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.readnone(ptr readnone immarg)
 
-; CHECK: Attribute 'immarg' is incompatible with other attributes
+; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
 declare void @llvm.immarg.readonly(ptr readonly immarg)

diff  --git a/llvm/test/Assembler/invalid-immarg4.ll b/llvm/test/Assembler/invalid-immarg4.ll
new file mode 100644
index 0000000000000..259a259b635b1
--- /dev/null
+++ b/llvm/test/Assembler/invalid-immarg4.ll
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK: Attribute 'range(i32 1, 145)' applied to incompatible type!
+declare void @llvm.test.immarg.range.intrinsic.f32(float immarg range(i32 1, 145))

diff  --git a/llvm/test/Assembler/invalid-immarg5.ll b/llvm/test/Assembler/invalid-immarg5.ll
new file mode 100644
index 0000000000000..deffbd3cad4cc
--- /dev/null
+++ b/llvm/test/Assembler/invalid-immarg5.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -3, 4))
+
+define void @test_int_immarg_with_range() {
+  ; CHECK: immarg value -4 out of range [-3, 4)
+  call void @llvm.test.immarg.range.intrinsic.i32(i32 -4)
+  ret void
+}


        


More information about the llvm-commits mailing list