using Ryujinx.Graphics.Shader.IntermediateRepresentation; using System; namespace Ryujinx.Graphics.Shader.Translation.Optimizations { static class BranchElimination { public static bool Eliminate(BasicBlock block) { if (block.HasBranch && IsRedundantBranch((Operation)block.GetLastOp(), Next(block))) { block.Branch = null; return true; } return false; } private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock) { //Here we check that: //- The current block ends with a branch. //- The next block only contains a branch. //- The branch on the next block is unconditional. //- Both branches are jumping to the same location. //In this case, the branch on the current block can be removed, //as the next block is going to jump to the same place anyway. if (nextBlock == null) { return false; } if (!(nextBlock.Operations.First?.Value is Operation next)) { return false; } if (next.Inst != Instruction.Branch) { return false; } return current.Dest == next.Dest; } private static BasicBlock Next(BasicBlock block) { block = block.Next; while (block != null && block.Operations.Count == 0) { if (block.HasBranch) { throw new InvalidOperationException("Found a bogus empty block that \"ends with a branch\"."); } block = block.Next; } return block; } } }