ControlFlowGraph.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using ARMeilleure.IntermediateRepresentation;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. namespace ARMeilleure.Translation
  6. {
  7. class ControlFlowGraph
  8. {
  9. public BasicBlock Entry { get; }
  10. public IntrusiveList<BasicBlock> Blocks { get; }
  11. public BasicBlock[] PostOrderBlocks { get; }
  12. public int[] PostOrderMap { get; }
  13. public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks)
  14. {
  15. Entry = entry;
  16. Blocks = blocks;
  17. RemoveUnreachableBlocks(blocks);
  18. var visited = new HashSet<BasicBlock>();
  19. var blockStack = new Stack<BasicBlock>();
  20. PostOrderBlocks = new BasicBlock[blocks.Count];
  21. PostOrderMap = new int[blocks.Count];
  22. visited.Add(entry);
  23. blockStack.Push(entry);
  24. int index = 0;
  25. while (blockStack.TryPop(out BasicBlock block))
  26. {
  27. bool visitedNew = false;
  28. for (int i = 0; i < block.SuccessorCount; i++)
  29. {
  30. BasicBlock succ = block.GetSuccessor(i);
  31. if (visited.Add(succ))
  32. {
  33. blockStack.Push(block);
  34. blockStack.Push(succ);
  35. visitedNew = true;
  36. break;
  37. }
  38. }
  39. if (!visitedNew)
  40. {
  41. PostOrderMap[block.Index] = index;
  42. PostOrderBlocks[index++] = block;
  43. }
  44. }
  45. }
  46. private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
  47. {
  48. var visited = new HashSet<BasicBlock>();
  49. var workQueue = new Queue<BasicBlock>();
  50. visited.Add(Entry);
  51. workQueue.Enqueue(Entry);
  52. while (workQueue.TryDequeue(out BasicBlock block))
  53. {
  54. Debug.Assert(block.Index != -1, "Invalid block index.");
  55. for (int i = 0; i < block.SuccessorCount; i++)
  56. {
  57. BasicBlock succ = block.GetSuccessor(i);
  58. if (visited.Add(succ))
  59. {
  60. workQueue.Enqueue(succ);
  61. }
  62. }
  63. }
  64. if (visited.Count < blocks.Count)
  65. {
  66. // Remove unreachable blocks and renumber.
  67. int index = 0;
  68. for (BasicBlock block = blocks.First; block != null;)
  69. {
  70. BasicBlock nextBlock = block.ListNext;
  71. if (!visited.Contains(block))
  72. {
  73. while (block.SuccessorCount > 0)
  74. {
  75. block.RemoveSuccessor(index: block.SuccessorCount - 1);
  76. }
  77. blocks.Remove(block);
  78. }
  79. else
  80. {
  81. block.Index = index++;
  82. }
  83. block = nextBlock;
  84. }
  85. }
  86. }
  87. public BasicBlock SplitEdge(BasicBlock predecessor, BasicBlock successor)
  88. {
  89. BasicBlock splitBlock = new BasicBlock(Blocks.Count);
  90. for (int i = 0; i < predecessor.SuccessorCount; i++)
  91. {
  92. if (predecessor.GetSuccessor(i) == successor)
  93. {
  94. predecessor.SetSuccessor(i, splitBlock);
  95. }
  96. }
  97. if (splitBlock.Predecessors.Count == 0)
  98. {
  99. throw new ArgumentException("Predecessor and successor are not connected.");
  100. }
  101. splitBlock.AddSuccessor(successor);
  102. Blocks.AddBefore(successor, splitBlock);
  103. return splitBlock;
  104. }
  105. }
  106. }