Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7970,16 +7970,39 @@ 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(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. 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(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: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp @@ -1112,37 +1112,6 @@ 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(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(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 @@ 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: llvm/trunk/test/CodeGen/X86/bool-zext.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/bool-zext.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/critical-edge-split-2.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/critical-edge-split-2.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/fp128-select.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/fp128-select.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/illegal-bitfield-loadstore.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/illegal-bitfield-loadstore.ll +++ llvm/trunk/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,7 +184,7 @@ ; ; 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: llvm/trunk/test/CodeGen/X86/mask-negated-bool.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/mask-negated-bool.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/negate-i1.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/negate-i1.ll +++ llvm/trunk/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,7 +129,7 @@ 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: llvm/trunk/test/CodeGen/X86/select_const.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/select_const.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/sext-i1.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/sext-i1.ll +++ llvm/trunk/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