Optimizer.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Ryujinx.Graphics.Shader.Translation.Optimizations
  5. {
  6. static class Optimizer
  7. {
  8. public static void Optimize(BasicBlock[] blocks, ShaderStage stage)
  9. {
  10. for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
  11. {
  12. GlobalToStorage.RunPass(blocks[blkIndex], stage);
  13. }
  14. bool modified;
  15. do
  16. {
  17. modified = false;
  18. for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
  19. {
  20. BasicBlock block = blocks[blkIndex];
  21. LinkedListNode<INode> node = block.Operations.First;
  22. while (node != null)
  23. {
  24. LinkedListNode<INode> nextNode = node.Next;
  25. bool isUnused = IsUnused(node.Value);
  26. if (!(node.Value is Operation operation) || isUnused)
  27. {
  28. if (isUnused)
  29. {
  30. RemoveNode(block, node);
  31. modified = true;
  32. }
  33. node = nextNode;
  34. continue;
  35. }
  36. ConstantFolding.RunPass(operation);
  37. Simplification.RunPass(operation);
  38. if (DestIsLocalVar(operation))
  39. {
  40. if (operation.Inst == Instruction.Copy)
  41. {
  42. PropagateCopy(operation);
  43. RemoveNode(block, node);
  44. modified = true;
  45. }
  46. else if (operation.Inst == Instruction.PackHalf2x16 && PropagatePack(operation))
  47. {
  48. if (operation.Dest.UseOps.Count == 0)
  49. {
  50. RemoveNode(block, node);
  51. }
  52. modified = true;
  53. }
  54. }
  55. node = nextNode;
  56. }
  57. if (BranchElimination.RunPass(block))
  58. {
  59. RemoveNode(block, block.Operations.Last);
  60. modified = true;
  61. }
  62. }
  63. }
  64. while (modified);
  65. }
  66. private static void PropagateCopy(Operation copyOp)
  67. {
  68. // Propagate copy source operand to all uses of
  69. // the destination operand.
  70. Operand dest = copyOp.Dest;
  71. Operand src = copyOp.GetSource(0);
  72. INode[] uses = dest.UseOps.ToArray();
  73. foreach (INode useNode in uses)
  74. {
  75. for (int index = 0; index < useNode.SourcesCount; index++)
  76. {
  77. if (useNode.GetSource(index) == dest)
  78. {
  79. useNode.SetSource(index, src);
  80. }
  81. }
  82. }
  83. }
  84. private static bool PropagatePack(Operation packOp)
  85. {
  86. // Propagate pack source operands to uses by unpack
  87. // instruction. The source depends on the unpack instruction.
  88. bool modified = false;
  89. Operand dest = packOp.Dest;
  90. Operand src0 = packOp.GetSource(0);
  91. Operand src1 = packOp.GetSource(1);
  92. INode[] uses = dest.UseOps.ToArray();
  93. foreach (INode useNode in uses)
  94. {
  95. if (!(useNode is Operation operation) || operation.Inst != Instruction.UnpackHalf2x16)
  96. {
  97. continue;
  98. }
  99. if (operation.GetSource(0) == dest)
  100. {
  101. operation.TurnIntoCopy(operation.ComponentIndex == 1 ? src1 : src0);
  102. modified = true;
  103. }
  104. }
  105. return modified;
  106. }
  107. private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
  108. {
  109. // Remove a node from the nodes list, and also remove itself
  110. // from all the use lists on the operands that this node uses.
  111. block.Operations.Remove(llNode);
  112. Queue<INode> nodes = new Queue<INode>();
  113. nodes.Enqueue(llNode.Value);
  114. while (nodes.TryDequeue(out INode node))
  115. {
  116. for (int index = 0; index < node.SourcesCount; index++)
  117. {
  118. Operand src = node.GetSource(index);
  119. if (src.Type != OperandType.LocalVariable)
  120. {
  121. continue;
  122. }
  123. if (src.UseOps.Remove(node) && src.UseOps.Count == 0)
  124. {
  125. nodes.Enqueue(src.AsgOp);
  126. }
  127. }
  128. }
  129. }
  130. private static bool IsUnused(INode node)
  131. {
  132. return DestIsLocalVar(node) && node.Dest.UseOps.Count == 0;
  133. }
  134. private static bool DestIsLocalVar(INode node)
  135. {
  136. return node.Dest != null && node.Dest.Type == OperandType.LocalVariable;
  137. }
  138. }
  139. }