mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-07-09 17:25:18 -06:00
SPU LLVM: Calculate FREST fraction LUT using vperm2dlculate FREST fraction using vperm2d for AVX512 (#18931)
The `FREST` instruction uses a scalar lookup-table loop to calculate the mantissa. Given that it's only 32 elements, we can load it into two 512-bit vectors and treat them as the sources to the `vperm2d` shuffle instruction. This allows it to be calculated in parallel, improving its performance.
This commit is contained in:
parent
c7478d6dcc
commit
927e2492ef
@ -3670,6 +3670,23 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
value_t<u32[4]> vperm2d128From512(T1 a, T2 b, T3 c)
|
||||
{
|
||||
value_t<u32[4]> result;
|
||||
value_t<u32[16]> perm512;
|
||||
|
||||
const auto data0 = a.eval(m_ir);
|
||||
const auto index128 = b.eval(m_ir);
|
||||
const auto data1 = c.eval(m_ir);
|
||||
|
||||
const auto index512 = m_ir->CreateInsertVector(get_type<u32[16]>(), llvm::UndefValue::get(get_type<u32[16]>()), index128, m_ir->getInt64(0));
|
||||
perm512.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpermi2var_d_512), {data0, index512, data1});
|
||||
|
||||
result.value = m_ir->CreateExtractVector(get_type<u32[4]>(), perm512.value, m_ir->getInt64(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
value_t<u8[16]> gf2p8affineqb(T1 a, T2 b, u8 c)
|
||||
{
|
||||
|
||||
@ -7498,13 +7498,23 @@ public:
|
||||
const auto a_sign = (a & splat<u32[4]>(0x80000000));
|
||||
value_t<u32[4]> final_result = eval(splat<u32[4]>(0));
|
||||
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
if (m_use_avx512)
|
||||
{
|
||||
const auto eval_fraction = eval(extract(a_fraction, i));
|
||||
value_t<u32[16]> lo_lut;
|
||||
value_t<u32[16]> hi_lut;
|
||||
lo_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut, 16));
|
||||
hi_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut + 16, 16));
|
||||
|
||||
value_t<u32> r_fraction = load_const<u32>(m_spu_frest_fraction_lut, eval_fraction);
|
||||
|
||||
final_result = eval(insert(final_result, i, r_fraction));
|
||||
final_result = vperm2d128From512(lo_lut, a_fraction, hi_lut);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
const auto eval_fraction = eval(extract(a_fraction, i));
|
||||
value_t<u32> r_fraction = load_const<u32>(m_spu_frest_fraction_lut, eval_fraction);
|
||||
final_result = eval(insert(final_result, i, r_fraction));
|
||||
}
|
||||
}
|
||||
|
||||
//final_result = eval(select(final_result != (0), final_result, bitcast<u32[4]>(pshufb(splat<u8[16]>(0), bitcast<u8[16]>(final_result)))));
|
||||
@ -8551,13 +8561,23 @@ public:
|
||||
const auto a_sign = (a & splat<u32[4]>(0x80000000));
|
||||
value_t<u32[4]> b = eval(splat<u32[4]>(0));
|
||||
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
if (m_use_avx512)
|
||||
{
|
||||
const auto eval_fraction = eval(extract(a_fraction, i));
|
||||
value_t<u32[16]> lo_lut;
|
||||
value_t<u32[16]> hi_lut;
|
||||
lo_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut, 16));
|
||||
hi_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut + 16, 16));
|
||||
|
||||
value_t<u32> r_fraction = load_const<u32>(m_spu_frest_fraction_lut, eval_fraction);
|
||||
|
||||
b = eval(insert(b, i, r_fraction));
|
||||
b = vperm2d128From512(lo_lut, a_fraction, hi_lut);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
const auto eval_fraction = eval(extract(a_fraction, i));
|
||||
value_t<u32> r_fraction = load_const<u32>(m_spu_frest_fraction_lut, eval_fraction);
|
||||
b = eval(insert(b, i, r_fraction));
|
||||
}
|
||||
}
|
||||
|
||||
b = eval(b | fix_exponent | a_sign);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user