diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2023-07-01 01:06:53 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-01 01:06:53 +0200 |
| commit | ed4403537fa0a83ddf2d0ceaae9323c40e5ba2d8 (patch) | |
| tree | ede46bf0f4875790778083247b61ab1e389ee20c /Source/Core | |
| parent | 82c986816f2ff409f91de625132812df8fd22499 (diff) | |
| parent | 061ec365a8850d140aa5069fc7d2a4c380be4752 (diff) | |
Merge pull request #11916 from JosJuice/ppcanalyst-reorder-loop
PPCAnalyst: Reduce number of iterations in ReorderInstructionsCore
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/PowerPC/PPCAnalyst.cpp | 92 |
1 files changed, 57 insertions, 35 deletions
diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 34501a5bbe..8e6a1eee00 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -470,52 +470,74 @@ static bool isCror(const CodeOp& a) void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse, ReorderType type) const { - // Bubbling an instruction sometimes reveals another opportunity to bubble an instruction, so do - // multiple passes. + // Instruction Reordering Pass + // 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) { - // Instruction Reordering Pass - // 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) + if (go_backwards) + { + i -= increment; + go_backwards = false; + } + else + { + i = next; + 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]))) { - 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 (type == ReorderType::Carry && i != start) + // if we read the CA flag, and the previous instruction sets it, don't move away. + 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)) { - // if we read the CA flag, and the previous instruction sets it, don't move away. - 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; + continue; } + } + + if (CanSwapAdjacentOps(a, b)) + { + // Alright, let's bubble it! + std::swap(a, b); - if (CanSwapAdjacentOps(a, b)) + if (i != start) { - // Alright, let's bubble it! - std::swap(a, b); - swapped = true; + // 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; } } |
