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();
ir_builder->SetInsertPoint(entry_basic_block);
module->GenerateIncInstructionCount();
instruction->GenerateCode(this);
}

View File

@ -46,6 +46,15 @@ void ModuleGen::Run()
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()
{
if (verify)
@ -111,6 +120,9 @@ void ModuleGen::GenerateGlobals()
// bool Verify - contains the value of verify for citra usage
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()

View File

@ -27,6 +27,7 @@ public:
void Run();
void GenerateIncInstructionCount();
// Generate code to read pc and run all following instructions, used in cases of indirect branch
void BranchReadPC();
// 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::GlobalVariable *block_address_array;
/*
* i32 InstructionCount;
* The count of instructions executed
*/
llvm::GlobalVariable *instruction_count;
/*
* i8 *GetBlockAddress(u32 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);
}
const_node = md_builder.createTBAAScalarTypeNode("Readonly", tbaa_root);
instruction_count_node = md_builder.createTBAAScalarTypeNode("InstructionCount", tbaa_root);
}
void TBAA::TagRegister(Instruction* instruction, Register reg)
@ -30,4 +31,9 @@ void TBAA::TagRegister(Instruction* instruction, Register reg)
void TBAA::TagConst(Instruction* instruction)
{
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 TagConst(llvm::Instruction *instruction);
void TagInstructionCount(llvm::Instruction *instruction);
private:
llvm::MDNode *register_nodes[RegisterCount];
// Tag for everything that is never written.
// Since it is never written, one tag works
llvm::MDNode *const_node;
llvm::MDNode *instruction_count_node;
};

View File

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

View File

@ -19,6 +19,7 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> g_loaded_object_info;
void(*g_run_function)();
bool(*g_can_run_function)();
uint32_t *g_instruction_count;
// Used by the verifier
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_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;
}
@ -145,18 +155,19 @@ bool BinaryTranslationLoader::CanRun(bool specific_address)
return true;
}
void BinaryTranslationLoader::Run()
uint32_t BinaryTranslationLoader::Run(uint32_t instruction_count)
{
// 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 (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_state->TFlag = g_state->Reg[15] & 1;
@ -164,6 +175,8 @@ void BinaryTranslationLoader::RunInternal()
g_state->Reg[15] &= 0xfffffffe;
else
g_state->Reg[15] &= 0xfffffffc;
return *g_instruction_count;
}
void Swap(void *a, void *b, size_t size)
@ -198,7 +211,7 @@ void BinaryTranslationLoader::VerifyCallback()
g_state_copy.SwapWith(*g_state);
// Run the opcode
RunInternal();
RunInternal(0);
// Test
auto current_as_saved_state = SavedState(*g_state);

View File

@ -13,8 +13,9 @@ public:
// If specific_address, checks the specific PC too
static bool CanRun(bool specific_address);
// 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
static void RunInternal();
static uint32_t RunInternal(uint32_t instruction_count);
static void VerifyCallback();
};