[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:55 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>

Port to ARM.

---
Full diff: https://github.com/llvm/llvm-project/pull/146591.diff


2 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+12) 
- (modified) llvm/test/CodeGen/Thumb2/csel.ll (+13) 


``````````diff
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 d786bc076aff9..4a40c79edad41 100644
--- a/llvm/test/CodeGen/Thumb2/csel.ll
+++ b/llvm/test/CodeGen/Thumb2/csel.ll
@@ -379,3 +379,16 @@ 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:    cmp r0, #1
+; CHECK-NEXT:    cinv r0, r0, ne
+; CHECK-NEXT:    bx lr
+  %cmp = icmp eq i32 %x, 1
+  %res = select i1 %cmp, i32 1, i32 -1
+  ret i32 %res
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/146591


More information about the llvm-commits mailing list