Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp @@ -9660,6 +9660,24 @@ return SDValue(); } +static SDValue PerformAddcSubcCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { + if (Subtarget->isThumb1Only()) { + SDValue RHS = N->getOperand(1); + if (ConstantSDNode *C = dyn_cast(RHS)) { + int64_t imm = C->getSExtValue(); + if (imm < 0) { + SDLoc DL(N); + RHS = DAG.getConstant(-imm, DL, MVT::i32); + unsigned Opcode = (N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC + : ARMISD::ADDC; + return DAG.getNode(Opcode, DL, N->getVTList(), N->getOperand(0), RHS); + } + } + } + return SDValue(); +} + static SDValue PerformAddeSubeCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget) { if (Subtarget->isThumb1Only()) { @@ -11729,6 +11747,8 @@ case ISD::OR: return PerformORCombine(N, DCI, Subtarget); case ISD::XOR: return PerformXORCombine(N, DCI, Subtarget); case ISD::AND: return PerformANDCombine(N, DCI, Subtarget); + case ARMISD::ADDC: + case ARMISD::SUBC: return PerformAddcSubcCombine(N, DCI.DAG, Subtarget); case ARMISD::SUBE: return PerformAddeSubeCombine(N, DCI.DAG, Subtarget); case ARMISD::BFI: return PerformBFICombine(N, DCI); case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI, Subtarget); Index: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td @@ -1453,12 +1453,6 @@ def : T1Pat<(ARMcmpZ tGPR:$Rn, tGPR:$Rm), (tCMPr tGPR:$Rn, tGPR:$Rm)>; -// Subtract with carry -def : T1Pat<(ARMaddc tGPR:$lhs, imm0_7_neg:$rhs), - (tSUBSi3 tGPR:$lhs, imm0_7_neg:$rhs)>; -def : T1Pat<(ARMaddc tGPR:$lhs, imm8_255_neg:$rhs), - (tSUBSi8 tGPR:$lhs, imm8_255_neg:$rhs)>; - // Bswap 16 with load/store def : T1Pat<(srl (bswap (extloadi16 t_addrmode_is2:$addr)), (i32 16)), (tREV16 (tLDRHi t_addrmode_is2:$addr))>; Index: llvm/trunk/test/CodeGen/Thumb/long.ll =================================================================== --- llvm/trunk/test/CodeGen/Thumb/long.ll +++ llvm/trunk/test/CodeGen/Thumb/long.ll @@ -132,8 +132,7 @@ ; CHECK: sbcs r1, r2 } -define i64 @f9d(i64 %x, i32 %y) { ; SUBS with small negative imm => SUBS reg -; FIXME: this would be better lowered as an `ADDS imm` +define i64 @f9d(i64 %x, i32 %y) { ; SUBS with small negative imm => ADDS imm entry: %conv = sext i32 %y to i64 %shl = shl i64 %conv, 32 @@ -141,9 +140,7 @@ %sub = sub nsw i64 %x, %or ret i64 %sub ; CHECK-LABEL: f9d: -; CHECK: movs r3, #0 -; CHECK: mvns r3, r3 -; CHECK: subs r0, r0, r3 +; CHECK: adds r0, r0, #1 ; CHECK: sbcs r1, r2 } @@ -187,11 +184,12 @@ %tmp2 = add i64 %tmp1, -1000 ret i64 %tmp2 ; CHECK-LABEL: f11: +; CHECK: movs r0, #125 +; CHECK: lsls r0, r0, #3 ; CHECK: movs r1, #0 -; CHECK: ldr r0, -; CHECK: adds r2, r2, r0 +; CHECK: subs r2, r2, r0 ; CHECK: sbcs r3, r1 -; CHECK: adds r0, r2, r0 +; CHECK: subs r0, r2, r0 ; CHECK: sbcs r3, r1 ; CHECK: movs r1, r3 }