[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