Skip to content

Commit 780a224

Browse files
committed
PPU LLVM: Fix optimization of branch string
1 parent ff4485d commit 780a224

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

rpcs3/Emu/Cell/PPUTranslator.cpp

+33-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,23 @@ 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+
// Save and restore current insert point
419+
const auto block_cur = m_ir->GetInsertBlock();
420+
421+
// Emit register load in the beginning of the common block
422+
m_ir->SetInsertPoint(prev_block, prev_block->getFirstInsertionPt());
423+
indirect = RegLoad(m_lr);
424+
m_lr = nullptr;
425+
m_ir->SetInsertPoint(block_cur);
426+
}
409427
}
410428

411429
break;
@@ -629,7 +647,7 @@ Value* PPUTranslator::Trunc(Value* value, Type* type)
629647
return type != value->getType() ? m_ir->CreateTrunc(value, type) : value;
630648
}
631649

632-
void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
650+
void PPUTranslator::UseCondition(MDNode* hint, Value* cond, BasicBlock* prev_block)
633651
{
634652
FlushRegisters();
635653

@@ -639,7 +657,7 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
639657
const auto next = BasicBlock::Create(m_context, "__next", m_function);
640658
m_ir->CreateCondBr(cond, local, next, hint);
641659
m_ir->SetInsertPoint(next);
642-
CallFunction(m_addr + 4);
660+
CallFunction(m_addr + 4, nullptr, prev_block);
643661
m_ir->SetInsertPoint(local);
644662
}
645663
}
@@ -2024,6 +2042,8 @@ void PPUTranslator::BC(ppu_opcode_t op)
20242042
const s32 bt14 = op.bt14; // Workaround for VS 16.5
20252043
const u64 target = (op.aa ? 0 : m_addr) + bt14;
20262044

2045+
const auto block = m_ir->GetInsertBlock();
2046+
20272047
if (op.aa && m_reloc)
20282048
{
20292049
CompilationError("Branch with absolute address");
@@ -2034,9 +2054,9 @@ void PPUTranslator::BC(ppu_opcode_t op)
20342054
m_ir->CreateStore(GetAddr(+4), m_ir->CreateStructGEP(m_thread_type, m_thread, static_cast<uint>(&m_lr - m_locals)));
20352055
}
20362056

2037-
UseCondition(CheckBranchProbability(op.bo), CheckBranchCondition(op.bo, op.bi));
2057+
UseCondition(CheckBranchProbability(op.bo), CheckBranchCondition(op.bo, op.bi), block);
20382058

2039-
CallFunction(target);
2059+
CallFunction(target, nullptr, block);
20402060
}
20412061

20422062
void PPUTranslator::SC(ppu_opcode_t op)
@@ -2074,6 +2094,8 @@ void PPUTranslator::B(ppu_opcode_t op)
20742094
const s32 bt24 = op.bt24; // Workaround for VS 16.5
20752095
const u64 target = (op.aa ? 0 : m_addr) + bt24;
20762096

2097+
const auto block = m_ir->GetInsertBlock();
2098+
20772099
if (op.aa && m_reloc)
20782100
{
20792101
CompilationError("Branch with absolute address");
@@ -2085,7 +2107,7 @@ void PPUTranslator::B(ppu_opcode_t op)
20852107
}
20862108

20872109
FlushRegisters();
2088-
CallFunction(target);
2110+
CallFunction(target, nullptr, block);
20892111
}
20902112

20912113
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)