using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation; using System.Diagnostics; using static ARMeilleure.IntermediateRepresentation.OperandHelper; namespace ARMeilleure.CodeGen.Optimizations { static class BlockPlacement { public static void RunPass(ControlFlowGraph cfg) { bool update = false; BasicBlock block; BasicBlock nextBlock; BasicBlock lastBlock = cfg.Blocks.Last; // Move cold blocks at the end of the list, so that they are emitted away from hot code. for (block = cfg.Blocks.First; block != lastBlock; block = nextBlock) { nextBlock = block.ListNext; if (block.Frequency == BasicBlockFrequency.Cold) { cfg.Blocks.Remove(block); cfg.Blocks.AddLast(block); } } for (block = cfg.Blocks.First; block != null; block = nextBlock) { nextBlock = block.ListNext; if (block.SuccessorCount == 2 && block.Operations.Last is Operation branchOp) { Debug.Assert(branchOp.Instruction == Instruction.BranchIf); BasicBlock falseSucc = block.GetSuccessor(0); BasicBlock trueSucc = block.GetSuccessor(1); // If true successor is next block in list, invert the condition. We avoid extra branching by // making the true side the fallthrough (i.e, convert it to the false side). if (trueSucc == block.ListNext) { Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32(); Comparison compInv = comp.Invert(); branchOp.SetSource(2, Const((int)compInv)); block.SetSuccessor(0, trueSucc); block.SetSuccessor(1, falseSucc); update = true; } } } if (update) { cfg.Update(removeUnreachableBlocks: false); } } } }