Skip to content

Commit 0e7efd4

Browse files
committed
PPU LLVM: Fix optimization of branch string
1 parent ff4485d commit 0e7efd4

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

rpcs3/Emu/Cell/PPUTranslator.cpp

+35-11
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ Function* PPUTranslator::Translate(const ppu_function& info)
266266
if (!m_ir->GetInsertBlock()->getTerminator())
267267
{
268268
FlushRegisters();
269-
CallFunction(m_addr);
269+
CallFunction(m_addr, nullptr, m_ir->GetInsertBlock());
270270
}
271271
}
272272

@@ -354,7 +354,7 @@ Value* PPUTranslator::RotateLeft(Value* arg, Value* n)
354354
return m_ir->CreateOr(m_ir->CreateShl(arg, m_ir->CreateAnd(n, mask)), m_ir->CreateLShr(arg, m_ir->CreateAnd(m_ir->CreateNeg(n), mask)));
355355
}
356356

357-
void PPUTranslator::CallFunction(u64 target, Value* indirect)
357+
void PPUTranslator::CallFunction(u64 target, Value* indirect, BasicBlock* prev_block)
358358
{
359359
const auto type = m_function->getFunctionType();
360360
const auto block = m_ir->GetInsertBlock();
@@ -372,13 +372,19 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
372372

373373
if (_target >= caddr && _target <= cend)
374374
{
375-
std::unordered_set<u64> passed_targets{_target};
375+
std::unordered_set<u64> passed_targets;
376376

377377
u32 target_last = _target;
378378

379379
// Try to follow unconditional branches as long as there is no infinite loop
380-
while (target_last != _target)
380+
while (target_last != m_addr + base)
381381
{
382+
if (passed_targets.empty())
383+
{
384+
passed_targets.emplace(_target);
385+
passed_targets.emplace(m_addr + base);
386+
}
387+
382388
const ppu_opcode_t op{*ensure(m_info.get_ptr<u32>(target_last))};
383389
const ppu_itype::type itype = g_ppu_itype.decode(op.opcode);
384390

@@ -401,11 +407,25 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
401407

402408
// Odd destination
403409
}
404-
else if (itype == ppu_itype::BCLR && (op.bo & 0x14) == 0x14 && !op.lk)
410+
else if (itype == ppu_itype::BCLR && (op.bo & 0x14) == 0x14 && !op.lk && (prev_block || m_lr))
405411
{
406412
// Special case: empty function
407413
// In this case the branch can be treated as BCLR because previous CIA does not matter
408-
indirect = RegLoad(m_lr);
414+
indirect = m_lr;
415+
416+
if (!indirect)
417+
{
418+
if (block != prev_block)
419+
{
420+
// Emit register load in the beginning of the common block
421+
m_ir->SetInsertPoint(prev_block, prev_block->getFirstInsertionPt());
422+
}
423+
424+
indirect = RegLoad(m_lr);
425+
426+
// Restore current insert point
427+
m_ir->SetInsertPoint(block);
428+
}
409429
}
410430

411431
break;
@@ -629,7 +649,7 @@ Value* PPUTranslator::Trunc(Value* value, Type* type)
629649
return type != value->getType() ? m_ir->CreateTrunc(value, type) : value;
630650
}
631651

632-
void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
652+
void PPUTranslator::UseCondition(MDNode* hint, Value* cond, BasicBlock* prev_block)
633653
{
634654
FlushRegisters();
635655

@@ -639,7 +659,7 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
639659
const auto next = BasicBlock::Create(m_context, "__next", m_function);
640660
m_ir->CreateCondBr(cond, local, next, hint);
641661
m_ir->SetInsertPoint(next);
642-
CallFunction(m_addr + 4);
662+
CallFunction(m_addr + 4, nullptr, prev_block);
643663
m_ir->SetInsertPoint(local);
644664
}
645665
}
@@ -2024,6 +2044,8 @@ void PPUTranslator::BC(ppu_opcode_t op)
20242044
const s32 bt14 = op.bt14; // Workaround for VS 16.5
20252045
const u64 target = (op.aa ? 0 : m_addr) + bt14;
20262046

2047+
const auto block = m_ir->GetInsertBlock();
2048+
20272049
if (op.aa && m_reloc)
20282050
{
20292051
CompilationError("Branch with absolute address");
@@ -2034,9 +2056,9 @@ void PPUTranslator::BC(ppu_opcode_t op)
20342056
m_ir->CreateStore(GetAddr(+4), m_ir->CreateStructGEP(m_thread_type, m_thread, static_cast<uint>(&m_lr - m_locals)));
20352057
}
20362058

2037-
UseCondition(CheckBranchProbability(op.bo), CheckBranchCondition(op.bo, op.bi));
2059+
UseCondition(CheckBranchProbability(op.bo), CheckBranchCondition(op.bo, op.bi), block);
20382060

2039-
CallFunction(target);
2061+
CallFunction(target, nullptr, block);
20402062
}
20412063

20422064
void PPUTranslator::SC(ppu_opcode_t op)
@@ -2074,6 +2096,8 @@ void PPUTranslator::B(ppu_opcode_t op)
20742096
const s32 bt24 = op.bt24; // Workaround for VS 16.5
20752097
const u64 target = (op.aa ? 0 : m_addr) + bt24;
20762098

2099+
const auto block = m_ir->GetInsertBlock();
2100+
20772101
if (op.aa && m_reloc)
20782102
{
20792103
CompilationError("Branch with absolute address");
@@ -2085,7 +2109,7 @@ void PPUTranslator::B(ppu_opcode_t op)
20852109
}
20862110

20872111
FlushRegisters();
2088-
CallFunction(target);
2112+
CallFunction(target, nullptr, block);
20892113
}
20902114

20912115
void PPUTranslator::MCRF(ppu_opcode_t op)

rpcs3/Emu/Cell/PPUTranslator.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class PPUTranslator final : public cpu_translator
148148
llvm::Value* RotateLeft(llvm::Value* arg, llvm::Value* n);
149149

150150
// Emit function call
151-
void CallFunction(u64 target, llvm::Value* indirect = nullptr);
151+
void CallFunction(u64 target, llvm::Value* indirect = nullptr, llvm::BasicBlock* prev_block = nullptr);
152152

153153
// Initialize global for writing
154154
llvm::Value* RegInit(llvm::Value*& local);
@@ -292,7 +292,7 @@ class PPUTranslator final : public cpu_translator
292292
llvm::MDNode* CheckBranchProbability(u32 bo);
293293

294294
// Branch to next instruction if condition failed, never branch on nullptr
295-
void UseCondition(llvm::MDNode* hint, llvm::Value* = nullptr);
295+
void UseCondition(llvm::MDNode* hint, llvm::Value* = nullptr, llvm::BasicBlock* prev_block = nullptr);
296296

297297
// Get memory pointer
298298
llvm::Value* GetMemory(llvm::Value* addr);

0 commit comments

Comments
 (0)