From c5d147322f81dfa474166829c0131cebcda62c76 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 24 Aug 2023 14:17:42 -0700 Subject: [PATCH 1/4] HostFeatures: Adds support for FCMA --- FEXCore/Source/Interface/Config/Config.json.in | 7 +++++-- FEXCore/Source/Interface/Core/HostFeatures.cpp | 11 +++++++++++ FEXCore/include/FEXCore/Core/HostFeatures.h | 1 + Scripts/InstructionCountParser.py | 2 ++ Source/Tools/CodeSizeValidation/Main.cpp | 7 +++++++ unittests/InstructionCountCI/Secondary_OpSize.json | 3 ++- unittests/InstructionCountCI/Secondary_REPNE.json | 3 ++- unittests/InstructionCountCI/VEX_map1.json | 4 +++- 8 files changed, 33 insertions(+), 5 deletions(-) diff --git a/FEXCore/Source/Interface/Config/Config.json.in b/FEXCore/Source/Interface/Config/Config.json.in index 9080a3c81..a15977031 100644 --- a/FEXCore/Source/Interface/Config/Config.json.in +++ b/FEXCore/Source/Interface/Config/Config.json.in @@ -74,7 +74,9 @@ "ENABLECLZERO": "enableclzero", "DISABLECLZERO": "disableclzero", "ENABLEATOMICS": "enableatomics", - "DISABLEATOMICS": "disableatomics" + "DISABLEATOMICS": "disableatomics", + "ENABLEFCMA": "enablefcma", + "DISABLEFCMA": "disablefcma" }, "Desc": [ "Allows controlling of the CPU features in the JIT.", @@ -88,7 +90,8 @@ "\t{enable,disable}pmull128: Will force enable or disable pmull128 even if the host doesn't support it", "\t{enable,disable}rng: Will force enable or disable rng even if the host doesn't support it", "\t{enable,disable}clzero: Will force enable or disable clzero even if the host doesn't support it", - "\t{enable,disable}atomics: Will force enable or disable ARMv8.1 LSE atomics even if the host doesn't support it" + "\t{enable,disable}atomics: Will force enable or disable ARMv8.1 LSE atomics even if the host doesn't support it", + "\t{enable,disable}fcma: Will force enable or disable fcma even if the host doesn't support it" ] } }, diff --git a/FEXCore/Source/Interface/Core/HostFeatures.cpp b/FEXCore/Source/Interface/Core/HostFeatures.cpp index dbc1a9c18..2a900be8d 100644 --- a/FEXCore/Source/Interface/Core/HostFeatures.cpp +++ b/FEXCore/Source/Interface/Core/HostFeatures.cpp @@ -96,6 +96,10 @@ static void OverrideFeatures(HostFeatures *Features) { const bool EnableAtomics = HostFeatures() & FEXCore::Config::HostFeatures::ENABLEATOMICS; LogMan::Throw::AFmt(!(DisableAtomics && EnableAtomics), "Disabling and Enabling CPU features are mutually exclusive"); + const bool DisableFCMA = HostFeatures() & FEXCore::Config::HostFeatures::DISABLEFCMA; + const bool EnableFCMA = HostFeatures() & FEXCore::Config::HostFeatures::ENABLEFCMA; + LogMan::Throw::AFmt(!(DisableFCMA && EnableFCMA), "Disabling and Enabling CPU features are mutually exclusive"); + if (EnableAVX) { Features->SupportsAVX = true; } @@ -156,6 +160,12 @@ static void OverrideFeatures(HostFeatures *Features) { else if (DisableAtomics) { Features->SupportsAtomics = false; } + if (EnableFCMA) { + Features->SupportsFCMA = true; + } + else if (DisableFCMA) { + Features->SupportsFCMA = false; + } } HostFeatures::HostFeatures() { @@ -181,6 +191,7 @@ HostFeatures::HostFeatures() { SupportsTSOImm9 = Features.Has(vixl::CPUFeatures::Feature::kRCpcImm); SupportsPMULL_128Bit = Features.Has(vixl::CPUFeatures::Feature::kPmull1Q); SupportsCSSC = Features.Has(vixl::CPUFeatures::Feature::kCSSC); + SupportsFCMA = Features.Has(vixl::CPUFeatures::Feature::kFcma); Supports3DNow = true; SupportsSSE4A = true; diff --git a/FEXCore/include/FEXCore/Core/HostFeatures.h b/FEXCore/include/FEXCore/Core/HostFeatures.h index 0be8de2de..9918470fb 100644 --- a/FEXCore/include/FEXCore/Core/HostFeatures.h +++ b/FEXCore/include/FEXCore/Core/HostFeatures.h @@ -31,6 +31,7 @@ class HostFeatures final { bool SupportsCLWB{}; bool SupportsPMULL_128Bit{}; bool SupportsCSSC{}; + bool SupportsFCMA{}; // Float exception behaviour bool SupportsFlushInputsToZero{}; diff --git a/Scripts/InstructionCountParser.py b/Scripts/InstructionCountParser.py index 0a8fb5fff..77cf74b06 100755 --- a/Scripts/InstructionCountParser.py +++ b/Scripts/InstructionCountParser.py @@ -46,12 +46,14 @@ class HostFeatures(Flag) : FEATURE_SVE256 = (1 << 1) FEATURE_CLZERO = (1 << 2) FEATURE_RNG = (1 << 3) + FEATURE_FCMA = (1 << 4) HostFeaturesLookup = { "SVE128" : HostFeatures.FEATURE_SVE128, "SVE256" : HostFeatures.FEATURE_SVE256, "CLZERO" : HostFeatures.FEATURE_CLZERO, "RNG" : HostFeatures.FEATURE_RNG, + "FCMA" : HostFeatures.FEATURE_FCMA, } def GetHostFeatures(data): diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 7c13d768b..e0855c6c9 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -384,6 +384,7 @@ int main(int argc, char **argv, char **const envp) { FEATURE_SVE256 = (1U << 1), FEATURE_CLZERO = (1U << 2), FEATURE_RNG = (1U << 3), + FEATURE_FCMA = (1U << 4), }; uint64_t SVEWidth = 0; @@ -402,6 +403,9 @@ int main(int argc, char **argv, char **const envp) { if (TestHeaderData->EnabledHostFeatures & FEATURE_RNG) { HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLERNG); } + if (TestHeaderData->EnabledHostFeatures & FEATURE_FCMA) { + HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLEFCMA); + } // Always enable ARMv8.1 LSE atomics. HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLEATOMICS); @@ -418,6 +422,9 @@ int main(int argc, char **argv, char **const envp) { if (TestHeaderData->DisabledHostFeatures & FEATURE_RNG) { HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::DISABLERNG); } + if (TestHeaderData->DisabledHostFeatures & FEATURE_FCMA) { + HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::DISABLEFCMA); + } FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_HOSTFEATURES, fextl::fmt::format("{}", HostFeatureControl)); FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_FORCESVEWIDTH, fextl::fmt::format("{}", SVEWidth)); diff --git a/unittests/InstructionCountCI/Secondary_OpSize.json b/unittests/InstructionCountCI/Secondary_OpSize.json index d76e27374..a4a48c825 100644 --- a/unittests/InstructionCountCI/Secondary_OpSize.json +++ b/unittests/InstructionCountCI/Secondary_OpSize.json @@ -4,7 +4,8 @@ "EnabledHostFeatures": [], "DisabledHostFeatures": [ "SVE128", - "SVE256" + "SVE256", + "FCMA" ] }, "Instructions": { diff --git a/unittests/InstructionCountCI/Secondary_REPNE.json b/unittests/InstructionCountCI/Secondary_REPNE.json index 976de8b3b..b9225306c 100644 --- a/unittests/InstructionCountCI/Secondary_REPNE.json +++ b/unittests/InstructionCountCI/Secondary_REPNE.json @@ -4,7 +4,8 @@ "EnabledHostFeatures": [], "DisabledHostFeatures": [ "SVE128", - "SVE256" + "SVE256", + "FCMA" ] }, "Instructions": { diff --git a/unittests/InstructionCountCI/VEX_map1.json b/unittests/InstructionCountCI/VEX_map1.json index 5fd5ba590..033c99690 100644 --- a/unittests/InstructionCountCI/VEX_map1.json +++ b/unittests/InstructionCountCI/VEX_map1.json @@ -5,7 +5,9 @@ "SVE128", "SVE256" ], - "DisabledHostFeatures": [] + "DisabledHostFeatures": [ + "FCMA" + ] }, "Instructions": { "vmovups xmm0, [rax]": { From ba01eac4673bba1cd28e83346a54239e14539e8c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 24 Aug 2023 14:18:33 -0700 Subject: [PATCH 2/4] IR: Adds support for ARM's FCMA FCADD instruction --- .../Core/Interpreter/InterpreterDefines.h | 11 +++++ .../Core/Interpreter/InterpreterOps.cpp | 1 + .../Core/Interpreter/InterpreterOps.h | 1 + .../Interface/Core/Interpreter/VectorOps.cpp | 38 ++++++++++++++++ .../Source/Interface/Core/JIT/Arm64/JIT.cpp | 1 + .../Interface/Core/JIT/Arm64/JITClass.h | 1 + .../Interface/Core/JIT/Arm64/VectorOps.cpp | 44 +++++++++++++++++++ FEXCore/Source/Interface/IR/IR.json | 4 ++ 8 files changed, 101 insertions(+) diff --git a/FEXCore/Source/Interface/Core/Interpreter/InterpreterDefines.h b/FEXCore/Source/Interface/Core/Interpreter/InterpreterDefines.h index 63da19906..1b42c769d 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/InterpreterDefines.h +++ b/FEXCore/Source/Interface/Core/Interpreter/InterpreterDefines.h @@ -65,6 +65,17 @@ } \ break; \ } +#define DO_VECTOR_FCADD_PAIR_OP(size, type, func) \ + case size: { \ + auto *Dst_d = reinterpret_cast(std::data(Tmp)); \ + auto *Src1_d = reinterpret_cast(Src1); \ + auto *Src2_d = reinterpret_cast(Src2); \ + for (uint8_t i = 0; i < Elements; i += 2) { \ + func(&Dst_d[i], &Src1_d[i], &Src2_d[i]); \ + } \ + break; \ + } + #define DO_VECTOR_SCALAR_OP(size, type, func) \ case size: { \ auto *Dst_d = reinterpret_cast(std::data(Tmp)); \ diff --git a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp index ad24d04ed..21c43accd 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp +++ b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp @@ -286,6 +286,7 @@ constexpr OpHandlerArray InterpreterOpHandlers = [] { REGISTER_OP(VREV64, VRev64); REGISTER_OP(VPCMPESTRX, VPCMPESTRX); REGISTER_OP(VPCMPISTRX, VPCMPISTRX); + REGISTER_OP(VFCADD, VFCADD); // Encryption ops REGISTER_OP(VAESIMC, AESImc); diff --git a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h index 53d9dfabb..85e245278 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h +++ b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h @@ -314,6 +314,7 @@ namespace FEXCore::CPU { DEF_OP(VRev64); DEF_OP(VPCMPESTRX); DEF_OP(VPCMPISTRX); + DEF_OP(VFCADD); ///< Encryption ops DEF_OP(AESImc); diff --git a/FEXCore/Source/Interface/Core/Interpreter/VectorOps.cpp b/FEXCore/Source/Interface/Core/Interpreter/VectorOps.cpp index b49c273c0..8c27f8ea0 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/VectorOps.cpp +++ b/FEXCore/Source/Interface/Core/Interpreter/VectorOps.cpp @@ -2561,6 +2561,44 @@ DEF_OP(VPCMPISTRX) { memcpy(GDP, &Result, sizeof(Result)); } +DEF_OP(VFCADD) { + const auto Op = IROp->C(); + const uint8_t OpSize = IROp->Size; + + const auto *Src1 = GetSrc(Data->SSAData, Op->Vector1); + const auto *Src2 = GetSrc(Data->SSAData, Op->Vector2); + const auto Rotate = Op->Rotate; + LOGMAN_THROW_A_FMT(Rotate == 90 || Rotate == 270, "Invalid rotate!"); + + TempVectorDataArray Tmp; + + const uint8_t ElementSize = Op->Header.ElementSize; + const uint8_t Elements = OpSize / ElementSize; + + const auto Func = [Rotate](auto dst, auto src1, auto src2) { + auto Element1 = src2[1]; + auto Element3 = src2[0]; + if (Rotate == 90) { + Element1 = -Element1; + } + else { + Element3 = -Element3; + } + dst[0] = src1[0] + Element1; + dst[1] = src1[1] + Element3; + }; + + switch (ElementSize) { + //DO_VECTOR_FCADD_PAIR_OP(2, float16_t, Func) + DO_VECTOR_FCADD_PAIR_OP(4, float, Func) + DO_VECTOR_FCADD_PAIR_OP(8, double, Func) + default: + LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize); + break; + } + memcpy(GDP, Tmp.data(), OpSize); +} + #undef DEF_OP } // namespace FEXCore::CPU diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index b195bb5af..9e0a0edde 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -1104,6 +1104,7 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry, REGISTER_OP(VTBL1, VTBL1); REGISTER_OP(VREV32, VRev32); REGISTER_OP(VREV64, VRev64); + REGISTER_OP(VFCADD, VFCADD); #undef REGISTER_OP default: diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h b/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h index 19317adce..29e242d7b 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h @@ -470,6 +470,7 @@ private: DEF_OP(VTBL1); DEF_OP(VRev32); DEF_OP(VRev64); + DEF_OP(VFCADD); ///< Encryption ops DEF_OP(AESImc); diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp index 39b256a78..af4f40b1b 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp @@ -3825,6 +3825,50 @@ DEF_OP(VRev64) { } } +DEF_OP(VFCADD) { + const auto Op = IROp->C(); + const auto OpSize = IROp->Size; + + const auto ElementSize = Op->Header.ElementSize; + const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE; + + const auto Dst = GetVReg(Node); + const auto Vector1 = GetVReg(Op->Vector1.ID()); + const auto Vector2 = GetVReg(Op->Vector2.ID()); + + LOGMAN_THROW_AA_FMT(ElementSize == 2 || ElementSize == 4 || ElementSize == 8, "Invalid size"); + LOGMAN_THROW_A_FMT(Op->Rotate == 90 || Op->Rotate == 270, "Invalidate Rotate"); + const auto SubRegSize = + ElementSize == 2 ? ARMEmitter::SubRegSize::i16Bit : + ElementSize == 4 ? ARMEmitter::SubRegSize::i32Bit : ARMEmitter::SubRegSize::i64Bit; + const auto Rotate = + Op->Rotate == 90 ? ARMEmitter::Rotation::ROTATE_90 : ARMEmitter::Rotation::ROTATE_270; + + if (HostSupportsSVE256 && Is256Bit) { + const auto Mask = PRED_TMP_32B.Merging(); + + if (Dst == Vector1) { + // Trivial case where we already have first vector in the destination + // register. We can just do the operation in place. + fcadd(SubRegSize, Dst.Z(), Mask, Vector1.Z(), Vector2.Z(), Rotate); + } + else { + // SVE FCADD is a destructive operation, so we need + // a temporary for performing operations. + movprfx(VTMP1.Z(), Vector1.Z()); + fcadd(SubRegSize, VTMP1.Z(), Mask, VTMP1.Z(), Vector2.Z(), Rotate); + mov(Dst.Z(), VTMP1.Z()); + } + } else { + if (OpSize == 8) { + fcadd(SubRegSize, Dst.D(), Vector1.D(), Vector2.D(), Rotate); + } + else { + fcadd(SubRegSize, Dst.Q(), Vector1.Q(), Vector2.Q(), Rotate); + } + } +} + #undef DEF_OP } diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index eddc13b48..154278404 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -1558,6 +1558,10 @@ "course of creating the intermediate result" ], "DestSize": "4" + }, + "FPR = VFCADD u8:#RegisterSize, u8:#ElementSize, FPR:$Vector1, FPR:$Vector2, u16:$Rotate": { + "DestSize": "RegisterSize", + "NumElements": "RegisterSize / ElementSize" } }, "Conv": { From a1210f892a87b633438897855dbc1c1ec2364560 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 24 Aug 2023 14:18:57 -0700 Subject: [PATCH 3/4] OpcodeDispatcher: Optimize addsubp{s,d} using fcadd This extension was added with seemingly Cortex-A710 and turns this instruction in to two instructions which is quite good. Needs #2994 merged first. Huge thanks to @dougallj for the optimization idea! --- .../Interface/Core/OpcodeDispatcher/Vector.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index c2f09c010..ef7df8614 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -2962,9 +2962,21 @@ OrderedNode* OpDispatchBuilder::ADDSUBPOpImpl(OpcodeArgs, size_t ElementSize, OrderedNode *Src1, OrderedNode *Src2) { const auto Size = GetSrcSize(Op); - auto ConstantEOR = LoadAndCacheNamedVectorConstant(Size, ElementSize == 4 ? NAMED_VECTOR_PADDSUBPS_INVERT : NAMED_VECTOR_PADDSUBPD_INVERT); - auto InvertedSource = _VXor(Size, ElementSize, Src2, ConstantEOR); - return _VFAdd(Size, ElementSize, Src1, InvertedSource); + if (CTX->HostFeatures.SupportsFCMA) { + if (ElementSize == 4) { + auto Swizzle = _VRev64(Size, 4, Src2); + return _VFCADD(Size, ElementSize, Src1, Swizzle, 90); + } + else { + auto Swizzle = _VExtr(Size, 1, Src2, Src2, 8); + return _VFCADD(Size, ElementSize, Src1, Swizzle, 90); + } + } + else { + auto ConstantEOR = LoadAndCacheNamedVectorConstant(Size, ElementSize == 4 ? NAMED_VECTOR_PADDSUBPS_INVERT : NAMED_VECTOR_PADDSUBPD_INVERT); + auto InvertedSource = _VXor(Size, ElementSize, Src2, ConstantEOR); + return _VFAdd(Size, ElementSize, Src1, InvertedSource); + } } template From 4e7adeec855cdde724472f1593412d1e31caca5d Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 24 Aug 2023 14:21:21 -0700 Subject: [PATCH 4/4] InstCountCI: Adds new files for FCMA --- .../Secondary_OpSize_FCMA.json | 23 ++++++ .../Secondary_REPNE_FCMA.json | 23 ++++++ .../InstructionCountCI/VEX_map1_FCMA.json | 71 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 unittests/InstructionCountCI/Secondary_OpSize_FCMA.json create mode 100644 unittests/InstructionCountCI/Secondary_REPNE_FCMA.json create mode 100644 unittests/InstructionCountCI/VEX_map1_FCMA.json diff --git a/unittests/InstructionCountCI/Secondary_OpSize_FCMA.json b/unittests/InstructionCountCI/Secondary_OpSize_FCMA.json new file mode 100644 index 000000000..daa99152b --- /dev/null +++ b/unittests/InstructionCountCI/Secondary_OpSize_FCMA.json @@ -0,0 +1,23 @@ +{ + "Features": { + "Bitness": 64, + "EnabledHostFeatures": [ + "FCMA" + ], + "DisabledHostFeatures": [ + "SVE128", + "SVE256" + ] + }, + "Instructions": { + "addsubpd xmm0, xmm1": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": "0x66 0x0f 0xd0", + "ExpectedArm64ASM": [ + "ext v4.16b, v17.16b, v17.16b, #8", + "fcadd v16.2d, v16.2d, v4.2d, #90" + ] + } + } +} diff --git a/unittests/InstructionCountCI/Secondary_REPNE_FCMA.json b/unittests/InstructionCountCI/Secondary_REPNE_FCMA.json new file mode 100644 index 000000000..8913dbbfa --- /dev/null +++ b/unittests/InstructionCountCI/Secondary_REPNE_FCMA.json @@ -0,0 +1,23 @@ +{ + "Features": { + "Bitness": 64, + "EnabledHostFeatures": [ + "FCMA" + ], + "DisabledHostFeatures": [ + "SVE128", + "SVE256" + ] + }, + "Instructions": { + "addsubps xmm0, xmm1": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": "0xf2 0x0f 0xd0", + "ExpectedArm64ASM": [ + "rev64 v4.4s, v17.4s", + "fcadd v16.4s, v16.4s, v4.4s, #90" + ] + } + } +} diff --git a/unittests/InstructionCountCI/VEX_map1_FCMA.json b/unittests/InstructionCountCI/VEX_map1_FCMA.json new file mode 100644 index 000000000..5ba4d6d49 --- /dev/null +++ b/unittests/InstructionCountCI/VEX_map1_FCMA.json @@ -0,0 +1,71 @@ +{ + "Features": { + "Bitness": 64, + "EnabledHostFeatures": [ + "SVE128", + "SVE256", + "FCMA" + ], + "DisabledHostFeatures": [] + }, + "Instructions": { + "vaddsubpd xmm0, xmm1, xmm2": { + "ExpectedInstructionCount": 6, + "Optimal": "No", + "Comment": [ + "Map 1 0b01 0xd0 128-bit" + ], + "ExpectedArm64ASM": [ + "mov z4.d, p7/m, z17.d", + "mov z5.d, p7/m, z18.d", + "ext v5.16b, v5.16b, v5.16b, #8", + "fcadd v4.2d, v4.2d, v5.2d, #90", + "mov v4.16b, v4.16b", + "mov z16.d, p7/m, z4.d" + ] + }, + "vaddsubpd ymm0, ymm1, ymm2": { + "ExpectedInstructionCount": 5, + "Optimal": "No", + "Comment": [ + "Map 1 0b01 0xd0 256-bit" + ], + "ExpectedArm64ASM": [ + "mov z4.d, p7/m, z17.d", + "mov z5.d, p7/m, z18.d", + "ext z5.b, z5.b, z5.b, #8", + "fcadd z4.d, p7/m, z4.d, z5.d, #90", + "mov z16.d, p7/m, z4.d" + ] + }, + "vaddsubps xmm0, xmm1, xmm2": { + "ExpectedInstructionCount": 6, + "Optimal": "No", + "Comment": [ + "Map 1 0b11 0xd0 128-bit" + ], + "ExpectedArm64ASM": [ + "mov z4.d, p7/m, z17.d", + "mov z5.d, p7/m, z18.d", + "rev64 v5.4s, v5.4s", + "fcadd v4.4s, v4.4s, v5.4s, #90", + "mov v4.16b, v4.16b", + "mov z16.d, p7/m, z4.d" + ] + }, + "vaddsubps ymm0, ymm1, ymm2": { + "ExpectedInstructionCount": 5, + "Optimal": "No", + "Comment": [ + "Map 1 0b11 0xd0 256-bit" + ], + "ExpectedArm64ASM": [ + "mov z4.d, p7/m, z17.d", + "mov z5.d, p7/m, z18.d", + "revw z5.d, p7/m, z5.d", + "fcadd z4.s, p7/m, z4.s, z5.s, #90", + "mov z16.d, p7/m, z4.d" + ] + } + } +}