SPU Anlyzer: Verify bitset index

This commit is contained in:
Elad 2026-03-30 13:25:51 +03:00 committed by Ani
parent 1c37f64a58
commit 615f416af3
3 changed files with 37 additions and 21 deletions

View file

@ -6087,17 +6087,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
u32 ra = s_reg_max, rb = s_reg_max, rc = s_reg_max;
if (m_use_ra.test(pos / 4))
if (::at32(m_use_ra, pos / 4))
{
ra = op.ra;
}
if (m_use_rb.test(pos / 4))
if (::at32(m_use_rb, pos / 4))
{
rb = op.rb;
}
if (m_use_rc.test(pos / 4))
if (::at32(m_use_rc, pos / 4))
{
rc = op.rc;
}
@ -6361,11 +6361,11 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto& b = ::at32(m_bbs, reduced_loop->loop_pc);
const auto& b2 = ::at32(m_bbs, bpc);
if (!reduced_loop->loop_dicts.test(i))
if (!::at32(reduced_loop->loop_dicts, i))
{
if (b.reg_use[i] || (!b.reg_mod.test(i) && b2.reg_use[i]))
if (b.reg_use[i] || (!::at32(b.reg_mod, i) && b2.reg_use[i]))
{
if ((b.reg_use[i] && b.reg_mod.test(i)) || b2.reg_mod.test(i))
if ((b.reg_use[i] && ::at32(b.reg_mod, i)) || ::at32(b2.reg_mod, i))
{
reduced_loop->is_constant_expression = false;
reduced_loop->loop_writes.set(i);
@ -6598,7 +6598,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
for (u32 i = 0; i < reg->regs.size() && reduced_loop->active; i++)
{
if (reg->regs.test(i))
if (::at32(reg->regs, i))
{
if (0) if (i == op_rt || reg->modified == 0)
{
@ -6644,11 +6644,11 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
auto reg_org = reduced_loop->find_reg(i);
u32 reg_index = i;
if (reg_org && !cond_val_incr_before_cond && reg_org->modified == 0 && reg_org->regs.count() - 1u <= 1u && !reg_org->regs.test(i))
if (reg_org && !cond_val_incr_before_cond && reg_org->modified == 0 && reg_org->regs.count() - 1u <= 1u && !::at32(reg_org->regs, i))
{
for (u32 j = 0; j <= s_reg_127; j++)
{
if (reg_org->regs.test(j))
if (::at32(reg_org->regs, j))
{
if (const auto reg_found = reduced_loop->find_reg(j))
{
@ -7040,11 +7040,11 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto& b = ::at32(m_bbs, reduced_loop->loop_pc);
const auto& b2 = ::at32(m_bbs, bpc);
if (!reduced_loop->loop_dicts.test(i))
if (!::at32(reduced_loop->loop_dicts, i))
{
if (b.reg_use[i] || (!b.reg_mod.test(i) && b2.reg_use[i]))
if (b.reg_use[i] || (!::at32(b.reg_mod, i) && b2.reg_use[i]))
{
if ((b.reg_use[i] && b.reg_mod.test(i)) || b2.reg_mod.test(i))
if ((b.reg_use[i] && ::at32(b.reg_mod, i)) || ::at32(b2.reg_mod, i))
{
reduced_loop->is_constant_expression = false;
reduced_loop->loop_writes.set(i);
@ -8298,17 +8298,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
u32 ra = s_reg_max, rb = s_reg_max, rc = s_reg_max;
if (m_use_ra.test(pos / 4))
if (::at32(m_use_ra, pos / 4))
{
ra = op.ra;
}
if (m_use_rb.test(pos / 4))
if (::at32(m_use_rb, pos / 4))
{
rb = op.rb;
}
if (m_use_rc.test(pos / 4))
if (::at32(m_use_rc, pos / 4))
{
rc = op.rc;
}
@ -8575,7 +8575,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
for (u32 i = 0; i < s_reg_max; i++)
{
if (pattern.loop_writes.test(i))
if (::at32(pattern.loop_writes, i))
{
if (regs.size() != 1)
{
@ -8585,7 +8585,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
fmt::append(regs, " r%u-w", i);
}
if (pattern.loop_args.test(i))
if (::at32(pattern.loop_args, i))
{
if (regs.size() != 1)
{

View file

@ -180,7 +180,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
bool is_gpr_not_NaN_hint(u32 i) const noexcept
{
return block_wide_reg_store_elimination && bb->reg_maybe_float[i] && bb->reg_use[i] >= 3 && !bb->reg_mod[i];
return block_wide_reg_store_elimination && ::at32(bb->reg_maybe_float, i) && ::at32(bb->reg_use, i) >= 3 && !::at32(bb->reg_mod, i);
}
};
@ -2536,6 +2536,11 @@ public:
condition = m_ir->CreateAnd(cond_nans, condition);
prev_i = umax;
}
if (is_last)
{
break;
}
}
}

View file

@ -11,6 +11,17 @@
#include <string>
#include <deque>
// std::bitset
template <typename CT, typename T>
requires requires(std::remove_cvref_t<CT>& x, T&& y) { x.count(); x.test(y); x.flip(y); }
[[nodiscard]] constexpr bool at32(CT&& container, T&& index, std::source_location src_loc = std::source_location::current())
{
const usz csv = container.size();
if (csv <= std::forward<T>(index)) [[unlikely]]
fmt::raw_range_error(src_loc, format_object_simplified(index), csv);
return container[std::forward<T>(index)];
}
// Helper class
class spu_cache
{
@ -421,7 +432,7 @@ public:
return true;
}
return regs.count() == 1 && regs.test(reg_val);
return regs.count() == 1 && ::at32(regs, reg_val);
}
bool is_loop_dictator(u32 reg_val, bool test_predictable = false, bool should_predictable = true) const
@ -431,7 +442,7 @@ public:
return false;
}
if (regs.count() >= 1 && regs.test(reg_val))
if (regs.count() >= 1 && ::at32(regs, reg_val))
{
if (!test_predictable)
{
@ -490,7 +501,7 @@ public:
return false;
}
if (regs.count() - (regs.test(reg_val) ? 1 : 0))
if (regs.count() - (::at32(regs, reg_val) ? 1 : 0))
{
return false;
}