<div dir="ltr">The switch in flipBoolean throws this warning<div><br></div><div>warning: default label in switch which covers all enumeration values [-Wcovered-switch-default]<br></div><div><br clear="all"><div><div dir="ltr" class="gmail_signature">~Craig</div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 4, 2018 at 12:27 PM Amaury Sechet via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: deadalnix<br>
Date: Mon Jun  4 12:23:22 2018<br>
New Revision: 333943<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=333943&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=333943&view=rev</a><br>
Log:<br>
[DAGcombine] Teach the combiner about -a = ~a + 1<br>
<br>
Summary: This include variant for add, uaddo and addcarry. usubo and subcarry require the carry to be flipped to preserve semantic, but we chose to do the transform anyway in that case as to push the transform down the carry chain.<br>
<br>
Reviewers: efriedma, spatel, RKSimon, zvi, bkramer<br>
<br>
Subscribers: llvm-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D46505" rel="noreferrer" target="_blank">https://reviews.llvm.org/D46505</a><br>
<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
    llvm/trunk/test/CodeGen/X86/add.ll<br>
    llvm/trunk/test/CodeGen/X86/addcarry.ll<br>
    llvm/trunk/test/CodeGen/X86/subcarry.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=333943&r1=333942&r2=333943&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=333943&r1=333942&r2=333943&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Jun  4 12:23:22 2018<br>
@@ -2053,6 +2053,11 @@ SDValue DAGCombiner::visitADD(SDNode *N)<br>
       DAG.haveNoCommonBitsSet(N0, N1))<br>
     return DAG.getNode(ISD::OR, DL, VT, N0, N1);<br>
<br>
+  // fold (add (xor a, -1), 1) -> (sub 0, a)<br>
+  if (isBitwiseNot(N0) && isOneConstantOrOneSplatConstant(N1))<br>
+    return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),<br>
+                       N0.getOperand(0));<br>
+<br>
   if (SDValue Combined = visitADDLike(N0, N1, N))<br>
     return Combined;<br>
<br>
@@ -2188,6 +2193,40 @@ SDValue DAGCombiner::visitADDC(SDNode *N<br>
   return SDValue();<br>
 }<br>
<br>
+static SDValue flipBoolean(SDValue V, const SDLoc &DL, EVT VT,<br>
+                           SelectionDAG &DAG, const TargetLowering &TLI) {<br>
+  SDValue Cst;<br>
+  switch(TLI.getBooleanContents(VT)) {<br>
+    case TargetLowering::ZeroOrOneBooleanContent:<br>
+    case TargetLowering::UndefinedBooleanContent:<br>
+      Cst = DAG.getConstant(1, DL, VT);<br>
+      break;<br>
+    case TargetLowering::ZeroOrNegativeOneBooleanContent:<br>
+      Cst = DAG.getConstant(-1, DL, VT);<br>
+      break;<br>
+    default:<br>
+      llvm_unreachable("Unsupported boolean content");<br>
+  }<br>
+<br>
+  return DAG.getNode(ISD::XOR, DL, VT, V, Cst);<br>
+}<br>
+<br>
+static bool isBooleanFlip(SDValue V, EVT VT, const TargetLowering &TLI) {<br>
+  if (V.getOpcode() != ISD::XOR) return false;<br>
+  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V.getOperand(1));<br>
+  if (!Const) return false;<br>
+<br>
+  switch(TLI.getBooleanContents(VT)) {<br>
+    case TargetLowering::ZeroOrOneBooleanContent:<br>
+      return Const->isOne();<br>
+    case TargetLowering::ZeroOrNegativeOneBooleanContent:<br>
+      return Const->isAllOnesValue();<br>
+    case TargetLowering::UndefinedBooleanContent:<br>
+      return (Const->getAPIntValue() & 0x01) == 1;<br>
+  }<br>
+  llvm_unreachable("Unsupported boolean content");<br>
+}<br>
+<br>
 SDValue DAGCombiner::visitUADDO(SDNode *N) {<br>
   SDValue N0 = N->getOperand(0);<br>
   SDValue N1 = N->getOperand(1);<br>
@@ -2218,6 +2257,15 @@ SDValue DAGCombiner::visitUADDO(SDNode *<br>
     return CombineTo(N, DAG.getNode(ISD::ADD, DL, VT, N0, N1),<br>
                      DAG.getConstant(0, DL, CarryVT));<br>
<br>
+  // fold (uaddo (xor a, -1), 1) -> (usub 0, a) and flip carry.<br>
+  if (isBitwiseNot(N0) && isOneConstantOrOneSplatConstant(N1)) {<br>
+    SDValue Sub = DAG.getNode(ISD::USUBO, DL, N->getVTList(),<br>
+                              DAG.getConstant(0, DL, VT),<br>
+                              N0.getOperand(0));<br>
+    return CombineTo(N, Sub,<br>
+                     flipBoolean(Sub.getValue(1), DL, CarryVT, DAG, TLI));<br>
+  }<br>
+<br>
   if (SDValue Combined = visitUADDOLike(N0, N1, N))<br>
     return Combined;<br>
<br>
@@ -2287,10 +2335,11 @@ SDValue DAGCombiner::visitADDCARRY(SDNod<br>
       return DAG.getNode(ISD::UADDO, DL, N->getVTList(), N0, N1);<br>
   }<br>
<br>
+  EVT CarryVT = CarryIn.getValueType();<br>
+<br>
   // fold (addcarry 0, 0, X) -> (and (ext/trunc X), 1) and no carry.<br>
   if (isNullConstant(N0) && isNullConstant(N1)) {<br>
     EVT VT = N0.getValueType();<br>
-    EVT CarryVT = CarryIn.getValueType();<br>
     SDValue CarryExt = DAG.getBoolExtOrTrunc(CarryIn, DL, VT, CarryVT);<br>
     AddToWorklist(CarryExt.getNode());<br>
     return CombineTo(N, DAG.getNode(ISD::AND, DL, VT, CarryExt,<br>
@@ -2298,6 +2347,16 @@ SDValue DAGCombiner::visitADDCARRY(SDNod<br>
                      DAG.getConstant(0, DL, CarryVT));<br>
   }<br>
<br>
+  // fold (addcarry (xor a, -1), 0, !b) -> (subcarry 0, a, b) and flip carry.<br>
+  if (isBitwiseNot(N0) && isNullConstant(N1) &&<br>
+      isBooleanFlip(CarryIn, CarryVT, TLI)) {<br>
+    SDValue Sub = DAG.getNode(ISD::SUBCARRY, DL, N->getVTList(),<br>
+                              DAG.getConstant(0, DL, N0.getValueType()),<br>
+                              N0.getOperand(0), CarryIn.getOperand(0));<br>
+    return CombineTo(N, Sub,<br>
+                     flipBoolean(Sub.getValue(1), DL, CarryVT, DAG, TLI));<br>
+  }<br>
+<br>
   if (SDValue Combined = visitADDCARRYLike(N0, N1, CarryIn, N))<br>
     return Combined;<br>
<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/add.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/add.ll?rev=333943&r1=333942&r2=333943&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/add.ll?rev=333943&r1=333942&r2=333943&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/add.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/add.ll Mon Jun  4 12:23:22 2018<br>
@@ -386,23 +386,20 @@ entry:<br>
 define i32 @inc_not(i32 %a) {<br>
 ; X32-LABEL: inc_not:<br>
 ; X32:       # %bb.0:<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
-; X32-NEXT:    notl %eax<br>
-; X32-NEXT:    incl %eax<br>
+; X32-NEXT:    xorl %eax, %eax<br>
+; X32-NEXT:    subl {{[0-9]+}}(%esp), %eax<br>
 ; X32-NEXT:    retl<br>
 ;<br>
 ; X64-LINUX-LABEL: inc_not:<br>
 ; X64-LINUX:       # %bb.0:<br>
-; X64-LINUX-NEXT:    # kill: def $edi killed $edi def $rdi<br>
-; X64-LINUX-NEXT:    notl %edi<br>
-; X64-LINUX-NEXT:    leal 1(%rdi), %eax<br>
+; X64-LINUX-NEXT:    negl %edi<br>
+; X64-LINUX-NEXT:    movl %edi, %eax<br>
 ; X64-LINUX-NEXT:    retq<br>
 ;<br>
 ; X64-WIN32-LABEL: inc_not:<br>
 ; X64-WIN32:       # %bb.0:<br>
-; X64-WIN32-NEXT:    # kill: def $ecx killed $ecx def $rcx<br>
-; X64-WIN32-NEXT:    notl %ecx<br>
-; X64-WIN32-NEXT:    leal 1(%rcx), %eax<br>
+; X64-WIN32-NEXT:    negl %ecx<br>
+; X64-WIN32-NEXT:    movl %ecx, %eax<br>
 ; X64-WIN32-NEXT:    retq<br>
   %nota = xor i32 %a, -1<br>
   %r = add i32 %nota, 1<br>
@@ -414,27 +411,24 @@ define void @uaddo1_not(i32 %a, i32* %p0<br>
 ; X32:       # %bb.0:<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx<br>
-; X32-NEXT:    notl %edx<br>
-; X32-NEXT:    addl $1, %edx<br>
+; X32-NEXT:    xorl %edx, %edx<br>
+; X32-NEXT:    subl {{[0-9]+}}(%esp), %edx<br>
 ; X32-NEXT:    movl %edx, (%ecx)<br>
-; X32-NEXT:    setb (%eax)<br>
+; X32-NEXT:    setae (%eax)<br>
 ; X32-NEXT:    retl<br>
 ;<br>
 ; X64-LINUX-LABEL: uaddo1_not:<br>
 ; X64-LINUX:       # %bb.0:<br>
-; X64-LINUX-NEXT:    notl %edi<br>
-; X64-LINUX-NEXT:    addl $1, %edi<br>
+; X64-LINUX-NEXT:    negl %edi<br>
 ; X64-LINUX-NEXT:    movl %edi, (%rsi)<br>
-; X64-LINUX-NEXT:    setb (%rdx)<br>
+; X64-LINUX-NEXT:    setae (%rdx)<br>
 ; X64-LINUX-NEXT:    retq<br>
 ;<br>
 ; X64-WIN32-LABEL: uaddo1_not:<br>
 ; X64-WIN32:       # %bb.0:<br>
-; X64-WIN32-NEXT:    notl %ecx<br>
-; X64-WIN32-NEXT:    addl $1, %ecx<br>
+; X64-WIN32-NEXT:    negl %ecx<br>
 ; X64-WIN32-NEXT:    movl %ecx, (%rdx)<br>
-; X64-WIN32-NEXT:    setb (%r8)<br>
+; X64-WIN32-NEXT:    setae (%r8)<br>
 ; X64-WIN32-NEXT:    retq<br>
   %nota = xor i32 %a, -1<br>
   %uaddo = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %nota, i32 1)<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/addcarry.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/addcarry.ll?rev=333943&r1=333942&r2=333943&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/addcarry.ll?rev=333943&r1=333942&r2=333943&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/addcarry.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/addcarry.ll Mon Jun  4 12:23:22 2018<br>
@@ -321,12 +321,10 @@ entry:<br>
 define i128 @addcarry1_not(i128 %n) {<br>
 ; CHECK-LABEL: addcarry1_not:<br>
 ; CHECK:       # %bb.0:<br>
-; CHECK-NEXT:    notq %rsi<br>
-; CHECK-NEXT:    notq %rdi<br>
-; CHECK-NEXT:    addq $1, %rdi<br>
-; CHECK-NEXT:    adcq $0, %rsi<br>
+; CHECK-NEXT:    xorl %edx, %edx<br>
+; CHECK-NEXT:    negq %rdi<br>
+; CHECK-NEXT:    sbbq %rsi, %rdx<br>
 ; CHECK-NEXT:    movq %rdi, %rax<br>
-; CHECK-NEXT:    movq %rsi, %rdx<br>
 ; CHECK-NEXT:    retq<br>
   %1 = xor i128 %n, -1<br>
   %2 = add i128 %1, 1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/subcarry.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/subcarry.ll?rev=333943&r1=333942&r2=333943&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/subcarry.ll?rev=333943&r1=333942&r2=333943&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/subcarry.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/subcarry.ll Mon Jun  4 12:23:22 2018<br>
@@ -37,22 +37,18 @@ entry:<br>
 define %S @negate(%S* nocapture readonly %this) {<br>
 ; CHECK-LABEL: negate:<br>
 ; CHECK:       # %bb.0: # %entry<br>
-; CHECK-NEXT:    movq (%rsi), %rax<br>
-; CHECK-NEXT:    movq 8(%rsi), %rcx<br>
-; CHECK-NEXT:    notq %rax<br>
-; CHECK-NEXT:    addq $1, %rax<br>
-; CHECK-NEXT:    notq %rcx<br>
-; CHECK-NEXT:    adcq $0, %rcx<br>
-; CHECK-NEXT:    movq 16(%rsi), %rdx<br>
-; CHECK-NEXT:    notq %rdx<br>
-; CHECK-NEXT:    adcq $0, %rdx<br>
-; CHECK-NEXT:    movq 24(%rsi), %rsi<br>
-; CHECK-NEXT:    notq %rsi<br>
-; CHECK-NEXT:    adcq $0, %rsi<br>
-; CHECK-NEXT:    movq %rax, (%rdi)<br>
-; CHECK-NEXT:    movq %rcx, 8(%rdi)<br>
-; CHECK-NEXT:    movq %rdx, 16(%rdi)<br>
-; CHECK-NEXT:    movq %rsi, 24(%rdi)<br>
+; CHECK-NEXT:    xorl %r8d, %r8d<br>
+; CHECK-NEXT:    xorl %ecx, %ecx<br>
+; CHECK-NEXT:    subq (%rsi), %rcx<br>
+; CHECK-NEXT:    movl $0, %edx<br>
+; CHECK-NEXT:    sbbq 8(%rsi), %rdx<br>
+; CHECK-NEXT:    movl $0, %eax<br>
+; CHECK-NEXT:    sbbq 16(%rsi), %rax<br>
+; CHECK-NEXT:    sbbq 24(%rsi), %r8<br>
+; CHECK-NEXT:    movq %rcx, (%rdi)<br>
+; CHECK-NEXT:    movq %rdx, 8(%rdi)<br>
+; CHECK-NEXT:    movq %rax, 16(%rdi)<br>
+; CHECK-NEXT:    movq %r8, 24(%rdi)<br>
 ; CHECK-NEXT:    movq %rdi, %rax<br>
 ; CHECK-NEXT:    retq<br>
 entry:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>