diff --git a/rpcs3/Emu/CPU/CPUTranslator.cpp b/rpcs3/Emu/CPU/CPUTranslator.cpp index 8466443a4c..7c9550ead5 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.cpp +++ b/rpcs3/Emu/CPU/CPUTranslator.cpp @@ -4,6 +4,9 @@ #include "util/v128.hpp" #include "util/simd.hpp" +#include "util/logs.hpp" + +LOG_CHANNEL(llvm_log, "LLVM"); llvm::LLVMContext g_llvm_ctx; @@ -369,25 +372,85 @@ llvm::Constant* cpu_translator::make_const_vector(v128 v, llvm::Type* t, u void cpu_translator::replace_intrinsics(llvm::Function& f) { - for (auto& bb : f) + for (llvm::BasicBlock& bb : f) { - for (auto bit = bb.begin(); bit != bb.end();) + std::set> names; + + using InstListType = llvm::BasicBlock::InstListType; + + std::function fix_funcs; + + fix_funcs = [&](InstListType::iterator inst_bit) { - if (auto ci = llvm::dyn_cast(&*bit)) + auto ci = llvm::dyn_cast(&*inst_bit); + + if (!ci) { - if (auto cf = ci->getCalledFunction()) + return std::next(inst_bit); + } + + const auto cf = ci->getCalledFunction(); + + if (!cf) + { + return std::next(inst_bit); + } + + std::string_view func_name{cf->getName().data(), cf->getName().size()}; + + const auto it = m_intrinsics.find(func_name); + + if (it == m_intrinsics.end()) + { + return std::next(inst_bit); + } + + if (!names.empty()) + { + llvm_log.trace("cpu_translator::replace_intrinsics(): function '%s' names_size=%d, names[0]=%s", func_name, names.size(), *names.begin()); + } + + if (names.contains(func_name)) + { + fmt::throw_exception("cpu_translator::replace_intrinsics(): Recursion detected at function '%s'!", func_name); + } + + names.emplace(std::string(func_name)); + + // Set insert point after call instruction + // In order to obtain a clear range of the inserted instructions + if (llvm::Instruction* next = ci->getNextNode()) + { + m_ir->SetInsertPoint(next); + } + else + { + m_ir->SetInsertPoint(std::addressof(bb)); + } + + ci->replaceAllUsesWith(it->second(ci)); + + InstListType::iterator end = m_ir->GetInsertPoint(); + + for (InstListType::iterator next_it = ci->eraseFromParent(), inner = next_it; inner != end;) + { + if (llvm::isa(&*inner)) { - if (auto it = m_intrinsics.find(std::string_view(cf->getName().data(), cf->getName().size())); it != m_intrinsics.end()) - { - m_ir->SetInsertPoint(ci); - ci->replaceAllUsesWith(it->second(ci)); - bit = ci->eraseFromParent(); - continue; - } + inner = fix_funcs(inner); + } + else + { + inner++; } } - ++bit; + // TODO: Simplify in C++23 with 'names.erase(func_name);' + names.erase(ensure(names.find(func_name), FN(x != names.end()))); + return end; + }; + + for (auto bit = bb.begin(); bit != bb.end(); bit = fix_funcs(bit)) + { } } } diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 18f9fa27b3..fcc21c09ae 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -6049,6 +6049,8 @@ public: final_result = eval(insert(final_result, i, r_fraction)); } + //final_result = eval(select(final_result != (0), final_result, bitcast(pshufb(splat(0), bitcast(final_result))))); + return bitcast(bitcast(final_result | bitcast(fix_exponent) | a_sign)); });