Added instruction counting

This commit is contained in:
Dani Messerman 2015-05-05 22:31:07 +03:00
parent 3ae4d8b646
commit 70463da199
8 changed files with 52 additions and 10 deletions

View File

@ -28,6 +28,8 @@ void InstructionBlock::GenerateCode()
auto ir_builder = Module()->IrBuilder(); auto ir_builder = Module()->IrBuilder();
ir_builder->SetInsertPoint(entry_basic_block); ir_builder->SetInsertPoint(entry_basic_block);
module->GenerateIncInstructionCount();
instruction->GenerateCode(this); instruction->GenerateCode(this);
} }

View File

@ -46,6 +46,15 @@ void ModuleGen::Run()
GenerateBlockAddressArray(); GenerateBlockAddressArray();
} }
void ModuleGen::GenerateIncInstructionCount()
{
auto load = ir_builder->CreateLoad(instruction_count);
auto inc = ir_builder->CreateAdd(load, ir_builder->getInt32(1));
auto store = ir_builder->CreateStore(inc, instruction_count);
tbaa->TagInstructionCount(load);
tbaa->TagInstructionCount(store);
}
void ModuleGen::BranchReadPC() void ModuleGen::BranchReadPC()
{ {
if (verify) if (verify)
@ -111,6 +120,9 @@ void ModuleGen::GenerateGlobals()
// bool Verify - contains the value of verify for citra usage // bool Verify - contains the value of verify for citra usage
new GlobalVariable(*module, ir_builder->getInt1Ty(), true, GlobalValue::ExternalLinkage, ir_builder->getInt1(verify), "Verify"); new GlobalVariable(*module, ir_builder->getInt1Ty(), true, GlobalValue::ExternalLinkage, ir_builder->getInt1(verify), "Verify");
instruction_count = new GlobalVariable(*Module(), ir_builder->getInt32Ty(), false, GlobalValue::ExternalLinkage,
ir_builder->getInt32(0), "InstructionCount");
} }
void ModuleGen::GenerateBlockAddressArray() void ModuleGen::GenerateBlockAddressArray()

View File

@ -27,6 +27,7 @@ public:
void Run(); void Run();
void GenerateIncInstructionCount();
// Generate code to read pc and run all following instructions, used in cases of indirect branch // Generate code to read pc and run all following instructions, used in cases of indirect branch
void BranchReadPC(); void BranchReadPC();
// Generate code to write to pc and run all following instructions, used in cases of direct branch // Generate code to write to pc and run all following instructions, used in cases of direct branch
@ -80,6 +81,11 @@ private:
*/ */
llvm::ArrayType *block_address_array_type; llvm::ArrayType *block_address_array_type;
llvm::GlobalVariable *block_address_array; llvm::GlobalVariable *block_address_array;
/*
* i32 InstructionCount;
* The count of instructions executed
*/
llvm::GlobalVariable *instruction_count;
/* /*
* i8 *GetBlockAddress(u32 pc) * i8 *GetBlockAddress(u32 pc)
* Returns the address of the block for the instruction at pc * Returns the address of the block for the instruction at pc

View File

@ -20,6 +20,7 @@ void TBAA::GenerateTags()
register_nodes[i] = md_builder.createTBAAScalarTypeNode(ss.str(), tbaa_root); register_nodes[i] = md_builder.createTBAAScalarTypeNode(ss.str(), tbaa_root);
} }
const_node = md_builder.createTBAAScalarTypeNode("Readonly", tbaa_root); const_node = md_builder.createTBAAScalarTypeNode("Readonly", tbaa_root);
instruction_count_node = md_builder.createTBAAScalarTypeNode("InstructionCount", tbaa_root);
} }
void TBAA::TagRegister(Instruction* instruction, Register reg) void TBAA::TagRegister(Instruction* instruction, Register reg)
@ -30,4 +31,9 @@ void TBAA::TagRegister(Instruction* instruction, Register reg)
void TBAA::TagConst(Instruction* instruction) void TBAA::TagConst(Instruction* instruction)
{ {
instruction->setMetadata(LLVMContext::MD_tbaa, const_node); instruction->setMetadata(LLVMContext::MD_tbaa, const_node);
}
void TBAA::TagInstructionCount(llvm::Instruction* instruction)
{
instruction->setMetadata(LLVMContext::MD_tbaa, instruction_count_node);
} }

View File

@ -21,9 +21,11 @@ public:
void TagRegister(llvm::Instruction *instruction, Register reg); void TagRegister(llvm::Instruction *instruction, Register reg);
void TagConst(llvm::Instruction *instruction); void TagConst(llvm::Instruction *instruction);
void TagInstructionCount(llvm::Instruction *instruction);
private: private:
llvm::MDNode *register_nodes[RegisterCount]; llvm::MDNode *register_nodes[RegisterCount];
// Tag for everything that is never written. // Tag for everything that is never written.
// Since it is never written, one tag works // Since it is never written, one tag works
llvm::MDNode *const_node; llvm::MDNode *const_node;
llvm::MDNode *instruction_count_node;
}; };

View File

@ -3985,7 +3985,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
#if ENABLE_BINARY_TRANSLATION #if ENABLE_BINARY_TRANSLATION
BinaryTranslationLoader::Run(); num_instrs = BinaryTranslationLoader::Run(num_instrs);
#endif #endif
if (cpu->TFlag) if (cpu->TFlag)

View File

@ -19,6 +19,7 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> g_loaded_object_info;
void(*g_run_function)(); void(*g_run_function)();
bool(*g_can_run_function)(); bool(*g_can_run_function)();
uint32_t *g_instruction_count;
// Used by the verifier // Used by the verifier
struct SavedState struct SavedState
@ -117,7 +118,16 @@ void BinaryTranslationLoader::Load(FileUtil::IOFile& file)
g_run_function = static_cast<decltype(g_run_function)>(g_dyld->getSymbolAddress("Run")); g_run_function = static_cast<decltype(g_run_function)>(g_dyld->getSymbolAddress("Run"));
g_can_run_function = static_cast<decltype(g_can_run_function)>(g_dyld->getSymbolAddress("CanRun")); g_can_run_function = static_cast<decltype(g_can_run_function)>(g_dyld->getSymbolAddress("CanRun"));
g_verify = *static_cast<bool*>(g_dyld->getSymbolAddress("Verify")); auto verify_ptr = static_cast<bool*>(g_dyld->getSymbolAddress("Verify"));
g_instruction_count = static_cast<uint32_t *>(g_dyld->getSymbolAddress("InstructionCount"));
if (!g_run_function || !g_can_run_function || !verify_ptr || !g_instruction_count)
{
LOG_WARNING(Loader, "Cannot load optimized file, missing critical function");
return;
}
g_verify = *verify_ptr;
g_enabled = true; g_enabled = true;
} }
@ -145,18 +155,19 @@ bool BinaryTranslationLoader::CanRun(bool specific_address)
return true; return true;
} }
void BinaryTranslationLoader::Run() uint32_t BinaryTranslationLoader::Run(uint32_t instruction_count)
{ {
// No need to check the PC, Run does it anyway // No need to check the PC, Run does it anyway
if (!CanRun(false)) return; if (!CanRun(false)) return instruction_count;
// If verify is enabled, it will run opcodes // If verify is enabled, it will run opcodes
if (g_verify) return; if (g_verify) return instruction_count;
RunInternal(); return RunInternal(instruction_count);
} }
void BinaryTranslationLoader::RunInternal() uint32_t BinaryTranslationLoader::RunInternal(uint32_t instruction_count)
{ {
*g_instruction_count = instruction_count;
g_run_function(); g_run_function();
g_state->TFlag = g_state->Reg[15] & 1; g_state->TFlag = g_state->Reg[15] & 1;
@ -164,6 +175,8 @@ void BinaryTranslationLoader::RunInternal()
g_state->Reg[15] &= 0xfffffffe; g_state->Reg[15] &= 0xfffffffe;
else else
g_state->Reg[15] &= 0xfffffffc; g_state->Reg[15] &= 0xfffffffc;
return *g_instruction_count;
} }
void Swap(void *a, void *b, size_t size) void Swap(void *a, void *b, size_t size)
@ -198,7 +211,7 @@ void BinaryTranslationLoader::VerifyCallback()
g_state_copy.SwapWith(*g_state); g_state_copy.SwapWith(*g_state);
// Run the opcode // Run the opcode
RunInternal(); RunInternal(0);
// Test // Test
auto current_as_saved_state = SavedState(*g_state); auto current_as_saved_state = SavedState(*g_state);

View File

@ -13,8 +13,9 @@ public:
// If specific_address, checks the specific PC too // If specific_address, checks the specific PC too
static bool CanRun(bool specific_address); static bool CanRun(bool specific_address);
// Runs the state provided at SetCpuState. // Runs the state provided at SetCpuState.
static void Run(); // Returns instruction_count + number of instructions executed
static uint32_t Run(uint32_t instruction_count);
// Link between Run and VerifyCallback // Link between Run and VerifyCallback
static void RunInternal(); static uint32_t RunInternal(uint32_t instruction_count);
static void VerifyCallback(); static void VerifyCallback();
}; };