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)
if (!(nextBlock.Operations.First?.Value is Operation next))
if (next.Inst != Instruction.Branch)
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\".");
return block;