aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Target/XCore/XCoreISelLowering.cpp30
-rw-r--r--test/CodeGen/XCore/ladd_lsub_combine.ll39
2 files changed, 69 insertions, 0 deletions
diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp
index d8cbd037cb..7ecd15135a 100644
--- a/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/lib/Target/XCore/XCoreISelLowering.cpp
@@ -1117,6 +1117,21 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
SDValue Ops [] = { Carry, Result };
return DAG.getMergeValues(Ops, 2, dl);
}
+
+ // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
+ // low bit set
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
+ VT.getSizeInBits() - 1);
+ DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
+ if (KnownZero == Mask) {
+ SDValue Carry = DAG.getConstant(0, VT);
+ SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
+ SDValue Ops [] = { Carry, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+ }
}
break;
case XCoreISD::LSUB: {
@@ -1141,6 +1156,21 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
return DAG.getMergeValues(Ops, 2, dl);
}
}
+
+ // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
+ // low bit set
+ if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
+ VT.getSizeInBits() - 1);
+ DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
+ if (KnownZero == Mask) {
+ SDValue Borrow = DAG.getConstant(0, VT);
+ SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
+ SDValue Ops [] = { Borrow, Result };
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+ }
}
break;
case ISD::STORE: {
diff --git a/test/CodeGen/XCore/ladd_lsub_combine.ll b/test/CodeGen/XCore/ladd_lsub_combine.ll
index ea9a3b78f2..a693ee2229 100644
--- a/test/CodeGen/XCore/ladd_lsub_combine.ll
+++ b/test/CodeGen/XCore/ladd_lsub_combine.ll
@@ -26,3 +26,42 @@ entry:
; CHECK-NEXT: lsub r1, r0, r1, r0, r2
; CHECK-NEXT: neg r1, r1
; CHECK-NEXT: retsp 0
+
+; Should compile to one ladd and one add
+define i64 @f3(i64 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %1 = add i64 %x, %0 ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f3:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: ladd r2, r0, r0, r2, r3
+; CHECK-NEXT: add r1, r1, r2
+; CHECK-NEXT: retsp 0
+
+; Should compile to one ladd and one add
+define i64 @f4(i32 %x, i64 %y) nounwind {
+entry:
+ %0 = zext i32 %x to i64 ; <i64> [#uses=1]
+ %1 = add i64 %0, %y ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f4:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: ladd r1, r0, r0, r1, r3
+; CHECK-NEXT: add r1, r2, r1
+; CHECK-NEXT: retsp 0
+
+; Should compile to one lsub and one sub
+define i64 @f5(i64 %x, i32 %y) nounwind {
+entry:
+ %0 = zext i32 %y to i64 ; <i64> [#uses=1]
+ %1 = sub i64 %x, %0 ; <i64> [#uses=1]
+ ret i64 %1
+}
+; CHECK: f5:
+; CHECK: ldc r3, 0
+; CHECK-NEXT: lsub r2, r0, r0, r2, r3
+; CHECK-NEXT: sub r1, r1, r2
+; CHECK-NEXT: retsp 0