summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp20
-rw-r--r--llvm/test/CodeGen/X86/adde-carry.ll18
2 files changed, 21 insertions, 17 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index aad07d8ae3c..8028eb3567e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -232,6 +232,7 @@ namespace {
SDValue visitTokenFactor(SDNode *N);
SDValue visitMERGE_VALUES(SDNode *N);
SDValue visitADD(SDNode *N);
+ SDValue visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference);
SDValue visitSUB(SDNode *N);
SDValue visitADDC(SDNode *N);
SDValue visitSUBC(SDNode *N);
@@ -1782,6 +1783,19 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
VT.isInteger() && DAG.haveNoCommonBitsSet(N0, N1))
return DAG.getNode(ISD::OR, DL, VT, N0, N1);
+ if (SDValue Combined = visitADDLike(N0, N1, N))
+ return Combined;
+
+ if (SDValue Combined = visitADDLike(N1, N0, N))
+ return Combined;
+
+ return SDValue();
+}
+
+SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference) {
+ EVT VT = N0.getValueType();
+ SDLoc DL(LocReference);
+
// fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n))
if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::SUB &&
isNullConstantOrNullSplatConstant(N1.getOperand(0).getOperand(0)))
@@ -1789,12 +1803,6 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
DAG.getNode(ISD::SHL, DL, VT,
N1.getOperand(0).getOperand(1),
N1.getOperand(1)));
- if (N0.getOpcode() == ISD::SHL && N0.getOperand(0).getOpcode() == ISD::SUB &&
- isNullConstantOrNullSplatConstant(N0.getOperand(0).getOperand(0)))
- return DAG.getNode(ISD::SUB, DL, VT, N1,
- DAG.getNode(ISD::SHL, DL, VT,
- N0.getOperand(0).getOperand(1),
- N0.getOperand(1)));
if (N1.getOpcode() == ISD::AND) {
SDValue AndOp0 = N1.getOperand(0);
diff --git a/llvm/test/CodeGen/X86/adde-carry.ll b/llvm/test/CodeGen/X86/adde-carry.ll
index 0eae984525b..e111f683dd3 100644
--- a/llvm/test/CodeGen/X86/adde-carry.ll
+++ b/llvm/test/CodeGen/X86/adde-carry.ll
@@ -29,9 +29,8 @@ define void @b(i32* nocapture %r, i64 %a, i64 %b, i32 %c) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: addq %rdx, %rsi
; CHECK-NEXT: sbbq %rax, %rax
-; CHECK-NEXT: andl $1, %eax
-; CHECK-NEXT: addl %ecx, %eax
-; CHECK-NEXT: movl %eax, (%rdi)
+; CHECK-NEXT: subl %eax, %ecx
+; CHECK-NEXT: movl %ecx, (%rdi)
; CHECK-NEXT: retq
entry:
%0 = zext i64 %a to i128
@@ -50,9 +49,8 @@ define void @c(i16* nocapture %r, i64 %a, i64 %b, i16 %c) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: addq %rdx, %rsi
; CHECK-NEXT: sbbq %rax, %rax
-; CHECK-NEXT: andl $1, %eax
-; CHECK-NEXT: addl %ecx, %eax
-; CHECK-NEXT: movw %ax, (%rdi)
+; CHECK-NEXT: subl %eax, %ecx
+; CHECK-NEXT: movw %cx, (%rdi)
; CHECK-NEXT: retq
entry:
%0 = zext i64 %a to i128
@@ -71,9 +69,8 @@ define void @d(i8* nocapture %r, i64 %a, i64 %b, i8 %c) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: addq %rdx, %rsi
; CHECK-NEXT: sbbq %rax, %rax
-; CHECK-NEXT: andl $1, %eax
-; CHECK-NEXT: addl %ecx, %eax
-; CHECK-NEXT: movb %al, (%rdi)
+; CHECK-NEXT: subl %eax, %ecx
+; CHECK-NEXT: movb %cl, (%rdi)
; CHECK-NEXT: retq
entry:
%0 = zext i64 %a to i128
@@ -169,9 +166,8 @@ define void @muladd(%accumulator* nocapture %this, i64 %arg.a, i64 %arg.b) {
; CHECK-NEXT: movq %rax, (%rdi)
; CHECK-NEXT: addq 8(%rdi), %rdx
; CHECK-NEXT: sbbq %rax, %rax
-; CHECK-NEXT: andl $1, %eax
; CHECK-NEXT: movq %rdx, 8(%rdi)
-; CHECK-NEXT: addl %eax, 16(%rdi)
+; CHECK-NEXT: subl %eax, 16(%rdi)
; CHECK-NEXT: retq
entry:
%0 = zext i64 %arg.a to i128
OpenPOWER on IntegriCloud