Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -3821,6 +3821,7 @@ SDValue ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &ARMcc, SelectionDAG &DAG, const SDLoc &dl) const { + bool SwapOperands = false; if (ConstantSDNode *RHSC = dyn_cast(RHS.getNode())) { unsigned C = RHSC->getZExtValue(); if (!isLegalICmpImmediate(C)) { @@ -3857,9 +3858,17 @@ 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. + SwapOperands = true; ARMCC::CondCodes CondCode = IntCCToARMCC(CC); + if (SwapOperands) { + CondCode = ARMCC::getOppositeCondition(CondCode); + std::swap(LHS, RHS); + } ARMISD::NodeType CompareType; switch (CondCode) { default: Index: test/CodeGen/ARM/cmp-shift-swap.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/cmp-shift-swap.ll @@ -0,0 +1,43 @@ +; RUN: llc -mtriple=armv7 %s -o - | FileCheck %s + +; CHECK-LABEL: swap_cmp_shl +; CHECK: cmp r1, r0, lsl #11 +define arm_aapcscc i32 @swap_cmp_shl(i32 %a, i32 %b) { +entry: + %shift = shl i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_lshr +; CHECK: cmp r1, r0, lsr #11 +define arm_aapcscc i32 @swap_cmp_lshr(i32 %a, i32 %b) { +entry: + %shift = lshr i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_ashr +; CHECK: cmp r1, r0, asr #11 +define arm_aapcscc i32 @swap_cmp_ashr(i32 %a, i32 %b) { +entry: + %shift = ashr i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_rotr +; CHECK: cmp r1, r0, ror #11 +define arm_aapcscc i32 @swap_cmp_rotr(i32 %a, i32 %b) { +entry: + %lsr = lshr i32 %a, 11 + %lsl = shl i32 %a, 21 + %ror = or i32 %lsr, %lsl + %cmp = icmp sgt i32 %ror, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} Index: test/CodeGen/Thumb2/thumb2-cmp2.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-cmp2.ll +++ test/CodeGen/Thumb2/thumb2-cmp2.ll @@ -50,3 +50,45 @@ %tmp1 = icmp ne i32 %a, %tmp ret i1 %tmp1 } + +; CHECK-LABEL: swap_cmp_shl +; CHECK: cmp.w r1, r0, lsl #11 +define arm_aapcscc i32 @swap_cmp_shl(i32 %a, i32 %b) { +entry: + %shift = shl i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_lshr +; CHECK: cmp.w r1, r0, lsr #11 +define arm_aapcscc i32 @swap_cmp_lshr(i32 %a, i32 %b) { +entry: + %shift = lshr i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_ashr +; CHECK: cmp.w r1, r0, asr #11 +define arm_aapcscc i32 @swap_cmp_ashr(i32 %a, i32 %b) { +entry: + %shift = ashr i32 %a, 11 + %cmp = icmp sgt i32 %shift, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-LABEL: swap_cmp_rotr +; CHECK: cmp.w r1, r0, ror #11 +define arm_aapcscc i32 @swap_cmp_rotr(i32 %a, i32 %b) { +entry: + %lsr = lshr i32 %a, 11 + %lsl = shl i32 %a, 21 + %rotr = or i32 %lsr, %lsl + %cmp = icmp sgt i32 %rotr, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +}