diff options
author | Craig Topper <craig.topper@gmail.com> | 2013-09-02 07:53:17 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@gmail.com> | 2013-09-02 07:53:17 +0000 |
commit | 69c474ffa8a4b0186067e39d338a165d4165af2b (patch) | |
tree | 87ab20fb6bd0890ab5ddcfdd121599b78855173f /lib/Target/X86/X86ISelLowering.cpp | |
parent | da0ce6eb8b11083b5cc1849b625509b87a7d9db9 (diff) | |
download | external_llvm-69c474ffa8a4b0186067e39d338a165d4165af2b.zip external_llvm-69c474ffa8a4b0186067e39d338a165d4165af2b.tar.gz external_llvm-69c474ffa8a4b0186067e39d338a165d4165af2b.tar.bz2 |
Create BEXTR instructions for (and ((sra or srl) x, imm), (2**size - 1)). Fixes PR17028.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189742 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 739c144..ba6c9c0 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -13693,6 +13693,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::BLSMSK: return "X86ISD::BLSMSK"; case X86ISD::BLSR: return "X86ISD::BLSR"; case X86ISD::BZHI: return "X86ISD::BZHI"; + case X86ISD::BEXTR: return "X86ISD::BEXTR"; case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM"; case X86ISD::PTEST: return "X86ISD::PTEST"; case X86ISD::TESTP: return "X86ISD::TESTP"; @@ -17503,6 +17504,7 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, // BLSI is X & (-X) // BLSR is X & (X-1) // BZHI is X & ((1 << Y) - 1) + // BEXTR is ((X >> imm) & (2**size-1)) if (VT == MVT::i32 || VT == MVT::i64) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -17528,6 +17530,22 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, if (N1.getOpcode() == ISD::ADD && N1.getOperand(0) == N0 && isAllOnes(N1.getOperand(1))) return DAG.getNode(X86ISD::BLSR, DL, VT, N0); + + // Check for BEXTR + if (N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::SRL) { + ConstantSDNode *MaskNode = dyn_cast<ConstantSDNode>(N1); + ConstantSDNode *ShiftNode = dyn_cast<ConstantSDNode>(N0.getOperand(1)); + if (MaskNode && ShiftNode) { + uint64_t Mask = MaskNode->getZExtValue(); + uint64_t Shift = ShiftNode->getZExtValue(); + if (isMask_64(Mask)) { + uint64_t MaskSize = CountPopulation_64(Mask); + if (Shift + MaskSize <= VT.getSizeInBits()) + return DAG.getNode(X86ISD::BEXTR, DL, VT, N0.getOperand(0), + DAG.getConstant(Shift | (MaskSize << 8), VT)); + } + } + } } if (Subtarget->hasBMI2()) { |