AstOptimizer.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using Ryujinx.Graphics.Shader.Translation;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
  6. namespace Ryujinx.Graphics.Shader.StructuredIr
  7. {
  8. static class AstOptimizer
  9. {
  10. public static void Optimize(StructuredProgramContext context)
  11. {
  12. AstBlock mainBlock = context.CurrentFunction.MainBlock;
  13. // When debug mode is enabled, we disable expression propagation
  14. // (this makes comparison with the disassembly easier).
  15. if ((context.Config.Flags & TranslationFlags.DebugMode) == 0)
  16. {
  17. AstBlockVisitor visitor = new AstBlockVisitor(mainBlock);
  18. foreach (IAstNode node in visitor.Visit())
  19. {
  20. if (node is AstAssignment assignment && assignment.Destination is AstOperand propVar)
  21. {
  22. bool isWorthPropagating = propVar.Uses.Count == 1 || IsWorthPropagating(assignment.Source);
  23. if (propVar.Defs.Count == 1 && isWorthPropagating)
  24. {
  25. PropagateExpression(propVar, assignment.Source);
  26. }
  27. if (propVar.Type == OperandType.LocalVariable && propVar.Uses.Count == 0)
  28. {
  29. visitor.Block.Remove(assignment);
  30. context.CurrentFunction.Locals.Remove(propVar);
  31. }
  32. }
  33. }
  34. }
  35. RemoveEmptyBlocks(mainBlock);
  36. }
  37. private static bool IsWorthPropagating(IAstNode source)
  38. {
  39. if (!(source is AstOperation srcOp))
  40. {
  41. return false;
  42. }
  43. if (!InstructionInfo.IsUnary(srcOp.Inst))
  44. {
  45. return false;
  46. }
  47. return srcOp.GetSource(0) is AstOperand || srcOp.Inst == Instruction.Copy;
  48. }
  49. private static void PropagateExpression(AstOperand propVar, IAstNode source)
  50. {
  51. IAstNode[] uses = propVar.Uses.ToArray();
  52. foreach (IAstNode useNode in uses)
  53. {
  54. if (useNode is AstBlock useBlock)
  55. {
  56. useBlock.Condition = source;
  57. }
  58. else if (useNode is AstOperation useOperation)
  59. {
  60. for (int srcIndex = 0; srcIndex < useOperation.SourcesCount; srcIndex++)
  61. {
  62. if (useOperation.GetSource(srcIndex) == propVar)
  63. {
  64. useOperation.SetSource(srcIndex, source);
  65. }
  66. }
  67. }
  68. else if (useNode is AstAssignment useAssignment)
  69. {
  70. useAssignment.Source = source;
  71. }
  72. }
  73. }
  74. private static void RemoveEmptyBlocks(AstBlock mainBlock)
  75. {
  76. Queue<AstBlock> pending = new Queue<AstBlock>();
  77. pending.Enqueue(mainBlock);
  78. while (pending.TryDequeue(out AstBlock block))
  79. {
  80. foreach (IAstNode node in block)
  81. {
  82. if (node is AstBlock childBlock)
  83. {
  84. pending.Enqueue(childBlock);
  85. }
  86. }
  87. AstBlock parent = block.Parent;
  88. if (parent == null)
  89. {
  90. continue;
  91. }
  92. AstBlock nextBlock = Next(block) as AstBlock;
  93. bool hasElse = nextBlock != null && nextBlock.Type == AstBlockType.Else;
  94. bool isIf = block.Type == AstBlockType.If;
  95. if (block.Count == 0)
  96. {
  97. if (isIf)
  98. {
  99. if (hasElse)
  100. {
  101. nextBlock.TurnIntoIf(InverseCond(block.Condition));
  102. }
  103. parent.Remove(block);
  104. }
  105. else if (block.Type == AstBlockType.Else)
  106. {
  107. parent.Remove(block);
  108. }
  109. }
  110. else if (isIf && parent.Type == AstBlockType.Else && parent.Count == (hasElse ? 2 : 1))
  111. {
  112. AstBlock parentOfParent = parent.Parent;
  113. parent.Remove(block);
  114. parentOfParent.AddAfter(parent, block);
  115. if (hasElse)
  116. {
  117. parent.Remove(nextBlock);
  118. parentOfParent.AddAfter(block, nextBlock);
  119. }
  120. parentOfParent.Remove(parent);
  121. block.TurnIntoElseIf();
  122. }
  123. }
  124. }
  125. }
  126. }