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