Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -3857,8 +3857,9 @@ const SDLoc &dl) const { if (ConstantSDNode *RHSC = dyn_cast(RHS.getNode())) { unsigned C = RHSC->getZExtValue(); - if (!isLegalICmpImmediate(C)) { - // Constant does not fit, try adjusting it by one? + if (!isLegalICmpImmediate((int32_t)C) || + (C == -1U && (CC == ISD::SETLE || CC == ISD::SETGT))) { + // Constant does not fit, try adjusting it by one. switch (CC) { default: break; case ISD::SETLT: @@ -13195,9 +13196,11 @@ bool ARMTargetLowering::isLegalICmpImmediate(int64_t Imm) const { // Thumb2 and ARM modes can use cmn for negative immediates. if (!Subtarget->isThumb()) - return ARM_AM::getSOImmVal(std::abs(Imm)) != -1; + return ARM_AM::getSOImmVal((uint32_t)Imm) != -1 || + ARM_AM::getSOImmVal(-(uint32_t)Imm) != -1; if (Subtarget->isThumb2()) - return ARM_AM::getT2SOImmVal(std::abs(Imm)) != -1; + return ARM_AM::getT2SOImmVal((uint32_t)Imm) != -1 || + ARM_AM::getT2SOImmVal(-(uint32_t)Imm) != -1; // Thumb1 doesn't have cmn, and only 8-bit immediates. return Imm >= 0 && Imm <= 255; } Index: test/CodeGen/Thumb2/thumb2-cmp.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-cmp.ll +++ test/CodeGen/Thumb2/thumb2-cmp.ll @@ -169,7 +169,7 @@ define i32 @slt_neg_soimm(i32 %a) { ; CHECK-LABEL: slt_neg_soimm: -; CHECK: mvn r1, #7929856 +; CHECK: cmn.w r0, #7929856 %b = icmp slt i32 %a, -7929856 br i1 %b, label %true, label %false @@ -208,8 +208,7 @@ define i32 @sgt_neg_soimm(i32 %a) { ; CHECK-LABEL: sgt_neg_soimm: -; CHECK: movs r1, #1 -; CHECK: movt r1, #65415 +; CHECK: cmn.w r0, #7929856 %b = icmp sgt i32 %a, -7929856 br i1 %b, label %true, label %false