aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/IntermediateRepresentation/Operation.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/IntermediateRepresentation/Operation.cs')
-rw-r--r--ARMeilleure/IntermediateRepresentation/Operation.cs384
1 files changed, 332 insertions, 52 deletions
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