[llvm-branch-commits] [llvm] [SelectionDAG] Emit `AssertZext` for function argument range attributes (PR #196786)
Iris Shi via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun May 10 00:31:43 PDT 2026
https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/196786
[SelectionDAG] Emit `AssertZext` for function argument range attributes
add test
update test
>From 99876cf3b35cdb539b91b72ea4eca75fdf06fbac Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Sun, 10 May 2026 15:30:20 +0800
Subject: [PATCH 1/3] [SelectionDAG] Emit `AssertZext` for function argument
range attributes
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 +++++++-
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 ++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c001f0e0bd450..f159e3170a5bd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10848,8 +10848,12 @@ 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;
@@ -12199,6 +12203,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..3c40b1dec4151 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 f7d49ccdb534e35517cb0e42f3bbb1b100643dc5 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Sun, 10 May 2026 15:30:45 +0800
Subject: [PATCH 2/3] 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 a34ffeba4f123e0ef82233479d58be0afc8d12d6 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Sun, 10 May 2026 15:31:13 +0800
Subject: [PATCH 3/3] update test
---
llvm/test/CodeGen/X86/argument-range-attr.ll | 26 +++++++++-----------
1 file changed, 12 insertions(+), 14 deletions(-)
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
More information about the llvm-branch-commits
mailing list