Merge pull request #11916 from JosJuice/ppcanalyst-reorder-loop
PPCAnalyst: Reduce number of iterations in ReorderInstructionsCore
This commit is contained in:
commit
ed4403537f
|
@ -470,52 +470,74 @@ static bool isCror(const CodeOp& a)
|
||||||
void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse,
|
void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse,
|
||||||
ReorderType type) const
|
ReorderType type) const
|
||||||
{
|
{
|
||||||
// Bubbling an instruction sometimes reveals another opportunity to bubble an instruction, so do
|
// Instruction Reordering Pass
|
||||||
// multiple passes.
|
// Carry pass: bubble carry-using instructions as close to each other as possible, so we can avoid
|
||||||
|
// storing the carry flag.
|
||||||
|
// Compare pass: bubble compare instructions next to branches, so they can be merged.
|
||||||
|
|
||||||
|
const int start = reverse ? instructions - 1 : 0;
|
||||||
|
const int end = reverse ? 0 : instructions - 1;
|
||||||
|
const int increment = reverse ? -1 : 1;
|
||||||
|
|
||||||
|
int i = start;
|
||||||
|
int next = start;
|
||||||
|
bool go_backwards = false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Instruction Reordering Pass
|
if (go_backwards)
|
||||||
// Carry pass: bubble carry-using instructions as close to each other as possible, so we can
|
|
||||||
// avoid
|
|
||||||
// storing the carry flag.
|
|
||||||
// Compare pass: bubble compare instructions next to branches, so they can be merged.
|
|
||||||
bool swapped = false;
|
|
||||||
int increment = reverse ? -1 : 1;
|
|
||||||
int start = reverse ? instructions - 1 : 0;
|
|
||||||
int end = reverse ? 0 : instructions - 1;
|
|
||||||
for (int i = start; i != end; i += increment)
|
|
||||||
{
|
{
|
||||||
CodeOp& a = code[i];
|
i -= increment;
|
||||||
CodeOp& b = code[i + increment];
|
go_backwards = false;
|
||||||
// Reorder integer compares, rlwinm., and carry-affecting ops
|
}
|
||||||
// (if we add more merged branch instructions, add them here!)
|
else
|
||||||
if ((type == ReorderType::CROR && isCror(a)) ||
|
{
|
||||||
(type == ReorderType::Carry && isCarryOp(a)) ||
|
i = next;
|
||||||
(type == ReorderType::CMP && (isCmp(a) || a.outputCR[0])))
|
next += increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
CodeOp& a = code[i];
|
||||||
|
CodeOp& b = code[i + increment];
|
||||||
|
|
||||||
|
// Reorder integer compares, rlwinm., and carry-affecting ops
|
||||||
|
// (if we add more merged branch instructions, add them here!)
|
||||||
|
if ((type == ReorderType::CROR && isCror(a)) || (type == ReorderType::Carry && isCarryOp(a)) ||
|
||||||
|
(type == ReorderType::CMP && (isCmp(a) || a.outputCR[0])))
|
||||||
|
{
|
||||||
|
// once we're next to a carry instruction, don't move away!
|
||||||
|
if (type == ReorderType::Carry && i != start)
|
||||||
{
|
{
|
||||||
// once we're next to a carry instruction, don't move away!
|
// if we read the CA flag, and the previous instruction sets it, don't move away.
|
||||||
if (type == ReorderType::Carry && i != start)
|
if (!reverse && (a.opinfo->flags & FL_READ_CA) &&
|
||||||
|
(code[i - increment].opinfo->flags & FL_SET_CA))
|
||||||
{
|
{
|
||||||
// if we read the CA flag, and the previous instruction sets it, don't move away.
|
continue;
|
||||||
if (!reverse && (a.opinfo->flags & FL_READ_CA) &&
|
|
||||||
(code[i - increment].opinfo->flags & FL_SET_CA))
|
|
||||||
continue;
|
|
||||||
// if we set the CA flag, and the next instruction reads it, don't move away.
|
|
||||||
if (reverse && (a.opinfo->flags & FL_SET_CA) &&
|
|
||||||
(code[i - increment].opinfo->flags & FL_READ_CA))
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanSwapAdjacentOps(a, b))
|
// if we set the CA flag, and the next instruction reads it, don't move away.
|
||||||
|
if (reverse && (a.opinfo->flags & FL_SET_CA) &&
|
||||||
|
(code[i - increment].opinfo->flags & FL_READ_CA))
|
||||||
{
|
{
|
||||||
// Alright, let's bubble it!
|
continue;
|
||||||
std::swap(a, b);
|
}
|
||||||
swapped = true;
|
}
|
||||||
|
|
||||||
|
if (CanSwapAdjacentOps(a, b))
|
||||||
|
{
|
||||||
|
// Alright, let's bubble it!
|
||||||
|
std::swap(a, b);
|
||||||
|
|
||||||
|
if (i != start)
|
||||||
|
{
|
||||||
|
// Bubbling an instruction sometimes reveals another opportunity to bubble an instruction,
|
||||||
|
// so go one step backwards and check if we have such an opportunity.
|
||||||
|
go_backwards = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!swapped)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue