mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
PPU/LLVM: Remove indirect call completly
This commit is contained in:
parent
60d5dd40f7
commit
58181c5c17
@ -75,7 +75,7 @@ Compiler::~Compiler() {
|
||||
delete m_llvm_context;
|
||||
}
|
||||
|
||||
std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::string & name, u32 start_address, u32 instruction_count, bool generate_linkable_exits) {
|
||||
std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::string & name, u32 start_address, u32 instruction_count) {
|
||||
auto compilation_start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
m_module = new llvm::Module("Module", *m_llvm_context);
|
||||
@ -118,8 +118,6 @@ std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::stri
|
||||
fpm->add(createCFGSimplificationPass());
|
||||
fpm->doInitialization();
|
||||
|
||||
m_state.generate_linkable_exits = generate_linkable_exits;
|
||||
|
||||
// Create the function
|
||||
m_state.function = (Function *)m_module->getOrInsertFunction(name, m_compiled_function_type);
|
||||
m_state.function->setCallingConv(CallingConv::X86_64_Win64);
|
||||
@ -174,27 +172,7 @@ std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::stri
|
||||
|
||||
SetPc(m_ir_builder->getInt32(m_state.current_instruction_address));
|
||||
|
||||
if (generate_linkable_exits) {
|
||||
Value *context_i64 = m_ir_builder->CreateZExt(exit_instr_i32, m_ir_builder->getInt64Ty());
|
||||
context_i64 = m_ir_builder->CreateOr(context_i64, (u64)start_address << 32);
|
||||
Value *ret_i32 = IndirectCall(m_state.current_instruction_address, context_i64, false);
|
||||
Value *cmp_i1 = m_ir_builder->CreateICmpNE(ret_i32, m_ir_builder->getInt32(0));
|
||||
BasicBlock *then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then_0");
|
||||
BasicBlock *merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge_0");
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
context_i64 = m_ir_builder->CreateZExt(ret_i32, m_ir_builder->getInt64Ty());
|
||||
context_i64 = m_ir_builder->CreateOr(context_i64, (u64)start_address << 32);
|
||||
m_ir_builder->CreateCall2(m_execute_unknown_block, m_state.args[CompileTaskState::Args::State], context_i64);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(merge_bb);
|
||||
m_ir_builder->CreateRet(m_ir_builder->getInt32(0));
|
||||
}
|
||||
else {
|
||||
m_ir_builder->CreateRet(exit_instr_i32);
|
||||
}
|
||||
m_ir_builder->CreateRet(exit_instr_i32);
|
||||
}
|
||||
|
||||
// If the function has a default exit block then generate code for it
|
||||
@ -204,24 +182,8 @@ std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::stri
|
||||
PHINode *exit_instr_i32 = m_ir_builder->CreatePHI(m_ir_builder->getInt32Ty(), 0);
|
||||
exit_instr_list.push_back(exit_instr_i32);
|
||||
|
||||
if (generate_linkable_exits) {
|
||||
Value *cmp_i1 = m_ir_builder->CreateICmpNE(exit_instr_i32, m_ir_builder->getInt32(0));
|
||||
BasicBlock *then_bb = GetBasicBlockFromAddress(0xFFFFFFFF, "then_0");
|
||||
BasicBlock *merge_bb = GetBasicBlockFromAddress(0xFFFFFFFF, "merge_0");
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, merge_bb);
|
||||
m_ir_builder->CreateRet(exit_instr_i32);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
Value *context_i64 = m_ir_builder->CreateZExt(exit_instr_i32, m_ir_builder->getInt64Ty());
|
||||
context_i64 = m_ir_builder->CreateOr(context_i64, (u64)start_address << 32);
|
||||
m_ir_builder->CreateCall2(m_execute_unknown_block, m_state.args[CompileTaskState::Args::State], context_i64);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(merge_bb);
|
||||
m_ir_builder->CreateRet(m_ir_builder->getInt32(0));
|
||||
}
|
||||
else {
|
||||
m_ir_builder->CreateRet(exit_instr_i32);
|
||||
}
|
||||
}
|
||||
|
||||
// Add incoming values for all exit instr PHI nodes
|
||||
@ -308,13 +270,6 @@ RecompilationEngine::~RecompilationEngine() {
|
||||
free(FunctionCachePagesCommited);
|
||||
}
|
||||
|
||||
Executable executeFunc;
|
||||
Executable executeUntilReturn;
|
||||
|
||||
const Executable *RecompilationEngine::GetExecutable(u32 address, bool isFunction) {
|
||||
return isFunction ? &executeFunc : &executeUntilReturn;
|
||||
}
|
||||
|
||||
bool RecompilationEngine::isAddressCommited(u32 address) const
|
||||
{
|
||||
size_t offset = address * sizeof(Executable);
|
||||
@ -511,7 +466,7 @@ void RecompilationEngine::CompileBlock(BlockEntry & block_entry) {
|
||||
return;
|
||||
Log() << "Compile: " << block_entry.ToString() << "\n";
|
||||
const std::pair<Executable, llvm::ExecutionEngine *> &compileResult =
|
||||
m_compiler.Compile(fmt::format("fn_0x%08X", block_entry.address), block_entry.address, block_entry.instructionCount, false /*generate_linkable_exits*/);
|
||||
m_compiler.Compile(fmt::format("fn_0x%08X", block_entry.address), block_entry.address, block_entry.instructionCount);
|
||||
|
||||
// If entry doesn't exist, create it (using lock)
|
||||
std::unordered_map<u32, ExecutableStorage>::iterator It = m_address_to_function.find(block_entry.address);
|
||||
@ -547,8 +502,6 @@ ppu_recompiler_llvm::CPUHybridDecoderRecompiler::CPUHybridDecoderRecompiler(PPUT
|
||||
, m_interpreter(new PPUInterpreter(ppu))
|
||||
, m_decoder(m_interpreter)
|
||||
, m_recompilation_engine(RecompilationEngine::GetInstance()) {
|
||||
executeFunc = CPUHybridDecoderRecompiler::ExecuteFunction;
|
||||
executeUntilReturn = CPUHybridDecoderRecompiler::ExecuteTillReturn;
|
||||
}
|
||||
|
||||
ppu_recompiler_llvm::CPUHybridDecoderRecompiler::~CPUHybridDecoderRecompiler() {
|
||||
|
@ -71,7 +71,7 @@ namespace ppu_recompiler_llvm {
|
||||
* Compile a code fragment described by a cfg and return an executable and the ExecutionEngine storing it
|
||||
* Pointer to function can be retrieved with getPointerToFunction
|
||||
*/
|
||||
std::pair<Executable, llvm::ExecutionEngine *> Compile(const std::string & name, u32 start_address, u32 instruction_count, bool generate_linkable_exits);
|
||||
std::pair<Executable, llvm::ExecutionEngine *> Compile(const std::string & name, u32 start_address, u32 instruction_count);
|
||||
|
||||
/// Retrieve compiler stats
|
||||
Stats GetStats();
|
||||
@ -506,9 +506,6 @@ namespace ppu_recompiler_llvm {
|
||||
/// This is set to false at the start of compilation of an instruction.
|
||||
/// If a branch instruction is encountered, this is set to true by the decode function.
|
||||
bool hit_branch_instruction;
|
||||
|
||||
/// Create code such that exit points can be linked to other blocks
|
||||
bool generate_linkable_exits;
|
||||
};
|
||||
|
||||
/// Recompilation engine
|
||||
@ -745,9 +742,6 @@ namespace ppu_recompiler_llvm {
|
||||
return m_ir_builder->CreateCall(fn, fn_args);
|
||||
}
|
||||
|
||||
/// Indirect call
|
||||
llvm::Value * IndirectCall(u32 address, llvm::Value * context_i64, bool is_function);
|
||||
|
||||
/// Test an instruction against the interpreter
|
||||
template <class... Args>
|
||||
void VerifyInstructionAgainstInterpreter(const char * name, void (Compiler::*recomp_fn)(Args...), void (PPUInterpreter::*interp_fn)(Args...), PPUState & input_state, Args... args);
|
||||
@ -781,13 +775,6 @@ namespace ppu_recompiler_llvm {
|
||||
public:
|
||||
virtual ~RecompilationEngine() override;
|
||||
|
||||
/**
|
||||
* Get the executable for the specified address
|
||||
* The pointer is always valid during the lifetime of RecompilationEngine
|
||||
* but the function pointed to can be updated.
|
||||
**/
|
||||
const Executable *GetExecutable(u32 address, bool isFunction);
|
||||
|
||||
/**
|
||||
* Get the executable for the specified address if a compiled version is
|
||||
* available, otherwise returns nullptr.
|
||||
|
@ -5273,25 +5273,6 @@ void Compiler::WriteMemory(Value * addr_i64, Value * val_ix, u32 alignment, bool
|
||||
m_ir_builder->CreateAlignedStore(val_ix, eaddr_ix_ptr, alignment);
|
||||
}
|
||||
|
||||
llvm::Value * Compiler::IndirectCall(u32 address, Value * context_i64, bool is_function) {
|
||||
const Executable *functionPtr = m_recompilation_engine.GetExecutable(address, is_function);
|
||||
auto location_i64 = m_ir_builder->getInt64((uint64_t)functionPtr);
|
||||
auto location_i64_ptr = m_ir_builder->CreateIntToPtr(location_i64, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||
auto executable_i64 = m_ir_builder->CreateLoad(location_i64_ptr);
|
||||
auto executable_ptr = m_ir_builder->CreateIntToPtr(executable_i64, m_compiled_function_type->getPointerTo());
|
||||
auto ret_i32 = m_ir_builder->CreateCall2(executable_ptr, m_state.args[CompileTaskState::Args::State], context_i64);
|
||||
|
||||
auto cmp_i1 = m_ir_builder->CreateICmpEQ(ret_i32, m_ir_builder->getInt32(0xFFFFFFFF));
|
||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then_all_fs");
|
||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge_all_fs");
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, merge_bb);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
m_ir_builder->CreateRet(m_ir_builder->getInt32(0));
|
||||
m_ir_builder->SetInsertPoint(merge_bb);
|
||||
return ret_i32;
|
||||
}
|
||||
|
||||
void Compiler::CompilationError(const std::string & error) {
|
||||
LOG_ERROR(PPU, "[0x%08X] %s", m_state.current_instruction_address, error.c_str());
|
||||
Emu.Pause();
|
||||
|
Loading…
Reference in New Issue
Block a user