[llvm] [AArch64] Fold SMax and SMin with -1 (PR #208264)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 8 09:52:40 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: AZero13 (AZero13)
<details>
<summary>Changes</summary>
Use orn to fold smax with -1.
---
Full diff: https://github.com/llvm/llvm-project/pull/208264.diff
6 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+18)
- (modified) llvm/test/CodeGen/AArch64/aarch64-saturating-arithmetic.ll (+2-4)
- (modified) llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll (+8-8)
- (modified) llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll (+8-8)
- (modified) llvm/test/CodeGen/AArch64/smax-allones.ll (+56)
- (modified) llvm/test/CodeGen/AArch64/win64_vararg.ll (+2-4)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 86670e136355f..a39d4a63a22b7 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -12646,6 +12646,24 @@ SDValue AArch64TargetLowering::LowerSELECT_CC(
return DAG.getNode(ISD::AND, DL, VT, LHS, Shift);
}
+ // Check for SMAX(lhs, -1) and SMIN(lhs, -1) patterns.
+ // (SELECT_CC setgt, lhs, -1, lhs, -1) -> (OR lhs, (SRA lhs, typesize-1))
+ // (SELECT_CC setlt, lhs, -1, lhs, -1) -> (ORN lhs, (SRA lhs, typesize-1))
+ // Both require less instructions than compare and conditional select.
+ if ((CC == ISD::SETGT || CC == ISD::SETLT) && LHS == TVal &&
+ RHSC && RHSC->isAllOnes() && CFVal && CFVal->isAllOnes() &&
+ LHS.getValueType() == RHS.getValueType()) {
+ EVT VT = LHS.getValueType();
+ SDValue Shift =
+ DAG.getNode(ISD::SRA, DL, VT, LHS,
+ DAG.getConstant(VT.getSizeInBits() - 1, DL, VT));
+
+ if (CC == ISD::SETLT)
+ Shift = DAG.getNOT(DL, Shift, VT);
+
+ return DAG.getNode(ISD::OR, DL, VT, LHS, Shift);
+ }
+
// Check for sign bit test patterns that can use TST optimization.
// (SELECT_CC setlt, sign_extend_inreg, 0, tval, fval)
// -> TST %operand, sign_bit; CSEL
diff --git a/llvm/test/CodeGen/AArch64/aarch64-saturating-arithmetic.ll b/llvm/test/CodeGen/AArch64/aarch64-saturating-arithmetic.ll
index db79b672d6f03..9546512fc4230 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-saturating-arithmetic.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-saturating-arithmetic.ll
@@ -106,9 +106,8 @@ define i64 @test_ssub_nonneg_rhs_nonconst(i64 %x) {
define i64 @test_ssub_neg_rhs_nonconst(i64 %x) {
; CHECK-LABEL: test_ssub_neg_rhs_nonconst:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmn x0, #1
+; CHECK-NEXT: orn x9, x0, x0, asr #63
; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff
-; CHECK-NEXT: csinv x9, x0, xzr, lt
; CHECK-NEXT: subs x9, x0, x9
; CHECK-NEXT: csel x0, x8, x9, vs
; CHECK-NEXT: ret
@@ -162,9 +161,8 @@ define i64 @test_ssub_nonneg_lhs_nonconst(i64 %x) {
define i64 @test_ssub_neg_lhs_nonconst(i64 %x) {
; CHECK-LABEL: test_ssub_neg_lhs_nonconst:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmn x0, #1
+; CHECK-NEXT: orn x9, x0, x0, asr #63
; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000
-; CHECK-NEXT: csinv x9, x0, xzr, lt
; CHECK-NEXT: subs x9, x9, x0
; CHECK-NEXT: csel x0, x8, x9, vs
; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll
index f95d338198c4d..67f598727a032 100644
--- a/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll
+++ b/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll
@@ -23,8 +23,8 @@ define i1 @test_signed_i1_f32(float %f) nounwind {
; CHECK-SD-LABEL: test_signed_i1_f32:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs w8, s0
-; CHECK-SD-NEXT: ands w8, w8, w8, asr #31
-; CHECK-SD-NEXT: csinv w8, w8, wzr, pl
+; CHECK-SD-NEXT: and w8, w8, w8, asr #31
+; CHECK-SD-NEXT: orr w8, w8, w8, lsr #31
; CHECK-SD-NEXT: and w0, w8, #0x1
; CHECK-SD-NEXT: ret
;
@@ -268,8 +268,8 @@ define i1 @test_signed_i1_f64(double %f) nounwind {
; CHECK-SD-LABEL: test_signed_i1_f64:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs w8, d0
-; CHECK-SD-NEXT: ands w8, w8, w8, asr #31
-; CHECK-SD-NEXT: csinv w8, w8, wzr, pl
+; CHECK-SD-NEXT: and w8, w8, w8, asr #31
+; CHECK-SD-NEXT: orr w8, w8, w8, lsr #31
; CHECK-SD-NEXT: and w0, w8, #0x1
; CHECK-SD-NEXT: ret
;
@@ -518,16 +518,16 @@ define i1 @test_signed_i1_f16(half %f) nounwind {
; CHECK-SD-CVT: // %bb.0:
; CHECK-SD-CVT-NEXT: fcvt s0, h0
; CHECK-SD-CVT-NEXT: fcvtzs w8, s0
-; CHECK-SD-CVT-NEXT: ands w8, w8, w8, asr #31
-; CHECK-SD-CVT-NEXT: csinv w8, w8, wzr, pl
+; CHECK-SD-CVT-NEXT: and w8, w8, w8, asr #31
+; CHECK-SD-CVT-NEXT: orr w8, w8, w8, lsr #31
; CHECK-SD-CVT-NEXT: and w0, w8, #0x1
; CHECK-SD-CVT-NEXT: ret
;
; CHECK-SD-FP16-LABEL: test_signed_i1_f16:
; CHECK-SD-FP16: // %bb.0:
; CHECK-SD-FP16-NEXT: fcvtzs w8, h0
-; CHECK-SD-FP16-NEXT: ands w8, w8, w8, asr #31
-; CHECK-SD-FP16-NEXT: csinv w8, w8, wzr, pl
+; CHECK-SD-FP16-NEXT: and w8, w8, w8, asr #31
+; CHECK-SD-FP16-NEXT: orr w8, w8, w8, lsr #31
; CHECK-SD-FP16-NEXT: and w0, w8, #0x1
; CHECK-SD-FP16-NEXT: ret
;
diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll
index 145aef9123a4e..892af7852e1bc 100644
--- a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll
+++ b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll
@@ -2350,14 +2350,14 @@ define <2 x i1> @test_signed_v2f64_v2i1(<2 x double> %f) {
; CHECK-SD-LABEL: test_signed_v2f64_v2i1:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov d1, v0.d[1]
-; CHECK-SD-NEXT: fcvtzs w9, d0
-; CHECK-SD-NEXT: fcvtzs w8, d1
-; CHECK-SD-NEXT: ands w8, w8, w8, asr #31
-; CHECK-SD-NEXT: csinv w8, w8, wzr, pl
-; CHECK-SD-NEXT: ands w9, w9, w9, asr #31
-; CHECK-SD-NEXT: csinv w9, w9, wzr, pl
-; CHECK-SD-NEXT: fmov s0, w9
-; CHECK-SD-NEXT: mov v0.s[1], w8
+; CHECK-SD-NEXT: fcvtzs w8, d0
+; CHECK-SD-NEXT: fcvtzs w9, d1
+; CHECK-SD-NEXT: and w8, w8, w8, asr #31
+; CHECK-SD-NEXT: orr w8, w8, w8, asr #31
+; CHECK-SD-NEXT: and w9, w9, w9, asr #31
+; CHECK-SD-NEXT: fmov s0, w8
+; CHECK-SD-NEXT: orr w9, w9, w9, asr #31
+; CHECK-SD-NEXT: mov v0.s[1], w9
; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
; CHECK-SD-NEXT: ret
;
diff --git a/llvm/test/CodeGen/AArch64/smax-allones.ll b/llvm/test/CodeGen/AArch64/smax-allones.ll
index f22af8756a866..75ae53ab3a9fc 100644
--- a/llvm/test/CodeGen/AArch64/smax-allones.ll
+++ b/llvm/test/CodeGen/AArch64/smax-allones.ll
@@ -61,3 +61,59 @@ define i64 @smin_zero_i64(i64 %x) {
%r = call i64 @llvm.smin.i64(i64 %x, i64 0)
ret i64 %r
}
+
+define i32 @smax_zero_i32(i32 %x) {
+; NOCSSC-LABEL: smax_zero_i32:
+; NOCSSC: // %bb.0:
+; NOCSSC-NEXT: bic w0, w0, w0, asr #31
+; NOCSSC-NEXT: ret
+;
+; CSSC-LABEL: smax_zero_i32:
+; CSSC: // %bb.0:
+; CSSC-NEXT: smax w0, w0, #0
+; CSSC-NEXT: ret
+ %r = call i32 @llvm.smax.i32(i32 %x, i32 0)
+ ret i32 %r
+}
+
+define i64 @smax_zero_i64(i64 %x) {
+; NOCSSC-LABEL: smax_zero_i64:
+; NOCSSC: // %bb.0:
+; NOCSSC-NEXT: bic x0, x0, x0, asr #63
+; NOCSSC-NEXT: ret
+;
+; CSSC-LABEL: smax_zero_i64:
+; CSSC: // %bb.0:
+; CSSC-NEXT: smax x0, x0, #0
+; CSSC-NEXT: ret
+ %r = call i64 @llvm.smax.i64(i64 %x, i64 0)
+ ret i64 %r
+}
+
+define i32 @smin_allones_i32(i32 %x) {
+; NOCSSC-LABEL: smin_allones_i32:
+; NOCSSC: // %bb.0:
+; NOCSSC-NEXT: orn w0, w0, w0, asr #31
+; NOCSSC-NEXT: ret
+;
+; CSSC-LABEL: smin_allones_i32:
+; CSSC: // %bb.0:
+; CSSC-NEXT: smin w0, w0, #-1
+; CSSC-NEXT: ret
+ %r = call i32 @llvm.smin.i32(i32 %x, i32 -1)
+ ret i32 %r
+}
+
+define i64 @smin_allones_i64(i64 %x) {
+; NOCSSC-LABEL: smin_allones_i64:
+; NOCSSC: // %bb.0:
+; NOCSSC-NEXT: orn x0, x0, x0, asr #63
+; NOCSSC-NEXT: ret
+;
+; CSSC-LABEL: smin_allones_i64:
+; CSSC: // %bb.0:
+; CSSC-NEXT: smin x0, x0, #-1
+; CSSC-NEXT: ret
+ %r = call i64 @llvm.smin.i64(i64 %x, i64 -1)
+ ret i64 %r
+}
diff --git a/llvm/test/CodeGen/AArch64/win64_vararg.ll b/llvm/test/CodeGen/AArch64/win64_vararg.ll
index 0f4cb44a6f73b..6b845c6163882 100644
--- a/llvm/test/CodeGen/AArch64/win64_vararg.ll
+++ b/llvm/test/CodeGen/AArch64/win64_vararg.ll
@@ -133,8 +133,7 @@ define i32 @fp(ptr, i64, ptr, ...) local_unnamed_addr #6 {
; CHECK-NEXT: mov x4, xzr
; CHECK-NEXT: orr x0, x8, #0x2
; CHECK-NEXT: bl __stdio_common_vsprintf
-; CHECK-NEXT: cmn w0, #1
-; CHECK-NEXT: csinv w0, w0, wzr, gt
+; CHECK-NEXT: orr w0, w0, w0, asr #31
; CHECK-NEXT: .seh_startepilogue
; CHECK-NEXT: ldp x29, x30, [sp, #24] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_fplr 24
@@ -268,8 +267,7 @@ define i32 @snprintf(ptr, i64, ptr, ...) local_unnamed_addr #5 {
; CHECK-NEXT: mov x4, xzr
; CHECK-NEXT: orr x0, x8, #0x2
; CHECK-NEXT: bl __stdio_common_vsprintf
-; CHECK-NEXT: cmn w0, #1
-; CHECK-NEXT: csinv w0, w0, wzr, gt
+; CHECK-NEXT: orr w0, w0, w0, asr #31
; CHECK-NEXT: .seh_startepilogue
; CHECK-NEXT: ldp x21, x30, [sp, #32] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_lrpair x21, 32
``````````
</details>
https://github.com/llvm/llvm-project/pull/208264
More information about the llvm-commits
mailing list