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
