Пример #1
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);
     }
 }
Пример #2
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);
     }
 }
Пример #3
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;
        }
Пример #4
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;
        }
Пример #5
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;
        }
Пример #6
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;
        }