aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2024-06-19 09:39:29 -0300
committerGitHub <noreply@github.com>2024-06-19 09:39:29 -0300
commit0afa8f2c14f046b46ac5ba14c96f3a5ce523ba16 (patch)
tree406a8cde8e662d045f4a0dbfc1d37876a623fa9e
parentd25a084858438dd1188113efb76548916c2da9de (diff)
JIT: Coalesce copies on LSRA with simple register preferencing (#6950)1.1.1336
* JIT: Coalesce copies on LSRA with simple register preferencing * PPTC version bump
-rw-r--r--src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs39
-rw-r--r--src/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs21
-rw-r--r--src/ARMeilleure/Translation/PTC/Ptc.cs2
3 files changed, 56 insertions, 6 deletions
diff --git a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
index f156e088..16feeb91 100644
--- a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
+++ b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
@@ -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];
// 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;
@@ -798,12 +811,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// The "visited" state is stored in the MSB of the local's value.
const ulong VisitedMask = 1ul << 63;
- bool IsVisited(Operand local)
+ static bool IsVisited(Operand local)
{
return (local.GetValueUnsafe() & VisitedMask) != 0;
}
- void SetVisited(Operand local)
+ static void SetVisited(Operand local)
{
local.GetValueUnsafe() |= VisitedMask;
}
@@ -826,9 +839,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
dest.NumberLocal(_intervals.Count);
- _intervals.Add(new LiveInterval(dest));
+ LiveInterval interval = new LiveInterval(dest);
+ _intervals.Add(interval);
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()]);
+ }
+ }
}
}
}
diff --git a/src/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs b/src/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
index 333d3951..cfe1bc7c 100644
--- a/src/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
+++ b/src/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
@@ -19,6 +19,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public LiveRange CurrRange;
public LiveInterval Parent;
+ public LiveInterval CopySource;
public UseList Uses;
public LiveIntervalList Children;
@@ -37,6 +38,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private ref LiveRange CurrRange => ref _data->CurrRange;
private ref LiveRange PrevRange => ref _data->PrevRange;
private ref LiveInterval Parent => ref _data->Parent;
+ private ref LiveInterval CopySource => ref _data->CopySource;
private ref UseList Uses => ref _data->Uses;
private ref LiveIntervalList Children => ref _data->Children;
@@ -78,6 +80,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
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()
{
PrevRange = default;
diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs
index f56bdce1..c2eed7a5 100644
--- a/src/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/src/ARMeilleure/Translation/PTC/Ptc.cs
@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\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 BackupDir = "1";