ControlFlowGraph.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Shader.Translation
  4. {
  5. static class ControlFlowGraph
  6. {
  7. public static BasicBlock[] MakeCfg(Operation[] operations)
  8. {
  9. Dictionary<Operand, BasicBlock> labels = new Dictionary<Operand, BasicBlock>();
  10. List<BasicBlock> blocks = new List<BasicBlock>();
  11. BasicBlock currentBlock = null;
  12. void NextBlock(BasicBlock nextBlock)
  13. {
  14. if (currentBlock != null && !EndsWithUnconditionalInst(currentBlock.GetLastOp()))
  15. {
  16. currentBlock.Next = nextBlock;
  17. }
  18. currentBlock = nextBlock;
  19. }
  20. void NewNextBlock()
  21. {
  22. BasicBlock block = new BasicBlock(blocks.Count);
  23. blocks.Add(block);
  24. NextBlock(block);
  25. }
  26. bool needsNewBlock = true;
  27. for (int index = 0; index < operations.Length; index++)
  28. {
  29. Operation operation = operations[index];
  30. if (operation.Inst == Instruction.MarkLabel)
  31. {
  32. Operand label = operation.Dest;
  33. if (labels.TryGetValue(label, out BasicBlock nextBlock))
  34. {
  35. nextBlock.Index = blocks.Count;
  36. blocks.Add(nextBlock);
  37. NextBlock(nextBlock);
  38. }
  39. else
  40. {
  41. NewNextBlock();
  42. labels.Add(label, currentBlock);
  43. }
  44. }
  45. else
  46. {
  47. if (needsNewBlock)
  48. {
  49. NewNextBlock();
  50. }
  51. currentBlock.Operations.AddLast(operation);
  52. }
  53. needsNewBlock = operation.Inst == Instruction.Branch ||
  54. operation.Inst == Instruction.BranchIfTrue ||
  55. operation.Inst == Instruction.BranchIfFalse;
  56. if (needsNewBlock)
  57. {
  58. Operand label = operation.Dest;
  59. if (!labels.TryGetValue(label, out BasicBlock branchBlock))
  60. {
  61. branchBlock = new BasicBlock();
  62. labels.Add(label, branchBlock);
  63. }
  64. currentBlock.Branch = branchBlock;
  65. }
  66. }
  67. return blocks.ToArray();
  68. }
  69. private static bool EndsWithUnconditionalInst(INode node)
  70. {
  71. if (node is Operation operation)
  72. {
  73. switch (operation.Inst)
  74. {
  75. case Instruction.Branch:
  76. case Instruction.Discard:
  77. case Instruction.Return:
  78. return true;
  79. }
  80. }
  81. return false;
  82. }
  83. }
  84. }