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;
 }
Exemplo n.º 2
0
        private string TryReduceBranch(BasicBlock root, BranchBasicBlock branchbb)
        {
            var beforeState = branchbb.Block.BeforeState;
            var afterState = branchbb.Block.AfterState;
            {
                // While-do
                var thenbb = branchbb.Target as JumpBasicBlock;
                var group = new Set<BasicBlock> { branchbb };
                if (thenbb != null && thenbb.Target.Equals(branchbb) && thenbb.Sources.Count == 1 && group.Add(thenbb) &&
                    !group.Contains(branchbb.Fallthrough))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var wdi = new WhileDoInstruction
                        (NextInstructionId--, new Instructions(beforeState, instructions), thenbb.Block)
                              {
                                  BeforeState = beforeState,
                                  AfterState = branchbb.Fallthrough.Block.BeforeState
                              };
                    var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(wdi), branchbb.Fallthrough);
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format("while-do from B{0}", branchbb.Id);
                }
            }

            {
                // Flipped while-do
                var elsebb = branchbb.Fallthrough as JumpBasicBlock;
                var group = new Set<BasicBlock> { branchbb };
                if (elsebb != null && elsebb.Target.Equals(branchbb) && elsebb.Sources.Count == 1 && group.Add(elsebb) &&
                    !group.Contains(branchbb.Target))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                    var wdi = new WhileDoInstruction
                        (NextInstructionId--, new Instructions(beforeState, instructions), elsebb.Block)
                              {
                                  BeforeState = beforeState,
                                  AfterState = branchbb.Target.Block.BeforeState
                              };
                    var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(wdi), branchbb.Target);
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format("while-do (flipped) from B{0}", branchbb.Id);
                }
            }

            {
                // Do-while
                var thenbb = branchbb.Target;
                if (thenbb.Equals(branchbb) && !branchbb.Fallthrough.Equals(branchbb))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, beforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var dwi = new DoWhileInstruction(NextInstructionId--, new Instructions(beforeState, instructions), cond)
                              {
                                  BeforeState = beforeState,
                                  AfterState = branchbb.Fallthrough.Block.BeforeState
                              };
                    var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(dwi), branchbb.Fallthrough);
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
                    return String.Format("do-while from B{0}", branchbb.Id);
                }
            }

            {
                // Flipped Do-while
                var elsebb = branchbb.Fallthrough;
                if (elsebb.Equals(branchbb) && !branchbb.Target.Equals(branchbb))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, beforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var dwi = new DoWhileInstruction(NextInstructionId--, new Instructions(beforeState, instructions), cond)
                              {
                                  BeforeState = beforeState,
                                  AfterState = branchbb.Target.Block.BeforeState
                              };
                    var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(dwi), branchbb.Target);
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
                    return String.Format("do-while (flipped) from B{0}", branchbb.Id);
                }
            }

            {
                // If-then, converging control
                var thenbb = branchbb.Target as JumpBasicBlock;
                if (thenbb != null && thenbb.Target.Equals(branchbb.Fallthrough) && thenbb.Sources.Count == 1)
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var itei = new IfThenElseInstruction(NextInstructionId--, cond, thenbb.Block, null)
                               { BeforeState = beforeState, AfterState = thenbb.Block.AfterState };
                    instructions.Add(itei);
                    var newbb = thenbb.CloneWithInstructions
                        (nextBlockId++, new Instructions(beforeState, instructions));
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, thenbb }, newbb);
                    return String.Format("if-then with converging control paths from B{0}", branchbb.Id);
                }
            }

            {
                // Flipped if-then, converging control
                var elsebb = branchbb.Fallthrough as JumpBasicBlock;
                if (elsebb != null && elsebb.Target.Equals(branchbb.Target) && elsebb.Sources.Count == 1)
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var itei = new IfThenElseInstruction(NextInstructionId--, cond, elsebb.Block, null)
                               { BeforeState = beforeState, AfterState = elsebb.Block.AfterState };
                    instructions.Add(itei);
                    var newbb = elsebb.CloneWithInstructions
                        (nextBlockId++, new Instructions(beforeState, instructions));
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, elsebb }, newbb);
                    return String.Format("if-then (flipped) with converging control paths from B{0}", branchbb.Id);
                }
            }

            {
                // Short-circuited and/or "expression"
                var thenbb = branchbb.Target as JumpBasicBlock;
                var elsebb = branchbb.Fallthrough as JumpBasicBlock;
                var group = new Set<BasicBlock> { branchbb };
                if (thenbb != null && elsebb != null && thenbb.Target.Equals(elsebb.Target) &&
                    elsebb.Sources.Count == 1 && group.Add(elsebb) && !group.Contains(thenbb) &&
                    !group.Contains(thenbb.Target) && !thenbb.Target.Equals(thenbb) &&
                    IsLoadBooleanBlock(thenbb.Block))
                {
                    var instructions = branchbb.Block.CopyContents();
                    var test = IsLoadTrueBooleanBlock(thenbb.Block) ? branchbb.Test : branchbb.Test.Negate();
                    test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var op = IsLoadTrueBooleanBlock(thenbb.Block) ? ShortCircuitingOp.Or : ShortCircuitingOp.And;
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, op, elsebb.Block)
                              { BeforeState = beforeState, AfterState = elsebb.Block.AfterState };
                    instructions.Add(sci);
                    var newbb = new JumpBasicBlock
                        (nextBlockId++, new Instructions(beforeState, instructions), elsebb.Target);
                    if (thenbb.Sources.Count == 1)
                        group.Add(thenbb);
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format("short-circuited and/or expression from B{0}", branchbb.Id);
                }
            }

            {
                // Flipped short-circuited and/or "expression"
                var thenbb = branchbb.Target as JumpBasicBlock;
                var elsebb = branchbb.Fallthrough as JumpBasicBlock;
                var group = new Set<BasicBlock> { branchbb };
                if (thenbb != null && elsebb != null && thenbb.Target.Equals(elsebb.Target) &&
                    thenbb.Sources.Count == 1 && group.Add(thenbb) && !group.Contains(elsebb) &&
                    !group.Contains(elsebb.Target) && !elsebb.Target.Equals(elsebb) &&
                    IsLoadBooleanBlock(elsebb.Block))
                {
                    var instructions = branchbb.Block.CopyContents();
                    var test = IsLoadTrueBooleanBlock(elsebb.Block) ? branchbb.Test.Negate() : branchbb.Test;
                    test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var op = IsLoadTrueBooleanBlock(elsebb.Block) ? ShortCircuitingOp.Or : ShortCircuitingOp.And;
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, op, thenbb.Block)
                              { BeforeState = beforeState, AfterState = thenbb.Block.AfterState };
                    instructions.Add(sci);
                    var newbb = new JumpBasicBlock
                        (nextBlockId++, new Instructions(beforeState, instructions), thenbb.Target);
                    if (elsebb.Sources.Count == 1)
                        group.Add(elsebb);
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format("short-circuited (flipped) and/or expression from B{0}", branchbb.Id);
                }
            }

            {
                // Short-circuited and/or control flow
                var group = new Set<BasicBlock> { branchbb };
                var thenbb = branchbb.Target as BranchBasicBlock;
                if (thenbb != null && branchbb.Fallthrough.Equals(thenbb.Fallthrough) && thenbb.Sources.Count == 1 &&
                    group.Add(thenbb) && !group.Contains(thenbb.Target) && !group.Contains(branchbb.Fallthrough))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var instructions2 = thenbb.Block.CopyContents();
                    var afterState2 = thenbb.Test.Eval
                        (instructions2, thenbb.Block.AfterState, thenbb.Target.Block.BeforeState, BottomPT);
                    var right = new Instructions(thenbb.Block.BeforeState, instructions2);
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, ShortCircuitingOp.And, right)
                              { BeforeState = beforeState, AfterState = afterState2 };
                    instructions.Add(sci);
                    var newbb = new BranchBasicBlock
                        (nextBlockId++,
                         new Instructions(beforeState, instructions),
                         new Test(TestOp.True, false, methEnv.Global.Int32Ref))
                                { Target = thenbb.Target, Fallthrough = thenbb.Fallthrough };
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format
                        ("short-circuited (normal, normal) and/or control flow from B{0}", branchbb.Id);
                }
            }

            {
                // Short-circuited and/or control flow, flipped first
                var group = new Set<BasicBlock> { branchbb };
                var elsebb = branchbb.Fallthrough as BranchBasicBlock;
                if (elsebb != null && branchbb.Target.Equals(elsebb.Fallthrough) && elsebb.Sources.Count == 1 &&
                    group.Add(elsebb) && !group.Contains(elsebb.Target) && !group.Contains(branchbb.Target))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var instructions2 = elsebb.Block.CopyContents();
                    var afterState2 = elsebb.Test.Eval
                        (instructions2, elsebb.Block.AfterState, elsebb.Target.Block.BeforeState, BottomPT);
                    var right = new Instructions(elsebb.Block.BeforeState, instructions2);
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, ShortCircuitingOp.And, right)
                              { BeforeState = beforeState, AfterState = afterState2 };
                    instructions.Add(sci);
                    var newbb = new BranchBasicBlock
                        (nextBlockId++,
                         new Instructions(beforeState, instructions),
                         new Test(TestOp.True, false, methEnv.Global.Int32Ref))
                                { Target = elsebb.Target, Fallthrough = branchbb.Target };
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format
                        ("short-circuited  (flipped, normal) and/or control flow from B{0}", branchbb.Id);
                }
            }

            {
                // Short-circuited and/or control flow, flipped second
                var group = new Set<BasicBlock> { branchbb };
                var thenbb = branchbb.Target as BranchBasicBlock;
                if (thenbb != null && branchbb.Fallthrough.Equals(thenbb.Target) && thenbb.Sources.Count == 1 &&
                    group.Add(thenbb) && !group.Contains(thenbb.Fallthrough) && !group.Contains(branchbb.Fallthrough))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var instructions2 = thenbb.Block.CopyContents();
                    var afterState2 = thenbb.Test.Negate().Eval
                        (instructions2, thenbb.Block.AfterState, thenbb.Fallthrough.Block.BeforeState, BottomPT);
                    var right = new Instructions(thenbb.Block.BeforeState, instructions2);
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, ShortCircuitingOp.And, right)
                              { BeforeState = beforeState, AfterState = afterState2 };
                    instructions.Add(sci);
                    var newbb = new BranchBasicBlock
                        (nextBlockId++,
                         new Instructions(beforeState, instructions),
                         new Test(TestOp.True, false, methEnv.Global.Int32Ref))
                                { Target = thenbb.Fallthrough, Fallthrough = branchbb.Fallthrough };
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format
                        ("short-circuited  (normal, flipped) and/or control flow from B{0}", branchbb.Id);
                }
            }

            {
                // Short-circuited and/or control flow, flipped first and second
                var group = new Set<BasicBlock> { branchbb };
                var elsebb = branchbb.Fallthrough as BranchBasicBlock;
                if (elsebb != null && branchbb.Target.Equals(elsebb.Target) && elsebb.Sources.Count == 1 &&
                    group.Add(elsebb) && !group.Contains(elsebb.Fallthrough) && !group.Contains(branchbb.Target))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                    var left = SeparateCondition(beforeState, ref instructions);
                    var instructions2 = elsebb.Block.CopyContents();
                    var afterState2 = elsebb.Test.Negate().Eval
                        (instructions2, elsebb.Block.AfterState, elsebb.Fallthrough.Block.BeforeState, BottomPT);
                    var right = new Instructions(elsebb.Block.BeforeState, instructions2);
                    var sci = new ShortCircuitingInstruction(NextInstructionId--, left, ShortCircuitingOp.And, right)
                              { BeforeState = beforeState, AfterState = afterState2 };
                    instructions.Add(sci);
                    var newbb = new BranchBasicBlock
                        (nextBlockId++,
                         new Instructions(beforeState, instructions),
                         new Test(TestOp.True, false, methEnv.Global.Int32Ref))
                                { Target = elsebb.Fallthrough, Fallthrough = branchbb.Target };
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format
                        ("short-circuited  (flipped, flipped) and/or control flow from B{0}", branchbb.Id);
                }
            }

            {
                // If-then-else, neither side returns
                var thenbb = branchbb.Target as NonReturningBasicBlock;
                var elsebb = branchbb.Fallthrough as NonReturningBasicBlock;
                if (thenbb != null && elsebb != null && !branchbb.Equals(thenbb) && !branchbb.Equals(elsebb) &&
                    !thenbb.Equals(elsebb) && branchbb.Target.Sources.Count == 1 &&
                    branchbb.Fallthrough.Sources.Count == 1)
                {
                    var instructions = branchbb.Block.CopyContents();
                    if (thenbb.Block.Size <= elsebb.Block.Size)
                    {
                        branchbb.Test.Eval
                            (instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                        var cond = SeparateCondition(beforeState, ref instructions);
                        var itei = new IfThenElseInstruction(NextInstructionId--, cond, thenbb.Block, null)
                                   { BeforeState = beforeState, AfterState = thenbb.Block.AfterState };
                        instructions.Add(itei);
                        var newbb = new JumpBasicBlock
                            (nextBlockId++, new Instructions(beforeState, instructions), elsebb);
                        root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, thenbb }, newbb);
                        return String.Format("if-then-else, no return, then smaller, from B{0}", branchbb.Id);
                    }
                    else
                    {
                        branchbb.Test.Negate().Eval
                            (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                        var cond = SeparateCondition(beforeState, ref instructions);
                        var itei = new IfThenElseInstruction(NextInstructionId--, cond, elsebb.Block, null)
                                   { BeforeState = beforeState, AfterState = elsebb.Block.AfterState };
                        instructions.Add(itei);
                        var newbb = new JumpBasicBlock
                            (nextBlockId++, new Instructions(beforeState, instructions), thenbb);
                        root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, elsebb }, newbb);
                        return String.Format("if-then-else, no return, else smaller, from B{0}", branchbb.Id);
                    }
                }
            }

            {
                // If-then, no-return
                var thenbb = branchbb.Target as NonReturningBasicBlock;
                if (thenbb != null && thenbb.Sources.Count == 1)
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval(instructions, afterState, thenbb.Block.BeforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var itei = new IfThenElseInstruction(NextInstructionId--, cond, thenbb.Block, null)
                               { BeforeState = beforeState, AfterState = thenbb.Block.AfterState };
                    instructions.Add(itei);
                    var newbb = new JumpBasicBlock
                        (nextBlockId++, new Instructions(beforeState, instructions), branchbb.Fallthrough);
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, thenbb }, newbb);
                    return String.Format("if-then, no return, from B{0}", branchbb.Id);
                }
            }

            {
                // Flipped if-then, no-return
                var elsebb = branchbb.Fallthrough as NonReturningBasicBlock;
                if (elsebb != null && elsebb.Sources.Count == 1)
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Negate().Eval
                        (instructions, afterState, elsebb.Block.BeforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var itei = new IfThenElseInstruction(NextInstructionId--, cond, elsebb.Block, null)
                               { BeforeState = beforeState, AfterState = elsebb.Block.AfterState };
                    instructions.Add(itei);
                    var newbb = new JumpBasicBlock
                        (nextBlockId++, new Instructions(beforeState, instructions), branchbb.Target);
                    root.Coalesce(branchbb, new Set<BasicBlock> { branchbb, elsebb }, newbb);
                    return String.Format("if-then (flipped), no return, from B{0}", branchbb.Id);
                }
            }

            {
                // If-then-else
                var group = new Set<BasicBlock> { branchbb };
                if (group.Add(branchbb.Target) && group.Add(branchbb.Fallthrough) &&
                    branchbb.Target.Sources.Count == 1 && branchbb.Fallthrough.Sources.Count == 1 &&
                    branchbb.Target.HasSameExit(branchbb.Fallthrough))
                {
                    var instructions = branchbb.Block.CopyContents();
                    branchbb.Test.Eval
                        (instructions, afterState, branchbb.Target.Block.BeforeState, BottomPT);
                    var cond = SeparateCondition(beforeState, ref instructions);
                    var itei = new IfThenElseInstruction
                        (NextInstructionId--, cond, branchbb.Target.Block, branchbb.Fallthrough.Block)
                               {
                                   BeforeState = beforeState,
                                   AfterState = branchbb.Target.Block.AfterState
                               };
                    instructions.Add(itei);
                    var newbb = branchbb.Fallthrough.CloneWithInstructions
                        (nextBlockId++, new Instructions(beforeState, instructions));
                    root.Coalesce(branchbb, group, newbb);
                    return String.Format("if-then-else from B{0}", branchbb.Id);
                }
            }

            return null;
        }
Exemplo n.º 3
0
 private void BreakReduceLeaveCatch(BasicBlock root, BBLoop loop, BasicBlock breakTarget, LeaveCatchBasicBlock leavebb, Seq<BasicBlock> removed, Seq<BasicBlock> added)
 {
     if (leavebb.Target.Equals(breakTarget))
     {
         var instructions = leavebb.Block.CopyContents();
         var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Break, loop.Label)
                       { BeforeState = leavebb.Block.AfterState, AfterState = leavebb.Block.AfterState };
         instructions.Add(lci);
         var newbb = new NonReturningBasicBlock(nextBlockId++, new Instructions(leavebb.Block.BeforeState, instructions));
         root.Coalesce(leavebb, new Set<BasicBlock> { leavebb }, newbb);
         removed.Add(leavebb);
         added.Add(newbb);
     }
 }
Exemplo n.º 4
0
        private string TryDuplicate(BasicBlock root, JumpBasicBlock jumpbb)
        {
            if (jumpbb.Target.Sources.Count > 1 && !jumpbb.Target.Equals(jumpbb) &&
                IsDuplicatableBasicBlock(jumpbb.Target))
            {
                // Inline and peephole
                var instructions = new Seq<Instruction>();
                // var block = new InstructionBlock(jumpbb.Block.BeforeState);
                jumpbb.Block.AccumClonedInstructions(instructions, ref NextInstructionId);
                jumpbb.Target.Block.AccumClonedInstructions(instructions, ref NextInstructionId);
                var newbb = jumpbb.Target.CloneWithInstructions
                    (nextBlockId++, Peephole(jumpbb.Block.BeforeState, instructions));
                jumpbb.Target.Sources.Remove(jumpbb);
                root.Coalesce(jumpbb, new Set<BasicBlock> { jumpbb }, newbb);
                return String.Format("inlined block B{0} into B{1}", jumpbb.Target.Id, jumpbb.Id);
            }

            return null;
        }
Exemplo n.º 5
0
        private string ContinueReduceBranch(BasicBlock root, BBLoop loop, BranchBasicBlock branchbb)
        {
            var beforeState = branchbb.Block.BeforeState;
            var afterState = branchbb.Block.AfterState;
            if (branchbb.Target.Equals(loop.ContinueTarget) && !branchbb.Fallthrough.Equals(loop.ContinueTarget) &&
                loop.ContinueTarget.Sources.Count > 1)
            {
                var instructions = branchbb.Block.CopyContents();
                branchbb.Test.Eval
                    (instructions, afterState, branchbb.Target.Block.BeforeState, BottomPT);
                var cond = SeparateCondition(beforeState, ref instructions);
                var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Continue, loop.Label)
                          { BeforeState = afterState, AfterState = afterState };
                var ifei = new IfThenElseInstruction(-1, cond, new Instructions(lci), null)
                           { BeforeState = beforeState, AfterState = afterState };
                instructions.Add(ifei);
                var newbb = new JumpBasicBlock
                    (nextBlockId++, new Instructions(beforeState, instructions), branchbb.Fallthrough);
                root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
                return String.Format("continue from branch at B{0} within loop from B{1}", branchbb.Id, loop.Head.Id);
            }

            if (branchbb.Fallthrough.Equals(loop.ContinueTarget) && !branchbb.Target.Equals(loop.ContinueTarget) &&
                loop.ContinueTarget.Sources.Count > 1)
            {
                var instructions = branchbb.Block.CopyContents();
                branchbb.Test.Negate().Eval
                    (instructions, afterState, branchbb.Fallthrough.Block.BeforeState, BottomPT);
                var cond = SeparateCondition(beforeState, ref instructions);
                var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Continue, loop.Label)
                              { BeforeState = afterState, AfterState = afterState };
                var ifei = new IfThenElseInstruction(NextInstructionId--, cond, new Instructions(lci), null)
                               { BeforeState = beforeState, AfterState = afterState };
                instructions.Add(ifei);
                var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(beforeState, instructions), branchbb.Target);
                root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
                return String.Format
                    ("continue from branch (flipped) at B{0} within loop from B{1}", branchbb.Id, loop.Head.Id);
            }

            return null;
        }
Exemplo n.º 6
0
 private void BreakReduceBranch(BasicBlock root, BBLoop loop, BasicBlock breakTarget, BranchBasicBlock branchbb, Seq<BasicBlock> removed, Seq<BasicBlock> added)
 {
     var beforeState = branchbb.Block.BeforeState;
     var afterState = branchbb.Block.AfterState;
     if (branchbb.Target.Equals(breakTarget) && !branchbb.Fallthrough.Equals(breakTarget))
     {
         var instructions = branchbb.Block.CopyContents();
         branchbb.Test.Eval(instructions, afterState, branchbb.Target.Block.BeforeState, BottomPT);
         var cond = SeparateCondition(beforeState, ref instructions);
         var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Break, loop.Label)
                       { BeforeState = afterState, AfterState = afterState };
         var itei = new IfThenElseInstruction(NextInstructionId--, cond, new Instructions(lci), null)
                        { BeforeState = beforeState, AfterState = afterState };
         instructions.Add(itei);
         var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(beforeState, instructions), branchbb.Fallthrough);
         root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
         removed.Add(branchbb);
         added.Add(newbb);
     }
     else if (branchbb.Fallthrough.Equals(breakTarget) && !branchbb.Target.Equals(breakTarget))
     {
         var instructions = branchbb.Block.CopyContents();
         branchbb.Test.Negate().Eval
             (instructions, afterState, branchbb.Fallthrough.Block.BeforeState, BottomPT);
         var cond = SeparateCondition(beforeState, ref instructions);
         var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Break, loop.Label)
                       { BeforeState = afterState, AfterState = afterState };
         var itei = new IfThenElseInstruction(NextInstructionId--, cond, new Instructions(lci), null)
                        { BeforeState = beforeState, AfterState = afterState };
         instructions.Add(itei);
         var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(beforeState, instructions), branchbb.Target);
         root.Coalesce(branchbb, new Set<BasicBlock> { branchbb }, newbb);
         removed.Add(branchbb);
         added.Add(newbb);
     }
 }
Exemplo n.º 7
0
        private string ContinueReduceLeaveTry(BasicBlock root, BBLoop loop, LeaveTryBasicBlock leavebb)
        {
            if (leavebb.Target.Equals(loop.ContinueTarget) && leavebb.HandlerPopCount == 1)
            {
                var instructions = leavebb.Block.CopyContents();
                var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Continue, loop.Label)
                              { BeforeState = leavebb.Block.AfterState, AfterState = leavebb.Block.AfterState };
                instructions.Add(lci);
                var newbb = new NonReturningBasicBlock(nextBlockId++, new Instructions(leavebb.Block.BeforeState, instructions));
                root.Coalesce(leavebb, new Set<BasicBlock> { leavebb }, newbb);
                return String.Format
                    ("continue from leave try at B{0} within loop from B{1}", leavebb.Id, loop.Head.Id);
            }

            return null;
        }
Exemplo n.º 8
0
        private string ContinueReduceJump(BasicBlock root, BBLoop loop, JumpBasicBlock jumpbb)
        {
            if (jumpbb.Target.Equals(loop.ContinueTarget) && jumpbb.Block.AfterState.Depth == 0 &&
                loop.ContinueTarget.Sources.Count > 1)
            {
                var instructions = jumpbb.Block.CopyContents();
                var lci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Continue, loop.Label)
                          { BeforeState = jumpbb.Block.AfterState, AfterState = jumpbb.Block.AfterState };
                instructions.Add(lci);
                var newbb = new NonReturningBasicBlock
                    (nextBlockId++, new Instructions(jumpbb.Block.BeforeState, instructions));
                root.Coalesce(jumpbb, new Set<BasicBlock> { jumpbb }, newbb);
                return String.Format("continue from jump at B{0} within loop from B{1}", jumpbb.Id, loop.Head.Id);
            }

            return null;
        }
Exemplo n.º 9
0
        private string TryReduceLoopCandidate(BasicBlock root, LoopCandidateBasicBlock loopbb)
        {
            var headbb = loopbb.Head;
            var jumpheadbb = headbb as JumpBasicBlock;
            var nonretheadbb = headbb as NonReturningBasicBlock;
            var group = new Set<BasicBlock> { loopbb };
            if ((jumpheadbb != null && jumpheadbb.Target.Equals(loopbb.Break) || nonretheadbb != null) &&
                group.Add(headbb) && !group.Contains(loopbb.Break))
            {
                var newbb = new JumpBasicBlock(nextBlockId++, headbb.Block, loopbb.Break);
                root.Coalesce(loopbb, group, newbb);
                return String.Format("loop with break from B{0}", loopbb.Id);
            }

            return null;
        }
Exemplo n.º 10
0
        private string TryReduceTry(BasicBlock root, TryBasicBlock trybb)
        {
            var group = new Set<BasicBlock> { trybb };
            var leavetrybb = trybb.Body as LeaveTryBasicBlock;
            if (leavetrybb == null || leavetrybb.HandlerPopCount != 1)
                return null;
            group.Add(leavetrybb);

            var handlers = new Seq<TryInstructionHandler>();
            foreach (var tbbHandler in trybb.Handlers)
            {
                var catchh = tbbHandler as TBBCatchHandler;
                if (catchh != null)
                {
                    if (!(catchh.Body is NonReturningBasicBlock))
                    {
                        // If body is not already free of control flow, check if it can be made to fall
                        // through to after try
                        var leavecatchbb = catchh.Body as LeaveCatchBasicBlock;
                        if (leavecatchbb == null || leavecatchbb.HandlerPopCount != 1 ||
                            !leavecatchbb.Target.Equals(leavetrybb.Target))
                            return null;
                        if (!group.Add(leavecatchbb))
                            // Should never happen
                            return null;
                    }
                    // else: catch ends with a return, throw, rethrow, break or continue
                    // Catch body WILL NOT end with leave
                    handlers.Add(new CatchTryInstructionHandler(catchh.Type, catchh.Body.Block));
                }
                else
                {
                    var faulth = tbbHandler as TBBFaultHandler;
                    if (faulth != null)
                    {
                        // Body must be an end fault
                        var endfaultbb = faulth.Body as EndFaultBasicBlock;
                        if (endfaultbb == null)
                            return null;
                        if (!group.Add(endfaultbb))
                            // Should never happen
                            return null;
                        // Fault handler body WILL NOT end with endfinally/endfault
                        handlers.Add(new FaultTryInstructionHandler(endfaultbb.Block));
                    }
                    else
                    {
                        var finallyh = tbbHandler as TBBFinallyHandler;
                        if (finallyh != null)
                        {
                            // Body must be an end finally
                            var endfinallybb = finallyh.Body as EndFinallyBasicBlock;
                            if (endfinallybb == null)
                                return null;
                            if (!group.Add(endfinallybb))
                                // Should never happen
                                return null;
                            // Finally handler body WILL NOT end with endfinally/endfault
                            handlers.Add(new FinallyTryInstructionHandler(endfinallybb.Block));
                        }
                        else
                            throw new InvalidOperationException("unrecognized handler");
                    }
                }
            }

            // Try body WILL NOT end with leave
            var tryi = new TryInstruction(NextInstructionId--, leavetrybb.Block, handlers)
                       { BeforeState = trybb.Block.BeforeState, AfterState = leavetrybb.Block.AfterState };
            var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(tryi), leavetrybb.Target);
            root.Coalesce(trybb, group, newbb);
            return String.Format("structural try/catch/finally/fault from B{0}", trybb.Id);
        }
Exemplo n.º 11
0
        private string TryReduceSwitch(BasicBlock root, SwitchBasicBlock switchbb)
        {
            // Build a map from basic blocks to the cases which enter it.
            // Also collect some simple stats.
            var caseMap = new Map<BasicBlock, Set<int>> { { switchbb.Fallthrough, new Set<int> { -1 } } };
            var allNonReturning = switchbb.Fallthrough is NonReturningBasicBlock;
            var allHaveOneSource = switchbb.Fallthrough.Sources.Count == 1;
            var jumpTargets = new Set<BasicBlock>();
            var jumpbb = switchbb.Fallthrough as JumpBasicBlock;
            if (jumpbb != null)
                jumpTargets.Add(jumpbb.Target);
            for (var i = 0; i < switchbb.CaseTargets.Count; i++)
            {
                var t = switchbb.CaseTargets[i];
                if (!(t is NonReturningBasicBlock))
                    allNonReturning = false;
                if (t.Sources.Count != 1)
                    allHaveOneSource = false;
                jumpbb = t as JumpBasicBlock;
                if (jumpbb != null)
                    jumpTargets.Add(jumpbb.Target);
                var values = default(Set<int>);
                if (caseMap.TryGetValue(t, out values))
                    // Block is shared amongst switch cases
                    values.Add(i);
                else
                    caseMap.Add(t, new Set<int> { i });
            }

            if (caseMap.Count == 1)
            {
                // CASE 1: all switch cases go to the same block, so replace the switch with a pop and jump
                var instructions = switchbb.Block.CopyContents();
                instructions.Add
                    (new MiscInstruction(NextInstructionId--, MiscOp.Pop)
                     { BeforeState = switchbb.Block.BeforeState, AfterState = switchbb.Fallthrough.Block.BeforeState });
                var newbb = new JumpBasicBlock
                    (nextBlockId++, Peephole(switchbb.Block.BeforeState, instructions), switchbb.Fallthrough);
                root.Coalesce(switchbb, new Set<BasicBlock> { switchbb }, newbb);
                return string.Format("removed switch at B{0}", switchbb.Id);
            }

            if (allNonReturning && allHaveOneSource)
            {
                // CASE 2: all switch cases are non-returning and have one source, so move them all into
                //         a non-returing block with switch
                var group = new Set<BasicBlock> { switchbb };
                var cases = new Seq<StructuralCase>();
                foreach (var kv in caseMap)
                {
                    cases.Add(new StructuralCase(kv.Value, kv.Key.Block));
                    group.Add(kv.Key);
                }
                var ssi = new StructuralSwitchInstruction(NextInstructionId--, switchbb.Block, cases)
                              {
                                  BeforeState = switchbb.Block.BeforeState,
                                  AfterState = switchbb.Fallthrough.Block.AfterState
                              };
                var newbb = new NonReturningBasicBlock(nextBlockId++, new Instructions(ssi));
                root.Coalesce(switchbb, group, newbb);
                return String.Format("non-returning structural switch from B{0}", switchbb.Id);
            }

            if (jumpTargets.Count == 1)
            {
                var theJumpTarget = jumpTargets[0];
                var allIntermediateAreNonReturningOrJumpToTarget = true;
                foreach (var kv in caseMap)
                {
                    if (!kv.Key.Equals(theJumpTarget))
                    {
                        if (kv.Key.Sources.Count > 1 ||
                            !(kv.Key is NonReturningBasicBlock || kv.Key is JumpBasicBlock))
                            allIntermediateAreNonReturningOrJumpToTarget = false;
                    }
                }
                if (allIntermediateAreNonReturningOrJumpToTarget)
                {
                    // CASE 3: all switch cases either jump directly to the switch successor or go via jump block,
                    //         or don't return. Inline all the cases and place the switch in a jump to target block
                    var group = new Set<BasicBlock> { switchbb };
                    var cases = new Seq<StructuralCase>();
                    var afterState = default(MachineState);
                    foreach (var kv in caseMap)
                    {
                        var block = default(Instructions);
                        if (kv.Key.Equals(theJumpTarget))
                        {
                            var bci = new BreakContinueInstruction(NextInstructionId--, BreakContinueOp.Break, null)
                                          {
                                              BeforeState = theJumpTarget.Block.BeforeState,
                                              AfterState = theJumpTarget.Block.BeforeState
                                          };
                            // Fallthrough to final jump target
                            block = new Instructions(bci);
                        }
                        else
                        {
                            // Inline case block, and if not non-returning then fallthrough to final jump target
                            var instructions = kv.Key.Block.CopyContents();
                            if (!kv.Key.Block.NeverReturns)
                            {
                                var bci = new BreakContinueInstruction
                                    (NextInstructionId--, BreakContinueOp.Break, null)
                                          {
                                              BeforeState = kv.Key.Block.AfterState,
                                              AfterState = kv.Key.Block.AfterState
                                          };
                                instructions.Add(bci);
                            }
                            group.Add(kv.Key);
                            block = new Instructions(kv.Key.Block.BeforeState, instructions);
                        }
                        if (afterState == null)
                            afterState = block.AfterState;
                        cases.Add(new StructuralCase(kv.Value, block));
                    }
                    var ssi = new StructuralSwitchInstruction(NextInstructionId--, switchbb.Block, cases)
                                  {
                                      BeforeState = switchbb.Block.BeforeState,
                                      AfterState = afterState
                                  };
                    var newbb = new JumpBasicBlock(nextBlockId++, new Instructions(ssi), theJumpTarget);
                    root.Coalesce(switchbb, group, newbb);
                    return String.Format("structural switch from B{0}", switchbb.Id);
                }
            }

            return null;
        }