[llvm] [ARM] Swap sides of cmp/cmn based on folding ability (PR #191915)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 17:10:53 PDT 2026
https://github.com/SiliconA-Z updated https://github.com/llvm/llvm-project/pull/191915
>From cae90acf57b09fdfd8e44d0c7fc703b9951414f7 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 13 Apr 2026 19:36:05 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)
---
llvm/test/CodeGen/ARM/cmp-shift.ll | 173 +++++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
create mode 100644 llvm/test/CodeGen/ARM/cmp-shift.ll
diff --git a/llvm/test/CodeGen/ARM/cmp-shift.ll b/llvm/test/CodeGen/ARM/cmp-shift.ll
new file mode 100644
index 0000000000000..6fa1d9fa6ffa7
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/cmp-shift.ll
@@ -0,0 +1,173 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=armv7 %s -o - | FileCheck %s --check-prefixes=CHECK-ARM
+; RUN: llc -mtriple=thumb-eabi -mcpu=arm7tdmi %s -o - | FileCheck %s --check-prefix=CHECK-T1
+; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK-T2
+
+declare void @otherfn()
+
+define void @cmp_shiftx(i32 %x, i32 %y) {
+; CHECK-ARM-LABEL: cmp_shiftx:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: cmp r1, r0, lsl #1
+; CHECK-ARM-NEXT: bxne lr
+; CHECK-ARM-NEXT: .LBB0_1: @ %if.then
+; CHECK-ARM-NEXT: b otherfn
+;
+; CHECK-T1-LABEL: cmp_shiftx:
+; CHECK-T1: @ %bb.0: @ %entry
+; CHECK-T1-NEXT: .save {r7, lr}
+; CHECK-T1-NEXT: push {r7, lr}
+; CHECK-T1-NEXT: lsls r0, r0, #1
+; CHECK-T1-NEXT: cmp r1, r0
+; CHECK-T1-NEXT: bne .LBB0_2
+; CHECK-T1-NEXT: @ %bb.1: @ %if.then
+; CHECK-T1-NEXT: bl otherfn
+; CHECK-T1-NEXT: .LBB0_2: @ %if.end
+; CHECK-T1-NEXT: pop {r7}
+; CHECK-T1-NEXT: pop {r0}
+; CHECK-T1-NEXT: bx r0
+;
+; CHECK-T2-LABEL: cmp_shiftx:
+; CHECK-T2: @ %bb.0: @ %entry
+; CHECK-T2-NEXT: cmp.w r1, r0, lsl #1
+; CHECK-T2-NEXT: it ne
+; CHECK-T2-NEXT: bxne lr
+; CHECK-T2-NEXT: b otherfn
+entry:
+ %shl = shl i32 %x, 1
+ %cmp = icmp eq i32 %shl, %y
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @otherfn()
+ ret void
+
+if.end: ; preds = %entry
+ ret void
+}
+
+define void @cmp_shifty(i32 %x, i32 %y) {
+; CHECK-ARM-LABEL: cmp_shifty:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: cmp r0, r1, lsl #1
+; CHECK-ARM-NEXT: bxne lr
+; CHECK-ARM-NEXT: .LBB1_1: @ %if.then
+; CHECK-ARM-NEXT: b otherfn
+;
+; CHECK-T1-LABEL: cmp_shifty:
+; CHECK-T1: @ %bb.0: @ %entry
+; CHECK-T1-NEXT: .save {r7, lr}
+; CHECK-T1-NEXT: push {r7, lr}
+; CHECK-T1-NEXT: lsls r1, r1, #1
+; CHECK-T1-NEXT: cmp r0, r1
+; CHECK-T1-NEXT: bne .LBB1_2
+; CHECK-T1-NEXT: @ %bb.1: @ %if.then
+; CHECK-T1-NEXT: bl otherfn
+; CHECK-T1-NEXT: .LBB1_2: @ %if.end
+; CHECK-T1-NEXT: pop {r7}
+; CHECK-T1-NEXT: pop {r0}
+; CHECK-T1-NEXT: bx r0
+;
+; CHECK-T2-LABEL: cmp_shifty:
+; CHECK-T2: @ %bb.0: @ %entry
+; CHECK-T2-NEXT: cmp.w r0, r1, lsl #1
+; CHECK-T2-NEXT: it ne
+; CHECK-T2-NEXT: bxne lr
+; CHECK-T2-NEXT: b otherfn
+entry:
+ %shl = shl i32 %y, 1
+ %cmp = icmp eq i32 %x, %shl
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @otherfn()
+ ret void
+
+if.end: ; preds = %entry
+ ret void
+}
+
+define void @cmn_shiftx(i32 %x, i32 %y) {
+; CHECK-ARM-LABEL: cmn_shiftx:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #0
+; CHECK-ARM-NEXT: cmp r1, r0, lsl #1
+; CHECK-ARM-NEXT: bxne lr
+; CHECK-ARM-NEXT: .LBB2_1: @ %if.then
+; CHECK-ARM-NEXT: b otherfn
+;
+; CHECK-T1-LABEL: cmn_shiftx:
+; CHECK-T1: @ %bb.0: @ %entry
+; CHECK-T1-NEXT: .save {r7, lr}
+; CHECK-T1-NEXT: push {r7, lr}
+; CHECK-T1-NEXT: lsls r0, r0, #1
+; CHECK-T1-NEXT: cmn r0, r1
+; CHECK-T1-NEXT: bne .LBB2_2
+; CHECK-T1-NEXT: @ %bb.1: @ %if.then
+; CHECK-T1-NEXT: bl otherfn
+; CHECK-T1-NEXT: .LBB2_2: @ %if.end
+; CHECK-T1-NEXT: pop {r7}
+; CHECK-T1-NEXT: pop {r0}
+; CHECK-T1-NEXT: bx r0
+;
+; CHECK-T2-LABEL: cmn_shiftx:
+; CHECK-T2: @ %bb.0: @ %entry
+; CHECK-T2-NEXT: rsbs r1, r1, #0
+; CHECK-T2-NEXT: cmp.w r1, r0, lsl #1
+; CHECK-T2-NEXT: it ne
+; CHECK-T2-NEXT: bxne lr
+; CHECK-T2-NEXT: b otherfn
+entry:
+ %shl = shl i32 %x, 1
+ %sub = sub nsw i32 0, %y
+ %cmp = icmp eq i32 %shl, %sub
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @otherfn()
+ ret void
+
+if.end: ; preds = %entry
+ ret void
+}
+
+define void @cmn_shifty(i32 %x, i32 %y) {
+; CHECK-ARM-LABEL: cmn_shifty:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: cmn r0, r1, lsl #1
+; CHECK-ARM-NEXT: bxne lr
+; CHECK-ARM-NEXT: .LBB3_1: @ %if.then
+; CHECK-ARM-NEXT: b otherfn
+;
+; CHECK-T1-LABEL: cmn_shifty:
+; CHECK-T1: @ %bb.0: @ %entry
+; CHECK-T1-NEXT: .save {r7, lr}
+; CHECK-T1-NEXT: push {r7, lr}
+; CHECK-T1-NEXT: lsls r1, r1, #1
+; CHECK-T1-NEXT: cmn r0, r1
+; CHECK-T1-NEXT: bne .LBB3_2
+; CHECK-T1-NEXT: @ %bb.1: @ %if.then
+; CHECK-T1-NEXT: bl otherfn
+; CHECK-T1-NEXT: .LBB3_2: @ %if.end
+; CHECK-T1-NEXT: pop {r7}
+; CHECK-T1-NEXT: pop {r0}
+; CHECK-T1-NEXT: bx r0
+;
+; CHECK-T2-LABEL: cmn_shifty:
+; CHECK-T2: @ %bb.0: @ %entry
+; CHECK-T2-NEXT: cmn.w r0, r1, lsl #1
+; CHECK-T2-NEXT: it ne
+; CHECK-T2-NEXT: bxne lr
+; CHECK-T2-NEXT: b otherfn
+entry:
+ %shl.neg = mul i32 %y, -2
+ %cmp = icmp eq i32 %x, %shl.neg
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @otherfn()
+ ret void
+
+if.end: ; preds = %entry
+ ret void
+}
>From 11858883f20af77045895e32d308c4af39f47757 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Thu, 16 Apr 2026 20:10:23 -0400
Subject: [PATCH 2/2] [ARM] Swap sides of cmp/cmn based on folding ability
To do this, I also had to remove from TableGen matches and have getArmCmp fold them instead.
---
llvm/lib/Target/ARM/ARMISelLowering.cpp | 105 ++++++++++++++----
llvm/lib/Target/ARM/ARMInstrInfo.td | 6 -
llvm/lib/Target/ARM/ARMInstrThumb.td | 4 -
llvm/lib/Target/ARM/ARMInstrThumb2.td | 6 -
llvm/test/CodeGen/ARM/atomic-ops-v8.ll | 16 +--
llvm/test/CodeGen/ARM/cmp-peephole.ll | 4 +-
llvm/test/CodeGen/ARM/cmp-shift.ll | 8 +-
llvm/test/CodeGen/ARM/cmp-to-cmn.ll | 6 +-
llvm/test/CodeGen/ARM/ssat.ll | 9 +-
llvm/test/CodeGen/ARM/umulo-32.ll | 2 +-
llvm/test/CodeGen/ARM/usat.ll | 13 +--
.../Thumb2/LowOverheadLoops/reductions.ll | 12 +-
12 files changed, 113 insertions(+), 78 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 0ad6c07f36868..5baec4e59eb95 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -4482,11 +4482,45 @@ static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG) {
(isSignedIntSetCC(CC) && isSafeSignedCMN(Op, DAG)));
}
+/// Returns a relative score for putting \p Op on the cmp/cmn **second** operand
+/// (ARM \p so_reg_imm / Thumb-2 \p t2_so_reg). Unlike AArch64, ARM does **not**
+/// fold zero/sign extends (uxtb/uxth style) into that operand—TableGen only
+/// matches \p shl, \p srl, \p sra, \p rotr for those ComplexPatterns.
+static unsigned getCmpOperandFoldingProfit(SDValue Op, const ARMSubtarget &ST) {
+ // Thumb-1 compare does not use the same shifted-second-operand forms as
+ // Thumb-2 / ARM-mode CMP/CMN.
+ if (ST.isThumb1Only())
+ return 0;
+
+ if (!Op.hasOneUse())
+ return 0;
+
+ unsigned Opc = Op.getOpcode();
+ if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA ||
+ Opc == ISD::ROTR) {
+ if (ConstantSDNode *Amnt = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
+ unsigned Shift = Amnt->getZExtValue();
+ if (Shift <= 31)
+ return 1;
+ return 0;
+ }
+ }
+
+ // Register-specified shift: ARM-mode CMP/CMN (so_reg_reg). Thumb-2
+ // t2_so_reg is immediate shift only.
+ if (!ST.isThumb())
+ return 1;
+
+ return 0;
+}
+
/// Returns appropriate ARM CMP (cmp) and corresponding condition code for
/// the given operands.
SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
SDValue &ARMcc, SelectionDAG &DAG,
const SDLoc &dl) const {
+
+ bool SwapProfitGuard = false;
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
unsigned C = RHSC->getZExtValue();
if (!isLegalICmpImmediate((int32_t)C)) {
@@ -4523,12 +4557,39 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
break;
}
}
- } else if ((ARM_AM::getShiftOpcForNode(LHS.getOpcode()) != ARM_AM::no_shift) &&
- (ARM_AM::getShiftOpcForNode(RHS.getOpcode()) == ARM_AM::no_shift)) {
+ } else if (!Subtarget->isThumb1Only() &&
+ (ARM_AM::getShiftOpcForNode(LHS.getOpcode()) !=
+ ARM_AM::no_shift) &&
+ (ARM_AM::getShiftOpcForNode(RHS.getOpcode()) ==
+ ARM_AM::no_shift)) {
// In ARM and Thumb-2, the compare instructions can shift their second
// operand.
CC = ISD::getSetCCSwappedOperands(CC);
std::swap(LHS, RHS);
+ SwapProfitGuard = true;
+ }
+
+ // Prefer folding shifts / CMN into the cmp/cmn second operand (so_reg /
+ // t2_so_reg). When both sides compete, pick the higher
+ // getCmpOperandFoldingProfit (operands are peeled if CMN). Only when RHS
+ // is not a legal icmp immediate: otherwise keep the canonical (reg, imm)
+ // form.
+ if (!SwapProfitGuard) {
+ bool RHSFitsICmpImmediate = false;
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS.getNode()))
+ RHSFitsICmpImmediate = isLegalICmpImmediate(C->getSExtValue());
+ if (!isa<ConstantSDNode>(RHS) || !RHSFitsICmpImmediate) {
+ bool LHSIsCMN = isCMN(LHS, CC, DAG);
+ bool RHSIsCMN = isCMN(RHS, CC, DAG);
+ SDValue TheLHS = LHSIsCMN ? LHS.getOperand(1) : LHS;
+ SDValue TheRHS = RHSIsCMN ? RHS.getOperand(1) : RHS;
+
+ if (getCmpOperandFoldingProfit(TheLHS, *Subtarget) + (LHSIsCMN ? 1 : 0) >
+ getCmpOperandFoldingProfit(TheRHS, *Subtarget) + (RHSIsCMN ? 1 : 0)) {
+ std::swap(LHS, RHS);
+ CC = ISD::getSetCCSwappedOperands(CC);
+ }
+ }
}
// Thumb1 has very limited immediate modes, so turning an "and" into a
@@ -4589,21 +4650,6 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode 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)) {
- switch (CondCode) {
- default: break;
- case ARMCC::GE:
- CondCode = ARMCC::PL;
- break;
- case ARMCC::LT:
- CondCode = ARMCC::MI;
- break;
- }
- }
-
unsigned CompareType;
switch (CondCode) {
default:
@@ -4616,20 +4662,31 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
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)) {
+ if (isCMN(RHS, CC, DAG)) {
CompareType = ARMISD::CMN;
RHS = RHS.getOperand(1);
- } else if (CompareType != ARMISD::CMPZ && isCMN(LHS, CC, DAG)) {
+ } else if (isCMN(LHS, CC, DAG)) {
CompareType = ARMISD::CMN;
LHS = LHS.getOperand(1);
CondCode = IntCCToARMCC(ISD::getSetCCSwappedOperands(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)) {
+ switch (CondCode) {
+ default:
+ break;
+ case ARMCC::GE:
+ CondCode = ARMCC::PL;
+ break;
+ case ARMCC::LT:
+ CondCode = ARMCC::MI;
+ break;
+ }
+ }
+
ARMcc = DAG.getConstant(CondCode, dl, MVT::i32);
return DAG.getNode(CompareType, dl, FlagsVT, LHS, RHS);
}
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index c74c84a2602b1..005fc867841d7 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -5140,12 +5140,6 @@ def : ARMPat<(ARMcmp GPR:$src, mod_imm_neg:$imm),
(CMNri GPR:$src, mod_imm_neg:$imm)>;
def : ARMPat<(ARMcmpZ GPR:$src, mod_imm_neg:$imm),
(CMNri GPR:$src, mod_imm_neg:$imm)>;
-def : ARMPat<(ARMcmpZ GPR:$src, (ineg GPR:$rhs)),
- (CMNrr GPR:$src, GPR:$rhs)>;
-def : ARMPat<(ARMcmpZ GPR:$src, (ineg so_reg_imm:$rhs)),
- (CMNrsi GPR:$src, so_reg_imm:$rhs)>;
-def : ARMPat<(ARMcmpZ GPRnopc:$src, (ineg so_reg_reg:$rhs)),
- (CMNrsr GPRnopc:$src, so_reg_reg:$rhs)>;
// Note that TST/TEQ don't set all the same flags that CMP does!
defm TST : AI1_cmp_irs<0b1000, "tst",
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index 1e2e3c30a78f7..54e689ac7b5fd 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -1576,10 +1576,6 @@ def tInt_WIN_eh_sjlj_longjmp
def : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8),
(tCMPi8 tGPR:$Rn, imm0_255:$imm8)>;
-// Fold compare-equal of a negated register into CMN register form.
-def : T1Pat<(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm)),
- (tCMN tGPR:$Rn, tGPR:$Rm)>;
-
def : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm),
(tCMPr tGPR:$Rn, tGPR:$Rm)>;
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 4f0cea8b00aac..35aa5babbe7a3 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -3551,12 +3551,6 @@ def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
def : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm),
(t2CMNri GPRnopc:$src, t2_so_imm_neg:$imm)>;
-// Fold compare-to-zero of a negated register into CMN register forms.
-def : T2Pat<(ARMcmpZ GPRnopc:$Rn, (ineg rGPR:$Rm)),
- (t2CMNrr GPRnopc:$Rn, rGPR:$Rm)>;
-def : T2Pat<(ARMcmpZ GPRnopc:$Rn, (ineg t2_so_reg:$ShiftedRm)),
- (t2CMNrs GPRnopc:$Rn, t2_so_reg:$ShiftedRm)>;
-
defm t2TST : T2I_cmp_irs<0b0000, "tst", rGPR,
IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>;
diff --git a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
index d48b070aa862e..0084f1abc259f 100644
--- a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
+++ b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
@@ -590,9 +590,9 @@ define i8 @test_atomic_load_min_i8(i8 signext %offset) nounwind {
; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
+; CHECK-NEXT: cmp {{r[0-9]+}}, r{{[0-9]+}}
; Thumb mode: it le
-; CHECK: movle r[[OLDX]], r[[OLD]]
+; CHECK: mov{{le|ge}} r[[OLDX]], r[[OLD]]
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@@ -616,9 +616,9 @@ define i16 @test_atomic_load_min_i16(i16 signext %offset) nounwind {
; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
+; CHECK-NEXT: cmp {{r[0-9]+}}, r{{[0-9]+}}
; Thumb mode: it le
-; CHECK: movle r[[OLDX]], r[[OLD]]
+; CHECK: mov{{le|ge}} r[[OLDX]], r[[OLD]]
; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@@ -700,9 +700,9 @@ define i8 @test_atomic_load_max_i8(i8 signext %offset) nounwind {
; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
+; CHECK-NEXT: cmp {{r[0-9]+}}, r{{[0-9]+}}
; Thumb mode: it gt
-; CHECK: movgt r[[OLDX]], r[[OLD]]
+; CHECK: mov{{gt|lt}} r[[OLDX]], r[[OLD]]
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
@@ -726,9 +726,9 @@ define i16 @test_atomic_load_max_i16(i16 signext %offset) nounwind {
; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
+; CHECK-NEXT: cmp {{r[0-9]+}}, r{{[0-9]+}}
; Thumb mode: it gt
-; CHECK: movgt r[[OLDX]], r[[OLD]]
+; CHECK: mov{{gt|lt}} r[[OLDX]], r[[OLD]]
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
; CHECK-NEXT: cmp [[STATUS]], #0
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
diff --git a/llvm/test/CodeGen/ARM/cmp-peephole.ll b/llvm/test/CodeGen/ARM/cmp-peephole.ll
index 73888558e6647..b58243ad7837f 100644
--- a/llvm/test/CodeGen/ARM/cmp-peephole.ll
+++ b/llvm/test/CodeGen/ARM/cmp-peephole.ll
@@ -1718,7 +1718,7 @@ define void @br_on_shift_eq_reg(i32 %a, i32 %b, i32 %c) {
; THUMB-NEXT: push {r7, lr}
; THUMB-NEXT: mov r3, r0
; THUMB-NEXT: asrs r3, r1
-; THUMB-NEXT: cmp r2, r3
+; THUMB-NEXT: cmp r3, r2
; THUMB-NEXT: bne .LBB56_2
; THUMB-NEXT: @ %bb.1: @ %true_br
; THUMB-NEXT: bl consume
@@ -1762,7 +1762,7 @@ define void @br_on_shift_ne_reg(i32 %a, i32 %b, i32 %c) {
; THUMB-NEXT: push {r7, lr}
; THUMB-NEXT: mov r3, r0
; THUMB-NEXT: lsls r3, r1
-; THUMB-NEXT: cmp r2, r3
+; THUMB-NEXT: cmp r3, r2
; THUMB-NEXT: beq .LBB57_2
; THUMB-NEXT: @ %bb.1: @ %true_br
; THUMB-NEXT: bl consume
diff --git a/llvm/test/CodeGen/ARM/cmp-shift.ll b/llvm/test/CodeGen/ARM/cmp-shift.ll
index 6fa1d9fa6ffa7..a76bc748830b6 100644
--- a/llvm/test/CodeGen/ARM/cmp-shift.ll
+++ b/llvm/test/CodeGen/ARM/cmp-shift.ll
@@ -18,7 +18,7 @@ define void @cmp_shiftx(i32 %x, i32 %y) {
; CHECK-T1-NEXT: .save {r7, lr}
; CHECK-T1-NEXT: push {r7, lr}
; CHECK-T1-NEXT: lsls r0, r0, #1
-; CHECK-T1-NEXT: cmp r1, r0
+; CHECK-T1-NEXT: cmp r0, r1
; CHECK-T1-NEXT: bne .LBB0_2
; CHECK-T1-NEXT: @ %bb.1: @ %if.then
; CHECK-T1-NEXT: bl otherfn
@@ -90,8 +90,7 @@ if.end: ; preds = %entry
define void @cmn_shiftx(i32 %x, i32 %y) {
; CHECK-ARM-LABEL: cmn_shiftx:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #0
-; CHECK-ARM-NEXT: cmp r1, r0, lsl #1
+; CHECK-ARM-NEXT: cmn r1, r0, lsl #1
; CHECK-ARM-NEXT: bxne lr
; CHECK-ARM-NEXT: .LBB2_1: @ %if.then
; CHECK-ARM-NEXT: b otherfn
@@ -112,8 +111,7 @@ define void @cmn_shiftx(i32 %x, i32 %y) {
;
; CHECK-T2-LABEL: cmn_shiftx:
; CHECK-T2: @ %bb.0: @ %entry
-; CHECK-T2-NEXT: rsbs r1, r1, #0
-; CHECK-T2-NEXT: cmp.w r1, r0, lsl #1
+; CHECK-T2-NEXT: cmn.w r1, r0, lsl #1
; CHECK-T2-NEXT: it ne
; CHECK-T2-NEXT: bxne lr
; CHECK-T2-NEXT: b otherfn
diff --git a/llvm/test/CodeGen/ARM/cmp-to-cmn.ll b/llvm/test/CodeGen/ARM/cmp-to-cmn.ll
index 60ab6473dce12..82e4ea9105838 100644
--- a/llvm/test/CodeGen/ARM/cmp-to-cmn.ll
+++ b/llvm/test/CodeGen/ARM/cmp-to-cmn.ll
@@ -442,14 +442,14 @@ define i1 @cmn_swap(i32 %a, i32 %b) {
; CHECK-ARM-LABEL: cmn_swap:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: mov r2, #0
-; CHECK-ARM-NEXT: cmn r1, r0
+; CHECK-ARM-NEXT: cmn r0, r1
; CHECK-ARM-NEXT: movwlt r2, #1
; CHECK-ARM-NEXT: mov r0, r2
; CHECK-ARM-NEXT: bx lr
;
; CHECK-T1-LABEL: cmn_swap:
; CHECK-T1: @ %bb.0:
-; CHECK-T1-NEXT: cmn r1, r0
+; CHECK-T1-NEXT: cmn r0, r1
; CHECK-T1-NEXT: blt .LBB11_2
; CHECK-T1-NEXT: @ %bb.1:
; CHECK-T1-NEXT: movs r0, #0
@@ -461,7 +461,7 @@ define i1 @cmn_swap(i32 %a, i32 %b) {
; CHECK-T2-LABEL: cmn_swap:
; CHECK-T2: @ %bb.0:
; CHECK-T2-NEXT: movs r2, #0
-; CHECK-T2-NEXT: cmn r1, r0
+; CHECK-T2-NEXT: cmn r0, r1
; CHECK-T2-NEXT: it lt
; CHECK-T2-NEXT: movlt r2, #1
; CHECK-T2-NEXT: mov r0, r2
diff --git a/llvm/test/CodeGen/ARM/ssat.ll b/llvm/test/CodeGen/ARM/ssat.ll
index ed777f2b1882b..7b689a8bea140 100644
--- a/llvm/test/CodeGen/ARM/ssat.ll
+++ b/llvm/test/CodeGen/ARM/ssat.ll
@@ -52,9 +52,8 @@ define i16 @sat_base_16bit(i16 %x) #0 {
; V4T-NEXT: mov r2, #255
; V4T-NEXT: lsl r1, r0, #16
; V4T-NEXT: orr r2, r2, #1792
-; V4T-NEXT: asr r1, r1, #16
-; V4T-NEXT: cmp r1, r2
-; V4T-NEXT: movge r0, r2
+; V4T-NEXT: cmp r2, r1, asr #16
+; V4T-NEXT: movle r0, r2
; V4T-NEXT: ldr r2, .LCPI1_0
; V4T-NEXT: lsl r1, r0, #16
; V4T-NEXT: asr r1, r1, #16
@@ -70,8 +69,8 @@ define i16 @sat_base_16bit(i16 %x) #0 {
; V6T2: @ %bb.0: @ %entry
; V6T2-NEXT: sxth r1, r0
; V6T2-NEXT: movw r2, #2047
-; V6T2-NEXT: cmp r1, r2
-; V6T2-NEXT: movge r0, r2
+; V6T2-NEXT: cmp r2, r1
+; V6T2-NEXT: movle r0, r2
; V6T2-NEXT: movw r2, #63488
; V6T2-NEXT: sxth r1, r0
; V6T2-NEXT: movt r2, #65535
diff --git a/llvm/test/CodeGen/ARM/umulo-32.ll b/llvm/test/CodeGen/ARM/umulo-32.ll
index b5f6b3aa61fc3..cd0d784c89818 100644
--- a/llvm/test/CodeGen/ARM/umulo-32.ll
+++ b/llvm/test/CodeGen/ARM/umulo-32.ll
@@ -34,7 +34,7 @@ define i32 @test2(ptr %m_degree) ssp {
; CHECK-NEXT: ldr r1, [r0]
; CHECK-NEXT: lsls r0, r1, #3
; CHECK-NEXT: lsrs r2, r0, #3
-; CHECK-NEXT: subs r1, r1, r2
+; CHECK-NEXT: subs r1, r2, r1
; CHECK-NEXT: subs r2, r1, #1
; CHECK-NEXT: sbcs r1, r2
; CHECK-NEXT: movs r4, #0
diff --git a/llvm/test/CodeGen/ARM/usat.ll b/llvm/test/CodeGen/ARM/usat.ll
index 2e1d0283ebde2..3cc34629b3932 100644
--- a/llvm/test/CodeGen/ARM/usat.ll
+++ b/llvm/test/CodeGen/ARM/usat.ll
@@ -66,9 +66,8 @@ define i16 @unsigned_sat_base_16bit(i16 %x) #0 {
; V4T-NEXT: mov r2, #255
; V4T-NEXT: lsl r1, r0, #16
; V4T-NEXT: orr r2, r2, #1792
-; V4T-NEXT: asr r1, r1, #16
-; V4T-NEXT: cmp r1, r2
-; V4T-NEXT: movlt r2, r0
+; V4T-NEXT: cmp r2, r1, asr #16
+; V4T-NEXT: movgt r2, r0
; V4T-NEXT: lsl r0, r2, #16
; V4T-NEXT: bic r0, r2, r0, asr #31
; V4T-NEXT: bx lr
@@ -78,8 +77,8 @@ define i16 @unsigned_sat_base_16bit(i16 %x) #0 {
; V6-NEXT: mov r2, #255
; V6-NEXT: sxth r1, r0
; V6-NEXT: orr r2, r2, #1792
-; V6-NEXT: cmp r1, r2
-; V6-NEXT: movlt r2, r0
+; V6-NEXT: cmp r2, r1
+; V6-NEXT: movgt r2, r0
; V6-NEXT: sxth r0, r2
; V6-NEXT: bic r0, r2, r0, asr #15
; V6-NEXT: bx lr
@@ -88,8 +87,8 @@ define i16 @unsigned_sat_base_16bit(i16 %x) #0 {
; V6T2: @ %bb.0: @ %entry
; V6T2-NEXT: sxth r1, r0
; V6T2-NEXT: movw r2, #2047
-; V6T2-NEXT: cmp r1, r2
-; V6T2-NEXT: movlt r2, r0
+; V6T2-NEXT: cmp r2, r1
+; V6T2-NEXT: movgt r2, r0
; V6T2-NEXT: sxth r0, r2
; V6T2-NEXT: bic r0, r2, r0, asr #15
; V6T2-NEXT: bx lr
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
index c418038b751d7..5159306fb23d0 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
@@ -642,14 +642,12 @@ define i32 @wrongop(ptr nocapture readonly %pd) {
; CHECK-NEXT: movw r4, #23593
; CHECK-NEXT: movt r1, #163
; CHECK-NEXT: ldr r0, [r0]
-; CHECK-NEXT: movt r4, #655
-; CHECK-NEXT: ror.w r12, r3, #4
-; CHECK-NEXT: cmp r12, r1
-; CHECK-NEXT: cset r1, lo
-; CHECK-NEXT: ror.w r3, r3, #2
; CHECK-NEXT: mov.w r12, #1
-; CHECK-NEXT: cmp r3, r4
-; CHECK-NEXT: csel r3, r1, r12, lo
+; CHECK-NEXT: movt r4, #655
+; CHECK-NEXT: cmp.w r1, r3, ror #4
+; CHECK-NEXT: cset r1, hi
+; CHECK-NEXT: cmp.w r4, r3, ror #2
+; CHECK-NEXT: csel r3, r1, r12, hi
; CHECK-NEXT: lsls.w r4, lr, #30
; CHECK-NEXT: csel r1, r1, r3, ne
; CHECK-NEXT: cmp r2, #1
More information about the llvm-commits
mailing list