diff --git a/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp b/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp index 676be025b..0e86c111a 100644 --- a/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp @@ -4914,10 +4914,10 @@ DEF_OP(VRev64) { } else if (OpSize == Core::CPUState::XMM_SSE_REG_SIZE) { vpshufd(Dst, Vector, - (0b11 << 0) | - (0b10 << 2) | - (0b01 << 4) | - (0b00 << 6)); + (0b01 << 0) | + (0b00 << 2) | + (0b11 << 4) | + (0b10 << 6)); } else { vpshufd(Dst, Vector, diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 7e971f989..058a4194e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -1262,6 +1262,135 @@ OrderedNode* OpDispatchBuilder::SHUFOpImpl(OpcodeArgs, size_t ElementSize, Shuffle >>= ShiftAmount; } } else { + if (ElementSize == 4) { + // We can shuffle optimally in a lot of cases. + // TODO: We can optimize more of these cases. + switch (Shuffle) { + case 0b01'00'01'00: + // Combining of low 64-bits. + // Dest[63:0] = Src1[63:0] + // Dest[127:64] = Src2[63:0] + return _VZip(DstSize, 8, Src1Node, Src2Node); + case 0b11'10'11'10: + // Combining of high 64-bits. + // Dest[63:0] = Src1[127:64] + // Dest[127:64] = Src2[127:64] + return _VZip2(DstSize, 8, Src1Node, Src2Node); + case 0b11'10'01'00: + // Mixing Low and high elements + // Dest[63:0] = Src1[63:0] + // Dest[127:64] = Src2[127:64] + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + case 0b01'00'11'10: + // Mixing Low and high elements, inverse of above + // Dest[63:0] = Src1[127:64] + // Dest[127:64] = Src2[63:0] + return _VExtr(DstSize, 1, Src2Node, Src1Node, 8); + case 0b10'00'10'00: + // Mixing even elements. + // Dest[31:0] = Src1[31:0] + // Dest[63:32] = Src1[95:64] + // Dest[95:64] = Src2[31:0] + // Dest[127:96] = Src2[95:64] + return _VUnZip(DstSize, ElementSize, Src1Node, Src2Node); + case 0b11'01'11'01: + // Mixing odd elements. + // Dest[31:0] = Src1[63:32] + // Dest[63:32] = Src1[127:96] + // Dest[95:64] = Src2[63:32] + // Dest[127:96] = Src2[127:96] + return _VUnZip2(DstSize, ElementSize, Src1Node, Src2Node); + case 0b11'10'00'00: + case 0b11'10'01'01: + case 0b11'10'10'10: + case 0b11'10'11'11: { + // Bottom elements duplicated, Top 64-bits inserted + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + return _VZip2(DstSize, 8, DupSrc1, Src2Node); + } + case 0b01'00'00'00: + case 0b01'00'01'01: + case 0b01'00'10'10: + case 0b01'00'11'11: { + // Bottom elements duplicated, Bottom 64-bits inserted + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + return _VZip(DstSize, 8, DupSrc1, Src2Node); + } + case 0b00'00'01'00: + case 0b01'01'01'00: + case 0b10'10'01'00: + case 0b11'11'01'00: { + // Top elements duplicated, Bottom 64-bits inserted + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip(DstSize, 8, Src1Node, DupSrc2); + } + case 0b00'00'11'10: + case 0b01'01'11'10: + case 0b10'10'11'10: + case 0b11'11'11'10: { + // Top elements duplicated, Top 64-bits inserted + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip2(DstSize, 8, Src1Node, DupSrc2); + } + case 0b01'00'01'11: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Odd elements inverted, Low 64-bits inserted + Src1Node = _VInsElement(DstSize, 4, 0, 3, Src1Node, Src1Node); + return _VZip(DstSize, 8, Src1Node, Src2Node); + } + case 0b11'10'01'11: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Odd elements inverted, Top 64-bits inserted + Src1Node = _VInsElement(DstSize, 4, 0, 3, Src1Node, Src1Node); + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + } + case 0b01'00'00'01: { + // Lower 32-bit elements inverted, low 64-bits inserted + Src1Node = _VRev64(DstSize, 4, Src1Node); + return _VZip(DstSize, 8, Src1Node, Src2Node); + } + case 0b11'10'00'01: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Lower 32-bit elements inverted, Top 64-bits inserted + Src1Node = _VRev64(DstSize, 4, Src1Node); + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + } + case 0b00'00'00'00: + case 0b00'00'01'01: + case 0b00'00'10'10: + case 0b00'00'11'11: + case 0b01'01'00'00: + case 0b01'01'01'01: + case 0b01'01'10'10: + case 0b01'01'11'11: + case 0b10'10'00'00: + case 0b10'10'01'01: + case 0b10'10'10'10: + case 0b10'10'11'11: + case 0b11'11'00'00: + case 0b11'11'01'01: + case 0b11'11'10'10: + case 0b11'11'11'11: + { + // Duplicate element in upper and lower across each 64-bit segment. + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip(DstSize, 8, DupSrc1, DupSrc2); + } + default: + // Intentional doing nothing. + // Uncomment if you want to see remaining fallthrough in the output logs. + //LogMan::Msg::DFmt("shufps: 0x{:x}", Shuffle); + break; + } + } + for (uint8_t Element = 0; Element < NumElements; ++Element) { const auto SrcIndex = Shuffle & SelectionMask; Dest = _VInsElement(DstSize, ElementSize, Element, SrcIndex, Dest, Srcs[Element]); diff --git a/unittests/ASM/Secondary/shufps_optimization.asm b/unittests/ASM/Secondary/shufps_optimization.asm new file mode 100644 index 000000000..9bd622772 --- /dev/null +++ b/unittests/ASM/Secondary/shufps_optimization.asm @@ -0,0 +1,70 @@ +%ifdef CONFIG +{ + "RegData": { + "XMM0": ["0x4054c664c2f837b5", "0x4044836d86ec17ec"], + "XMM1": ["0x402a1e1c58255b03", "0x4035fe425aee6320"], + "XMM2": ["0x401568e0c9d9d346", "0x40154b7d41743e96"], + "XMM3": ["0x40154b7d41743e96", "0x403d075a31a4bdba"], + "XMM4": ["0xbd66277c31a4bdba", "0x4ea4a8c17ebaf102"], + "XMM5": ["0x4056d74040334ec1", "0x40497b13404439b5"], + "XMM6": ["0x404439b5404439b5", "0x4037f9ca18bd6627"], + "XMM7": ["0x4037f9ca4037f9ca", "0x403839b866e43aa8"], + "XMM8": ["0x403839b8403839b8", "0x4058bc1f212d7732"], + "XMM9": ["0x4058bc1f212d7732", "0xa10e0221a10e0221"], + "XMM10": ["0x4058defb00bcbe62", "0x9eecbfb19eecbfb1"], + "XMM11": ["0x40503e3c4052997f", "0x40395a6bf8769ec3"], + "XMM12": ["0x40419d2240395a6b", "0x40177e28240b7803"], + "XMM13": ["0x240b780340177e28", "0x404a03c74fb549f9"], + "XMM14": ["0x9f16b11c40408402", "0x404d31595feda661"], + "XMM15": ["0x5feda6615feda661", "0x7aa25d8d7aa25d8d"] + } +} +%endif + +movaps xmm0, [rel .data + 16 * 0] +movaps xmm1, [rel .data + 16 * 1] + +movaps xmm2, [rel .data + 16 * 2] +movaps xmm3, [rel .data + 16 * 3] + +movaps xmm4, [rel .data + 16 * 4] +movaps xmm5, [rel .data + 16 * 5] + +movaps xmm6, [rel .data + 16 * 6] +movaps xmm7, [rel .data + 16 * 7] + +movaps xmm8, [rel .data + 16 * 8] +movaps xmm9, [rel .data + 16 * 9] + +movaps xmm10, [rel .data + 16 * 10] +movaps xmm11, [rel .data + 16 * 11] + +movaps xmm12, [rel .data + 16 * 12] +movaps xmm13, [rel .data + 16 * 13] + +movaps xmm14, [rel .data + 16 * 14] +movaps xmm15, [rel .data + 16 * 15] + +shufps xmm0, xmm1, 01000100b +shufps xmm1, xmm2, 11101110b +shufps xmm2, xmm3, 11100100b +shufps xmm3, xmm4, 01001110b +shufps xmm4, xmm5, 10001000b +shufps xmm5, xmm6, 11011101b +shufps xmm6, xmm7, 11100101b +shufps xmm7, xmm8, 11101111b +shufps xmm8, xmm9, 01001111b +shufps xmm9, xmm10, 00000100b +shufps xmm10, xmm11, 00001110b +shufps xmm11, xmm12, 11100111b +shufps xmm12, xmm13, 01000111b +shufps xmm13, xmm14, 11100001b +shufps xmm14, xmm15, 01000001b +shufps xmm15, [rel .data + 16 * 16], 0 + +hlt + +align 16 +; 512bytes of random data +.data: +dq 83.0999,69.50512,41.02678,13.05881,5.35242,21.9932,9.67383,5.32372,29.02872,66.50151,19.30764,91.3633,40.45086,50.96153,32.64489,23.97574,90.64316,24.22547,98.9394,91.21715,90.80143,99.48407,64.97245,74.39838,35.22761,25.35321,5.8732,90.19956,33.03133,52.02952,58.38554,10.17531,47.84703,84.04831,90.02965,65.81329,96.27991,6.64479,25.58971,95.00694,88.1929,37.16964,49.52602,10.27223,77.70605,20.21439,9.8056,41.29389,15.4071,57.54286,9.61117,55.54302,52.90745,4.88086,72.52882,3.0201,56.55091,71.22749,61.84736,88.74295,47.72641,24.17404,33.70564,96.71303 diff --git a/unittests/InstructionCountCI/Secondary.json b/unittests/InstructionCountCI/Secondary.json index abd7c5990..79e9c3040 100644 --- a/unittests/InstructionCountCI/Secondary.json +++ b/unittests/InstructionCountCI/Secondary.json @@ -3611,35 +3611,523 @@ "uxth x4, w20" ] }, - "shufps xmm0, xmm1, 0": { - "ExpectedInstructionCount": 8, + "shufps xmm0, xmm1, 01000100b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[63:0]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "zip1 v16.2d, v16.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101110b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[127:64]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "zip2 v16.2d, v16.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100100b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "mov v16.d[1], v17.d[1]" + ] + }, + "shufps xmm0, xmm1, 01001110b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "ext v16.16b, v16.16b, v17.16b, #8" + ] + }, + "shufps xmm0, xmm1, 00000000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00000101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00001010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00001111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01010000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01010101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01011010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01011111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10100000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10100101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10101010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10101111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11110000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11110101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11111010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11100000b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100101b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101010b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101111b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01000000b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01000101b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01001010b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01001111b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 00000100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[0]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01010100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[1]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 10100100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[2]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 11110100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[3]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 00001110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[0]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01011110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[1]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 10101110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[2]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 11111110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[3]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01000111b": { + "ExpectedInstructionCount": 4, "Optimal": "No", - "Comment": "0x0f 0xc6", + "Comment": [ + "odd elements inverted, Low 64-bits inserted", + "SRA quirks with RA fail to understand that v16 is dead", + "Could InsElement directly in to v16 but it does two moves instead", + "0x0f 0xc6" + ], "ExpectedArm64ASM": [ "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[0]", + "mov v0.s[0], v16.s[3]", + "mov v2.16b, v0.16b", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100111b": { + "ExpectedInstructionCount": 6, + "Optimal": "No", + "Comment": [ + "odd elements inverted, Top 64-bits inserted", + "SRA quirks with RA fail to understand that v16 is dead", + "Could InsElement directly in to v16 but it does two moves instead", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "mov v0.16b, v16.16b", + "mov v0.s[0], v16.s[3]", "mov v2.16b, v0.16b", - "mov v2.s[1], v16.s[0]", - "mov v2.s[2], v17.s[0]", "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[0]", + "mov v0.d[1], v17.d[1]", "mov v16.16b, v0.16b" ] }, + "shufps xmm0, xmm1, 11100001b": { + "ExpectedInstructionCount": 4, + "Optimal": "Yes", + "Comment": [ + "Lower 32-bit elements inverted, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "rev64 v2.4s, v16.4s", + "mov v0.16b, v2.16b", + "mov v0.d[1], v17.d[1]", + "mov v16.16b, v0.16b" + ] + }, + "shufps xmm0, xmm1, 01000001b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Lower 32-bit elements inverted, Low 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "rev64 v2.4s, v16.4s", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11111111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, "shufps xmm0, [rax], 0": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 4, "Optimal": "No", "Comment": "0x0f 0xc6", "ExpectedArm64ASM": [ "ldr q2, [x4]", - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[0]", - "mov v3.16b, v0.16b", - "mov v3.s[1], v16.s[0]", - "mov v3.s[2], v2.s[0]", - "mov v0.16b, v3.16b", - "mov v0.s[3], v2.s[0]", - "mov v16.16b, v0.16b" + "dup v3.4s, v16.s[0]", + "dup v2.4s, v2.s[0]", + "zip1 v16.2d, v3.2d, v2.2d" ] }, "shufps xmm0, xmm1, 1": { @@ -3673,35 +4161,15 @@ "mov v16.16b, v0.16b" ] }, - "shufps xmm0, xmm1, 0xFF": { - "ExpectedInstructionCount": 8, - "Optimal": "No", - "Comment": "0x0f 0xc6", - "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[3]", - "mov v2.16b, v0.16b", - "mov v2.s[1], v16.s[3]", - "mov v2.s[2], v17.s[3]", - "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", - "mov v16.16b, v0.16b" - ] - }, "shufps xmm0, [rax], 0xFF": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 4, "Optimal": "No", "Comment": "0x0f 0xc6", "ExpectedArm64ASM": [ "ldr q2, [x4]", - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[3]", - "mov v3.16b, v0.16b", - "mov v3.s[1], v16.s[3]", - "mov v3.s[2], v2.s[3]", - "mov v0.16b, v3.16b", - "mov v0.s[3], v2.s[3]", - "mov v16.16b, v0.16b" + "dup v3.4s, v16.s[3]", + "dup v2.4s, v2.s[3]", + "zip1 v16.2d, v3.2d, v2.2d" ] }, "bswap eax": { diff --git a/unittests/InstructionCountCI/VEX_map1.json b/unittests/InstructionCountCI/VEX_map1.json index fc71252e9..421701861 100644 --- a/unittests/InstructionCountCI/VEX_map1.json +++ b/unittests/InstructionCountCI/VEX_map1.json @@ -3145,7 +3145,7 @@ ] }, "vshufps xmm0, xmm1, xmm2, 00b": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 7, "Optimal": "No", "Comment": [ "Map 1 0b00 0xC6 128-bit" @@ -3153,14 +3153,9 @@ "ExpectedArm64ASM": [ "mov z2.d, p7/m, z17.d", "mov z3.d, p7/m, z18.d", - "mov v0.16b, v2.16b", - "mov v0.s[0], v2.s[0]", - "mov v4.16b, v0.16b", - "mov v0.16b, v4.16b", - "mov v0.s[1], v2.s[0]", - "mov v2.16b, v0.16b", - "mov v2.s[2], v3.s[0]", - "mov v2.s[3], v3.s[0]", + "dup v2.4s, v2.s[0]", + "dup v3.4s, v3.s[0]", + "zip1 v2.2d, v2.2d, v3.2d", "mov v2.16b, v2.16b", "mov z16.d, p7/m, z2.d" ]