BranchElimination.cs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using System;
  3. namespace Ryujinx.Graphics.Shader.Translation.Optimizations
  4. {
  5. static class BranchElimination
  6. {
  7. public static bool RunPass(BasicBlock block)
  8. {
  9. if (block.HasBranch && IsRedundantBranch((Operation)block.GetLastOp(), Next(block)))
  10. {
  11. block.Branch = null;
  12. return true;
  13. }
  14. return false;
  15. }
  16. private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock)
  17. {
  18. // Here we check that:
  19. // - The current block ends with a branch.
  20. // - The next block only contains a branch.
  21. // - The branch on the next block is unconditional.
  22. // - Both branches are jumping to the same location.
  23. // In this case, the branch on the current block can be removed,
  24. // as the next block is going to jump to the same place anyway.
  25. if (nextBlock == null)
  26. {
  27. return false;
  28. }
  29. if (!(nextBlock.Operations.First?.Value is Operation next))
  30. {
  31. return false;
  32. }
  33. if (next.Inst != Instruction.Branch)
  34. {
  35. return false;
  36. }
  37. return current.Dest == next.Dest;
  38. }
  39. private static BasicBlock Next(BasicBlock block)
  40. {
  41. block = block.Next;
  42. while (block != null && block.Operations.Count == 0)
  43. {
  44. if (block.HasBranch)
  45. {
  46. throw new InvalidOperationException("Found a bogus empty block that \"ends with a branch\".");
  47. }
  48. block = block.Next;
  49. }
  50. return block;
  51. }
  52. }
  53. }