diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /ARMeilleure/CodeGen/Optimizations | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'ARMeilleure/CodeGen/Optimizations')
| -rw-r--r-- | ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs | 72 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs | 346 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/Optimizations/Optimizer.cs | 252 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/Optimizations/Simplification.cs | 183 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/Optimizations/TailMerge.cs | 83 |
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; - } - } - } -} |
