diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a956074e50d86..a206fdf62c6e2 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -51887,6 +51887,27 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG, } } + if (Subtarget.is64Bit()&&!Subtarget.isSHLDSlow()&&(VT == MVT::i16||VT == MVT::i32||VT == MVT::i64)) { + using namespace llvm::SDPatternMatch; + APInt MaskConst, ShlConst; + SDValue A, B; + if (sd_match(N, m_Or(m_Shl(m_Value(B), m_ConstInt(ShlConst)), + m_And(m_Value(A), m_ConstInt(MaskConst))))) { + uint64_t ShiftValue = ShlConst.getZExtValue(); + if (MaskConst.isMask(ShiftValue)&& (A.getOpcode()==ISD::CopyFromReg|| A.getOpcode()==ISD::TRUNCATE)&& (B.getOpcode()==ISD::CopyFromReg||B.getOpcode()==ISD::TRUNCATE)) { + unsigned NumBits = B.getScalarValueSizeInBits(); + unsigned NewShift = NumBits - ShiftValue; + if(ShiftValue>4&&ShiftValue!=8&&ShiftValue!=16&&ShiftValue!=32&&ShiftValue!=64){ + SDValue NewSHL = DAG.getNode( + ISD::SHL, dl, VT, A, DAG.getShiftAmountConstant(NewShift, VT, dl)); + SDValue R = DAG.getNode(ISD::FSHR, dl, VT, B, NewSHL, + DAG.getShiftAmountConstant(NewShift, VT, dl)); + return R; + } + } + } + } + if (SDValue SetCC = combineAndOrForCcmpCtest(N, DAG, DCI, Subtarget)) return SetCC; diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll new file mode 100644 index 0000000000000..2d8825dab2974 --- /dev/null +++ b/llvm/test/CodeGen/X86/insert-bitfield.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=X64,X64-FAST +; RUN: llc < %s -mtriple=x86_64-- -mattr=+slow-shld | FileCheck %s --check-prefixes=X64,X64-SLOW + +define i64 @updateTop10Bits_64bits(i64 %A, i64 %B) { +; X64-FAST-LABEL: updateTop10Bits_64bits: +; X64-FAST: # %bb.0: +; X64-FAST-NEXT: movq %rdi, %rax +; X64-FAST-NEXT: shlq $10, %rax +; X64-FAST-NEXT: shrdq $10, %rsi, %rax +; X64-FAST-NEXT: retq +; +; X64-SLOW-LABEL: updateTop10Bits_64bits: +; X64-SLOW: # %bb.0: +; X64-SLOW-NEXT: movabsq $18014398509481983, %rax +; X64-SLOW-NEXT: andq %rdi, %rax +; X64-SLOW-NEXT: shlq $54, %rsi +; X64-SLOW-NEXT: orq %rsi, %rax +; X64-SLOW-NEXT: retq +entry: + %and = and i64 %A, 18014398509481983 + %shl = shl i64 %B, 54 + %or = or disjoint i64 %shl, %and + ret i64 %or +} + +define i32 @updateTop10Bits_32bits(i32 %A, i32 %B) { +; X64-FAST-LABEL: updateTop10Bits_32bits: +; X64-FAST: # %bb.0: # %entry +; X64-FAST-NEXT: movl %edi, %eax +; X64-FAST-NEXT: shll $10, %eax +; X64-FAST-NEXT: shrdl $10, %esi, %eax +; X64-FAST-NEXT: retq +; +; X64-SLOW-LABEL: updateTop10Bits_32bits: +; X64-SLOW: # %bb.0: # %entry +; X64-SLOW-NEXT: # kill: def $esi killed $esi def $rsi +; X64-SLOW-NEXT: # kill: def $edi killed $edi def $rdi +; X64-SLOW-NEXT: andl $4194303, %edi # imm = 0x3FFFFF +; X64-SLOW-NEXT: shll $22, %esi +; X64-SLOW-NEXT: leal (%rsi,%rdi), %eax +; X64-SLOW-NEXT: retq +entry: + %and = and i32 %A, 4194303 + %shl = shl i32 %B, 22 + %or = or disjoint i32 %shl, %and + ret i32 %or +} + +define i16 @updateTop10Bits_16bits(i16 %A, i16 %B) { +; X64-FAST-LABEL: updateTop10Bits_16bits: +; X64-FAST: # %bb.0: # %entry +; X64-FAST-NEXT: movl %edi, %eax +; X64-FAST-NEXT: shll $10, %eax +; X64-FAST-NEXT: shrdw $10, %si, %ax +; X64-FAST-NEXT: # kill: def $ax killed $ax killed $eax +; X64-FAST-NEXT: retq +; +; X64-SLOW-LABEL: updateTop10Bits_16bits: +; X64-SLOW: # %bb.0: # %entry +; X64-SLOW-NEXT: # kill: def $esi killed $esi def $rsi +; X64-SLOW-NEXT: # kill: def $edi killed $edi def $rdi +; X64-SLOW-NEXT: andl $63, %edi +; X64-SLOW-NEXT: shll $6, %esi +; X64-SLOW-NEXT: leal (%rsi,%rdi), %eax +; X64-SLOW-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SLOW-NEXT: retq +entry: + %and = and i16 %A, 63 + %shl = shl i16 %B, 6 + %or = or disjoint i16 %shl, %and + ret i16 %or +} + +define i8 @updateTop3Bits_8bits(i8 %A, i8 %B) { +; X64-LABEL: updateTop3Bits_8bits: +; X64: # %bb.0: # %entry +; X64-NEXT: # kill: def $esi killed $esi def $rsi +; X64-NEXT: andb $7, %dil +; X64-NEXT: leal (,%rsi,8), %eax +; X64-NEXT: orb %dil, %al +; X64-NEXT: # kill: def $al killed $al killed $eax +; X64-NEXT: retq + +entry: + %and = and i8 %A, 7 + %shl = shl i8 %B, 3 + %or = or disjoint i8 %shl, %and + ret i8 %or +} \ No newline at end of file