Refactoring and optimization on CPU translation (#661)

* Refactoring and optimization on CPU translation

* Remove now unused property

* Rename ilBlock -> block (local)

* Change equality comparison on RegisterMask for consistency

Co-Authored-By: gdkchan <gab.dark.100@gmail.com>

* Add back the aggressive inlining attribute to the Synchronize method

* Implement IEquatable on the Register struct

* Fix identation
This commit is contained in:
gdkchan 2019-04-26 01:55:12 -03:00 committed by jduncanator
parent 2b8eac1bce
commit 8a7d99cdea
48 changed files with 1257 additions and 1280 deletions

View file

@ -0,0 +1,122 @@
using ChocolArm64.State;
using System;
using System.Collections.Generic;
using static ChocolArm64.State.RegisterConsts;
namespace ChocolArm64.IntermediateRepresentation
{
class BasicBlock
{
public int Index { get; set; }
public RegisterMask RegInputs { get; private set; }
public RegisterMask RegOutputs { get; private set; }
public bool HasStateLoad { get; private set; }
private List<Operation> _operations;
public int Count => _operations.Count;
private BasicBlock _next;
private BasicBlock _branch;
public BasicBlock Next
{
get => _next;
set => _next = AddSuccessor(_next, value);
}
public BasicBlock Branch
{
get => _branch;
set => _branch = AddSuccessor(_branch, value);
}
public List<BasicBlock> Predecessors { get; }
public BasicBlock(int index = 0)
{
Index = index;
_operations = new List<Operation>();
Predecessors = new List<BasicBlock>();
}
private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock)
{
oldBlock?.Predecessors.Remove(this);
newBlock?.Predecessors.Add(this);
return newBlock;
}
public void Add(Operation operation)
{
if (operation.Type == OperationType.LoadLocal ||
operation.Type == OperationType.StoreLocal)
{
int index = operation.GetArg<int>(0);
if (IsRegIndex(index))
{
long intMask = 0;
long vecMask = 0;
switch (operation.GetArg<RegisterType>(1))
{
case RegisterType.Flag: intMask = (1L << RegsCount) << index; break;
case RegisterType.Int: intMask = 1L << index; break;
case RegisterType.Vector: vecMask = 1L << index; break;
}
RegisterMask mask = new RegisterMask(intMask, vecMask);
if (operation.Type == OperationType.LoadLocal)
{
RegInputs |= mask & ~RegOutputs;
}
else
{
RegOutputs |= mask;
}
}
}
else if (operation.Type == OperationType.LoadContext)
{
HasStateLoad = true;
}
operation.Parent = this;
_operations.Add(operation);
}
public static bool IsRegIndex(int index)
{
return (uint)index < RegsCount;
}
public Operation GetOperation(int index)
{
if ((uint)index >= _operations.Count)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _operations[index];
}
public Operation GetLastOp()
{
if (Count == 0)
{
return null;
}
return _operations[Count - 1];
}
}
}

View file

@ -0,0 +1,4 @@
namespace ChocolArm64.IntermediateRepresentation
{
class ILLabel { }
}

View file

@ -0,0 +1,112 @@
using ChocolArm64.State;
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace ChocolArm64.IntermediateRepresentation
{
class Operation
{
public BasicBlock Parent { get; set; }
public OperationType Type { get; }
private object[] _arguments { get; }
private Operation(OperationType type, params object[] arguments)
{
Type = type;
_arguments = arguments;
}
public T GetArg<T>(int index)
{
return (T)GetArg(index);
}
public object GetArg(int index)
{
if ((uint)index >= _arguments.Length)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _arguments[index];
}
public static Operation Call(MethodInfo info)
{
return new Operation(OperationType.Call, info);
}
public static Operation CallVirtual(MethodInfo info)
{
return new Operation(OperationType.CallVirtual, info);
}
public static Operation IL(OpCode ilOp)
{
return new Operation(OperationType.IL, ilOp);
}
public static Operation ILBranch(OpCode ilOp, ILLabel target)
{
return new Operation(OperationType.ILBranch, ilOp, target);
}
public static Operation LoadArgument(int index)
{
return new Operation(OperationType.LoadArgument, index);
}
public static Operation LoadConstant(int value)
{
return new Operation(OperationType.LoadConstant, value);
}
public static Operation LoadConstant(long value)
{
return new Operation(OperationType.LoadConstant, value);
}
public static Operation LoadConstant(float value)
{
return new Operation(OperationType.LoadConstant, value);
}
public static Operation LoadConstant(double value)
{
return new Operation(OperationType.LoadConstant, value);
}
public static Operation LoadContext()
{
return new Operation(OperationType.LoadContext);
}
public static Operation LoadField(FieldInfo info)
{
return new Operation(OperationType.LoadField, info);
}
public static Operation LoadLocal(int index, RegisterType type, RegisterSize size)
{
return new Operation(OperationType.LoadLocal, index, type, size);
}
public static Operation MarkLabel(ILLabel label)
{
return new Operation(OperationType.MarkLabel, label);
}
public static Operation StoreContext()
{
return new Operation(OperationType.StoreContext);
}
public static Operation StoreLocal(int index, RegisterType type, RegisterSize size)
{
return new Operation(OperationType.StoreLocal, index, type, size);
}
}
}

View file

@ -0,0 +1,18 @@
namespace ChocolArm64.IntermediateRepresentation
{
enum OperationType
{
Call,
CallVirtual,
IL,
ILBranch,
LoadArgument,
LoadConstant,
LoadContext,
LoadField,
LoadLocal,
MarkLabel,
StoreContext,
StoreLocal
}
}

View file

@ -0,0 +1,56 @@
using System;
namespace ChocolArm64.IntermediateRepresentation
{
struct RegisterMask : IEquatable<RegisterMask>
{
public long IntMask { get; set; }
public long VecMask { get; set; }
public RegisterMask(long intMask, long vecMask)
{
IntMask = intMask;
VecMask = vecMask;
}
public static RegisterMask operator &(RegisterMask x, RegisterMask y)
{
return new RegisterMask(x.IntMask & y.IntMask, x.VecMask & y.VecMask);
}
public static RegisterMask operator |(RegisterMask x, RegisterMask y)
{
return new RegisterMask(x.IntMask | y.IntMask, x.VecMask | y.VecMask);
}
public static RegisterMask operator ~(RegisterMask x)
{
return new RegisterMask(~x.IntMask, ~x.VecMask);
}
public static bool operator ==(RegisterMask x, RegisterMask y)
{
return x.Equals(y);
}
public static bool operator !=(RegisterMask x, RegisterMask y)
{
return !x.Equals(y);
}
public override bool Equals(object obj)
{
return obj is RegisterMask regMask && Equals(regMask);
}
public bool Equals(RegisterMask other)
{
return IntMask == other.IntMask && VecMask == other.VecMask;
}
public override int GetHashCode()
{
return HashCode.Combine(IntMask, VecMask);
}
}
}