[llvm] [ARM] Swap sides of cmp/cmn based on folding ability (PR #191915)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 22 13:56:34 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/191915

>From 9363e44acf78d4be8cf1b33b53afdb8155a9848b Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 20 Jun 2026 14:46:11 -0400
Subject: [PATCH 1/2] Pre-commit tests (NFC)

---
 llvm/test/CodeGen/ARM/cmn-shift.ll | 116 +++++++++++++++++++++++++++++
 1 file changed, 116 insertions(+)
 create mode 100644 llvm/test/CodeGen/ARM/cmn-shift.ll

diff --git a/llvm/test/CodeGen/ARM/cmn-shift.ll b/llvm/test/CodeGen/ARM/cmn-shift.ll
new file mode 100644
index 0000000000000..ef7fa6858a3df
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/cmn-shift.ll
@@ -0,0 +1,116 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck -check-prefix=ARM %s
+; RUN: llc -mtriple=thumbv7-eabi %s -o - | FileCheck -check-prefix=THUMB %s
+
+declare void @otherfn()
+
+define void @cmp_shiftx(i32 %a, i32 %b) {
+; ARM-LABEL: cmp_shiftx:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    cmp r1, r0, lsl #1
+; ARM-NEXT:    movne pc, lr
+; ARM-NEXT:  .LBB0_1: @ %if.then
+; ARM-NEXT:    b otherfn
+;
+; THUMB-LABEL: cmp_shiftx:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    cmp.w r1, r0, lsl #1
+; THUMB-NEXT:    it ne
+; THUMB-NEXT:    bxne lr
+; THUMB-NEXT:    b otherfn
+entry:
+  %shl = shl i32 %a, 1
+  %cmp = icmp eq i32 %shl, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @otherfn()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define void @cmp_shifty(i32 %a, i32 %b) {
+; ARM-LABEL: cmp_shifty:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    cmp r0, r1, lsl #1
+; ARM-NEXT:    movne pc, lr
+; ARM-NEXT:  .LBB1_1: @ %if.then
+; ARM-NEXT:    b otherfn
+;
+; THUMB-LABEL: cmp_shifty:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    cmp.w r0, r1, lsl #1
+; THUMB-NEXT:    it ne
+; THUMB-NEXT:    bxne lr
+; THUMB-NEXT:    b otherfn
+entry:
+  %shl = shl i32 %b, 1
+  %cmp = icmp eq i32 %a, %shl
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @otherfn()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define void @cmn_shiftx(i32 %a, i32 %b) {
+; ARM-LABEL: cmn_shiftx:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    rsb r1, r1, #0
+; ARM-NEXT:    cmp r1, r0, lsl #1
+; ARM-NEXT:    movne pc, lr
+; ARM-NEXT:  .LBB2_1: @ %if.then
+; ARM-NEXT:    b otherfn
+;
+; THUMB-LABEL: cmn_shiftx:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    rsbs r1, r1, #0
+; THUMB-NEXT:    cmp.w r1, r0, lsl #1
+; THUMB-NEXT:    it ne
+; THUMB-NEXT:    bxne lr
+; THUMB-NEXT:    b otherfn
+entry:
+  %shl = shl i32 %a, 1
+  %sub = sub nsw i32 0, %b
+  %cmp = icmp eq i32 %shl, %sub
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @otherfn()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define void @cmn_shifty(i32 %a, i32 %b) {
+; ARM-LABEL: cmn_shifty:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    cmn r0, r1, lsl #1
+; ARM-NEXT:    movne pc, lr
+; ARM-NEXT:  .LBB3_1: @ %if.then
+; ARM-NEXT:    b otherfn
+;
+; THUMB-LABEL: cmn_shifty:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    cmn.w r0, r1, lsl #1
+; THUMB-NEXT:    it ne
+; THUMB-NEXT:    bxne lr
+; THUMB-NEXT:    b otherfn
+entry:
+  %mul = mul i32 %b, -2
+  %cmp = icmp eq i32 %a, %mul
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @otherfn()
+  br label %if.end
+
+if.end:
+  ret void
+}

>From e260ae2dc27d142fadf4269c314878af35daa44d Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 20 Jun 2026 12:10:54 -0400
Subject: [PATCH 2/2] [ARM] Swap sides of cmp/cmn based on folding ability

If we can fold lsl, lsr, rotr, or asr into the right side of the compare, we should do so.

Add missing patterns for folding to the side.
---
 llvm/lib/Target/ARM/ARMISelLowering.cpp       | 95 ++++++++++++++-----
 llvm/lib/Target/ARM/ARMInstrInfo.td           |  4 +
 llvm/lib/Target/ARM/ARMInstrThumb2.td         |  2 +
 llvm/test/CodeGen/ARM/atomic-ops-v8.ll        | 16 ++--
 llvm/test/CodeGen/ARM/cmn-shift.ll            |  6 +-
 llvm/test/CodeGen/ARM/cmp-peephole.ll         |  8 +-
 llvm/test/CodeGen/ARM/cmp-to-cmn.ll           |  6 +-
 llvm/test/CodeGen/ARM/umulo-32.ll             |  2 +-
 .../Thumb2/LowOverheadLoops/reductions.ll     | 12 +--
 9 files changed, 99 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 248f5b3f9f083..c5fab4c907cde 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -4503,6 +4503,42 @@ static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG) {
           (isSignedIntSetCC(CC) && isSafeSignedCMN(Op, DAG)));
 }
 
+/// Returns how profitable it is to fold a comparison's operand's shift and/or
+/// extension operations into the comparison instruction's second operand
+/// (so_reg_imm / so_reg_reg for ARM, t2_so_reg for Thumb-2).
+static unsigned getCmpOperandFoldingProfit(SDValue Op, const ARMSubtarget &ST) {
+  // Thumb-1 CMP does not support shifted second operands.
+  if (ST.isThumb1Only() || !Op.hasOneUse())
+    return 0;
+
+  unsigned Opc = Op.getOpcode();
+  if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA) {
+    if (auto *ShiftAmt = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
+      return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
+    // Register-controlled shift: only ARM-mode CMP/CMN (so_reg_reg) supports
+    // this; Thumb-2 t2_so_reg requires an immediate shift amount.
+    return ST.isThumb() ? 0 : 1;
+  }
+
+  if (Opc == ISD::ROTR) {
+    // Rotr constants will be normalized via mod 32, or & 31,
+    // so we do not have to bounds check.
+    if (isa<ConstantSDNode>(Op.getOperand(1)))
+      return 1;
+    return ST.isThumb() ? 0 : 1;
+  }
+
+  return 0;
+}
+
+static unsigned getCmpOrCmnOperandFoldingProfit(SDValue Op, ISD::CondCode CC,
+                                                SelectionDAG &DAG,
+                                                const ARMSubtarget &ST) {
+  if (isCMN(Op, CC, DAG))
+    return getCmpOperandFoldingProfit(Op.getOperand(1), ST) + 1;
+  return getCmpOperandFoldingProfit(Op, ST);
+}
+
 /// Returns appropriate ARM CMP (cmp) and corresponding condition code for
 /// the given operands.
 SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
@@ -4544,12 +4580,22 @@ 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)) {
-    // In ARM and Thumb-2, the compare instructions can shift their second
-    // operand.
-    CC = ISD::getSetCCSwappedOperands(CC);
-    std::swap(LHS, RHS);
+  }
+
+  // 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.
+  bool RHSFitsICmpImmediate = false;
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS.getNode()))
+    RHSFitsICmpImmediate = isLegalICmpImmediate(C->getSExtValue());
+  if (!isa<ConstantSDNode>(RHS) || !RHSFitsICmpImmediate) {
+    if (getCmpOrCmnOperandFoldingProfit(LHS, CC, DAG, *Subtarget) >
+        getCmpOrCmnOperandFoldingProfit(RHS, CC, DAG, *Subtarget)) {
+      std::swap(LHS, RHS);
+      CC = ISD::getSetCCSwappedOperands(CC);
+    }
   }
 
   // Thumb1 has very limited immediate modes, so turning an "and" into a
@@ -4610,21 +4656,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:
@@ -4651,6 +4682,22 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
     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);
 }
@@ -13760,8 +13807,6 @@ ARMTargetLowering::isDesirableToCommuteWithShift(const SDNode *N,
     // Avoid making expensive immediates by commuting shifts. (This logic
     // only applies to Thumb1 because ARM and Thumb2 immediates can be shifted
     // for free.)
-    if (N->getOpcode() != ISD::SHL)
-      return true;
     SDValue N1 = N->getOperand(0);
     if (N1->getOpcode() != ISD::ADD && N1->getOpcode() != ISD::AND &&
         N1->getOpcode() != ISD::OR && N1->getOpcode() != ISD::XOR)
@@ -13877,14 +13922,14 @@ static SDValue PerformSHLSimplify(SDNode *N,
   // b + ((a << 1) ^ 510)
   // b + ((a << 1) + 510)
 
-  // Many instructions can  perform the shift for free, but it requires both
+  // Many instructions can perform the shift for free, but it requires both
   // the operands to be registers. If c1 << c2 is too large, a mov immediate
   // instruction will needed. So, unfold back to the original pattern if:
   // - if c1 and c2 are small enough that they don't require mov imms.
   // - the user(s) of the node can perform an shl
 
   // No shifted operands for 16-bit instructions.
-  if (ST->isThumb() && ST->isThumb1Only())
+  if (ST->isThumb1Only())
     return SDValue();
 
   // Check that all the users could perform the shl themselves.
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 4f80746fd8bc5..397342841a89b 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -5145,8 +5145,12 @@ 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 (ineg GPR:$Rn), so_reg_imm:$ShiftedRm),
+             (CMNrsi GPR:$Rn, so_reg_imm:$ShiftedRm)>;
 def : ARMPat<(ARMcmpZ GPRnopc:$src, (ineg so_reg_reg:$rhs)),
              (CMNrsr GPRnopc:$src, so_reg_reg:$rhs)>;
+def : ARMPat<(ARMcmpZ (ineg GPRnopc:$Rn), so_reg_reg:$ShiftedRm),
+             (CMNrsr GPRnopc:$Rn, so_reg_reg:$ShiftedRm)>;
 
 // 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/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 228baa9df6226..3ce2c3eb5a95b 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -3557,6 +3557,8 @@ 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)>;
+def : T2Pat<(ARMcmpZ (ineg GPRnopc:$Rn), 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,
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/cmn-shift.ll b/llvm/test/CodeGen/ARM/cmn-shift.ll
index ef7fa6858a3df..3836a671701c9 100644
--- a/llvm/test/CodeGen/ARM/cmn-shift.ll
+++ b/llvm/test/CodeGen/ARM/cmn-shift.ll
@@ -61,16 +61,14 @@ if.end:
 define void @cmn_shiftx(i32 %a, i32 %b) {
 ; ARM-LABEL: cmn_shiftx:
 ; ARM:       @ %bb.0: @ %entry
-; ARM-NEXT:    rsb r1, r1, #0
-; ARM-NEXT:    cmp r1, r0, lsl #1
+; ARM-NEXT:    cmn r1, r0, lsl #1
 ; ARM-NEXT:    movne pc, lr
 ; ARM-NEXT:  .LBB2_1: @ %if.then
 ; ARM-NEXT:    b otherfn
 ;
 ; THUMB-LABEL: cmn_shiftx:
 ; THUMB:       @ %bb.0: @ %entry
-; THUMB-NEXT:    rsbs r1, r1, #0
-; THUMB-NEXT:    cmp.w r1, r0, lsl #1
+; THUMB-NEXT:    cmn.w r1, r0, lsl #1
 ; THUMB-NEXT:    it ne
 ; THUMB-NEXT:    bxne lr
 ; THUMB-NEXT:    b otherfn
diff --git a/llvm/test/CodeGen/ARM/cmp-peephole.ll b/llvm/test/CodeGen/ARM/cmp-peephole.ll
index 73888558e6647..55ed38c0ebe40 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
@@ -1728,7 +1728,7 @@ define void @br_on_shift_eq_reg(i32 %a, i32 %b, i32 %c) {
 ; THUMB2-LABEL: br_on_shift_eq_reg:
 ; THUMB2:       @ %bb.0:
 ; THUMB2-NEXT:    asr.w r1, r0, r1
-; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    cmp r1, r2
 ; THUMB2-NEXT:    it ne
 ; THUMB2-NEXT:    bxne lr
 ; THUMB2-NEXT:  .LBB56_1: @ %true_br
@@ -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
@@ -1772,7 +1772,7 @@ define void @br_on_shift_ne_reg(i32 %a, i32 %b, i32 %c) {
 ; THUMB2-LABEL: br_on_shift_ne_reg:
 ; THUMB2:       @ %bb.0:
 ; THUMB2-NEXT:    lsl.w r1, r0, r1
-; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    cmp r1, r2
 ; THUMB2-NEXT:    it eq
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:  .LBB57_1: @ %true_br
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/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/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