Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -5501,6 +5501,8 @@ return ForCodesize ? 4 : 1; if (ARM_AM::isSOImmTwoPartVal(Val)) // two instrs return ForCodesize ? 8 : 2; + if (ARM_AM::isSOImmTwoPartVal(-Val)) // two instrs + return ForCodesize ? 8 : 2; } if (Subtarget->useMovt()) // MOVW + MOVT return ForCodesize ? 8 : 2; Index: llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp =================================================================== --- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -873,16 +873,25 @@ // FIXME Windows CE supports older ARM CPUs assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+"); - // Expand into a movi + orr. - LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg); - HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri)) - .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) - .addReg(DstReg); - assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!"); - unsigned ImmVal = (unsigned)MO.getImm(); - unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); - unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); + unsigned ImmVal = (unsigned)MO.getImm(), SOImmValV1 = 0, SOImmValV2 = 0; + + if (ARM_AM::isSOImmTwoPartVal(ImmVal)) { // Expand into a movi + orr. + LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg); + HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg); + SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); + SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); + } else { // Expand into a mvni + subri. + LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), DstReg); + HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg); + SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(-ImmVal); + SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(-ImmVal); + } + unsigned MIFlags = MI.getFlags(); LO16 = LO16.addImm(SOImmValV1); HI16 = HI16.addImm(SOImmValV2); Index: llvm/lib/Target/ARM/ARMInstrInfo.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrInfo.td +++ llvm/lib/Target/ARM/ARMInstrInfo.td @@ -812,7 +812,9 @@ def arm_i32imm : IntImmLeafuseMovt()) return true; - return ARM_AM::isSOImmTwoPartVal(Imm.getZExtValue()); + if (ARM_AM::isSOImmTwoPartVal(Imm.getZExtValue())) + return true; + return ARM_AM::isSOImmTwoPartVal(-Imm.getZExtValue()); }]>; /// imm0_1 predicate - Immediate in the range [0,1]. Index: llvm/test/CodeGen/ARM/select-imm.ll =================================================================== --- llvm/test/CodeGen/ARM/select-imm.ll +++ llvm/test/CodeGen/ARM/select-imm.ll @@ -85,7 +85,8 @@ define i32 @t4(i32 %a, i32 %b, i32 %x) nounwind { entry: ; ARM-LABEL: t4: -; ARM: ldr +; ARM: mvn [[R0:r[0-9]+]], #171 +; ARM: sub [[R0:r[0-9]+]], [[R0:r[0-9]+]], #11141120 ; ARM: mov{{lt|ge}} ; ARMT2-LABEL: t4: