]> granicus.if.org Git - llvm/commitdiff
[DAGCombiner] fold assertzexts separated by trunc
authorSanjay Patel <spatel@rotateright.com>
Mon, 18 Sep 2017 22:05:35 +0000 (22:05 +0000)
committerSanjay Patel <spatel@rotateright.com>
Mon, 18 Sep 2017 22:05:35 +0000 (22:05 +0000)
If we have an AssertZext of a truncated value that has already been AssertZext'ed,
we can assert on the wider source op to improve the zext-y knowledge:
 assert (trunc (assert X, i8) to iN), i1 --> trunc (assert X, i1) to iN

This moves a fold from being Mips-specific to general combining, and x86 shows
improvements.

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

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

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
lib/Target/Mips/MipsISelLowering.cpp
test/CodeGen/X86/bool-zext.ll
test/CodeGen/X86/critical-edge-split-2.ll
test/CodeGen/X86/fp128-select.ll
test/CodeGen/X86/illegal-bitfield-loadstore.ll
test/CodeGen/X86/mask-negated-bool.ll
test/CodeGen/X86/negate-i1.ll
test/CodeGen/X86/select_const.ll
test/CodeGen/X86/sext-i1.ll

index b69a5f4738cb21404da8b4a67894ee14567c6af3..018ea1b48b8186933fea5272136187a199894966 100644 (file)
@@ -7970,16 +7970,39 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
   return SDValue();
 }
 
+// TODO: These transforms should work with AssertSext too.
+// Change the function name, comments, opcode references, and caller.
 SDValue DAGCombiner::visitAssertZext(SDNode *N) {
   SDValue N0 = N->getOperand(0);
   SDValue N1 = N->getOperand(1);
-  EVT EVT = cast<VTSDNode>(N1)->getVT();
+  EVT AssertVT = cast<VTSDNode>(N1)->getVT();
 
   // fold (assertzext (assertzext x, vt), vt) -> (assertzext x, vt)
   if (N0.getOpcode() == ISD::AssertZext &&
-      EVT == cast<VTSDNode>(N0.getOperand(1))->getVT())
+      AssertVT == cast<VTSDNode>(N0.getOperand(1))->getVT())
     return N0;
 
+  if (N0.getOpcode() == ISD::TRUNCATE && N0.hasOneUse() &&
+      N0.getOperand(0).getOpcode() == ISD::AssertZext) {
+    // We have an assert, truncate, assert sandwich. Make one stronger assert
+    // by asserting on the smallest asserted type to the larger source type.
+    // This eliminates the later assert:
+    // assert (trunc (assert X, i8) to iN), i1 --> trunc (assert X, i1) to iN
+    // assert (trunc (assert X, i1) to iN), i8 --> trunc (assert X, i1) to iN
+    SDValue BigA = N0.getOperand(0);
+    EVT BigA_AssertVT = cast<VTSDNode>(BigA.getOperand(1))->getVT();
+    assert(BigA_AssertVT.bitsLE(N0.getValueType()) &&
+           "Asserting zero/sign-extended bits from a type larger than the "
+           "truncated destination does not provide information");
+
+    SDLoc DL(N);
+    EVT MinAssertVT = AssertVT.bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
+    SDValue MinAssertVTVal = DAG.getValueType(MinAssertVT);
+    SDValue NewAssert = DAG.getNode(ISD::AssertZext, DL, BigA.getValueType(),
+                                    BigA.getOperand(0), MinAssertVTVal);
+    return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewAssert);
+  }
+
   return SDValue();
 }
 
index 4c8f87f9381caec681b2df4d091a77de710cdc38..06874eb97964024d10ffed707da56c5b4f071d07 100644 (file)
@@ -1112,37 +1112,6 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
   return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo);
 }
 
-static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
-                                        TargetLowering::DAGCombinerInfo &DCI,
-                                        const MipsSubtarget &Subtarget) {
-  SDValue N0 = N->getOperand(0);
-  EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT();
-
-  if (N0.getOpcode() != ISD::TRUNCATE)
-    return SDValue();
-
-  if (N0.getOperand(0).getOpcode() != ISD::AssertZext)
-    return SDValue();
-
-  // fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x))
-  // if the type of the extension of the innermost AssertZext node is
-  // smaller from that of the outermost node, eg:
-  // (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8)
-  //   -> (trunc:i32 (AssertZext X, i8))
-  SDValue WiderAssertZext = N0.getOperand(0);
-  EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT();
-
-  if (NarrowerVT.bitsLT(WiderVT)) {
-    SDValue NewAssertZext = DAG.getNode(
-        ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(),
-        WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT));
-    return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0),
-                       NewAssertZext);
-  }
-
-  return SDValue();
-}
-
 static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
                                  TargetLowering::DAGCombinerInfo &DCI,
                                  const MipsSubtarget &Subtarget) {
@@ -1215,8 +1184,6 @@ SDValue  MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
     return performORCombine(N, DAG, DCI, Subtarget);
   case ISD::ADD:
     return performADDCombine(N, DAG, DCI, Subtarget);
-  case ISD::AssertZext:
-    return performAssertZextCombine(N, DAG, DCI, Subtarget);
   case ISD::SHL:
     return performSHLCombine(N, DAG, DCI, Subtarget);
   case ISD::SUB:
index b2680c570e097adc7e4246bf3501f5705fffd7fd..e9375f7313610b6e094d8f299c597ff241f1cbb6 100644 (file)
@@ -2,7 +2,7 @@
 ; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s -check-prefix=X32
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -check-prefix=X64
 
-; Check that the argument gets zero-extended before calling.
+; It's not necessary to zero-extend the arg because it is specified 'zeroext'. 
 define void @bar1(i1 zeroext %v1) nounwind ssp {
 ; X32-LABEL: bar1:
 ; X32:       # BB#0:
@@ -14,7 +14,6 @@ define void @bar1(i1 zeroext %v1) nounwind ssp {
 ;
 ; X64-LABEL: bar1:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %dil, %edi
 ; X64-NEXT:    xorl %eax, %eax
 ; X64-NEXT:    jmp foo1 # TAILCALL
   %conv = zext i1 %v1 to i32
index 693d1ab1fcfc315346289c9c716b869e4006001e..9dd13cabac5956b51fa42632cff4393bb461369c 100644 (file)
@@ -12,7 +12,7 @@ define i16 @test1(i1 zeroext %C, i8** nocapture %argv) nounwind ssp {
 ; CHECK-LABEL: test1:
 ; CHECK:       # BB#0: # %entry
 ; CHECK-NEXT:    movw $1, %ax
-; CHECK-NEXT:    testb %dil, %dil
+; CHECK-NEXT:    testl %edi, %edi
 ; CHECK-NEXT:    jne .LBB0_2
 ; CHECK-NEXT:  # BB#1: # %cond.false.i
 ; CHECK-NEXT:    movl $g_4, %eax
index c02db1fcdde845f59407f576caa1ca47d29a66c4..9416163357e0a84dee8ded3cbd43b5953c27ed63 100644 (file)
@@ -11,7 +11,7 @@
 define void @test_select(fp128* %p, fp128* %q, i1 zeroext %c) {
 ; MMX-LABEL: test_select:
 ; MMX:       # BB#0:
-; MMX-NEXT:    testb %dl, %dl
+; MMX-NEXT:    testl %edx, %edx
 ; MMX-NEXT:    jne .LBB0_1
 ; MMX-NEXT:  # BB#2:
 ; MMX-NEXT:    movaps {{.*}}(%rip), %xmm0
@@ -25,7 +25,7 @@ define void @test_select(fp128* %p, fp128* %q, i1 zeroext %c) {
 ; CHECK-LABEL: test_select:
 ; CHECK:       # BB#0:
 ; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    testb %dl, %dl
+; CHECK-NEXT:    testl %edx, %edx
 ; CHECK-NEXT:    cmovneq (%rdi), %rax
 ; CHECK-NEXT:    movabsq $9223231299366420480, %rcx # imm = 0x7FFF800000000000
 ; CHECK-NEXT:    cmovneq 8(%rdi), %rcx
index 8059e4acbb114d0c291c64e6062a1831c649869e..5450809bb1031ba830e8e7fae2c2e23586808f4b 100644 (file)
@@ -87,16 +87,15 @@ define void @i24_insert_bit(i24* %a, i1 zeroext %bit) {
 ;
 ; X64-LABEL: i24_insert_bit:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %sil, %eax
-; X64-NEXT:    movzwl (%rdi), %ecx
-; X64-NEXT:    movzbl 2(%rdi), %edx
-; X64-NEXT:    movb %dl, 2(%rdi)
-; X64-NEXT:    shll $16, %edx
-; X64-NEXT:    orl %ecx, %edx
-; X64-NEXT:    shll $13, %eax
-; X64-NEXT:    andl $16769023, %edx # imm = 0xFFDFFF
-; X64-NEXT:    orl %eax, %edx
-; X64-NEXT:    movw %dx, (%rdi)
+; X64-NEXT:    movzwl (%rdi), %eax
+; X64-NEXT:    movzbl 2(%rdi), %ecx
+; X64-NEXT:    movb %cl, 2(%rdi)
+; X64-NEXT:    shll $16, %ecx
+; X64-NEXT:    orl %eax, %ecx
+; X64-NEXT:    shll $13, %esi
+; X64-NEXT:    andl $16769023, %ecx # imm = 0xFFDFFF
+; X64-NEXT:    orl %esi, %ecx
+; X64-NEXT:    movw %cx, (%rdi)
 ; X64-NEXT:    retq
   %extbit = zext i1 %bit to i24
   %b = load i24, i24* %a, align 1
@@ -185,7 +184,7 @@ define void @i56_insert_bit(i56* %a, i1 zeroext %bit) {
 ;
 ; X64-LABEL: i56_insert_bit:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %sil, %eax
+; X64-NEXT:    movl %esi, %eax
 ; X64-NEXT:    movzwl 4(%rdi), %ecx
 ; X64-NEXT:    movzbl 6(%rdi), %edx
 ; X64-NEXT:    movb %dl, 6(%rdi)
index 779641cee7d22fa9bf746e7534dc4523bd310a1b..29ecbf01c0f914e2492bad40484ad55c02ae5153 100644 (file)
@@ -16,7 +16,7 @@ define i32 @mask_negated_zext_bool1(i1 %x) {
 define i32 @mask_negated_zext_bool2(i1 zeroext %x) {
 ; CHECK-LABEL: mask_negated_zext_bool2:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    retq
   %ext = zext i1 %x to i32
   %neg = sub i32 0, %ext
@@ -50,7 +50,7 @@ define i32 @mask_negated_sext_bool1(i1 %x) {
 define i32 @mask_negated_sext_bool2(i1 zeroext %x) {
 ; CHECK-LABEL: mask_negated_sext_bool2:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    retq
   %ext = sext i1 %x to i32
   %neg = sub i32 0, %ext
index 13f831fd37b7b0f4b756834f50a48ef79918976a..3736f4df5ecb8aa8a61d681b4c1b1dbd18bf729a 100644 (file)
@@ -58,9 +58,8 @@ define i16 @select_i16_neg1_or_0(i1 %a) {
 define i16 @select_i16_neg1_or_0_zeroext(i1 zeroext %a) {
 ; X64-LABEL: select_i16_neg1_or_0_zeroext:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %dil, %eax
-; X64-NEXT:    negl %eax
-; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
+; X64-NEXT:    negl %edi
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    retq
 ;
 ; X32-LABEL: select_i16_neg1_or_0_zeroext:
@@ -94,8 +93,8 @@ define i32 @select_i32_neg1_or_0(i1 %a) {
 define i32 @select_i32_neg1_or_0_zeroext(i1 zeroext %a) {
 ; X64-LABEL: select_i32_neg1_or_0_zeroext:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %dil, %eax
-; X64-NEXT:    negl %eax
+; X64-NEXT:    negl %edi
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    retq
 ;
 ; X32-LABEL: select_i32_neg1_or_0_zeroext:
@@ -130,7 +129,7 @@ define i64 @select_i64_neg1_or_0(i1 %a) {
 define i64 @select_i64_neg1_or_0_zeroext(i1 zeroext %a) {
 ; X64-LABEL: select_i64_neg1_or_0_zeroext:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %dil, %eax
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    negq %rax
 ; X64-NEXT:    retq
 ;
index 7d13cc7b788c7e72c811ec70fd0918e1663d96f5..07aa909d9a94e4c1b3e089e2aaf835207029ed66 100644 (file)
@@ -53,7 +53,7 @@ define i32 @select_1_or_0(i1 %cond) {
 define i32 @select_1_or_0_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_1_or_0_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    retq
   %sel = select i1 %cond, i32 1, i32 0
   ret i32 %sel
@@ -85,8 +85,8 @@ define i32 @select_0_or_neg1(i1 %cond) {
 define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_0_or_neg1_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
-; CHECK-NEXT:    decl %eax
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal -1(%rdi), %eax
 ; CHECK-NEXT:    retq
   %sel = select i1 %cond, i32 0, i32 -1
   ret i32 %sel
@@ -119,8 +119,8 @@ define i32 @select_neg1_or_0(i1 %cond) {
 define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_neg1_or_0_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
-; CHECK-NEXT:    negl %eax
+; CHECK-NEXT:    negl %edi
+; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    retq
   %sel = select i1 %cond, i32 -1, i32 0
   ret i32 %sel
@@ -151,8 +151,8 @@ define i32 @select_Cplus1_C(i1 %cond) {
 define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_Cplus1_C_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %eax
-; CHECK-NEXT:    addl $41, %eax
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal 41(%rdi), %eax
 ; CHECK-NEXT:    retq
   %sel = select i1 %cond, i32 42, i32 41
   ret i32 %sel
@@ -185,9 +185,8 @@ define i32 @select_C_Cplus1(i1 %cond) {
 define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_C_Cplus1_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movzbl %dil, %ecx
 ; CHECK-NEXT:    movl $42, %eax
-; CHECK-NEXT:    subl %ecx, %eax
+; CHECK-NEXT:    subl %edi, %eax
 ; CHECK-NEXT:    retq
   %sel = select i1 %cond, i32 41, i32 42
   ret i32 %sel
@@ -413,7 +412,7 @@ define i32 @select_C1_C2(i1 %cond) {
 define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
 ; CHECK-LABEL: select_C1_C2_zeroext:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    testb %dil, %dil
+; CHECK-NEXT:    testl %edi, %edi
 ; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
 ; CHECK-NEXT:    movl $42, %eax
 ; CHECK-NEXT:    cmovnel %ecx, %eax
index d159fe1742290d00b3bc6b8f53be96e0475b52bf..0c840e69c7c6ff422c9f3d5dfedb4cad6916601f 100644 (file)
@@ -144,8 +144,8 @@ define i32 @select_0_or_1s_zeroext(i1 zeroext %cond) {
 ;
 ; X64-LABEL: select_0_or_1s_zeroext:
 ; X64:       # BB#0:
-; X64-NEXT:    movzbl %dil, %eax
-; X64-NEXT:    decl %eax
+; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; X64-NEXT:    leal -1(%rdi), %eax
 ; X64-NEXT:    retq
   %not = xor i1 %cond, 1
   %sext = sext i1 %not to i32