aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/CodeGen/RegisterAllocators
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/CodeGen/RegisterAllocators')
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs21
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs11
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs98
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs36
4 files changed, 89 insertions, 77 deletions
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
index 65901e80..417f3bae 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
@@ -2,6 +2,9 @@ using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
+using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+
namespace ARMeilleure.CodeGen.RegisterAllocators
{
class CopyResolver
@@ -133,14 +136,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static void EmitCopy(List<Operation> sequence, Operand x, Operand y)
{
- sequence.Add(new Operation(Instruction.Copy, x, y));
+ sequence.Add(Operation(Instruction.Copy, x, y));
}
private static void EmitXorSwap(List<Operation> sequence, Operand x, Operand y)
{
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, y, y, x));
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, y, y, x));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
}
}
@@ -194,20 +197,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Operand register = GetRegister(right.Register, type);
- Operand offset = new Operand(left.SpillOffset);
+ Operand offset = Const(left.SpillOffset);
- _fillQueue.Enqueue(new Operation(Instruction.Fill, register, offset));
+ _fillQueue.Enqueue(Operation(Instruction.Fill, register, offset));
HasCopy = true;
}
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
{
- Operand offset = new Operand(right.SpillOffset);
+ Operand offset = Const(right.SpillOffset);
Operand register = GetRegister(left.Register, type);
- _spillQueue.Enqueue(new Operation(Instruction.Spill, null, offset, register));
+ _spillQueue.Enqueue(Operation(Instruction.Spill, null, offset, register));
HasCopy = true;
}
@@ -240,7 +243,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetRegister(Register reg, OperandType type)
{
- return new Operand(reg.Index, reg.Type, type);
+ return Register(reg.Index, reg.Type, type);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
index ce7936f9..21470a66 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
@@ -1,10 +1,11 @@
-using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Numerics;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -265,7 +266,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
node.SetSource(srcIndex, temp);
}
- Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset));
+ Operation fillOp = Operation(Instruction.Fill, temp, Const(info.SpillOffset));
block.Operations.AddBefore(node, fillOp);
}
@@ -317,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (info.IsBlockLocal && mask != 0)
{
- int selectedReg = BitUtils.LowestBitSet(mask);
+ int selectedReg = BitOperations.TrailingZeroCount(mask);
info.Register = selectedReg;
@@ -363,7 +364,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
node.SetDestination(dstIndex, temp);
- Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
+ Operation spillOp = Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
block.Operations.AddAfter(node, spillOp);
@@ -415,7 +416,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetSpillTemp(Operand local, int freeMask, ref int useMask)
{
- int selectedReg = BitUtils.LowestBitSet(freeMask & ~useMask);
+ int selectedReg = BitOperations.TrailingZeroCount(freeMask & ~useMask);
useMask |= 1 << selectedReg;
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
index 1dc6ad73..01bb9554 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Numerics;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -32,7 +33,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private int _operationsCount;
- private class AllocationContext
+ private class AllocationContext : IDisposable
{
public RegisterMasks Masks { get; }
@@ -49,8 +50,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
StackAlloc = stackAlloc;
Masks = masks;
- Active = new BitMap(intervalsCount);
- Inactive = new BitMap(intervalsCount);
+ Active = BitMapPool.Allocate(intervalsCount);
+ Inactive = BitMapPool.Allocate(intervalsCount);
}
public void MoveActiveToInactive(int bit)
@@ -69,6 +70,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
dest.Set(bit);
}
+
+ public void Dispose()
+ {
+ BitMapPool.Release();
+ }
}
public AllocationResult RunPass(
@@ -121,10 +127,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
InsertSplitCopies();
InsertSplitCopiesAtEdges(cfg);
- return new AllocationResult(
+ AllocationResult result = new AllocationResult(
context.IntUsedRegisters,
context.VecUsedRegisters,
context.StackAlloc.TotalSize);
+
+ context.Dispose();
+
+ return result;
}
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
@@ -618,15 +628,22 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
bool hasSingleOrNoSuccessor = block.Next == null || block.Branch == null;
- foreach (BasicBlock successor in Successors(block))
+ for (int i = 0; i < 2; i++)
{
+ // This used to use an enumerable, but it ended up generating a lot of garbage, so now it is a loop.
+ BasicBlock successor = (i == 0) ? block.Next : block.Branch;
+ if (successor == null)
+ {
+ continue;
+ }
+
int succIndex = successor.Index;
// If the current node is a split node, then the actual successor node
// (the successor before the split) should be right after it.
if (IsSplitEdgeBlock(successor))
{
- succIndex = Successors(successor).First().Index;
+ succIndex = FirstSuccessor(successor).Index;
}
CopyResolver copyResolver = new CopyResolver();
@@ -699,8 +716,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Operand register = GetRegister(current);
- foreach (int usePosition in current.UsePositions())
+ IList<int> usePositions = current.UsePositions();
+ for (int i = usePositions.Count - 1; i >= 0; i--)
{
+ int usePosition = -usePositions[i];
(_, Node operation) = GetOperationNode(usePosition);
for (int index = 0; index < operation.SourcesCount; index++)
@@ -743,7 +762,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
- return new Operand(
+ return OperandHelper.Register(
interval.Register.Index,
interval.Register.Type,
interval.Local.Type);
@@ -778,8 +797,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
_operationNodes.Add((block.Operations, node));
- foreach (Operand dest in Destinations(node))
+ for (int i = 0; i < node.DestinationsCount; i++)
{
+ Operand dest = node.GetDestination(i);
if (dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
{
dest.NumberLocal(_intervals.Count);
@@ -815,12 +835,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// Compute local live sets.
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{
- BitMap liveGen = new BitMap(mapSize);
- BitMap liveKill = new BitMap(mapSize);
+ BitMap liveGen = BitMapPool.Allocate(mapSize);
+ BitMap liveKill = BitMapPool.Allocate(mapSize);
for (Node node = block.Operations.First; node != null; node = node.ListNext)
{
- foreach (Operand source in Sources(node))
+ Sources(node, (source) =>
{
int id = GetOperandId(source);
@@ -828,10 +848,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
liveGen.Set(id);
}
- }
+ });
- foreach (Operand dest in Destinations(node))
+ for (int i = 0; i < node.DestinationsCount; i++)
{
+ Operand dest = node.GetDestination(i);
liveKill.Set(GetOperandId(dest));
}
}
@@ -846,8 +867,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
for (int index = 0; index < cfg.Blocks.Count; index++)
{
- blkLiveIn [index] = new BitMap(mapSize);
- blkLiveOut[index] = new BitMap(mapSize);
+ blkLiveIn [index] = BitMapPool.Allocate(mapSize);
+ blkLiveOut[index] = BitMapPool.Allocate(mapSize);
}
bool modified;
@@ -862,12 +883,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
BitMap liveOut = blkLiveOut[block.Index];
- foreach (BasicBlock successor in Successors(block))
+ if ((block.Next != null && liveOut.Set(blkLiveIn[block.Next.Index])) ||
+ (block.Branch != null && liveOut.Set(blkLiveIn[block.Branch.Index])))
{
- if (liveOut.Set(blkLiveIn[successor.Index]))
- {
- modified = true;
- }
+ modified = true;
}
BitMap liveIn = blkLiveIn[block.Index];
@@ -920,21 +939,22 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
operationPos -= InstructionGap;
- foreach (Operand dest in Destinations(node))
+ for (int i = 0; i < node.DestinationsCount; i++)
{
+ Operand dest = node.GetDestination(i);
LiveInterval interval = _intervals[GetOperandId(dest)];
interval.SetStart(operationPos + 1);
interval.AddUsePosition(operationPos + 1);
}
- foreach (Operand source in Sources(node))
+ Sources(node, (source) =>
{
LiveInterval interval = _intervals[GetOperandId(source)];
interval.AddRange(blockStart, operationPos + 1);
interval.AddUsePosition(operationPos);
- }
+ });
if (node is Operation operation && operation.Instruction == Instruction.Call)
{
@@ -949,7 +969,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
while (mask != 0)
{
- int regIndex = BitUtils.LowestBitSet(mask);
+ int regIndex = BitOperations.TrailingZeroCount(mask);
Register callerSavedReg = new Register(regIndex, regType);
@@ -982,17 +1002,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return (register.Index << 1) | (register.Type == RegisterType.Vector ? 1 : 0);
}
- private static IEnumerable<BasicBlock> Successors(BasicBlock block)
+ private static BasicBlock FirstSuccessor(BasicBlock block)
{
- if (block.Next != null)
- {
- yield return block.Next;
- }
-
- if (block.Branch != null)
- {
- yield return block.Branch;
- }
+ return block.Next ?? block.Branch;
}
private static IEnumerable<Node> BottomOperations(BasicBlock block)
@@ -1007,15 +1019,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- private static IEnumerable<Operand> Destinations(Node node)
- {
- for (int index = 0; index < node.DestinationsCount; index++)
- {
- yield return node.GetDestination(index);
- }
- }
-
- private static IEnumerable<Operand> Sources(Node node)
+ private static void Sources(Node node, Action<Operand> action)
{
for (int index = 0; index < node.SourcesCount; index++)
{
@@ -1023,7 +1027,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (IsLocalOrRegister(source.Kind))
{
- yield return source;
+ action(source);
}
else if (source.Kind == OperandKind.Memory)
{
@@ -1031,12 +1035,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (memOp.BaseAddress != null)
{
- yield return memOp.BaseAddress;
+ action(memOp.BaseAddress);
}
if (memOp.Index != null)
{
- yield return memOp.Index;
+ action(memOp.Index);
}
}
}
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
index 18858a76..6e786061 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
@@ -1,3 +1,4 @@
+using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
@@ -12,7 +13,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private LiveInterval _parent;
- private SortedSet<int> _usePositions;
+ private SortedIntegerList _usePositions;
public int UsesCount => _usePositions.Count;
@@ -38,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Local = local;
_parent = parent ?? this;
- _usePositions = new SortedSet<int>();
+ _usePositions = new SortedIntegerList();
_ranges = new List<LiveRange>();
@@ -196,7 +197,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public void AddUsePosition(int position)
{
- _usePositions.Add(position);
+ // Inserts are in descending order, but ascending is faster for SortedIntegerList<>.
+ // We flip the ordering, then iterate backwards when using the final list.
+ _usePositions.Add(-position);
}
public bool Overlaps(int position)
@@ -247,9 +250,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return _childs.Values;
}
- public IEnumerable<int> UsePositions()
+ public IList<int> UsePositions()
{
- return _usePositions;
+ return _usePositions.GetList();
}
public int FirstUse()
@@ -259,20 +262,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return NotFound;
}
- return _usePositions.First();
+ return -_usePositions.Last();
}
public int NextUseAfter(int position)
{
- foreach (int usePosition in _usePositions)
- {
- if (usePosition >= position)
- {
- return usePosition;
- }
- }
+ int index = _usePositions.FindLessEqualIndex(-position);
+ return (index >= 0) ? -_usePositions[index] : NotFound;
+ }
- return NotFound;
+ public void RemoveAfter(int position)
+ {
+ int index = _usePositions.FindLessEqualIndex(-position);
+ _usePositions.RemoveRange(0, index + 1);
}
public LiveInterval Split(int position)
@@ -311,12 +313,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_ranges.RemoveRange(splitIndex, count);
}
- foreach (int usePosition in _usePositions.Where(x => x >= position))
+ int addAfter = _usePositions.FindLessEqualIndex(-position);
+ for (int index = addAfter; index >= 0; index--)
{
+ int usePosition = _usePositions[index];
right._usePositions.Add(usePosition);
}
- _usePositions.RemoveWhere(x => x >= position);
+ RemoveAfter(position);
Debug.Assert(_ranges.Count != 0, "Left interval is empty after split.");