From 95c36221fa8aaa7e99d2aa9765f58fba45b6bb7e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 1 Sep 2021 14:04:05 +0300 Subject: [PATCH] LLVM DSL: reimplement ctlz, ctpop --- rpcs3/Emu/CPU/CPUTranslator.h | 115 +++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 003dd5c3a2..47393c43e1 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -2425,6 +2425,93 @@ struct llvm_shuffle2 } }; +template > +struct llvm_ctlz +{ + using type = T; + + llvm_expr_t a1; + + static_assert(llvm_value_t::is_sint || llvm_value_t::is_uint, "llvm_ctlz<>: invalid type"); + + static constexpr bool is_ok = llvm_value_t::is_sint || llvm_value_t::is_uint; + + llvm::Value* eval(llvm::IRBuilder<>* ir) const + { + llvm::Value* v = a1.eval(ir); + + if (llvm::isa(v)) + { + return llvm::ConstantFoldInstruction(ir->CreateIntrinsic(llvm::Intrinsic::ctlz, {v->getType()}, {v, ir->getFalse()}), llvm::DataLayout("")); + } + + return ir->CreateIntrinsic(llvm::Intrinsic::ctlz, {v->getType()}, {v, ir->getFalse()}); + } + + llvm_match_tuple match(llvm::Value*& value) const + { + llvm::Value* v1 = {}; + + if (auto i = llvm::dyn_cast_or_null(value); i && i->getIntrinsicID() == llvm::Intrinsic::ctlz) + { + v1 = i->getOperand(0); + + if (i->getOperand(2) == llvm::ConstantInt::getFalse(value->getContext())) + { + if (auto r1 = a1.match(v1); v1) + { + return r1; + } + } + } + + value = nullptr; + return {}; + } +}; + +template > +struct llvm_ctpop +{ + using type = T; + + llvm_expr_t a1; + + static_assert(llvm_value_t::is_sint || llvm_value_t::is_uint, "llvm_ctpop<>: invalid type"); + + static constexpr bool is_ok = llvm_value_t::is_sint || llvm_value_t::is_uint; + + llvm::Value* eval(llvm::IRBuilder<>* ir) const + { + llvm::Value* v = a1.eval(ir); + + if (llvm::isa(v)) + { + return llvm::ConstantFoldInstruction(ir->CreateUnaryIntrinsic(llvm::Intrinsic::ctpop, v), llvm::DataLayout("")); + } + + return ir->CreateUnaryIntrinsic(llvm::Intrinsic::ctpop, v); + } + + llvm_match_tuple match(llvm::Value*& value) const + { + llvm::Value* v1 = {}; + + if (auto i = llvm::dyn_cast_or_null(value); i && i->getIntrinsicID() == llvm::Intrinsic::ctpop) + { + v1 = i->getOperand(0); + + if (auto r1 = a1.match(v1); v1) + { + return r1; + } + } + + value = nullptr; + return {}; + } +}; + class cpu_translator { protected: @@ -2705,6 +2792,18 @@ public: return llvm_shuffle2{std::forward(v1), std::forward(v2), {static_cast(indices)...}}; } + template ::is_ok>> + static auto ctlz(T&& a) + { + return llvm_ctlz{std::forward(a)}; + } + + template ::is_ok>> + static auto ctpop(T&& a) + { + return llvm_ctpop{std::forward(a)}; + } + // Average: (a + b + 1) >> 1 template inline auto avg(T a, T b) @@ -2733,22 +2832,6 @@ public: return llvm::Intrinsic::getDeclaration(_module, id, {get_type()...}); } - template - auto ctlz(T a) - { - value_t result; - result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::ctlz), {a.eval(m_ir), m_ir->getFalse()}); - return result; - } - - template - auto ctpop(T a) - { - value_t result; - result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::ctpop), {a.eval(m_ir)}); - return result; - } - template auto sqrt(T a) {