summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtyom Skrobov <Artyom.Skrobov@arm.com>2017-03-13 22:36:14 +0000
committerArtyom Skrobov <Artyom.Skrobov@arm.com>2017-03-13 22:36:14 +0000
commit7a06df3cf902e79b1b80e3b4932927200fa6fd23 (patch)
tree830f3ddc6c14c1140ec7690e60fe638f8aee668f
parentbb60730437f512d4465581b88ccda2375b3f4f3e (diff)
[Thumb1] combine ADDC/SUBC with a negative immediate
Summary: This simple optimization has been split out of https://reviews.llvm.org/D30400 Reviewers: efriedma, jmolloy Subscribers: llvm-commits, rengolin Differential Revision: https://reviews.llvm.org/D30829 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297682 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp20
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td6
-rw-r--r--test/CodeGen/Thumb/long.ll14
3 files changed, 26 insertions, 14 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 598ed1ae481..ad95d988e9a 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -9660,6 +9660,24 @@ static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG,
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<ConstantSDNode>(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 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
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);
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index d7e343307e7..f205dc857ab 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -1453,12 +1453,6 @@ def : T1Pat<(ARMcmpZ tGPR:$Rn, imm0_255:$imm8),
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))>;
diff --git a/test/CodeGen/Thumb/long.ll b/test/CodeGen/Thumb/long.ll
index bf5efd4889d..e35f7cc82b1 100644
--- a/test/CodeGen/Thumb/long.ll
+++ b/test/CodeGen/Thumb/long.ll
@@ -132,8 +132,7 @@ entry:
; 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 @@ entry:
%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 @@ entry:
%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
}