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); } }
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); } }
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; }
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; }
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; }
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; }