[llvm] [ARM] Avoid materializing constant 1 when generating cneg instructions (PR #146591)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 1 12:06:20 PDT 2025
https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/146591
Port to ARM.
>From b22b3b870008e83fe0ac9dbd990ab15b13d2d1ae Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 1 Jul 2025 14:59:12 -0400
Subject: [PATCH 1/2] [Thumb2] Pre-commit tests (NFC)
---
llvm/test/CodeGen/Thumb2/csel.ll | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/llvm/test/CodeGen/Thumb2/csel.ll b/llvm/test/CodeGen/Thumb2/csel.ll
index d786bc076aff9..e96b46e845d45 100644
--- a/llvm/test/CodeGen/Thumb2/csel.ll
+++ b/llvm/test/CodeGen/Thumb2/csel.ll
@@ -379,3 +379,17 @@ entry:
%t = add i32 %s, %b
ret i32 %t
}
+
+; Rather than use a CNEG, use a CSINV to transform "a == 1 ? 1 : -1" toAdd commentMore actions
+; "a == 1 ? a : -1" to avoid materializing a constant.
+define i32 @test_cneg(i32 %x) {
+; CHECK-LABEL: test_cneg:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movs r1, #1
+; CHECK-NEXT: cmp r0, #1
+; CHECK-NEXT: cneg r0, r1, ne
+; CHECK-NEXT: bx lr
+ %cmp = icmp eq i32 %x, 1
+ %res = select i1 %cmp, i32 1, i32 -1
+ ret i32 %res
+}
>From 8ad3063397eb7d5eca882c958ffbf6fdb393cf05 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 1 Jul 2025 15:05:48 -0400
Subject: [PATCH 2/2] [ARM] Avoid materializing constant 1 when generating cneg
instructions
Port to ARM
---
llvm/lib/Target/ARM/ARMISelLowering.cpp | 12 ++++++++++++
llvm/test/CodeGen/Thumb2/csel.ll | 3 +--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 2f89e23993385..d9bea6c646ccf 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -5530,6 +5530,18 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
CC = ISD::getSetCCInverse(CC, LHS.getValueType());
}
+ ConstantSDNode *RHSVal = dyn_cast<ConstantSDNode>(RHS);
+ if (Opcode == ARMISD::CSNEG && RHSVal && RHSVal->isOne()) {
+ assert(CTVal && CFVal && "Expected constant operands for CSNEG.");
+ // Use a CSINV to transform "a == C ? 1 : -1" to "a == C ? a : -1" to
+ // avoid materializing C.
+ if (CTVal == RHSVal && CC == ISD::SETEQ) {
+ Opcode = ARMISD::CSINV;
+ TrueVal = LHS;
+ FalseVal = DAG.getConstant(0, dl, FalseVal.getValueType());
+ }
+ }
+
if (Opcode) {
// If one of the constants is cheaper than another, materialise the
// cheaper one and let the csel generate the other.
diff --git a/llvm/test/CodeGen/Thumb2/csel.ll b/llvm/test/CodeGen/Thumb2/csel.ll
index e96b46e845d45..4a40c79edad41 100644
--- a/llvm/test/CodeGen/Thumb2/csel.ll
+++ b/llvm/test/CodeGen/Thumb2/csel.ll
@@ -385,9 +385,8 @@ entry:
define i32 @test_cneg(i32 %x) {
; CHECK-LABEL: test_cneg:
; CHECK: @ %bb.0:
-; CHECK-NEXT: movs r1, #1
; CHECK-NEXT: cmp r0, #1
-; CHECK-NEXT: cneg r0, r1, ne
+; CHECK-NEXT: cinv r0, r0, ne
; CHECK-NEXT: bx lr
%cmp = icmp eq i32 %x, 1
%res = select i1 %cmp, i32 1, i32 -1
More information about the llvm-commits
mailing list