Optimizer.cs 5.2 KB

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