[DAGCombine][ARM][X86] (sub Carry, X) -> (addcarry (sub 0, X), 0, Carry) fold
authorRoman Lebedev <lebedev.ri@gmail.com>
Wed, 18 Sep 2019 20:48:27 +0000 (20:48 +0000)
committerRoman Lebedev <lebedev.ri@gmail.com>
Wed, 18 Sep 2019 20:48:27 +0000 (20:48 +0000)
Summary:
`DAGCombiner::visitADDLikeCommutative()` already has a sibling fold:
`(add X, Carry) -> (addcarry X, 0, Carry)`

This fold, as suggested by @efriedma, helps recover from //some//
of the regressions of D62266

Reviewers: efriedma, deadalnix

Subscribers: javed.absar, kristof.beyls, llvm-commits, efriedma

Tags: #llvm

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

llvm-svn: 372259

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/ARM/addsubcarry-promotion.ll
llvm/test/CodeGen/X86/subcarry.ll

index a7e5068..edb5ecb 100644 (file)
@@ -3384,6 +3384,18 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
     }
   }
 
+  if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT)) {
+    // (sub Carry, X)  ->  (addcarry (sub 0, X), 0, Carry)
+    if (SDValue Carry = getAsCarry(TLI, N0)) {
+      SDValue X = N1;
+      SDValue Zero = DAG.getConstant(0, DL, VT);
+      SDValue NegX = DAG.getNode(ISD::SUB, DL, VT, Zero, X);
+      return DAG.getNode(ISD::ADDCARRY, DL,
+                         DAG.getVTList(VT, Carry.getValueType()), NegX, Zero,
+                         Carry);
+    }
+  }
+
   return SDValue();
 }
 
index 2dfd217..aaf7189 100644 (file)
 define void @fn1(i32 %a, i32 %b, i32 %c) local_unnamed_addr #0 {
 ; ARM-LABEL: fn1:
 ; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    rsb r2, r2, #0
 ; ARM-NEXT:    adds r0, r1, r0
-; ARM-NEXT:    mov r3, #0
-; ARM-NEXT:    adc r0, r3, #0
 ; ARM-NEXT:    movw r1, #65535
-; ARM-NEXT:    sub r0, r0, r2
+; ARM-NEXT:    sxth r2, r2
+; ARM-NEXT:    adc r0, r2, #0
 ; ARM-NEXT:    uxth r0, r0
 ; ARM-NEXT:    cmp r0, r1
 ; ARM-NEXT:    bxeq lr
@@ -24,11 +24,12 @@ define void @fn1(i32 %a, i32 %b, i32 %c) local_unnamed_addr #0 {
 ;
 ; THUMBV6M-LABEL: fn1:
 ; THUMBV6M:       @ %bb.0: @ %entry
+; THUMBV6M-NEXT:    rsbs r2, r2, #0
+; THUMBV6M-NEXT:    sxth r2, r2
 ; THUMBV6M-NEXT:    movs r3, #0
 ; THUMBV6M-NEXT:    adds r0, r1, r0
-; THUMBV6M-NEXT:    adcs r3, r3
-; THUMBV6M-NEXT:    subs r0, r3, r2
-; THUMBV6M-NEXT:    uxth r0, r0
+; THUMBV6M-NEXT:    adcs r3, r2
+; THUMBV6M-NEXT:    uxth r0, r3
 ; THUMBV6M-NEXT:    ldr r1, .LCPI0_0
 ; THUMBV6M-NEXT:    cmp r0, r1
 ; THUMBV6M-NEXT:    beq .LBB0_2
@@ -44,11 +45,12 @@ define void @fn1(i32 %a, i32 %b, i32 %c) local_unnamed_addr #0 {
 ;
 ; THUMBV8M-BASE-LABEL: fn1:
 ; THUMBV8M-BASE:       @ %bb.0: @ %entry
+; THUMBV8M-BASE-NEXT:    rsbs r2, r2, #0
+; THUMBV8M-BASE-NEXT:    sxth r2, r2
 ; THUMBV8M-BASE-NEXT:    movs r3, #0
 ; THUMBV8M-BASE-NEXT:    adds r0, r1, r0
-; THUMBV8M-BASE-NEXT:    adcs r3, r3
-; THUMBV8M-BASE-NEXT:    subs r0, r3, r2
-; THUMBV8M-BASE-NEXT:    uxth r0, r0
+; THUMBV8M-BASE-NEXT:    adcs r3, r2
+; THUMBV8M-BASE-NEXT:    uxth r0, r3
 ; THUMBV8M-BASE-NEXT:    movw r1, #65535
 ; THUMBV8M-BASE-NEXT:    cmp r0, r1
 ; THUMBV8M-BASE-NEXT:    beq .LBB0_2
@@ -60,11 +62,11 @@ define void @fn1(i32 %a, i32 %b, i32 %c) local_unnamed_addr #0 {
 ;
 ; THUMB-LABEL: fn1:
 ; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    rsbs r2, r2, #0
 ; THUMB-NEXT:    adds r0, r0, r1
-; THUMB-NEXT:    mov.w r3, #0
-; THUMB-NEXT:    adc r0, r3, #0
 ; THUMB-NEXT:    movw r1, #65535
-; THUMB-NEXT:    subs r0, r0, r2
+; THUMB-NEXT:    sxth r2, r2
+; THUMB-NEXT:    adc r0, r2, #0
 ; THUMB-NEXT:    uxth r0, r0
 ; THUMB-NEXT:    cmp r0, r1
 ; THUMB-NEXT:    it eq
index d5f1d55..75ee6ef 100644 (file)
@@ -169,11 +169,11 @@ declare {i64, i1} @llvm.usub.with.overflow(i64, i64)
 define i64 @sub_from_carry(i64 %x, i64 %y, i64* %valout, i64 %z) {
 ; CHECK-LABEL: sub_from_carry:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    negq %rax
 ; CHECK-NEXT:    addq %rsi, %rdi
-; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    movq %rdi, (%rdx)
-; CHECK-NEXT:    subq %rcx, %rax
+; CHECK-NEXT:    adcq $0, %rax
 ; CHECK-NEXT:    retq
   %agg = call {i64, i1} @llvm.uadd.with.overflow(i64 %x, i64 %y)
   %val = extractvalue {i64, i1} %agg, 0