diff options
Diffstat (limited to 'ARMeilleure/IntermediateRepresentation')
15 files changed, 989 insertions, 715 deletions
diff --git a/ARMeilleure/IntermediateRepresentation/BasicBlock.cs b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs index 056a9d46..7cee52e5 100644 --- a/ARMeilleure/IntermediateRepresentation/BasicBlock.cs +++ b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs @@ -1,37 +1,47 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace ARMeilleure.IntermediateRepresentation { - class BasicBlock : IIntrusiveListNode<BasicBlock> + class BasicBlock : IEquatable<BasicBlock>, IIntrusiveListNode<BasicBlock> { - private readonly List<BasicBlock> _successors; + private const uint MaxSuccessors = 2; - public int Index { get; set; } + private int _succCount; + private BasicBlock _succ0; + private BasicBlock _succ1; + private HashSet<BasicBlock> _domFrontiers; + public int Index { get; set; } public BasicBlockFrequency Frequency { get; set; } - public BasicBlock ListPrevious { get; set; } public BasicBlock ListNext { get; set; } - - public IntrusiveList<Node> Operations { get; } - + public IntrusiveList<Operation> Operations { get; } public List<BasicBlock> Predecessors { get; } - - public HashSet<BasicBlock> DominanceFrontiers { get; } public BasicBlock ImmediateDominator { get; set; } - public int SuccessorCount => _successors.Count; + public int SuccessorsCount => _succCount; + + public HashSet<BasicBlock> DominanceFrontiers + { + get + { + if (_domFrontiers == null) + { + _domFrontiers = new HashSet<BasicBlock>(); + } + + return _domFrontiers; + } + } public BasicBlock() : this(index: -1) { } public BasicBlock(int index) { - _successors = new List<BasicBlock>(); - - Operations = new IntrusiveList<Node>(); + Operations = new IntrusiveList<Operation>(); Predecessors = new List<BasicBlock>(); - DominanceFrontiers = new HashSet<BasicBlock>(); Index = index; } @@ -40,54 +50,92 @@ namespace ARMeilleure.IntermediateRepresentation { if (block == null) { - throw new ArgumentNullException(nameof(block)); + ThrowNull(nameof(block)); + } + + if ((uint)_succCount + 1 > MaxSuccessors) + { + ThrowSuccessorOverflow(); } block.Predecessors.Add(this); - _successors.Add(block); + GetSuccessorUnsafe(_succCount++) = block; } public void RemoveSuccessor(int index) { - BasicBlock oldBlock = _successors[index]; + if ((uint)index >= (uint)_succCount) + { + ThrowOutOfRange(nameof(index)); + } + + ref BasicBlock oldBlock = ref GetSuccessorUnsafe(index); oldBlock.Predecessors.Remove(this); + oldBlock = null; + + if (index == 0) + { + _succ0 = _succ1; + } - _successors.RemoveAt(index); + _succCount--; } public BasicBlock GetSuccessor(int index) { - return _successors[index]; + if ((uint)index >= (uint)_succCount) + { + ThrowOutOfRange(nameof(index)); + } + + return GetSuccessorUnsafe(index); + } + + private ref BasicBlock GetSuccessorUnsafe(int index) + { + return ref Unsafe.Add(ref _succ0, index); } public void SetSuccessor(int index, BasicBlock block) { if (block == null) { - throw new ArgumentNullException(nameof(block)); + ThrowNull(nameof(block)); } - BasicBlock oldBlock = _successors[index]; + if ((uint)index >= (uint)_succCount) + { + ThrowOutOfRange(nameof(index)); + } + + ref BasicBlock oldBlock = ref GetSuccessorUnsafe(index); oldBlock.Predecessors.Remove(this); block.Predecessors.Add(this); - - _successors[index] = block; + + oldBlock = block; } - public void Append(Node node) + public void Append(Operation node) { - var lastOp = Operations.Last as Operation; + Operation last = Operations.Last; // Append node before terminal or to end if no terminal. - switch (lastOp?.Instruction) + if (last == default) + { + Operations.AddLast(node); + + return; + } + + switch (last.Instruction) { case Instruction.Return: case Instruction.Tailcall: case Instruction.BranchIf: - Operations.AddBefore(lastOp, node); + Operations.AddBefore(last, node); break; default: @@ -96,9 +144,23 @@ namespace ARMeilleure.IntermediateRepresentation } } - public Node GetLastOp() + private static void ThrowNull(string name) => throw new ArgumentNullException(name); + private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); + private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors."); + + public bool Equals(BasicBlock other) + { + return other == this; + } + + public override bool Equals(object obj) + { + return Equals(obj as BasicBlock); + } + + public override int GetHashCode() { - return Operations.Last; + return base.GetHashCode(); } } }
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/IIntrusiveListNode.cs b/ARMeilleure/IntermediateRepresentation/IIntrusiveListNode.cs index 797e7891..caa9b83f 100644 --- a/ARMeilleure/IntermediateRepresentation/IIntrusiveListNode.cs +++ b/ARMeilleure/IntermediateRepresentation/IIntrusiveListNode.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.IntermediateRepresentation { - interface IIntrusiveListNode<T> where T : class + interface IIntrusiveListNode<T> { T ListPrevious { get; set; } T ListNext { get; set; } diff --git a/ARMeilleure/IntermediateRepresentation/Instruction.cs b/ARMeilleure/IntermediateRepresentation/Instruction.cs index 938a528d..b675ed1c 100644 --- a/ARMeilleure/IntermediateRepresentation/Instruction.cs +++ b/ARMeilleure/IntermediateRepresentation/Instruction.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.IntermediateRepresentation { - enum Instruction + enum Instruction : ushort { Add, BitwiseAnd, @@ -63,6 +63,7 @@ namespace ARMeilleure.IntermediateRepresentation Extended, Fill, LoadFromContext, + Phi, Spill, SpillArg, StoreToContext diff --git a/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs index 1ddf93e5..f5c5f3d7 100644 --- a/ARMeilleure/IntermediateRepresentation/Intrinsic.cs +++ b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.IntermediateRepresentation { - enum Intrinsic + enum Intrinsic : ushort { X86Addpd, X86Addps, diff --git a/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs b/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs deleted file mode 100644 index 34781b70..00000000 --- a/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ARMeilleure.IntermediateRepresentation -{ - class IntrinsicOperation : Operation - { - public Intrinsic Intrinsic { get; } - - public IntrinsicOperation(Intrinsic intrin, Operand dest, params Operand[] sources) : base(Instruction.Extended, dest, sources) - { - Intrinsic = intrin; - } - } -}
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs b/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs index a7b0f7a7..184df87c 100644 --- a/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs +++ b/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs @@ -1,4 +1,6 @@ -using System.Diagnostics; +using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; namespace ARMeilleure.IntermediateRepresentation @@ -7,7 +9,7 @@ namespace ARMeilleure.IntermediateRepresentation /// Represents a efficient linked list that stores the pointer on the object directly and does not allocate. /// </summary> /// <typeparam name="T">Type of the list items</typeparam> - class IntrusiveList<T> where T : class, IIntrusiveListNode<T> + class IntrusiveList<T> where T : IEquatable<T>, IIntrusiveListNode<T> { /// <summary> /// First item of the list, or null if empty. @@ -25,21 +27,33 @@ namespace ARMeilleure.IntermediateRepresentation public int Count { get; private set; } /// <summary> + /// Initializes a new instance of the <see cref="IntrusiveList{T}"/> class. + /// </summary> + /// <exception cref="ArgumentException"><typeparamref name="T"/> is not pointer sized.</exception> + public IntrusiveList() + { + if (Unsafe.SizeOf<T>() != IntPtr.Size) + { + throw new ArgumentException("T must be a reference type or a pointer sized struct."); + } + } + + /// <summary> /// Adds a item as the first item of the list. /// </summary> /// <param name="newNode">Item to be added</param> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddFirst(T newNode) + public T AddFirst(T newNode) { - if (First != null) + if (!EqualsNull(First)) { - AddBefore(First, newNode); + return AddBefore(First, newNode); } else { - Debug.Assert(newNode.ListPrevious == null); - Debug.Assert(newNode.ListNext == null); - Debug.Assert(Last == null); + Debug.Assert(EqualsNull(newNode.ListPrevious)); + Debug.Assert(EqualsNull(newNode.ListNext)); + Debug.Assert(EqualsNull(Last)); First = newNode; Last = newNode; @@ -47,6 +61,8 @@ namespace ARMeilleure.IntermediateRepresentation Debug.Assert(Count == 0); Count = 1; + + return newNode; } } @@ -55,17 +71,17 @@ namespace ARMeilleure.IntermediateRepresentation /// </summary> /// <param name="newNode">Item to be added</param> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddLast(T newNode) + public T AddLast(T newNode) { - if (Last != null) + if (!EqualsNull(Last)) { - AddAfter(Last, newNode); + return AddAfter(Last, newNode); } else { - Debug.Assert(newNode.ListPrevious == null); - Debug.Assert(newNode.ListNext == null); - Debug.Assert(First == null); + Debug.Assert(EqualsNull(newNode.ListPrevious)); + Debug.Assert(EqualsNull(newNode.ListNext)); + Debug.Assert(EqualsNull(First)); First = newNode; Last = newNode; @@ -73,6 +89,8 @@ namespace ARMeilleure.IntermediateRepresentation Debug.Assert(Count == 0); Count = 1; + + return newNode; } } @@ -85,20 +103,20 @@ namespace ARMeilleure.IntermediateRepresentation [MethodImpl(MethodImplOptions.AggressiveInlining)] public T AddBefore(T node, T newNode) { - Debug.Assert(newNode.ListPrevious == null); - Debug.Assert(newNode.ListNext == null); + Debug.Assert(EqualsNull(newNode.ListPrevious)); + Debug.Assert(EqualsNull(newNode.ListNext)); newNode.ListPrevious = node.ListPrevious; newNode.ListNext = node; node.ListPrevious = newNode; - if (newNode.ListPrevious != null) + if (!EqualsNull(newNode.ListPrevious)) { newNode.ListPrevious.ListNext = newNode; } - if (First == node) + if (Equals(First, node)) { First = newNode; } @@ -117,20 +135,20 @@ namespace ARMeilleure.IntermediateRepresentation [MethodImpl(MethodImplOptions.AggressiveInlining)] public T AddAfter(T node, T newNode) { - Debug.Assert(newNode.ListPrevious == null); - Debug.Assert(newNode.ListNext == null); + Debug.Assert(EqualsNull(newNode.ListPrevious)); + Debug.Assert(EqualsNull(newNode.ListNext)); newNode.ListPrevious = node; newNode.ListNext = node.ListNext; node.ListNext = newNode; - if (newNode.ListNext != null) + if (!EqualsNull(newNode.ListNext)) { newNode.ListNext.ListPrevious = newNode; } - if (Last == node) + if (Equals(Last, node)) { Last = newNode; } @@ -147,32 +165,44 @@ namespace ARMeilleure.IntermediateRepresentation [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Remove(T node) { - if (node.ListPrevious != null) + if (!EqualsNull(node.ListPrevious)) { node.ListPrevious.ListNext = node.ListNext; } else { - Debug.Assert(First == node); + Debug.Assert(Equals(First, node)); First = node.ListNext; } - if (node.ListNext != null) + if (!EqualsNull(node.ListNext)) { node.ListNext.ListPrevious = node.ListPrevious; } else { - Debug.Assert(Last == node); + Debug.Assert(Equals(Last, node)); Last = node.ListPrevious; } - node.ListPrevious = null; - node.ListNext = null; + node.ListPrevious = default; + node.ListNext = default; Count--; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool EqualsNull(T a) + { + return EqualityComparer<T>.Default.Equals(a, default); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool Equals(T a, T b) + { + return EqualityComparer<T>.Default.Equals(a, b); + } } } diff --git a/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs index 56d07288..07d2633b 100644 --- a/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs +++ b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs @@ -1,29 +1,54 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + namespace ARMeilleure.IntermediateRepresentation { - class MemoryOperand : Operand + unsafe struct MemoryOperand { - public Operand BaseAddress { get; set; } - public Operand Index { get; set; } + private struct Data + { +#pragma warning disable CS0649 + public byte Kind; + public byte Type; +#pragma warning restore CS0649 + public byte Scale; + public Operand BaseAddress; + public Operand Index; + public int Displacement; + } + + private Data* _data; + + public MemoryOperand(Operand operand) + { + Debug.Assert(operand.Kind == OperandKind.Memory); + + _data = (Data*)Unsafe.As<Operand, IntPtr>(ref operand); + } - public Multiplier Scale { get; private set; } + public Operand BaseAddress + { + get => _data->BaseAddress; + set => _data->BaseAddress = value; + } - public int Displacement { get; private set; } + public Operand Index + { + get => _data->Index; + set => _data->Index = value; + } - public MemoryOperand() { } + public Multiplier Scale + { + get => (Multiplier)_data->Scale; + set => _data->Scale = (byte)value; + } - public MemoryOperand With( - OperandType type, - Operand baseAddress, - Operand index = null, - Multiplier scale = Multiplier.x1, - int displacement = 0) + public int Displacement { - With(OperandKind.Memory, type); - BaseAddress = baseAddress; - Index = index; - Scale = scale; - Displacement = displacement; - return this; + get => _data->Displacement; + set => _data->Displacement = value; } } }
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/Node.cs b/ARMeilleure/IntermediateRepresentation/Node.cs deleted file mode 100644 index 3f41d814..00000000 --- a/ARMeilleure/IntermediateRepresentation/Node.cs +++ /dev/null @@ -1,309 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ARMeilleure.IntermediateRepresentation -{ - class Node : IIntrusiveListNode<Node> - { - public Node ListPrevious { get; set; } - public Node ListNext { get; set; } - - public Operand Destination - { - get => _destinations.Count != 0 ? GetDestination(0) : null; - set => SetDestination(value); - } - - private readonly List<Operand> _destinations; - private readonly List<Operand> _sources; - private bool _clearedDest; - - public int DestinationsCount => _destinations.Count; - public int SourcesCount => _sources.Count; - - private void Resize(List<Operand> list, int size) - { - if (list.Count > size) - { - list.RemoveRange(size, list.Count - size); - } - else - { - while (list.Count < size) - { - list.Add(null); - } - } - } - - public Node() - { - _destinations = new List<Operand>(); - _sources = new List<Operand>(); - } - - public Node(Operand destination, int sourcesCount) : this() - { - Destination = destination; - - Resize(_sources, sourcesCount); - } - - private void Reset(int sourcesCount) - { - _clearedDest = true; - _sources.Clear(); - ListPrevious = null; - ListNext = null; - - Resize(_sources, sourcesCount); - } - - public Node With(Operand destination, int sourcesCount) - { - Reset(sourcesCount); - Destination = destination; - - return this; - } - - public Node With(Operand[] destinations, int sourcesCount) - { - Reset(sourcesCount); - SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations))); - - return this; - } - - public Operand GetDestination(int index) - { - return _destinations[index]; - } - - public Operand GetSource(int index) - { - return _sources[index]; - } - - public void SetDestination(int index, Operand destination) - { - if (!_clearedDest) - { - RemoveAssignment(_destinations[index]); - } - - AddAssignment(destination); - - _clearedDest = false; - - _destinations[index] = destination; - } - - public void SetSource(int index, Operand source) - { - RemoveUse(_sources[index]); - - AddUse(source); - - _sources[index] = source; - } - - private void RemoveOldDestinations() - { - if (!_clearedDest) - { - for (int index = 0; index < _destinations.Count; index++) - { - RemoveAssignment(_destinations[index]); - } - } - - _clearedDest = false; - } - - public void SetDestination(Operand destination) - { - RemoveOldDestinations(); - - if (destination == null) - { - _destinations.Clear(); - _clearedDest = true; - } - else - { - Resize(_destinations, 1); - - _destinations[0] = destination; - - AddAssignment(destination); - } - } - - public void SetDestinations(Operand[] destinations) - { - RemoveOldDestinations(); - - Resize(_destinations, destinations.Length); - - for (int index = 0; index < destinations.Length; index++) - { - Operand newOp = destinations[index]; - - _destinations[index] = newOp; - - AddAssignment(newOp); - } - } - - private void RemoveOldSources() - { - for (int index = 0; index < _sources.Count; index++) - { - RemoveUse(_sources[index]); - } - } - - public void SetSource(Operand source) - { - RemoveOldSources(); - - if (source == null) - { - _sources.Clear(); - } - else - { - Resize(_sources, 1); - - _sources[0] = source; - - AddUse(source); - } - } - - public void SetSources(Operand[] sources) - { - RemoveOldSources(); - - Resize(_sources, sources.Length); - - for (int index = 0; index < sources.Length; index++) - { - Operand newOp = sources[index]; - - _sources[index] = newOp; - - AddUse(newOp); - } - } - - private void AddAssignment(Operand op) - { - if (op == null) - { - return; - } - - if (op.Kind == OperandKind.LocalVariable) - { - op.Assignments.Add(this); - } - else if (op.Kind == OperandKind.Memory) - { - MemoryOperand memOp = (MemoryOperand)op; - - if (memOp.BaseAddress != null) - { - memOp.BaseAddress.Assignments.Add(this); - } - - if (memOp.Index != null) - { - memOp.Index.Assignments.Add(this); - } - } - } - - private void RemoveAssignment(Operand op) - { - if (op == null) - { - return; - } - - if (op.Kind == OperandKind.LocalVariable) - { - op.Assignments.Remove(this); - } - else if (op.Kind == OperandKind.Memory) - { - MemoryOperand memOp = (MemoryOperand)op; - - if (memOp.BaseAddress != null) - { - memOp.BaseAddress.Assignments.Remove(this); - } - - if (memOp.Index != null) - { - memOp.Index.Assignments.Remove(this); - } - } - } - - private void AddUse(Operand op) - { - if (op == null) - { - return; - } - - if (op.Kind == OperandKind.LocalVariable) - { - op.Uses.Add(this); - } - else if (op.Kind == OperandKind.Memory) - { - MemoryOperand memOp = (MemoryOperand)op; - - if (memOp.BaseAddress != null) - { - memOp.BaseAddress.Uses.Add(this); - } - - if (memOp.Index != null) - { - memOp.Index.Uses.Add(this); - } - } - } - - private void RemoveUse(Operand op) - { - if (op == null) - { - return; - } - - if (op.Kind == OperandKind.LocalVariable) - { - op.Uses.Remove(this); - } - else if (op.Kind == OperandKind.Memory) - { - MemoryOperand memOp = (MemoryOperand)op; - - if (memOp.BaseAddress != null) - { - memOp.BaseAddress.Uses.Remove(this); - } - - if (memOp.Index != null) - { - memOp.Index.Uses.Remove(this); - } - } - } - } -}
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs index 64df416f..2e0b649c 100644 --- a/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -1,3 +1,4 @@ +using ARMeilleure.Common; using ARMeilleure.Translation.PTC; using System; using System.Collections.Generic; @@ -6,94 +7,106 @@ using System.Runtime.CompilerServices; namespace ARMeilleure.IntermediateRepresentation { - class Operand + unsafe struct Operand : IEquatable<Operand> { - public OperandKind Kind { get; private set; } - public OperandType Type { get; private set; } - - public ulong Value { get; private set; } - - public List<Node> Assignments { get; } - public List<Node> Uses { get; } + internal struct Data + { + public byte Kind; + public byte Type; + public byte SymbolType; + public ushort AssignmentsCount; + public ushort AssignmentsCapacity; + public ushort UsesCount; + public ushort UsesCapacity; + public Operation* Assignments; + public Operation* Uses; + public ulong Value; + public ulong SymbolValue; + } - public Symbol Symbol { get; private set; } - public bool Relocatable => Symbol.Type != SymbolType.None; + private Data* _data; - public Operand() + public OperandKind Kind { - Assignments = new List<Node>(); - Uses = new List<Node>(); + get => (OperandKind)_data->Kind; + private set => _data->Kind = (byte)value; } - public Operand(OperandKind kind, OperandType type = OperandType.None) : this() + public OperandType Type { - Kind = kind; - Type = type; + get => (OperandType)_data->Type; + private set => _data->Type = (byte)value; } - public Operand With( - OperandKind kind, - OperandType type = OperandType.None, - ulong value = 0, - Symbol symbol = default) + public ulong Value { - Kind = kind; - Type = type; - - Value = value; + get => _data->Value; + private set => _data->Value = value; + } - Symbol = symbol; + public Symbol Symbol + { + get + { + Debug.Assert(Kind != OperandKind.Memory); - Assignments.Clear(); - Uses.Clear(); + return new Symbol((SymbolType)_data->SymbolType, _data->SymbolValue); + } + private set + { + Debug.Assert(Kind != OperandKind.Memory); - return this; + if (value.Type == SymbolType.None) + { + _data->SymbolType = (byte)SymbolType.None; + } + else + { + _data->SymbolType = (byte)value.Type; + _data->SymbolValue = value.Value; + } + } } - public Operand With(int value) + public ReadOnlySpan<Operation> Assignments { - return With(OperandKind.Constant, OperandType.I32, (uint)value); - } + get + { + Debug.Assert(Kind != OperandKind.Memory); - public Operand With(uint value) - { - return With(OperandKind.Constant, OperandType.I32, value); + return new ReadOnlySpan<Operation>(_data->Assignments, _data->AssignmentsCount); + } } - public Operand With(long value) + public ReadOnlySpan<Operation> Uses { - return With(OperandKind.Constant, OperandType.I64, (ulong)value); - } + get + { + Debug.Assert(Kind != OperandKind.Memory); - public Operand With(long value, Symbol symbol) - { - return With(OperandKind.Constant, OperandType.I64, (ulong)value, symbol); + return new ReadOnlySpan<Operation>(_data->Uses, _data->UsesCount); + } } - public Operand With(ulong value) - { - return With(OperandKind.Constant, OperandType.I64, value); - } + public int UsesCount => _data->UsesCount; + public int AssignmentsCount => _data->AssignmentsCount; - public Operand With(float value) - { - return With(OperandKind.Constant, OperandType.FP32, (ulong)BitConverter.SingleToInt32Bits(value)); - } + public bool Relocatable => Symbol.Type != SymbolType.None; - public Operand With(double value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Register GetRegister() { - return With(OperandKind.Constant, OperandType.FP64, (ulong)BitConverter.DoubleToInt64Bits(value)); - } + Debug.Assert(Kind == OperandKind.Register); - public Operand With(int index, RegisterType regType, OperandType type) - { - return With(OperandKind.Register, type, (ulong)((int)regType << 24 | index)); + return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Register GetRegister() + public MemoryOperand GetMemory() { - return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24)); + Debug.Assert(Kind == OperandKind.Memory); + + return new MemoryOperand(this); } public int GetLocalNumber() @@ -133,6 +146,11 @@ namespace ARMeilleure.IntermediateRepresentation return BitConverter.Int64BitsToDouble((long)Value); } + internal ref ulong GetValueUnsafe() + { + return ref _data->Value; + } + internal void NumberLocal(int number) { if (Kind != OperandKind.LocalVariable) @@ -143,6 +161,158 @@ namespace ARMeilleure.IntermediateRepresentation Value = (ulong)number; } + public void AddAssignment(Operation operation) + { + if (Kind == OperandKind.LocalVariable) + { + Add(operation, ref _data->Assignments, ref _data->AssignmentsCount, ref _data->AssignmentsCapacity); + } + else if (Kind == OperandKind.Memory) + { + MemoryOperand memOp = GetMemory(); + Operand addr = memOp.BaseAddress; + Operand index = memOp.Index; + + if (addr != default) + { + Add(operation, ref addr._data->Assignments, ref addr._data->AssignmentsCount, ref addr._data->AssignmentsCapacity); + } + + if (index != default) + { + Add(operation, ref index._data->Assignments, ref index._data->AssignmentsCount, ref index._data->AssignmentsCapacity); + } + } + } + + public void RemoveAssignment(Operation operation) + { + if (Kind == OperandKind.LocalVariable) + { + Remove(operation, ref _data->Assignments, ref _data->AssignmentsCount); + } + else if (Kind == OperandKind.Memory) + { + MemoryOperand memOp = GetMemory(); + Operand addr = memOp.BaseAddress; + Operand index = memOp.Index; + + if (addr != default) + { + Remove(operation, ref addr._data->Assignments, ref addr._data->AssignmentsCount); + } + + if (index != default) + { + Remove(operation, ref index._data->Assignments, ref index._data->AssignmentsCount); + } + } + } + + public void AddUse(Operation operation) + { + if (Kind == OperandKind.LocalVariable) + { + Add(operation, ref _data->Uses, ref _data->UsesCount, ref _data->UsesCapacity); + } + else if (Kind == OperandKind.Memory) + { + MemoryOperand memOp = GetMemory(); + Operand addr = memOp.BaseAddress; + Operand index = memOp.Index; + + if (addr != default) + { + Add(operation, ref addr._data->Uses, ref addr._data->UsesCount, ref addr._data->UsesCapacity); + } + + if (index != default) + { + Add(operation, ref index._data->Uses, ref index._data->UsesCount, ref index._data->UsesCapacity); + } + } + } + + public void RemoveUse(Operation operation) + { + if (Kind == OperandKind.LocalVariable) + { + Remove(operation, ref _data->Uses, ref _data->UsesCount); + } + else if (Kind == OperandKind.Memory) + { + MemoryOperand memOp = GetMemory(); + Operand addr = memOp.BaseAddress; + Operand index = memOp.Index; + + if (addr != default) + { + Remove(operation, ref addr._data->Uses, ref addr._data->UsesCount); + } + + if (index != default) + { + Remove(operation, ref index._data->Uses, ref index._data->UsesCount); + } + } + } + + private static void New<T>(ref T* data, ref ushort count, ref ushort capacity, ushort initialCapacity) where T : unmanaged + { + count = 0; + capacity = initialCapacity; + data = Allocators.References.Allocate<T>(initialCapacity); + } + + private static void Add<T>(T item, ref T* data, ref ushort count, ref ushort capacity) where T : unmanaged + { + if (count < capacity) + { + data[(uint)count++] = item; + + return; + } + + // Could not add item in the fast path, fallback onto the slow path. + ExpandAdd(item, ref data, ref count, ref capacity); + + static void ExpandAdd(T item, ref T* data, ref ushort count, ref ushort capacity) + { + ushort newCount = checked((ushort)(count + 1)); + ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue); + + var oldSpan = new Span<T>(data, count); + + capacity = newCapacity; + data = Allocators.References.Allocate<T>(capacity); + + oldSpan.CopyTo(new Span<T>(data, count)); + + data[count] = item; + count = newCount; + } + } + + private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged + { + var span = new Span<T>(data, count); + + for (int i = 0; i < span.Length; i++) + { + if (EqualityComparer<T>.Default.Equals(span[i], item)) + { + if (i + 1 < count) + { + span.Slice(i + 1).CopyTo(span.Slice(i)); + } + + count--; + + return; + } + } + } + public override int GetHashCode() { if (Kind == OperandKind.LocalVariable) @@ -154,5 +324,201 @@ namespace ARMeilleure.IntermediateRepresentation return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20); } } + + public bool Equals(Operand operand) + { + return operand._data == _data; + } + + public override bool Equals(object obj) + { + return obj is Operand operand && Equals(operand); + } + + public static bool operator ==(Operand a, Operand b) + { + return a.Equals(b); + } + + public static bool operator !=(Operand a, Operand b) + { + return !a.Equals(b); + } + + public static class Factory + { + private const int InternTableSize = 256; + private const int InternTableProbeLength = 8; + + [ThreadStatic] + private static Data* _internTable; + + private static Data* InternTable + { + get + { + if (_internTable == null) + { + _internTable = (Data*)NativeAllocator.Instance.Allocate((uint)sizeof(Data) * InternTableSize); + + // Make sure the table is zeroed. + new Span<Data>(_internTable, InternTableSize).Clear(); + } + + return _internTable; + } + } + + private static Operand Make(OperandKind kind, OperandType type, ulong value, Symbol symbol = default) + { + Debug.Assert(kind != OperandKind.None); + + Data* data = null; + + // If constant or register, then try to look up in the intern table before allocating. + if (kind == OperandKind.Constant || kind == OperandKind.Register) + { + uint hash = (uint)HashCode.Combine(kind, type, value); + + // Look in the next InternTableProbeLength slots for a match. + for (uint i = 0; i < InternTableProbeLength; i++) + { + Operand interned = new(); + interned._data = &InternTable[(hash + i) % InternTableSize]; + + // If slot matches the allocation request then return that slot. + if (interned.Kind == kind && interned.Type == type && interned.Value == value && interned.Symbol == symbol) + { + return interned; + } + // Otherwise if the slot is not occupied, we store in that slot. + else if (interned.Kind == OperandKind.None) + { + data = interned._data; + + break; + } + } + } + + // If we could not get a slot from the intern table, we allocate somewhere else and store there. + if (data == null) + { + data = Allocators.Operands.Allocate<Data>(); + } + + *data = default; + + Operand result = new(); + result._data = data; + result.Value = value; + result.Kind = kind; + result.Type = type; + + if (kind != OperandKind.Memory) + { + result.Symbol = symbol; + } + + // If local variable, then the use and def list is initialized with default sizes. + if (kind == OperandKind.LocalVariable) + { + New(ref result._data->Assignments, ref result._data->AssignmentsCount, ref result._data->AssignmentsCapacity, 1); + New(ref result._data->Uses, ref result._data->UsesCount, ref result._data->UsesCapacity, 4); + } + + return result; + } + + public static Operand Const(OperandType type, long value) + { + Debug.Assert(type is OperandType.I32 or OperandType.I64); + + return type == OperandType.I32 ? Const((int)value) : Const(value); + } + + public static Operand Const(bool value) + { + return Const(value ? 1 : 0); + } + + public static Operand Const(int value) + { + return Const((uint)value); + } + + public static Operand Const(uint value) + { + return Make(OperandKind.Constant, OperandType.I32, value); + } + + public static Operand Const(long value) + { + return Const(value, symbol: default); + } + + public static Operand Const<T>(ref T reference, Symbol symbol = default) + { + return Const((long)Unsafe.AsPointer(ref reference), symbol); + } + + public static Operand Const(long value, Symbol symbol) + { + return Make(OperandKind.Constant, OperandType.I64, (ulong)value, symbol); + } + + public static Operand Const(ulong value) + { + return Make(OperandKind.Constant, OperandType.I64, value); + } + + public static Operand ConstF(float value) + { + return Make(OperandKind.Constant, OperandType.FP32, (ulong)BitConverter.SingleToInt32Bits(value)); + } + + public static Operand ConstF(double value) + { + return Make(OperandKind.Constant, OperandType.FP64, (ulong)BitConverter.DoubleToInt64Bits(value)); + } + + public static Operand Label() + { + return Make(OperandKind.Label, OperandType.None, 0); + } + + public static Operand Local(OperandType type) + { + return Make(OperandKind.LocalVariable, type, 0); + } + + public static Operand Register(int index, RegisterType regType, OperandType type) + { + return Make(OperandKind.Register, type, (ulong)((int)regType << 24 | index)); + } + + public static Operand Undef() + { + return Make(OperandKind.Undefined, OperandType.None, 0); + } + + public static Operand MemoryOp( + OperandType type, + Operand baseAddress, + Operand index = default, + Multiplier scale = Multiplier.x1, + int displacement = 0) + { + Operand result = Make(OperandKind.Memory, type, 0); + + MemoryOperand memory = result.GetMemory(); + memory.BaseAddress = baseAddress; + memory.Index = index; + memory.Scale = scale; + memory.Displacement = displacement; + + return result; + } + } } }
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs deleted file mode 100644 index 420555a7..00000000 --- a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs +++ /dev/null @@ -1,119 +0,0 @@ -using ARMeilleure.Common; -using ARMeilleure.Translation.PTC; -using System.Runtime.CompilerServices; - -namespace ARMeilleure.IntermediateRepresentation -{ - static class OperandHelper - { - public static Operand Const(OperandType type, long value) - { - return type == OperandType.I32 ? Operand().With((int)value) : Operand().With(value); - } - - public static Operand Const(bool value) - { - return Operand().With(value ? 1 : 0); - } - - public static Operand Const(int value) - { - return Operand().With(value); - } - - public static Operand Const(uint value) - { - return Operand().With(value); - } - - public static Operand Const(long value) - { - return Operand().With(value); - } - - public static Operand Const(long value, Symbol symbol) - { - return Operand().With(value, symbol); - } - - public static Operand Const(ulong value) - { - return Operand().With(value); - } - - public static unsafe Operand Const<T>(ref T reference, Symbol symbol = default) - { - return Operand().With((long)Unsafe.AsPointer(ref reference), symbol); - } - - public static Operand ConstF(float value) - { - return Operand().With(value); - } - - public static Operand ConstF(double value) - { - return Operand().With(value); - } - - public static Operand Label() - { - return Operand().With(OperandKind.Label); - } - - public static Operand Local(OperandType type) - { - return Operand().With(OperandKind.LocalVariable, type); - } - - public static Operand Register(int index, RegisterType regType, OperandType type) - { - return Operand().With(index, regType, type); - } - - public static Operand Undef() - { - return Operand().With(OperandKind.Undefined); - } - - public static MemoryOperand MemoryOp( - OperandType type, - Operand baseAddress, - Operand index = null, - Multiplier scale = Multiplier.x1, - int displacement = 0) - { - return MemoryOperand().With(type, baseAddress, index, scale, displacement); - } - - #region "ThreadStaticPool" - public static void PrepareOperandPool(int groupId = 0) - { - ThreadStaticPool<Operand>.PreparePool(groupId, ChunkSizeLimit.Large); - ThreadStaticPool<MemoryOperand>.PreparePool(groupId, ChunkSizeLimit.Small); - } - - private static Operand Operand() - { - return ThreadStaticPool<Operand>.Instance.Allocate(); - } - - private static MemoryOperand MemoryOperand() - { - return ThreadStaticPool<MemoryOperand>.Instance.Allocate(); - } - - public static void ResetOperandPool(int groupId = 0) - { - ThreadStaticPool<MemoryOperand>.ResetPool(groupId); - ThreadStaticPool<Operand>.ResetPool(groupId); - } - - public static void DisposeOperandPools() - { - ThreadStaticPool<Operand>.DisposePools(); - ThreadStaticPool<MemoryOperand>.DisposePools(); - } - #endregion - } -} diff --git a/ARMeilleure/IntermediateRepresentation/OperandKind.cs b/ARMeilleure/IntermediateRepresentation/OperandKind.cs index 57618353..adb83561 100644 --- a/ARMeilleure/IntermediateRepresentation/OperandKind.cs +++ b/ARMeilleure/IntermediateRepresentation/OperandKind.cs @@ -2,6 +2,7 @@ namespace ARMeilleure.IntermediateRepresentation { enum OperandKind { + None, Constant, Label, LocalVariable, diff --git a/ARMeilleure/IntermediateRepresentation/Operation.cs b/ARMeilleure/IntermediateRepresentation/Operation.cs index 4cdbe326..08b874cf 100644 --- a/ARMeilleure/IntermediateRepresentation/Operation.cs +++ b/ARMeilleure/IntermediateRepresentation/Operation.cs @@ -1,89 +1,180 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + namespace ARMeilleure.IntermediateRepresentation { - class Operation : Node + unsafe struct Operation : IEquatable<Operation>, IIntrusiveListNode<Operation> { - public Instruction Instruction { get; private set; } + internal struct Data + { + public ushort Instruction; + public ushort Intrinsic; + public ushort SourcesCount; + public ushort DestinationsCount; + public Operation ListPrevious; + public Operation ListNext; + public Operand* Destinations; + public Operand* Sources; + } - public Operation() : base() { } + private Data* _data; - public Operation( - Instruction instruction, - Operand destination, - Operand[] sources) : base(destination, sources.Length) + public Instruction Instruction { - Instruction = instruction; + get => (Instruction)_data->Instruction; + private set => _data->Instruction = (ushort)value; + } - for (int index = 0; index < sources.Length; index++) - { - SetSource(index, sources[index]); - } + public Intrinsic Intrinsic + { + get => (Intrinsic)_data->Intrinsic; + private set => _data->Intrinsic = (ushort)value; } - public Operation With(Instruction instruction, Operand destination) + public Operation ListPrevious { - With(destination, 0); - Instruction = instruction; - return this; + get => _data->ListPrevious; + set => _data->ListPrevious = value; } - public Operation With(Instruction instruction, Operand destination, Operand[] sources) + public Operation ListNext { - With(destination, sources.Length); - Instruction = instruction; + get => _data->ListNext; + set => _data->ListNext = value; + } - for (int index = 0; index < sources.Length; index++) + public Operand Destination + { + get => _data->DestinationsCount != 0 ? GetDestination(0) : default; + set => SetDestination(value); + } + + public int DestinationsCount => _data->DestinationsCount; + public int SourcesCount => _data->SourcesCount; + + private Span<Operand> Destinations => new(_data->Destinations, _data->DestinationsCount); + private Span<Operand> Sources => new(_data->Sources, _data->SourcesCount); + + public PhiOperation AsPhi() + { + Debug.Assert(Instruction == Instruction.Phi); + + return new PhiOperation(this); + } + + public Operand GetDestination(int index) + { + return Destinations[index]; + } + + public Operand GetSource(int index) + { + return Sources[index]; + } + + public void SetDestination(int index, Operand dest) + { + ref Operand curDest = ref Destinations[index]; + + RemoveAssignment(curDest); + AddAssignment(dest); + + curDest = dest; + } + + public void SetSource(int index, Operand src) + { + ref Operand curSrc = ref Sources[index]; + + RemoveUse(curSrc); + AddUse(src); + + curSrc = src; + } + + private void RemoveOldDestinations() + { + for (int i = 0; i < _data->DestinationsCount; i++) { - SetSource(index, sources[index]); + RemoveAssignment(_data->Destinations[i]); } - return this; } - public Operation With(Instruction instruction, Operand destination, - Operand source0) + public void SetDestination(Operand dest) { - With(destination, 1); - Instruction = instruction; + RemoveOldDestinations(); + + if (dest == default) + { + _data->DestinationsCount = 0; + } + else + { + EnsureCapacity(ref _data->Destinations, ref _data->DestinationsCount, 1); + + _data->Destinations[0] = dest; - SetSource(0, source0); - return this; + AddAssignment(dest); + } } - public Operation With(Instruction instruction, Operand destination, - Operand source0, Operand source1) + public void SetDestinations(Operand[] dests) { - With(destination, 2); - Instruction = instruction; + RemoveOldDestinations(); + + EnsureCapacity(ref _data->Destinations, ref _data->DestinationsCount, dests.Length); + + for (int index = 0; index < dests.Length; index++) + { + Operand newOp = dests[index]; + + _data->Destinations[index] = newOp; - SetSource(0, source0); - SetSource(1, source1); - return this; + AddAssignment(newOp); + } } - public Operation With(Instruction instruction, Operand destination, - Operand source0, Operand source1, Operand source2) + private void RemoveOldSources() { - With(destination, 3); - Instruction = instruction; + for (int index = 0; index < _data->SourcesCount; index++) + { + RemoveUse(_data->Sources[index]); + } + } + + public void SetSource(Operand src) + { + RemoveOldSources(); - SetSource(0, source0); - SetSource(1, source1); - SetSource(2, source2); - return this; + if (src == default) + { + _data->SourcesCount = 0; + } + else + { + EnsureCapacity(ref _data->Sources, ref _data->SourcesCount, 1); + + _data->Sources[0] = src; + + AddUse(src); + } } - public Operation With( - Instruction instruction, - Operand[] destinations, - Operand[] sources) + public void SetSources(Operand[] srcs) { - With(destinations, sources.Length); - Instruction = instruction; + RemoveOldSources(); - for (int index = 0; index < sources.Length; index++) + EnsureCapacity(ref _data->Sources, ref _data->SourcesCount, srcs.Length); + + for (int index = 0; index < srcs.Length; index++) { - SetSource(index, sources[index]); + Operand newOp = srcs[index]; + + _data->Sources[index] = newOp; + + AddUse(newOp); } - return this; } public void TurnIntoCopy(Operand source) @@ -92,5 +183,194 @@ namespace ARMeilleure.IntermediateRepresentation SetSource(source); } + + private void AddAssignment(Operand op) + { + if (op != default) + { + op.AddAssignment(this); + } + } + + private void RemoveAssignment(Operand op) + { + if (op != default) + { + op.RemoveAssignment(this); + } + } + + private void AddUse(Operand op) + { + if (op != default) + { + op.AddUse(this); + } + } + + private void RemoveUse(Operand op) + { + if (op != default) + { + op.RemoveUse(this); + } + } + + public bool Equals(Operation operation) + { + return operation._data == _data; + } + + public override bool Equals(object obj) + { + return obj is Operation operation && Equals(operation); + } + + public override int GetHashCode() + { + return HashCode.Combine((IntPtr)_data); + } + + public static bool operator ==(Operation a, Operation b) + { + return a.Equals(b); + } + + public static bool operator !=(Operation a, Operation b) + { + return !a.Equals(b); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void EnsureCapacity(ref Operand* list, ref ushort capacity, int newCapacity) + { + if (newCapacity > ushort.MaxValue) + { + ThrowOverflow(newCapacity); + } + // We only need to allocate a new buffer if we're increasing the size. + else if (newCapacity > capacity) + { + list = Allocators.References.Allocate<Operand>((uint)newCapacity); + } + + capacity = (ushort)newCapacity; + } + + private static void ThrowOverflow(int count) => + throw new OverflowException($"Exceeded maximum size for Source or Destinations. Required {count}."); + + public static class Factory + { + private static Operation Make(Instruction inst, int destCount, int srcCount) + { + Data* data = Allocators.Operations.Allocate<Data>(); + *data = default; + + Operation result = new(); + result._data = data; + result.Instruction = inst; + + EnsureCapacity(ref result._data->Destinations, ref result._data->DestinationsCount, destCount); + EnsureCapacity(ref result._data->Sources, ref result._data->SourcesCount, srcCount); + + result.Destinations.Clear(); + result.Sources.Clear(); + + return result; + } + + public static Operation Operation(Instruction inst, Operand dest) + { + Operation result = Make(inst, 0, 0); + result.SetDestination(dest); + return result; + } + + public static Operation Operation(Instruction inst, Operand dest, Operand src0) + { + Operation result = Make(inst, 0, 1); + result.SetDestination(dest); + result.SetSource(0, src0); + return result; + } + + public static Operation Operation(Instruction inst, Operand dest, Operand src0, Operand src1) + { + Operation result = Make(inst, 0, 2); + result.SetDestination(dest); + result.SetSource(0, src0); + result.SetSource(1, src1); + return result; + } + + public static Operation Operation(Instruction inst, Operand dest, Operand src0, Operand src1, Operand src2) + { + Operation result = Make(inst, 0, 3); + result.SetDestination(dest); + result.SetSource(0, src0); + result.SetSource(1, src1); + result.SetSource(2, src2); + return result; + } + + public static Operation Operation(Instruction inst, Operand dest, int srcCount) + { + Operation result = Make(inst, 0, srcCount); + result.SetDestination(dest); + return result; + } + + public static Operation Operation(Instruction inst, Operand dest, Operand[] srcs) + { + Operation result = Make(inst, 0, srcs.Length); + + result.SetDestination(dest); + + for (int index = 0; index < srcs.Length; index++) + { + result.SetSource(index, srcs[index]); + } + + return result; + } + + public static Operation Operation(Intrinsic intrin, Operand dest, params Operand[] srcs) + { + Operation result = Make(Instruction.Extended, 0, srcs.Length); + + result.Intrinsic = intrin; + result.SetDestination(dest); + + for (int index = 0; index < srcs.Length; index++) + { + result.SetSource(index, srcs[index]); + } + + return result; + } + + public static Operation Operation(Instruction inst, Operand[] dests, Operand[] srcs) + { + Operation result = Make(inst, dests.Length, srcs.Length); + + for (int index = 0; index < dests.Length; index++) + { + result.SetDestination(index, dests[index]); + } + + for (int index = 0; index < srcs.Length; index++) + { + result.SetSource(index, srcs[index]); + } + + return result; + } + + public static Operation PhiOperation(Operand dest, int srcCount) + { + return Operation(Instruction.Phi, dest, srcCount * 2); + } + } } }
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/OperationHelper.cs b/ARMeilleure/IntermediateRepresentation/OperationHelper.cs deleted file mode 100644 index 0e560ee0..00000000 --- a/ARMeilleure/IntermediateRepresentation/OperationHelper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using ARMeilleure.Common; - -namespace ARMeilleure.IntermediateRepresentation -{ - static class OperationHelper - { - public static Operation Operation(Instruction instruction, Operand destination) - { - return Operation().With(instruction, destination); - } - - public static Operation Operation(Instruction instruction, Operand destination, - Operand[] sources) - { - return Operation().With(instruction, destination, sources); - } - - public static Operation Operation(Instruction instruction, Operand destination, - Operand source0) - { - return Operation().With(instruction, destination, source0); - } - - public static Operation Operation(Instruction instruction, Operand destination, - Operand source0, Operand source1) - { - return Operation().With(instruction, destination, source0, source1); - } - - public static Operation Operation(Instruction instruction, Operand destination, - Operand source0, Operand source1, Operand source2) - { - return Operation().With(instruction, destination, source0, source1, source2); - } - - public static Operation Operation( - Instruction instruction, - Operand[] destinations, - Operand[] sources) - { - return Operation().With(instruction, destinations, sources); - } - - #region "ThreadStaticPool" - public static void PrepareOperationPool(int groupId = 0) - { - ThreadStaticPool<Operation>.PreparePool(groupId, ChunkSizeLimit.Medium); - } - - private static Operation Operation() - { - return ThreadStaticPool<Operation>.Instance.Allocate(); - } - - public static void ResetOperationPool(int groupId = 0) - { - ThreadStaticPool<Operation>.ResetPool(groupId); - } - - public static void DisposeOperationPools() - { - ThreadStaticPool<Operation>.DisposePools(); - } - #endregion - } -} diff --git a/ARMeilleure/IntermediateRepresentation/PhiNode.cs b/ARMeilleure/IntermediateRepresentation/PhiNode.cs deleted file mode 100644 index 30fc4d38..00000000 --- a/ARMeilleure/IntermediateRepresentation/PhiNode.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace ARMeilleure.IntermediateRepresentation -{ - class PhiNode : Node - { - private BasicBlock[] _blocks; - - public PhiNode(Operand destination, int predecessorsCount) : base(destination, predecessorsCount) - { - _blocks = new BasicBlock[predecessorsCount]; - } - - public BasicBlock GetBlock(int index) - { - return _blocks[index]; - } - - public void SetBlock(int index, BasicBlock block) - { - _blocks[index] = block; - } - } -}
\ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/PhiOperation.cs b/ARMeilleure/IntermediateRepresentation/PhiOperation.cs new file mode 100644 index 00000000..f2430882 --- /dev/null +++ b/ARMeilleure/IntermediateRepresentation/PhiOperation.cs @@ -0,0 +1,37 @@ +using ARMeilleure.Translation; +using static ARMeilleure.IntermediateRepresentation.Operand.Factory; + +namespace ARMeilleure.IntermediateRepresentation +{ + struct PhiOperation + { + private readonly Operation _operation; + + public PhiOperation(Operation operation) + { + _operation = operation; + } + + public int SourcesCount => _operation.SourcesCount / 2; + + public BasicBlock GetBlock(ControlFlowGraph cfg, int index) + { + return cfg.PostOrderBlocks[cfg.PostOrderMap[_operation.GetSource(index * 2).AsInt32()]]; + } + + public void SetBlock(int index, BasicBlock block) + { + _operation.SetSource(index * 2, Const(block.Index)); + } + + public Operand GetSource(int index) + { + return _operation.GetSource(index * 2 + 1); + } + + public void SetSource(int index, Operand operand) + { + _operation.SetSource(index * 2 + 1, operand); + } + } +} |
