Exemplo n.º 1
0
 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;
 }