diff options
| author | Wunkolo <Wunkolo@gmail.com> | 2023-02-05 17:55:09 -0800 |
|---|---|---|
| committer | Rick Gibbed <rick@gibbed.us> | 2023-05-29 14:57:09 -0500 |
| commit | 6ee2e3718f81748f3f2c6cae7287dffa7f87b14e (patch) | |
| tree | c97e3c635806c4f324a9e99c4d7299fd330d2810 /src | |
| parent | 121bf93cbe2c23fe0a47f1f43e3f050df46e976d (diff) | |
[x64] Add AVX512 optimizations for `OPCODE_VECTOR_COMPARE_UGT`(Integer)
AVX512 has native unsigned integer comparisons instructions, removing
the need to XOR the most-significant-bit with a constant in memory to
use the signed comparison instructions. These instructions only write to
a k-mask register though and need an additional call to `vpmovm2*` to
turn the mask-register into a vector-mask register.
As of Icelake:
`vpcmpu*` is all L3/T1
`vpmovm2d` is L1/T0.33
`vpmovm2{b,w}` is L3/T0.33
As of Zen4:
`vpcmpu*` is all L3/T0.50
`vpmovm2*` is all L1/T0.25
Diffstat (limited to 'src')
| -rw-r--r-- | src/xenia/cpu/backend/x64/x64_seq_vector.cc | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/xenia/cpu/backend/x64/x64_seq_vector.cc b/src/xenia/cpu/backend/x64/x64_seq_vector.cc index 75f162559..205adf2a4 100644 --- a/src/xenia/cpu/backend/x64/x64_seq_vector.cc +++ b/src/xenia/cpu/backend/x64/x64_seq_vector.cc @@ -409,6 +409,43 @@ struct VECTOR_COMPARE_UGT_V128 : Sequence<VECTOR_COMPARE_UGT_V128, I<OPCODE_VECTOR_COMPARE_UGT, V128Op, V128Op, V128Op>> { static void Emit(X64Emitter& e, const EmitArgType& i) { + if (e.IsFeatureEnabled(kX64EmitAVX512Ortho | kX64EmitAVX512BW | + kX64EmitAVX512DQ) && + (i.instr->flags != FLOAT32_TYPE)) { + Xmm src1 = e.xmm0; + if (i.src1.is_constant) { + e.LoadConstantXmm(src1, i.src1.constant()); + } else { + src1 = i.src1; + } + + Xmm src2 = e.xmm1; + if (i.src2.is_constant) { + e.LoadConstantXmm(src2, i.src2.constant()); + } else { + src2 = i.src2; + } + + switch (i.instr->flags) { + case INT8_TYPE: + e.vpcmpub(e.k1, src1, src2, 0x6); + e.vpmovm2b(i.dest, e.k1); + break; + case INT16_TYPE: + e.vpcmpuw(e.k1, src1, src2, 0x6); + e.vpmovm2w(i.dest, e.k1); + break; + case INT32_TYPE: + e.vpcmpud(e.k1, src1, src2, 0x6); + e.vpmovm2d(i.dest, e.k1); + break; + default: + assert_always(); + break; + } + return; + } + Xbyak::Address sign_addr = e.ptr[e.rax]; // dummy switch (i.instr->flags) { case INT8_TYPE: |
