diff options
author | Craig Topper <craig.topper@gmail.com> | 2016-10-18 04:48:33 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@gmail.com> | 2016-10-18 04:48:33 +0000 |
commit | 448358b5f1f5db2e821641302aec4eba4d0a1df0 (patch) | |
tree | 2a39704b2e64eb11254905458f46ff666b898687 /llvm/lib | |
parent | f9df92c91569adbf640a69ba7a0d84344366bdeb (diff) | |
download | bcm5719-llvm-448358b5f1f5db2e821641302aec4eba4d0a1df0.tar.gz bcm5719-llvm-448358b5f1f5db2e821641302aec4eba4d0a1df0.zip |
[X86] Fix DecodeVPERMVMask to handle cases where the constant pool entry has a different type than the shuffle itself.
This is especially important for 32-bit targets with 64-bit shuffle elements.
llvm-svn: 284453
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp | 50 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h | 2 |
3 files changed, 24 insertions, 30 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 09b49ff8871..eaa2c5a3004 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5091,7 +5091,7 @@ static bool getTargetShuffleMask(SDNode *N, MVT VT, bool AllowSentinelZero, break; } if (auto *C = getTargetConstantFromNode(MaskNode)) { - DecodeVPERMVMask(C, VT, Mask); + DecodeVPERMVMask(C, MaskEltSize, Mask); break; } return false; diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp index 04b00d34d92..29498160842 100644 --- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp +++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp @@ -275,38 +275,32 @@ void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) { } } -void DecodeVPERMVMask(const Constant *C, MVT VT, +void DecodeVPERMVMask(const Constant *C, unsigned ElSize, SmallVectorImpl<int> &ShuffleMask) { Type *MaskTy = C->getType(); - if (MaskTy->isVectorTy()) { - unsigned NumElements = MaskTy->getVectorNumElements(); - if (NumElements == VT.getVectorNumElements()) { - unsigned EltMaskSize = Log2_64(NumElements); - for (unsigned i = 0; i < NumElements; ++i) { - Constant *COp = C->getAggregateElement(i); - if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp))) { - ShuffleMask.clear(); - return; - } - if (isa<UndefValue>(COp)) - ShuffleMask.push_back(SM_SentinelUndef); - else { - APInt Element = cast<ConstantInt>(COp)->getValue(); - Element = Element.getLoBits(EltMaskSize); - ShuffleMask.push_back(Element.getZExtValue()); - } - } - } + unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits(); + (void)MaskTySize; + assert((MaskTySize == 128 || MaskTySize == 256 || MaskTySize == 512) && + "Unexpected vector size."); + assert((ElSize == 8 || ElSize == 16 || ElSize == 32 || ElSize == 64) && + "Unexpected vector element size."); + + // The shuffle mask requires elements the same size as the target. + SmallBitVector UndefElts; + SmallVector<uint64_t, 8> RawMask; + if (!extractConstantMask(C, ElSize, UndefElts, RawMask)) return; + + unsigned NumElts = RawMask.size(); + + for (unsigned i = 0; i != NumElts; ++i) { + if (UndefElts[i]) { + ShuffleMask.push_back(SM_SentinelUndef); + continue; + } + int Index = RawMask[i] & (NumElts - 1); + ShuffleMask.push_back(Index); } - // Scalar value; just broadcast it - if (!isa<ConstantInt>(C)) - return; - uint64_t Element = cast<ConstantInt>(C)->getZExtValue(); - int NumElements = VT.getVectorNumElements(); - Element &= (1 << NumElements) - 1; - for (int i = 0; i < NumElements; ++i) - ShuffleMask.push_back(Element); } void DecodeVPERMV3Mask(const Constant *C, unsigned ElSize, diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h index 248719db195..b703cbbd2b2 100644 --- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h +++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h @@ -40,7 +40,7 @@ void DecodeVPERMIL2PMask(const Constant *C, unsigned MatchImm, unsigned ElSize, void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask); /// Decode a VPERM W/D/Q/PS/PD mask from an IR-level vector constant. -void DecodeVPERMVMask(const Constant *C, MVT VT, +void DecodeVPERMVMask(const Constant *C, unsigned ElSize, SmallVectorImpl<int> &ShuffleMask); /// Decode a VPERMT2 W/D/Q/PS/PD mask from an IR-level vector constant. |