Author SHA1 Message Date
Stefanos Kornilios Mitsis Poiitidis 8855e13540 shrec: Some ideas for block graphs 2015-09-23 13:42:14 +02:00
6 changed files with 185 additions and 1 deletions

No files matched your search

+7 -1
View File
@@ -122,7 +122,11 @@ RuntimeBlockInfo* bm_GetBlock(void* dynarec_code)
}
else
{
printf("bm_GetBlock(%08X) failed ..\n",dynarec_code);
for (iter = blkmap.begin(); iter != blkmap.end(); iter++) {
if ((*iter)->contains_code((u8*)dynarec_code))
return *iter;
}
//printf("bm_GetBlock(%p, %p) failed ..\n",dynarec_code, ngen_FailedToFindBlock);
return 0;
}
}
@@ -158,6 +162,8 @@ void bm_AddBlock(RuntimeBlockInfo* blk)
verify((void*)bm_GetCode(blk->addr)==(void*)ngen_FailedToFindBlock);
FPCA(blk->addr)=blk->code;
verify(bm_GetBlock(blk->addr) == blk);
#ifdef DYNA_OPROF
if (oprofHandle)
{
+1
View File
@@ -71,6 +71,7 @@ struct RuntimeBlockInfo: RuntimeBlockInfo_Core
u32 memops;
u32 linkedmemops;
bool entry_block;
};
struct CachedBlockInfo: RuntimeBlockInfo_Core
+10
View File
@@ -14,6 +14,7 @@
#include "hw/sh4/sh4_core.h"
#include "hw/sh4/sh4_mem.h"
#include "decoder_opcodes.h"
#include "../interpr/sh4_opcodes.h"
#define BLOCK_MAX_SH_OPS_SOFT 500
#define BLOCK_MAX_SH_OPS_HARD 511
@@ -1098,6 +1099,13 @@ void dec_DecodeBlock(RuntimeBlockInfo* rbi,u32 max_cycles)
else
blk->guest_cycles+=CPU_RATIO;
if ((state.cpu.is_delayslot && OpDesc[op]->SetPC()) ||
OpDesc[op]->oph == iNotImplemented) {
blk->addr = -1;
return;
}
verify(!(state.cpu.is_delayslot && OpDesc[op]->SetPC()));
if (state.ngen.OnlyDynamicEnds || !OpDesc[op]->rec_oph)
{
@@ -1168,6 +1176,8 @@ _end:
if (settings.dynarec.idleskip)
{
//Experimental hash-id based idle skip
if (blk->addr == 0x8C0B926A)
blk->guest_cycles *= 100;
if (strstr(idle_hash,blk->hash(false,true)))
{
//printf("IDLESKIP: %08X reloc match %s\n",blk->addr,blk->hash(false,true));
+150
View File
@@ -72,11 +72,24 @@ void RASDASD()
LastAddr=LastAddr_min;
memset(emit_GetCCPtr(),0xCC,emit_FreeSpace());
}
#include <map>
#include <algorithm>
#include <set>
typedef map<u32, RuntimeBlockInfo*> BlockGraph;
vector<BlockGraph*> graphs;
map<u32, BlockGraph*> blockgraphs;
void recSh4_ClearCache()
{
LastAddr=LastAddr_min;
bm_Reset();
graphs.clear();
blockgraphs.clear();
printf("recSh4:Dynarec Cache clear at %08X\n",curr_pc);
}
@@ -212,9 +225,145 @@ void RuntimeBlockInfo::Setup(u32 rpc,fpscr_t rfpu_cfg)
AnalyseBlock(this);
}
void merge_graphs(BlockGraph* one, BlockGraph* two) {
for (BlockGraph::iterator it = two->begin(); it != two->end(); it++) {
blockgraphs[it->second->addr] = one;
(*one)[it->second->addr] = it->second;
}
graphs.erase(find(graphs.begin(), graphs.end(), two));
}
void discover_graph(u32 bootstrap) {
BlockGraph* graph;
set<u32> resolved;
vector<u32> unresolved;
if (blockgraphs.count(bootstrap)) {
graph = blockgraphs[bootstrap];
(*graph)[bootstrap]->entry_block = true;
return;
} else {
graph = new BlockGraph();
graphs.push_back(graph);
}
unresolved.push_back(bootstrap);
while (unresolved.size()) {
u32 pc = unresolved[unresolved.size()-1];
unresolved.pop_back();
if (resolved.count(pc))
continue;
if (graph->count(pc))
continue;
if (blockgraphs.count(pc)) {
verify(blockgraphs[pc] != graph);
merge_graphs(blockgraphs[pc], graph);
graph = blockgraphs[pc];
resolved.clear();
continue;
}
resolved.insert(pc);
//printf("resolving %08X\n", pc);
RuntimeBlockInfo* rbi = ngen_AllocateBlock();
rbi->Setup(pc,fpscr);
rbi->entry_block = pc == bootstrap;
if (rbi->addr == -1)
continue;
(*graph)[pc] = rbi;
blockgraphs[pc] = graph;
if (rbi->BranchBlock !=-1 && rbi->BlockType != BET_StaticCall)
unresolved.push_back(rbi->BranchBlock);
if (rbi->NextBlock != -1)
unresolved.push_back(rbi->NextBlock);
}
int entrypoints = 0;
for (BlockGraph::iterator it = graph->begin(); it != graph->end(); it++) {
entrypoints += it->second->entry_block;
}
//printf("Graph: %d blocks w/ %d entrypoints, %d graphs\n", graph->size(), entrypoints, graphs.size());
}
void print_graphs() {
int top_runs = 0;
int total_runs = 0;
map<BlockGraph*, u32> graph_runs;
for (size_t i = 0; i < graphs.size(); i++) {
BlockGraph* graph = graphs[i];
for (BlockGraph::iterator it = graphs[i]->begin(); it != graphs[i]->end(); it++) {
RuntimeBlockInfo* natblock = bm_GetBlock(it->first);
if (!natblock || natblock->runs == 0)
continue;
if (natblock->runs > top_runs)
top_runs = natblock->runs;
total_runs += natblock->runs;
graph_runs[graph] += natblock->runs;
}
}
int baseline = top_runs / 100;
printf("<Graphdump\n");
for (size_t i = 0; i < graphs.size(); i++) {
BlockGraph* graph = graphs[i];
if (graph_runs[graph] < baseline)
continue;
printf("\tGraph: %p\n", graphs[i]);
int cnt = 0;
int cnt2 = 0;
for (BlockGraph::iterator it = graphs[i]->begin(); it != graphs[i]->end(); it++) {
RuntimeBlockInfo* natblock = bm_GetBlock(it->first);
if (!natblock || natblock->runs == 0 || natblock->runs < baseline) {
if (natblock) {
cnt2++;
natblock->runs = 0;
} else {
cnt++;
}
continue;
}
printf("\t\tBlock %08X, compiled: %d, entrypoint: %d, type: %d, len: %d, cycles: %d, runs %d, loop %d\n",
it->first, natblock != 0, it->second->entry_block, it->second->BlockType, it->second->oplist.size(),
it->second->guest_cycles, natblock ? natblock->runs : 0,
(it->second->BlockType == BET_Cond_0 || it->second->BlockType == BET_Cond_1) && graph->count(it->second->BranchBlock) );
if (natblock)
natblock->runs = 0;
}
if (cnt2) {
printf("\t\t and %d more not worth mentioning\n", cnt2);
}
if (cnt) {
printf("\t\t and %d more that never run\n", cnt);
}
}
printf("Graphdump>\n");
}
DynarecCodeEntryPtr rdv_CompilePC()
{
u32 pc=next_pc;
discover_graph(pc);
if (emit_FreeSpace()<16*1024 || pc==0x8c0000e0 || pc==0xac010000 || pc==0xac008300)
recSh4_ClearCache();
@@ -232,6 +381,7 @@ DynarecCodeEntryPtr rdv_CompilePC()
rbi->staging_runs=do_opts?100:-100;
ngen_Compile(rbi,DoCheck(rbi->addr),(pc&0xFFFFFF)==0x08300 || (pc&0xFFFFFF)==0x10000,false,do_opts);
verify(rbi->code!=0);
verify(rbi->host_code_size!=0);
bm_AddBlock(rbi);
+12
View File
@@ -189,6 +189,18 @@ void UpdateInputState(u32 port)
#if defined(USE_SDL)
input_sdl_handle(port);
#endif
//Whatever happened to these?
#if FEAT_SHREC != DYNAREC_NONE
/*
void print_graphs();
if ('b' == key) emit_WriteCodeCache();
if ('n' == key) bm_Reset();
if ('m' == key) bm_Sort();
if (',' == key) { emit_WriteCodeCache(); bm_Sort(); }
if ('q' == key) print_graphs();
*/
#endif
}
void os_DoEvents()
+5
View File
@@ -162,6 +162,10 @@ public:
sub(dword[rax], block->guest_cycles);
mov(rax, (size_t)&block->runs);
add(dword[rax], 1);
sub(rsp, 0x28);
for (size_t i = 0; i < block->oplist.size(); i++) {
@@ -355,6 +359,7 @@ public:
block->code = (DynarecCodeEntryPtr)getCode();
block->host_code_size = getSize();
emit_Skip(getSize());
}