[llvm] [ARM] Refactor getARMCmp to deal with the vselect situation (PR #192873)

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 19 14:01:17 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: SiliconA-Z

<details>
<summary>Changes</summary>

Deal with it automatically, so getARMCmp can later be extended without issue.

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


5 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+45-51) 
- (modified) llvm/lib/Target/ARM/ARMISelLowering.h (+2-1) 
- (modified) llvm/test/CodeGen/ARM/consthoist-icmpimm.ll (+16-16) 
- (modified) llvm/test/CodeGen/ARM/select-constant-xor.ll (+2-2) 
- (modified) llvm/test/CodeGen/Thumb/smul_fix_sat.ll (+1-1) 


``````````diff
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 0ad6c07f36868..3bc5415cf7ed5 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -4486,7 +4486,8 @@ static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG) {
 /// the given operands.
 SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
                                      SDValue &ARMcc, SelectionDAG &DAG,
-                                     const SDLoc &dl) const {
+                                     const SDLoc &dl,
+                                     bool ForbidMIandPL) const {
   if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
     unsigned C = RHSC->getZExtValue();
     if (!isLegalICmpImmediate((int32_t)C)) {
@@ -4587,47 +4588,37 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
     return Shift.getValue(1);
   }
 
+  unsigned CompareType = ARMISD::CMP;
+  if (isCMN(RHS, CC, DAG)) {
+    CompareType = ARMISD::CMN;
+    RHS = RHS.getOperand(1);
+  } else if (isCMN(LHS, CC, DAG)) {
+    CompareType = ARMISD::CMN;
+    LHS = LHS.getOperand(1);
+    CC = ISD::getSetCCSwappedOperands(CC);
+  }
+
   ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
 
   // If the RHS is a constant zero then the V (overflow) flag will never be
   // set. This can allow us to simplify GE to PL or LT to MI, which can be
   // simpler for other passes (like the peephole optimiser) to deal with.
-  if (isNullConstant(RHS)) {
+  if (!ForbidMIandPL && isNullConstant(RHS)) {
     switch (CondCode) {
-      default: break;
-      case ARMCC::GE:
-        CondCode = ARMCC::PL;
-        break;
-      case ARMCC::LT:
-        CondCode = ARMCC::MI;
-        break;
+    default:
+      break;
+    case ARMCC::GE:
+      CondCode = ARMCC::PL;
+      break;
+    case ARMCC::LT:
+      CondCode = ARMCC::MI;
+      break;
     }
   }
 
-  unsigned CompareType;
-  switch (CondCode) {
-  default:
-    CompareType = ARMISD::CMP;
-    break;
-  case ARMCC::EQ:
-  case ARMCC::NE:
-    // Uses only Z Flag
+  if (CompareType == ARMISD::CMP &&
+      (CondCode == ARMCC::EQ || CondCode == ARMCC::NE)) {
     CompareType = ARMISD::CMPZ;
-    break;
-  }
-
-  // TODO: Remove CMPZ check once we generalize and remove the CMPZ enum from
-  // the codebase.
-
-  // TODO: When we have a solution to the vselect predicate not allowing pl/mi
-  // all the time, allow those cases to be cmn too no matter what.
-  if (CompareType != ARMISD::CMPZ && isCMN(RHS, CC, DAG)) {
-    CompareType = ARMISD::CMN;
-    RHS = RHS.getOperand(1);
-  } else if (CompareType != ARMISD::CMPZ && isCMN(LHS, CC, DAG)) {
-    CompareType = ARMISD::CMN;
-    LHS = LHS.getOperand(1);
-    CondCode = IntCCToARMCC(ISD::getSetCCSwappedOperands(CC));
   }
 
   ARMcc = DAG.getConstant(CondCode, dl, MVT::i32);
@@ -5196,6 +5187,13 @@ static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal,
   return TrueVal;
 }
 
+static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG) {
+  ARMCC::CondCodes CondCode =
+      (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
+  CondCode = ARMCC::getOppositeCondition(CondCode);
+  return DAG.getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
+}
+
 SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
   EVT VT = Op.getValueType();
   SDLoc dl(Op);
@@ -5296,22 +5294,25 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
     // inverting the compare condition, swapping 'less' and 'greater') and
     // sometimes need to swap the operands to the VSEL (which inverts the
     // condition in the sense of firing whenever the previous condition didn't)
-    if (Subtarget->hasFPARMv8Base() && (TrueVal.getValueType() == MVT::f16 ||
+    bool hasVSelRestrictions =
+        Subtarget->hasFPARMv8Base() && (TrueVal.getValueType() == MVT::f16 ||
                                         TrueVal.getValueType() == MVT::f32 ||
-                                        TrueVal.getValueType() == MVT::f64)) {
-      ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
-      if (CondCode == ARMCC::LT || CondCode == ARMCC::LE ||
-          CondCode == ARMCC::VC || CondCode == ARMCC::NE) {
-        CC = ISD::getSetCCInverse(CC, LHS.getValueType());
+                                        TrueVal.getValueType() == MVT::f64);
+
+    SDValue ARMcc;
+    SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl, hasVSelRestrictions);
+
+    if (hasVSelRestrictions) {
+      // No MI or PL
+      switch (ARMcc->getAsZExtVal()) {
+      case ARMCC::LT:
+      case ARMCC::LE:
+      case ARMCC::VC:
+      case ARMCC::NE:
+        ARMcc = getInvertedARMCondCode(ARMcc, DAG);
         std::swap(TrueVal, FalseVal);
       }
     }
-
-    SDValue ARMcc;
-    SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
-    // Choose GE over PL, which vsel does now support
-    if (ARMcc->getAsZExtVal() == ARMCC::PL)
-      ARMcc = DAG.getConstant(ARMCC::GE, dl, MVT::i32);
     return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
   }
 
@@ -5478,13 +5479,6 @@ SDValue ARMTargetLowering::LowerABS(SDValue Op, SelectionDAG &DAG) const {
                      DAG.getConstant(ARMCC::MI, DL, MVT::i32), Cmp);
 }
 
-static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG) {
-  ARMCC::CondCodes CondCode =
-      (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
-  CondCode = ARMCC::getOppositeCondition(CondCode);
-  return DAG.getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
-}
-
 SDValue ARMTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
   SDValue Chain = Op.getOperand(0);
   SDValue Cond = Op.getOperand(1);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index e58d872c548e4..8e5a67c661d5e 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -702,7 +702,8 @@ class VectorType;
     SDValue getCMOV(const SDLoc &dl, EVT VT, SDValue FalseVal, SDValue TrueVal,
                     SDValue ARMcc, SDValue Flags, SelectionDAG &DAG) const;
     SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                      SDValue &ARMcc, SelectionDAG &DAG, const SDLoc &dl) const;
+                      SDValue &ARMcc, SelectionDAG &DAG, const SDLoc &dl,
+                      bool ForbidMIandPL = false) const;
     SDValue getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
                       const SDLoc &dl, bool Signaling = false) const;
 
diff --git a/llvm/test/CodeGen/ARM/consthoist-icmpimm.ll b/llvm/test/CodeGen/ARM/consthoist-icmpimm.ll
index 16b7403bdb932..fc0f9b6c16700 100644
--- a/llvm/test/CodeGen/ARM/consthoist-icmpimm.ll
+++ b/llvm/test/CodeGen/ARM/consthoist-icmpimm.ll
@@ -14,16 +14,16 @@ define i32 @icmp64_sge_0(i64 %x, i64 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  @ %bb.1: @ %then
 ; CHECKV6M-NEXT:    cmp r3, #0
 ; CHECKV6M-NEXT:    mov r3, r0
-; CHECKV6M-NEXT:    blt .LBB0_7
+; CHECKV6M-NEXT:    bmi .LBB0_7
 ; CHECKV6M-NEXT:  @ %bb.2: @ %then
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    blt .LBB0_8
+; CHECKV6M-NEXT:    bmi .LBB0_8
 ; CHECKV6M-NEXT:  .LBB0_3: @ %then
 ; CHECKV6M-NEXT:    adds r0, r0, r3
 ; CHECKV6M-NEXT:    bx lr
 ; CHECKV6M-NEXT:  .LBB0_4: @ %else
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    bge .LBB0_6
+; CHECKV6M-NEXT:    bpl .LBB0_6
 ; CHECKV6M-NEXT:  @ %bb.5: @ %else
 ; CHECKV6M-NEXT:    mov r0, r2
 ; CHECKV6M-NEXT:  .LBB0_6: @ %else
@@ -31,7 +31,7 @@ define i32 @icmp64_sge_0(i64 %x, i64 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  .LBB0_7: @ %then
 ; CHECKV6M-NEXT:    mov r3, r2
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    bge .LBB0_3
+; CHECKV6M-NEXT:    bpl .LBB0_3
 ; CHECKV6M-NEXT:  .LBB0_8: @ %then
 ; CHECKV6M-NEXT:    mov r0, r2
 ; CHECKV6M-NEXT:    adds r0, r0, r3
@@ -105,16 +105,16 @@ define i32 @icmp64_sgt_m1(i64 %x, i64 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  @ %bb.1: @ %then
 ; CHECKV6M-NEXT:    cmp r3, #0
 ; CHECKV6M-NEXT:    mov r3, r0
-; CHECKV6M-NEXT:    blt .LBB1_7
+; CHECKV6M-NEXT:    bmi .LBB1_7
 ; CHECKV6M-NEXT:  @ %bb.2: @ %then
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    blt .LBB1_8
+; CHECKV6M-NEXT:    bmi .LBB1_8
 ; CHECKV6M-NEXT:  .LBB1_3: @ %then
 ; CHECKV6M-NEXT:    adds r0, r0, r3
 ; CHECKV6M-NEXT:    bx lr
 ; CHECKV6M-NEXT:  .LBB1_4: @ %else
 ; CHECKV6M-NEXT:    cmp r3, #0
-; CHECKV6M-NEXT:    bge .LBB1_6
+; CHECKV6M-NEXT:    bpl .LBB1_6
 ; CHECKV6M-NEXT:  @ %bb.5: @ %else
 ; CHECKV6M-NEXT:    mov r0, r2
 ; CHECKV6M-NEXT:  .LBB1_6: @ %else
@@ -122,7 +122,7 @@ define i32 @icmp64_sgt_m1(i64 %x, i64 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  .LBB1_7: @ %then
 ; CHECKV6M-NEXT:    mov r3, r2
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    bge .LBB1_3
+; CHECKV6M-NEXT:    bpl .LBB1_3
 ; CHECKV6M-NEXT:  .LBB1_8: @ %then
 ; CHECKV6M-NEXT:    mov r0, r2
 ; CHECKV6M-NEXT:    adds r0, r0, r3
@@ -196,16 +196,16 @@ define i32 @icmp32_sge_0(i32 %x, i32 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  @ %bb.1: @ %then
 ; CHECKV6M-NEXT:    cmp r1, #0
 ; CHECKV6M-NEXT:    mov r1, r2
-; CHECKV6M-NEXT:    blt .LBB2_7
+; CHECKV6M-NEXT:    bmi .LBB2_7
 ; CHECKV6M-NEXT:  @ %bb.2: @ %then
 ; CHECKV6M-NEXT:    cmp r0, #0
-; CHECKV6M-NEXT:    blt .LBB2_8
+; CHECKV6M-NEXT:    bmi .LBB2_8
 ; CHECKV6M-NEXT:  .LBB2_3: @ %then
 ; CHECKV6M-NEXT:    adds r0, r2, r1
 ; CHECKV6M-NEXT:    pop {r4, pc}
 ; CHECKV6M-NEXT:  .LBB2_4: @ %else
 ; CHECKV6M-NEXT:    cmp r0, #0
-; CHECKV6M-NEXT:    bge .LBB2_6
+; CHECKV6M-NEXT:    bpl .LBB2_6
 ; CHECKV6M-NEXT:  @ %bb.5: @ %else
 ; CHECKV6M-NEXT:    mov r2, r3
 ; CHECKV6M-NEXT:  .LBB2_6: @ %else
@@ -214,7 +214,7 @@ define i32 @icmp32_sge_0(i32 %x, i32 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  .LBB2_7: @ %then
 ; CHECKV6M-NEXT:    mov r1, r3
 ; CHECKV6M-NEXT:    cmp r0, #0
-; CHECKV6M-NEXT:    bge .LBB2_3
+; CHECKV6M-NEXT:    bpl .LBB2_3
 ; CHECKV6M-NEXT:  .LBB2_8: @ %then
 ; CHECKV6M-NEXT:    mov r2, r3
 ; CHECKV6M-NEXT:    adds r0, r2, r1
@@ -290,16 +290,16 @@ define i32 @icmp32_sgt_m1(i32 %x, i32 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  @ %bb.1: @ %then
 ; CHECKV6M-NEXT:    cmp r1, #0
 ; CHECKV6M-NEXT:    mov r1, r2
-; CHECKV6M-NEXT:    blt .LBB3_7
+; CHECKV6M-NEXT:    bmi .LBB3_7
 ; CHECKV6M-NEXT:  @ %bb.2: @ %then
 ; CHECKV6M-NEXT:    cmp r0, #0
-; CHECKV6M-NEXT:    blt .LBB3_8
+; CHECKV6M-NEXT:    bmi .LBB3_8
 ; CHECKV6M-NEXT:  .LBB3_3: @ %then
 ; CHECKV6M-NEXT:    adds r0, r2, r1
 ; CHECKV6M-NEXT:    pop {r4, pc}
 ; CHECKV6M-NEXT:  .LBB3_4: @ %else
 ; CHECKV6M-NEXT:    cmp r1, #0
-; CHECKV6M-NEXT:    bge .LBB3_6
+; CHECKV6M-NEXT:    bpl .LBB3_6
 ; CHECKV6M-NEXT:  @ %bb.5: @ %else
 ; CHECKV6M-NEXT:    mov r2, r3
 ; CHECKV6M-NEXT:  .LBB3_6: @ %else
@@ -308,7 +308,7 @@ define i32 @icmp32_sgt_m1(i32 %x, i32 %y, i32 %a, i32 %b, i1 %c) {
 ; CHECKV6M-NEXT:  .LBB3_7: @ %then
 ; CHECKV6M-NEXT:    mov r1, r3
 ; CHECKV6M-NEXT:    cmp r0, #0
-; CHECKV6M-NEXT:    bge .LBB3_3
+; CHECKV6M-NEXT:    bpl .LBB3_3
 ; CHECKV6M-NEXT:  .LBB3_8: @ %then
 ; CHECKV6M-NEXT:    mov r2, r3
 ; CHECKV6M-NEXT:    adds r0, r2, r1
diff --git a/llvm/test/CodeGen/ARM/select-constant-xor.ll b/llvm/test/CodeGen/ARM/select-constant-xor.ll
index 543ddcd3efac9..cce20f669bafb 100644
--- a/llvm/test/CodeGen/ARM/select-constant-xor.ll
+++ b/llvm/test/CodeGen/ARM/select-constant-xor.ll
@@ -87,7 +87,7 @@ define i32 @selecti64i32(i64 %a) {
 ; CHECK6M:       @ %bb.0:
 ; CHECK6M-NEXT:    ldr r0, .LCPI2_0
 ; CHECK6M-NEXT:    cmp r1, #0
-; CHECK6M-NEXT:    bge .LBB2_2
+; CHECK6M-NEXT:    bpl .LBB2_2
 ; CHECK6M-NEXT:  @ %bb.1:
 ; CHECK6M-NEXT:    adds r0, r0, #1
 ; CHECK6M-NEXT:  .LBB2_2:
@@ -328,7 +328,7 @@ define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) {
 ; CHECK6M-LABEL: icmpasrne:
 ; CHECK6M:       @ %bb.0:
 ; CHECK6M-NEXT:    cmp r0, #0
-; CHECK6M-NEXT:    bge .LBB9_2
+; CHECK6M-NEXT:    bpl .LBB9_2
 ; CHECK6M-NEXT:  @ %bb.1:
 ; CHECK6M-NEXT:    mov r1, r2
 ; CHECK6M-NEXT:  .LBB9_2:
diff --git a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
index 52921f0f347b9..dbff58806284d 100644
--- a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
+++ b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
@@ -456,7 +456,7 @@ define i64 @func7(i64 %x, i64 %y) nounwind {
 ; ARM-NEXT:    adcs r7, r2
 ; ARM-NEXT:    cmp r3, #0
 ; ARM-NEXT:    mov r3, r0
-; ARM-NEXT:    bge .LBB6_8
+; ARM-NEXT:    bpl .LBB6_8
 ; ARM-NEXT:  @ %bb.7:
 ; ARM-NEXT:    mov r3, r4
 ; ARM-NEXT:  .LBB6_8:

``````````

</details>


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


More information about the llvm-commits mailing list