private string TryReduceJump(BasicBlock root, JumpBasicBlock jumpbb) { // Try to find a linear chain of branches of length > 1 var group = new Set<BasicBlock> { jumpbb }; var chain = new Seq<BasicBlock> { jumpbb }; var start = jumpbb; while (start.Sources.Count == 1 && start.Sources[0] is JumpBasicBlock && !group.Contains(start.Sources[0])) { // Extend chain upwards start = (JumpBasicBlock)start.Sources[0]; group.Add(start); chain.Insert(0, start); } var endjump = jumpbb; while (endjump.Target.Sources.Count == 1 && endjump.Target is JumpBasicBlock && !group.Contains(endjump.Target)) { // Extend chain downwards endjump = (JumpBasicBlock)endjump.Target; group.Add(endjump); chain.Add(endjump); } var end = (BasicBlock)endjump; if (endjump.Target.Sources.Count == 1 && endjump.Target.AcceptsInstructions && !group.Contains(endjump.Target)) { // Extend chain downwards to include a final non jump basic block, provided we can put all // the accumulated instructions there end = endjump.Target; group.Add(end); chain.Add(end); } if (chain.Count > 1) { // Coalesce and peephole var instructions = new Seq<Instruction>(); foreach (var bb in chain) bb.Block.AccumInstructions(instructions); var newbb = end.CloneWithInstructions(nextBlockId++, Peephole(chain[0].Block.BeforeState, instructions)); root.Coalesce(start, group, newbb); return String.Format("collapsed chain of {0} jump blocks from B{1}", chain.Count, start.Id); } else if (start.Block.Count == 0 && !start.Target.Equals(start)) { // Short-circuit a trivial jump root.Delete(start); return String.Format("short-circuited trivial jump at B{0}", start.Id); } else if (start.Target.Equals(start)) { // loop var li = new LoopInstruction(NextInstructionId--, start.Block) { BeforeState = jumpbb.Block.BeforeState, AfterState = jumpbb.Block.AfterState }; var newbb = new NonReturningBasicBlock(nextBlockId++, new Instructions(li)); root.Coalesce(start, new Set<BasicBlock> { start }, newbb); return String.Format("trival loop at B{0}", start.Id); } else return null; }