PPU LLVM: Optimize branch list

This commit is contained in:
Eladash 2023-09-04 20:00:05 +03:00 committed by Elad Ashkenazi
parent cf6eb64f0b
commit fdbb0b0e2f

View File

@ -13,6 +13,7 @@
#include "util/v128.hpp"
#include "util/simd.hpp"
#include <algorithm>
#include <unordered_set>
#include <span>
using namespace llvm;
@ -371,8 +372,50 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
if (_target >= caddr && _target <= cend)
{
callee = m_module->getOrInsertFunction(fmt::format("__0x%x", target), type);
cast<Function>(callee.getCallee())->setCallingConv(CallingConv::GHC);
std::unordered_set<u64> passed_targets{_target};
u32 target_last = _target;
// Try to follow unconditional branches as long as there is no infinite loop
while (target_last != _target)
{
const ppu_opcode_t op{*ensure(m_info.get_ptr<u32>(target_last))};
const ppu_itype::type itype = g_ppu_itype.decode(op.opcode);
if (((itype == ppu_itype::BC && (op.bo & 0x14) == 0x14) || itype == ppu_itype::B) && !op.lk)
{
const u32 new_target = (op.aa ? 0 : target_last) + (itype == ppu_itype::B ? +op.bt24 : +op.bt14);
if (target_last >= caddr && target_last <= cend)
{
if (passed_targets.emplace(new_target).second)
{
// Ok
target_last = new_target;
continue;
}
// Infinite loop detected
target_last = _target;
}
// Odd destination
}
else if (itype == ppu_itype::BCLR && (op.bo & 0x14) == 0x14 && !op.lk)
{
// Special case: empty function
// In this case the branch can be treated as BCLR because previous CIA does not matter
indirect = RegLoad(m_lr);
}
break;
}
if (!indirect)
{
callee = m_module->getOrInsertFunction(fmt::format("__0x%x", target_last - base), type);
cast<Function>(callee.getCallee())->setCallingConv(CallingConv::GHC);
}
}
else
{