| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.Translation;
- using System.Diagnostics;
- using static ARMeilleure.IntermediateRepresentation.OperandHelper;
- namespace ARMeilleure.CodeGen.Optimizations
- {
- static class Optimizer
- {
- public static void RunPass(ControlFlowGraph cfg)
- {
- bool modified;
- do
- {
- modified = false;
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
- {
- Node node = block.Operations.First;
- while (node != null)
- {
- Node nextNode = node.ListNext;
- bool isUnused = IsUnused(node);
- if (!(node is Operation operation) || isUnused)
- {
- if (isUnused)
- {
- RemoveNode(block, node);
- modified = true;
- }
- node = nextNode;
- continue;
- }
- ConstantFolding.RunPass(operation);
- Simplification.RunPass(operation);
- if (DestIsLocalVar(operation))
- {
- if (IsPropagableCompare(operation))
- {
- modified |= PropagateCompare(operation);
- if (modified && IsUnused(operation))
- {
- RemoveNode(block, node);
- }
- }
- else if (IsPropagableCopy(operation))
- {
- PropagateCopy(operation);
- RemoveNode(block, node);
- modified = true;
- }
- }
- node = nextNode;
- }
- }
- }
- while (modified);
- }
- public static void RemoveUnusedNodes(ControlFlowGraph cfg)
- {
- bool modified;
- do
- {
- modified = false;
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
- {
- Node node = block.Operations.First;
- while (node != null)
- {
- Node nextNode = node.ListNext;
- if (IsUnused(node))
- {
- RemoveNode(block, node);
- modified = true;
- }
- node = nextNode;
- }
- }
- }
- while (modified);
- }
- private static bool PropagateCompare(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();
- Node[] uses = dest.Uses.ToArray();
- foreach (Node use in uses)
- {
- if (!(use is Operation operation))
- {
- continue;
- }
- // If operation is a BranchIf and has a constant value 0 in its RHS or LHS source operands.
- if (IsZeroBranch(operation, out Comparison otherCompType))
- {
- Comparison propCompType;
- if (otherCompType == Comparison.NotEqual)
- {
- propCompType = compType;
- }
- else if (otherCompType == Comparison.Equal)
- {
- propCompType = compType.Invert();
- }
- else
- {
- continue;
- }
- operation.SetSource(0, src1);
- operation.SetSource(1, src2);
- operation.SetSource(2, Const((int)propCompType));
- modified = true;
- }
- }
- return modified;
- }
- private static void PropagateCopy(Operation copyOp)
- {
- // Propagate copy source operand to all uses of the destination operand.
- Operand dest = copyOp.Destination;
- Operand source = copyOp.GetSource(0);
- Node[] uses = dest.Uses.ToArray();
- foreach (Node 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, Node 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, null);
- }
- Debug.Assert(node.Destination == null || node.Destination.Uses.Count == 0);
- node.Destination = null;
- }
- private static bool IsUnused(Node node)
- {
- return DestIsLocalVar(node) && node.Destination.Uses.Count == 0 && !HasSideEffects(node);
- }
- private static bool DestIsLocalVar(Node node)
- {
- return node.Destination != null && node.Destination.Kind == OperandKind.LocalVariable;
- }
- private static bool HasSideEffects(Node node)
- {
- return (node is Operation operation) && (operation.Instruction == Instruction.Call
- || operation.Instruction == Instruction.Tailcall
- || operation.Instruction == Instruction.CompareAndSwap
- || operation.Instruction == Instruction.CompareAndSwap16
- || operation.Instruction == Instruction.CompareAndSwap8);
- }
- 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;
- }
- }
- }
|