ControlFlowGraph.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Shader.Translation
  4. {
  5. class ControlFlowGraph
  6. {
  7. public BasicBlock[] Blocks { get; }
  8. public BasicBlock[] PostOrderBlocks { get; }
  9. public int[] PostOrderMap { get; }
  10. public ControlFlowGraph(BasicBlock[] blocks)
  11. {
  12. Blocks = blocks;
  13. HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
  14. Stack<BasicBlock> blockStack = new Stack<BasicBlock>();
  15. List<BasicBlock> postOrderBlocks = new List<BasicBlock>(blocks.Length);
  16. PostOrderMap = new int[blocks.Length];
  17. visited.Add(blocks[0]);
  18. blockStack.Push(blocks[0]);
  19. while (blockStack.TryPop(out BasicBlock block))
  20. {
  21. if (block.Next != null && visited.Add(block.Next))
  22. {
  23. blockStack.Push(block);
  24. blockStack.Push(block.Next);
  25. }
  26. else if (block.Branch != null && visited.Add(block.Branch))
  27. {
  28. blockStack.Push(block);
  29. blockStack.Push(block.Branch);
  30. }
  31. else
  32. {
  33. PostOrderMap[block.Index] = postOrderBlocks.Count;
  34. postOrderBlocks.Add(block);
  35. }
  36. }
  37. PostOrderBlocks = postOrderBlocks.ToArray();
  38. }
  39. public static ControlFlowGraph Create(Operation[] operations)
  40. {
  41. Dictionary<Operand, BasicBlock> labels = new Dictionary<Operand, BasicBlock>();
  42. List<BasicBlock> blocks = new List<BasicBlock>();
  43. BasicBlock currentBlock = null;
  44. void NextBlock(BasicBlock nextBlock)
  45. {
  46. if (currentBlock != null && !EndsWithUnconditionalInst(currentBlock.GetLastOp()))
  47. {
  48. currentBlock.Next = nextBlock;
  49. }
  50. currentBlock = nextBlock;
  51. }
  52. void NewNextBlock()
  53. {
  54. BasicBlock block = new BasicBlock(blocks.Count);
  55. blocks.Add(block);
  56. NextBlock(block);
  57. }
  58. bool needsNewBlock = true;
  59. for (int index = 0; index < operations.Length; index++)
  60. {
  61. Operation operation = operations[index];
  62. if (operation.Inst == Instruction.MarkLabel)
  63. {
  64. Operand label = operation.Dest;
  65. if (labels.TryGetValue(label, out BasicBlock nextBlock))
  66. {
  67. nextBlock.Index = blocks.Count;
  68. blocks.Add(nextBlock);
  69. NextBlock(nextBlock);
  70. }
  71. else
  72. {
  73. NewNextBlock();
  74. labels.Add(label, currentBlock);
  75. }
  76. }
  77. else
  78. {
  79. if (needsNewBlock)
  80. {
  81. NewNextBlock();
  82. }
  83. currentBlock.Operations.AddLast(operation);
  84. }
  85. needsNewBlock = operation.Inst == Instruction.Branch ||
  86. operation.Inst == Instruction.BranchIfTrue ||
  87. operation.Inst == Instruction.BranchIfFalse;
  88. if (needsNewBlock)
  89. {
  90. Operand label = operation.Dest;
  91. if (!labels.TryGetValue(label, out BasicBlock branchBlock))
  92. {
  93. branchBlock = new BasicBlock();
  94. labels.Add(label, branchBlock);
  95. }
  96. currentBlock.Branch = branchBlock;
  97. }
  98. }
  99. // Remove unreachable blocks.
  100. bool hasUnreachable;
  101. do
  102. {
  103. hasUnreachable = false;
  104. for (int blkIndex = 1; blkIndex < blocks.Count; blkIndex++)
  105. {
  106. BasicBlock block = blocks[blkIndex];
  107. if (block.Predecessors.Count == 0)
  108. {
  109. block.Next = null;
  110. block.Branch = null;
  111. blocks.RemoveAt(blkIndex--);
  112. hasUnreachable = true;
  113. }
  114. else
  115. {
  116. block.Index = blkIndex;
  117. }
  118. }
  119. } while (hasUnreachable);
  120. return new ControlFlowGraph(blocks.ToArray());
  121. }
  122. private static bool EndsWithUnconditionalInst(INode node)
  123. {
  124. if (node is Operation operation)
  125. {
  126. switch (operation.Inst)
  127. {
  128. case Instruction.Branch:
  129. case Instruction.Discard:
  130. case Instruction.Return:
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. }
  137. }