aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/CodeGen/Optimizations
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /ARMeilleure/CodeGen/Optimizations
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'ARMeilleure/CodeGen/Optimizations')
-rw-r--r--ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs72
-rw-r--r--ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs346
-rw-r--r--ARMeilleure/CodeGen/Optimizations/Optimizer.cs252
-rw-r--r--ARMeilleure/CodeGen/Optimizations/Simplification.cs183
-rw-r--r--ARMeilleure/CodeGen/Optimizations/TailMerge.cs83
5 files changed, 0 insertions, 936 deletions
diff --git a/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs b/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
deleted file mode 100644
index 9e243d37..00000000
--- a/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using ARMeilleure.IntermediateRepresentation;
-using ARMeilleure.Translation;
-using System.Diagnostics;
-using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
-
-namespace ARMeilleure.CodeGen.Optimizations
-{
- static class BlockPlacement
- {
- public static void RunPass(ControlFlowGraph cfg)
- {
- bool update = false;
-
- BasicBlock block;
- BasicBlock nextBlock;
-
- BasicBlock lastBlock = cfg.Blocks.Last;
-
- // Move cold blocks at the end of the list, so that they are emitted away from hot code.
- for (block = cfg.Blocks.First; block != null; block = nextBlock)
- {
- nextBlock = block.ListNext;
-
- if (block.Frequency == BasicBlockFrequency.Cold)
- {
- cfg.Blocks.Remove(block);
- cfg.Blocks.AddLast(block);
- }
-
- if (block == lastBlock)
- {
- break;
- }
- }
-
- for (block = cfg.Blocks.First; block != null; block = nextBlock)
- {
- nextBlock = block.ListNext;
-
- if (block.SuccessorsCount == 2)
- {
- Operation branchOp = block.Operations.Last;
-
- Debug.Assert(branchOp.Instruction == Instruction.BranchIf);
-
- BasicBlock falseSucc = block.GetSuccessor(0);
- BasicBlock trueSucc = block.GetSuccessor(1);
-
- // If true successor is next block in list, invert the condition. We avoid extra branching by
- // making the true side the fallthrough (i.e, convert it to the false side).
- if (trueSucc == block.ListNext)
- {
- Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
- Comparison compInv = comp.Invert();
-
- branchOp.SetSource(2, Const((int)compInv));
-
- block.SetSuccessor(0, trueSucc);
- block.SetSuccessor(1, falseSucc);
-
- update = true;
- }
- }
- }
-
- if (update)
- {
- cfg.Update();
- }
- }
- }
-}
diff --git a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
deleted file mode 100644
index c5a22a53..00000000
--- a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
+++ /dev/null
@@ -1,346 +0,0 @@
-using ARMeilleure.IntermediateRepresentation;
-using System;
-using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
-
-namespace ARMeilleure.CodeGen.Optimizations
-{
- static class ConstantFolding
- {
- public static void RunPass(Operation operation)
- {
- if (operation.Destination == default || operation.SourcesCount == 0)
- {
- return;
- }
-
- if (!AreAllSourcesConstant(operation))
- {
- return;
- }
-
- OperandType type = operation.Destination.Type;
-
- switch (operation.Instruction)
- {
- case Instruction.Add:
- if (operation.GetSource(0).Relocatable ||
- operation.GetSource(1).Relocatable)
- {
- break;
- }
-
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x + y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x + y);
- }
- break;
-
- case Instruction.BitwiseAnd:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x & y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x & y);
- }
- break;
-
- case Instruction.BitwiseExclusiveOr:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x ^ y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x ^ y);
- }
- break;
-
- case Instruction.BitwiseNot:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => ~x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => ~x);
- }
- break;
-
- case Instruction.BitwiseOr:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x | y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x | y);
- }
- break;
-
- case Instruction.ConvertI64ToI32:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => x);
- }
- break;
-
- case Instruction.Compare:
- if (type == OperandType.I32 &&
- operation.GetSource(0).Type == type &&
- operation.GetSource(1).Type == type)
- {
- switch ((Comparison)operation.GetSource(2).Value)
- {
- case Comparison.Equal:
- EvaluateBinaryI32(operation, (x, y) => x == y ? 1 : 0);
- break;
- case Comparison.NotEqual:
- EvaluateBinaryI32(operation, (x, y) => x != y ? 1 : 0);
- break;
- case Comparison.Greater:
- EvaluateBinaryI32(operation, (x, y) => x > y ? 1 : 0);
- break;
- case Comparison.LessOrEqual:
- EvaluateBinaryI32(operation, (x, y) => x <= y ? 1 : 0);
- break;
- case Comparison.GreaterUI:
- EvaluateBinaryI32(operation, (x, y) => (uint)x > (uint)y ? 1 : 0);
- break;
- case Comparison.LessOrEqualUI:
- EvaluateBinaryI32(operation, (x, y) => (uint)x <= (uint)y ? 1 : 0);
- break;
- case Comparison.GreaterOrEqual:
- EvaluateBinaryI32(operation, (x, y) => x >= y ? 1 : 0);
- break;
- case Comparison.Less:
- EvaluateBinaryI32(operation, (x, y) => x < y ? 1 : 0);
- break;
- case Comparison.GreaterOrEqualUI:
- EvaluateBinaryI32(operation, (x, y) => (uint)x >= (uint)y ? 1 : 0);
- break;
- case Comparison.LessUI:
- EvaluateBinaryI32(operation, (x, y) => (uint)x < (uint)y ? 1 : 0);
- break;
- }
- }
- break;
-
- case Instruction.Copy:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => x);
- }
- break;
-
- case Instruction.Divide:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => y != 0 ? x / y : 0);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => y != 0 ? x / y : 0);
- }
- break;
-
- case Instruction.DivideUI:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => y != 0 ? (int)((uint)x / (uint)y) : 0);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => y != 0 ? (long)((ulong)x / (ulong)y) : 0);
- }
- break;
-
- case Instruction.Multiply:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x * y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x * y);
- }
- break;
-
- case Instruction.Negate:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => -x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => -x);
- }
- break;
-
- case Instruction.ShiftLeft:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x << y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x << (int)y);
- }
- break;
-
- case Instruction.ShiftRightSI:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x >> y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x >> (int)y);
- }
- break;
-
- case Instruction.ShiftRightUI:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => (int)((uint)x >> y));
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => (long)((ulong)x >> (int)y));
- }
- break;
-
- case Instruction.SignExtend16:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => (short)x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (short)x);
- }
- break;
-
- case Instruction.SignExtend32:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (int)x);
- }
- break;
-
- case Instruction.SignExtend8:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => (sbyte)x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (sbyte)x);
- }
- break;
-
- case Instruction.ZeroExtend16:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => (ushort)x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (ushort)x);
- }
- break;
-
- case Instruction.ZeroExtend32:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (uint)x);
- }
- break;
-
- case Instruction.ZeroExtend8:
- if (type == OperandType.I32)
- {
- EvaluateUnaryI32(operation, (x) => (byte)x);
- }
- else if (type == OperandType.I64)
- {
- EvaluateUnaryI64(operation, (x) => (byte)x);
- }
- break;
-
- case Instruction.Subtract:
- if (type == OperandType.I32)
- {
- EvaluateBinaryI32(operation, (x, y) => x - y);
- }
- else if (type == OperandType.I64)
- {
- EvaluateBinaryI64(operation, (x, y) => x - y);
- }
- break;
- }
- }
-
- private static bool AreAllSourcesConstant(Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- Operand srcOp = operation.GetSource(index);
-
- if (srcOp.Kind != OperandKind.Constant)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static void EvaluateUnaryI32(Operation operation, Func<int, int> op)
- {
- int x = operation.GetSource(0).AsInt32();
-
- operation.TurnIntoCopy(Const(op(x)));
- }
-
- private static void EvaluateUnaryI64(Operation operation, Func<long, long> op)
- {
- long x = operation.GetSource(0).AsInt64();
-
- operation.TurnIntoCopy(Const(op(x)));
- }
-
- private static void EvaluateBinaryI32(Operation operation, Func<int, int, int> op)
- {
- int x = operation.GetSource(0).AsInt32();
- int y = operation.GetSource(1).AsInt32();
-
- operation.TurnIntoCopy(Const(op(x, y)));
- }
-
- private static void EvaluateBinaryI64(Operation operation, Func<long, long, long> op)
- {
- long x = operation.GetSource(0).AsInt64();
- long y = operation.GetSource(1).AsInt64();
-
- operation.TurnIntoCopy(Const(op(x, y)));
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs b/ARMeilleure/CodeGen/Optimizations/Optimizer.cs
deleted file mode 100644
index a45bb455..00000000
--- a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs
+++ /dev/null
@@ -1,252 +0,0 @@
-using ARMeilleure.IntermediateRepresentation;
-using ARMeilleure.Translation;
-using System;
-using System.Diagnostics;
-using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
-
-namespace ARMeilleure.CodeGen.Optimizations
-{
- static class Optimizer
- {
- 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.Last; block != null; block = block.ListPrevious)
- {
- Operation node;
- Operation prevNode;
-
- for (node = block.Operations.Last; node != default; node = prevNode)
- {
- prevNode = node.ListPrevious;
-
- if (IsUnused(node))
- {
- RemoveNode(block, node);
-
- modified = true;
-
- continue;
- }
- else if (node.Instruction == Instruction.Phi)
- {
- continue;
- }
-
- ConstantFolding.RunPass(node);
- Simplification.RunPass(node);
-
- if (DestIsSingleLocalVar(node))
- {
- if (IsPropagableCompare(node))
- {
- modified |= PropagateCompare(ref buffer, node);
-
- if (modified && IsUnused(node))
- {
- RemoveNode(block, node);
- }
- }
- else if (IsPropagableCopy(node))
- {
- PropagateCopy(ref buffer, node);
-
- RemoveNode(block, node);
-
- modified = true;
- }
- }
- }
- }
- }
- while (modified);
- }
-
- public static void RemoveUnusedNodes(ControlFlowGraph cfg)
- {
- bool modified;
-
- do
- {
- modified = false;
-
- for (BasicBlock block = cfg.Blocks.Last; block != null; block = block.ListPrevious)
- {
- Operation node;
- Operation prevNode;
-
- for (node = block.Operations.Last; node != default; node = prevNode)
- {
- prevNode = node.ListPrevious;
-
- if (IsUnused(node))
- {
- RemoveNode(block, node);
-
- modified = true;
- }
- }
- }
- }
- while (modified);
- }
-
- 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:
- //
- // - BranchIf %x, 0x0, Equal ;; i.e BranchIfFalse %x
- // - BranchIf %x, 0x0, NotEqual ;; i.e BranchIfTrue %x
- //
- // The commutative property of Equal and NotEqual is taken into consideration as well.
- //
- // For example:
- //
- // %x = Compare %a, %b, comp
- // BranchIf %x, 0x0, NotEqual
- //
- // =>
- //
- // BranchIf %a, %b, comp
-
- static bool IsZeroBranch(Operation operation, out Comparison compType)
- {
- compType = Comparison.Equal;
-
- if (operation.Instruction != Instruction.BranchIf)
- {
- return false;
- }
-
- Operand src1 = operation.GetSource(0);
- Operand src2 = operation.GetSource(1);
- Operand comp = operation.GetSource(2);
-
- compType = (Comparison)comp.AsInt32();
-
- return (src1.Kind == OperandKind.Constant && src1.Value == 0) ||
- (src2.Kind == OperandKind.Constant && src2.Value == 0);
- }
-
- bool modified = false;
-
- Operand dest = compOp.Destination;
- Operand src1 = compOp.GetSource(0);
- Operand src2 = compOp.GetSource(1);
- Operand comp = compOp.GetSource(2);
-
- Comparison compType = (Comparison)comp.AsInt32();
-
- Span<Operation> uses = dest.GetUses(ref buffer);
-
- foreach (Operation use in uses)
- {
- // If operation is a BranchIf and has a constant value 0 in its RHS or LHS source operands.
- if (IsZeroBranch(use, out Comparison otherCompType))
- {
- Comparison propCompType;
-
- if (otherCompType == Comparison.NotEqual)
- {
- propCompType = compType;
- }
- else if (otherCompType == Comparison.Equal)
- {
- propCompType = compType.Invert();
- }
- else
- {
- continue;
- }
-
- use.SetSource(0, src1);
- use.SetSource(1, src2);
- use.SetSource(2, Const((int)propCompType));
-
- modified = true;
- }
- }
-
- return modified;
- }
-
- 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);
-
- Span<Operation> uses = dest.GetUses(ref buffer);
-
- foreach (Operation use in uses)
- {
- for (int index = 0; index < use.SourcesCount; index++)
- {
- if (use.GetSource(index) == dest)
- {
- use.SetSource(index, source);
- }
- }
- }
- }
-
- 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.
- block.Operations.Remove(node);
-
- for (int index = 0; index < node.SourcesCount; index++)
- {
- node.SetSource(index, default);
- }
-
- Debug.Assert(node.Destination == default || node.Destination.UsesCount == 0);
-
- node.Destination = default;
- }
-
- private static bool IsUnused(Operation node)
- {
- return DestIsSingleLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
- }
-
- private static bool DestIsSingleLocalVar(Operation node)
- {
- return node.DestinationsCount == 1 && node.Destination.Kind == OperandKind.LocalVariable;
- }
-
- private static bool HasSideEffects(Operation node)
- {
- 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)
- {
- return operation.Instruction == Instruction.Compare;
- }
-
- private static bool IsPropagableCopy(Operation operation)
- {
- if (operation.Instruction != Instruction.Copy)
- {
- return false;
- }
-
- return operation.Destination.Type == operation.GetSource(0).Type;
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/Optimizations/Simplification.cs b/ARMeilleure/CodeGen/Optimizations/Simplification.cs
deleted file mode 100644
index a439d642..00000000
--- a/ARMeilleure/CodeGen/Optimizations/Simplification.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-using ARMeilleure.IntermediateRepresentation;
-using System;
-using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
-
-namespace ARMeilleure.CodeGen.Optimizations
-{
- static class Simplification
- {
- public static void RunPass(Operation operation)
- {
- switch (operation.Instruction)
- {
- case Instruction.Add:
- if (operation.GetSource(0).Relocatable ||
- operation.GetSource(1).Relocatable)
- {
- break;
- }
-
- TryEliminateBinaryOpComutative(operation, 0);
- break;
-
- case Instruction.BitwiseAnd:
- TryEliminateBitwiseAnd(operation);
- break;
-
- case Instruction.BitwiseOr:
- TryEliminateBitwiseOr(operation);
- break;
-
- case Instruction.BitwiseExclusiveOr:
- TryEliminateBitwiseExclusiveOr(operation);
- break;
-
- case Instruction.ConditionalSelect:
- TryEliminateConditionalSelect(operation);
- break;
-
- case Instruction.Divide:
- TryEliminateBinaryOpY(operation, 1);
- break;
-
- case Instruction.Multiply:
- TryEliminateBinaryOpComutative(operation, 1);
- break;
-
- case Instruction.ShiftLeft:
- case Instruction.ShiftRightSI:
- case Instruction.ShiftRightUI:
- case Instruction.Subtract:
- TryEliminateBinaryOpY(operation, 0);
- break;
- }
- }
-
- private static void TryEliminateBitwiseAnd(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
- // x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, AllOnes(x.Type)))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, AllOnes(y.Type)))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, 0) || IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(Const(x.Type, 0));
- }
- }
-
- private static void TryEliminateBitwiseOr(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x | 0x00000000 == x, 0x00000000 | y == y,
- // x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, 0))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, AllOnes(x.Type)) || IsConstEqual(y, AllOnes(y.Type)))
- {
- operation.TurnIntoCopy(Const(AllOnes(x.Type)));
- }
- }
-
- private static void TryEliminateBitwiseExclusiveOr(Operation operation)
- {
- // Try to recognize and optimize those 2 patterns (in order):
- // x ^ y == 0x00000000 when x == y
- // 0x00000000 ^ y == y, x ^ 0x00000000 == x
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (x == y && x.Type.IsInteger())
- {
- operation.TurnIntoCopy(Const(x.Type, 0));
- }
- else
- {
- TryEliminateBinaryOpComutative(operation, 0);
- }
- }
-
- private static void TryEliminateBinaryOpY(Operation operation, ulong comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateBinaryOpComutative(Operation operation, ulong comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, comparand))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateConditionalSelect(Operation operation)
- {
- Operand cond = operation.GetSource(0);
-
- if (cond.Kind != OperandKind.Constant)
- {
- return;
- }
-
- // The condition is constant, we can turn it into a copy, and select
- // the source based on the condition value.
- int srcIndex = cond.Value != 0 ? 1 : 2;
-
- Operand source = operation.GetSource(srcIndex);
-
- operation.TurnIntoCopy(source);
- }
-
- private static bool IsConstEqual(Operand operand, ulong comparand)
- {
- if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger())
- {
- return false;
- }
-
- return operand.Value == comparand;
- }
-
- private static ulong AllOnes(OperandType type)
- {
- switch (type)
- {
- case OperandType.I32: return ~0U;
- case OperandType.I64: return ~0UL;
- }
-
- throw new ArgumentException("Invalid operand type \"" + type + "\".");
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/Optimizations/TailMerge.cs b/ARMeilleure/CodeGen/Optimizations/TailMerge.cs
deleted file mode 100644
index e94df159..00000000
--- a/ARMeilleure/CodeGen/Optimizations/TailMerge.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using ARMeilleure.IntermediateRepresentation;
-using ARMeilleure.Translation;
-using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
-
-namespace ARMeilleure.CodeGen.Optimizations
-{
- static class TailMerge
- {
- public static void RunPass(in CompilerContext cctx)
- {
- ControlFlowGraph cfg = cctx.Cfg;
-
- BasicBlock mergedReturn = new(cfg.Blocks.Count);
-
- Operand returnValue;
- Operation returnOp;
-
- if (cctx.FuncReturnType == OperandType.None)
- {
- returnValue = default;
- returnOp = Operation(Instruction.Return, default);
- }
- else
- {
- returnValue = cfg.AllocateLocal(cctx.FuncReturnType);
- returnOp = Operation(Instruction.Return, default, returnValue);
- }
-
- mergedReturn.Frequency = BasicBlockFrequency.Cold;
- mergedReturn.Operations.AddLast(returnOp);
-
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
- {
- Operation op = block.Operations.Last;
-
- if (op != default && op.Instruction == Instruction.Return)
- {
- block.Operations.Remove(op);
-
- if (cctx.FuncReturnType == OperandType.None)
- {
- PrepareMerge(block, mergedReturn);
- }
- else
- {
- Operation copyOp = Operation(Instruction.Copy, returnValue, op.GetSource(0));
-
- PrepareMerge(block, mergedReturn).Append(copyOp);
- }
- }
- }
-
- cfg.Blocks.AddLast(mergedReturn);
- cfg.Update();
- }
-
- private static BasicBlock PrepareMerge(BasicBlock from, BasicBlock to)
- {
- BasicBlock fromPred = from.Predecessors.Count == 1 ? from.Predecessors[0] : null;
-
- // If the block is empty, we can try to append to the predecessor and avoid unnecessary jumps.
- if (from.Operations.Count == 0 && fromPred != null && fromPred.SuccessorsCount == 1)
- {
- for (int i = 0; i < fromPred.SuccessorsCount; i++)
- {
- if (fromPred.GetSuccessor(i) == from)
- {
- fromPred.SetSuccessor(i, to);
- }
- }
-
- // NOTE: `from` becomes unreachable and the call to `cfg.Update()` will remove it.
- return fromPred;
- }
- else
- {
- from.AddSuccessor(to);
-
- return from;
- }
- }
- }
-}