def dominator_tree(start_node = self.enter)
      doms = {start_node => start_node}
      changed = true
      reverse_postorder = compute_post_order(self, start_node)
      while changed
        changed = false
        reverse_postorder.each do |b|
          if (original = b.each_real_predecessors.find { |node| doms[node] })
            new_idom = original
            b.each_real_predecessors do |p|
              if doms[p] && p != original
                new_idom = dominator_set_intersect(p, new_idom, doms)
              end
            end
            if doms[b] != new_idom
              doms[b] = new_idom
              changed = true
            end
          end
        end
      end

      # doms is IDOM. All outward edges connect an IDom to its dominee.
      d_tree = self.class.new
      (vertices - [enter, exit]).each do |b|
        copy = Laser::Analysis::ControlFlow::BasicBlock.new(b.name)
        copy.instructions = b.instructions
        d_tree.add_vertex(copy)
      end
      doms.each { |src, dest| d_tree.add_edge(d_tree[src], d_tree[dest]) unless src == enter && dest == enter }
      d_tree
    end
def dominator_tree(start_node = self.enter)
      doms = {start_node => start_node}
      changed = true
      reverse_postorder = compute_post_order(self, start_node)
      while changed
        changed = false
        reverse_postorder.each do |b|
          if (original = b.each_real_predecessors.find { |node| doms[node] })
            new_idom = original
            b.each_real_predecessors do |p|
              if doms[p] && p != original
                new_idom = dominator_set_intersect(p, new_idom, doms)
              end
            end
            if doms[b] != new_idom
              doms[b] = new_idom
              changed = true
            end
          end
        end
      end

      # doms is IDOM. All outward edges connect an IDom to its dominee.
      d_tree = self.class.new
      (vertices - [enter, exit]).each do |b|
        copy = Laser::Analysis::ControlFlow::BasicBlock.new(b.name)
        copy.instructions = b.instructions
        d_tree.add_vertex(copy)
      end
      doms.each { |src, dest| d_tree.add_edge(d_tree[src], d_tree[dest]) unless src == enter && dest == enter }
      d_tree
    end
Returns the dominator tree of the graph. O(V^2), but performs better than
 or close to Lengauer-Tarjan on real-world ASTs.

 If the start node is not provided, it is assumed the receiver is a
 ControlFlowGraph and has an #enter method.