aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs21
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs11
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs98
-rw-r--r--ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs36
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenerator.cs43
-rw-r--r--ARMeilleure/CodeGen/X86/PreAllocator.cs165
-rw-r--r--ARMeilleure/CodeGen/X86/X86Optimizer.cs7
-rw-r--r--ARMeilleure/Common/BitMap.cs87
-rw-r--r--ARMeilleure/Common/BitMapPool.cs19
-rw-r--r--ARMeilleure/Common/BitUtils.cs42
-rw-r--r--ARMeilleure/Common/SortedIntegerList.cs73
-rw-r--r--ARMeilleure/Common/ThreadStaticPool.cs104
-rw-r--r--ARMeilleure/IntermediateRepresentation/MemoryOperand.cs12
-rw-r--r--ARMeilleure/IntermediateRepresentation/Node.cs126
-rw-r--r--ARMeilleure/IntermediateRepresentation/Operand.cs46
-rw-r--r--ARMeilleure/IntermediateRepresentation/OperandHelper.cs59
-rw-r--r--ARMeilleure/IntermediateRepresentation/Operation.cs64
-rw-r--r--ARMeilleure/IntermediateRepresentation/OperationHelper.cs59
-rw-r--r--ARMeilleure/Translation/ControlFlowGraph.cs2
-rw-r--r--ARMeilleure/Translation/EmitterContext.cs53
-rw-r--r--ARMeilleure/Translation/PriorityQueue.cs10
-rw-r--r--ARMeilleure/Translation/RegisterUsage.cs19
-rw-r--r--ARMeilleure/Translation/SsaDeconstruction.cs5
-rw-r--r--ARMeilleure/Translation/Translator.cs8
24 files changed, 845 insertions, 324 deletions
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
index 65901e80..417f3bae 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs
@@ -2,6 +2,9 @@ using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
+using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
+
namespace ARMeilleure.CodeGen.RegisterAllocators
{
class CopyResolver
@@ -133,14 +136,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static void EmitCopy(List<Operation> sequence, Operand x, Operand y)
{
- sequence.Add(new Operation(Instruction.Copy, x, y));
+ sequence.Add(Operation(Instruction.Copy, x, y));
}
private static void EmitXorSwap(List<Operation> sequence, Operand x, Operand y)
{
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, y, y, x));
- sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, y, y, x));
+ sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
}
}
@@ -194,20 +197,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Operand register = GetRegister(right.Register, type);
- Operand offset = new Operand(left.SpillOffset);
+ Operand offset = Const(left.SpillOffset);
- _fillQueue.Enqueue(new Operation(Instruction.Fill, register, offset));
+ _fillQueue.Enqueue(Operation(Instruction.Fill, register, offset));
HasCopy = true;
}
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
{
- Operand offset = new Operand(right.SpillOffset);
+ Operand offset = Const(right.SpillOffset);
Operand register = GetRegister(left.Register, type);
- _spillQueue.Enqueue(new Operation(Instruction.Spill, null, offset, register));
+ _spillQueue.Enqueue(Operation(Instruction.Spill, null, offset, register));
HasCopy = true;
}
@@ -240,7 +243,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetRegister(Register reg, OperandType type)
{
- return new Operand(reg.Index, reg.Type, type);
+ return Register(reg.Index, reg.Type, type);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
index ce7936f9..21470a66 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/HybridAllocator.cs
@@ -1,10 +1,11 @@
-using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Numerics;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -265,7 +266,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
node.SetSource(srcIndex, temp);
}
- Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset));
+ Operation fillOp = Operation(Instruction.Fill, temp, Const(info.SpillOffset));
block.Operations.AddBefore(node, fillOp);
}
@@ -317,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (info.IsBlockLocal && mask != 0)
{
- int selectedReg = BitUtils.LowestBitSet(mask);
+ int selectedReg = BitOperations.TrailingZeroCount(mask);
info.Register = selectedReg;
@@ -363,7 +364,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
node.SetDestination(dstIndex, temp);
- Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
+ Operation spillOp = Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
block.Operations.AddAfter(node, spillOp);
@@ -415,7 +416,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetSpillTemp(Operand local, int freeMask, ref int useMask)
{
- int selectedReg = BitUtils.LowestBitSet(freeMask & ~useMask);
+ int selectedReg = BitOperations.TrailingZeroCount(freeMask & ~useMask);
useMask |= 1 << selectedReg;
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
index 1dc6ad73..01bb9554 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Numerics;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
@@ -32,7 +33,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private int _operationsCount;
- private class AllocationContext
+ private class AllocationContext : IDisposable
{
public RegisterMasks Masks { get; }
@@ -49,8 +50,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
StackAlloc = stackAlloc;
Masks = masks;
- Active = new BitMap(intervalsCount);
- Inactive = new BitMap(intervalsCount);
+ Active = BitMapPool.Allocate(intervalsCount);
+ Inactive = BitMapPool.Allocate(intervalsCount);
}
public void MoveActiveToInactive(int bit)
@@ -69,6 +70,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
dest.Set(bit);
}
+
+ public void Dispose()
+ {
+ BitMapPool.Release();
+ }
}
public AllocationResult RunPass(
@@ -121,10 +127,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
InsertSplitCopies();
InsertSplitCopiesAtEdges(cfg);
- return new AllocationResult(
+ AllocationResult result = new AllocationResult(
context.IntUsedRegisters,
context.VecUsedRegisters,
context.StackAlloc.TotalSize);
+
+ context.Dispose();
+
+ return result;
}
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
@@ -618,15 +628,22 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
bool hasSingleOrNoSuccessor = block.Next == null || block.Branch == null;
- foreach (BasicBlock successor in Successors(block))
+ for (int i = 0; i < 2; i++)
{
+ // This used to use an enumerable, but it ended up generating a lot of garbage, so now it is a loop.
+ BasicBlock successor = (i == 0) ? block.Next : block.Branch;
+ if (successor == null)
+ {
+ continue;
+ }
+
int succIndex = successor.Index;
// If the current node is a split node, then the actual successor node
// (the successor before the split) should be right after it.
if (IsSplitEdgeBlock(successor))
{
- succIndex = Successors(successor).First().Index;
+ succIndex = FirstSuccessor(successor).Index;
}
CopyResolver copyResolver = new CopyResolver();
@@ -699,8 +716,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Operand register = GetRegister(current);
- foreach (int usePosition in current.UsePositions())
+ IList<int> usePositions = current.UsePositions();
+ for (int i = usePositions.Count - 1; i >= 0; i--)
{
+ int usePosition = -usePositions[i];
(_, Node operation) = GetOperationNode(usePosition);
for (int index = 0; index < operation.SourcesCount; index++)
@@ -743,7 +762,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
- return new Operand(
+ return OperandHelper.Register(
interval.Register.Index,
interval.Register.Type,
interval.Local.Type);
@@ -778,8 +797,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
_operationNodes.Add((block.Operations, node));
- foreach (Operand dest in Destinations(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);
@@ -815,12 +835,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// Compute local live sets.
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{
- BitMap liveGen = new BitMap(mapSize);
- BitMap liveKill = new BitMap(mapSize);
+ BitMap liveGen = BitMapPool.Allocate(mapSize);
+ BitMap liveKill = BitMapPool.Allocate(mapSize);
for (Node node = block.Operations.First; node != null; node = node.ListNext)
{
- foreach (Operand source in Sources(node))
+ Sources(node, (source) =>
{
int id = GetOperandId(source);
@@ -828,10 +848,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
liveGen.Set(id);
}
- }
+ });
- foreach (Operand dest in Destinations(node))
+ for (int i = 0; i < node.DestinationsCount; i++)
{
+ Operand dest = node.GetDestination(i);
liveKill.Set(GetOperandId(dest));
}
}
@@ -846,8 +867,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
for (int index = 0; index < cfg.Blocks.Count; index++)
{
- blkLiveIn [index] = new BitMap(mapSize);
- blkLiveOut[index] = new BitMap(mapSize);
+ blkLiveIn [index] = BitMapPool.Allocate(mapSize);
+ blkLiveOut[index] = BitMapPool.Allocate(mapSize);
}
bool modified;
@@ -862,12 +883,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
BitMap liveOut = blkLiveOut[block.Index];
- foreach (BasicBlock successor in Successors(block))
+ if ((block.Next != null && liveOut.Set(blkLiveIn[block.Next.Index])) ||
+ (block.Branch != null && liveOut.Set(blkLiveIn[block.Branch.Index])))
{
- if (liveOut.Set(blkLiveIn[successor.Index]))
- {
- modified = true;
- }
+ modified = true;
}
BitMap liveIn = blkLiveIn[block.Index];
@@ -920,21 +939,22 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
operationPos -= InstructionGap;
- foreach (Operand dest in Destinations(node))
+ for (int i = 0; i < node.DestinationsCount; i++)
{
+ Operand dest = node.GetDestination(i);
LiveInterval interval = _intervals[GetOperandId(dest)];
interval.SetStart(operationPos + 1);
interval.AddUsePosition(operationPos + 1);
}
- foreach (Operand source in Sources(node))
+ Sources(node, (source) =>
{
LiveInterval interval = _intervals[GetOperandId(source)];
interval.AddRange(blockStart, operationPos + 1);
interval.AddUsePosition(operationPos);
- }
+ });
if (node is Operation operation && operation.Instruction == Instruction.Call)
{
@@ -949,7 +969,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
while (mask != 0)
{
- int regIndex = BitUtils.LowestBitSet(mask);
+ int regIndex = BitOperations.TrailingZeroCount(mask);
Register callerSavedReg = new Register(regIndex, regType);
@@ -982,17 +1002,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return (register.Index << 1) | (register.Type == RegisterType.Vector ? 1 : 0);
}
- private static IEnumerable<BasicBlock> Successors(BasicBlock block)
+ private static BasicBlock FirstSuccessor(BasicBlock block)
{
- if (block.Next != null)
- {
- yield return block.Next;
- }
-
- if (block.Branch != null)
- {
- yield return block.Branch;
- }
+ return block.Next ?? block.Branch;
}
private static IEnumerable<Node> BottomOperations(BasicBlock block)
@@ -1007,15 +1019,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
- private static IEnumerable<Operand> Destinations(Node node)
- {
- for (int index = 0; index < node.DestinationsCount; index++)
- {
- yield return node.GetDestination(index);
- }
- }
-
- private static IEnumerable<Operand> Sources(Node node)
+ private static void Sources(Node node, Action<Operand> action)
{
for (int index = 0; index < node.SourcesCount; index++)
{
@@ -1023,7 +1027,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (IsLocalOrRegister(source.Kind))
{
- yield return source;
+ action(source);
}
else if (source.Kind == OperandKind.Memory)
{
@@ -1031,12 +1035,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (memOp.BaseAddress != null)
{
- yield return memOp.BaseAddress;
+ action(memOp.BaseAddress);
}
if (memOp.Index != null)
{
- yield return memOp.Index;
+ action(memOp.Index);
}
}
}
diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
index 18858a76..6e786061 100644
--- a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
+++ b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs
@@ -1,3 +1,4 @@
+using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
@@ -12,7 +13,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private LiveInterval _parent;
- private SortedSet<int> _usePositions;
+ private SortedIntegerList _usePositions;
public int UsesCount => _usePositions.Count;
@@ -38,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Local = local;
_parent = parent ?? this;
- _usePositions = new SortedSet<int>();
+ _usePositions = new SortedIntegerList();
_ranges = new List<LiveRange>();
@@ -196,7 +197,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public void AddUsePosition(int position)
{
- _usePositions.Add(position);
+ // Inserts are in descending order, but ascending is faster for SortedIntegerList<>.
+ // We flip the ordering, then iterate backwards when using the final list.
+ _usePositions.Add(-position);
}
public bool Overlaps(int position)
@@ -247,9 +250,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return _childs.Values;
}
- public IEnumerable<int> UsePositions()
+ public IList<int> UsePositions()
{
- return _usePositions;
+ return _usePositions.GetList();
}
public int FirstUse()
@@ -259,20 +262,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return NotFound;
}
- return _usePositions.First();
+ return -_usePositions.Last();
}
public int NextUseAfter(int position)
{
- foreach (int usePosition in _usePositions)
- {
- if (usePosition >= position)
- {
- return usePosition;
- }
- }
+ int index = _usePositions.FindLessEqualIndex(-position);
+ return (index >= 0) ? -_usePositions[index] : NotFound;
+ }
- return NotFound;
+ public void RemoveAfter(int position)
+ {
+ int index = _usePositions.FindLessEqualIndex(-position);
+ _usePositions.RemoveRange(0, index + 1);
}
public LiveInterval Split(int position)
@@ -311,12 +313,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_ranges.RemoveRange(splitIndex, count);
}
- foreach (int usePosition in _usePositions.Where(x => x >= position))
+ int addAfter = _usePositions.FindLessEqualIndex(-position);
+ for (int index = addAfter; index >= 0; index--)
{
+ int usePosition = _usePositions[index];
right._usePositions.Add(usePosition);
}
- _usePositions.RemoveWhere(x => x >= position);
+ RemoveAfter(position);
Debug.Assert(_ranges.Count != 0, "Left interval is empty after split.");
diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
index 1d0a4c12..1bcab736 100644
--- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs
+++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
@@ -9,6 +9,9 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Numerics;
+
+using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.CodeGen.X86
{
@@ -550,7 +553,7 @@ namespace ARMeilleure.CodeGen.X86
if (operation.SourcesCount == 5) // CompareAndSwap128 has 5 sources, compared to CompareAndSwap64/32's 3.
{
- MemoryOperand memOp = new MemoryOperand(OperandType.I64, src1);
+ MemoryOperand memOp = MemoryOp(OperandType.I64, src1);
context.Assembler.Cmpxchg16b(memOp);
}
@@ -561,7 +564,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src2, src3);
- MemoryOperand memOp = new MemoryOperand(src3.Type, src1);
+ MemoryOperand memOp = MemoryOp(src3.Type, src1);
context.Assembler.Cmpxchg(memOp, src3);
}
@@ -751,7 +754,7 @@ namespace ARMeilleure.CodeGen.X86
// operand size constant to the destination register.
context.JumpToNear(X86Condition.NotEqual);
- context.Assembler.Mov(dest, new Operand(operandSize | operandMask), OperandType.I32);
+ context.Assembler.Mov(dest, Const(operandSize | operandMask), OperandType.I32);
context.JumpHere();
@@ -759,7 +762,7 @@ namespace ARMeilleure.CodeGen.X86
// starting from the least significant bit. However we are supposed to
// return the number of 0 bits on the high end. So, we invert the result
// of the BSR using XOR to get the correct value.
- context.Assembler.Xor(dest, new Operand(operandMask), OperandType.I32);
+ context.Assembler.Xor(dest, Const(operandMask), OperandType.I32);
}
private static void GenerateCpuId(CodeGenContext context, Operation operation)
@@ -828,7 +831,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = new MemoryOperand(dest.Type, rsp, null, Multiplier.x1, offs);
+ MemoryOperand memOp = MemoryOp(dest.Type, rsp, null, Multiplier.x1, offs);
GenerateLoad(context, memOp, dest);
}
@@ -1027,7 +1030,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = new MemoryOperand(source.Type, rsp, null, Multiplier.x1, offs);
+ MemoryOperand memOp = MemoryOp(source.Type, rsp, null, Multiplier.x1, offs);
GenerateStore(context, memOp, source);
}
@@ -1043,7 +1046,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rsp = Register(X86Register.Rsp);
- MemoryOperand memOp = new MemoryOperand(OperandType.I64, rsp, null, Multiplier.x1, offs);
+ MemoryOperand memOp = MemoryOp(OperandType.I64, rsp, null, Multiplier.x1, offs);
context.Assembler.Lea(dest, memOp, OperandType.I64);
}
@@ -1247,7 +1250,7 @@ namespace ARMeilleure.CodeGen.X86
if ((index & 1) != 0)
{
- context.Assembler.Shr(dest, new Operand(8), OperandType.I32);
+ context.Assembler.Shr(dest, Const(8), OperandType.I32);
}
else
{
@@ -1286,7 +1289,7 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Pinsrw(dest, dest, src2, (byte)(index * words + word));
// Move next word down.
- context.Assembler.Ror(src2, new Operand(16), src2.Type);
+ context.Assembler.Ror(src2, Const(16), src2.Type);
}
}
@@ -1594,7 +1597,7 @@ namespace ARMeilleure.CodeGen.X86
while (mask != 0)
{
- int bit = BitUtils.LowestBitSet(mask);
+ int bit = BitOperations.TrailingZeroCount(mask);
context.Assembler.Push(Register((X86Register)bit));
@@ -1614,7 +1617,7 @@ namespace ARMeilleure.CodeGen.X86
if (reservedStackSize != 0)
{
- context.Assembler.Sub(rsp, new Operand(reservedStackSize), OperandType.I64);
+ context.Assembler.Sub(rsp, Const(reservedStackSize), OperandType.I64);
}
int offset = reservedStackSize;
@@ -1623,11 +1626,11 @@ namespace ARMeilleure.CodeGen.X86
while (mask != 0)
{
- int bit = BitUtils.LowestBitSet(mask);
+ int bit = BitOperations.TrailingZeroCount(mask);
offset -= 16;
- MemoryOperand memOp = new MemoryOperand(OperandType.V128, rsp, null, Multiplier.x1, offset);
+ MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
context.Assembler.Movdqu(memOp, Xmm((X86Register)bit));
@@ -1653,11 +1656,11 @@ namespace ARMeilleure.CodeGen.X86
while (mask != 0)
{
- int bit = BitUtils.LowestBitSet(mask);
+ int bit = BitOperations.TrailingZeroCount(mask);
offset -= 16;
- MemoryOperand memOp = new MemoryOperand(OperandType.V128, rsp, null, Multiplier.x1, offset);
+ MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
context.Assembler.Movdqu(Xmm((X86Register)bit), memOp);
@@ -1666,7 +1669,7 @@ namespace ARMeilleure.CodeGen.X86
if (reservedStackSize != 0)
{
- context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
+ context.Assembler.Add(rsp, Const(reservedStackSize), OperandType.I64);
}
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
@@ -1698,7 +1701,7 @@ namespace ARMeilleure.CodeGen.X86
for (int offset = PageSize; offset < size; offset += PageSize)
{
- Operand memOp = new MemoryOperand(OperandType.I32, rsp, null, Multiplier.x1, -offset);
+ Operand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, -offset);
context.Assembler.Mov(temp, memOp, OperandType.I32);
}
@@ -1711,17 +1714,17 @@ namespace ARMeilleure.CodeGen.X86
return operand as MemoryOperand;
}
- return new MemoryOperand(type, operand);
+ return MemoryOp(type, operand);
}
private static Operand Register(X86Register register, OperandType type = OperandType.I64)
{
- return new Operand((int)register, RegisterType.Integer, type);
+ return OperandHelper.Register((int)register, RegisterType.Integer, type);
}
private static Operand Xmm(X86Register register)
{
- return new Operand((int)register, RegisterType.Vector, OperandType.V128);
+ return OperandHelper.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 e20fca9d..7c119349 100644
--- a/ARMeilleure/CodeGen/X86/PreAllocator.cs
+++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.CodeGen.X86
{
@@ -223,8 +224,8 @@ namespace ARMeilleure.CodeGen.X86
// - The value at the memory location is loaded to RDX:RAX.
void SplitOperand(Operand source, Operand lr, Operand hr)
{
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, lr, source, Const(0)));
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, hr, source, Const(1)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, lr, source, Const(0)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, hr, source, Const(1)));
}
Operand rax = Gpr(X86Register.Rax, OperandType.I64);
@@ -235,8 +236,8 @@ namespace ARMeilleure.CodeGen.X86
SplitOperand(operation.GetSource(1), rax, rdx);
SplitOperand(operation.GetSource(2), rbx, rcx);
- node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, rax));
- node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
+ node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
+ node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
operation.SetDestinations(new Operand[] { rdx, rax });
@@ -252,11 +253,11 @@ namespace ARMeilleure.CodeGen.X86
Operand rax = Gpr(X86Register.Rax, expected.Type);
- nodes.AddBefore(node, new Operation(Instruction.Copy, rax, expected));
+ nodes.AddBefore(node, Operation(Instruction.Copy, rax, expected));
operation.SetSources(new Operand[] { operation.GetSource(0), rax, operation.GetSource(2) });
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rax));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
operation.Destination = rax;
}
@@ -278,16 +279,16 @@ namespace ARMeilleure.CodeGen.X86
Operand edx = Gpr(X86Register.Rdx, OperandType.I32);
// Value 0x01 = Version, family and feature information.
- nodes.AddBefore(node, new Operation(Instruction.Copy, eax, Const(1)));
+ nodes.AddBefore(node, Operation(Instruction.Copy, eax, Const(1)));
// Copy results to the destination register.
// The values are split into 2 32-bits registers, we merge them
// into a single 64-bits register.
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
- node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, dest, edx));
- node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, dest, dest, Const(32)));
- node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, dest, dest, rcx));
+ node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, dest, edx));
+ node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, dest, dest, Const(32)));
+ node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, dest, dest, rcx));
operation.SetDestinations(new Operand[] { eax, ebx, ecx, edx });
@@ -310,10 +311,10 @@ namespace ARMeilleure.CodeGen.X86
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
- nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1));
- nodes.AddBefore(node, new Operation(Instruction.Clobber, rdx));
+ nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
+ nodes.AddBefore(node, Operation(Instruction.Clobber, rdx));
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rax));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
operation.SetDestinations(new Operand[] { rdx, rax });
@@ -337,7 +338,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
- nodes.AddBefore(node, new Operation(Instruction.Copy, xmm0, operation.GetSource(2)));
+ nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, operation.GetSource(2)));
operation.SetSource(2, xmm0);
}
@@ -357,11 +358,11 @@ namespace ARMeilleure.CodeGen.X86
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
- nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1));
+ nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
operation.SetSource(0, rax);
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rdx));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
operation.SetDestinations(new Operand[] { rdx, rax });
@@ -378,7 +379,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32);
- nodes.AddBefore(node, new Operation(Instruction.Copy, rcx, operation.GetSource(1)));
+ nodes.AddBefore(node, Operation(Instruction.Copy, rcx, operation.GetSource(1)));
operation.SetSource(1, rcx);
}
@@ -427,17 +428,17 @@ namespace ARMeilleure.CodeGen.X86
// local would be overwritten.
Operand temp = Local(dest.Type);
- nodes.AddBefore(node, new Operation(Instruction.Copy, temp, src1));
+ nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1));
operation.SetSource(0, temp);
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, temp));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
operation.Destination = temp;
}
else
{
- nodes.AddBefore(node, new Operation(Instruction.Copy, dest, src1));
+ nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1));
operation.SetSource(0, dest);
}
@@ -451,17 +452,17 @@ namespace ARMeilleure.CodeGen.X86
{
Operand temp = Local(dest.Type);
- nodes.AddBefore(node, new Operation(Instruction.Copy, temp, src3));
+ nodes.AddBefore(node, Operation(Instruction.Copy, temp, src3));
operation.SetSource(2, temp);
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, temp));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
operation.Destination = temp;
}
else
{
- nodes.AddBefore(node, new Operation(Instruction.Copy, dest, src3));
+ nodes.AddBefore(node, Operation(Instruction.Copy, dest, src3));
operation.SetSource(2, dest);
}
@@ -488,8 +489,8 @@ namespace ARMeilleure.CodeGen.X86
// and then use the 64-bits signed conversion instructions.
Operand zex = Local(OperandType.I64);
- node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, zex, source));
- node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, dest, zex));
+ node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
+ node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
}
else /* if (source.Type == OperandType.I64) */
{
@@ -508,17 +509,17 @@ namespace ARMeilleure.CodeGen.X86
Operand lsbF = Local(dest.Type);
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, lsb, source));
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, half, source));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, lsb, source));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, half, source));
- node = nodes.AddAfter(node, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
- node = nodes.AddAfter(node, new Operation(Instruction.ShiftRightUI, half, half, Const(1)));
+ node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
+ node = nodes.AddAfter(node, Operation(Instruction.ShiftRightUI, half, half, Const(1)));
- node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, lsbF, lsb));
- node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, dest, half));
+ node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, lsbF, lsb));
+ node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, half));
- node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, dest));
- node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, lsbF));
+ node = nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, dest));
+ node = nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, lsbF));
}
Delete(nodes, currentNode, operation);
@@ -541,7 +542,7 @@ namespace ARMeilleure.CodeGen.X86
Operand res = Local(dest.Type);
- node = nodes.AddAfter(node, new Operation(Instruction.VectorOne, res));
+ node = nodes.AddAfter(node, Operation(Instruction.VectorOne, res));
if (dest.Type == OperandType.FP32)
{
@@ -554,7 +555,7 @@ namespace ARMeilleure.CodeGen.X86
node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Xorps, res, res, source));
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, res));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, res));
Delete(nodes, currentNode, operation);
@@ -580,26 +581,26 @@ namespace ARMeilleure.CodeGen.X86
Operand temp1 = Local(OperandType.I32);
Operand temp2 = Local(OperandType.I32);
- node = nodes.AddAfter(node, new Operation(Instruction.Copy, temp2, src2));
+ node = nodes.AddAfter(node, Operation(Instruction.Copy, temp2, src2));
- Operation vextOp = new Operation(Instruction.VectorExtract16, temp1, src1, Const(index >> 1));
+ Operation vextOp = Operation(Instruction.VectorExtract16, temp1, src1, Const(index >> 1));
node = nodes.AddAfter(node, vextOp);
if ((index & 1) != 0)
{
- node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend8, temp1, temp1));
- node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, temp2, temp2, Const(8)));
- node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
+ node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp1, temp1));
+ node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, temp2, temp2, Const(8)));
+ node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
}
else
{
- node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend8, temp2, temp2));
- node = nodes.AddAfter(node, new Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00)));
- node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
+ node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp2, temp2));
+ node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00)));
+ node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
}
- Operation vinsOp = new Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1));
+ Operation vinsOp = Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1));
node = nodes.AddAfter(node, vinsOp);
@@ -643,7 +644,7 @@ namespace ARMeilleure.CodeGen.X86
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
- Operation allocOp = new Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset));
+ Operation allocOp = Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset));
nodes.AddBefore(node, allocOp);
@@ -678,9 +679,9 @@ namespace ARMeilleure.CodeGen.X86
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes());
- nodes.AddBefore(node, new Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
+ nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
- Operation storeOp = new Operation(Instruction.Store, null, stackAddr, source);
+ Operation storeOp = Operation(Instruction.Store, null, stackAddr, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, storeOp), storeOp);
@@ -706,7 +707,7 @@ namespace ARMeilleure.CodeGen.X86
argReg = Xmm(CallingConvention.GetVecArgumentRegister(argIndex), source.Type);
}
- Operation copyOp = new Operation(Instruction.Copy, argReg, source);
+ Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
@@ -719,9 +720,9 @@ namespace ARMeilleure.CodeGen.X86
{
Operand source = operation.GetSource(index + 1);
- Operand offset = new Operand((index + retArgs) * 8);
+ Operand offset = Const((index + retArgs) * 8);
- Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
+ Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
}
@@ -732,9 +733,9 @@ namespace ARMeilleure.CodeGen.X86
{
Operand retValueAddr = Local(OperandType.I64);
- nodes.AddBefore(node, new Operation(Instruction.Copy, retValueAddr, arg0Reg));
+ nodes.AddBefore(node, Operation(Instruction.Copy, retValueAddr, arg0Reg));
- Operation loadOp = new Operation(Instruction.Load, dest, retValueAddr);
+ Operation loadOp = Operation(Instruction.Load, dest, retValueAddr);
node = nodes.AddAfter(node, loadOp);
@@ -746,7 +747,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
- Operation copyOp = new Operation(Instruction.Copy, dest, retReg);
+ Operation copyOp = Operation(Instruction.Copy, dest, retReg);
node = nodes.AddAfter(node, copyOp);
@@ -803,8 +804,8 @@ namespace ARMeilleure.CodeGen.X86
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0)));
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue;
}
@@ -815,7 +816,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
- Operation copyOp = new Operation(Instruction.Copy, argReg, source);
+ Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
@@ -823,9 +824,9 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
- Operand offset = new Operand(stackOffset);
+ Operand offset = Const(stackOffset);
- Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
+ Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
@@ -840,8 +841,8 @@ namespace ARMeilleure.CodeGen.X86
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
- node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, retLReg));
- node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
+ node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
+ node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
operation.Destination = null;
}
@@ -851,7 +852,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
- Operation copyOp = new Operation(Instruction.Copy, dest, retReg);
+ Operation copyOp = Operation(Instruction.Copy, dest, retReg);
node = nodes.AddAfter(node, copyOp);
@@ -900,8 +901,8 @@ namespace ARMeilleure.CodeGen.X86
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0)));
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue;
}
@@ -912,7 +913,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
- Operation copyOp = new Operation(Instruction.Copy, argReg, source);
+ Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
@@ -929,7 +930,7 @@ namespace ARMeilleure.CodeGen.X86
// callee saved register (which would be trashed on the epilogue).
Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
- Operation addrCopyOp = new Operation(Instruction.Copy, retReg, operation.GetSource(0));
+ Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0));
nodes.AddBefore(node, addrCopyOp);
@@ -960,7 +961,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
- Operation copyOp = new Operation(Instruction.Copy, argReg, source);
+ Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
@@ -972,7 +973,7 @@ namespace ARMeilleure.CodeGen.X86
// callee saved register (which would be trashed on the epilogue).
Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
- Operation addrCopyOp = new Operation(Instruction.Copy, retReg, operation.GetSource(0));
+ Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0));
nodes.AddBefore(node, addrCopyOp);
@@ -1023,14 +1024,14 @@ namespace ARMeilleure.CodeGen.X86
pArg = Local(dest.Type);
}
- Operation copyOp = new Operation(Instruction.Copy, pArg, argReg);
+ Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
preservedArgs[index] = pArg;
}
- Operation argCopyOp = new Operation(dest.Type == OperandType.V128
+ Operation argCopyOp = Operation(dest.Type == OperandType.V128
? Instruction.Load
: Instruction.Copy, dest, preservedArgs[index]);
@@ -1107,8 +1108,8 @@ namespace ARMeilleure.CodeGen.X86
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
- Operation copyL = new Operation(Instruction.VectorCreateScalar, pArg, argLReg);
- Operation copyH = new Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
+ Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg);
+ Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
cctx.Cfg.Entry.Operations.AddFirst(copyH);
cctx.Cfg.Entry.Operations.AddFirst(copyL);
@@ -1123,7 +1124,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
- Operation copyOp = new Operation(Instruction.Copy, pArg, argReg);
+ Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
@@ -1131,7 +1132,7 @@ namespace ARMeilleure.CodeGen.X86
}
}
- Operation argCopyOp = new Operation(Instruction.Copy, dest, preservedArgs[index]);
+ Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]);
nodes.AddBefore(node, argCopyOp);
@@ -1171,7 +1172,7 @@ namespace ARMeilleure.CodeGen.X86
Operand arg0 = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
- Operation copyOp = new Operation(Instruction.Copy, preservedArg, arg0);
+ Operation copyOp = Operation(Instruction.Copy, preservedArg, arg0);
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
@@ -1187,18 +1188,18 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type == OperandType.V128)
{
- Operation retStoreOp = new Operation(Instruction.Store, null, retReg, source);
+ Operation retStoreOp = Operation(Instruction.Store, null, retReg, source);
nodes.AddBefore(node, retStoreOp);
}
else
{
- Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
+ Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
nodes.AddBefore(node, retCopyOp);
}
- operation.SetSources(System.Array.Empty<Operand>());
+ operation.SetSources(Array.Empty<Operand>());
}
private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
@@ -1215,8 +1216,8 @@ namespace ARMeilleure.CodeGen.X86
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
- nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
+ nodes.AddBefore(node, Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
}
else
{
@@ -1224,7 +1225,7 @@ namespace ARMeilleure.CodeGen.X86
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
- Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
+ Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
nodes.AddBefore(node, retCopyOp);
}
@@ -1236,7 +1237,7 @@ namespace ARMeilleure.CodeGen.X86
Operand intConst = AddCopy(nodes, node, GetIntConst(source));
- Operation copyOp = new Operation(Instruction.VectorCreateScalar, temp, intConst);
+ Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst);
nodes.AddBefore(node, copyOp);
@@ -1247,7 +1248,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand temp = Local(source.Type);
- Operation copyOp = new Operation(Instruction.Copy, temp, source);
+ Operation copyOp = Operation(Instruction.Copy, temp, source);
nodes.AddBefore(node, copyOp);
diff --git a/ARMeilleure/CodeGen/X86/X86Optimizer.cs b/ARMeilleure/CodeGen/X86/X86Optimizer.cs
index c52541ca..30fd6c71 100644
--- a/ARMeilleure/CodeGen/X86/X86Optimizer.cs
+++ b/ARMeilleure/CodeGen/X86/X86Optimizer.cs
@@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.CodeGen.X86
{
@@ -34,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand temp = Local(src1.Type);
- Operation copyOp = new Operation(Instruction.Copy, temp, src1);
+ Operation copyOp = Operation(Instruction.Copy, temp, src1);
block.Operations.AddBefore(operation, copyOp);
@@ -45,7 +46,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand temp = Local(src2.Type);
- Operation copyOp = new Operation(Instruction.Copy, temp, src2);
+ Operation copyOp = Operation(Instruction.Copy, temp, src2);
block.Operations.AddBefore(operation, copyOp);
@@ -110,7 +111,7 @@ namespace ARMeilleure.CodeGen.X86
return null;
}
- return new MemoryOperand(type, baseOp, indexOp, scale, imm);
+ return MemoryOp(type, baseOp, indexOp, scale, imm);
}
private static int GetConstOp(ref Operand baseOp)
diff --git a/ARMeilleure/Common/BitMap.cs b/ARMeilleure/Common/BitMap.cs
index 9dff271b..35100536 100644
--- a/ARMeilleure/Common/BitMap.cs
+++ b/ARMeilleure/Common/BitMap.cs
@@ -1,20 +1,50 @@
using System.Collections;
using System.Collections.Generic;
+using System.Numerics;
namespace ARMeilleure.Common
{
- class BitMap : IEnumerable<int>
+ class BitMap : IEnumerator<int>
{
- private const int IntSize = 32;
+ private const int IntSize = 64;
private const int IntMask = IntSize - 1;
- private List<int> _masks;
+ private List<long> _masks;
+
+ private int _enumIndex;
+ private long _enumMask;
+ private int _enumBit;
+
+ public int Current => _enumIndex * IntSize + _enumBit;
+ object IEnumerator.Current => Current;
+
+ public BitMap()
+ {
+ _masks = new List<long>(0);
+ }
public BitMap(int initialCapacity)
{
int count = (initialCapacity + IntMask) / IntSize;
- _masks = new List<int>(count);
+ _masks = new List<long>(count);
+
+ while (count-- > 0)
+ {
+ _masks.Add(0);
+ }
+ }
+
+ public void Reset(int initialCapacity)
+ {
+ int count = (initialCapacity + IntMask) / IntSize;
+
+ if (count > _masks.Capacity)
+ {
+ _masks.Capacity = count;
+ }
+
+ _masks.Clear();
while (count-- > 0)
{
@@ -29,7 +59,7 @@ namespace ARMeilleure.Common
int wordIndex = bit / IntSize;
int wordBit = bit & IntMask;
- int wordMask = 1 << wordBit;
+ long wordMask = 1L << wordBit;
if ((_masks[wordIndex] & wordMask) != 0)
{
@@ -48,7 +78,7 @@ namespace ARMeilleure.Common
int wordIndex = bit / IntSize;
int wordBit = bit & IntMask;
- int wordMask = 1 << wordBit;
+ long wordMask = 1L << wordBit;
_masks[wordIndex] &= ~wordMask;
}
@@ -60,7 +90,7 @@ namespace ARMeilleure.Common
int wordIndex = bit / IntSize;
int wordBit = bit & IntMask;
- return (_masks[wordIndex] & (1 << wordBit)) != 0;
+ return (_masks[wordIndex] & (1L << wordBit)) != 0;
}
public bool Set(BitMap map)
@@ -71,7 +101,7 @@ namespace ARMeilleure.Common
for (int index = 0; index < _masks.Count; index++)
{
- int newValue = _masks[index] | map._masks[index];
+ long newValue = _masks[index] | map._masks[index];
if (_masks[index] != newValue)
{
@@ -92,7 +122,7 @@ namespace ARMeilleure.Common
for (int index = 0; index < _masks.Count; index++)
{
- int newValue = _masks[index] & ~map._masks[index];
+ long newValue = _masks[index] & ~map._masks[index];
if (_masks[index] != newValue)
{
@@ -105,6 +135,10 @@ namespace ARMeilleure.Common
return modified;
}
+ #region IEnumerable<long> Methods
+
+ // Note: The bit enumerator is embedded in this class to avoid creating garbage when enumerating.
+
private void EnsureCapacity(int size)
{
while (_masks.Count * IntSize < size)
@@ -115,24 +149,37 @@ namespace ARMeilleure.Common
public IEnumerator<int> GetEnumerator()
{
- for (int index = 0; index < _masks.Count; index++)
- {
- int mask = _masks[index];
+ Reset();
+ return this;
+ }
- while (mask != 0)
+ public bool MoveNext()
+ {
+ if (_enumMask != 0)
+ {
+ _enumMask &= ~(1L << _enumBit);
+ }
+ while (_enumMask == 0)
+ {
+ if (++_enumIndex >= _masks.Count)
{
- int bit = BitUtils.LowestBitSet(mask);
-
- mask &= ~(1 << bit);
-
- yield return index * IntSize + bit;
+ return false;
}
+ _enumMask = _masks[_enumIndex];
}
+ _enumBit = BitOperations.TrailingZeroCount(_enumMask);
+ return true;
}
- IEnumerator IEnumerable.GetEnumerator()
+ public void Reset()
{
- return GetEnumerator();
+ _enumIndex = -1;
+ _enumMask = 0;
+ _enumBit = 0;
}
+
+ public void Dispose() { }
+
+#endregion
}
} \ No newline at end of file
diff --git a/ARMeilleure/Common/BitMapPool.cs b/ARMeilleure/Common/BitMapPool.cs
new file mode 100644
index 00000000..caba2317
--- /dev/null
+++ b/ARMeilleure/Common/BitMapPool.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace ARMeilleure.Common
+{
+ static class BitMapPool
+ {
+ public static BitMap Allocate(int initialCapacity)
+ {
+ BitMap result = ThreadStaticPool<BitMap>.Instance.Allocate();
+ result.Reset(initialCapacity);
+ return result;
+ }
+
+ public static void Release()
+ {
+ ThreadStaticPool<BitMap>.Instance.Clear();
+ }
+ }
+}
diff --git a/ARMeilleure/Common/BitUtils.cs b/ARMeilleure/Common/BitUtils.cs
index 7a29dcff..00fc6e5b 100644
--- a/ARMeilleure/Common/BitUtils.cs
+++ b/ARMeilleure/Common/BitUtils.cs
@@ -1,24 +1,13 @@
+using System.Numerics;
+
namespace ARMeilleure.Common
{
static class BitUtils
{
- private const int DeBrujinSequence = 0x77cb531;
-
- private static readonly int[] DeBrujinLbsLut;
-
private static readonly sbyte[] HbsNibbleLut;
static BitUtils()
{
- DeBrujinLbsLut = new int[32];
-
- for (int index = 0; index < DeBrujinLbsLut.Length; index++)
- {
- uint lutIndex = (uint)(DeBrujinSequence * (1 << index)) >> 27;
-
- DeBrujinLbsLut[lutIndex] = index;
- }
-
HbsNibbleLut = new sbyte[] { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
}
@@ -43,20 +32,7 @@ namespace ARMeilleure.Common
public static int HighestBitSet(int value)
{
- if (value == 0)
- {
- return -1;
- }
-
- for (int bit = 31; bit >= 0; bit--)
- {
- if (((value >> bit) & 1) != 0)
- {
- return bit;
- }
- }
-
- return -1;
+ return 31 - BitOperations.LeadingZeroCount((uint)value);
}
public static int HighestBitSetNibble(int value)
@@ -64,18 +40,6 @@ namespace ARMeilleure.Common
return HbsNibbleLut[value];
}
- public static int LowestBitSet(int value)
- {
- if (value == 0)
- {
- return -1;
- }
-
- int lsb = value & -value;
-
- return DeBrujinLbsLut[(uint)(DeBrujinSequence * lsb) >> 27];
- }
-
public static long Replicate(long bits, int size)
{
long output = 0;
diff --git a/ARMeilleure/Common/SortedIntegerList.cs b/ARMeilleure/Common/SortedIntegerList.cs
new file mode 100644
index 00000000..cceab62b
--- /dev/null
+++ b/ARMeilleure/Common/SortedIntegerList.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+
+namespace ARMeilleure.Common
+{
+ public class SortedIntegerList
+ {
+ private List<int> _items;
+
+ public int Count => _items.Count;
+
+ public int this[int index]
+ {
+ get
+ {
+ return _items[index];
+ }
+ set
+ {
+ _items[index] = value;
+ }
+ }
+
+ public SortedIntegerList()
+ {
+ _items = new List<int>();
+ }
+
+ public bool Add(int value)
+ {
+ if (_items.Count == 0 || value > Last())
+ {
+ _items.Add(value);
+ return true;
+ }
+ else
+ {
+ int index = _items.BinarySearch(value);
+ if (index >= 0)
+ {
+ return false;
+ }
+
+ _items.Insert(-1 - index, value);
+ return true;
+ }
+ }
+
+ public int FindLessEqualIndex(int value)
+ {
+ int index = _items.BinarySearch(value);
+ return (index < 0) ? (-2 - index) : index;
+ }
+
+ public void RemoveRange(int index, int count)
+ {
+ if (count > 0)
+ {
+ _items.RemoveRange(index, count);
+ }
+ }
+
+ public int Last()
+ {
+ return _items[Count - 1];
+ }
+
+ public List<int> GetList()
+ {
+ return _items;
+ }
+ }
+}
diff --git a/ARMeilleure/Common/ThreadStaticPool.cs b/ARMeilleure/Common/ThreadStaticPool.cs
new file mode 100644
index 00000000..cf3a7bb4
--- /dev/null
+++ b/ARMeilleure/Common/ThreadStaticPool.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace ARMeilleure.Common
+{
+ internal class ThreadStaticPool<T> where T : class, new()
+ {
+ private const int PoolSizeIncrement = 200;
+
+ [ThreadStatic]
+ private static ThreadStaticPool<T> _instance;
+ public static ThreadStaticPool<T> Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ PreparePool(0); // So that we can still use a pool when blindly initializing one.
+ }
+ return _instance;
+ }
+ }
+
+ private static ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>>();
+
+ private static Stack<ThreadStaticPool<T>> GetPools(int groupId)
+ {
+ return _pools.GetOrAdd(groupId, x => new Stack<ThreadStaticPool<T>>());
+ }
+
+ public static void PreparePool(int groupId)
+ {
+ // Prepare the pool for this thread, ideally using an existing one from the specified group.
+ if (_instance == null)
+ {
+ Stack<ThreadStaticPool<T>> pools = GetPools(groupId);
+ lock (pools)
+ {
+ _instance = (pools.Count != 0) ? pools.Pop() : new ThreadStaticPool<T>(PoolSizeIncrement * 2);
+ }
+ }
+ }
+
+ public static void ReturnPool(int groupId)
+ {
+ // Reset and return the pool for this thread to the specified group.
+ Stack<ThreadStaticPool<T>> pools = GetPools(groupId);
+ lock (pools)
+ {
+ _instance.Clear();
+ pools.Push(_instance);
+ _instance = null;
+ }
+ }
+
+ private T[] _pool;
+ private int _poolUsed = -1;
+ private int _poolSize;
+
+ public ThreadStaticPool(int initialSize)
+ {
+ _pool = new T[initialSize];
+
+ for (int i = 0; i < initialSize; i++)
+ {
+ _pool[i] = new T();
+ }
+
+ _poolSize = initialSize;
+ }
+
+ public T Allocate()
+ {
+ int index = Interlocked.Increment(ref _poolUsed);
+ if (index >= _poolSize)
+ {
+ IncreaseSize();
+ }
+ return _pool[index];
+ }
+
+ private void IncreaseSize()
+ {
+ _poolSize += PoolSizeIncrement;
+
+ T[] newArray = new T[_poolSize];
+ Array.Copy(_pool, 0, newArray, 0, _pool.Length);
+
+ for (int i = _pool.Length; i < _poolSize; i++)
+ {
+ newArray[i] = new T();
+ }
+
+ Interlocked.Exchange(ref _pool, newArray);
+ }
+
+ public void Clear()
+ {
+ _poolUsed = -1;
+ }
+ }
+}
diff --git a/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs
index 742842fa..56d07288 100644
--- a/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs
+++ b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs
@@ -5,21 +5,25 @@ namespace ARMeilleure.IntermediateRepresentation
public Operand BaseAddress { get; set; }
public Operand Index { get; set; }
- public Multiplier Scale { get; }
+ public Multiplier Scale { get; private set; }
- public int Displacement { get; }
+ public int Displacement { get; private set; }
- public MemoryOperand(
+ public MemoryOperand() { }
+
+ public MemoryOperand With(
OperandType type,
Operand baseAddress,
Operand index = null,
Multiplier scale = Multiplier.x1,
- int displacement = 0) : base(OperandKind.Memory, type)
+ int displacement = 0)
{
+ With(OperandKind.Memory, type);
BaseAddress = baseAddress;
Index = index;
Scale = scale;
Displacement = displacement;
+ return this;
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Node.cs b/ARMeilleure/IntermediateRepresentation/Node.cs
index 37647c56..9ce78c09 100644
--- a/ARMeilleure/IntermediateRepresentation/Node.cs
+++ b/ARMeilleure/IntermediateRepresentation/Node.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace ARMeilleure.IntermediateRepresentation
{
@@ -11,39 +12,80 @@ namespace ARMeilleure.IntermediateRepresentation
{
get
{
- return _destinations.Length != 0 ? GetDestination(0) : null;
+ return _destinations.Count != 0 ? GetDestination(0) : null;
}
set
{
if (value != null)
{
- SetDestinations(new Operand[] { value });
+ SetDestination(value);
}
else
{
- SetDestinations(new Operand[0]);
+ _destinations.Clear();
}
}
}
- private Operand[] _destinations;
- private Operand[] _sources;
+ private List<Operand> _destinations;
+ private List<Operand> _sources;
+ private bool _clearedDest;
- public int DestinationsCount => _destinations.Length;
- public int SourcesCount => _sources.Length;
+ public int DestinationsCount => _destinations.Count;
+ public int SourcesCount => _sources.Count;
- public Node(Operand destination, int sourcesCount)
+ private void Resize(List<Operand> list, int size)
{
+ if (list.Count > size)
+ {
+ list.RemoveRange(size, list.Count - size);
+ }
+ else
+ {
+ while (list.Count < size)
+ {
+ list.Add(null);
+ }
+ }
+ }
+
+ public Node()
+ {
+ _destinations = new List<Operand>();
+ _sources = new List<Operand>();
+ }
+
+ public Node(Operand destination, int sourcesCount) : this()
+ {
+ Destination = destination;
+
+ Resize(_sources, sourcesCount);
+ }
+
+ private void Reset(int sourcesCount)
+ {
+ _clearedDest = true;
+ _sources.Clear();
+ ListPrevious = null;
+ ListNext = null;
+
+ Resize(_sources, sourcesCount);
+ }
+
+ public Node With(Operand destination, int sourcesCount)
+ {
+ Reset(sourcesCount);
Destination = destination;
- _sources = new Operand[sourcesCount];
+ return this;
}
- public Node(Operand[] destinations, int sourcesCount)
+ public Node With(Operand[] destinations, int sourcesCount)
{
+ Reset(sourcesCount);
SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
- _sources = new Operand[sourcesCount];
+ return this;
}
public Operand GetDestination(int index)
@@ -58,10 +100,15 @@ namespace ARMeilleure.IntermediateRepresentation
public void SetDestination(int index, Operand destination)
{
- RemoveAssignment(_destinations[index]);
+ if (!_clearedDest)
+ {
+ RemoveAssignment(_destinations[index]);
+ }
AddAssignment(destination);
+ _clearedDest = false;
+
_destinations[index] = destination;
}
@@ -74,21 +121,37 @@ namespace ARMeilleure.IntermediateRepresentation
_sources[index] = source;
}
- public void SetDestinations(Operand[] destinations)
+ private void RemoveOldDestinations()
{
- if (_destinations != null)
+ if (_destinations != null && !_clearedDest)
{
- for (int index = 0; index < _destinations.Length; index++)
+ for (int index = 0; index < _destinations.Count; index++)
{
RemoveAssignment(_destinations[index]);
}
-
- _destinations = destinations;
}
- else
+ _clearedDest = false;
+ }
+
+ public void SetDestination(Operand destination)
+ {
+ RemoveOldDestinations();
+
+ Resize(_destinations, 1);
+
+ _destinations[0] = destination;
+
+ if (destination.Kind == OperandKind.LocalVariable)
{
- _destinations = new Operand[destinations.Length];
+ destination.Assignments.Add(this);
}
+ }
+
+ public void SetDestinations(Operand[] destinations)
+ {
+ RemoveOldDestinations();
+
+ Resize(_destinations, destinations.Length);
for (int index = 0; index < destinations.Length; index++)
{
@@ -100,14 +163,33 @@ namespace ARMeilleure.IntermediateRepresentation
}
}
- public void SetSources(Operand[] sources)
+ private void RemoveOldSources()
{
- for (int index = 0; index < _sources.Length; index++)
+ for (int index = 0; index < _sources.Count; index++)
{
RemoveUse(_sources[index]);
}
+ }
+
+ public void SetSource(Operand source)
+ {
+ RemoveOldSources();
+
+ Resize(_sources, 1);
+
+ _sources[0] = source;
+
+ if (source.Kind == OperandKind.LocalVariable)
+ {
+ source.Uses.Add(this);
+ }
+ }
+
+ public void SetSources(Operand[] sources)
+ {
+ RemoveOldSources();
- _sources = new Operand[sources.Length];
+ Resize(_sources, sources.Length);
for (int index = 0; index < sources.Length; index++)
{
diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs
index fe5bf073..2d5e762a 100644
--- a/ARMeilleure/IntermediateRepresentation/Operand.cs
+++ b/ARMeilleure/IntermediateRepresentation/Operand.cs
@@ -5,16 +5,16 @@ namespace ARMeilleure.IntermediateRepresentation
{
class Operand
{
- public OperandKind Kind { get; }
+ public OperandKind Kind { get; private set; }
- public OperandType Type { get; }
+ public OperandType Type { get; private set; }
public ulong Value { get; private set; }
public List<Node> Assignments { get; }
public List<Node> Uses { get; }
- private Operand()
+ public Operand()
{
Assignments = new List<Node>();
Uses = new List<Node>();
@@ -26,42 +26,50 @@ namespace ARMeilleure.IntermediateRepresentation
Type = type;
}
- public Operand(int value) : this(OperandKind.Constant, OperandType.I32)
+ public Operand With(OperandKind kind, OperandType type = OperandType.None, ulong value = 0)
{
- Value = (uint)value;
+ Kind = kind;
+ Type = type;
+ Value = value;
+
+ Assignments.Clear();
+ Uses.Clear();
+ return this;
}
- public Operand(uint value) : this(OperandKind.Constant, OperandType.I32)
+ public Operand With(int value)
{
- Value = (uint)value;
+ return With(OperandKind.Constant, OperandType.I32, (uint)value);
}
- public Operand(long value) : this(OperandKind.Constant, OperandType.I64)
+ public Operand With(uint value)
{
- Value = (ulong)value;
+ return With(OperandKind.Constant, OperandType.I32, value);
}
- public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)
+ public Operand With(long value)
{
- Value = value;
+ return With(OperandKind.Constant, OperandType.I64, (ulong)value);
}
- public Operand(float value) : this(OperandKind.Constant, OperandType.FP32)
+ public Operand With(ulong value)
{
- Value = (ulong)BitConverter.SingleToInt32Bits(value);
+ return With(OperandKind.Constant, OperandType.I64, value);
}
- public Operand(double value) : this(OperandKind.Constant, OperandType.FP64)
+ public Operand With(float value)
{
- Value = (ulong)BitConverter.DoubleToInt64Bits(value);
+ return With(OperandKind.Constant, OperandType.FP32, (ulong)BitConverter.SingleToInt32Bits(value));
}
- public Operand(int index, RegisterType regType, OperandType type) : this()
+ public Operand With(double value)
{
- Kind = OperandKind.Register;
- Type = type;
+ return With(OperandKind.Constant, OperandType.FP64, (ulong)BitConverter.DoubleToInt64Bits(value));
+ }
- Value = (ulong)((int)regType << 24 | index);
+ public Operand With(int index, RegisterType regType, OperandType type)
+ {
+ return With(OperandKind.Register, type, (ulong)((int)regType << 24 | index));
}
public Register GetRegister()
diff --git a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs
index 4a930e03..cfdb32d9 100644
--- a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs
+++ b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs
@@ -1,68 +1,99 @@
-using ARMeilleure.State;
-using System;
+using ARMeilleure.Common;
namespace ARMeilleure.IntermediateRepresentation
{
static class OperandHelper
{
+ private static MemoryOperand MemoryOperand()
+ {
+ return ThreadStaticPool<MemoryOperand>.Instance.Allocate();
+ }
+
+ private static Operand Operand()
+ {
+ return ThreadStaticPool<Operand>.Instance.Allocate();
+ }
+
public static Operand Const(OperandType type, long value)
{
- return type == OperandType.I32 ? new Operand((int)value) : new Operand(value);
+ return type == OperandType.I32 ? Operand().With((int)value) : Operand().With(value);
}
public static Operand Const(bool value)
{
- return new Operand(value ? 1 : 0);
+ return Operand().With(value ? 1 : 0);
}
public static Operand Const(int value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand Const(uint value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand Const(long value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand Const(ulong value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand ConstF(float value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand ConstF(double value)
{
- return new Operand(value);
+ return Operand().With(value);
}
public static Operand Label()
{
- return new Operand(OperandKind.Label);
+ return Operand().With(OperandKind.Label);
}
public static Operand Local(OperandType type)
{
- return new Operand(OperandKind.LocalVariable, type);
+ return Operand().With(OperandKind.LocalVariable, type);
}
public static Operand Register(int index, RegisterType regType, OperandType type)
{
- return new Operand(index, regType, type);
+ return Operand().With(index, regType, type);
}
public static Operand Undef()
{
- return new Operand(OperandKind.Undefined);
+ return Operand().With(OperandKind.Undefined);
+ }
+
+ public static MemoryOperand MemoryOp(
+ OperandType type,
+ Operand baseAddress,
+ Operand index = null,
+ Multiplier scale = Multiplier.x1,
+ int displacement = 0)
+ {
+ return MemoryOperand().With(type, baseAddress, index, scale, displacement);
+ }
+
+ public static void PrepareOperandPool(bool highCq)
+ {
+ ThreadStaticPool<Operand>.PreparePool(highCq ? 1 : 0);
+ ThreadStaticPool<MemoryOperand>.PreparePool(highCq ? 1 : 0);
+ }
+
+ public static void ResetOperandPool(bool highCq)
+ {
+ ThreadStaticPool<Operand>.ReturnPool(highCq ? 1 : 0);
+ ThreadStaticPool<MemoryOperand>.ReturnPool(highCq ? 1 : 0);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Operation.cs b/ARMeilleure/IntermediateRepresentation/Operation.cs
index 620bf3f6..4cdbe326 100644
--- a/ARMeilleure/IntermediateRepresentation/Operation.cs
+++ b/ARMeilleure/IntermediateRepresentation/Operation.cs
@@ -4,10 +4,12 @@ namespace ARMeilleure.IntermediateRepresentation
{
public Instruction Instruction { get; private set; }
+ public Operation() : base() { }
+
public Operation(
Instruction instruction,
Operand destination,
- params Operand[] sources) : base(destination, sources.Length)
+ Operand[] sources) : base(destination, sources.Length)
{
Instruction = instruction;
@@ -17,24 +19,78 @@ namespace ARMeilleure.IntermediateRepresentation
}
}
- public Operation(
+ public Operation With(Instruction instruction, Operand destination)
+ {
+ With(destination, 0);
+ Instruction = instruction;
+ return this;
+ }
+
+ public Operation With(Instruction instruction, Operand destination, Operand[] sources)
+ {
+ With(destination, sources.Length);
+ Instruction = instruction;
+
+ for (int index = 0; index < sources.Length; index++)
+ {
+ SetSource(index, sources[index]);
+ }
+ return this;
+ }
+
+ public Operation With(Instruction instruction, Operand destination,
+ Operand source0)
+ {
+ With(destination, 1);
+ Instruction = instruction;
+
+ SetSource(0, source0);
+ return this;
+ }
+
+ public Operation With(Instruction instruction, Operand destination,
+ Operand source0, Operand source1)
+ {
+ With(destination, 2);
+ Instruction = instruction;
+
+ SetSource(0, source0);
+ SetSource(1, source1);
+ return this;
+ }
+
+ public Operation With(Instruction instruction, Operand destination,
+ Operand source0, Operand source1, Operand source2)
+ {
+ With(destination, 3);
+ Instruction = instruction;
+
+ SetSource(0, source0);
+ SetSource(1, source1);
+ SetSource(2, source2);
+ return this;
+ }
+
+ public Operation With(
Instruction instruction,
Operand[] destinations,
- Operand[] sources) : base(destinations, sources.Length)
+ Operand[] sources)
{
+ With(destinations, sources.Length);
Instruction = instruction;
for (int index = 0; index < sources.Length; index++)
{
SetSource(index, sources[index]);
}
+ return this;
}
public void TurnIntoCopy(Operand source)
{
Instruction = Instruction.Copy;
- SetSources(new Operand[] { source });
+ SetSource(source);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/OperationHelper.cs b/ARMeilleure/IntermediateRepresentation/OperationHelper.cs
new file mode 100644
index 00000000..20c7d4ef
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/OperationHelper.cs
@@ -0,0 +1,59 @@
+using ARMeilleure.Common;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ static class OperationHelper
+ {
+ public static Operation Operation()
+ {
+ return ThreadStaticPool<Operation>.Instance.Allocate();
+ }
+
+ public static Operation Operation(Instruction instruction, Operand destination)
+ {
+ return Operation().With(instruction, destination);
+ }
+
+ public static Operation Operation(Instruction instruction, Operand destination,
+ Operand[] sources)
+ {
+ return Operation().With(instruction, destination, sources);
+ }
+
+ public static Operation Operation(Instruction instruction, Operand destination,
+ Operand source0)
+ {
+ return Operation().With(instruction, destination, source0);
+ }
+
+ public static Operation Operation(Instruction instruction, Operand destination,
+ Operand source0, Operand source1)
+ {
+ return Operation().With(instruction, destination, source0, source1);
+ }
+
+ public static Operation Operation(Instruction instruction, Operand destination,
+ Operand source0, Operand source1, Operand source2)
+ {
+ return Operation().With(instruction, destination, source0, source1, source2);
+ }
+
+ public static Operation Operation(
+ Instruction instruction,
+ Operand[] destinations,
+ Operand[] sources)
+ {
+ return Operation().With(instruction, destinations, sources);
+ }
+
+ public static void PrepareOperationPool(bool highCq)
+ {
+ ThreadStaticPool<Operation>.PreparePool(highCq ? 1 : 0);
+ }
+
+ public static void ResetOperationPool(bool highCq)
+ {
+ ThreadStaticPool<Operation>.ReturnPool(highCq ? 1 : 0);
+ }
+ }
+}
diff --git a/ARMeilleure/Translation/ControlFlowGraph.cs b/ARMeilleure/Translation/ControlFlowGraph.cs
index 37613eb4..16b406ab 100644
--- a/ARMeilleure/Translation/ControlFlowGraph.cs
+++ b/ARMeilleure/Translation/ControlFlowGraph.cs
@@ -141,7 +141,7 @@ namespace ARMeilleure.Translation
splitBlock2.Branch = successor;
- splitBlock2.Operations.AddLast(new Operation(Instruction.Branch, null));
+ splitBlock2.Operations.AddLast(OperationHelper.Operation(Instruction.Branch, null));
Blocks.AddBefore(successor, splitBlock2);
}
diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs
index a11d25a6..d9e0a4ed 100644
--- a/ARMeilleure/Translation/EmitterContext.cs
+++ b/ARMeilleure/Translation/EmitterContext.cs
@@ -459,14 +459,63 @@ namespace ARMeilleure.Translation
return Add(Instruction.ZeroExtend8, Local(type), op1);
}
- private Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
+ private void NewNextBlockIfNeeded()
{
if (_needsNewBlock)
{
NewNextBlock();
}
+ }
+
+ private Operand Add(Instruction inst, Operand dest = null)
+ {
+ NewNextBlockIfNeeded();
+
+ Operation operation = OperationHelper.Operation(inst, dest);
+
+ _irBlock.Operations.AddLast(operation);
+
+ return dest;
+ }
+
+ private Operand Add(Instruction inst, Operand dest, Operand[] sources)
+ {
+ NewNextBlockIfNeeded();
+
+ Operation operation = OperationHelper.Operation(inst, dest, sources);
+
+ _irBlock.Operations.AddLast(operation);
+
+ return dest;
+ }
+
+ private Operand Add(Instruction inst, Operand dest, Operand source0)
+ {
+ NewNextBlockIfNeeded();
+
+ Operation operation = OperationHelper.Operation(inst, dest, source0);
+
+ _irBlock.Operations.AddLast(operation);
+
+ return dest;
+ }
+
+ private Operand Add(Instruction inst, Operand dest, Operand source0, Operand source1)
+ {
+ NewNextBlockIfNeeded();
+
+ Operation operation = OperationHelper.Operation(inst, dest, source0, source1);
+
+ _irBlock.Operations.AddLast(operation);
+
+ return dest;
+ }
+
+ private Operand Add(Instruction inst, Operand dest, Operand source0, Operand source1, Operand source2)
+ {
+ NewNextBlockIfNeeded();
- Operation operation = new Operation(inst, dest, sources);
+ Operation operation = OperationHelper.Operation(inst, dest, source0, source1, source2);
_irBlock.Operations.AddLast(operation);
diff --git a/ARMeilleure/Translation/PriorityQueue.cs b/ARMeilleure/Translation/PriorityQueue.cs
index ab593dc0..000a5009 100644
--- a/ARMeilleure/Translation/PriorityQueue.cs
+++ b/ARMeilleure/Translation/PriorityQueue.cs
@@ -4,28 +4,28 @@ namespace ARMeilleure.Translation
{
class PriorityQueue<T>
{
- private ConcurrentQueue<T>[] _queues;
+ private ConcurrentStack<T>[] _queues;
public PriorityQueue(int priorities)
{
- _queues = new ConcurrentQueue<T>[priorities];
+ _queues = new ConcurrentStack<T>[priorities];
for (int index = 0; index < priorities; index++)
{
- _queues[index] = new ConcurrentQueue<T>();
+ _queues[index] = new ConcurrentStack<T>();
}
}
public void Enqueue(int priority, T value)
{
- _queues[priority].Enqueue(value);
+ _queues[priority].Push(value);
}
public bool TryDequeue(out T value)
{
for (int index = 0; index < _queues.Length; index++)
{
- if (_queues[index].TryDequeue(out value))
+ if (_queues[index].TryPop(out value))
{
return true;
}
diff --git a/ARMeilleure/Translation/RegisterUsage.cs b/ARMeilleure/Translation/RegisterUsage.cs
index 84dfce7b..d5124285 100644
--- a/ARMeilleure/Translation/RegisterUsage.cs
+++ b/ARMeilleure/Translation/RegisterUsage.cs
@@ -3,6 +3,7 @@ using ARMeilleure.State;
using System;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.Translation
{
@@ -299,16 +300,16 @@ namespace ARMeilleure.Translation
Operand addr = Local(OperandType.I64);
- Operation loadOp = new Operation(Instruction.Load, dest, addr);
+ Operation loadOp = Operation(Instruction.Load, dest, addr);
block.Operations.AddFirst(loadOp);
- Operation calcOffsOp = new Operation(Instruction.Add, addr, arg0, Const(offset));
+ Operation calcOffsOp = Operation(Instruction.Add, addr, arg0, Const(offset));
block.Operations.AddFirst(calcOffsOp);
}
- Operation loadArg0 = new Operation(Instruction.LoadArgument, arg0, Const(0));
+ Operation loadArg0 = Operation(Instruction.LoadArgument, arg0, Const(0));
block.Operations.AddFirst(loadArg0);
}
@@ -329,7 +330,7 @@ namespace ARMeilleure.Translation
Operand arg0 = Local(OperandType.I64);
- Operation loadArg0 = new Operation(Instruction.LoadArgument, arg0, Const(0));
+ Operation loadArg0 = Operation(Instruction.LoadArgument, arg0, Const(0));
block.Append(loadArg0);
@@ -348,11 +349,11 @@ namespace ARMeilleure.Translation
Operand addr = Local(OperandType.I64);
- Operation calcOffsOp = new Operation(Instruction.Add, addr, arg0, Const(offset));
+ Operation calcOffsOp = Operation(Instruction.Add, addr, arg0, Const(offset));
block.Append(calcOffsOp);
- Operation storeOp = new Operation(Instruction.Store, null, addr, source);
+ Operation storeOp = Operation(Instruction.Store, null, addr, source);
block.Append(storeOp);
}
@@ -362,15 +363,15 @@ namespace ARMeilleure.Translation
{
if (bit < RegsCount)
{
- return new Operand(bit, baseType, GetOperandType(baseType, mode));
+ return OperandHelper.Register(bit, baseType, GetOperandType(baseType, mode));
}
else if (baseType == RegisterType.Integer)
{
- return new Operand(bit & RegsMask, RegisterType.Flag, OperandType.I32);
+ return OperandHelper.Register(bit & RegsMask, RegisterType.Flag, OperandType.I32);
}
else if (baseType == RegisterType.Vector)
{
- return new Operand(bit & RegsMask, RegisterType.FpFlag, OperandType.I32);
+ return OperandHelper.Register(bit & RegsMask, RegisterType.FpFlag, OperandType.I32);
}
else
{
diff --git a/ARMeilleure/Translation/SsaDeconstruction.cs b/ARMeilleure/Translation/SsaDeconstruction.cs
index 37d61625..c3bcaf8c 100644
--- a/ARMeilleure/Translation/SsaDeconstruction.cs
+++ b/ARMeilleure/Translation/SsaDeconstruction.cs
@@ -2,6 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
using System.Collections.Generic;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.Translation
{
@@ -25,12 +26,12 @@ namespace ARMeilleure.Translation
Operand source = phi.GetSource(index);
- predecessor.Append(new Operation(Instruction.Copy, local, source));
+ predecessor.Append(Operation(Instruction.Copy, local, source));
phi.SetSource(index, null);
}
- Operation copyOp = new Operation(Instruction.Copy, phi.Destination, local);
+ Operation copyOp = Operation(Instruction.Copy, phi.Destination, local);
block.Operations.AddBefore(node, copyOp);
diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs
index 9d534d58..053c7328 100644
--- a/ARMeilleure/Translation/Translator.cs
+++ b/ARMeilleure/Translation/Translator.cs
@@ -73,7 +73,7 @@ namespace ARMeilleure.Translation
// If we only have one rejit thread, it should be normal priority as highCq code is performance critical.
// TODO: Use physical cores rather than logical. This only really makes sense for processors with hyperthreading. Requires OS specific code.
int unboundedThreadCount = Math.Max(1, (Environment.ProcessorCount - 6) / 3);
- int threadCount = Math.Min(3, unboundedThreadCount);
+ int threadCount = Math.Min(4, unboundedThreadCount);
for (int i = 0; i < threadCount; i++)
{
bool last = i != 0 && i == unboundedThreadCount - 1;
@@ -146,6 +146,9 @@ namespace ARMeilleure.Translation
{
ArmEmitterContext context = new ArmEmitterContext(_memory, _jumpTable, (long)address, highCq, Aarch32Mode.User);
+ OperandHelper.PrepareOperandPool(highCq);
+ OperationHelper.PrepareOperationPool(highCq);
+
Logger.StartPass(PassName.Decoding);
Block[] blocks = AlwaysTranslateFunctions
@@ -181,6 +184,9 @@ namespace ARMeilleure.Translation
GuestFunction func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
+ OperandHelper.ResetOperandPool(highCq);
+ OperationHelper.ResetOperationPool(highCq);
+
return new TranslatedFunction(func, rejit: !highCq);
}