Add an early TailMerge pass (#2721)

* Add an early `TailMerge` pass

Some translations can have a lot of guest calls and since for each guest
call there is a call guard which may return. This can produce a lot of
epilogue code for returns. This pass merges the epilogue into a single
block.

```
Using filter 'hcq'.
Using metric 'code size'.

Total diff: -1648111 (-7.19 %) (bytes):
  Base: 22913847
  Diff: 21265736

Improved: 4567, regressed: 14, unchanged: 144
```

* Set PTC version

* Address feedback

* Handle `void` returning functions

* Actually handle `void` returning functions

* Fix `RegisterToLocal` logging
This commit is contained in:
FICTURE7 2021-10-19 02:51:22 +04:00 committed by GitHub
parent d512ce122c
commit fbf40424f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 148 additions and 26 deletions

View file

@ -203,12 +203,18 @@ namespace ARMeilleure.Translation
// It always needs a context load as it is the first block to run.
if (block.Predecessors.Count == 0 || hasContextLoad)
{
arg = Local(OperandType.I64);
long vecMask = globalInputs[block.Index].VecMask;
long intMask = globalInputs[block.Index].IntMask;
Operation loadArg = block.Operations.AddFirst(Operation(Instruction.LoadArgument, arg, Const(0)));
if (vecMask != 0 || intMask != 0)
{
arg = Local(OperandType.I64);
LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector, mode, loadArg, arg);
LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer, mode, loadArg, arg);
Operation loadArg = block.Operations.AddFirst(Operation(Instruction.LoadArgument, arg, Const(0)));
LoadLocals(block, vecMask, RegisterType.Vector, mode, loadArg, arg);
LoadLocals(block, intMask, RegisterType.Integer, mode, loadArg, arg);
}
}
bool hasContextStore = HasContextStore(block);
@ -220,15 +226,21 @@ namespace ARMeilleure.Translation
if (EndsWithReturn(block) || hasContextStore)
{
if (arg == default)
long vecMask = globalOutputs[block.Index].VecMask;
long intMask = globalOutputs[block.Index].IntMask;
if (vecMask != 0 || intMask != 0)
{
arg = Local(OperandType.I64);
if (arg == default)
{
arg = Local(OperandType.I64);
block.Append(Operation(Instruction.LoadArgument, arg, Const(0)));
block.Append(Operation(Instruction.LoadArgument, arg, Const(0)));
}
StoreLocals(block, intMask, RegisterType.Integer, mode, arg);
StoreLocals(block, vecMask, RegisterType.Vector, mode, arg);
}
StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer, mode, arg);
StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector, mode, arg);
}
}
}