Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -9789,7 +9789,7 @@ SDValue RHS = N->getOperand(1); if (ConstantSDNode *C = dyn_cast(RHS)) { int64_t imm = C->getSExtValue(); - if (imm < 0) { + if (imm < 0 && imm > -(1<<31)) { SDLoc DL(N); RHS = DAG.getConstant(-imm, DL, MVT::i32); unsigned Opcode = (N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC Index: test/CodeGen/Thumb/long.ll =================================================================== --- test/CodeGen/Thumb/long.ll +++ test/CodeGen/Thumb/long.ll @@ -144,6 +144,33 @@ ; CHECK: sbcs r1, r2 } +; i32 type represents from -2^31 to 2^31-1. Cannot transform this into +; add i64 %y, 2147483648 because Thumb addc/subc don't support MVT::i32 type. +define i64 @f9e(i64 %x, i64 %y) { +entry: + %tmp1 = sub i64 %y, -2147483648 + ret i64 %tmp1 +; CHECK-LABEL: f9e: +; CHECK: movs r0, #1 +; CHECK: lsls r0, r0, #31 +; CHECK: movs r1, #0 +; CHECK: adds r0, r2, r0 +; CHECK: adcs r1, r3 +} + +define i64 @f9f(i64 %x, i64 %y) { +entry: + %tmp1 = add i64 %y, -2147483648 + ret i64 %tmp1 +; CHECK-LABEL: f9f: +; CHECK: movs r0, #1 +; CHECK: lsls r0, r0, #31 +; CHECK: movs r1, #0 +; CHECK: adds r0, r2, r0 +; CHECK: sbcs r3, r1 +; CHECK: movs r1, r3 +} + define i64 @f(i32 %a, i32 %b) { entry: %tmp = sext i32 %a to i64 ; [#uses=1]