diff options
| author | Ficture Seven <FICTURE7@gmail.com> | 2020-06-18 07:37:21 +0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-18 13:37:21 +1000 |
| commit | 2421186d974446ef4183420c50bc37e58d9fe213 (patch) | |
| tree | e182d974bc8dde8c6dcb206936cd2c4146f2f736 /ARMeilleure/Decoders/Optimizations | |
| parent | 5e724cf24e3d696b95be859c055a617e5d37bf80 (diff) | |
Generalize tail continues (#1298)
* Generalize tail continues
* Fix DecodeBasicBlock
`Next` and `Branch` would be null, which is not the state expected by
the branch instructions. They end up branching or falling into a block
which is never populated by the `Translator`. This causes an assert to
be fired when building the CFG.
* Clean up Decode overloads
* Do not synchronize when branching into exit block
If we're branching into an exit block, that exit block will tail
continue into another translation which already has a synchronization.
* Remove A32 predicate tail continue
If `block` is not an exit block then the `block.Next` must exist (as
per the last instruction of `block`).
* Throw if decoded 0 blocks
Address gdkchan's feedback
* Rebuild block list instead of setting to null
Address gdkchan's feedback
Diffstat (limited to 'ARMeilleure/Decoders/Optimizations')
| -rw-r--r-- | ARMeilleure/Decoders/Optimizations/TailCallRemover.cs | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/ARMeilleure/Decoders/Optimizations/TailCallRemover.cs b/ARMeilleure/Decoders/Optimizations/TailCallRemover.cs index 2d6439ba..e64f9a54 100644 --- a/ARMeilleure/Decoders/Optimizations/TailCallRemover.cs +++ b/ARMeilleure/Decoders/Optimizations/TailCallRemover.cs @@ -1,16 +1,15 @@ -using ARMeilleure.Decoders; -using System; +using System; using System.Collections.Generic; namespace ARMeilleure.Decoders.Optimizations { static class TailCallRemover { - public static void RunPass(ulong entryAddress, List<Block> blocks) + public static Block[] RunPass(ulong entryAddress, List<Block> blocks) { // Detect tail calls: // - Assume this function spans the space covered by contiguous code blocks surrounding the entry address. - // - Unconditional jump to an area outside this contiguous region will be treated as a tail call. + // - A jump to an area outside this contiguous region will be treated as an exit block. // - Include a small allowance for jumps outside the contiguous range. if (!Decoder.BinarySearch(blocks, entryAddress, out int entryBlockId)) @@ -19,57 +18,72 @@ namespace ARMeilleure.Decoders.Optimizations } const ulong allowance = 4; + Block entryBlock = blocks[entryBlockId]; - int startBlockIndex = entryBlockId; + Block startBlock = entryBlock; - int endBlockIndex = entryBlockId; - Block endBlock = entryBlock; + Block endBlock = entryBlock; + + int startBlockIndex = entryBlockId; + int endBlockIndex = entryBlockId; for (int i = entryBlockId + 1; i < blocks.Count; i++) // Search forwards. { Block block = blocks[i]; + if (endBlock.EndAddress < block.Address - allowance) { break; // End of contiguous function. } - endBlock = block; + endBlock = block; endBlockIndex = i; } for (int i = entryBlockId - 1; i >= 0; i--) // Search backwards. { Block block = blocks[i]; + if (startBlock.Address > block.EndAddress + allowance) { break; // End of contiguous function. } - startBlock = block; + startBlock = block; startBlockIndex = i; } if (startBlockIndex == 0 && endBlockIndex == blocks.Count - 1) { - return; // Nothing to do here. + return blocks.ToArray(); // Nothing to do here. } - - // Replace all branches to blocks outside the range with null, and force a tail call. - + + // Mark branches outside of contiguous region as exit blocks. for (int i = startBlockIndex; i <= endBlockIndex; i++) { Block block = blocks[i]; + if (block.Branch != null && (block.Branch.Address > endBlock.EndAddress || block.Branch.EndAddress < startBlock.Address)) { - block.Branch = null; - block.TailCall = true; + block.Branch.Exit = true; + block.Branch.TailCall = true; } } - // Finally, delete all blocks outside the contiguous range. + var newBlocks = new List<Block>(blocks.Count); + + // Finally, rebuild decoded block list, ignoring blocks outside the contiguous range. + for (int i = 0; i < blocks.Count; i++) + { + Block block = blocks[i]; + + if (block.Exit || (i >= startBlockIndex && i <= endBlockIndex)) + { + newBlocks.Add(block); + } + } - blocks.RemoveRange(endBlockIndex + 1, (blocks.Count - endBlockIndex) - 1); - blocks.RemoveRange(0, startBlockIndex); + return newBlocks.ToArray(); } } } |
