[llvm] [ARM] Try to lower sign bit SELECT_CC to shift (PR #186349)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 13 02:39:52 PDT 2026
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/186349
Lower a `x < 0 ? 1 : 0` style SELECT_CC to `x>>(bw-1)`. This will become more important with an upcoming change, but also appears to be somewhat useful by itself.
>From fa2538f545e994952584d21725ab37e4b74d0afa Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 13 Mar 2026 10:36:42 +0100
Subject: [PATCH] [ARM] Try to lower sign bit SELECT_CC to shift
Lower a `x < 0 ? 1 : 0` style SELECT_CC to `x>>(bw-1)`. This will
become more important with an upcoming change, but also appears to
be somewhat useful by itself.
---
llvm/lib/Target/ARM/ARMISelLowering.cpp | 6 ++
...st-and-by-const-from-lshr-in-eqcmp-zero.ll | 49 ++---------
...ist-and-by-const-from-shl-in-eqcmp-zero.ll | 27 ++----
llvm/test/CodeGen/Thumb/smul_fix_sat.ll | 85 +++++++++----------
.../CodeGen/Thumb2/mve-saturating-arith.ll | 60 ++++++-------
5 files changed, 92 insertions(+), 135 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 228ed68e386b4..970c962197ac0 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -5199,6 +5199,12 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
return DAG.getNode(ISD::AND, dl, VT, LHS, Shift);
}
+
+ // (SELECT_CC setlt, x, 0, 1, 0) -> SRL(x, bw-1)
+ if (CC == ISD::SETLT && isNullConstant(RHS) && isOneConstant(TrueVal) &&
+ isNullConstant(FalseVal) && LHS.getValueType() == VT)
+ return DAG.getNode(ISD::SRL, dl, VT, LHS,
+ DAG.getConstant(VT.getSizeInBits() - 1, dl, VT));
}
if (LHS.getValueType() == MVT::i32) {
diff --git a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
index 7cc623fb0a616..a44c92687466e 100644
--- a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
@@ -966,48 +966,15 @@ define i1 @scalar_i32_x_is_const2_eq(i32 %y) nounwind {
;------------------------------------------------------------------------------;
define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
-; ARM6-LABEL: negative_scalar_i8_bitsinmiddle_slt:
-; ARM6: @ %bb.0:
-; ARM6-NEXT: uxtb r1, r1
-; ARM6-NEXT: mov r2, #24
-; ARM6-NEXT: ands r0, r0, r2, lsr r1
-; ARM6-NEXT: mov r0, #0
-; ARM6-NEXT: movmi r0, #1
-; ARM6-NEXT: bx lr
-;
-; ARM78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
-; ARM78: @ %bb.0:
-; ARM78-NEXT: uxtb r1, r1
-; ARM78-NEXT: mov r2, #24
-; ARM78-NEXT: ands r0, r0, r2, lsr r1
-; ARM78-NEXT: mov r0, #0
-; ARM78-NEXT: movwmi r0, #1
-; ARM78-NEXT: bx lr
-;
-; THUMB6-LABEL: negative_scalar_i8_bitsinmiddle_slt:
-; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
-; THUMB6-NEXT: movs r2, #24
-; THUMB6-NEXT: lsrs r2, r1
-; THUMB6-NEXT: ands r2, r0
-; THUMB6-NEXT: bmi .LBB20_2
-; THUMB6-NEXT: @ %bb.1:
-; THUMB6-NEXT: movs r0, #0
-; THUMB6-NEXT: bx lr
-; THUMB6-NEXT: .LBB20_2:
-; THUMB6-NEXT: movs r0, #1
-; THUMB6-NEXT: bx lr
+; ARM-LABEL: negative_scalar_i8_bitsinmiddle_slt:
+; ARM: @ %bb.0:
+; ARM-NEXT: mov r0, #0
+; ARM-NEXT: bx lr
;
-; THUMB78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
-; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
-; THUMB78-NEXT: movs r2, #24
-; THUMB78-NEXT: lsr.w r1, r2, r1
-; THUMB78-NEXT: ands r0, r1
-; THUMB78-NEXT: mov.w r0, #0
-; THUMB78-NEXT: it mi
-; THUMB78-NEXT: movmi r0, #1
-; THUMB78-NEXT: bx lr
+; THUMB-LABEL: negative_scalar_i8_bitsinmiddle_slt:
+; THUMB: @ %bb.0:
+; THUMB-NEXT: movs r0, #0
+; THUMB-NEXT: bx lr
%t0 = lshr i8 24, %y
%t1 = and i8 %t0, %x
%res = icmp slt i8 %t1, 0
diff --git a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
index a8421ae9a6a89..c3ad3fc0217df 100644
--- a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
@@ -1010,10 +1010,8 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
; ARM6-NEXT: uxtb r1, r1
; ARM6-NEXT: mov r2, #24
; ARM6-NEXT: and r0, r0, r2, lsl r1
-; ARM6-NEXT: sxtb r1, r0
-; ARM6-NEXT: mov r0, #0
-; ARM6-NEXT: cmp r1, #0
-; ARM6-NEXT: movmi r0, #1
+; ARM6-NEXT: mov r1, #1
+; ARM6-NEXT: and r0, r1, r0, lsr #7
; ARM6-NEXT: bx lr
;
; ARM78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
@@ -1021,10 +1019,7 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
; ARM78-NEXT: uxtb r1, r1
; ARM78-NEXT: mov r2, #24
; ARM78-NEXT: and r0, r0, r2, lsl r1
-; ARM78-NEXT: sxtb r1, r0
-; ARM78-NEXT: mov r0, #0
-; ARM78-NEXT: cmp r1, #0
-; ARM78-NEXT: movwmi r0, #1
+; ARM78-NEXT: ubfx r0, r0, #7, #1
; ARM78-NEXT: bx lr
;
; THUMB6-LABEL: negative_scalar_i8_bitsinmiddle_slt:
@@ -1033,14 +1028,8 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
; THUMB6-NEXT: movs r2, #24
; THUMB6-NEXT: lsls r2, r1
; THUMB6-NEXT: ands r2, r0
-; THUMB6-NEXT: sxtb r0, r2
-; THUMB6-NEXT: cmp r0, #0
-; THUMB6-NEXT: bmi .LBB20_2
-; THUMB6-NEXT: @ %bb.1:
-; THUMB6-NEXT: movs r0, #0
-; THUMB6-NEXT: bx lr
-; THUMB6-NEXT: .LBB20_2:
-; THUMB6-NEXT: movs r0, #1
+; THUMB6-NEXT: lsls r0, r2, #24
+; THUMB6-NEXT: lsrs r0, r0, #31
; THUMB6-NEXT: bx lr
;
; THUMB78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
@@ -1049,11 +1038,7 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
; THUMB78-NEXT: movs r2, #24
; THUMB78-NEXT: lsl.w r1, r2, r1
; THUMB78-NEXT: ands r0, r1
-; THUMB78-NEXT: sxtb r1, r0
-; THUMB78-NEXT: movs r0, #0
-; THUMB78-NEXT: cmp r1, #0
-; THUMB78-NEXT: it mi
-; THUMB78-NEXT: movmi r0, #1
+; THUMB78-NEXT: ubfx r0, r0, #7, #1
; THUMB78-NEXT: bx lr
%t0 = shl i8 24, %y
%t1 = and i8 %t0, %x
diff --git a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
index 24209b45e302d..52921f0f347b9 100644
--- a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
+++ b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
@@ -421,69 +421,68 @@ define i64 @func7(i64 %x, i64 %y) nounwind {
; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload
; ARM-NEXT: mov r3, r5
; ARM-NEXT: bl __aeabi_lmul
-; ARM-NEXT: adds r0, r0, r7
+; ARM-NEXT: adds r3, r0, r7
; ARM-NEXT: adcs r1, r6
-; ARM-NEXT: rsbs r5, r1, #0
-; ARM-NEXT: adcs r5, r1
-; ARM-NEXT: movs r2, #1
-; ARM-NEXT: str r0, [sp, #16] @ 4-byte Spill
-; ARM-NEXT: cmp r0, #0
-; ARM-NEXT: mov r3, r2
-; ARM-NEXT: bge .LBB6_2
+; ARM-NEXT: rsbs r0, r1, #0
+; ARM-NEXT: adcs r0, r1
+; ARM-NEXT: lsrs r2, r3, #31
+; ARM-NEXT: ands r2, r0
+; ARM-NEXT: movs r0, #1
+; ARM-NEXT: cmp r1, #0
+; ARM-NEXT: mov r5, r0
+; ARM-NEXT: bgt .LBB6_2
; ARM-NEXT: @ %bb.1:
-; ARM-NEXT: mov r3, r4
+; ARM-NEXT: mov r5, r4
; ARM-NEXT: .LBB6_2:
-; ARM-NEXT: mov r6, r2
-; ARM-NEXT: bmi .LBB6_4
+; ARM-NEXT: orrs r5, r2
+; ARM-NEXT: mvns r6, r4
+; ARM-NEXT: cmp r5, #0
+; ARM-NEXT: bne .LBB6_4
; ARM-NEXT: @ %bb.3:
-; ARM-NEXT: mov r6, r4
+; ARM-NEXT: str r3, [sp, #16] @ 4-byte Spill
+; ARM-NEXT: mov r5, r6
+; ARM-NEXT: beq .LBB6_5
+; ARM-NEXT: b .LBB6_6
; ARM-NEXT: .LBB6_4:
-; ARM-NEXT: ands r5, r6
-; ARM-NEXT: cmp r1, #0
-; ARM-NEXT: mov r7, r2
-; ARM-NEXT: bgt .LBB6_6
-; ARM-NEXT: @ %bb.5:
-; ARM-NEXT: mov r7, r4
+; ARM-NEXT: ldr r2, .LCPI6_0
+; ARM-NEXT: str r2, [sp, #16] @ 4-byte Spill
+; ARM-NEXT: mov r5, r6
+; ARM-NEXT: bne .LBB6_6
+; ARM-NEXT: .LBB6_5:
+; ARM-NEXT: ldr r5, [sp] @ 4-byte Reload
; ARM-NEXT: .LBB6_6:
-; ARM-NEXT: orrs r7, r5
-; ARM-NEXT: mvns r6, r4
-; ARM-NEXT: cmp r7, #0
-; ARM-NEXT: beq .LBB6_8
+; ARM-NEXT: adds r2, r1, #1
+; ARM-NEXT: rsbs r7, r2, #0
+; ARM-NEXT: adcs r7, r2
+; ARM-NEXT: cmp r3, #0
+; ARM-NEXT: mov r3, r0
+; ARM-NEXT: bge .LBB6_8
; ARM-NEXT: @ %bb.7:
-; ARM-NEXT: ldr r0, .LCPI6_0
-; ARM-NEXT: str r0, [sp, #16] @ 4-byte Spill
+; ARM-NEXT: mov r3, r4
; ARM-NEXT: .LBB6_8:
-; ARM-NEXT: mov r5, r6
-; ARM-NEXT: bne .LBB6_10
-; ARM-NEXT: @ %bb.9:
-; ARM-NEXT: ldr r5, [sp] @ 4-byte Reload
-; ARM-NEXT: .LBB6_10:
-; ARM-NEXT: adds r0, r1, #1
-; ARM-NEXT: rsbs r7, r0, #0
-; ARM-NEXT: adcs r7, r0
; ARM-NEXT: ands r7, r3
; ARM-NEXT: cmp r1, r6
-; ARM-NEXT: mov r3, r2
-; ARM-NEXT: blt .LBB6_12
-; ARM-NEXT: @ %bb.11:
+; ARM-NEXT: mov r3, r0
+; ARM-NEXT: blt .LBB6_10
+; ARM-NEXT: @ %bb.9:
; ARM-NEXT: mov r3, r4
-; ARM-NEXT: .LBB6_12:
+; ARM-NEXT: .LBB6_10:
; ARM-NEXT: orrs r3, r7
-; ARM-NEXT: lsls r1, r2, #31
+; ARM-NEXT: lsls r1, r0, #31
; ARM-NEXT: cmp r3, #0
+; ARM-NEXT: bne .LBB6_12
+; ARM-NEXT: @ %bb.11:
+; ARM-NEXT: mov r4, r5
+; ARM-NEXT: .LBB6_12:
; ARM-NEXT: bne .LBB6_14
; ARM-NEXT: @ %bb.13:
-; ARM-NEXT: mov r4, r5
-; ARM-NEXT: .LBB6_14:
-; ARM-NEXT: bne .LBB6_16
-; ARM-NEXT: @ %bb.15:
; ARM-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
-; ARM-NEXT: .LBB6_16:
+; ARM-NEXT: .LBB6_14:
; ARM-NEXT: mov r0, r4
; ARM-NEXT: add sp, #20
; ARM-NEXT: pop {r4, r5, r6, r7, pc}
; ARM-NEXT: .p2align 2
-; ARM-NEXT: @ %bb.17:
+; ARM-NEXT: @ %bb.15:
; ARM-NEXT: .LCPI6_0:
; ARM-NEXT: .long 2147483647 @ 0x7fffffff
%tmp = call i64 @llvm.smul.fix.sat.i64(i64 %x, i64 %y, i32 32)
diff --git a/llvm/test/CodeGen/Thumb2/mve-saturating-arith.ll b/llvm/test/CodeGen/Thumb2/mve-saturating-arith.ll
index bbc0ff9bd1be5..16d450a4e3b7a 100644
--- a/llvm/test/CodeGen/Thumb2/mve-saturating-arith.ll
+++ b/llvm/test/CodeGen/Thumb2/mve-saturating-arith.ll
@@ -34,45 +34,45 @@ entry:
define arm_aapcs_vfpcc <2 x i64> @sadd_int64_t(<2 x i64> %src1, <2 x i64> %src2) {
; CHECK-LABEL: sadd_int64_t:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: .save {r4, r5, r7, lr}
-; CHECK-NEXT: push {r4, r5, r7, lr}
+; CHECK-NEXT: .save {r4, r5, r6, lr}
+; CHECK-NEXT: push {r4, r5, r6, lr}
; CHECK-NEXT: vmov r0, r1, d2
; CHECK-NEXT: vmov r2, r3, d0
+; CHECK-NEXT: vmov r4, r5, d1
; CHECK-NEXT: adds.w r12, r2, r0
-; CHECK-NEXT: vmov r0, r4, d1
-; CHECK-NEXT: adc.w lr, r3, r1
+; CHECK-NEXT: adc.w r0, r3, r1
; CHECK-NEXT: subs.w r2, r12, r2
-; CHECK-NEXT: sbcs.w r2, lr, r3
+; CHECK-NEXT: sbcs.w r2, r0, r3
+; CHECK-NEXT: mov.w r3, #0
; CHECK-NEXT: cset r2, lt
-; CHECK-NEXT: cmp r1, #0
-; CHECK-NEXT: it mi
-; CHECK-NEXT: eormi r2, r2, #1
-; CHECK-NEXT: rsbs r1, r2, #0
-; CHECK-NEXT: movs r2, #0
-; CHECK-NEXT: bfi r2, r1, #0, #8
-; CHECK-NEXT: vmov r1, r3, d3
-; CHECK-NEXT: adds r1, r1, r0
-; CHECK-NEXT: adc.w r5, r4, r3
-; CHECK-NEXT: subs r0, r1, r0
-; CHECK-NEXT: sbcs.w r0, r5, r4
-; CHECK-NEXT: vmov q0[2], q0[0], r12, r1
-; CHECK-NEXT: cset r0, lt
-; CHECK-NEXT: cmp r3, #0
-; CHECK-NEXT: it mi
-; CHECK-NEXT: eormi r0, r0, #1
-; CHECK-NEXT: asr.w r1, lr, #31
-; CHECK-NEXT: rsbs r0, r0, #0
-; CHECK-NEXT: vmov q0[3], q0[1], lr, r5
-; CHECK-NEXT: bfi r2, r0, #8, #8
-; CHECK-NEXT: asrs r0, r5, #31
-; CHECK-NEXT: vmov q1[2], q1[0], r1, r0
-; CHECK-NEXT: vmsr p0, r2
-; CHECK-NEXT: vmov q1[3], q1[1], r1, r0
+; CHECK-NEXT: cmp.w r3, r1, lsr #31
+; CHECK-NEXT: it ne
+; CHECK-NEXT: eorne r2, r2, #1
+; CHECK-NEXT: rsb.w lr, r2, #0
+; CHECK-NEXT: vmov r2, r1, d3
+; CHECK-NEXT: adds r2, r2, r4
+; CHECK-NEXT: adc.w r6, r5, r1
+; CHECK-NEXT: subs r4, r2, r4
+; CHECK-NEXT: sbcs.w r4, r6, r5
+; CHECK-NEXT: vmov q0[2], q0[0], r12, r2
+; CHECK-NEXT: cset r4, lt
+; CHECK-NEXT: cmp.w r3, r1, lsr #31
+; CHECK-NEXT: it ne
+; CHECK-NEXT: eorne r4, r4, #1
+; CHECK-NEXT: bfi r3, lr, #0, #8
+; CHECK-NEXT: rsbs r1, r4, #0
+; CHECK-NEXT: vmov q0[3], q0[1], r0, r6
+; CHECK-NEXT: bfi r3, r1, #8, #8
+; CHECK-NEXT: asrs r1, r6, #31
+; CHECK-NEXT: asrs r0, r0, #31
+; CHECK-NEXT: vmsr p0, r3
+; CHECK-NEXT: vmov q1[2], q1[0], r0, r1
+; CHECK-NEXT: vmov q1[3], q1[1], r0, r1
; CHECK-NEXT: adr r0, .LCPI3_0
; CHECK-NEXT: vldrw.u32 q2, [r0]
; CHECK-NEXT: veor q1, q1, q2
; CHECK-NEXT: vpsel q0, q1, q0
-; CHECK-NEXT: pop {r4, r5, r7, pc}
+; CHECK-NEXT: pop {r4, r5, r6, pc}
; CHECK-NEXT: .p2align 4
; CHECK-NEXT: @ %bb.1:
; CHECK-NEXT: .LCPI3_0:
More information about the llvm-commits
mailing list