Index: lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- lib/Target/X86/X86ISelDAGToDAG.cpp +++ lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2583,6 +2583,7 @@ } // See if this is an (X >> C1) & C2 that we can match to BEXTR/BEXTRI. +// We also handle (X >> C1) & (C2 << C3) as ((X >> (C1 + C3)) & C2) << C3 bool X86DAGToDAGISel::matchBEXTRFromAnd(SDNode *Node) { MVT NVT = Node->getSimpleValueType(0); SDLoc dl(Node); @@ -2611,17 +2612,19 @@ if (!MaskCst || !ShiftCst) return false; - // And RHS must be a mask. + // And RHS must be a (potentially shifted) mask. uint64_t Mask = MaskCst->getZExtValue(); - if (!isMask_64(Mask)) + if (!isShiftedMask_64(Mask)) return false; - uint64_t Shift = ShiftCst->getZExtValue(); uint64_t MaskSize = countPopulation(Mask); + uint64_t ZeroPaddingSize = countTrailingZeros(Mask); + + uint64_t Shift = ZeroPaddingSize + ShiftCst->getZExtValue(); // Don't interfere with something that can be handled by extracting AH. // TODO: If we are able to fold a load, BEXTR might still be better than AH. - if (Shift == 8 && MaskSize == 8) + if (Shift == 8 && MaskSize == 8 && ZeroPaddingSize == 0) return false; // Make sure we are only using bits that were in the original value, not @@ -2633,6 +2636,12 @@ SDValue C = CurDAG->getConstant(Shift | (MaskSize << 8), dl, NVT); SDValue New = CurDAG->getNode(X86ISD::BEXTR, dl, NVT, N0->getOperand(0), C); + if (ZeroPaddingSize > 0) { + insertDAGNode(*CurDAG, SDValue(Node, 0), New); + // If the mask had some zero low bits, we need to re-introduce them. + SDValue Cp = CurDAG->getConstant(ZeroPaddingSize, dl, MVT::i8); + New = CurDAG->getNode(ISD::SHL, dl, NVT, New, Cp); + } ReplaceNode(Node, New.getNode()); SelectCode(New.getNode()); return true; Index: test/CodeGen/X86/bmi-x86_64.ll =================================================================== --- test/CodeGen/X86/bmi-x86_64.ll +++ test/CodeGen/X86/bmi-x86_64.ll @@ -75,9 +75,9 @@ define i64 @non_bextr64(i64 %x) { ; CHECK-LABEL: non_bextr64: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: shrq $2, %rdi -; CHECK-NEXT: movabsq $8589934590, %rax # imm = 0x1FFFFFFFE -; CHECK-NEXT: andq %rdi, %rax +; CHECK-NEXT: movl $8195, %eax # imm = 0x2003 +; CHECK-NEXT: bextrq %rax, %rdi, %rax +; CHECK-NEXT: addq %rax, %rax ; CHECK-NEXT: retq entry: %shr = lshr i64 %x, 2 Index: test/CodeGen/X86/extract-bits.ll =================================================================== --- test/CodeGen/X86/extract-bits.ll +++ test/CodeGen/X86/extract-bits.ll @@ -5614,23 +5614,75 @@ ; ---------------------------------------------------------------------------- ; define void @pr38938(i32* %a0, i64* %a1) { -; X86-LABEL: pr38938: -; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl (%ecx), %ecx -; X86-NEXT: shrl $19, %ecx -; X86-NEXT: andl $4092, %ecx # imm = 0xFFC -; X86-NEXT: incl (%eax,%ecx) -; X86-NEXT: retl +; X86-NOBMI-LABEL: pr38938: +; X86-NOBMI: # %bb.0: +; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NOBMI-NEXT: movl (%ecx), %ecx +; X86-NOBMI-NEXT: shrl $19, %ecx +; X86-NOBMI-NEXT: andl $4092, %ecx # imm = 0xFFC +; X86-NOBMI-NEXT: incl (%eax,%ecx) +; X86-NOBMI-NEXT: retl ; -; X64-LABEL: pr38938: -; X64: # %bb.0: -; X64-NEXT: movq (%rsi), %rax -; X64-NEXT: shrq $19, %rax -; X64-NEXT: andl $4092, %eax # imm = 0xFFC -; X64-NEXT: incl (%rdi,%rax) -; X64-NEXT: retq +; X86-BMI1NOTBM-LABEL: pr38938: +; X86-BMI1NOTBM: # %bb.0: +; X86-BMI1NOTBM-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-BMI1NOTBM-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-BMI1NOTBM-NEXT: movl $2581, %edx # imm = 0xA15 +; X86-BMI1NOTBM-NEXT: bextrl %edx, (%ecx), %ecx +; X86-BMI1NOTBM-NEXT: shll $2, %ecx +; X86-BMI1NOTBM-NEXT: incl (%eax,%ecx) +; X86-BMI1NOTBM-NEXT: retl +; +; X86-BMI1TBM-LABEL: pr38938: +; X86-BMI1TBM: # %bb.0: +; X86-BMI1TBM-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-BMI1TBM-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-BMI1TBM-NEXT: bextrl $2581, (%ecx), %ecx # imm = 0xA15 +; X86-BMI1TBM-NEXT: shll $2, %ecx +; X86-BMI1TBM-NEXT: incl (%eax,%ecx) +; X86-BMI1TBM-NEXT: retl +; +; X86-BMI1NOTBMBMI2-LABEL: pr38938: +; X86-BMI1NOTBMBMI2: # %bb.0: +; X86-BMI1NOTBMBMI2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-BMI1NOTBMBMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-BMI1NOTBMBMI2-NEXT: movl $2581, %edx # imm = 0xA15 +; X86-BMI1NOTBMBMI2-NEXT: bextrl %edx, (%ecx), %ecx +; X86-BMI1NOTBMBMI2-NEXT: shll $2, %ecx +; X86-BMI1NOTBMBMI2-NEXT: incl (%eax,%ecx) +; X86-BMI1NOTBMBMI2-NEXT: retl +; +; X64-NOBMI-LABEL: pr38938: +; X64-NOBMI: # %bb.0: +; X64-NOBMI-NEXT: movq (%rsi), %rax +; X64-NOBMI-NEXT: shrq $19, %rax +; X64-NOBMI-NEXT: andl $4092, %eax # imm = 0xFFC +; X64-NOBMI-NEXT: incl (%rdi,%rax) +; X64-NOBMI-NEXT: retq +; +; X64-BMI1NOTBM-LABEL: pr38938: +; X64-BMI1NOTBM: # %bb.0: +; X64-BMI1NOTBM-NEXT: movl $2581, %eax # imm = 0xA15 +; X64-BMI1NOTBM-NEXT: bextrq %rax, (%rsi), %rax +; X64-BMI1NOTBM-NEXT: shlq $2, %rax +; X64-BMI1NOTBM-NEXT: incl (%rdi,%rax) +; X64-BMI1NOTBM-NEXT: retq +; +; X64-BMI1TBM-LABEL: pr38938: +; X64-BMI1TBM: # %bb.0: +; X64-BMI1TBM-NEXT: bextrq $2581, (%rsi), %rax # imm = 0xA15 +; X64-BMI1TBM-NEXT: shlq $2, %rax +; X64-BMI1TBM-NEXT: incl (%rdi,%rax) +; X64-BMI1TBM-NEXT: retq +; +; X64-BMI1NOTBMBMI2-LABEL: pr38938: +; X64-BMI1NOTBMBMI2: # %bb.0: +; X64-BMI1NOTBMBMI2-NEXT: movl $2581, %eax # imm = 0xA15 +; X64-BMI1NOTBMBMI2-NEXT: bextrq %rax, (%rsi), %rax +; X64-BMI1NOTBMBMI2-NEXT: shlq $2, %rax +; X64-BMI1NOTBMBMI2-NEXT: incl (%rdi,%rax) +; X64-BMI1NOTBMBMI2-NEXT: retq %tmp = load i64, i64* %a1, align 8 %tmp1 = lshr i64 %tmp, 21 %tmp2 = and i64 %tmp1, 1023 Index: test/CodeGen/X86/selectcc-to-shiftand.ll =================================================================== --- test/CodeGen/X86/selectcc-to-shiftand.ll +++ test/CodeGen/X86/selectcc-to-shiftand.ll @@ -35,9 +35,9 @@ ; ; CHECK-BMI-LABEL: neg_sel_special_constant: ; CHECK-BMI: # %bb.0: -; CHECK-BMI-NEXT: movl %edi, %eax -; CHECK-BMI-NEXT: shrl $22, %eax -; CHECK-BMI-NEXT: andl $512, %eax # imm = 0x200 +; CHECK-BMI-NEXT: movl $287, %eax # imm = 0x11F +; CHECK-BMI-NEXT: bextrl %eax, %edi, %eax +; CHECK-BMI-NEXT: shll $9, %eax ; CHECK-BMI-NEXT: retq %tmp.1 = icmp slt i32 %a, 0 %retval = select i1 %tmp.1, i32 512, i32 0 @@ -124,10 +124,10 @@ ; ; CHECK-BMI-LABEL: pos_sel_special_constant: ; CHECK-BMI: # %bb.0: -; CHECK-BMI-NEXT: movl %edi, %eax -; CHECK-BMI-NEXT: notl %eax -; CHECK-BMI-NEXT: shrl $22, %eax -; CHECK-BMI-NEXT: andl $512, %eax # imm = 0x200 +; CHECK-BMI-NEXT: notl %edi +; CHECK-BMI-NEXT: movl $287, %eax # imm = 0x11F +; CHECK-BMI-NEXT: bextrl %eax, %edi, %eax +; CHECK-BMI-NEXT: shll $9, %eax ; CHECK-BMI-NEXT: retq %tmp.1 = icmp sgt i32 %a, -1 %retval = select i1 %tmp.1, i32 512, i32 0