diff options
Diffstat (limited to 'ARMeilleure/CodeGen')
-rw-r--r-- | ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs | 9 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs | 5 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/Optimizations/Optimizer.cs | 130 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/Optimizations/Simplification.cs | 3 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs | 7 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs | 244 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs | 70 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs | 2 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/X86/Assembler.cs | 141 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/X86/CodeGenerator.cs | 72 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/X86/PreAllocator.cs | 395 | ||||
-rw-r--r-- | ARMeilleure/CodeGen/X86/X86Optimizer.cs | 71 |
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) |