CAP/MiniC/TP05/EnterSSA.py

81 lines
2.6 KiB
Python
Raw Normal View History

2024-10-06 19:58:11 +02:00
"""
CAP, SSA Intro, Elimination and Optimisations
Functions to convert a CFG into SSA Form.
"""
from typing import List, Dict, Set
from Lib.CFG import Block, CFG
2024-11-18 13:55:36 +01:00
from Lib.Operands import Renamer, Operand
from Lib.Statement import Instruction, Label
2024-10-06 19:58:11 +02:00
from Lib.PhiNode import PhiNode
from Lib.Dominators import computeDom, computeDT, computeDF
def insertPhis(cfg: CFG, DF: Dict[Block, Set[Block]]) -> None:
"""
`insertPhis(CFG, DF)` inserts phi nodes in `cfg` where needed.
At this point, phi nodes will look like `temp_x = φ(temp_x, ..., temp_x)`.
This is an helper function called during SSA entry.
"""
for var, defs in cfg.gather_defs().items():
has_phi: Set[Block] = set()
queue: List[Block] = list(defs)
while queue:
d = queue.pop(0)
for b in DF[d]:
if b not in has_phi:
2024-11-18 13:55:36 +01:00
srcs: Dict[Label, Operand] = {
x.get_label(): var for x in b.get_in()
}
phi = PhiNode(var, srcs)
b.add_phi(phi)
queue.append(b)
has_phi.add(b)
2024-10-06 19:58:11 +02:00
def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Block) -> None:
"""
Rename variables from block b.
This is an auxiliary function for `rename_variables`.
"""
renamer = renamer.copy()
for i in b.get_all_statements():
if isinstance(i, Instruction | PhiNode):
i.rename(renamer)
for succ in cfg.out_blocks(b):
for i in succ.get_phis():
assert (isinstance(i, PhiNode))
i.rename_from(renamer, b.get_label())
2024-11-18 13:55:36 +01:00
for succ in DT[b]:
rename_block(cfg, DT, renamer, succ)
2024-10-06 19:58:11 +02:00
def rename_variables(cfg: CFG, DT: Dict[Block, Set[Block]]) -> None:
"""
Rename variables in the CFG, to transform `temp_x = φ(temp_x, ..., temp_x)`
into `temp_x = φ(temp_0, ... temp_n)`.
This is an helper function called during SSA entry.
"""
renamer = Renamer(cfg.fdata._pool)
2024-11-18 13:55:36 +01:00
for b in cfg.get_entries():
rename_block(cfg, DT, renamer, b)
2024-10-06 19:58:11 +02:00
def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None:
"""
Convert the CFG `cfg` into SSA Form:
compute the dominance frontier, then insert phi nodes and finally
rename variables accordingly.
`dom_graphs` indicates if we have to print the domination graphs.
`basename` is used for the names of the produced graphs.
"""
2024-11-18 13:55:36 +01:00
dom = computeDom(cfg)
DT = computeDT(cfg, dom, dom_graphs, basename)
DF = computeDF(cfg, dom, DT, dom_graphs, basename)
insertPhis(cfg, DF)
rename_variables(cfg, DT)