Optimizer.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using ARMeilleure.IntermediateRepresentation;
  2. using ARMeilleure.Translation;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. namespace ARMeilleure.CodeGen.Optimizations
  7. {
  8. static class Optimizer
  9. {
  10. public static void RunPass(ControlFlowGraph cfg)
  11. {
  12. bool modified;
  13. do
  14. {
  15. modified = false;
  16. foreach (BasicBlock block in cfg.Blocks)
  17. {
  18. LinkedListNode<Node> node = block.Operations.First;
  19. while (node != null)
  20. {
  21. LinkedListNode<Node> nextNode = node.Next;
  22. bool isUnused = IsUnused(node.Value);
  23. if (!(node.Value is Operation operation) || isUnused)
  24. {
  25. if (isUnused)
  26. {
  27. RemoveNode(block, node);
  28. modified = true;
  29. }
  30. node = nextNode;
  31. continue;
  32. }
  33. ConstantFolding.RunPass(operation);
  34. Simplification.RunPass(operation);
  35. if (DestIsLocalVar(operation) && IsPropagableCopy(operation))
  36. {
  37. PropagateCopy(operation);
  38. RemoveNode(block, node);
  39. modified = true;
  40. }
  41. node = nextNode;
  42. }
  43. }
  44. }
  45. while (modified);
  46. }
  47. private static void PropagateCopy(Operation copyOp)
  48. {
  49. // Propagate copy source operand to all uses of the destination operand.
  50. Operand dest = copyOp.Destination;
  51. Operand source = copyOp.GetSource(0);
  52. Node[] uses = dest.Uses.ToArray();
  53. foreach (Node use in uses)
  54. {
  55. for (int index = 0; index < use.SourcesCount; index++)
  56. {
  57. if (use.GetSource(index) == dest)
  58. {
  59. use.SetSource(index, source);
  60. }
  61. }
  62. }
  63. }
  64. private static void RemoveNode(BasicBlock block, LinkedListNode<Node> llNode)
  65. {
  66. // Remove a node from the nodes list, and also remove itself
  67. // from all the use lists on the operands that this node uses.
  68. block.Operations.Remove(llNode);
  69. Node node = llNode.Value;
  70. for (int index = 0; index < node.SourcesCount; index++)
  71. {
  72. node.SetSource(index, null);
  73. }
  74. Debug.Assert(node.Destination == null || node.Destination.Uses.Count == 0);
  75. node.Destination = null;
  76. }
  77. private static bool IsUnused(Node node)
  78. {
  79. return DestIsLocalVar(node) && node.Destination.Uses.Count == 0 && !HasSideEffects(node);
  80. }
  81. private static bool DestIsLocalVar(Node node)
  82. {
  83. return node.Destination != null && node.Destination.Kind == OperandKind.LocalVariable;
  84. }
  85. private static bool HasSideEffects(Node node)
  86. {
  87. return (node is Operation operation) && operation.Instruction == Instruction.Call;
  88. }
  89. private static bool IsPropagableCopy(Operation operation)
  90. {
  91. if (operation.Instruction != Instruction.Copy)
  92. {
  93. return false;
  94. }
  95. return operation.Destination.Type == operation.GetSource(0).Type;
  96. }
  97. }
  98. }