artiq/artiq/compiler/analyses/domination.py
2015-11-01 09:49:39 +03:00

67 lines
2.2 KiB
Python

"""
:class:`DominatorTree` computes the dominance relation over
control flow graphs.
See http://www.cs.colostate.edu/~mstrout/CS553/slides/lecture04.pdf.
"""
from functools import reduce, cmp_to_key
# Key Idea
# If a node dominates all
# predecessors of node n, then it
# also dominates node n
class DominatorTree:
def __init__(self, func):
entry = func.entry()
self.dominated_by = { entry: {entry} }
for block in func.basic_blocks:
if block != entry:
self.dominated_by[block] = set(func.basic_blocks)
predecessors = {block: block.predecessors() for block in func.basic_blocks}
while True:
changed = False
for block in func.basic_blocks:
if block == entry:
continue
new_dominated_by = {block}.union(
reduce(lambda a, b: a.intersection(b),
(self.dominated_by[pred] for pred in predecessors[block])))
if new_dominated_by != self.dominated_by[block]:
self.dominated_by[block] = new_dominated_by
changed = True
if not changed:
break
class PostDominatorTree:
def __init__(self, func):
exits = [block for block in func.basic_blocks if none(block.successors())]
self.dominated_by = { exit: {exit} for exit in exits }
for block in func.basic_blocks:
if block != entry:
self.dominated_by[block] = set(func.basic_blocks)
successors = {block: block.successors() for block in func.basic_blocks}
while True:
changed = False
for block in func.basic_blocks:
if block in exits:
continue
new_dominated_by = {block}.union(
reduce(lambda a, b: a.intersection(b),
(self.dominated_by[pred] for pred in successors[block])))
if new_dominated_by != self.dominated_by[block]:
self.dominated_by[block] = new_dominated_by
changed = True
if not changed:
break