JIT: Coalesce copies on LSRA with simple register preferencing (#6950)
* JIT: Coalesce copies on LSRA with simple register preferencing * PPTC version bump
This commit is contained in:
parent
d25a084858
commit
0afa8f2c14
3 changed files with 56 additions and 6 deletions
|
@ -251,7 +251,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int selectedReg = GetHighestValueIndex(freePositions);
|
// If this is a copy destination variable, we prefer the register used for the copy source.
|
||||||
|
// If the register is available, then the copy can be eliminated later as both source
|
||||||
|
// and destination will use the same register.
|
||||||
|
int selectedReg;
|
||||||
|
|
||||||
|
if (current.TryGetCopySourceRegister(out int preferredReg) && freePositions[preferredReg] >= current.GetEnd())
|
||||||
|
{
|
||||||
|
selectedReg = preferredReg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedReg = GetHighestValueIndex(freePositions);
|
||||||
|
}
|
||||||
|
|
||||||
int selectedNextUse = freePositions[selectedReg];
|
int selectedNextUse = freePositions[selectedReg];
|
||||||
|
|
||||||
// Intervals starts and ends at odd positions, unless they span an entire
|
// Intervals starts and ends at odd positions, unless they span an entire
|
||||||
|
@ -431,7 +444,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetHighestValueIndex(Span<int> span)
|
private static int GetHighestValueIndex(ReadOnlySpan<int> span)
|
||||||
{
|
{
|
||||||
int highest = int.MinValue;
|
int highest = int.MinValue;
|
||||||
|
|
||||||
|
@ -798,12 +811,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
// The "visited" state is stored in the MSB of the local's value.
|
// The "visited" state is stored in the MSB of the local's value.
|
||||||
const ulong VisitedMask = 1ul << 63;
|
const ulong VisitedMask = 1ul << 63;
|
||||||
|
|
||||||
bool IsVisited(Operand local)
|
static bool IsVisited(Operand local)
|
||||||
{
|
{
|
||||||
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVisited(Operand local)
|
static void SetVisited(Operand local)
|
||||||
{
|
{
|
||||||
local.GetValueUnsafe() |= VisitedMask;
|
local.GetValueUnsafe() |= VisitedMask;
|
||||||
}
|
}
|
||||||
|
@ -826,9 +839,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
dest.NumberLocal(_intervals.Count);
|
dest.NumberLocal(_intervals.Count);
|
||||||
|
|
||||||
_intervals.Add(new LiveInterval(dest));
|
LiveInterval interval = new LiveInterval(dest);
|
||||||
|
_intervals.Add(interval);
|
||||||
|
|
||||||
SetVisited(dest);
|
SetVisited(dest);
|
||||||
|
|
||||||
|
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
||||||
|
// This is used for register preferencing later on, which allows the copy to be eliminated
|
||||||
|
// in some cases.
|
||||||
|
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
|
||||||
|
{
|
||||||
|
Operand source = node.GetSource(0);
|
||||||
|
|
||||||
|
if (source.Kind == OperandKind.LocalVariable &&
|
||||||
|
source.GetLocalNumber() > 0 &&
|
||||||
|
(node.Instruction == Instruction.Copy || source.Type == OperandType.I32))
|
||||||
|
{
|
||||||
|
interval.SetCopySource(_intervals[source.GetLocalNumber()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
public LiveRange CurrRange;
|
public LiveRange CurrRange;
|
||||||
|
|
||||||
public LiveInterval Parent;
|
public LiveInterval Parent;
|
||||||
|
public LiveInterval CopySource;
|
||||||
|
|
||||||
public UseList Uses;
|
public UseList Uses;
|
||||||
public LiveIntervalList Children;
|
public LiveIntervalList Children;
|
||||||
|
@ -37,6 +38,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
private ref LiveRange CurrRange => ref _data->CurrRange;
|
private ref LiveRange CurrRange => ref _data->CurrRange;
|
||||||
private ref LiveRange PrevRange => ref _data->PrevRange;
|
private ref LiveRange PrevRange => ref _data->PrevRange;
|
||||||
private ref LiveInterval Parent => ref _data->Parent;
|
private ref LiveInterval Parent => ref _data->Parent;
|
||||||
|
private ref LiveInterval CopySource => ref _data->CopySource;
|
||||||
private ref UseList Uses => ref _data->Uses;
|
private ref UseList Uses => ref _data->Uses;
|
||||||
private ref LiveIntervalList Children => ref _data->Children;
|
private ref LiveIntervalList Children => ref _data->Children;
|
||||||
|
|
||||||
|
@ -78,6 +80,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
Register = register;
|
Register = register;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetCopySource(LiveInterval copySource)
|
||||||
|
{
|
||||||
|
CopySource = copySource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetCopySourceRegister(out int copySourceRegIndex)
|
||||||
|
{
|
||||||
|
if (CopySource._data != null)
|
||||||
|
{
|
||||||
|
copySourceRegIndex = CopySource.Register.Index;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
copySourceRegIndex = 0;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
PrevRange = default;
|
PrevRange = default;
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 6634; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 6950; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
|
Loading…
Reference in a new issue