private static int GetReconvergencePoint(ControlFlowGraph cfg, BranchingInstruction branchingInstruction)
		{
			// Find BasicBlock that contains the branching instruction.
			var sourceBasicBlock = cfg.BasicBlocks.Single(x => x.Instructions.Contains(branchingInstruction));

			// Get first instruction in the immediate post dominator block.
			var firstInstruction = sourceBasicBlock.ImmediatePostDominator.Instructions.First();

			// Return index of this instruction.
			return GetInstructionIndex(cfg.AllInstructions, firstInstruction);
		}
		public static ControlFlowGraph FromInstructions(IEnumerable<InstructionBase> instructions)
		{
			var instructionsList = instructions.ToList();
			var result = new ControlFlowGraph(instructionsList);

			// The following algorithm is from "Analyzing Control Flow in Java Bytecode" by Jianjun Zhao.
			// Determine the basic blocks by finding the set of leaders:
			// - The first instruction is a leader.
			// - Each instruction that is the target of an unconditional branch is a leader.
			// - Each instruction that is the target of a conditional branch is a leader.
			// - Each instruction that immediately follows a conditional or unconditional branch is a leader.
			// - TODO: switch statements.
			// Each leader gives rise to a basic block consisting of all instructions up to the next leader
			// or the end of the bytecode.

			var blockInstructions = new List<InstructionBase>();
			int position = 0;
			for (int i = 0; i < instructionsList.Count; i++)
			{
				if (IsLeader(instructionsList, i) && blockInstructions.Any())
				{
					result.BasicBlocks.Add(new BasicBlock(position++, blockInstructions));
					blockInstructions = new List<InstructionBase>();
				}
				blockInstructions.Add(instructionsList[i]);
			}
			result.BasicBlocks.Add(new BasicBlock(position, blockInstructions));

			// Now we can use the following rules to construct the CFG.
			// Given that u and v are basic blocks:
			// - Add an edge (u,v) if v follows u in the bytecode and u does not terminate in an unconditional branch.
			// - Add an edge (u,v) if the last instruction of u is a conditional or unconditional branch to the first
			//   instruction of v.
			// - TODO: switch statements.
			foreach (var u in result.BasicBlocks)
			{
				foreach (var v in result.BasicBlocks.Where(x => x != u))
				{
					if ((v.Position == u.Position + 1 && !u.Instructions.Last().IsUnconditionalBranch)
						|| u.Instructions.Last().BranchesTo(v.Instructions.First()))
						u.Successors.Add(v);
				}
			}

			result.ComputePostDominators();

			return result;
		}
		public static IEnumerable<ExecutableInstruction> Rewrite(ControlFlowGraph controlFlowGraph)
		{
			foreach (var explicitBranchingInstruction in controlFlowGraph.AllInstructions)
			{
				int thisPC = GetInstructionIndex(controlFlowGraph.AllInstructions, explicitBranchingInstruction);

				if (explicitBranchingInstruction is BranchingInstruction && !explicitBranchingInstruction.IsUnconditionalBranch)
				{
					var branchingInstruction = (BranchingInstruction) explicitBranchingInstruction;
					yield return new DivergentExecutableInstruction(explicitBranchingInstruction.InstructionToken, branchingInstruction.BranchIfPositive)
					{
						ReconvergencePC = GetReconvergencePoint(controlFlowGraph, branchingInstruction),
						NextPCs = new List<int>
						{
							GetInstructionIndex(controlFlowGraph.AllInstructions, ((BranchingInstruction) explicitBranchingInstruction).BranchTarget),
							thisPC + 1
						},

						OpcodeType = ExecutableOpcodeType.BranchC
					};
				}
				else
				{
					ExecutableOpcodeType opcodeType;
					int nextPC;
					if (explicitBranchingInstruction.IsUnconditionalBranch)
					{
						opcodeType = ExecutableOpcodeType.Branch;
						nextPC = GetInstructionIndex(controlFlowGraph.AllInstructions, ((BranchingInstruction) explicitBranchingInstruction).BranchTarget);
					}
					else
					{
						opcodeType = MapOpcodeType(explicitBranchingInstruction.InstructionToken.Header.OpcodeType);
						nextPC = thisPC + 1;
					}

					yield return new NonDivergentExecutableInstruction(explicitBranchingInstruction.InstructionToken)
					{
						NextPC = nextPC,
						OpcodeType = opcodeType,
					};
				}
			}
		}
		public void CanComputePostDominators()
		{
			// Arrange.
			// A
			// |\
			// | \
			// B  C
			// |   \
			// |    \
			// D__>__E
			// |    /
			// |   /
			// |  /
			// | /
			// |/
			// F
			var blockA = new BasicBlock(0, null);
			var blockB = new BasicBlock(1, null);
			var blockC = new BasicBlock(2, null);
			var blockD = new BasicBlock(3, null);
			var blockE = new BasicBlock(4, null);
			var blockF = new BasicBlock(5, null);
			blockA.Successors.AddRange(new[] { blockB, blockC });
			blockB.Successors.AddRange(new[] { blockD });
			blockC.Successors.AddRange(new[] { blockE });
			blockD.Successors.AddRange(new[] { blockE, blockF });
			blockE.Successors.AddRange(new[] { blockF });
			var controlFlowGraph = new ControlFlowGraph(null)
			{
				BasicBlocks = { blockA, blockB, blockC, blockD, blockE, blockF }
			};

			// Act.
			controlFlowGraph.ComputePostDominators();

			// Assert.
			Assert.That(blockA.ImmediatePostDominator, Is.EqualTo(blockF));
			Assert.That(blockB.ImmediatePostDominator, Is.EqualTo(blockD));
			Assert.That(blockC.ImmediatePostDominator, Is.EqualTo(blockE));
			Assert.That(blockD.ImmediatePostDominator, Is.EqualTo(blockF));
			Assert.That(blockE.ImmediatePostDominator, Is.EqualTo(blockF));
			Assert.That(blockF.ImmediatePostDominator, Is.Null);
		}