Remove the old PPAnalyst::Flatten function that is no longer in use.

This commit is contained in:
Ryan Houdek 2014-04-30 08:20:00 -05:00
parent c794dc8085
commit 8e1dfef14c
2 changed files with 0 additions and 300 deletions

View File

@ -269,302 +269,6 @@ bool CanSwapAdjacentOps(const CodeOp &a, const CodeOp &b)
return true;
}
// Does not yet perform inlining - although there are plans for that.
// Returns the exit address of the next PC
u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer,
int blockSize, u32* merged_addresses,
int capacity_of_merged_addresses, int& size_of_merged_addresses)
{
if (capacity_of_merged_addresses < FUNCTION_FOLLOWING_THRESHOLD) {
PanicAlert("Capacity of merged_addresses is too small!");
}
std::fill_n(merged_addresses, capacity_of_merged_addresses, 0);
merged_addresses[0] = address;
size_of_merged_addresses = 1;
memset(st, 0, sizeof(*st));
// Disabled the following optimization in preference of FAST_ICACHE
//UGeckoInstruction previnst = Memory::Read_Opcode_JIT_LC(address - 4);
//if (previnst.hex == 0x4e800020)
// st->isFirstBlockOfFunction = true;
gpa->any = true;
fpa->any = false;
for (int i = 0; i < 32; i++)
{
gpa->firstRead[i] = -1;
gpa->firstWrite[i] = -1;
gpa->numReads[i] = 0;
gpa->numWrites[i] = 0;
}
u32 blockstart = address;
int maxsize = blockSize;
int num_inst = 0;
int numFollows = 0;
int numCycles = 0;
CodeOp *code = buffer->codebuffer;
bool foundExit = false;
u32 return_address = 0;
// Do analysis of the code, look for dependencies etc
int numSystemInstructions = 0;
for (int i = 0; i < maxsize; i++)
{
UGeckoInstruction inst = JitInterface::Read_Opcode_JIT(address);
if (inst.hex != 0)
{
num_inst++;
memset(&code[i], 0, sizeof(CodeOp));
GekkoOPInfo *opinfo = GetOpInfo(inst);
code[i].opinfo = opinfo;
// FIXME: code[i].address may not be correct due to CST1 code.
code[i].address = address;
code[i].inst = inst;
code[i].branchTo = -1;
code[i].branchToIndex = -1;
code[i].skip = false;
numCycles += opinfo->numCycles;
code[i].wantsCR0 = false;
code[i].wantsCR1 = false;
code[i].wantsPS1 = false;
int flags = opinfo->flags;
if (flags & FL_USE_FPU)
fpa->any = true;
if (flags & FL_TIMER)
gpa->anyTimer = true;
// Does the instruction output CR0?
if (flags & FL_RC_BIT)
code[i].outputCR0 = inst.hex & 1; //todo fix
else if ((flags & FL_SET_CRn) && inst.CRFD == 0)
code[i].outputCR0 = true;
else
code[i].outputCR0 = (flags & FL_SET_CR0) ? true : false;
// Does the instruction output CR1?
if (flags & FL_RC_BIT_F)
code[i].outputCR1 = inst.hex & 1; //todo fix
else if ((flags & FL_SET_CRn) && inst.CRFD == 1)
code[i].outputCR1 = true;
else
code[i].outputCR1 = (flags & FL_SET_CR1) ? true : false;
int numOut = 0;
int numIn = 0;
if (flags & FL_OUT_A)
{
code[i].regsOut[numOut++] = inst.RA;
gpa->SetOutputRegister(inst.RA, i);
}
if (flags & FL_OUT_D)
{
code[i].regsOut[numOut++] = inst.RD;
gpa->SetOutputRegister(inst.RD, i);
}
if (flags & FL_OUT_S)
{
code[i].regsOut[numOut++] = inst.RS;
gpa->SetOutputRegister(inst.RS, i);
}
if ((flags & FL_IN_A) || ((flags & FL_IN_A0) && inst.RA != 0))
{
code[i].regsIn[numIn++] = inst.RA;
gpa->SetInputRegister(inst.RA, i);
}
if (flags & FL_IN_B)
{
code[i].regsIn[numIn++] = inst.RB;
gpa->SetInputRegister(inst.RB, i);
}
if (flags & FL_IN_C)
{
code[i].regsIn[numIn++] = inst.RC;
gpa->SetInputRegister(inst.RC, i);
}
if (flags & FL_IN_S)
{
code[i].regsIn[numIn++] = inst.RS;
gpa->SetInputRegister(inst.RS, i);
}
// Set remaining register slots as unused (-1)
for (int j = numIn; j < 3; j++)
code[i].regsIn[j] = -1;
for (int j = numOut; j < 2; j++)
code[i].regsOut[j] = -1;
for (int j = 0; j < 3; j++)
code[i].fregsIn[j] = -1;
code[i].fregOut = -1;
switch (opinfo->type)
{
case OPTYPE_INTEGER:
case OPTYPE_LOAD:
case OPTYPE_STORE:
case OPTYPE_LOADFP:
case OPTYPE_STOREFP:
break;
case OPTYPE_FPU:
break;
case OPTYPE_BRANCH:
if (code[i].inst.hex == 0x4e800020)
{
// For analysis purposes, we can assume that blr eats flags.
code[i].outputCR0 = true;
code[i].outputCR1 = true;
}
break;
case OPTYPE_SYSTEM:
case OPTYPE_SYSTEMFP:
numSystemInstructions++;
break;
}
bool follow = false;
u32 destination = 0;
if (inst.OPCD == 18 && blockSize > 1)
{
//Is bx - should we inline? yes!
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = address + SignExt26(inst.LI << 2);
if (destination != blockstart)
follow = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2)) &&
return_address != 0)
{
// bclrx with unconditional branch = return
follow = true;
destination = return_address;
return_address = 0;
if (inst.LK)
return_address = address + 4;
}
else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
{
// mtspr
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
if (index == SPR_LR) {
// We give up to follow the return address
// because we have to check the register usage.
return_address = 0;
}
}
if (follow)
numFollows++;
// TODO: Find the optimal value for FUNCTION_FOLLOWING_THRESHOLD.
// If it is small, the performance will be down.
// If it is big, the size of generated code will be big and
// cache clearning will happen many times.
// TODO: Investivate the reason why
// "0" is fastest in some games, MP2 for example.
if (numFollows > FUNCTION_FOLLOWING_THRESHOLD)
follow = false;
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMergeBlocks) {
follow = false;
}
if (!follow)
{
if (opinfo->flags & FL_ENDBLOCK) //right now we stop early
{
foundExit = true;
break;
}
address += 4;
}
else
{
// We don't "code[i].skip = true" here
// because bx may store a certain value to the link register.
// Instead, we skip a part of bx in Jit**::bx().
address = destination;
merged_addresses[size_of_merged_addresses++] = address;
}
}
else
{
// ISI exception or other critical memory exception occurred (game over)
break;
}
}
st->numCycles = numCycles;
// Instruction Reordering Pass
if (num_inst > 1)
{
// Bubble down compares towards branches, so that they can be merged.
// -2: -1 for the pair, -1 for not swapping with the final instruction which is probably the branch.
for (int i = 0; i < num_inst - 2; i++)
{
CodeOp &a = code[i];
CodeOp &b = code[i + 1];
// All integer compares can be reordered.
if ((a.inst.OPCD == 10 || a.inst.OPCD == 11) ||
(a.inst.OPCD == 31 && (a.inst.SUBOP10 == 0 || a.inst.SUBOP10 == 32)))
{
// Got a compare instruction.
if (CanSwapAdjacentOps(a, b)) {
// Alright, let's bubble it down!
CodeOp c = a;
a = b;
b = c;
}
}
}
}
if (!foundExit && num_inst > 0)
{
// A broken block is a block that does not end in a branch
broken_block = true;
}
// Scan for CR0 dependency
// assume next block wants CR0 to be safe
bool wantsCR0 = true;
bool wantsCR1 = true;
bool wantsPS1 = true;
for (int i = num_inst - 1; i >= 0; i--)
{
if (code[i].outputCR0)
wantsCR0 = false;
if (code[i].outputCR1)
wantsCR1 = false;
if (code[i].outputPS1)
wantsPS1 = false;
wantsCR0 |= code[i].wantsCR0;
wantsCR1 |= code[i].wantsCR1;
wantsPS1 |= code[i].wantsPS1;
code[i].wantsCR0 = wantsCR0;
code[i].wantsCR1 = wantsCR1;
code[i].wantsPS1 = wantsPS1;
}
*realsize = num_inst;
// ...
return address;
}
// Most functions that are relevant to analyze should be
// called by another function. Therefore, let's scan the
// entire space for bl operations and find what functions

View File

@ -175,10 +175,6 @@ public:
u32 Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32 blockSize);
};
u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer,
int blockSize, u32* merged_addresses,
int capacity_of_merged_addresses, int& size_of_merged_addresses);
void LogFunctionCall(u32 addr);
void FindFunctions(u32 startAddr, u32 endAddr, PPCSymbolDB *func_db);
bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size = 0);