Example: Control flow graph manipulation - Merging basic blocks

Now let's look at an example of control flow graph manipulation. Let's write a pass that will merge two basic blocks which are immediately adjacent where the first basic block has no other successors and the second basic block has no other predecessors. Obviously, we need to ignore the entry and exit basic blocks. Additionally, let's maintain exception semantics by requiring that the exception handler set is the same for both basic blocks.

Code goes here.

This one is a little more involved. When visiting a basic block, we look at the predecessors of the current basic block. By merging basic blocks with their predecessors rather than their successors, we can avoid having to re-compute the traversal order if we traverse forward through the graph.

We check that the basic block is not the exit node and that there is only one predecessor. Likewise, we check that the predecessor has only one successor and that the predecessor is not the entry node. Finally, we check the equality of the exception handlers. If all of these tests pass, the basic blocks are mergeable.

We check the last quad in the previous basic block; if it is a branch we remove it. We add all of the quads in the current basic block to the previous basic block, merge the flags of the two basic blocks, remove the successor edge between them, and add all successors of the second basic block to the first basic block. And the blocks are merged!

When should I use iterators versus visitors for IR elements?

These two techniques are interchangeable, but in some cases it is more convenient to use one rather than the other.

Visitors are good because they separate the traversal order from the operations performed on each element. Because they are objects, they can be passed around and be used to store results. They also allow advanced selection of objects based on their type, a la QuadVisitor.

However, visitors require a class definition and are therefore cumbersome for simple traversals. If a traversal is very simple and doesn't warrant a new class definition, it may be better to use an iterator.

<-- previous home