[llvm] e728d1a - [DAGCombiner] create binop nodes with all of expected values

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 25 13:20:35 PDT 2021


Author: Sanjay Patel
Date: 2021-08-25T16:14:22-04:00
New Revision: e728d1a3e82b097d439c47b7b02d94f11f45624d

URL: https://github.com/llvm/llvm-project/commit/e728d1a3e82b097d439c47b7b02d94f11f45624d
DIFF: https://github.com/llvm/llvm-project/commit/e728d1a3e82b097d439c47b7b02d94f11f45624d.diff

LOG: [DAGCombiner] create binop nodes with all of expected values

This is another bug exposed by https://llvm.org/PR51612
(and the one that triggered the initial assertion) in the report.

That example was suppressed with:
985b48f18341

...but these would still crash because we created nodes
like UADDO without the expected 2 output values.

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/X86/select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 6def3258228b..d9991b801905 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -22572,12 +22572,16 @@ SDValue DAGCombiner::foldSelectOfBinops(SDNode *N) {
   if (!N0->hasOneUse() || !N1->hasOneUse() || !N2->hasOneUse())
     return SDValue();
 
+  // Binops may include opcodes that return multiple values, so all values
+  // must be created/propagated from the newly created binops below.
+  SDVTList OpVTs = N1->getVTList();
+
   // Fold select(cond, binop(x, y), binop(z, y))
   //  --> binop(select(cond, x, z), y)
   if (N1.getOperand(1) == N2.getOperand(1)) {
     SDValue NewSel =
         DAG.getSelect(DL, VT, N0, N1.getOperand(0), N2.getOperand(0));
-    SDValue NewBinOp = DAG.getNode(BinOpc, DL, VT, NewSel, N1.getOperand(1));
+    SDValue NewBinOp = DAG.getNode(BinOpc, DL, OpVTs, NewSel, N1.getOperand(1));
     NewBinOp->setFlags(N1->getFlags());
     NewBinOp->intersectFlagsWith(N2->getFlags());
     return NewBinOp;
@@ -22591,7 +22595,7 @@ SDValue DAGCombiner::foldSelectOfBinops(SDNode *N) {
       VT == N2.getOperand(1).getValueType()) {
     SDValue NewSel =
         DAG.getSelect(DL, VT, N0, N1.getOperand(1), N2.getOperand(1));
-    SDValue NewBinOp = DAG.getNode(BinOpc, DL, VT, N1.getOperand(0), NewSel);
+    SDValue NewBinOp = DAG.getNode(BinOpc, DL, OpVTs, N1.getOperand(0), NewSel);
     NewBinOp->setFlags(N1->getFlags());
     NewBinOp->intersectFlagsWith(N2->getFlags());
     return NewBinOp;

diff  --git a/llvm/test/CodeGen/X86/select.ll b/llvm/test/CodeGen/X86/select.ll
index 7a9219c8c5fc..9fc5fd477c5e 100644
--- a/llvm/test/CodeGen/X86/select.ll
+++ b/llvm/test/CodeGen/X86/select.ll
@@ -1589,3 +1589,107 @@ define i64 @PR51612(i64 %x, i64 %y) {
   %and = and i64 %sel, %conv
   ret i64 %and
 }
+
+; The next 2 tests are for additional bugs based on PR51612.
+
+declare { i8, i1 } @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone
+declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
+
+define i8 @select_uaddo_common_op0(i8 %a, i8 %b, i8 %c, i1 %cond) {
+; GENERIC-LABEL: select_uaddo_common_op0:
+; GENERIC:       ## %bb.0:
+; GENERIC-NEXT:    ## kill: def $esi killed $esi def $rsi
+; GENERIC-NEXT:    ## kill: def $edi killed $edi def $rdi
+; GENERIC-NEXT:    testb $1, %cl
+; GENERIC-NEXT:    cmovel %edx, %esi
+; GENERIC-NEXT:    leal (%rsi,%rdi), %eax
+; GENERIC-NEXT:    ## kill: def $al killed $al killed $eax
+; GENERIC-NEXT:    retq
+;
+; ATOM-LABEL: select_uaddo_common_op0:
+; ATOM:       ## %bb.0:
+; ATOM-NEXT:    ## kill: def $esi killed $esi def $rsi
+; ATOM-NEXT:    testb $1, %cl
+; ATOM-NEXT:    ## kill: def $edi killed $edi def $rdi
+; ATOM-NEXT:    cmovel %edx, %esi
+; ATOM-NEXT:    leal (%rsi,%rdi), %eax
+; ATOM-NEXT:    ## kill: def $al killed $al killed $eax
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    retq
+;
+; ATHLON-LABEL: select_uaddo_common_op0:
+; ATHLON:       ## %bb.0:
+; ATHLON-NEXT:    movb {{[0-9]+}}(%esp), %al
+; ATHLON-NEXT:    testb $1, {{[0-9]+}}(%esp)
+; ATHLON-NEXT:    leal {{[0-9]+}}(%esp), %ecx
+; ATHLON-NEXT:    leal {{[0-9]+}}(%esp), %edx
+; ATHLON-NEXT:    cmovnel %ecx, %edx
+; ATHLON-NEXT:    addb (%edx), %al
+; ATHLON-NEXT:    retl
+;
+; MCU-LABEL: select_uaddo_common_op0:
+; MCU:       # %bb.0:
+; MCU-NEXT:    testb $1, {{[0-9]+}}(%esp)
+; MCU-NEXT:    jne .LBB32_2
+; MCU-NEXT:  # %bb.1:
+; MCU-NEXT:    movl %ecx, %edx
+; MCU-NEXT:  .LBB32_2:
+; MCU-NEXT:    addb %dl, %al
+; MCU-NEXT:    # kill: def $al killed $al killed $eax
+; MCU-NEXT:    retl
+  %ab = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
+  %ac = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %c)
+  %ab0 = extractvalue { i8, i1 } %ab, 0
+  %ac0 = extractvalue { i8, i1 } %ac, 0
+  %sel = select i1 %cond, i8 %ab0, i8 %ac0
+  ret i8 %sel
+}
+
+define i32 @select_uaddo_common_op1(i32 %a, i32 %b, i32 %c, i1 %cond) {
+; GENERIC-LABEL: select_uaddo_common_op1:
+; GENERIC:       ## %bb.0:
+; GENERIC-NEXT:    ## kill: def $esi killed $esi def $rsi
+; GENERIC-NEXT:    ## kill: def $edi killed $edi def $rdi
+; GENERIC-NEXT:    testb $1, %cl
+; GENERIC-NEXT:    cmovel %edx, %edi
+; GENERIC-NEXT:    leal (%rdi,%rsi), %eax
+; GENERIC-NEXT:    retq
+;
+; ATOM-LABEL: select_uaddo_common_op1:
+; ATOM:       ## %bb.0:
+; ATOM-NEXT:    ## kill: def $edi killed $edi def $rdi
+; ATOM-NEXT:    testb $1, %cl
+; ATOM-NEXT:    ## kill: def $esi killed $esi def $rsi
+; ATOM-NEXT:    cmovel %edx, %edi
+; ATOM-NEXT:    leal (%rdi,%rsi), %eax
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    retq
+;
+; ATHLON-LABEL: select_uaddo_common_op1:
+; ATHLON:       ## %bb.0:
+; ATHLON-NEXT:    testb $1, {{[0-9]+}}(%esp)
+; ATHLON-NEXT:    leal {{[0-9]+}}(%esp), %eax
+; ATHLON-NEXT:    leal {{[0-9]+}}(%esp), %ecx
+; ATHLON-NEXT:    cmovnel %eax, %ecx
+; ATHLON-NEXT:    movl (%ecx), %eax
+; ATHLON-NEXT:    addl {{[0-9]+}}(%esp), %eax
+; ATHLON-NEXT:    retl
+;
+; MCU-LABEL: select_uaddo_common_op1:
+; MCU:       # %bb.0:
+; MCU-NEXT:    testb $1, {{[0-9]+}}(%esp)
+; MCU-NEXT:    jne .LBB33_2
+; MCU-NEXT:  # %bb.1:
+; MCU-NEXT:    movl %ecx, %eax
+; MCU-NEXT:  .LBB33_2:
+; MCU-NEXT:    addl %edx, %eax
+; MCU-NEXT:    retl
+  %ab = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
+  %cb = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %c, i32 %b)
+  %ab0 = extractvalue { i32, i1 } %ab, 0
+  %cb0 = extractvalue { i32, i1 } %cb, 0
+  %sel = select i1 %cond, i32 %ab0, i32 %cb0
+  ret i32 %sel
+}


        


More information about the llvm-commits mailing list