diff options
-rw-r--r-- | llvm/lib/Target/X86/X86MCInstLower.cpp | 34 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp | 71 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h | 4 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/vector-shuffle-combining-xop.ll | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/xop-mask-comments.ll | 92 |
5 files changed, 198 insertions, 5 deletions
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 0111d7fbdc2..00debd849cd 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1422,6 +1422,40 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { } break; } + + case X86::VPERMIL2PDrm: + case X86::VPERMIL2PSrm: + case X86::VPERMIL2PDrmY: + case X86::VPERMIL2PSrmY: { + if (!OutStreamer->isVerboseAsm()) + break; + assert(MI->getNumOperands() > 7 && + "We should always have at least 7 operands!"); + const MachineOperand &DstOp = MI->getOperand(0); + const MachineOperand &SrcOp1 = MI->getOperand(1); + const MachineOperand &SrcOp2 = MI->getOperand(2); + const MachineOperand &MaskOp = MI->getOperand(6); + const MachineOperand &CtrlOp = MI->getOperand(MI->getNumOperands() - 1); + + if (!CtrlOp.isImm()) + break; + + unsigned ElSize; + switch (MI->getOpcode()) { + default: llvm_unreachable("Invalid opcode"); + case X86::VPERMIL2PSrm: case X86::VPERMIL2PSrmY: ElSize = 32; break; + case X86::VPERMIL2PDrm: case X86::VPERMIL2PDrmY: ElSize = 64; break; + } + + if (auto *C = getConstantFromPool(*MI, MaskOp)) { + SmallVector<int, 16> Mask; + DecodeVPERMIL2PMask(C, (unsigned)CtrlOp.getImm(), ElSize, Mask); + if (!Mask.empty()) + OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp1, SrcOp2, Mask)); + } + break; + } + case X86::VPPERMrrm: { if (!OutStreamer->isVerboseAsm()) break; diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp index f24f38d4a21..abc05e43676 100644 --- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp +++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp @@ -153,6 +153,77 @@ void DecodeVPERMILPMask(const Constant *C, unsigned ElSize, // TODO: Handle funny-looking vectors too. } +void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize, + SmallVectorImpl<int> &ShuffleMask) { + Type *MaskTy = C->getType(); + + unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits(); + if (MaskTySize != 128 && MaskTySize != 256) + return; + + // Only support vector types. + if (!MaskTy->isVectorTy()) + return; + + // Make sure its an integer type. + Type *VecEltTy = MaskTy->getVectorElementType(); + if (!VecEltTy->isIntegerTy()) + return; + + // Support any element type from byte up to element size. + // This is necessary primarily because 64-bit elements get split to 32-bit + // in the constant pool on 32-bit target. + unsigned EltTySize = VecEltTy->getIntegerBitWidth(); + if (EltTySize < 8 || EltTySize > ElSize) + return; + + unsigned NumElements = MaskTySize / ElSize; + assert((NumElements == 2 || NumElements == 4 || NumElements == 8) && + "Unexpected number of vector elements."); + ShuffleMask.reserve(NumElements); + unsigned NumElementsPerLane = 128 / ElSize; + unsigned Factor = ElSize / EltTySize; + + for (unsigned i = 0; i < NumElements; ++i) { + Constant *COp = C->getAggregateElement(i * Factor); + if (!COp) { + ShuffleMask.clear(); + return; + } else if (isa<UndefValue>(COp)) { + ShuffleMask.push_back(SM_SentinelUndef); + continue; + } + + // VPERMIL2 Operation. + // Bits[3] - Match Bit. + // Bits[2:1] - (Per Lane) PD Shuffle Mask. + // Bits[2:0] - (Per Lane) PS Shuffle Mask. + uint64_t Selector = cast<ConstantInt>(COp)->getZExtValue(); + int MatchBit = (Selector >> 3) & 0x1; + + // M2Z[0:1] MatchBit + // 0Xb X Source selected by Selector index. + // 10b 0 Source selected by Selector index. + // 10b 1 Zero. + // 11b 0 Zero. + // 11b 1 Source selected by Selector index. + if ((M2Z & 0x2) != 0 && MatchBit != (M2Z & 0x1)) { + ShuffleMask.push_back(SM_SentinelZero); + continue; + } + + int Index = Selector & 0x3; + Index >>= (ElSize == 64 ? 1 : 0); + Index += (i / NumElementsPerLane) * NumElementsPerLane; + + int Src = (Selector >> 2) & 0x1; + Index += Src * NumElements; + ShuffleMask.push_back(Index); + } + + // TODO: Handle funny-looking vectors too. +} + void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) { Type *MaskTy = C->getType(); assert(MaskTy->getPrimitiveSizeInBits() == 128); diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h index a07b26c04f7..d2565b84980 100644 --- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h +++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h @@ -32,6 +32,10 @@ void DecodePSHUFBMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask); void DecodeVPERMILPMask(const Constant *C, unsigned ElSize, SmallVectorImpl<int> &ShuffleMask); +/// Decode a VPERMILP2 variable mask from an IR-level vector constant. +void DecodeVPERMIL2PMask(const Constant *C, unsigned MatchImm, unsigned ElSize, + SmallVectorImpl<int> &ShuffleMask); + /// Decode a VPPERM variable mask from an IR-level vector constant. void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask); diff --git a/llvm/test/CodeGen/X86/vector-shuffle-combining-xop.ll b/llvm/test/CodeGen/X86/vector-shuffle-combining-xop.ll index 9c352e7f98f..08547775fc1 100644 --- a/llvm/test/CodeGen/X86/vector-shuffle-combining-xop.ll +++ b/llvm/test/CodeGen/X86/vector-shuffle-combining-xop.ll @@ -62,7 +62,7 @@ define <8 x float> @combine_vpermil2ps256_identity(<8 x float> %a0, <8 x float> define <4 x float> @combine_vpermil2ps_blend_with_zero(<4 x float> %a0, <4 x float> %a1) { ; CHECK-LABEL: combine_vpermil2ps_blend_with_zero: ; CHECK: # BB#0: -; CHECK-NEXT: vpermil2ps $2, {{.*}}(%rip), %xmm1, %xmm0, %xmm0 +; CHECK-NEXT: vpermil2ps {{.*#+}} xmm0 = zero,xmm0[1,2,3] ; CHECK-NEXT: retq %res0 = call <4 x float> @llvm.x86.xop.vpermil2ps(<4 x float> %a0, <4 x float> %a1, <4 x i32> <i32 8, i32 1, i32 2, i32 3>, i8 2) ret <4 x float> %res0 diff --git a/llvm/test/CodeGen/X86/xop-mask-comments.ll b/llvm/test/CodeGen/X86/xop-mask-comments.ll index 363aa9e6552..351400819e6 100644 --- a/llvm/test/CodeGen/X86/xop-mask-comments.ll +++ b/llvm/test/CodeGen/X86/xop-mask-comments.ll @@ -95,10 +95,94 @@ define <16 x i8> @vpperm_shuffle_general(<16 x i8> %a0, <16 x i8> %a1) { ; VPERMIL2 ; -declare <2 x double> @llvm.x86.xop.vpermil2pd(<2 x double>, <2 x double>, <2 x double>, i8) nounwind readnone -declare <4 x double> @llvm.x86.xop.vpermil2pd.256(<4 x double>, <4 x double>, <4 x double>, i8) nounwind readnone +define <2 x double> @vpermil2pd_21(<2 x double> %a0, <2 x double> %a1) { +; X32-LABEL: vpermil2pd_21: +; X32: # BB#0: +; X32-NEXT: vpermil2pd {{.*#+}} xmm0 = xmm1[0],xmm0[1] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2pd_21: +; X64: # BB#0: +; X64-NEXT: vpermil2pd {{.*#+}} xmm0 = xmm1[0],xmm0[1] +; X64-NEXT: retq + %1 = call <2 x double> @llvm.x86.xop.vpermil2pd(<2 x double> %a0, <2 x double> %a1, <2 x i64> <i64 4, i64 2>, i8 0) + ret <2 x double> %1 +} + +define <4 x double> @vpermil2pd256_0062(<4 x double> %a0, <4 x double> %a1) { +; X32-LABEL: vpermil2pd256_0062: +; X32: # BB#0: +; X32-NEXT: vpermil2pd {{.*#+}} ymm0 = ymm0[0,0],ymm1[2],ymm0[2] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2pd256_0062: +; X64: # BB#0: +; X64-NEXT: vpermil2pd {{.*#+}} ymm0 = ymm0[0,0],ymm1[2],ymm0[2] +; X64-NEXT: retq + %1 = call <4 x double> @llvm.x86.xop.vpermil2pd.256(<4 x double> %a0, <4 x double> %a1, <4 x i64> <i64 0, i64 0, i64 4, i64 0>, i8 0) + ret <4 x double> %1 +} + +define <4 x double> @vpermil2pd256_zz73(<4 x double> %a0, <4 x double> %a1) { +; X32-LABEL: vpermil2pd256_zz73: +; X32: # BB#0: +; X32-NEXT: vpermil2pd {{.*#+}} ymm0 = zero,zero,ymm1[3],ymm0[3] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2pd256_zz73: +; X64: # BB#0: +; X64-NEXT: vpermil2pd {{.*#+}} ymm0 = zero,zero,ymm1[3],ymm0[3] +; X64-NEXT: retq + %1 = call <4 x double> @llvm.x86.xop.vpermil2pd.256(<4 x double> %a0, <4 x double> %a1, <4 x i64> <i64 0, i64 0, i64 14, i64 10>, i8 3) + ret <4 x double> %1 +} + +define <4 x float> @vpermil2ps_0561(<4 x float> %a0, <4 x float> %a1) { +; X32-LABEL: vpermil2ps_0561: +; X32: # BB#0: +; X32-NEXT: vpermil2ps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2],xmm0[1] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2ps_0561: +; X64: # BB#0: +; X64-NEXT: vpermil2ps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2],xmm0[1] +; X64-NEXT: retq + %1 = call <4 x float> @llvm.x86.xop.vpermil2ps(<4 x float> %a0, <4 x float> %a1, <4 x i32> <i32 0, i32 5, i32 6, i32 1>, i8 0) + ret <4 x float> %1 +} + +define <8 x float> @vpermil2ps256_098144FE(<8 x float> %a0, <8 x float> %a1) { +; X32-LABEL: vpermil2ps256_098144FE: +; X32: # BB#0: +; X32-NEXT: vpermil2ps {{.*#+}} ymm0 = ymm0[0],ymm1[1,0],ymm0[1,4,4],ymm1[7,6] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2ps256_098144FE: +; X64: # BB#0: +; X64-NEXT: vpermil2ps {{.*#+}} ymm0 = ymm0[0],ymm1[1,0],ymm0[1,4,4],ymm1[7,6] +; X64-NEXT: retq + %1 = call <8 x float> @llvm.x86.xop.vpermil2ps.256(<8 x float> %a0, <8 x float> %a1, <8 x i32> <i32 0, i32 5, i32 4, i32 1, i32 0, i32 0, i32 7, i32 6>, i8 0) + ret <8 x float> %1 +} + +define <8 x float> @vpermil2ps256_0zz8BzzA(<8 x float> %a0, <8 x float> %a1) { +; X32-LABEL: vpermil2ps256_0zz8BzzA: +; X32: # BB#0: +; X32-NEXT: vpermil2ps {{.*#+}} ymm0 = ymm0[0],zero,zero,ymm1[0,7],zero,zero,ymm1[6] +; X32-NEXT: retl +; +; X64-LABEL: vpermil2ps256_0zz8BzzA: +; X64: # BB#0: +; X64-NEXT: vpermil2ps {{.*#+}} ymm0 = ymm0[0],zero,zero,ymm1[0,7],zero,zero,ymm1[6] +; X64-NEXT: retq + %1 = call <8 x float> @llvm.x86.xop.vpermil2ps.256(<8 x float> %a0, <8 x float> %a1, <8 x i32> <i32 0, i32 8, i32 8, i32 4, i32 7, i32 8, i32 8, i32 6>, i8 2) + ret <8 x float> %1 +} + +declare <2 x double> @llvm.x86.xop.vpermil2pd(<2 x double>, <2 x double>, <2 x i64>, i8) nounwind readnone +declare <4 x double> @llvm.x86.xop.vpermil2pd.256(<4 x double>, <4 x double>, <4 x i64>, i8) nounwind readnone -declare <4 x float> @llvm.x86.xop.vpermil2ps(<4 x float>, <4 x float>, <4 x float>, i8) nounwind readnone -declare <8 x float> @llvm.x86.xop.vpermil2ps.256(<8 x float>, <8 x float>, <8 x float>, i8) nounwind readnone +declare <4 x float> @llvm.x86.xop.vpermil2ps(<4 x float>, <4 x float>, <4 x i32>, i8) nounwind readnone +declare <8 x float> @llvm.x86.xop.vpermil2ps.256(<8 x float>, <8 x float>, <8 x i32>, i8) nounwind readnone declare <16 x i8> @llvm.x86.xop.vpperm(<16 x i8>, <16 x i8>, <16 x i8>) nounwind readnone |