Optimizer.cs 4.3 KB

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