Replace LinkedList by IntrusiveList to avoid allocations on JIT (#931)
* Replace LinkedList by IntrusiveList to avoid allocations on JIT * Fix wrong replacements
This commit is contained in:
parent
e9a37ca6a8
commit
e5f78fb1d4
@ -16,17 +16,17 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||||||
{
|
{
|
||||||
modified = false;
|
modified = false;
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> node = block.Operations.First;
|
Node node = block.Operations.First;
|
||||||
|
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> nextNode = node.Next;
|
Node nextNode = node.ListNext;
|
||||||
|
|
||||||
bool isUnused = IsUnused(node.Value);
|
bool isUnused = IsUnused(node);
|
||||||
|
|
||||||
if (!(node.Value is Operation operation) || isUnused)
|
if (!(node is Operation operation) || isUnused)
|
||||||
{
|
{
|
||||||
if (isUnused)
|
if (isUnused)
|
||||||
{
|
{
|
||||||
@ -80,13 +80,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RemoveNode(BasicBlock block, LinkedListNode<Node> llNode)
|
private static void RemoveNode(BasicBlock block, Node node)
|
||||||
{
|
{
|
||||||
// Remove a node from the nodes list, and also remove itself
|
// Remove a node from the nodes list, and also remove itself
|
||||||
// from all the use lists on the operands that this node uses.
|
// from all the use lists on the operands that this node uses.
|
||||||
block.Operations.Remove(llNode);
|
block.Operations.Remove(node);
|
||||||
|
|
||||||
Node node = llNode.Value;
|
|
||||||
|
|
||||||
for (int index = 0; index < node.SourcesCount; index++)
|
for (int index = 0; index < node.SourcesCount; index++)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
bool hasCall = false;
|
bool hasCall = false;
|
||||||
|
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
if (node is Operation operation && operation.Instruction == Instruction.Call)
|
if (node is Operation operation && operation.Instruction == Instruction.Call)
|
||||||
{
|
{
|
||||||
@ -176,10 +176,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
intLocalFreeRegisters &= ~(intSpillTempRegisters | intCallerSavedRegisters);
|
intLocalFreeRegisters &= ~(intSpillTempRegisters | intCallerSavedRegisters);
|
||||||
vecLocalFreeRegisters &= ~(vecSpillTempRegisters | vecCallerSavedRegisters);
|
vecLocalFreeRegisters &= ~(vecSpillTempRegisters | vecCallerSavedRegisters);
|
||||||
|
|
||||||
for (LinkedListNode<Node> llNode = block.Operations.First; llNode != null; llNode = llNode.Next)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
Node node = llNode.Value;
|
|
||||||
|
|
||||||
int intLocalUse = 0;
|
int intLocalUse = 0;
|
||||||
int vecLocalUse = 0;
|
int vecLocalUse = 0;
|
||||||
|
|
||||||
@ -232,7 +230,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset));
|
Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset));
|
||||||
|
|
||||||
block.Operations.AddBefore(llNode, fillOp);
|
block.Operations.AddBefore(node, fillOp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +304,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
|
Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
|
||||||
|
|
||||||
llNode = block.Operations.AddAfter(llNode, spillOp);
|
block.Operations.AddAfter(node, spillOp);
|
||||||
|
|
||||||
|
node = spillOp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private LiveInterval[] _parentIntervals;
|
private LiveInterval[] _parentIntervals;
|
||||||
|
|
||||||
private List<LinkedListNode<Node>> _operationNodes;
|
private List<(IntrusiveList<Node>, Node)> _operationNodes;
|
||||||
|
|
||||||
private int _operationsCount;
|
private int _operationsCount;
|
||||||
|
|
||||||
@ -583,15 +583,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
int splitPosition = kv.Key;
|
int splitPosition = kv.Key;
|
||||||
|
|
||||||
LinkedListNode<Node> node = GetOperationNode(splitPosition);
|
(IntrusiveList<Node> nodes, Node node) = GetOperationNode(splitPosition);
|
||||||
|
|
||||||
Operation[] sequence = copyResolver.Sequence();
|
Operation[] sequence = copyResolver.Sequence();
|
||||||
|
|
||||||
node = node.List.AddBefore(node, sequence[0]);
|
nodes.AddBefore(node, sequence[0]);
|
||||||
|
|
||||||
|
node = sequence[0];
|
||||||
|
|
||||||
for (int index = 1; index < sequence.Length; index++)
|
for (int index = 1; index < sequence.Length; index++)
|
||||||
{
|
{
|
||||||
node = node.List.AddAfter(node, sequence[index]);
|
nodes.AddAfter(node, sequence[index]);
|
||||||
|
|
||||||
|
node = sequence[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -605,10 +609,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
return block.Index >= blocksCount;
|
return block.Index >= blocksCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LinkedListNode<BasicBlock> node = cfg.Blocks.First; node != null; node = node.Next)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
BasicBlock block = node.Value;
|
|
||||||
|
|
||||||
if (IsSplitEdgeBlock(block))
|
if (IsSplitEdgeBlock(block))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -666,13 +668,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
else if (successor.Predecessors.Count == 1)
|
else if (successor.Predecessors.Count == 1)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> prependNode = successor.Operations.AddFirst(sequence[0]);
|
successor.Operations.AddFirst(sequence[0]);
|
||||||
|
|
||||||
|
Node prependNode = sequence[0];
|
||||||
|
|
||||||
for (int index = 1; index < sequence.Length; index++)
|
for (int index = 1; index < sequence.Length; index++)
|
||||||
{
|
{
|
||||||
Operation operation = sequence[index];
|
Operation operation = sequence[index];
|
||||||
|
|
||||||
prependNode = successor.Operations.AddAfter(prependNode, operation);
|
successor.Operations.AddAfter(prependNode, operation);
|
||||||
|
|
||||||
|
prependNode = operation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -695,7 +701,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
foreach (int usePosition in current.UsePositions())
|
foreach (int usePosition in current.UsePositions())
|
||||||
{
|
{
|
||||||
Node operation = GetOperationNode(usePosition).Value;
|
(_, Node operation) = GetOperationNode(usePosition);
|
||||||
|
|
||||||
for (int index = 0; index < operation.SourcesCount; index++)
|
for (int index = 0; index < operation.SourcesCount; index++)
|
||||||
{
|
{
|
||||||
@ -729,14 +735,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
interval.Local.Type);
|
interval.Local.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedListNode<Node> GetOperationNode(int position)
|
private (IntrusiveList<Node>, Node) GetOperationNode(int position)
|
||||||
{
|
{
|
||||||
return _operationNodes[position / InstructionGap];
|
return _operationNodes[position / InstructionGap];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NumberLocals(ControlFlowGraph cfg)
|
private void NumberLocals(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
_operationNodes = new List<LinkedListNode<Node>>();
|
_operationNodes = new List<(IntrusiveList<Node>, Node)>();
|
||||||
|
|
||||||
_intervals = new List<LiveInterval>();
|
_intervals = new List<LiveInterval>();
|
||||||
|
|
||||||
@ -754,13 +760,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
BasicBlock block = cfg.PostOrderBlocks[index];
|
BasicBlock block = cfg.PostOrderBlocks[index];
|
||||||
|
|
||||||
for (LinkedListNode<Node> node = block.Operations.First; node != null; node = node.Next)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
_operationNodes.Add(node);
|
_operationNodes.Add((block.Operations, node));
|
||||||
|
|
||||||
Node operation = node.Value;
|
foreach (Operand dest in Destinations(node))
|
||||||
|
|
||||||
foreach (Operand dest in Destinations(operation))
|
|
||||||
{
|
{
|
||||||
if (dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
|
if (dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
|
||||||
{
|
{
|
||||||
@ -776,7 +780,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
if (block.Operations.Count == 0)
|
if (block.Operations.Count == 0)
|
||||||
{
|
{
|
||||||
// Pretend we have a dummy instruction on the empty block.
|
// Pretend we have a dummy instruction on the empty block.
|
||||||
_operationNodes.Add(null);
|
_operationNodes.Add((null, null));
|
||||||
|
|
||||||
_operationsCount += InstructionGap;
|
_operationsCount += InstructionGap;
|
||||||
}
|
}
|
||||||
@ -795,12 +799,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
|
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
|
||||||
|
|
||||||
// Compute local live sets.
|
// Compute local live sets.
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
BitMap liveGen = new BitMap(mapSize);
|
BitMap liveGen = new BitMap(mapSize);
|
||||||
BitMap liveKill = new BitMap(mapSize);
|
BitMap liveKill = new BitMap(mapSize);
|
||||||
|
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
foreach (Operand source in Sources(node))
|
foreach (Operand source in Sources(node))
|
||||||
{
|
{
|
||||||
@ -979,13 +983,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private static IEnumerable<Node> BottomOperations(BasicBlock block)
|
private static IEnumerable<Node> BottomOperations(BasicBlock block)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> node = block.Operations.Last;
|
Node node = block.Operations.Last;
|
||||||
|
|
||||||
while (node != null && !(node.Value is PhiNode))
|
while (node != null && !(node is PhiNode))
|
||||||
{
|
{
|
||||||
yield return node.Value;
|
yield return node;
|
||||||
|
|
||||||
node = node.Previous;
|
node = node.ListPrevious;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,11 +157,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
UnwindInfo unwindInfo = WritePrologue(context);
|
UnwindInfo unwindInfo = WritePrologue(context);
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
context.EnterBlock(block);
|
context.EnterBlock(block);
|
||||||
|
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
if (node is Operation operation)
|
if (node is Operation operation)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,6 @@ using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
|||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
using LLNode = LinkedListNode<Node>;
|
|
||||||
|
|
||||||
static class PreAllocator
|
static class PreAllocator
|
||||||
{
|
{
|
||||||
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
||||||
@ -20,24 +18,24 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operand[] preservedArgs = new Operand[CallingConvention.GetArgumentsOnRegsCount()];
|
Operand[] preservedArgs = new Operand[CallingConvention.GetArgumentsOnRegsCount()];
|
||||||
|
|
||||||
foreach (BasicBlock block in cctx.Cfg.Blocks)
|
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
LLNode nextNode;
|
Node nextNode;
|
||||||
|
|
||||||
for (LLNode node = block.Operations.First; node != null; node = nextNode)
|
for (Node node = block.Operations.First; node != null; node = nextNode)
|
||||||
{
|
{
|
||||||
nextNode = node.Next;
|
nextNode = node.ListNext;
|
||||||
|
|
||||||
if (!(node.Value is Operation operation))
|
if (!(node is Operation operation))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleConstantCopy(node, operation);
|
HandleConstantCopy(block.Operations, node, operation);
|
||||||
|
|
||||||
HandleSameDestSrc1Copy(node, operation);
|
HandleSameDestSrc1Copy(block.Operations, node, operation);
|
||||||
|
|
||||||
HandleFixedRegisterCopy(node, operation);
|
HandleFixedRegisterCopy(block.Operations, node, operation);
|
||||||
|
|
||||||
switch (operation.Instruction)
|
switch (operation.Instruction)
|
||||||
{
|
{
|
||||||
@ -62,51 +60,51 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// being called, as mandated by the ABI.
|
// being called, as mandated by the ABI.
|
||||||
if (callConv == CallConvName.Windows)
|
if (callConv == CallConvName.Windows)
|
||||||
{
|
{
|
||||||
node = HandleCallWindowsAbi(stackAlloc, node, operation);
|
node = HandleCallWindowsAbi(block.Operations, stackAlloc, node, operation);
|
||||||
}
|
}
|
||||||
else /* if (callConv == CallConvName.SystemV) */
|
else /* if (callConv == CallConvName.SystemV) */
|
||||||
{
|
{
|
||||||
node = HandleCallSystemVAbi(node, operation);
|
node = HandleCallSystemVAbi(block.Operations, node, operation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction.ConvertToFPUI:
|
case Instruction.ConvertToFPUI:
|
||||||
HandleConvertToFPUI(node, operation);
|
HandleConvertToFPUI(block.Operations, node, operation);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction.LoadArgument:
|
case Instruction.LoadArgument:
|
||||||
if (callConv == CallConvName.Windows)
|
if (callConv == CallConvName.Windows)
|
||||||
{
|
{
|
||||||
HandleLoadArgumentWindowsAbi(cctx, node, preservedArgs, operation);
|
HandleLoadArgumentWindowsAbi(cctx, block.Operations, node, preservedArgs, operation);
|
||||||
}
|
}
|
||||||
else /* if (callConv == CallConvName.SystemV) */
|
else /* if (callConv == CallConvName.SystemV) */
|
||||||
{
|
{
|
||||||
HandleLoadArgumentSystemVAbi(cctx, node, preservedArgs, operation);
|
HandleLoadArgumentSystemVAbi(cctx, block.Operations, node, preservedArgs, operation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction.Negate:
|
case Instruction.Negate:
|
||||||
if (!operation.GetSource(0).Type.IsInteger())
|
if (!operation.GetSource(0).Type.IsInteger())
|
||||||
{
|
{
|
||||||
node = HandleNegate(node, operation);
|
node = HandleNegate(block.Operations, node, operation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction.Return:
|
case Instruction.Return:
|
||||||
if (callConv == CallConvName.Windows)
|
if (callConv == CallConvName.Windows)
|
||||||
{
|
{
|
||||||
HandleReturnWindowsAbi(cctx, node, preservedArgs, operation);
|
HandleReturnWindowsAbi(cctx, block.Operations, node, preservedArgs, operation);
|
||||||
}
|
}
|
||||||
else /* if (callConv == CallConvName.SystemV) */
|
else /* if (callConv == CallConvName.SystemV) */
|
||||||
{
|
{
|
||||||
HandleReturnSystemVAbi(node, operation);
|
HandleReturnSystemVAbi(block.Operations, node, operation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction.VectorInsert8:
|
case Instruction.VectorInsert8:
|
||||||
if (!HardwareCapabilities.SupportsSse41)
|
if (!HardwareCapabilities.SupportsSse41)
|
||||||
{
|
{
|
||||||
node = HandleVectorInsert8(node, operation);
|
node = HandleVectorInsert8(block.Operations, node, operation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -114,7 +112,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleConstantCopy(LLNode node, Operation operation)
|
private static void HandleConstantCopy(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
if (operation.SourcesCount == 0 || IsIntrinsic(operation.Instruction))
|
if (operation.SourcesCount == 0 || IsIntrinsic(operation.Instruction))
|
||||||
{
|
{
|
||||||
@ -135,7 +133,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// - Insert a copy with the constant value (as integer) to a GPR.
|
// - Insert a copy with the constant value (as integer) to a GPR.
|
||||||
// - Insert a copy from the GPR to a XMM register.
|
// - Insert a copy from the GPR to a XMM register.
|
||||||
// - Replace the constant use with the XMM register.
|
// - Replace the constant use with the XMM register.
|
||||||
src1 = AddXmmCopy(node, src1);
|
src1 = AddXmmCopy(nodes, node, src1);
|
||||||
|
|
||||||
operation.SetSource(0, src1);
|
operation.SetSource(0, src1);
|
||||||
}
|
}
|
||||||
@ -164,7 +162,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
if (src1.Kind == OperandKind.Constant)
|
if (src1.Kind == OperandKind.Constant)
|
||||||
{
|
{
|
||||||
src1 = AddCopy(node, src1);
|
src1 = AddCopy(nodes, node, src1);
|
||||||
|
|
||||||
operation.SetSource(0, src1);
|
operation.SetSource(0, src1);
|
||||||
}
|
}
|
||||||
@ -182,25 +180,23 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
if (!src2.Type.IsInteger())
|
if (!src2.Type.IsInteger())
|
||||||
{
|
{
|
||||||
src2 = AddXmmCopy(node, src2);
|
src2 = AddXmmCopy(nodes, node, src2);
|
||||||
|
|
||||||
operation.SetSource(1, src2);
|
operation.SetSource(1, src2);
|
||||||
}
|
}
|
||||||
else if (!HasConstSrc2(inst) || IsLongConst(src2))
|
else if (!HasConstSrc2(inst) || IsLongConst(src2))
|
||||||
{
|
{
|
||||||
src2 = AddCopy(node, src2);
|
src2 = AddCopy(nodes, node, src2);
|
||||||
|
|
||||||
operation.SetSource(1, src2);
|
operation.SetSource(1, src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleFixedRegisterCopy(LLNode node, Operation operation)
|
private static Node HandleFixedRegisterCopy(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
|
||||||
|
|
||||||
switch (operation.Instruction)
|
switch (operation.Instruction)
|
||||||
{
|
{
|
||||||
case Instruction.CompareAndSwap128:
|
case Instruction.CompareAndSwap128:
|
||||||
@ -359,7 +355,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleSameDestSrc1Copy(LLNode node, Operation operation)
|
private static Node HandleSameDestSrc1Copy(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
if (operation.Destination == null || operation.SourcesCount == 0)
|
if (operation.Destination == null || operation.SourcesCount == 0)
|
||||||
{
|
{
|
||||||
@ -371,8 +367,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand src1 = operation.GetSource(0);
|
Operand src1 = operation.GetSource(0);
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
|
||||||
|
|
||||||
// The multiply instruction (that maps to IMUL) is somewhat special, it has
|
// The multiply instruction (that maps to IMUL) is somewhat special, it has
|
||||||
// a three operand form where the second source is a immediate value.
|
// a three operand form where the second source is a immediate value.
|
||||||
bool threeOperandForm = inst == Instruction.Multiply && operation.GetSource(1).Kind == OperandKind.Constant;
|
bool threeOperandForm = inst == Instruction.Multiply && operation.GetSource(1).Kind == OperandKind.Constant;
|
||||||
@ -441,7 +435,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleConvertToFPUI(LLNode node, Operation operation)
|
private static Node HandleConvertToFPUI(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
// Unsigned integer to FP conversions are not supported on X86.
|
// Unsigned integer to FP conversions are not supported on X86.
|
||||||
// We need to turn them into signed integer to FP conversions, and
|
// We need to turn them into signed integer to FP conversions, and
|
||||||
@ -451,9 +445,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
|
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
Node currentNode = node;
|
||||||
|
|
||||||
LLNode currentNode = node;
|
|
||||||
|
|
||||||
if (source.Type == OperandType.I32)
|
if (source.Type == OperandType.I32)
|
||||||
{
|
{
|
||||||
@ -494,12 +486,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, lsbF));
|
node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, lsbF));
|
||||||
}
|
}
|
||||||
|
|
||||||
Delete(currentNode, operation);
|
Delete(nodes, currentNode, operation);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleNegate(LLNode node, Operation operation)
|
private static Node HandleNegate(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
// There's no SSE FP negate instruction, so we need to transform that into
|
// There's no SSE FP negate instruction, so we need to transform that into
|
||||||
// a XOR of the value to be negated with a mask with the highest bit set.
|
// a XOR of the value to be negated with a mask with the highest bit set.
|
||||||
@ -510,9 +502,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Debug.Assert(dest.Type == OperandType.FP32 ||
|
Debug.Assert(dest.Type == OperandType.FP32 ||
|
||||||
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
Node currentNode = node;
|
||||||
|
|
||||||
LLNode currentNode = node;
|
|
||||||
|
|
||||||
Operand res = Local(dest.Type);
|
Operand res = Local(dest.Type);
|
||||||
|
|
||||||
@ -531,12 +521,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, res));
|
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, res));
|
||||||
|
|
||||||
Delete(currentNode, operation);
|
Delete(nodes, currentNode, operation);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleVectorInsert8(LLNode node, Operation operation)
|
private static Node HandleVectorInsert8(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
// Handle vector insertion, when SSE 4.1 is not supported.
|
// Handle vector insertion, when SSE 4.1 is not supported.
|
||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
@ -550,9 +540,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(index < 16);
|
Debug.Assert(index < 16);
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
Node currentNode = node;
|
||||||
|
|
||||||
LLNode currentNode = node;
|
|
||||||
|
|
||||||
Operand temp1 = Local(OperandType.I32);
|
Operand temp1 = Local(OperandType.I32);
|
||||||
Operand temp2 = Local(OperandType.I32);
|
Operand temp2 = Local(OperandType.I32);
|
||||||
@ -580,17 +568,15 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
node = nodes.AddAfter(node, vinsOp);
|
node = nodes.AddAfter(node, vinsOp);
|
||||||
|
|
||||||
Delete(currentNode, operation);
|
Delete(nodes, currentNode, operation);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleCallWindowsAbi(StackAllocator stackAlloc, LLNode node, Operation operation)
|
private static Node HandleCallWindowsAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
|
||||||
|
|
||||||
// Handle struct arguments.
|
// Handle struct arguments.
|
||||||
int retArgs = 0;
|
int retArgs = 0;
|
||||||
|
|
||||||
@ -661,7 +647,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation storeOp = new Operation(Instruction.Store, null, stackAddr, source);
|
Operation storeOp = new Operation(Instruction.Store, null, stackAddr, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes.AddBefore(node, storeOp), storeOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, storeOp), storeOp);
|
||||||
|
|
||||||
operation.SetSource(index, stackAddr);
|
operation.SetSource(index, stackAddr);
|
||||||
}
|
}
|
||||||
@ -687,7 +673,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
||||||
|
|
||||||
sources[1 + retArgs + index] = argReg;
|
sources[1 + retArgs + index] = argReg;
|
||||||
}
|
}
|
||||||
@ -702,7 +688,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest != null)
|
if (dest != null)
|
||||||
@ -738,15 +724,14 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LLNode HandleCallSystemVAbi(LLNode node, Operation operation)
|
private static Node HandleCallSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
|
|
||||||
LinkedList<Node> nodes = node.List;
|
List<Operand> sources = new List<Operand>
|
||||||
|
{
|
||||||
List<Operand> sources = new List<Operand>();
|
operation.GetSource(0)
|
||||||
|
};
|
||||||
sources.Add(operation.GetSource(0));
|
|
||||||
|
|
||||||
int argsCount = operation.SourcesCount - 1;
|
int argsCount = operation.SourcesCount - 1;
|
||||||
|
|
||||||
@ -797,7 +782,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
||||||
|
|
||||||
sources.Add(argReg);
|
sources.Add(argReg);
|
||||||
}
|
}
|
||||||
@ -807,7 +792,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
||||||
|
|
||||||
stackOffset += source.Type.GetSizeInBytes();
|
stackOffset += source.Type.GetSizeInBytes();
|
||||||
}
|
}
|
||||||
@ -846,7 +831,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static void HandleLoadArgumentWindowsAbi(
|
private static void HandleLoadArgumentWindowsAbi(
|
||||||
CompilerContext cctx,
|
CompilerContext cctx,
|
||||||
LLNode node,
|
IntrusiveList<Node> nodes,
|
||||||
|
Node node,
|
||||||
Operand[] preservedArgs,
|
Operand[] preservedArgs,
|
||||||
Operation operation)
|
Operation operation)
|
||||||
{
|
{
|
||||||
@ -896,9 +882,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
? Instruction.Load
|
? Instruction.Load
|
||||||
: Instruction.Copy, dest, preservedArgs[index]);
|
: Instruction.Copy, dest, preservedArgs[index]);
|
||||||
|
|
||||||
node.List.AddBefore(node, argCopyOp);
|
nodes.AddBefore(node, argCopyOp);
|
||||||
|
|
||||||
Delete(node, operation);
|
Delete(nodes, node, operation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -908,7 +894,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static void HandleLoadArgumentSystemVAbi(
|
private static void HandleLoadArgumentSystemVAbi(
|
||||||
CompilerContext cctx,
|
CompilerContext cctx,
|
||||||
LLNode node,
|
IntrusiveList<Node> nodes,
|
||||||
|
Node node,
|
||||||
Operand[] preservedArgs,
|
Operand[] preservedArgs,
|
||||||
Operation operation)
|
Operation operation)
|
||||||
{
|
{
|
||||||
@ -994,9 +981,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation argCopyOp = new Operation(Instruction.Copy, dest, preservedArgs[index]);
|
Operation argCopyOp = new Operation(Instruction.Copy, dest, preservedArgs[index]);
|
||||||
|
|
||||||
node.List.AddBefore(node, argCopyOp);
|
nodes.AddBefore(node, argCopyOp);
|
||||||
|
|
||||||
Delete(node, operation);
|
Delete(nodes, node, operation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1006,7 +993,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static void HandleReturnWindowsAbi(
|
private static void HandleReturnWindowsAbi(
|
||||||
CompilerContext cctx,
|
CompilerContext cctx,
|
||||||
LLNode node,
|
IntrusiveList<Node> nodes,
|
||||||
|
Node node,
|
||||||
Operand[] preservedArgs,
|
Operand[] preservedArgs,
|
||||||
Operation operation)
|
Operation operation)
|
||||||
{
|
{
|
||||||
@ -1049,19 +1037,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
Operation retStoreOp = new Operation(Instruction.Store, null, retReg, source);
|
Operation retStoreOp = new Operation(Instruction.Store, null, retReg, source);
|
||||||
|
|
||||||
node.List.AddBefore(node, retStoreOp);
|
nodes.AddBefore(node, retStoreOp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
||||||
|
|
||||||
node.List.AddBefore(node, retCopyOp);
|
nodes.AddBefore(node, retCopyOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.SetSources(new Operand[0]);
|
operation.SetSources(new Operand[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleReturnSystemVAbi(LLNode node, Operation operation)
|
private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
if (operation.SourcesCount == 0)
|
if (operation.SourcesCount == 0)
|
||||||
{
|
{
|
||||||
@ -1075,8 +1063,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
||||||
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
||||||
|
|
||||||
node.List.AddBefore(node, new Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
|
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
|
||||||
node.List.AddBefore(node, new Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
|
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1086,30 +1074,30 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
||||||
|
|
||||||
node.List.AddBefore(node, retCopyOp);
|
nodes.AddBefore(node, retCopyOp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand AddXmmCopy(LLNode node, Operand source)
|
private static Operand AddXmmCopy(IntrusiveList<Node> nodes, Node node, Operand source)
|
||||||
{
|
{
|
||||||
Operand temp = Local(source.Type);
|
Operand temp = Local(source.Type);
|
||||||
|
|
||||||
Operand intConst = AddCopy(node, GetIntConst(source));
|
Operand intConst = AddCopy(nodes, node, GetIntConst(source));
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.VectorCreateScalar, temp, intConst);
|
Operation copyOp = new Operation(Instruction.VectorCreateScalar, temp, intConst);
|
||||||
|
|
||||||
node.List.AddBefore(node, copyOp);
|
nodes.AddBefore(node, copyOp);
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand AddCopy(LLNode node, Operand source)
|
private static Operand AddCopy(IntrusiveList<Node> nodes, Node node, Operand source)
|
||||||
{
|
{
|
||||||
Operand temp = Local(source.Type);
|
Operand temp = Local(source.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, temp, source);
|
Operation copyOp = new Operation(Instruction.Copy, temp, source);
|
||||||
|
|
||||||
node.List.AddBefore(node, copyOp);
|
nodes.AddBefore(node, copyOp);
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@ -1142,7 +1130,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return value == (int)value;
|
return value == (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Delete(LLNode node, Operation operation)
|
private static void Delete(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
{
|
{
|
||||||
operation.Destination = null;
|
operation.Destination = null;
|
||||||
|
|
||||||
@ -1151,7 +1139,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
operation.SetSource(index, null);
|
operation.SetSource(index, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.List.Remove(node);
|
nodes.Remove(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand Gpr(X86Register register, OperandType type)
|
private static Operand Gpr(X86Register register, OperandType type)
|
||||||
|
@ -35,7 +35,7 @@ namespace ARMeilleure.Diagnostics
|
|||||||
|
|
||||||
IncreaseIndentation();
|
IncreaseIndentation();
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
string blockName = GetBlockName(block);
|
string blockName = GetBlockName(block);
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ namespace ARMeilleure.Diagnostics
|
|||||||
|
|
||||||
IncreaseIndentation();
|
IncreaseIndentation();
|
||||||
|
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
string[] sources = new string[node.SourcesCount];
|
string[] sources = new string[node.SourcesCount];
|
||||||
|
|
||||||
|
@ -2,13 +2,14 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace ARMeilleure.IntermediateRepresentation
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
class BasicBlock
|
class BasicBlock : IIntrusiveListNode<BasicBlock>
|
||||||
{
|
{
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
public LinkedListNode<BasicBlock> Node { get; set; }
|
public BasicBlock ListPrevious { get; set; }
|
||||||
|
public BasicBlock ListNext { get; set; }
|
||||||
|
|
||||||
public LinkedList<Node> Operations { get; }
|
public IntrusiveList<Node> Operations { get; }
|
||||||
|
|
||||||
private BasicBlock _next;
|
private BasicBlock _next;
|
||||||
private BasicBlock _branch;
|
private BasicBlock _branch;
|
||||||
@ -33,7 +34,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
public BasicBlock()
|
public BasicBlock()
|
||||||
{
|
{
|
||||||
Operations = new LinkedList<Node>();
|
Operations = new IntrusiveList<Node>();
|
||||||
|
|
||||||
Predecessors = new List<BasicBlock>();
|
Predecessors = new List<BasicBlock>();
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
public Node GetLastOp()
|
public Node GetLastOp()
|
||||||
{
|
{
|
||||||
return Operations.Last?.Value;
|
return Operations.Last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
|
{
|
||||||
|
interface IIntrusiveListNode<T> where T : class
|
||||||
|
{
|
||||||
|
T ListPrevious { get; set; }
|
||||||
|
T ListNext { get; set; }
|
||||||
|
}
|
||||||
|
}
|
178
ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
Normal file
178
ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// First item of the list, or null if empty.
|
||||||
|
/// </summary>
|
||||||
|
public T First { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last item of the list, or null if empty.
|
||||||
|
/// </summary>
|
||||||
|
public T Last { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total number of items on the list.
|
||||||
|
/// </summary>
|
||||||
|
public int Count { get; private set; }
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
if (First != null)
|
||||||
|
{
|
||||||
|
AddBefore(First, newNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(newNode.ListPrevious == null);
|
||||||
|
Debug.Assert(newNode.ListNext == null);
|
||||||
|
Debug.Assert(Last == null);
|
||||||
|
|
||||||
|
First = newNode;
|
||||||
|
Last = newNode;
|
||||||
|
|
||||||
|
Debug.Assert(Count == 0);
|
||||||
|
|
||||||
|
Count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a item as the last item of the list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newNode">Item to be added</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void AddLast(T newNode)
|
||||||
|
{
|
||||||
|
if (Last != null)
|
||||||
|
{
|
||||||
|
AddAfter(Last, newNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(newNode.ListPrevious == null);
|
||||||
|
Debug.Assert(newNode.ListNext == null);
|
||||||
|
Debug.Assert(First == null);
|
||||||
|
|
||||||
|
First = newNode;
|
||||||
|
Last = newNode;
|
||||||
|
|
||||||
|
Debug.Assert(Count == 0);
|
||||||
|
|
||||||
|
Count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a item before a existing item on the list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">Item on the list that will succeed the new item</param>
|
||||||
|
/// <param name="newNode">Item to be added</param>
|
||||||
|
/// <returns>New item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public T AddBefore(T node, T newNode)
|
||||||
|
{
|
||||||
|
Debug.Assert(newNode.ListPrevious == null);
|
||||||
|
Debug.Assert(newNode.ListNext == null);
|
||||||
|
|
||||||
|
newNode.ListPrevious = node.ListPrevious;
|
||||||
|
newNode.ListNext = node;
|
||||||
|
|
||||||
|
node.ListPrevious = newNode;
|
||||||
|
|
||||||
|
if (newNode.ListPrevious != null)
|
||||||
|
{
|
||||||
|
newNode.ListPrevious.ListNext = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (First == node)
|
||||||
|
{
|
||||||
|
First = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Count++;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a item after a existing item on the list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">Item on the list that will preceed the new item</param>
|
||||||
|
/// <param name="newNode">Item to be added</param>
|
||||||
|
/// <returns>New item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public T AddAfter(T node, T newNode)
|
||||||
|
{
|
||||||
|
Debug.Assert(newNode.ListPrevious == null);
|
||||||
|
Debug.Assert(newNode.ListNext == null);
|
||||||
|
|
||||||
|
newNode.ListPrevious = node;
|
||||||
|
newNode.ListNext = node.ListNext;
|
||||||
|
|
||||||
|
node.ListNext = newNode;
|
||||||
|
|
||||||
|
if (newNode.ListNext != null)
|
||||||
|
{
|
||||||
|
newNode.ListNext.ListPrevious = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Last == node)
|
||||||
|
{
|
||||||
|
Last = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Count++;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a item from the list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">The item to be removed</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Remove(T node)
|
||||||
|
{
|
||||||
|
if (node.ListPrevious != null)
|
||||||
|
{
|
||||||
|
node.ListPrevious.ListNext = node.ListNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(First == node);
|
||||||
|
|
||||||
|
First = node.ListNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.ListNext != null)
|
||||||
|
{
|
||||||
|
node.ListNext.ListPrevious = node.ListPrevious;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(Last == node);
|
||||||
|
|
||||||
|
Last = node.ListPrevious;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.ListPrevious = null;
|
||||||
|
node.ListNext = null;
|
||||||
|
|
||||||
|
Count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ARMeilleure.IntermediateRepresentation
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
class Node
|
class Node : IIntrusiveListNode<Node>
|
||||||
{
|
{
|
||||||
|
public Node ListPrevious { get; set; }
|
||||||
|
public Node ListNext { get; set; }
|
||||||
|
|
||||||
public Operand Destination
|
public Operand Destination
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -27,9 +29,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
private Operand[] _destinations;
|
private Operand[] _destinations;
|
||||||
private Operand[] _sources;
|
private Operand[] _sources;
|
||||||
|
|
||||||
private LinkedListNode<Node>[] _asgUseNodes;
|
|
||||||
private LinkedListNode<Node>[] _srcUseNodes;
|
|
||||||
|
|
||||||
public int DestinationsCount => _destinations.Length;
|
public int DestinationsCount => _destinations.Length;
|
||||||
public int SourcesCount => _sources.Length;
|
public int SourcesCount => _sources.Length;
|
||||||
|
|
||||||
@ -38,8 +37,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
Destination = destination;
|
Destination = destination;
|
||||||
|
|
||||||
_sources = new Operand[sourcesCount];
|
_sources = new Operand[sourcesCount];
|
||||||
|
|
||||||
_srcUseNodes = new LinkedListNode<Node>[sourcesCount];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node(Operand[] destinations, int sourcesCount)
|
public Node(Operand[] destinations, int sourcesCount)
|
||||||
@ -47,8 +44,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
|
SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
|
||||||
|
|
||||||
_sources = new Operand[sourcesCount];
|
_sources = new Operand[sourcesCount];
|
||||||
|
|
||||||
_srcUseNodes = new LinkedListNode<Node>[sourcesCount];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operand GetDestination(int index)
|
public Operand GetDestination(int index)
|
||||||
@ -67,12 +62,12 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
oldOp.Assignments.Remove(_asgUseNodes[index]);
|
oldOp.Assignments.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destination != null && destination.Kind == OperandKind.LocalVariable)
|
if (destination != null && destination.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
_asgUseNodes[index] = destination.Assignments.AddLast(this);
|
destination.Assignments.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_destinations[index] = destination;
|
_destinations[index] = destination;
|
||||||
@ -84,12 +79,12 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
oldOp.Uses.Remove(_srcUseNodes[index]);
|
oldOp.Uses.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source != null && source.Kind == OperandKind.LocalVariable)
|
if (source != null && source.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
_srcUseNodes[index] = source.Uses.AddLast(this);
|
source.Uses.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sources[index] = source;
|
_sources[index] = source;
|
||||||
@ -105,7 +100,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
oldOp.Assignments.Remove(_asgUseNodes[index]);
|
oldOp.Assignments.Remove(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +111,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
_destinations = new Operand[destinations.Length];
|
_destinations = new Operand[destinations.Length];
|
||||||
}
|
}
|
||||||
|
|
||||||
_asgUseNodes = new LinkedListNode<Node>[destinations.Length];
|
|
||||||
|
|
||||||
for (int index = 0; index < destinations.Length; index++)
|
for (int index = 0; index < destinations.Length; index++)
|
||||||
{
|
{
|
||||||
Operand newOp = destinations[index];
|
Operand newOp = destinations[index];
|
||||||
@ -126,7 +119,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (newOp.Kind == OperandKind.LocalVariable)
|
if (newOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
_asgUseNodes[index] = newOp.Assignments.AddLast(this);
|
newOp.Assignments.Add(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,14 +132,12 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
oldOp.Uses.Remove(_srcUseNodes[index]);
|
oldOp.Uses.Remove(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sources = new Operand[sources.Length];
|
_sources = new Operand[sources.Length];
|
||||||
|
|
||||||
_srcUseNodes = new LinkedListNode<Node>[sources.Length];
|
|
||||||
|
|
||||||
for (int index = 0; index < sources.Length; index++)
|
for (int index = 0; index < sources.Length; index++)
|
||||||
{
|
{
|
||||||
Operand newOp = sources[index];
|
Operand newOp = sources[index];
|
||||||
@ -155,7 +146,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
if (newOp.Kind == OperandKind.LocalVariable)
|
if (newOp.Kind == OperandKind.LocalVariable)
|
||||||
{
|
{
|
||||||
_srcUseNodes[index] = newOp.Uses.AddLast(this);
|
newOp.Uses.Add(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,13 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
public ulong Value { get; private set; }
|
public ulong Value { get; private set; }
|
||||||
|
|
||||||
public LinkedList<Node> Assignments { get; }
|
public List<Node> Assignments { get; }
|
||||||
public LinkedList<Node> Uses { get; }
|
public List<Node> Uses { get; }
|
||||||
|
|
||||||
private Operand()
|
private Operand()
|
||||||
{
|
{
|
||||||
Assignments = new LinkedList<Node>();
|
Assignments = new List<Node>();
|
||||||
Uses = new LinkedList<Node>();
|
Uses = new List<Node>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operand(OperandKind kind, OperandType type = OperandType.None) : this()
|
public Operand(OperandKind kind, OperandType type = OperandType.None) : this()
|
||||||
|
@ -9,13 +9,13 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
public BasicBlock Entry { get; }
|
public BasicBlock Entry { get; }
|
||||||
|
|
||||||
public LinkedList<BasicBlock> Blocks { get; }
|
public IntrusiveList<BasicBlock> Blocks { get; }
|
||||||
|
|
||||||
public BasicBlock[] PostOrderBlocks { get; }
|
public BasicBlock[] PostOrderBlocks { get; }
|
||||||
|
|
||||||
public int[] PostOrderMap { get; }
|
public int[] PostOrderMap { get; }
|
||||||
|
|
||||||
public ControlFlowGraph(BasicBlock entry, LinkedList<BasicBlock> blocks)
|
public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks)
|
||||||
{
|
{
|
||||||
Entry = entry;
|
Entry = entry;
|
||||||
Blocks = blocks;
|
Blocks = blocks;
|
||||||
@ -57,7 +57,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveUnreachableBlocks(LinkedList<BasicBlock> blocks)
|
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
|
||||||
{
|
{
|
||||||
HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
|
HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
|
||||||
|
|
||||||
@ -87,25 +87,23 @@ namespace ARMeilleure.Translation
|
|||||||
// Remove unreachable blocks and renumber.
|
// Remove unreachable blocks and renumber.
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
for (LinkedListNode<BasicBlock> node = blocks.First; node != null;)
|
for (BasicBlock block = blocks.First; block != null;)
|
||||||
{
|
{
|
||||||
LinkedListNode<BasicBlock> nextNode = node.Next;
|
BasicBlock nextBlock = block.ListNext;
|
||||||
|
|
||||||
BasicBlock block = node.Value;
|
|
||||||
|
|
||||||
if (!visited.Contains(block))
|
if (!visited.Contains(block))
|
||||||
{
|
{
|
||||||
block.Next = null;
|
block.Next = null;
|
||||||
block.Branch = null;
|
block.Branch = null;
|
||||||
|
|
||||||
blocks.Remove(node);
|
blocks.Remove(block);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
block.Index = index++;
|
block.Index = index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = nextNode;
|
block = nextBlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +128,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert the new block on the list of blocks.
|
// Insert the new block on the list of blocks.
|
||||||
BasicBlock succPrev = successor.Node.Previous?.Value;
|
BasicBlock succPrev = successor.ListPrevious;
|
||||||
|
|
||||||
if (succPrev != null && succPrev != predecessor && succPrev.Next == successor)
|
if (succPrev != null && succPrev != predecessor && succPrev.Next == successor)
|
||||||
{
|
{
|
||||||
@ -145,12 +143,12 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
splitBlock2.Operations.AddLast(new Operation(Instruction.Branch, null));
|
splitBlock2.Operations.AddLast(new Operation(Instruction.Branch, null));
|
||||||
|
|
||||||
Blocks.AddBefore(successor.Node, splitBlock2);
|
Blocks.AddBefore(successor, splitBlock2);
|
||||||
}
|
}
|
||||||
|
|
||||||
splitBlock.Next = successor;
|
splitBlock.Next = successor;
|
||||||
|
|
||||||
Blocks.AddBefore(successor.Node, splitBlock);
|
Blocks.AddBefore(successor, splitBlock);
|
||||||
|
|
||||||
return splitBlock;
|
return splitBlock;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public static void FindDominanceFrontiers(ControlFlowGraph cfg)
|
public static void FindDominanceFrontiers(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
if (block.Predecessors.Count < 2)
|
if (block.Predecessors.Count < 2)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
private Dictionary<Operand, BasicBlock> _irLabels;
|
private Dictionary<Operand, BasicBlock> _irLabels;
|
||||||
|
|
||||||
private LinkedList<BasicBlock> _irBlocks;
|
private IntrusiveList<BasicBlock> _irBlocks;
|
||||||
|
|
||||||
private BasicBlock _irBlock;
|
private BasicBlock _irBlock;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
_irLabels = new Dictionary<Operand, BasicBlock>();
|
_irLabels = new Dictionary<Operand, BasicBlock>();
|
||||||
|
|
||||||
_irBlocks = new LinkedList<BasicBlock>();
|
_irBlocks = new IntrusiveList<BasicBlock>();
|
||||||
|
|
||||||
_needsNewBlock = true;
|
_needsNewBlock = true;
|
||||||
}
|
}
|
||||||
@ -508,7 +508,8 @@ namespace ARMeilleure.Translation
|
|||||||
if (_irLabels.TryGetValue(label, out BasicBlock nextBlock))
|
if (_irLabels.TryGetValue(label, out BasicBlock nextBlock))
|
||||||
{
|
{
|
||||||
nextBlock.Index = _irBlocks.Count;
|
nextBlock.Index = _irBlocks.Count;
|
||||||
nextBlock.Node = _irBlocks.AddLast(nextBlock);
|
|
||||||
|
_irBlocks.AddLast(nextBlock);
|
||||||
|
|
||||||
NextBlock(nextBlock);
|
NextBlock(nextBlock);
|
||||||
}
|
}
|
||||||
@ -524,7 +525,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
BasicBlock block = new BasicBlock(_irBlocks.Count);
|
BasicBlock block = new BasicBlock(_irBlocks.Count);
|
||||||
|
|
||||||
block.Node = _irBlocks.AddLast(block);
|
_irBlocks.AddLast(block);
|
||||||
|
|
||||||
NextBlock(block);
|
NextBlock(block);
|
||||||
}
|
}
|
||||||
@ -556,7 +557,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public ControlFlowGraph GetControlFlowGraph()
|
public ControlFlowGraph GetControlFlowGraph()
|
||||||
{
|
{
|
||||||
return new ControlFlowGraph(_irBlocks.First.Value, _irBlocks);
|
return new ControlFlowGraph(_irBlocks.First, _irBlocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,9 +25,9 @@ namespace ARMeilleure.Translation
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
Operand dest = node.Destination;
|
Operand dest = node.Destination;
|
||||||
|
|
||||||
|
@ -74,9 +74,9 @@ namespace ARMeilleure.Translation
|
|||||||
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
|
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
|
||||||
RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];
|
RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
foreach (Node node in block.Operations)
|
for (Node node = block.Operations.First; node != null; node = node.ListNext)
|
||||||
{
|
{
|
||||||
Operation operation = node as Operation;
|
Operation operation = node as Operation;
|
||||||
|
|
||||||
@ -192,13 +192,13 @@ namespace ARMeilleure.Translation
|
|||||||
while (modified);
|
while (modified);
|
||||||
|
|
||||||
// Insert load and store context instructions where needed.
|
// Insert load and store context instructions where needed.
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
bool hasContextLoad = HasContextLoad(block);
|
bool hasContextLoad = HasContextLoad(block);
|
||||||
|
|
||||||
if (hasContextLoad)
|
if (hasContextLoad)
|
||||||
{
|
{
|
||||||
block.Operations.RemoveFirst();
|
block.Operations.Remove(block.Operations.First);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The only block without any predecessor should be the entry block.
|
// The only block without any predecessor should be the entry block.
|
||||||
@ -213,7 +213,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
if (hasContextStore)
|
if (hasContextStore)
|
||||||
{
|
{
|
||||||
block.Operations.RemoveLast();
|
block.Operations.Remove(block.Operations.Last);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EndsWithReturn(block) || hasContextStore)
|
if (EndsWithReturn(block) || hasContextStore)
|
||||||
@ -226,7 +226,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
private static bool HasContextLoad(BasicBlock block)
|
private static bool HasContextLoad(BasicBlock block)
|
||||||
{
|
{
|
||||||
return StartsWith(block, Instruction.LoadFromContext) && block.Operations.First.Value.SourcesCount == 0;
|
return StartsWith(block, Instruction.LoadFromContext) && block.Operations.First.SourcesCount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasContextStore(BasicBlock block)
|
private static bool HasContextStore(BasicBlock block)
|
||||||
@ -241,7 +241,7 @@ namespace ARMeilleure.Translation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block.Operations.First.Value is Operation operation && operation.Instruction == inst;
|
return block.Operations.First is Operation operation && operation.Instruction == inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool EndsWith(BasicBlock block, Instruction inst)
|
private static bool EndsWith(BasicBlock block, Instruction inst)
|
||||||
@ -251,7 +251,7 @@ namespace ARMeilleure.Translation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block.Operations.Last.Value is Operation operation && operation.Instruction == inst;
|
return block.Operations.Last is Operation operation && operation.Instruction == inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RegisterMask GetMask(Register register)
|
private static RegisterMask GetMask(Register register)
|
||||||
|
@ -47,7 +47,7 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
DefMap[] globalDefs = new DefMap[cfg.Blocks.Count];
|
DefMap[] globalDefs = new DefMap[cfg.Blocks.Count];
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
globalDefs[block.Index] = new DefMap();
|
globalDefs[block.Index] = new DefMap();
|
||||||
}
|
}
|
||||||
@ -55,11 +55,11 @@ namespace ARMeilleure.Translation
|
|||||||
Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>();
|
Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>();
|
||||||
|
|
||||||
// First pass, get all defs and locals uses.
|
// First pass, get all defs and locals uses.
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
|
Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
|
||||||
|
|
||||||
LinkedListNode<Node> node = block.Operations.First;
|
Node node = block.Operations.First;
|
||||||
|
|
||||||
Operand RenameLocal(Operand operand)
|
Operand RenameLocal(Operand operand)
|
||||||
{
|
{
|
||||||
@ -75,7 +75,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
if (node.Value is Operation operation)
|
if (node is Operation operation)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < operation.SourcesCount; index++)
|
for (int index = 0; index < operation.SourcesCount; index++)
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node.Next;
|
node = node.ListNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int index = 0; index < RegisterConsts.TotalCount; index++)
|
for (int index = 0; index < RegisterConsts.TotalCount; index++)
|
||||||
@ -126,11 +126,11 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Second pass, rename variables with definitions on different blocks.
|
// Second pass, rename variables with definitions on different blocks.
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
|
Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
|
||||||
|
|
||||||
LinkedListNode<Node> node = block.Operations.First;
|
Node node = block.Operations.First;
|
||||||
|
|
||||||
Operand RenameGlobal(Operand operand)
|
Operand RenameGlobal(Operand operand)
|
||||||
{
|
{
|
||||||
@ -155,7 +155,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
if (node.Value is Operation operation)
|
if (node is Operation operation)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < operation.SourcesCount; index++)
|
for (int index = 0; index < operation.SourcesCount; index++)
|
||||||
{
|
{
|
||||||
@ -163,7 +163,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node.Next;
|
node = node.ListNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,17 +238,17 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
private static void AddPhi(BasicBlock block, PhiNode phi)
|
private static void AddPhi(BasicBlock block, PhiNode phi)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> node = block.Operations.First;
|
Node node = block.Operations.First;
|
||||||
|
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
while (node.Next?.Value is PhiNode)
|
while (node.ListNext is PhiNode)
|
||||||
{
|
{
|
||||||
node = node.Next;
|
node = node.ListNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node?.Value is PhiNode)
|
if (node is PhiNode)
|
||||||
{
|
{
|
||||||
block.Operations.AddAfter(node, phi);
|
block.Operations.AddAfter(node, phi);
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,13 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
public static void Deconstruct(ControlFlowGraph cfg)
|
public static void Deconstruct(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> node = block.Operations.First;
|
Node node = block.Operations.First;
|
||||||
|
|
||||||
while (node?.Value is PhiNode phi)
|
while (node is PhiNode phi)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> nextNode = node.Next;
|
Node nextNode = node.ListNext;
|
||||||
|
|
||||||
Operand local = Local(phi.Destination.Type);
|
Operand local = Local(phi.Destination.Type);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user