aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/CodeGen')
-rw-r--r--ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs9
-rw-r--r--ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs5
-rw-r--r--ARMeilleure/CodeGen/Optimizations/Optimizer.cs130
-rw-r--r--ARMeilleure/CodeGen/Optimizations/Simplification.cs3
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs7
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs244
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs70
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs2
-rw-r--r--ARMeilleure/CodeGen/X86/Assembler.cs141
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenerator.cs72
-rw-r--r--ARMeilleure/CodeGen/X86/PreAllocator.cs395
-rw-r--r--ARMeilleure/CodeGen/X86/X86Optimizer.cs71
12 files changed, 567 insertions, 582 deletions
diff --git a/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs b/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
index a200f54e..c06ed520 100644
--- a/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
+++ b/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
@@ -1,8 +1,7 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Diagnostics;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
@@ -33,8 +32,10 @@ namespace ARMeilleure.CodeGen.Optimizations
{
nextBlock = block.ListNext;
- if (block.SuccessorCount == 2 && block.Operations.Last is Operation branchOp)
+ if (block.SuccessorsCount == 2)
{
+ Operation branchOp = block.Operations.Last;
+
Debug.Assert(branchOp.Instruction == Instruction.BranchIf);
BasicBlock falseSucc = block.GetSuccessor(0);
@@ -59,7 +60,7 @@ namespace ARMeilleure.CodeGen.Optimizations
if (update)
{
- cfg.Update(removeUnreachableBlocks: false);
+ cfg.Update();
}
}
}
diff --git a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
index 412f6ea4..0423c255 100644
--- a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
+++ b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
@@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation;
using System;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
@@ -9,7 +8,7 @@ namespace ARMeilleure.CodeGen.Optimizations
{
public static void RunPass(Operation operation)
{
- if (operation.Destination == null || operation.SourcesCount == 0)
+ if (operation.Destination == default || operation.SourcesCount == 0)
{
return;
}
diff --git a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs b/ARMeilleure/CodeGen/Optimizations/Optimizer.cs
index 438010a2..919e996b 100644
--- a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs
+++ b/ARMeilleure/CodeGen/Optimizations/Optimizer.cs
@@ -1,8 +1,8 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
+using System;
using System.Diagnostics;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
@@ -10,62 +10,60 @@ namespace ARMeilleure.CodeGen.Optimizations
{
public static void RunPass(ControlFlowGraph cfg)
{
+ // Scratch buffer used to store uses.
+ Span<Operation> buffer = default;
+
bool modified;
do
{
modified = false;
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
+ for (BasicBlock block = cfg.Blocks.Last; block != null; block = block.ListPrevious)
{
- Node node = block.Operations.First;
+ Operation node;
+ Operation prevNode;
- while (node != null)
+ for (node = block.Operations.Last; node != default; node = prevNode)
{
- Node nextNode = node.ListNext;
+ prevNode = node.ListPrevious;
- bool isUnused = IsUnused(node);
-
- if (!(node is Operation operation) || isUnused)
+ if (IsUnused(node))
{
- if (isUnused)
- {
- RemoveNode(block, node);
-
- modified = true;
- }
+ RemoveNode(block, node);
- node = nextNode;
+ modified = true;
continue;
}
+ else if (node.Instruction == Instruction.Phi)
+ {
+ continue;
+ }
- ConstantFolding.RunPass(operation);
-
- Simplification.RunPass(operation);
+ ConstantFolding.RunPass(node);
+ Simplification.RunPass(node);
- if (DestIsLocalVar(operation))
+ if (DestIsLocalVar(node))
{
- if (IsPropagableCompare(operation))
+ if (IsPropagableCompare(node))
{
- modified |= PropagateCompare(operation);
+ modified |= PropagateCompare(ref buffer, node);
- if (modified && IsUnused(operation))
+ if (modified && IsUnused(node))
{
RemoveNode(block, node);
}
}
- else if (IsPropagableCopy(operation))
+ else if (IsPropagableCopy(node))
{
- PropagateCopy(operation);
+ PropagateCopy(ref buffer, node);
RemoveNode(block, node);
modified = true;
}
}
-
- node = nextNode;
}
}
}
@@ -80,13 +78,14 @@ namespace ARMeilleure.CodeGen.Optimizations
{
modified = false;
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
+ for (BasicBlock block = cfg.Blocks.Last; block != null; block = block.ListPrevious)
{
- Node node = block.Operations.First;
+ Operation node;
+ Operation prevNode;
- while (node != null)
+ for (node = block.Operations.Last; node != default; node = prevNode)
{
- Node nextNode = node.ListNext;
+ prevNode = node.ListPrevious;
if (IsUnused(node))
{
@@ -94,15 +93,27 @@ namespace ARMeilleure.CodeGen.Optimizations
modified = true;
}
-
- node = nextNode;
}
}
}
while (modified);
}
- private static bool PropagateCompare(Operation compOp)
+ private static Span<Operation> GetUses(ref Span<Operation> buffer, Operand operand)
+ {
+ ReadOnlySpan<Operation> uses = operand.Uses;
+
+ if (buffer.Length < uses.Length)
+ {
+ buffer = Allocators.Default.AllocateSpan<Operation>((uint)uses.Length);
+ }
+
+ uses.CopyTo(buffer);
+
+ return buffer.Slice(0, uses.Length);
+ }
+
+ private static bool PropagateCompare(ref Span<Operation> buffer, Operation compOp)
{
// Try to propagate Compare operations into their BranchIf uses, when these BranchIf uses are in the form
// of:
@@ -149,17 +160,12 @@ namespace ARMeilleure.CodeGen.Optimizations
Comparison compType = (Comparison)comp.AsInt32();
- Node[] uses = dest.Uses.ToArray();
+ Span<Operation> uses = GetUses(ref buffer, dest);
- foreach (Node use in uses)
+ foreach (Operation use in uses)
{
- if (!(use is Operation operation))
- {
- continue;
- }
-
// If operation is a BranchIf and has a constant value 0 in its RHS or LHS source operands.
- if (IsZeroBranch(operation, out Comparison otherCompType))
+ if (IsZeroBranch(use, out Comparison otherCompType))
{
Comparison propCompType;
@@ -176,9 +182,9 @@ namespace ARMeilleure.CodeGen.Optimizations
continue;
}
- operation.SetSource(0, src1);
- operation.SetSource(1, src2);
- operation.SetSource(2, Const((int)propCompType));
+ use.SetSource(0, src1);
+ use.SetSource(1, src2);
+ use.SetSource(2, Const((int)propCompType));
modified = true;
}
@@ -187,15 +193,15 @@ namespace ARMeilleure.CodeGen.Optimizations
return modified;
}
- private static void PropagateCopy(Operation copyOp)
+ private static void PropagateCopy(ref Span<Operation> buffer, Operation copyOp)
{
// Propagate copy source operand to all uses of the destination operand.
Operand dest = copyOp.Destination;
Operand source = copyOp.GetSource(0);
- Node[] uses = dest.Uses.ToArray();
+ Span<Operation> uses = GetUses(ref buffer, dest);
- foreach (Node use in uses)
+ foreach (Operation use in uses)
{
for (int index = 0; index < use.SourcesCount; index++)
{
@@ -207,7 +213,7 @@ namespace ARMeilleure.CodeGen.Optimizations
}
}
- private static void RemoveNode(BasicBlock block, Node node)
+ private static void RemoveNode(BasicBlock block, Operation node)
{
// Remove a node from the nodes list, and also remove itself
// from all the use lists on the operands that this node uses.
@@ -215,31 +221,31 @@ namespace ARMeilleure.CodeGen.Optimizations
for (int index = 0; index < node.SourcesCount; index++)
{
- node.SetSource(index, null);
+ node.SetSource(index, default);
}
- Debug.Assert(node.Destination == null || node.Destination.Uses.Count == 0);
+ Debug.Assert(node.Destination == default || node.Destination.UsesCount == 0);
- node.Destination = null;
+ node.Destination = default;
}
- private static bool IsUnused(Node node)
+ private static bool IsUnused(Operation node)
{
- return DestIsLocalVar(node) && node.Destination.Uses.Count == 0 && !HasSideEffects(node);
+ return DestIsLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
}
- private static bool DestIsLocalVar(Node node)
+ private static bool DestIsLocalVar(Operation node)
{
- return node.Destination != null && node.Destination.Kind == OperandKind.LocalVariable;
+ return node.Destination != default && node.Destination.Kind == OperandKind.LocalVariable;
}
- private static bool HasSideEffects(Node node)
+ private static bool HasSideEffects(Operation node)
{
- return (node is Operation operation) && (operation.Instruction == Instruction.Call
- || operation.Instruction == Instruction.Tailcall
- || operation.Instruction == Instruction.CompareAndSwap
- || operation.Instruction == Instruction.CompareAndSwap16
- || operation.Instruction == Instruction.CompareAndSwap8);
+ return node.Instruction == Instruction.Call
+ || node.Instruction == Instruction.Tailcall
+ || node.Instruction == Instruction.CompareAndSwap
+ || node.Instruction == Instruction.CompareAndSwap16
+ || node.Instruction == Instruction.CompareAndSwap8;
}
private static bool IsPropagableCompare(Operation operation)
diff --git a/ARMeilleure/CodeGen/Optimizations/Simplification.cs b/ARMeilleure/CodeGen/Optimizations/Simplification.cs
index db32e993..341143d8 100644
--- a/ARMeilleure/CodeGen/Optimizations/Simplification.cs
+++ b/ARMeilleure/CodeGen/Optimizations/Simplification.cs
@@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation;
using System;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
index 417f3bae..cc731b74 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
@@ -1,9 +1,8 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
-using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
+using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -210,7 +209,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operand register = GetRegister(left.Register, type);
- _spillQueue.Enqueue(Operation(Instruction.Spill, null, offset, register));
+ _spillQueue.Enqueue(Operation(Instruction.Spill, default, offset, register));
HasCopy = true;
}
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
index 2f68c43f..7b339efb 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
@@ -1,11 +1,10 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
-using System.Collections.Generic;
+using System;
using System.Diagnostics;
using System.Numerics;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
-using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
+using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -29,19 +28,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- private class LocalInfo
+ private struct LocalInfo
{
- public int Uses { get; set; }
- public int UseCount { get; set; }
-
- public bool PreAllocated { get; set; }
- public int Register { get; set; }
- public int SpillOffset { get; set; }
-
+ public int Uses { get; set; }
+ public int UsesAllocated { get; set; }
+ public int Register { get; set; }
+ public int SpillOffset { get; set; }
public int Sequence { get; set; }
-
public Operand Temp { get; set; }
-
public OperandType Type { get; }
private int _first;
@@ -49,13 +43,21 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public bool IsBlockLocal => _first == _last;
- public LocalInfo(OperandType type, int uses)
+ public LocalInfo(OperandType type, int uses, int blkIndex)
{
Uses = uses;
Type = type;
+ UsesAllocated = 0;
+ Register = 0;
+ SpillOffset = 0;
+ Sequence = 0;
+ Temp = default;
+
_first = -1;
_last = -1;
+
+ SetBlockIndex(blkIndex);
}
public void SetBlockIndex(int blkIndex)
@@ -72,10 +74,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- public AllocationResult RunPass(
- ControlFlowGraph cfg,
- StackAllocator stackAlloc,
- RegisterMasks regMasks)
+ public AllocationResult RunPass(ControlFlowGraph cfg, StackAllocator stackAlloc, RegisterMasks regMasks)
{
int intUsedRegisters = 0;
int vecUsedRegisters = 0;
@@ -84,9 +83,33 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int vecFreeRegisters = regMasks.VecAvailableRegisters;
var blockInfo = new BlockInfo[cfg.Blocks.Count];
+ var localInfo = new LocalInfo[cfg.Blocks.Count * 3];
+ int localInfoCount = 0;
+
+ // The "visited" state is stored in the MSB of the local's value.
+ const ulong VisitedMask = 1ul << 63;
+
+ bool IsVisited(Operand local)
+ {
+ return (local.GetValueUnsafe() & VisitedMask) != 0;
+ }
+
+ void SetVisited(Operand local)
+ {
+ local.GetValueUnsafe() |= VisitedMask | (uint)++localInfoCount;
+ }
+
+ ref LocalInfo GetLocalInfo(Operand local)
+ {
+ Debug.Assert(local.Kind == OperandKind.LocalVariable);
+
+ if (!IsVisited(local))
+ {
+ throw new InvalidOperationException("Local was not visisted yet. Used before defined?");
+ }
- var locInfo = new List<LocalInfo>();
- var locVisited = new HashSet<Operand>();
+ return ref localInfo[(uint)local.GetValueUnsafe() - 1];
+ }
for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--)
{
@@ -97,59 +120,58 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
bool hasCall = false;
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{
- if (node is Operation operation && operation.Instruction == Instruction.Call)
+ if (node.Instruction == Instruction.Call)
{
hasCall = true;
}
- for (int srcIndex = 0; srcIndex < node.SourcesCount; srcIndex++)
+ for (int i = 0; i < node.SourcesCount; i++)
{
- Operand source = node.GetSource(srcIndex);
+ Operand source = node.GetSource(i);
if (source.Kind == OperandKind.LocalVariable)
{
- locInfo[source.GetLocalNumber() - 1].SetBlockIndex(block.Index);
+ GetLocalInfo(source).SetBlockIndex(block.Index);
}
else if (source.Kind == OperandKind.Memory)
{
- MemoryOperand memOp = (MemoryOperand)source;
+ MemoryOperand memOp = source.GetMemory();
- if (memOp.BaseAddress != null)
+ if (memOp.BaseAddress != default)
{
- locInfo[memOp.BaseAddress.GetLocalNumber() - 1].SetBlockIndex(block.Index);
+ GetLocalInfo(memOp.BaseAddress).SetBlockIndex(block.Index);
}
- if (memOp.Index != null)
+ if (memOp.Index != default)
{
- locInfo[memOp.Index.GetLocalNumber() - 1].SetBlockIndex(block.Index);
+ GetLocalInfo(memOp.Index).SetBlockIndex(block.Index);
}
}
}
- for (int dstIndex = 0; dstIndex < node.DestinationsCount; dstIndex++)
+ for (int i = 0; i < node.DestinationsCount; i++)
{
- Operand dest = node.GetDestination(dstIndex);
+ Operand dest = node.GetDestination(i);
if (dest.Kind == OperandKind.LocalVariable)
{
- LocalInfo info;
-
- if (!locVisited.Add(dest))
+ if (IsVisited(dest))
{
- info = locInfo[dest.GetLocalNumber() - 1];
+ GetLocalInfo(dest).SetBlockIndex(block.Index);
}
else
{
- dest.NumberLocal(locInfo.Count + 1);
+ SetVisited(dest);
- info = new LocalInfo(dest.Type, UsesCount(dest));
+ if (localInfoCount > localInfo.Length)
+ {
+ Array.Resize(ref localInfo, localInfoCount * 2);
+ }
- locInfo.Add(info);
+ GetLocalInfo(dest) = new LocalInfo(dest.Type, UsesCount(dest), block.Index);
}
-
- info.SetBlockIndex(block.Index);
}
else if (dest.Kind == OperandKind.Register)
{
@@ -192,42 +214,26 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
intLocalFreeRegisters &= ~(intSpillTempRegisters | intCallerSavedRegisters);
vecLocalFreeRegisters &= ~(vecSpillTempRegisters | vecCallerSavedRegisters);
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{
int intLocalUse = 0;
int vecLocalUse = 0;
- void AllocateRegister(Operand source, MemoryOperand memOp, int srcIndex)
+ Operand AllocateRegister(Operand local)
{
- LocalInfo info = locInfo[source.GetLocalNumber() - 1];
+ ref LocalInfo info = ref GetLocalInfo(local);
- info.UseCount++;
+ info.UsesAllocated++;
- Debug.Assert(info.UseCount <= info.Uses);
+ Debug.Assert(info.UsesAllocated <= info.Uses);
if (info.Register != -1)
{
- Operand reg = Register(info.Register, source.Type.ToRegisterType(), source.Type);
-
- if (memOp != null)
- {
- if (srcIndex == 0)
- {
- memOp.BaseAddress = reg;
- }
- else /* if (srcIndex == 1) */
- {
- memOp.Index = reg;
- }
- }
- else
- {
- node.SetSource(srcIndex, reg);
- }
+ Operand reg = Register(info.Register, local.Type.ToRegisterType(), local.Type);
- if (info.UseCount == info.Uses && !info.PreAllocated)
+ if (info.UsesAllocated == info.Uses)
{
- if (source.Type.IsInteger())
+ if (local.Type.IsInteger())
{
intLocalFreeRegisters |= 1 << info.Register;
}
@@ -236,72 +242,80 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
vecLocalFreeRegisters |= 1 << info.Register;
}
}
- }
- else if (node is Operation operation && operation.Instruction == Instruction.Copy)
- {
- Operation fillOp = Operation(Instruction.Fill, node.Destination, Const(info.SpillOffset));
- block.Operations.AddBefore(node, fillOp);
- block.Operations.Remove(node);
-
- node = fillOp;
+ return reg;
}
else
{
Operand temp = info.Temp;
- if (temp == null || info.Sequence != sequence)
+ if (temp == default || info.Sequence != sequence)
{
- temp = source.Type.IsInteger()
- ? GetSpillTemp(source, intSpillTempRegisters, ref intLocalUse)
- : GetSpillTemp(source, vecSpillTempRegisters, ref vecLocalUse);
+ temp = local.Type.IsInteger()
+ ? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse)
+ : GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse);
info.Sequence = sequence;
info.Temp = temp;
}
- if (memOp != null)
- {
- if (srcIndex == 0)
- {
- memOp.BaseAddress = temp;
- }
- else /* if (srcIndex == 1) */
- {
- memOp.Index = temp;
- }
- }
- else
- {
- node.SetSource(srcIndex, temp);
- }
-
Operation fillOp = Operation(Instruction.Fill, temp, Const(info.SpillOffset));
block.Operations.AddBefore(node, fillOp);
+
+ return temp;
}
}
- for (int srcIndex = 0; srcIndex < node.SourcesCount; srcIndex++)
+ bool folded = false;
+
+ // If operation is a copy of a local and that local is living on the stack, we turn the copy into
+ // a fill, instead of inserting a fill before it.
+ if (node.Instruction == Instruction.Copy)
{
- Operand source = node.GetSource(srcIndex);
+ Operand source = node.GetSource(0);
if (source.Kind == OperandKind.LocalVariable)
{
- AllocateRegister(source, null, srcIndex);
+ ref LocalInfo info = ref GetLocalInfo(source);
+
+ if (info.Register == -1)
+ {
+ Operation fillOp = Operation(Instruction.Fill, node.Destination, Const(info.SpillOffset));
+
+ block.Operations.AddBefore(node, fillOp);
+ block.Operations.Remove(node);
+
+ node = fillOp;
+
+ folded = true;
+ }
}
- else if (source.Kind == OperandKind.Memory)
+ }
+
+ if (!folded)
+ {
+ for (int i = 0; i < node.SourcesCount; i++)
{
- MemoryOperand memOp = (MemoryOperand)source;
+ Operand source = node.GetSource(i);
- if (memOp.BaseAddress != null)
+ if (source.Kind == OperandKind.LocalVariable)
{
- AllocateRegister(memOp.BaseAddress, memOp, 0);
+ node.SetSource(i, AllocateRegister(source));
}
-
- if (memOp.Index != null)
+ else if (source.Kind == OperandKind.Memory)
{
- AllocateRegister(memOp.Index, memOp, 1);
+ MemoryOperand memOp = source.GetMemory();
+
+ if (memOp.BaseAddress != default)
+ {
+ memOp.BaseAddress = AllocateRegister(memOp.BaseAddress);
+ }
+
+ if (memOp.Index != default)
+ {
+ memOp.Index = AllocateRegister(memOp.Index);
+ }
}
}
}
@@ -309,18 +323,18 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int intLocalAsg = 0;
int vecLocalAsg = 0;
- for (int dstIndex = 0; dstIndex < node.DestinationsCount; dstIndex++)
+ for (int i = 0; i < node.DestinationsCount; i++)
{
- Operand dest = node.GetDestination(dstIndex);
+ Operand dest = node.GetDestination(i);
if (dest.Kind != OperandKind.LocalVariable)
{
continue;
}
- LocalInfo info = locInfo[dest.GetLocalNumber() - 1];
+ ref LocalInfo info = ref GetLocalInfo(dest);
- if (info.UseCount == 0 && !info.PreAllocated)
+ if (info.UsesAllocated == 0)
{
int mask = dest.Type.IsInteger()
? intLocalFreeRegisters
@@ -350,19 +364,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- info.UseCount++;
+ info.UsesAllocated++;
- Debug.Assert(info.UseCount <= info.Uses);
+ Debug.Assert(info.UsesAllocated <= info.Uses);
if (info.Register != -1)
{
- node.SetDestination(dstIndex, Register(info.Register, dest.Type.ToRegisterType(), dest.Type));
+ node.SetDestination(i, Register(info.Register, dest.Type.ToRegisterType(), dest.Type));
}
else
{
Operand temp = info.Temp;
- if (temp == null || info.Sequence != sequence)
+ if (temp == default || info.Sequence != sequence)
{
temp = dest.Type.IsInteger()
? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg)
@@ -372,9 +386,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
info.Temp = temp;
}
- node.SetDestination(dstIndex, temp);
+ node.SetDestination(i, temp);
- Operation spillOp = Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
+ Operation spillOp = Operation(Instruction.Spill, default, Const(info.SpillOffset), temp);
block.Operations.AddAfter(node, spillOp);
@@ -435,7 +449,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static int UsesCount(Operand local)
{
- return local.Assignments.Count + local.Uses.Count;
+ return local.AssignmentsCount + local.UsesCount;
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
index 88adeeb0..fd1420a2 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
@@ -29,11 +29,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private LiveInterval[] _parentIntervals;
- private List<(IntrusiveList<Node>, Node)> _operationNodes;
+ private List<(IntrusiveList<Operation>, Operation)> _operationNodes;
private int _operationsCount;
- private class AllocationContext : IDisposable
+ private class AllocationContext
{
public RegisterMasks Masks { get; }
@@ -50,10 +50,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
StackAlloc = stackAlloc;
Masks = masks;
- BitMapPool.PrepareBitMapPool();
-
- Active = BitMapPool.Allocate(intervalsCount);
- Inactive = BitMapPool.Allocate(intervalsCount);
+ Active = new BitMap(Allocators.Default, intervalsCount);
+ Inactive = new BitMap(Allocators.Default, intervalsCount);
}
public void MoveActiveToInactive(int bit)
@@ -72,11 +70,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
dest.Set(bit);
}
-
- public void Dispose()
- {
- BitMapPool.ResetBitMapPool();
- }
}
public AllocationResult RunPass(
@@ -86,7 +79,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
NumberLocals(cfg);
- using AllocationContext context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
+ var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
BuildIntervals(cfg, context);
@@ -588,7 +581,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int splitPosition = kv.Key;
- (IntrusiveList<Node> nodes, Node node) = GetOperationNode(splitPosition);
+ (IntrusiveList<Operation> nodes, Operation node) = GetOperationNode(splitPosition);
Operation[] sequence = copyResolver.Sequence();
@@ -621,9 +614,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
continue;
}
- bool hasSingleOrNoSuccessor = block.SuccessorCount <= 1;
+ bool hasSingleOrNoSuccessor = block.SuccessorsCount <= 1;
- for (int i = 0; i < block.SuccessorCount; i++)
+ for (int i = 0; i < block.SuccessorsCount; i++)
{
BasicBlock successor = block.GetSuccessor(i);
@@ -677,7 +670,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
successor.Operations.AddFirst(sequence[0]);
- Node prependNode = sequence[0];
+ Operation prependNode = sequence[0];
for (int index = 1; index < sequence.Length; index++)
{
@@ -710,7 +703,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
for (int i = usePositions.Count - 1; i >= 0; i--)
{
int usePosition = -usePositions[i];
- (_, Node operation) = GetOperationNode(usePosition);
+ (_, Operation operation) = GetOperationNode(usePosition);
for (int index = 0; index < operation.SourcesCount; index++)
{
@@ -722,7 +715,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
else if (source.Kind == OperandKind.Memory)
{
- MemoryOperand memOp = (MemoryOperand)source;
+ MemoryOperand memOp = source.GetMemory();
if (memOp.BaseAddress == current.Local)
{
@@ -752,20 +745,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
- return OperandHelper.Register(
+ return Operand.Factory.Register(
interval.Register.Index,
interval.Register.Type,
interval.Local.Type);
}
- private (IntrusiveList<Node>, Node) GetOperationNode(int position)
+ private (IntrusiveList<Operation>, Operation) GetOperationNode(int position)
{
return _operationNodes[position / InstructionGap];
}
private void NumberLocals(ControlFlowGraph cfg)
{
- _operationNodes = new List<(IntrusiveList<Node>, Node)>();
+ _operationNodes = new List<(IntrusiveList<Operation>, Operation)>();
_intervals = new List<LiveInterval>();
@@ -783,13 +776,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
BasicBlock block = cfg.PostOrderBlocks[index];
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{
_operationNodes.Add((block.Operations, node));
for (int i = 0; i < node.DestinationsCount; i++)
{
Operand dest = node.GetDestination(i);
+
if (dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
{
dest.NumberLocal(_intervals.Count);
@@ -804,7 +798,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (block.Operations.Count == 0)
{
// Pretend we have a dummy instruction on the empty block.
- _operationNodes.Add((null, null));
+ _operationNodes.Add((default, default));
_operationsCount += InstructionGap;
}
@@ -825,10 +819,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// Compute local live sets.
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{
- BitMap liveGen = BitMapPool.Allocate(mapSize);
- BitMap liveKill = BitMapPool.Allocate(mapSize);
+ BitMap liveGen = new BitMap(Allocators.Default, mapSize);
+ BitMap liveKill = new BitMap(Allocators.Default, mapSize);
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{
Sources(node, (source) =>
{
@@ -857,8 +851,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
for (int index = 0; index < cfg.Blocks.Count; index++)
{
- blkLiveIn [index] = BitMapPool.Allocate(mapSize);
- blkLiveOut[index] = BitMapPool.Allocate(mapSize);
+ blkLiveIn [index] = new BitMap(Allocators.Default, mapSize);
+ blkLiveOut[index] = new BitMap(Allocators.Default, mapSize);
}
bool modified;
@@ -873,7 +867,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
BitMap liveOut = blkLiveOut[block.Index];
- for (int i = 0; i < block.SuccessorCount; i++)
+ for (int i = 0; i < block.SuccessorsCount; i++)
{
BasicBlock succ = block.GetSuccessor(i);
@@ -926,7 +920,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
continue;
}
- foreach (Node node in BottomOperations(block))
+ foreach (Operation node in BottomOperations(block))
{
operationPos -= InstructionGap;
@@ -947,7 +941,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
interval.AddUsePosition(operationPos);
});
- if (node is Operation operation && operation.Instruction == Instruction.Call)
+ if (node.Instruction == Instruction.Call)
{
AddIntervalCallerSavedReg(context.Masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
AddIntervalCallerSavedReg(context.Masks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
@@ -993,11 +987,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return (register.Index << 1) | (register.Type == RegisterType.Vector ? 1 : 0);
}
- private static IEnumerable<Node> BottomOperations(BasicBlock block)
+ private static IEnumerable<Operation> BottomOperations(BasicBlock block)
{
- Node node = block.Operations.Last;
+ Operation node = block.Operations.Last;
- while (node != null && !(node is PhiNode))
+ while (node != default)
{
yield return node;
@@ -1005,7 +999,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- private static void Sources(Node node, Action<Operand> action)
+ private static void Sources(Operation node, Action<Operand> action)
{
for (int index = 0; index < node.SourcesCount; index++)
{
@@ -1017,14 +1011,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
else if (source.Kind == OperandKind.Memory)
{
- MemoryOperand memOp = (MemoryOperand)source;
+ MemoryOperand memOp = source.GetMemory();
- if (memOp.BaseAddress != null)
+ if (memOp.BaseAddress != default)
{
action(memOp.BaseAddress);
}
- if (memOp.Index != null)
+ if (memOp.Index != default)
{
action(memOp.Index);
}
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
index 309c5ba3..be587652 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
@@ -34,7 +34,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public bool IsEmpty => _ranges.Count == 0;
- public LiveInterval(Operand local = null, LiveInterval parent = null)
+ public LiveInterval(Operand local = default, LiveInterval parent = null)
{
Local = local;
_parent = parent ?? this;
diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs
index 39aeb7c9..044f6047 100644
--- a/ARMeilleure/CodeGen/X86/Assembler.cs
+++ b/ARMeilleure/CodeGen/X86/Assembler.cs
@@ -329,12 +329,12 @@ namespace ARMeilleure.CodeGen.X86
public void Bswap(Operand dest)
{
- WriteInstruction(dest, null, dest.Type, X86Instruction.Bswap);
+ WriteInstruction(dest, default, dest.Type, X86Instruction.Bswap);
}
public void Call(Operand dest)
{
- WriteInstruction(dest, null, OperandType.None, X86Instruction.Call);
+ WriteInstruction(dest, default, OperandType.None, X86Instruction.Call);
}
public void Cdq()
@@ -346,7 +346,7 @@ namespace ARMeilleure.CodeGen.X86
{
InstructionInfo info = _instTable[(int)X86Instruction.Cmovcc];
- WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM | (int)condition, rrm: true);
+ WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM | (int)condition, rrm: true);
}
public void Cmp(Operand src1, Operand src2, OperandType type)
@@ -360,30 +360,38 @@ namespace ARMeilleure.CodeGen.X86
WriteByte(0x99);
}
- public void Cmpxchg(MemoryOperand memOp, Operand src)
+ public void Cmpxchg(Operand memOp, Operand src)
{
+ Debug.Assert(memOp.Kind == OperandKind.Memory);
+
WriteByte(LockPrefix);
WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg);
}
- public void Cmpxchg16(MemoryOperand memOp, Operand src)
+ public void Cmpxchg16(Operand memOp, Operand src)
{
+ Debug.Assert(memOp.Kind == OperandKind.Memory);
+
WriteByte(LockPrefix);
WriteByte(0x66);
WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg);
}
- public void Cmpxchg16b(MemoryOperand memOp)
+ public void Cmpxchg16b(Operand memOp)
{
+ Debug.Assert(memOp.Kind == OperandKind.Memory);
+
WriteByte(LockPrefix);
- WriteInstruction(memOp, null, OperandType.None, X86Instruction.Cmpxchg16b);
+ WriteInstruction(memOp, default, OperandType.None, X86Instruction.Cmpxchg16b);
}
- public void Cmpxchg8(MemoryOperand memOp, Operand src)
+ public void Cmpxchg8(Operand memOp, Operand src)
{
+ Debug.Assert(memOp.Kind == OperandKind.Memory);
+
WriteByte(LockPrefix);
WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg8);
@@ -391,12 +399,12 @@ namespace ARMeilleure.CodeGen.X86
public void Comisd(Operand src1, Operand src2)
{
- WriteInstruction(src1, null, src2, X86Instruction.Comisd);
+ WriteInstruction(src1, default, src2, X86Instruction.Comisd);
}
public void Comiss(Operand src1, Operand src2)
{
- WriteInstruction(src1, null, src2, X86Instruction.Comiss);
+ WriteInstruction(src1, default, src2, X86Instruction.Comiss);
}
public void Cvtsd2ss(Operand dest, Operand src1, Operand src2)
@@ -421,7 +429,7 @@ namespace ARMeilleure.CodeGen.X86
public void Div(Operand source)
{
- WriteInstruction(null, source, source.Type, X86Instruction.Div);
+ WriteInstruction(default, source, source.Type, X86Instruction.Div);
}
public void Divsd(Operand dest, Operand src1, Operand src2)
@@ -436,12 +444,12 @@ namespace ARMeilleure.CodeGen.X86
public void Idiv(Operand source)
{
- WriteInstruction(null, source, source.Type, X86Instruction.Idiv);
+ WriteInstruction(default, source, source.Type, X86Instruction.Idiv);
}
public void Imul(Operand source)
{
- WriteInstruction(null, source, source.Type, X86Instruction.Imul128);
+ WriteInstruction(default, source, source.Type, X86Instruction.Imul128);
}
public void Imul(Operand dest, Operand source, OperandType type)
@@ -465,13 +473,13 @@ namespace ARMeilleure.CodeGen.X86
if (IsImm8(src2.Value, src2.Type) && info.OpRMImm8 != BadOp)
{
- WriteOpCode(dest, null, src1, type, info.Flags, info.OpRMImm8, rrm: true);
+ WriteOpCode(dest, default, src1, type, info.Flags, info.OpRMImm8, rrm: true);
WriteByte(src2.AsByte());
}
else if (IsImm32(src2.Value, src2.Type) && info.OpRMImm32 != BadOp)
{
- WriteOpCode(dest, null, src1, type, info.Flags, info.OpRMImm32, rrm: true);
+ WriteOpCode(dest, default, src1, type, info.Flags, info.OpRMImm32, rrm: true);
WriteInt32(src2.AsInt32());
}
@@ -531,12 +539,12 @@ namespace ARMeilleure.CodeGen.X86
public void Jmp(Operand dest)
{
- WriteInstruction(dest, null, OperandType.None, X86Instruction.Jmp);
+ WriteInstruction(dest, default, OperandType.None, X86Instruction.Jmp);
}
public void Ldmxcsr(Operand dest)
{
- WriteInstruction(dest, null, OperandType.I32, X86Instruction.Ldmxcsr);
+ WriteInstruction(dest, default, OperandType.I32, X86Instruction.Ldmxcsr);
}
public void Lea(Operand dest, Operand source, OperandType type)
@@ -565,17 +573,17 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
{
- WriteOpCode(dest, null, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
+ WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
}
else
{
- WriteOpCode(dest, null, source, OperandType.None, info.Flags, info.OpRMR);
+ WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRMR);
}
}
public void Movdqu(Operand dest, Operand source)
{
- WriteInstruction(dest, null, source, X86Instruction.Movdqu);
+ WriteInstruction(dest, default, source, X86Instruction.Movdqu);
}
public void Movhlps(Operand dest, Operand src1, Operand src2)
@@ -596,11 +604,11 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
{
- WriteOpCode(dest, null, source, OperandType.None, flags, info.OpRRM, rrm: true);
+ WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true);
}
else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory)
{
- WriteOpCode(dest, null, source, OperandType.None, flags, info.OpRMR);
+ WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR);
}
else
{
@@ -645,7 +653,7 @@ namespace ARMeilleure.CodeGen.X86
public void Mul(Operand source)
{
- WriteInstruction(null, source, source.Type, X86Instruction.Mul128);
+ WriteInstruction(default, source, source.Type, X86Instruction.Mul128);
}
public void Mulsd(Operand dest, Operand src1, Operand src2)
@@ -660,12 +668,12 @@ namespace ARMeilleure.CodeGen.X86
public void Neg(Operand dest)
{
- WriteInstruction(dest, null, dest.Type, X86Instruction.Neg);
+ WriteInstruction(dest, default, dest.Type, X86Instruction.Neg);
}
public void Not(Operand dest)
{
- WriteInstruction(dest, null, dest.Type, X86Instruction.Not);
+ WriteInstruction(dest, default, dest.Type, X86Instruction.Not);
}
public void Or(Operand dest, Operand source, OperandType type)
@@ -675,7 +683,7 @@ namespace ARMeilleure.CodeGen.X86
public void Pclmulqdq(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pclmulqdq);
+ WriteInstruction(dest, default, source, X86Instruction.Pclmulqdq);
WriteByte(imm);
}
@@ -687,28 +695,28 @@ namespace ARMeilleure.CodeGen.X86
public void Pextrb(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pextrb);
+ WriteInstruction(dest, default, source, X86Instruction.Pextrb);
WriteByte(imm);
}
public void Pextrd(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pextrd);
+ WriteInstruction(dest, default, source, X86Instruction.Pextrd);
WriteByte(imm);
}
public void Pextrq(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pextrq);
+ WriteInstruction(dest, default, source, X86Instruction.Pextrq);
WriteByte(imm);
}
public void Pextrw(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pextrw);
+ WriteInstruction(dest, default, source, X86Instruction.Pextrw);
WriteByte(imm);
}
@@ -749,7 +757,7 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
- WriteInstruction(dest, null, dest.Type, X86Instruction.Pop);
+ WriteInstruction(dest, default, dest.Type, X86Instruction.Pop);
}
}
@@ -760,7 +768,7 @@ namespace ARMeilleure.CodeGen.X86
public void Pshufd(Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, X86Instruction.Pshufd);
+ WriteInstruction(dest, default, source, X86Instruction.Pshufd);
WriteByte(imm);
}
@@ -773,7 +781,7 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
- WriteInstruction(null, source, source.Type, X86Instruction.Push);
+ WriteInstruction(default, source, source.Type, X86Instruction.Push);
}
}
@@ -806,12 +814,12 @@ namespace ARMeilleure.CodeGen.X86
{
InstructionInfo info = _instTable[(int)X86Instruction.Setcc];
- WriteOpCode(dest, null, null, OperandType.None, info.Flags, info.OpRRM | (int)condition);
+ WriteOpCode(dest, default, default, OperandType.None, info.Flags, info.OpRRM | (int)condition);
}
public void Stmxcsr(Operand dest)
{
- WriteInstruction(dest, null, OperandType.I32, X86Instruction.Stmxcsr);
+ WriteInstruction(dest, default, OperandType.I32, X86Instruction.Stmxcsr);
}
public void Sub(Operand dest, Operand source, OperandType type)
@@ -850,7 +858,7 @@ namespace ARMeilleure.CodeGen.X86
Operand source,
OperandType type = OperandType.None)
{
- WriteInstruction(dest, null, source, inst, type);
+ WriteInstruction(dest, default, source, inst, type);
}
public void WriteInstruction(X86Instruction inst, Operand dest, Operand src1, Operand src2)
@@ -877,7 +885,7 @@ namespace ARMeilleure.CodeGen.X86
public void WriteInstruction(X86Instruction inst, Operand dest, Operand source, byte imm)
{
- WriteInstruction(dest, null, source, inst);
+ WriteInstruction(dest, default, source, inst);
WriteByte(imm);
}
@@ -917,11 +925,11 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(shiftReg == X86Register.Rcx, $"Invalid shift register \"{shiftReg}\".");
- source = null;
+ source = default;
}
else if (source.Kind == OperandKind.Constant)
{
- source = source.With((int)source.Value & (dest.Type == OperandType.I32 ? 0x1f : 0x3f));
+ source = Operand.Factory.Const((int)source.Value & (dest.Type == OperandType.I32 ? 0x1f : 0x3f));
}
WriteInstruction(dest, source, type, inst);
@@ -931,7 +939,7 @@ namespace ARMeilleure.CodeGen.X86
{
InstructionInfo info = _instTable[(int)inst];
- if (source != null)
+ if (source != default)
{
if (source.Kind == OperandKind.Constant)
{
@@ -939,29 +947,29 @@ namespace ARMeilleure.CodeGen.X86
if (inst == X86Instruction.Mov8)
{
- WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm8);
+ WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else if (inst == X86Instruction.Mov16)
{
- WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm32);
+ WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt16((short)imm);
}
else if (IsImm8(imm, type) && info.OpRMImm8 != BadOp)
{
- WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm8);
+ WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else if (!source.Relocatable && IsImm32(imm, type) && info.OpRMImm32 != BadOp)
{
- WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm32);
+ WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt32((int)imm);
}
- else if (dest?.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
+ else if (dest != default && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
{
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
@@ -972,7 +980,7 @@ namespace ARMeilleure.CodeGen.X86
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
- if (_ptcInfo != null && source.Relocatable)
+ if (_ptcInfo != default && source.Relocatable)
{
_ptcInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, source.Symbol));
}
@@ -986,11 +994,11 @@ namespace ARMeilleure.CodeGen.X86
}
else if (source.Kind == OperandKind.Register && info.OpRMR != BadOp)
{
- WriteOpCode(dest, null, source, type, info.Flags, info.OpRMR);
+ WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR);
}
else if (info.OpRRM != BadOp)
{
- WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM, rrm: true);
+ WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true);
}
else
{
@@ -999,11 +1007,11 @@ namespace ARMeilleure.CodeGen.X86
}
else if (info.OpRRM != BadOp)
{
- WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM, rrm: true);
+ WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true);
}
else if (info.OpRMR != BadOp)
{
- WriteOpCode(dest, null, source, type, info.Flags, info.OpRMR);
+ WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR);
}
else
{
@@ -1020,7 +1028,7 @@ namespace ARMeilleure.CodeGen.X86
{
InstructionInfo info = _instTable[(int)inst];
- if (src2 != null)
+ if (src2 != default)
{
if (src2.Kind == OperandKind.Constant)
{
@@ -1028,7 +1036,7 @@ namespace ARMeilleure.CodeGen.X86
if ((byte)imm == imm && info.OpRMImm8 != BadOp)
{
- WriteOpCode(dest, src1, null, type, info.Flags, info.OpRMImm8);
+ WriteOpCode(dest, src1, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
@@ -1082,9 +1090,10 @@ namespace ARMeilleure.CodeGen.X86
int modRM = (opCode >> OpModRMBits) << 3;
- MemoryOperand memOp = null;
+ MemoryOperand memOp = default;
+ bool hasMemOp = false;
- if (dest != null)
+ if (dest != default)
{
if (dest.Kind == OperandKind.Register)
{
@@ -1099,7 +1108,8 @@ namespace ARMeilleure.CodeGen.X86
}
else if (dest.Kind == OperandKind.Memory)
{
- memOp = dest as MemoryOperand;
+ memOp = dest.GetMemory();
+ hasMemOp = true;
}
else
{
@@ -1107,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86
}
}
- if (src2 != null)
+ if (src2 != default)
{
if (src2.Kind == OperandKind.Register)
{
@@ -1120,9 +1130,10 @@ namespace ARMeilleure.CodeGen.X86
rexPrefix |= RexPrefix;
}
}
- else if (src2.Kind == OperandKind.Memory && memOp == null)
+ else if (src2.Kind == OperandKind.Memory && !hasMemOp)
{
- memOp = src2 as MemoryOperand;
+ memOp = src2.GetMemory();
+ hasMemOp = true;
}
else
{
@@ -1135,14 +1146,14 @@ namespace ARMeilleure.CodeGen.X86
int sib = 0;
- if (memOp != null)
+ if (hasMemOp)
{
// Either source or destination is a memory operand.
Register baseReg = memOp.BaseAddress.GetRegister();
X86Register baseRegLow = (X86Register)(baseReg.Index & 0b111);
- needsSibByte = memOp.Index != null || baseRegLow == X86Register.Rsp;
+ needsSibByte = memOp.Index != default || baseRegLow == X86Register.Rsp;
needsDisplacement = memOp.Displacement != 0 || baseRegLow == X86Register.Rbp;
if (needsDisplacement)
@@ -1168,7 +1179,7 @@ namespace ARMeilleure.CodeGen.X86
{
sib = (int)baseRegLow;
- if (memOp.Index != null)
+ if (memOp.Index != default)
{
int indexReg = memOp.Index.GetRegister().Index;
@@ -1217,7 +1228,7 @@ namespace ARMeilleure.CodeGen.X86
_ => 0
};
- if (src1 != null)
+ if (src1 != default)
{
vexByte2 |= (src1.GetRegister().Index ^ 0xf) << 3;
}
@@ -1284,7 +1295,7 @@ namespace ARMeilleure.CodeGen.X86
}
}
- if (dest != null && (flags & InstructionFlags.RegOnly) != 0)
+ if (dest != default && (flags & InstructionFlags.RegOnly) != 0)
{
opCode += dest.GetRegister().Index & 7;
}
@@ -1353,12 +1364,12 @@ namespace ARMeilleure.CodeGen.X86
}
}
- if (dest != null && dest.Kind == OperandKind.Register)
+ if (dest != default && dest.Kind == OperandKind.Register)
{
SetRegisterHighBit(dest.GetRegister(), rrm ? 2 : 0);
}
- if (source != null && source.Kind == OperandKind.Register)
+ if (source != default && source.Kind == OperandKind.Register)
{
SetRegisterHighBit(source.GetRegister(), rrm ? 0 : 2);
}
diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
index 3c14594d..5818eb2e 100644
--- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs
+++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
@@ -11,8 +11,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Numerics;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.X86
{
@@ -162,20 +161,18 @@ namespace ARMeilleure.CodeGen.X86
{
context.EnterBlock(block);
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{
- if (node is Operation operation)
- {
- GenerateOperation(context, operation);
- }
+ GenerateOperation(context, node);
}
- if (block.SuccessorCount == 0)
+ if (block.SuccessorsCount == 0)
{
// The only blocks which can have 0 successors are exit blocks.
- Debug.Assert(block.Operations.Last is Operation operation &&
- (operation.Instruction == Instruction.Tailcall ||
- operation.Instruction == Instruction.Return));
+ Operation last = block.Operations.Last;
+
+ Debug.Assert(last.Instruction == Instruction.Tailcall ||
+ last.Instruction == Instruction.Return);
}
else
{
@@ -205,9 +202,7 @@ namespace ARMeilleure.CodeGen.X86
{
if (operation.Instruction == Instruction.Extended)
{
- IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
-
- IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic);
+ IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
switch (info.Type)
{
@@ -217,7 +212,7 @@ namespace ARMeilleure.CodeGen.X86
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
- switch (intrinOp.Intrinsic)
+ switch (operation.Intrinsic)
{
case Intrinsic.X86Comisdeq:
context.Assembler.Comisd(src1, src2);
@@ -266,14 +261,13 @@ namespace ARMeilleure.CodeGen.X86
int offs = offset.AsInt32() + context.CallArgsRegionSize;
Operand rsp = Register(X86Register.Rsp);
-
- MemoryOperand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, offs);
+ Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, offs);
Debug.Assert(HardwareCapabilities.SupportsSse || HardwareCapabilities.SupportsVexEncoding);
context.Assembler.Stmxcsr(memOp);
- if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb)
+ if (operation.Intrinsic == Intrinsic.X86Mxcsrmb)
{
context.Assembler.Or(memOp, bits, OperandType.I32);
}
@@ -324,7 +318,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger());
- if (intrinOp.Intrinsic == Intrinsic.X86Cvtsi2si)
+ if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{
if (dest.Type == OperandType.I32)
{
@@ -538,7 +532,7 @@ namespace ARMeilleure.CodeGen.X86
if (src2.Kind == OperandKind.Constant)
{
offset = src2.AsInt32();
- index = null;
+ index = default;
}
else
{
@@ -546,7 +540,7 @@ namespace ARMeilleure.CodeGen.X86
index = src2;
}
- MemoryOperand memOp = MemoryOp(dest.Type, src1, index, Multiplier.x1, offset);
+ Operand memOp = MemoryOp(dest.Type, src1, index, Multiplier.x1, offset);
context.Assembler.Lea(dest, memOp, dest.Type);
}
@@ -720,7 +714,7 @@ namespace ARMeilleure.CodeGen.X86
if (operation.SourcesCount == 5) // CompareAndSwap128 has 5 sources, compared to CompareAndSwap64/32's 3.
{
- MemoryOperand memOp = MemoryOp(OperandType.I64, src1);
+ Operand memOp = MemoryOp(OperandType.I64, src1);
context.Assembler.Cmpxchg16b(memOp);
}
@@ -731,7 +725,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src2, src3);
- MemoryOperand memOp = MemoryOp(src3.Type, src1);
+ Operand memOp = MemoryOp(src3.Type, src1);
context.Assembler.Cmpxchg(memOp, src3);
}
@@ -745,7 +739,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src2, src3);
- MemoryOperand memOp = MemoryOp(src3.Type, src1);
+ Operand memOp = MemoryOp(src3.Type, src1);
context.Assembler.Cmpxchg16(memOp, src3);
}
@@ -758,7 +752,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src2, src3);
- MemoryOperand memOp = MemoryOp(src3.Type, src1);
+ Operand memOp = MemoryOp(src3.Type, src1);
context.Assembler.Cmpxchg8(memOp, src3);
}
@@ -954,7 +948,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = MemoryOp(dest.Type, rsp, null, Multiplier.x1, offs);
+ Operand memOp = MemoryOp(dest.Type, rsp, default, Multiplier.x1, offs);
GenerateLoad(context, memOp, dest);
}
@@ -1153,7 +1147,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = MemoryOp(source.Type, rsp, null, Multiplier.x1, offs);
+ Operand memOp = MemoryOp(source.Type, rsp, default, Multiplier.x1, offs);
GenerateStore(context, memOp, source);
}
@@ -1169,7 +1163,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = MemoryOp(OperandType.I64, rsp, null, Multiplier.x1, offs);
+ Operand memOp = MemoryOp(OperandType.I64, rsp, default, Multiplier.x1, offs);
context.Assembler.Lea(dest, memOp, OperandType.I64);
}
@@ -1644,19 +1638,19 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Pshufd(dest, dest, 0xfc);
}
- private static bool MatchOperation(Node node, Instruction inst, OperandType destType, Register destReg)
+ private static bool MatchOperation(Operation node, Instruction inst, OperandType destType, Register destReg)
{
- if (!(node is Operation operation) || node.DestinationsCount == 0)
+ if (node == default || node.DestinationsCount == 0)
{
return false;
}
- if (operation.Instruction != inst)
+ if (node.Instruction != inst)
{
return false;
}
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
return dest.Kind == OperandKind.Register &&
dest.Type == destType &&
@@ -1761,7 +1755,7 @@ namespace ARMeilleure.CodeGen.X86
offset -= 16;
- MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
+ Operand memOp = MemoryOp(OperandType.V128, rsp, default, Multiplier.x1, offset);
context.Assembler.Movdqu(memOp, Xmm((X86Register)bit));
@@ -1791,7 +1785,7 @@ namespace ARMeilleure.CodeGen.X86
offset -= 16;
- MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
+ Operand memOp = MemoryOp(OperandType.V128, rsp, default, Multiplier.x1, offset);
context.Assembler.Movdqu(Xmm((X86Register)bit), memOp);
@@ -1832,17 +1826,17 @@ namespace ARMeilleure.CodeGen.X86
for (int offset = PageSize; offset < size; offset += PageSize)
{
- Operand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, -offset);
+ Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, -offset);
context.Assembler.Mov(temp, memOp, OperandType.I32);
}
}
- private static MemoryOperand Memory(Operand operand, OperandType type)
+ private static Operand Memory(Operand operand, OperandType type)
{
if (operand.Kind == OperandKind.Memory)
{
- return operand as MemoryOperand;
+ return operand;
}
return MemoryOp(type, operand);
@@ -1850,12 +1844,12 @@ namespace ARMeilleure.CodeGen.X86
private static Operand Register(X86Register register, OperandType type = OperandType.I64)
{
- return OperandHelper.Register((int)register, RegisterType.Integer, type);
+ return Operand.Factory.Register((int)register, RegisterType.Integer, type);
}
private static Operand Xmm(X86Register register)
{
- return OperandHelper.Register((int)register, RegisterType.Vector, OperandType.V128);
+ return Operand.Factory.Register((int)register, RegisterType.Vector, OperandType.V128);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs
index 3b3fd683..334f8f7e 100644
--- a/ARMeilleure/CodeGen/X86/PreAllocator.cs
+++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs
@@ -4,9 +4,8 @@ using ARMeilleure.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
-using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
+using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.X86
{
@@ -22,31 +21,31 @@ namespace ARMeilleure.CodeGen.X86
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
{
- Node nextNode;
+ Operation nextNode;
- for (Node node = block.Operations.First; node != null; node = nextNode)
+ for (Operation node = block.Operations.First; node != default; node = nextNode)
{
nextNode = node.ListNext;
- if (node is not Operation operation)
+ if (node.Instruction == Instruction.Phi)
{
continue;
}
- HandleConstantRegCopy(block.Operations, node, operation);
- HandleDestructiveRegCopy(block.Operations, node, operation);
- HandleConstrainedRegCopy(block.Operations, node, operation);
+ HandleConstantRegCopy(block.Operations, node);
+ HandleDestructiveRegCopy(block.Operations, node);
+ HandleConstrainedRegCopy(block.Operations, node);
- switch (operation.Instruction)
+ switch (node.Instruction)
{
case Instruction.Call:
// Get the maximum number of arguments used on a call.
// On windows, when a struct is returned from the call,
// we also need to pass the pointer where the struct
// should be written on the first argument.
- int argsCount = operation.SourcesCount - 1;
+ int argsCount = node.SourcesCount - 1;
- if (operation.Destination != null && operation.Destination.Type == OperandType.V128)
+ if (node.Destination != default && node.Destination.Type == OperandType.V128)
{
argsCount++;
}
@@ -60,72 +59,71 @@ namespace ARMeilleure.CodeGen.X86
// being called, as mandated by the ABI.
if (callConv == CallConvName.Windows)
{
- HandleCallWindowsAbi(block.Operations, stackAlloc, node, operation);
+ HandleCallWindowsAbi(block.Operations, stackAlloc, node);
}
else /* if (callConv == CallConvName.SystemV) */
{
- HandleCallSystemVAbi(block.Operations, node, operation);
+ HandleCallSystemVAbi(block.Operations, node);
}
break;
case Instruction.ConvertToFPUI:
- HandleConvertToFPUI(block.Operations, node, operation);
+ HandleConvertToFPUI(block.Operations, node);
break;
case Instruction.LoadArgument:
if (callConv == CallConvName.Windows)
{
- nextNode = HandleLoadArgumentWindowsAbi(cctx, block.Operations, node, preservedArgs, operation);
+ nextNode = HandleLoadArgumentWindowsAbi(cctx, block.Operations, preservedArgs, node);
}
else /* if (callConv == CallConvName.SystemV) */
{
- nextNode = HandleLoadArgumentSystemVAbi(cctx, block.Operations, node, preservedArgs, operation);
+ nextNode = HandleLoadArgumentSystemVAbi(cctx, block.Operations, preservedArgs, node);
}
break;
case Instruction.Negate:
- if (!operation.GetSource(0).Type.IsInteger())
+ if (!node.GetSource(0).Type.IsInteger())
{
- HandleNegate(block.Operations, node, operation);
+ HandleNegate(block.Operations, node);
}
break;
case Instruction.Return:
if (callConv == CallConvName.Windows)
{
- HandleReturnWindowsAbi(cctx, block.Operations, node, preservedArgs, operation);
+ HandleReturnWindowsAbi(cctx, block.Operations, preservedArgs, node);
}
else /* if (callConv == CallConvName.SystemV) */
{
- HandleReturnSystemVAbi(block.Operations, node, operation);
+ HandleReturnSystemVAbi(block.Operations, node);
}
break;
case Instruction.Tailcall:
if (callConv == CallConvName.Windows)
{
- HandleTailcallWindowsAbi(block.Operations, stackAlloc, node, operation);
+ HandleTailcallWindowsAbi(block.Operations, stackAlloc, node);
}
else
{
- HandleTailcallSystemVAbi(block.Operations, stackAlloc, node, operation);
+ HandleTailcallSystemVAbi(block.Operations, stackAlloc, node);
}
break;
case Instruction.VectorInsert8:
if (!HardwareCapabilities.SupportsSse41)
{
- HandleVectorInsert8(block.Operations, node, operation);
+ HandleVectorInsert8(block.Operations, node);
}
break;
case Instruction.Extended:
- IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
-
- if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb || intrinOp.Intrinsic == Intrinsic.X86Mxcsrub)
+ if (node.Intrinsic == Intrinsic.X86Mxcsrmb || node.Intrinsic == Intrinsic.X86Mxcsrub)
{
int stackOffset = stackAlloc.Allocate(OperandType.I32);
- operation.SetSources(new Operand[] { Const(stackOffset), operation.GetSource(0) });
+
+ node.SetSources(new Operand[] { Const(stackOffset), node.GetSource(0) });
}
break;
}
@@ -133,16 +131,16 @@ namespace ARMeilleure.CodeGen.X86
}
}
- private static void HandleConstantRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleConstantRegCopy(IntrusiveList<Operation> nodes, Operation node)
{
- if (operation.SourcesCount == 0 || IsXmmIntrinsic(operation))
+ if (node.SourcesCount == 0 || IsXmmIntrinsic(node))
{
return;
}
- Instruction inst = operation.Instruction;
+ Instruction inst = node.Instruction;
- Operand src1 = operation.GetSource(0);
+ Operand src1 = node.GetSource(0);
Operand src2;
if (src1.Kind == OperandKind.Constant)
@@ -156,7 +154,7 @@ namespace ARMeilleure.CodeGen.X86
// - Replace the constant use with the XMM register.
src1 = AddXmmCopy(nodes, node, src1);
- operation.SetSource(0, src1);
+ node.SetSource(0, src1);
}
else if (!HasConstSrc1(inst))
{
@@ -168,34 +166,34 @@ namespace ARMeilleure.CodeGen.X86
// -- Doing so may allow us to encode the constant as operand 2 and avoid a copy.
// - If the constant is on operand 2, we check if the instruction supports it,
// if not, we also add a copy. 64-bits constants are usually not supported.
- if (IsCommutative(operation))
+ if (IsCommutative(node))
{
- src2 = operation.GetSource(1);
+ src2 = node.GetSource(1);
Operand temp = src1;
src1 = src2;
src2 = temp;
- operation.SetSource(0, src1);
- operation.SetSource(1, src2);
+ node.SetSource(0, src1);
+ node.SetSource(1, src2);
}
if (src1.Kind == OperandKind.Constant)
{
src1 = AddCopy(nodes, node, src1);
- operation.SetSource(0, src1);
+ node.SetSource(0, src1);
}
}
}
- if (operation.SourcesCount < 2)
+ if (node.SourcesCount < 2)
{
return;
}
- src2 = operation.GetSource(1);
+ src2 = node.GetSource(1);
if (src2.Kind == OperandKind.Constant)
{
@@ -203,28 +201,28 @@ namespace ARMeilleure.CodeGen.X86
{
src2 = AddXmmCopy(nodes, node, src2);
- operation.SetSource(1, src2);
+ node.SetSource(1, src2);
}
else if (!HasConstSrc2(inst) || CodeGenCommon.IsLongConst(src2))
{
src2 = AddCopy(nodes, node, src2);
- operation.SetSource(1, src2);
+ node.SetSource(1, src2);
}
}
}
- private static void HandleConstrainedRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleConstrainedRegCopy(IntrusiveList<Operation> nodes, Operation node)
{
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
- switch (operation.Instruction)
+ switch (node.Instruction)
{
case Instruction.CompareAndSwap:
case Instruction.CompareAndSwap16:
case Instruction.CompareAndSwap8:
{
- OperandType type = operation.GetSource(1).Type;
+ OperandType type = node.GetSource(1).Type;
if (type == OperandType.V128)
{
@@ -243,14 +241,15 @@ namespace ARMeilleure.CodeGen.X86
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
Operand rdx = Gpr(X86Register.Rdx, OperandType.I64);
- SplitOperand(operation.GetSource(1), rax, rdx);
- SplitOperand(operation.GetSource(2), rbx, rcx);
+ SplitOperand(node.GetSource(1), rax, rdx);
+ SplitOperand(node.GetSource(2), rbx, rcx);
+
+ Operation operation = node;
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
operation.SetDestinations(new Operand[] { rdx, rax });
-
operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
}
else
@@ -258,8 +257,8 @@ namespace ARMeilleure.CodeGen.X86
// Handle the many restrictions of the compare and exchange (32/64) instruction:
// - The expected value should be in (E/R)AX.
// - The value at the memory location is loaded to (E/R)AX.
- Operand expected = operation.GetSource(1);
- Operand newValue = operation.GetSource(2);
+ Operand expected = node.GetSource(1);
+ Operand newValue = node.GetSource(2);
Operand rax = Gpr(X86Register.Rax, expected.Type);
@@ -271,11 +270,11 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
- operation.SetSources(new Operand[] { operation.GetSource(0), rax, temp });
+ node.SetSources(new Operand[] { node.GetSource(0), rax, temp });
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
- operation.Destination = rax;
+ node.Destination = rax;
}
break;
@@ -290,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
// - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger())
{
- Operand src1 = operation.GetSource(0);
+ Operand src1 = node.GetSource(0);
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
@@ -300,11 +299,8 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
- operation.SetDestinations(new Operand[] { rdx, rax });
-
- operation.SetSources(new Operand[] { rdx, rax, operation.GetSource(1) });
-
- operation.Destination = rax;
+ node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) });
+ node.Destination = rax;
}
break;
@@ -312,19 +308,17 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.Extended:
{
- IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
-
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
- if ((intrinOp.Intrinsic == Intrinsic.X86Blendvpd ||
- intrinOp.Intrinsic == Intrinsic.X86Blendvps ||
- intrinOp.Intrinsic == Intrinsic.X86Pblendvb) &&
+ if ((node.Intrinsic == Intrinsic.X86Blendvpd ||
+ node.Intrinsic == Intrinsic.X86Blendvps ||
+ node.Intrinsic == Intrinsic.X86Pblendvb) &&
!HardwareCapabilities.SupportsVexEncoding)
{
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
- nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, operation.GetSource(2)));
+ nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, node.GetSource(2)));
- operation.SetSource(2, xmm0);
+ node.SetSource(2, xmm0);
}
break;
@@ -337,18 +331,18 @@ namespace ARMeilleure.CodeGen.X86
// - The multiplicand is always in RAX.
// - The lower 64-bits of the result is always in RAX.
// - The higher 64-bits of the result is always in RDX.
- Operand src1 = operation.GetSource(0);
+ Operand src1 = node.GetSource(0);
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
- operation.SetSource(0, rax);
+ node.SetSource(0, rax);
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
- operation.SetDestinations(new Operand[] { rdx, rax });
+ node.SetDestinations(new Operand[] { rdx, rax });
break;
}
@@ -359,13 +353,13 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.ShiftRightUI:
{
// The shift register is always implied to be CL (low 8-bits of RCX or ECX).
- if (operation.GetSource(1).Kind == OperandKind.LocalVariable)
+ if (node.GetSource(1).Kind == OperandKind.LocalVariable)
{
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32);
- nodes.AddBefore(node, Operation(Instruction.Copy, rcx, operation.GetSource(1)));
+ nodes.AddBefore(node, Operation(Instruction.Copy, rcx, node.GetSource(1)));
- operation.SetSource(1, rcx);
+ node.SetSource(1, rcx);
}
break;
@@ -373,29 +367,29 @@ namespace ARMeilleure.CodeGen.X86
}
}
- private static void HandleDestructiveRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleDestructiveRegCopy(IntrusiveList<Operation> nodes, Operation node)
{
- if (operation.Destination == null || operation.SourcesCount == 0)
+ if (node.Destination == default || node.SourcesCount == 0)
{
return;
}
- Instruction inst = operation.Instruction;
+ Instruction inst = node.Instruction;
- Operand dest = operation.Destination;
- Operand src1 = operation.GetSource(0);
+ Operand dest = node.Destination;
+ Operand src1 = node.GetSource(0);
// The multiply instruction (that maps to IMUL) is somewhat special, it has
// 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 && node.GetSource(1).Kind == OperandKind.Constant;
- if (IsSameOperandDestSrc1(operation) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm)
+ if (IsSameOperandDestSrc1(node) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm)
{
bool useNewLocal = false;
- for (int srcIndex = 1; srcIndex < operation.SourcesCount; srcIndex++)
+ for (int srcIndex = 1; srcIndex < node.SourcesCount; srcIndex++)
{
- if (operation.GetSource(srcIndex) == dest)
+ if (node.GetSource(srcIndex) == dest)
{
useNewLocal = true;
@@ -412,23 +406,23 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1));
- operation.SetSource(0, temp);
+ node.SetSource(0, temp);
nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
- operation.Destination = temp;
+ node.Destination = temp;
}
else
{
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1));
- operation.SetSource(0, dest);
+ node.SetSource(0, dest);
}
}
else if (inst == Instruction.ConditionalSelect)
{
- Operand src2 = operation.GetSource(1);
- Operand src3 = operation.GetSource(2);
+ Operand src2 = node.GetSource(1);
+ Operand src3 = node.GetSource(2);
if (src1 == dest || src2 == dest)
{
@@ -436,32 +430,32 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src3));
- operation.SetSource(2, temp);
+ node.SetSource(2, temp);
nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
- operation.Destination = temp;
+ node.Destination = temp;
}
else
{
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src3));
- operation.SetSource(2, dest);
+ node.SetSource(2, dest);
}
}
}
- private static void HandleConvertToFPUI(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleConvertToFPUI(IntrusiveList<Operation> nodes, Operation node)
{
// Unsigned integer to FP conversions are not supported on X86.
// We need to turn them into signed integer to FP conversions, and
// adjust the final result.
- Operand dest = operation.Destination;
- Operand source = operation.GetSource(0);
+ Operand dest = node.Destination;
+ Operand source = node.GetSource(0);
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
- Node currentNode = node;
+ Operation currentNode = node;
if (source.Type == OperandType.I32)
{
@@ -502,21 +496,21 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, lsbF));
}
- Delete(nodes, currentNode, operation);
+ Delete(nodes, currentNode);
}
- private static void HandleNegate(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleNegate(IntrusiveList<Operation> nodes, Operation node)
{
// 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.
// This also produces -0 for a negation of the value 0.
- Operand dest = operation.Destination;
- Operand source = operation.GetSource(0);
+ Operand dest = node.Destination;
+ Operand source = node.GetSource(0);
Debug.Assert(dest.Type == OperandType.FP32 ||
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
- Node currentNode = node;
+ Operation currentNode = node;
Operand res = Local(dest.Type);
@@ -524,27 +518,27 @@ namespace ARMeilleure.CodeGen.X86
if (dest.Type == OperandType.FP32)
{
- node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Pslld, res, res, Const(31)));
+ node = nodes.AddAfter(node, Operation(Intrinsic.X86Pslld, res, res, Const(31)));
}
else /* if (dest.Type == OperandType.FP64) */
{
- node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Psllq, res, res, Const(63)));
+ node = nodes.AddAfter(node, Operation(Intrinsic.X86Psllq, res, res, Const(63)));
}
- node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Xorps, res, res, source));
+ node = nodes.AddAfter(node, Operation(Intrinsic.X86Xorps, res, res, source));
nodes.AddAfter(node, Operation(Instruction.Copy, dest, res));
- Delete(nodes, currentNode, operation);
+ Delete(nodes, currentNode);
}
- private static void HandleVectorInsert8(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleVectorInsert8(IntrusiveList<Operation> nodes, Operation node)
{
// Handle vector insertion, when SSE 4.1 is not supported.
- Operand dest = operation.Destination;
- Operand src1 = operation.GetSource(0); // Vector
- Operand src2 = operation.GetSource(1); // Value
- Operand src3 = operation.GetSource(2); // Index
+ Operand dest = node.Destination;
+ Operand src1 = node.GetSource(0); // Vector
+ Operand src2 = node.GetSource(1); // Value
+ Operand src3 = node.GetSource(2); // Index
Debug.Assert(src3.Kind == OperandKind.Constant);
@@ -552,7 +546,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(index < 16);
- Node currentNode = node;
+ Operation currentNode = node;
Operand temp1 = Local(OperandType.I32);
Operand temp2 = Local(OperandType.I32);
@@ -580,16 +574,15 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, vinsOp);
- Delete(nodes, currentNode, operation);
+ Delete(nodes, currentNode);
}
- private static void HandleCallWindowsAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation)
+ private static void HandleCallWindowsAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
{
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
// Handle struct arguments.
int retArgs = 0;
-
int stackAllocOffset = 0;
int AllocateOnStack(int size)
@@ -610,9 +603,9 @@ namespace ARMeilleure.CodeGen.X86
return offset;
}
- Operand arg0Reg = null;
+ Operand arg0Reg = default;
- if (dest != null && dest.Type == OperandType.V128)
+ if (dest != default && dest.Type == OperandType.V128)
{
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes());
@@ -625,8 +618,7 @@ namespace ARMeilleure.CodeGen.X86
retArgs = 1;
}
- int argsCount = operation.SourcesCount - 1;
-
+ int argsCount = node.SourcesCount - 1;
int maxArgs = CallingConvention.GetArgumentsOnRegsCount() - retArgs;
if (argsCount > maxArgs)
@@ -636,16 +628,16 @@ namespace ARMeilleure.CodeGen.X86
Operand[] sources = new Operand[1 + retArgs + argsCount];
- sources[0] = operation.GetSource(0);
+ sources[0] = node.GetSource(0);
- if (arg0Reg != null)
+ if (arg0Reg != default)
{
sources[1] = arg0Reg;
}
- for (int index = 1; index < operation.SourcesCount; index++)
+ for (int index = 1; index < node.SourcesCount; index++)
{
- Operand source = operation.GetSource(index);
+ Operand source = node.GetSource(index);
if (source.Type == OperandType.V128)
{
@@ -655,19 +647,18 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
- Operation storeOp = Operation(Instruction.Store, null, stackAddr, source);
+ Operation storeOp = Operation(Instruction.Store, default, stackAddr, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, storeOp), storeOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, storeOp));
- operation.SetSource(index, stackAddr);
+ node.SetSource(index, stackAddr);
}
}
// Handle arguments passed on registers.
for (int index = 0; index < argsCount; index++)
{
- Operand source = operation.GetSource(index + 1);
-
+ Operand source = node.GetSource(index + 1);
Operand argReg;
int argIndex = index + retArgs;
@@ -683,25 +674,24 @@ namespace ARMeilleure.CodeGen.X86
Operation copyOp = Operation(Instruction.Copy, argReg, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp));
sources[1 + retArgs + index] = argReg;
}
// The remaining arguments (those that are not passed on registers)
// should be passed on the stack, we write them to the stack with "SpillArg".
- for (int index = argsCount; index < operation.SourcesCount - 1; index++)
+ for (int index = argsCount; index < node.SourcesCount - 1; index++)
{
- Operand source = operation.GetSource(index + 1);
-
+ Operand source = node.GetSource(index + 1);
Operand offset = Const((index + retArgs) * 8);
- Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
+ Operation spillOp = Operation(Instruction.SpillArg, default, offset, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp));
}
- if (dest != null)
+ if (dest != default)
{
if (dest.Type == OperandType.V128)
{
@@ -713,7 +703,7 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, loadOp);
- operation.Destination = null;
+ node.Destination = default;
}
else
{
@@ -725,23 +715,23 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, copyOp);
- operation.Destination = retReg;
+ node.Destination = retReg;
}
}
- operation.SetSources(sources);
+ node.SetSources(sources);
}
- private static void HandleCallSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleCallSystemVAbi(IntrusiveList<Operation> nodes, Operation node)
{
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
List<Operand> sources = new List<Operand>
{
- operation.GetSource(0)
+ node.GetSource(0)
};
- int argsCount = operation.SourcesCount - 1;
+ int argsCount = node.SourcesCount - 1;
int intMax = CallingConvention.GetIntArgumentsOnRegsCount();
int vecMax = CallingConvention.GetVecArgumentsOnRegsCount();
@@ -753,7 +743,7 @@ namespace ARMeilleure.CodeGen.X86
for (int index = 0; index < argsCount; index++)
{
- Operand source = operation.GetSource(index + 1);
+ Operand source = node.GetSource(index + 1);
bool passOnReg;
@@ -790,7 +780,7 @@ namespace ARMeilleure.CodeGen.X86
Operation copyOp = Operation(Instruction.Copy, argReg, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp));
sources.Add(argReg);
}
@@ -798,25 +788,27 @@ namespace ARMeilleure.CodeGen.X86
{
Operand offset = Const(stackOffset);
- Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
+ Operation spillOp = Operation(Instruction.SpillArg, default, offset, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes();
}
}
- if (dest != null)
+ if (dest != default)
{
if (dest.Type == OperandType.V128)
{
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
+ Operation operation = node;
+
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
- operation.Destination = null;
+ operation.Destination = default;
}
else
{
@@ -828,21 +820,21 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddAfter(node, copyOp);
- operation.Destination = retReg;
+ node.Destination = retReg;
}
}
- operation.SetSources(sources.ToArray());
+ node.SetSources(sources.ToArray());
}
- private static void HandleTailcallSystemVAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation)
+ private static void HandleTailcallSystemVAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
{
List<Operand> sources = new List<Operand>
{
- operation.GetSource(0)
+ node.GetSource(0)
};
- int argsCount = operation.SourcesCount - 1;
+ int argsCount = node.SourcesCount - 1;
int intMax = CallingConvention.GetIntArgumentsOnRegsCount();
int vecMax = CallingConvention.GetVecArgumentsOnRegsCount();
@@ -853,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86
// Handle arguments passed on registers.
for (int index = 0; index < argsCount; index++)
{
- Operand source = operation.GetSource(1 + index);
+ Operand source = node.GetSource(1 + index);
bool passOnReg;
@@ -886,7 +878,7 @@ namespace ARMeilleure.CodeGen.X86
Operation copyOp = Operation(Instruction.Copy, argReg, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp));
sources.Add(argReg);
}
@@ -901,19 +893,18 @@ namespace ARMeilleure.CodeGen.X86
// callee saved register (which would be trashed on the epilogue).
Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
- Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0));
+ Operation addrCopyOp = Operation(Instruction.Copy, retReg, node.GetSource(0));
nodes.AddBefore(node, addrCopyOp);
sources[0] = retReg;
- operation.SetSources(sources.ToArray());
+ node.SetSources(sources.ToArray());
}
- private static void HandleTailcallWindowsAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation)
+ private static void HandleTailcallWindowsAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
{
- int argsCount = operation.SourcesCount - 1;
-
+ int argsCount = node.SourcesCount - 1;
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
if (argsCount > maxArgs)
@@ -926,15 +917,14 @@ namespace ARMeilleure.CodeGen.X86
// Handle arguments passed on registers.
for (int index = 0; index < argsCount; index++)
{
- Operand source = operation.GetSource(1 + index);
-
+ Operand source = node.GetSource(1 + index);
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
Operation copyOp = Operation(Instruction.Copy, argReg, source);
- HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
+ HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp));
sources[1 + index] = argReg;
}
@@ -944,23 +934,22 @@ namespace ARMeilleure.CodeGen.X86
// callee saved register (which would be trashed on the epilogue).
Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
- Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0));
+ Operation addrCopyOp = Operation(Instruction.Copy, retReg, node.GetSource(0));
nodes.AddBefore(node, addrCopyOp);
sources[0] = retReg;
- operation.SetSources(sources);
+ node.SetSources(sources);
}
- private static Node HandleLoadArgumentWindowsAbi(
+ private static Operation HandleLoadArgumentWindowsAbi(
CompilerContext cctx,
- IntrusiveList<Node> nodes,
- Node node,
+ IntrusiveList<Operation> nodes,
Operand[] preservedArgs,
- Operation operation)
+ Operation node)
{
- Operand source = operation.GetSource(0);
+ Operand source = node.GetSource(0);
Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind.");
@@ -970,28 +959,25 @@ namespace ARMeilleure.CodeGen.X86
if (index < CallingConvention.GetArgumentsOnRegsCount())
{
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
- if (preservedArgs[index] == null)
+ if (preservedArgs[index] == default)
{
Operand argReg, pArg;
if (dest.Type.IsInteger())
{
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type);
-
pArg = Local(dest.Type);
}
else if (dest.Type == OperandType.V128)
{
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), OperandType.I64);
-
pArg = Local(OperandType.I64);
}
else
{
argReg = Xmm(CallingConvention.GetVecArgumentRegister(index), dest.Type);
-
pArg = Local(dest.Type);
}
@@ -1006,9 +992,9 @@ namespace ARMeilleure.CodeGen.X86
? Instruction.Load
: Instruction.Copy, dest, preservedArgs[index]);
- Node newNode = nodes.AddBefore(node, argCopyOp);
+ Operation newNode = nodes.AddBefore(node, argCopyOp);
- Delete(nodes, node, operation);
+ Delete(nodes, node);
return newNode;
}
@@ -1019,14 +1005,13 @@ namespace ARMeilleure.CodeGen.X86
}
}
- private static Node HandleLoadArgumentSystemVAbi(
+ private static Operation HandleLoadArgumentSystemVAbi(
CompilerContext cctx,
- IntrusiveList<Node> nodes,
- Node node,
+ IntrusiveList<Operation> nodes,
Operand[] preservedArgs,
- Operation operation)
+ Operation node)
{
- Operand source = operation.GetSource(0);
+ Operand source = node.GetSource(0);
Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind.");
@@ -1070,9 +1055,9 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg)
{
- Operand dest = operation.Destination;
+ Operand dest = node.Destination;
- if (preservedArgs[index] == null)
+ if (preservedArgs[index] == default)
{
if (dest.Type == OperandType.V128)
{
@@ -1108,9 +1093,9 @@ namespace ARMeilleure.CodeGen.X86
Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]);
- Node newNode = nodes.AddBefore(node, argCopyOp);
+ Operation newNode = nodes.AddBefore(node, argCopyOp);
- Delete(nodes, node, operation);
+ Delete(nodes, node);
return newNode;
}
@@ -1123,18 +1108,16 @@ namespace ARMeilleure.CodeGen.X86
private static void HandleReturnWindowsAbi(
CompilerContext cctx,
- IntrusiveList<Node> nodes,
- Node node,
+ IntrusiveList<Operation> nodes,
Operand[] preservedArgs,
- Operation operation)
+ Operation node)
{
- if (operation.SourcesCount == 0)
+ if (node.SourcesCount == 0)
{
return;
}
- Operand source = operation.GetSource(0);
-
+ Operand source = node.GetSource(0);
Operand retReg;
if (source.Type.IsInteger())
@@ -1143,10 +1126,9 @@ namespace ARMeilleure.CodeGen.X86
}
else if (source.Type == OperandType.V128)
{
- if (preservedArgs[0] == null)
+ if (preservedArgs[0] == default)
{
Operand preservedArg = Local(OperandType.I64);
-
Operand arg0 = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
Operation copyOp = Operation(Instruction.Copy, preservedArg, arg0);
@@ -1165,7 +1147,7 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type == OperandType.V128)
{
- Operation retStoreOp = Operation(Instruction.Store, null, retReg, source);
+ Operation retStoreOp = Operation(Instruction.Store, default, retReg, source);
nodes.AddBefore(node, retStoreOp);
}
@@ -1176,17 +1158,17 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, retCopyOp);
}
- operation.SetSources(Array.Empty<Operand>());
+ node.SetSources(Array.Empty<Operand>());
}
- private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void HandleReturnSystemVAbi(IntrusiveList<Operation> nodes, Operation node)
{
- if (operation.SourcesCount == 0)
+ if (node.SourcesCount == 0)
{
return;
}
- Operand source = operation.GetSource(0);
+ Operand source = node.GetSource(0);
if (source.Type == OperandType.V128)
{
@@ -1208,10 +1190,9 @@ namespace ARMeilleure.CodeGen.X86
}
}
- private static Operand AddXmmCopy(IntrusiveList<Node> nodes, Node node, Operand source)
+ private static Operand AddXmmCopy(IntrusiveList<Operation> nodes, Operation node, Operand source)
{
Operand temp = Local(source.Type);
-
Operand intConst = AddCopy(nodes, node, GetIntConst(source));
Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst);
@@ -1221,7 +1202,7 @@ namespace ARMeilleure.CodeGen.X86
return temp;
}
- private static Operand AddCopy(IntrusiveList<Node> nodes, Node node, Operand source)
+ private static Operand AddCopy(IntrusiveList<Operation> nodes, Operation node, Operand source)
{
Operand temp = Local(source.Type);
@@ -1246,13 +1227,13 @@ namespace ARMeilleure.CodeGen.X86
return value;
}
- private static void Delete(IntrusiveList<Node> nodes, Node node, Operation operation)
+ private static void Delete(IntrusiveList<Operation> nodes, Operation node)
{
- operation.Destination = null;
+ node.Destination = default;
- for (int index = 0; index < operation.SourcesCount; index++)
+ for (int index = 0; index < node.SourcesCount; index++)
{
- operation.SetSource(index, null);
+ node.SetSource(index, default);
}
nodes.Remove(node);
@@ -1307,8 +1288,7 @@ namespace ARMeilleure.CodeGen.X86
private static bool IsIntrinsicSameOperandDestSrc1(Operation operation)
{
- IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
- IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic);
+ IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
return info.Type == IntrinsicType.Crc32 || info.Type == IntrinsicType.Fma || IsVexSameOperandDestSrc1(operation);
}
@@ -1319,7 +1299,7 @@ namespace ARMeilleure.CodeGen.X86
{
bool isUnary = operation.SourcesCount < 2;
- bool hasVecDest = operation.Destination != null && operation.Destination.Type == OperandType.V128;
+ bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128;
return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest;
}
@@ -1408,8 +1388,7 @@ namespace ARMeilleure.CodeGen.X86
return false;
}
- IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
- IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic);
+ IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
return info.Type != IntrinsicType.Crc32;
}
diff --git a/ARMeilleure/CodeGen/X86/X86Optimizer.cs b/ARMeilleure/CodeGen/X86/X86Optimizer.cs
index fa8b54e8..ed040e15 100644
--- a/ARMeilleure/CodeGen/X86/X86Optimizer.cs
+++ b/ARMeilleure/CodeGen/X86/X86Optimizer.cs
@@ -2,9 +2,8 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Collections.Generic;
-
-using static ARMeilleure.IntermediateRepresentation.OperandHelper;
-using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
+using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.X86
{
@@ -34,32 +33,27 @@ namespace ARMeilleure.CodeGen.X86
{
constants.Clear();
- Node nextNode;
+ Operation nextNode;
- for (Node node = block.Operations.First; node != null; node = nextNode)
+ for (Operation node = block.Operations.First; node != default; node = nextNode)
{
nextNode = node.ListNext;
- if (!(node is Operation operation))
- {
- continue;
- }
-
// Insert copies for constants that can't fit on a 32-bits immediate.
// Doing this early unblocks a few optimizations.
- if (operation.Instruction == Instruction.Add)
+ if (node.Instruction == Instruction.Add)
{
- Operand src1 = operation.GetSource(0);
- Operand src2 = operation.GetSource(1);
+ Operand src1 = node.GetSource(0);
+ Operand src2 = node.GetSource(1);
if (src1.Kind == OperandKind.Constant && (src1.Relocatable || CodeGenCommon.IsLongConst(src1)))
{
- operation.SetSource(0, GetConstantCopy(block, operation, src1));
+ node.SetSource(0, GetConstantCopy(block, node, src1));
}
if (src2.Kind == OperandKind.Constant && (src2.Relocatable || CodeGenCommon.IsLongConst(src2)))
{
- operation.SetSource(1, GetConstantCopy(block, operation, src2));
+ node.SetSource(1, GetConstantCopy(block, node, src2));
}
}
@@ -70,24 +64,24 @@ namespace ARMeilleure.CodeGen.X86
// mov rax, [rax]
// Into:
// mov rax, [rax+rbx*4+0xcafe]
- if (IsMemoryLoadOrStore(operation.Instruction))
+ if (IsMemoryLoadOrStore(node.Instruction))
{
OperandType type;
- if (operation.Destination != null)
+ if (node.Destination != default)
{
- type = operation.Destination.Type;
+ type = node.Destination.Type;
}
else
{
- type = operation.GetSource(1).Type;
+ type = node.GetSource(1).Type;
}
- MemoryOperand memOp = GetMemoryOperandOrNull(operation.GetSource(0), type);
+ Operand memOp = GetMemoryOperandOrNull(node.GetSource(0), type);
- if (memOp != null)
+ if (memOp != default)
{
- operation.SetSource(0, memOp);
+ node.SetSource(0, memOp);
}
}
}
@@ -96,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
Optimizer.RemoveUnusedNodes(cfg);
}
- private static MemoryOperand GetMemoryOperandOrNull(Operand addr, OperandType type)
+ private static Operand GetMemoryOperandOrNull(Operand addr, OperandType type)
{
Operand baseOp = addr;
@@ -117,10 +111,10 @@ namespace ARMeilleure.CodeGen.X86
// If baseOp is still equal to address, then there's nothing that can be optimized.
if (baseOp == addr)
{
- return null;
+ return default;
}
- if (imm == 0 && scale == Multiplier.x1 && indexOp != null)
+ if (imm == 0 && scale == Multiplier.x1 && indexOp != default)
{
imm = GetConstOp(ref indexOp);
}
@@ -132,7 +126,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operation operation = GetAsgOpWithInst(baseOp, Instruction.Add);
- if (operation == null)
+ if (operation == default)
{
return 0;
}
@@ -172,13 +166,13 @@ namespace ARMeilleure.CodeGen.X86
private static (Operand, Multiplier) GetIndexOp(ref Operand baseOp)
{
- Operand indexOp = null;
+ Operand indexOp = default;
Multiplier scale = Multiplier.x1;
Operation addOp = GetAsgOpWithInst(baseOp, Instruction.Add);
- if (addOp == null)
+ if (addOp == default)
{
return (indexOp, scale);
}
@@ -198,14 +192,14 @@ namespace ARMeilleure.CodeGen.X86
bool indexOnSrc2 = false;
- if (shlOp == null)
+ if (shlOp == default)
{
shlOp = GetAsgOpWithInst(src2, Instruction.ShiftLeft);
indexOnSrc2 = true;
}
- if (shlOp != null)
+ if (shlOp != default)
{
Operand shSrc = shlOp.GetSource(0);
Operand shift = shlOp.GetSource(1);
@@ -233,24 +227,19 @@ namespace ARMeilleure.CodeGen.X86
// If we have multiple assignments, folding is not safe
// as the value may be different depending on the
// control flow path.
- if (op.Assignments.Count != 1)
+ if (op.AssignmentsCount != 1)
{
- return null;
+ return default;
}
- Node asgOp = op.Assignments[0];
-
- if (!(asgOp is Operation operation))
- {
- return null;
- }
+ Operation asgOp = op.Assignments[0];
- if (operation.Instruction != inst)
+ if (asgOp.Instruction != inst)
{
- return null;
+ return default;
}
- return operation;
+ return asgOp;
}
private static bool IsMemoryLoadOrStore(Instruction inst)