Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7907,13 +7907,29 @@ SDValue DAGCombiner::visitAssertZext(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); - EVT EVT = cast(N1)->getVT(); + EVT AssertVT = cast(N1)->getVT(); // fold (assertzext (assertzext x, vt), vt) -> (assertzext x, vt) if (N0.getOpcode() == ISD::AssertZext && - EVT == cast(N0.getOperand(1))->getVT()) + AssertVT == cast(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. If the later assert has a + // smaller asserting type, make the first assert stronger by asserting on + // that smaller type. This eliminates the later assert: + // assert (trunc (assert X, i8) to iN), i1 --> trunc (assert X, i1) to iN + SDValue BigAZ = N0.getOperand(0); + EVT BigAZVT = cast(BigAZ.getOperand(1))->getVT(); + if (AssertVT.getSizeInBits() < BigAZVT.getSizeInBits()) { + SDLoc DL(N); + SDValue NewAZ = DAG.getNode(ISD::AssertZext, DL, BigAZ.getValueType(), + BigAZ.getOperand(0), N1); + return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewAZ); + } + } + return SDValue(); } Index: test/CodeGen/X86/bool-zext.ll =================================================================== --- test/CodeGen/X86/bool-zext.ll +++ test/CodeGen/X86/bool-zext.ll @@ -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 @@ ; ; 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: test/CodeGen/X86/critical-edge-split-2.ll =================================================================== --- test/CodeGen/X86/critical-edge-split-2.ll +++ test/CodeGen/X86/critical-edge-split-2.ll @@ -12,7 +12,7 @@ ; 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: test/CodeGen/X86/fp128-select.ll =================================================================== --- test/CodeGen/X86/fp128-select.ll +++ test/CodeGen/X86/fp128-select.ll @@ -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 @@ ; 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: test/CodeGen/X86/illegal-bitfield-loadstore.ll =================================================================== --- test/CodeGen/X86/illegal-bitfield-loadstore.ll +++ test/CodeGen/X86/illegal-bitfield-loadstore.ll @@ -87,16 +87,15 @@ ; ; 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,23 +184,23 @@ ; ; X64-LABEL: i56_insert_bit: ; X64: # BB#0: -; X64-NEXT: movzbl %sil, %eax -; X64-NEXT: movzwl 4(%rdi), %ecx -; X64-NEXT: movzbl 6(%rdi), %edx -; X64-NEXT: movl (%rdi), %esi -; X64-NEXT: movb %dl, 6(%rdi) -; X64-NEXT: # kill: %EDX %EDX %RDX %RDX -; X64-NEXT: shll $16, %edx -; X64-NEXT: orl %ecx, %edx -; X64-NEXT: shlq $32, %rdx -; X64-NEXT: orq %rdx, %rsi -; X64-NEXT: shlq $13, %rax -; X64-NEXT: movabsq $72057594037919743, %rcx # imm = 0xFFFFFFFFFFDFFF -; X64-NEXT: andq %rsi, %rcx -; X64-NEXT: orq %rax, %rcx -; X64-NEXT: movl %ecx, (%rdi) -; X64-NEXT: shrq $32, %rcx -; X64-NEXT: movw %cx, 4(%rdi) +; X64-NEXT: # kill: %ESI %ESI %RSI +; X64-NEXT: movzwl 4(%rdi), %eax +; X64-NEXT: movzbl 6(%rdi), %ecx +; X64-NEXT: movl (%rdi), %edx +; X64-NEXT: movb %cl, 6(%rdi) +; X64-NEXT: # kill: %ECX %ECX %RCX %RCX +; X64-NEXT: shll $16, %ecx +; X64-NEXT: orl %eax, %ecx +; X64-NEXT: shlq $32, %rcx +; X64-NEXT: orq %rcx, %rdx +; X64-NEXT: shlq $13, %rsi +; X64-NEXT: movabsq $72057594037919743, %rax # imm = 0xFFFFFFFFFFDFFF +; X64-NEXT: andq %rdx, %rax +; X64-NEXT: orq %rsi, %rax +; X64-NEXT: movl %eax, (%rdi) +; X64-NEXT: shrq $32, %rax +; X64-NEXT: movw %ax, 4(%rdi) ; X64-NEXT: retq %extbit = zext i1 %bit to i56 %b = load i56, i56* %a, align 1 Index: test/CodeGen/X86/mask-negated-bool.ll =================================================================== --- test/CodeGen/X86/mask-negated-bool.ll +++ test/CodeGen/X86/mask-negated-bool.ll @@ -16,7 +16,7 @@ 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_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: test/CodeGen/X86/negate-i1.ll =================================================================== --- test/CodeGen/X86/negate-i1.ll +++ test/CodeGen/X86/negate-i1.ll @@ -58,9 +58,8 @@ 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 %AX %EAX +; 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_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,8 +129,9 @@ 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: negq %rax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: negq %rdi +; X64-NEXT: movq %rdi, %rax ; X64-NEXT: retq ; ; X32-LABEL: select_i64_neg1_or_0_zeroext: Index: test/CodeGen/X86/select_const.ll =================================================================== --- test/CodeGen/X86/select_const.ll +++ test/CodeGen/X86/select_const.ll @@ -53,7 +53,7 @@ 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_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 %EDI %RDI +; 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_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_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 %EDI %RDI +; 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_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_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: test/CodeGen/X86/sext-i1.ll =================================================================== --- test/CodeGen/X86/sext-i1.ll +++ test/CodeGen/X86/sext-i1.ll @@ -144,8 +144,8 @@ ; ; X64-LABEL: select_0_or_1s_zeroext: ; X64: # BB#0: -; X64-NEXT: movzbl %dil, %eax -; X64-NEXT: decl %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal -1(%rdi), %eax ; X64-NEXT: retq %not = xor i1 %cond, 1 %sext = sext i1 %not to i32