diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -5621,12 +5621,37 @@ onlyUsesZeroFlag(SDValue(Node, 0))) { unsigned ShiftOpcode = ISD::DELETED_NODE; unsigned ShiftAmt; - if (isMask_64(~Mask)) { - ShiftOpcode = X86::SHR64ri; - ShiftAmt = countTrailingZeros(Mask); - } else if (isMask_64(Mask)) { - ShiftOpcode = X86::SHL64ri; - ShiftAmt = countLeadingZeros(Mask); + unsigned SubRegIdx = 0; + unsigned TestOpcode = ISD::DELETED_NODE; + MVT SubRegVT; + if (isShiftedMask_64(Mask)) { + unsigned LeadingZeros = countLeadingZeros(Mask); + unsigned TrailingZeros = countTrailingZeros(Mask); + if (LeadingZeros == 0) { + ShiftOpcode = X86::SHR64ri; + ShiftAmt = TrailingZeros; + } else if (TrailingZeros == 0) { + ShiftOpcode = X86::SHL64ri; + ShiftAmt = LeadingZeros; + } else { + unsigned PopCount = 64 - LeadingZeros - TrailingZeros; + if (PopCount == 8) { + ShiftOpcode = X86::SHR64ri; + TestOpcode = X86::TEST8rr; + SubRegIdx = X86::sub_8bit; + SubRegVT = MVT::i8; + } else if (PopCount == 16) { + ShiftOpcode = X86::SHR64ri; + TestOpcode = X86::TEST16rr; + SubRegIdx = X86::sub_16bit; + SubRegVT = MVT::i16; + } else if (PopCount == 32) { + ShiftOpcode = X86::SHR64ri; + TestOpcode = X86::TEST32rr; + SubRegIdx = X86::sub_32bit; + SubRegVT = MVT::i32; + } + } } if (ShiftOpcode != ISD::DELETED_NODE) { SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64); @@ -5634,8 +5659,16 @@ CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32, N0.getOperand(0), ShiftC), 0); - MachineSDNode *Test = - CurDAG->getMachineNode(X86::TEST64rr, dl, MVT::i32, Shift, Shift); + MachineSDNode *Test; + if (SubRegIdx == 0) { + Test = CurDAG->getMachineNode(X86::TEST64rr, dl, MVT::i32, Shift, + Shift); + } else { + SDValue TestOp = CurDAG->getTargetExtractSubreg(SubRegIdx, dl, + SubRegVT, Shift); + Test = CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, TestOp, + TestOp); + } ReplaceNode(Node, Test); return; } diff --git a/llvm/test/CodeGen/X86/cmp.ll b/llvm/test/CodeGen/X86/cmp.ll --- a/llvm/test/CodeGen/X86/cmp.ll +++ b/llvm/test/CodeGen/X86/cmp.ll @@ -533,9 +533,8 @@ define i1 @shifted_mask_testb(i64 %a) { ; CHECK-LABEL: shifted_mask_testb: ; CHECK: # %bb.0: -; CHECK-NEXT: movabsq $287104476244869120, %rax # encoding: [0x48,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x03] -; CHECK-NEXT: # imm = 0x3FC000000000000 -; CHECK-NEXT: testq %rax, %rdi # encoding: [0x48,0x85,0xc7] +; CHECK-NEXT: shrq $64, %rdi # encoding: [0x48,0xc1,0xef,0x40] +; CHECK-NEXT: testb %dil, %dil # encoding: [0x40,0x84,0xff] ; CHECK-NEXT: setne %al # encoding: [0x0f,0x95,0xc0] ; CHECK-NEXT: retq # encoding: [0xc3] %v0 = and i64 %a, 287104476244869120 ; 0xff << 50 @@ -546,9 +545,8 @@ define i1 @shifted_mask_testw(i64 %a) { ; CHECK-LABEL: shifted_mask_testw: ; CHECK: # %bb.0: -; CHECK-NEXT: movabsq $562941363486720, %rax # encoding: [0x48,0xb8,0x00,0x00,0x00,0x00,0xfe,0xff,0x01,0x00] -; CHECK-NEXT: # imm = 0x1FFFE00000000 -; CHECK-NEXT: testq %rax, %rdi # encoding: [0x48,0x85,0xc7] +; CHECK-NEXT: shrq $64, %rdi # encoding: [0x48,0xc1,0xef,0x40] +; CHECK-NEXT: testw %di, %di # encoding: [0x66,0x85,0xff] ; CHECK-NEXT: setne %al # encoding: [0x0f,0x95,0xc0] ; CHECK-NEXT: retq # encoding: [0xc3] %v0 = and i64 %a, 562941363486720 ; 0xffff << 33 @@ -559,9 +557,8 @@ define i1 @shifted_mask_testl(i64 %a) { ; CHECK-LABEL: shifted_mask_testl: ; CHECK: # %bb.0: -; CHECK-NEXT: movabsq $549755813760, %rax # encoding: [0x48,0xb8,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00] -; CHECK-NEXT: # imm = 0x7FFFFFFF80 -; CHECK-NEXT: testq %rax, %rdi # encoding: [0x48,0x85,0xc7] +; CHECK-NEXT: shrq $64, %rdi # encoding: [0x48,0xc1,0xef,0x40] +; CHECK-NEXT: testl %edi, %edi # encoding: [0x85,0xff] ; CHECK-NEXT: sete %al # encoding: [0x0f,0x94,0xc0] ; CHECK-NEXT: retq # encoding: [0xc3] %v0 = and i64 %a, 549755813760 ; 0xffffffff << 7