OSDN Git Service

[DAGCombiner] fold (add (add (xor a, -1), b), 1) -> (sub b, a)
authorAmaury Sechet <deadalnix@gmail.com>
Fri, 8 Mar 2019 19:39:32 +0000 (19:39 +0000)
committerAmaury Sechet <deadalnix@gmail.com>
Fri, 8 Mar 2019 19:39:32 +0000 (19:39 +0000)
Summary: This pattern is sometime created after legalization.

Reviewers: efriedma, spatel, RKSimon, zvi, bkramer

Subscribers: llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D58874

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355716 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
test/CodeGen/X86/add.ll
test/CodeGen/X86/combine-add.ll

index 30259c1..6ac6bb8 100644 (file)
@@ -2186,10 +2186,30 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
       DAG.haveNoCommonBitsSet(N0, N1))
     return DAG.getNode(ISD::OR, DL, VT, N0, N1);
 
-  // fold (add (xor a, -1), 1) -> (sub 0, a)
-  if (isBitwiseNot(N0) && isOneOrOneSplat(N1))
-    return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),
-                       N0.getOperand(0));
+  if (isOneOrOneSplat(N1)) {
+    // fold (add (xor a, -1), 1) -> (sub 0, a)
+    if (isBitwiseNot(N0))
+      return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),
+                         N0.getOperand(0));
+
+    // fold (add (add (xor a, -1), b), 1) -> (sub b, a)
+    if (N0.getOpcode() == ISD::ADD ||
+        N0.getOpcode() == ISD::UADDO ||
+        N0.getOpcode() == ISD::SADDO) {
+      SDValue A, Xor;
+
+      if (isBitwiseNot(N0.getOperand(0))) {
+        A = N0.getOperand(1);
+        Xor = N0.getOperand(0);
+      } else if (isBitwiseNot(N0.getOperand(1))) {
+        A = N0.getOperand(0);
+        Xor = N0.getOperand(1);
+      }
+
+      if (Xor)
+        return DAG.getNode(ISD::SUB, DL, VT, A, Xor.getOperand(0));
+    }
+  }
 
   if (SDValue Combined = visitADDLike(N0, N1, N))
     return Combined;
index dcb34ed..72bf912 100644 (file)
@@ -482,25 +482,19 @@ define i32 @add_to_sub(i32 %a, i32 %b) {
 ; X32-LABEL: add_to_sub:
 ; X32:       # %bb.0:
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X32-NEXT:    notl %ecx
-; X32-NEXT:    leal 1(%ecx,%eax), %eax
+; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax
 ; X32-NEXT:    retl
 ;
 ; X64-LINUX-LABEL: add_to_sub:
 ; X64-LINUX:       # %bb.0:
-; X64-LINUX-NEXT:    # kill: def $esi killed $esi def $rsi
-; X64-LINUX-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-LINUX-NEXT:    notl %edi
-; X64-LINUX-NEXT:    leal 1(%rdi,%rsi), %eax
+; X64-LINUX-NEXT:    movl %esi, %eax
+; X64-LINUX-NEXT:    subl %edi, %eax
 ; X64-LINUX-NEXT:    retq
 ;
 ; X64-WIN32-LABEL: add_to_sub:
 ; X64-WIN32:       # %bb.0:
-; X64-WIN32-NEXT:    # kill: def $edx killed $edx def $rdx
-; X64-WIN32-NEXT:    # kill: def $ecx killed $ecx def $rcx
-; X64-WIN32-NEXT:    notl %ecx
-; X64-WIN32-NEXT:    leal 1(%rcx,%rdx), %eax
+; X64-WIN32-NEXT:    movl %edx, %eax
+; X64-WIN32-NEXT:    subl %ecx, %eax
 ; X64-WIN32-NEXT:    retq
   %nota = xor i32 %a, -1
   %add = add i32 %nota, %b
index afa5aa3..6f5f137 100644 (file)
@@ -350,22 +350,18 @@ define <4 x i32> @combine_vec_add_sextinreg(<4 x i32> %a0, <4 x i32> %a1) {
   ret <4 x i32> %3
 }
 
-; TODO: (add (add (xor a, -1), b), 1) -> (sub b, a)
+; (add (add (xor a, -1), b), 1) -> (sub b, a)
 define i32 @combine_add_add_not(i32 %a, i32 %b) {
 ; SSE-LABEL: combine_add_add_not:
 ; SSE:       # %bb.0:
-; SSE-NEXT:    # kill: def $esi killed $esi def $rsi
-; SSE-NEXT:    # kill: def $edi killed $edi def $rdi
-; SSE-NEXT:    notl %edi
-; SSE-NEXT:    leal 1(%rdi,%rsi), %eax
+; SSE-NEXT:    movl %esi, %eax
+; SSE-NEXT:    subl %edi, %eax
 ; SSE-NEXT:    retq
 ;
 ; AVX-LABEL: combine_add_add_not:
 ; AVX:       # %bb.0:
-; AVX-NEXT:    # kill: def $esi killed $esi def $rsi
-; AVX-NEXT:    # kill: def $edi killed $edi def $rdi
-; AVX-NEXT:    notl %edi
-; AVX-NEXT:    leal 1(%rdi,%rsi), %eax
+; AVX-NEXT:    movl %esi, %eax
+; AVX-NEXT:    subl %edi, %eax
 ; AVX-NEXT:    retq
   %nota = xor i32 %a, -1
   %add = add i32 %nota, %b
@@ -376,18 +372,13 @@ define i32 @combine_add_add_not(i32 %a, i32 %b) {
 define <4 x i32> @combine_vec_add_add_not(<4 x i32> %a, <4 x i32> %b) {
 ; SSE-LABEL: combine_vec_add_add_not:
 ; SSE:       # %bb.0:
-; SSE-NEXT:    pcmpeqd %xmm2, %xmm2
-; SSE-NEXT:    pxor %xmm2, %xmm0
-; SSE-NEXT:    paddd %xmm1, %xmm0
-; SSE-NEXT:    psubd %xmm2, %xmm0
+; SSE-NEXT:    psubd %xmm0, %xmm1
+; SSE-NEXT:    movdqa %xmm1, %xmm0
 ; SSE-NEXT:    retq
 ;
 ; AVX-LABEL: combine_vec_add_add_not:
 ; AVX:       # %bb.0:
-; AVX-NEXT:    vpcmpeqd %xmm2, %xmm2, %xmm2
-; AVX-NEXT:    vpxor %xmm2, %xmm0, %xmm0
-; AVX-NEXT:    vpaddd %xmm1, %xmm0, %xmm0
-; AVX-NEXT:    vpsubd %xmm2, %xmm0, %xmm0
+; AVX-NEXT:    vpsubd %xmm0, %xmm1, %xmm0
 ; AVX-NEXT:    retq
   %nota = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
   %add = add <4 x i32> %nota, %b