1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-01-31 12:31:45 +01:00

SPU LLVM: add match_vr<> template

Returns reg value only if type is compatible, avoiding bitcast.
This commit is contained in:
Nekotekina 2019-04-24 20:09:58 +03:00
parent dd9bd1338b
commit 8754bbd444
2 changed files with 55 additions and 0 deletions

View File

@ -361,6 +361,24 @@ struct is_llvm_expr_of<T, Of, std::void_t<typename is_llvm_expr<T>::type, typena
template <typename T, typename... Types>
using llvm_common_t = std::enable_if_t<(is_llvm_expr_of<T, Types>::ok && ...), typename is_llvm_expr<T>::type>;
template <typename T, typename U = llvm_common_t<llvm_value_t<T>>>
struct llvm_match_t
{
using type = T;
llvm::Value* value = nullptr;
explicit operator bool() const
{
return value != nullptr;
}
llvm::Value* eval(llvm::IRBuilder<>* ir) const
{
return value;
}
};
template <typename T, bool ForceSigned = false>
struct llvm_const_int
{

View File

@ -2686,6 +2686,31 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
return {get_vr<T>(args)...};
}
template <typename T = u32[4], uint I>
llvm_match_t<T> match_vr(const bf_t<u32, I, 7>& index)
{
llvm_match_t<T> r;
if (m_block)
{
auto v = m_block->reg.at(index);
if (v && v->getType() == get_type<T>())
{
r.value = v;
return r;
}
}
return r;
}
template <typename T = u32[4], typename... Args>
std::tuple<std::conditional_t<false, Args, llvm_match_t<T>>...> match_vrs(const Args&... args)
{
return {match_vr<T>(args)...};
}
void set_reg_fixed(u32 index, llvm::Value* value, bool fixup = true)
{
llvm::StoreInst* dummy{};
@ -4962,6 +4987,18 @@ public:
void AND(spu_opcode_t op)
{
if (const auto [a, b] = match_vrs<u8[16]>(op.ra, op.rb); a && b)
{
set_vr(op.rt, a & b);
return;
}
if (const auto [a, b] = match_vrs<u16[8]>(op.ra, op.rb); a && b)
{
set_vr(op.rt, a & b);
return;
}
set_vr(op.rt, get_vr(op.ra) & get_vr(op.rb));
}