dominator.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. from copy import copy
  2. def generate_dominator_tree(nodes):
  3. """Add dominator administration to the given flow graph nodes."""
  4. # Dominator of the start node is the start itself
  5. nodes[0].dom = set([nodes[0]])
  6. # For all other nodes, set all nodes as the dominators
  7. for n in nodes[1:]:
  8. n.dom = set(copy(nodes))
  9. def pred(n, known=[]):
  10. """Recursively find all predecessors of a node."""
  11. direct = filter(lambda x: x not in known, n.edges_from)
  12. p = copy(direct)
  13. for ancestor in direct:
  14. p += pred(ancestor, direct)
  15. return p
  16. # Iteratively eliminate nodes that are not dominators
  17. changed = True
  18. while changed:
  19. changed = False
  20. for n in nodes[1:]:
  21. old_dom = n.dom
  22. intersection = lambda p1, p2: p1.dom & p2.dom
  23. n.dom = set([n]) | reduce(intersection, pred(n), set([]))
  24. if n.dom != old_dom:
  25. changed = True
  26. def idom(d, n):
  27. """Check if d immediately dominates n."""
  28. for b in n.dom:
  29. if b != d and b != n and b in n.dom:
  30. return False
  31. return True
  32. # Build tree using immediate dominators
  33. for n in nodes:
  34. for d in n.dom:
  35. if idom(d, n):
  36. d.set_dominates(n)
  37. break