https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/196786

>From 02177f39214de7c77a10563d6e847bd90fd896d4 Mon Sep 17 00:00:00 2001
From: Iris Shi <[email protected]>
Date: Sun, 10 May 2026 15:30:20 +0800
Subject: [PATCH 1/4] [SelectionDAG] Emit `AssertZext` for function argument
 range attributes

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 7 ++++++-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h   | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 5753d74168e59..1139ba64fa01c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10847,8 +10847,11 @@ void SelectionDAGBuilder::visitVACopy(const CallInst 
&I) {
 SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG,
                                                     const Instruction &I,
                                                     SDValue Op) {
-  std::optional<ConstantRange> CR = getRange(I);
+  return lowerRangeToAssertZExt(DAG, getRange(I), Op);
+}
 
+SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(
+    SelectionDAG &DAG, std::optional<ConstantRange> CR, SDValue Op) {
   if (!CR || CR->isFullSet() || CR->isEmptySet() || CR->isUpperWrapped())
     return Op;
 
@@ -12198,6 +12201,8 @@ void SelectionDAGISel::LowerArguments(const Function 
&F) {
           OutVal = DAG.getNode(ISD::AssertNoFPClass, dl, OutVal.getValueType(),
                                OutVal, SDNoFPClass);
         }
+        if (NumValues == 1 && VT.isInteger())
+          OutVal = SDB->lowerRangeToAssertZExt(DAG, Arg.getRange(), OutVal);
         ArgValues.push_back(OutVal);
       }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 21aac333a73cd..7edf005586989 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -429,6 +429,8 @@ class SelectionDAGBuilder {
   // floor power of two.
   SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const Instruction &I,
                                  SDValue Op);
+  SDValue lowerRangeToAssertZExt(SelectionDAG &DAG,
+                                 std::optional<ConstantRange> CR, SDValue Op);
 
   // Lower nofpclass attributes to AssertNoFPClass
   SDValue lowerNoFPClassToAssertNoFPClass(SelectionDAG &DAG,

>From 3855bbafd2b2011a2509d4ac346644a71bd22c8c Mon Sep 17 00:00:00 2001
From: Iris Shi <[email protected]>
Date: Sun, 10 May 2026 15:30:45 +0800
Subject: [PATCH 2/4] add test

---
 llvm/test/CodeGen/X86/argument-range-attr.ll | 123 +++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/argument-range-attr.ll

diff --git a/llvm/test/CodeGen/X86/argument-range-attr.ll 
b/llvm/test/CodeGen/X86/argument-range-attr.ll
new file mode 100644
index 0000000000000..376213bf6bd7c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/argument-range-attr.ll
@@ -0,0 +1,123 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 4
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+; range: 0..2^61
+; mask: 2^61 - 8
+define i64 @arg_range_top3(i64 range(i64 0, 2305843009213693952) %n) {
+; CHECK-LABEL: arg_range_top3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 2305843009213693944
+  ret i64 %r
+}
+
+; range: 0..256
+; mask: 0xF8 = 248
+define i64 @arg_range_byte(i64 range(i64 0, 256) %n) {
+; CHECK-LABEL: arg_range_byte:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 248
+  ret i64 %r
+}
+
+define i64 @arg_range_nonzero_lo(i64 range(i64 1, 2305843009213693952) %n) {
+; CHECK-LABEL: arg_range_nonzero_lo:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 2305843009213693944
+  ret i64 %r
+}
+
+define i64 @arg_range_byte_nonzero_lo(i64 range(i64 1, 256) %n) {
+; CHECK-LABEL: arg_range_byte_nonzero_lo:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 248
+  ret i64 %r
+}
+
+define i32 @arg_range_i32_byte(i32 range(i32 0, 256) %n) {
+; CHECK-LABEL: arg_range_i32_byte:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    retq
+  %r = and i32 %n, 248
+  ret i32 %r
+}
+
+define i64 @arg_range_top1(i64 range(i64 0, 9223372036854775808) %n) {
+; CHECK-LABEL: arg_range_top1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    shrq $63, %rax
+; CHECK-NEXT:    retq
+  %r = lshr i64 %n, 63
+  ret i64 %r
+}
+
+define i64 @arg_range_two_args(i64 range(i64 0, 256) %a, i64 range(i64 0, 
65536) %b) {
+; CHECK-LABEL: arg_range_two_args:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    andl $248, %edi
+; CHECK-NEXT:    andl $65528, %eax # imm = 0xFFF8
+; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    retq
+  %ra = and i64 %a, 248
+  %rb = and i64 %b, 65528
+  %r = or i64 %ra, %rb
+  ret i64 %r
+}
+
+define i32 @arg_range_zeroext(i8 zeroext range(i8 0, 16) %n) {
+; CHECK-LABEL: arg_range_zeroext:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andl $14, %eax
+; CHECK-NEXT:    retq
+  %z = zext i8 %n to i32
+  %r = and i32 %z, 14
+  ret i32 %r
+}
+
+; Negative tests
+
+define i64 @neg_no_range(i64 %n) {
+; CHECK-LABEL: neg_no_range:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 2305843009213693944
+  ret i64 %r
+}
+
+define i64 @neg_wrapped_range(i64 range(i64 -100, 100) %n) {
+; CHECK-LABEL: neg_wrapped_range:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %r = and i64 %n, 2305843009213693944
+  ret i64 %r
+}
+
+define i32 @neg_near_full_range(i32 range(i32 0, -1) %n) {
+; CHECK-LABEL: neg_near_full_range:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    retq
+  %r = and i32 %n, 248
+  ret i32 %r
+}

>From 0291fcdaf92b9dc65893d088c24e23896fc396d0 Mon Sep 17 00:00:00 2001
From: Iris Shi <[email protected]>
Date: Sun, 10 May 2026 15:31:13 +0800
Subject: [PATCH 3/4] update test

---
 .../AMDGPU/bit-op-reduce-width-known-bits.ll  |  6 ++---
 llvm/test/CodeGen/X86/argument-range-attr.ll  | 26 +++++++++----------
 2 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/bit-op-reduce-width-known-bits.ll 
b/llvm/test/CodeGen/AMDGPU/bit-op-reduce-width-known-bits.ll
index ad26dfa7f93e8..a8be7e5827af0 100644
--- a/llvm/test/CodeGen/AMDGPU/bit-op-reduce-width-known-bits.ll
+++ b/llvm/test/CodeGen/AMDGPU/bit-op-reduce-width-known-bits.ll
@@ -11,7 +11,7 @@ define i64 @v_xor_i64_known_hi_i32_from_arg_range(i64 
range(i64 0, 4294967296) %
 ; CHECK-LABEL: v_xor_i64_known_hi_i32_from_arg_range:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_xor_b32_e32 v1, v1, v3
+; CHECK-NEXT:    v_mov_b32_e32 v1, v3
 ; CHECK-NEXT:    v_xor_b32_e32 v0, v0, v2
 ; CHECK-NEXT:    s_setpc_b64 s[30:31]
   %xor = xor i64 %arg0, %arg1
@@ -24,7 +24,7 @@ define i64 @v_or_i64_known_hi_i32_from_arg_range(i64 
range(i64 0, 4294967296) %a
 ; CHECK-LABEL: v_or_i64_known_hi_i32_from_arg_range:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_or_b32_e32 v1, v1, v3
+; CHECK-NEXT:    v_mov_b32_e32 v1, v3
 ; CHECK-NEXT:    v_or_b32_e32 v0, v0, v2
 ; CHECK-NEXT:    s_setpc_b64 s[30:31]
   %or = or i64 %arg0, %arg1
@@ -50,7 +50,7 @@ define i64 @s_xor_i64_known_i32_from_arg_range(i64 range(i64 
0, 65) inreg %arg)
 ; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; CHECK-NEXT:    s_not_b64 s[4:5], s[16:17]
 ; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    v_mov_b32_e32 v1, s5
+; CHECK-NEXT:    v_mov_b32_e32 v1, -1
 ; CHECK-NEXT:    s_setpc_b64 s[30:31]
   %xor = xor i64 %arg, -1
   ret i64 %xor
diff --git a/llvm/test/CodeGen/X86/argument-range-attr.ll 
b/llvm/test/CodeGen/X86/argument-range-attr.ll
index 376213bf6bd7c..9d684f7f596b2 100644
--- a/llvm/test/CodeGen/X86/argument-range-attr.ll
+++ b/llvm/test/CodeGen/X86/argument-range-attr.ll
@@ -6,8 +6,8 @@
 define i64 @arg_range_top3(i64 range(i64 0, 2305843009213693952) %n) {
 ; CHECK-LABEL: arg_range_top3:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
-; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    andq $-8, %rax
 ; CHECK-NEXT:    retq
   %r = and i64 %n, 2305843009213693944
   ret i64 %r
@@ -19,7 +19,7 @@ define i64 @arg_range_byte(i64 range(i64 0, 256) %n) {
 ; CHECK-LABEL: arg_range_byte:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    andl $-8, %eax
 ; CHECK-NEXT:    retq
   %r = and i64 %n, 248
   ret i64 %r
@@ -28,8 +28,8 @@ define i64 @arg_range_byte(i64 range(i64 0, 256) %n) {
 define i64 @arg_range_nonzero_lo(i64 range(i64 1, 2305843009213693952) %n) {
 ; CHECK-LABEL: arg_range_nonzero_lo:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movabsq $2305843009213693944, %rax # imm = 0x1FFFFFFFFFFFFFF8
-; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    andq $-8, %rax
 ; CHECK-NEXT:    retq
   %r = and i64 %n, 2305843009213693944
   ret i64 %r
@@ -39,7 +39,7 @@ define i64 @arg_range_byte_nonzero_lo(i64 range(i64 1, 256) 
%n) {
 ; CHECK-LABEL: arg_range_byte_nonzero_lo:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    andl $-8, %eax
 ; CHECK-NEXT:    retq
   %r = and i64 %n, 248
   ret i64 %r
@@ -49,7 +49,7 @@ define i32 @arg_range_i32_byte(i32 range(i32 0, 256) %n) {
 ; CHECK-LABEL: arg_range_i32_byte:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    andl $-8, %eax
 ; CHECK-NEXT:    retq
   %r = and i32 %n, 248
   ret i32 %r
@@ -58,8 +58,7 @@ define i32 @arg_range_i32_byte(i32 range(i32 0, 256) %n) {
 define i64 @arg_range_top1(i64 range(i64 0, 9223372036854775808) %n) {
 ; CHECK-LABEL: arg_range_top1:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    shrq $63, %rax
+; CHECK-NEXT:    xorl %eax, %eax
 ; CHECK-NEXT:    retq
   %r = lshr i64 %n, 63
   ret i64 %r
@@ -68,10 +67,9 @@ define i64 @arg_range_top1(i64 range(i64 0, 
9223372036854775808) %n) {
 define i64 @arg_range_two_args(i64 range(i64 0, 256) %a, i64 range(i64 0, 
65536) %b) {
 ; CHECK-LABEL: arg_range_two_args:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq %rsi, %rax
-; CHECK-NEXT:    andl $248, %edi
-; CHECK-NEXT:    andl $65528, %eax # imm = 0xFFF8
-; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    orl %esi, %eax
+; CHECK-NEXT:    andl $-8, %eax
 ; CHECK-NEXT:    retq
   %ra = and i64 %a, 248
   %rb = and i64 %b, 65528
@@ -83,7 +81,7 @@ define i32 @arg_range_zeroext(i8 zeroext range(i8 0, 16) %n) {
 ; CHECK-LABEL: arg_range_zeroext:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    andl $14, %eax
+; CHECK-NEXT:    andl $-2, %eax
 ; CHECK-NEXT:    retq
   %z = zext i8 %n to i32
   %r = and i32 %z, 14

>From 67d7ee6ec9c28f1dfd29c2848c50eb7ef2194d84 Mon Sep 17 00:00:00 2001
From: Iris Shi <[email protected]>
Date: Mon, 11 May 2026 18:36:28 +0800
Subject: [PATCH 4/4] address review comment

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |  2 +-
 llvm/test/CodeGen/X86/argument-range-attr.ll          | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1139ba64fa01c..d782e9038343e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -12201,7 +12201,7 @@ void SelectionDAGISel::LowerArguments(const Function 
&F) {
           OutVal = DAG.getNode(ISD::AssertNoFPClass, dl, OutVal.getValueType(),
                                OutVal, SDNoFPClass);
         }
-        if (NumValues == 1 && VT.isInteger())
+        if (NumValues == 1 && VT.isInteger() && !isa<LoadSDNode>(OutVal))
           OutVal = SDB->lowerRangeToAssertZExt(DAG, Arg.getRange(), OutVal);
         ArgValues.push_back(OutVal);
       }
diff --git a/llvm/test/CodeGen/X86/argument-range-attr.ll 
b/llvm/test/CodeGen/X86/argument-range-attr.ll
index 9d684f7f596b2..c6ae1a6e6c895 100644
--- a/llvm/test/CodeGen/X86/argument-range-attr.ll
+++ b/llvm/test/CodeGen/X86/argument-range-attr.ll
@@ -88,6 +88,17 @@ define i32 @arg_range_zeroext(i8 zeroext range(i8 0, 16) %n) 
{
   ret i32 %r
 }
 
+; The 7th integer arg is passed on the stack on x86-64 SysV.
+define i64 @arg_range_stack(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, 
i64 range(i64 0, 256) %g) {
+; CHECK-LABEL: arg_range_stack:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rax
+; CHECK-NEXT:    andl $248, %eax
+; CHECK-NEXT:    retq
+  %r = and i64 %g, 248
+  ret i64 %r
+}
+
 ; Negative tests
 
 define i64 @neg_no_range(i64 %n) {

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to