Add compiler improvement
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 36 KiB |
BIN
Project-02-03-04-05/images/getOptimized/after.png
Normal file
BIN
Project-02-03-04-05/images/getOptimized/after.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
BIN
Project-02-03-04-05/images/getOptimized/before.png
Normal file
BIN
Project-02-03-04-05/images/getOptimized/before.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
@@ -17,6 +17,7 @@ from cfa.to_dot import analysis_to_dot
|
|||||||
from cfg.CFG import CFG
|
from cfg.CFG import CFG
|
||||||
from vistram.tram import *
|
from vistram.tram import *
|
||||||
from vistram.vistram import MachineUI
|
from vistram.vistram import MachineUI
|
||||||
|
from optimizations.optimize import optimize
|
||||||
|
|
||||||
matplotlib.use("TkAgg")
|
matplotlib.use("TkAgg")
|
||||||
|
|
||||||
@@ -129,6 +130,9 @@ if __name__ == "__main__":
|
|||||||
ast = yacc.parser.parse(source)
|
ast = yacc.parser.parse(source)
|
||||||
|
|
||||||
if mode == 0:
|
if mode == 0:
|
||||||
|
if cnsl.prompt_confirmation("\nOptimize AST?", default="y"):
|
||||||
|
ast = optimize(ast)
|
||||||
|
|
||||||
# Pretty print
|
# Pretty print
|
||||||
if cnsl.prompt_confirmation("\nPretty-print AST?"):
|
if cnsl.prompt_confirmation("\nPretty-print AST?"):
|
||||||
print("")
|
print("")
|
||||||
@@ -156,6 +160,9 @@ if __name__ == "__main__":
|
|||||||
print("Rendered AST diagram.")
|
print("Rendered AST diagram.")
|
||||||
|
|
||||||
elif mode == 1:
|
elif mode == 1:
|
||||||
|
if cnsl.prompt_confirmation("\nOptimize AST?", default="y"):
|
||||||
|
ast = optimize(ast)
|
||||||
|
|
||||||
tram_code = assemble(ast)
|
tram_code = assemble(ast)
|
||||||
|
|
||||||
# Print TRAM code
|
# Print TRAM code
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import cfg_build
|
||||||
|
from cfg.CFG import CFG
|
||||||
|
from cfg.CFG_Node import CFG_Node
|
||||||
|
from cfa.ReachedUses import ReachedUses
|
||||||
|
from syntax import EXPRESSION, ASSIGN
|
||||||
|
from optimizations.Optimization import Optimization
|
||||||
|
|
||||||
|
class DeadAssignmentElimination(Optimization):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._node_by_ast_id: dict[int, CFG_Node] = {}
|
||||||
|
self.__ru: ReachedUses | None = None
|
||||||
|
|
||||||
|
def setup(self, ast: EXPRESSION) -> None:
|
||||||
|
cfg_build.FUNCTIONS.clear()
|
||||||
|
cfg_build.CURRENT_FUNCTION = None
|
||||||
|
cfg = CFG(ast)
|
||||||
|
self.__ru = ReachedUses(cfg)
|
||||||
|
self._node_by_ast_id = {id(n.ast_node): n for n in self.__ru.cfg.nodes() if n.ast_node is not None}
|
||||||
|
|
||||||
|
def apply(self, node: EXPRESSION) -> EXPRESSION:
|
||||||
|
# Only ASSIGN nodes can be dead assignments.
|
||||||
|
if not isinstance(node, ASSIGN):
|
||||||
|
return node
|
||||||
|
|
||||||
|
# Find the CFG node corresponding to this AST node.
|
||||||
|
# If none is found, the node was not analyzed — leave it unchanged.
|
||||||
|
cfg_node = self._node_by_ast_id.get(id(node))
|
||||||
|
if cfg_node is None:
|
||||||
|
return node
|
||||||
|
|
||||||
|
ru = self.__ru
|
||||||
|
nid = cfg_node.id
|
||||||
|
defined_vars = ru.defs.get(nid, set())
|
||||||
|
out = ru.out_sets.get(nid, set())
|
||||||
|
|
||||||
|
# Check if any use-fact in OUT(n) belongs to a variable defined at n.
|
||||||
|
# If so, the assignment is live — at least one use is reachable from here.
|
||||||
|
for (_, var) in out:
|
||||||
|
if var in defined_vars:
|
||||||
|
return node
|
||||||
|
|
||||||
|
# No reached use found for the assigned variable — the assignment is dead.
|
||||||
|
# Replace ASSIGN(var, expr) with expr to preserve side effects on the RHS.
|
||||||
|
return node.expr
|
||||||
7
Project-02-03-04-05/optimizations/Optimization.py
Normal file
7
Project-02-03-04-05/optimizations/Optimization.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
from syntax import EXPRESSION
|
||||||
|
|
||||||
|
|
||||||
|
class Optimization:
|
||||||
|
def setup(self, ast: EXPRESSION) -> None: ...
|
||||||
|
def apply(self, node: EXPRESSION) -> EXPRESSION: ...
|
||||||
2
Project-02-03-04-05/optimizations/__init__.py
Normal file
2
Project-02-03-04-05/optimizations/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from optimizations.DeadAssignmentElimination import DeadAssignmentElimination
|
||||||
|
from optimizations.Optimization import Optimization
|
||||||
36
Project-02-03-04-05/optimizations/optimize.py
Normal file
36
Project-02-03-04-05/optimizations/optimize.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
from optimizations.Optimization import Optimization
|
||||||
|
from optimizations.DeadAssignmentElimination import DeadAssignmentElimination
|
||||||
|
from syntax import EXPRESSION
|
||||||
|
|
||||||
|
# Traverses the AST and applies the given optimizations
|
||||||
|
def __apply_optimizations(node: EXPRESSION, optimizations: list[Optimization]) -> EXPRESSION:
|
||||||
|
for key, value in list(node.__dict__.items()):
|
||||||
|
if key == "pp":
|
||||||
|
continue
|
||||||
|
if isinstance(value, EXPRESSION):
|
||||||
|
new_child = __apply_optimizations(value, optimizations)
|
||||||
|
if new_child is not value:
|
||||||
|
setattr(node, key, new_child)
|
||||||
|
elif isinstance(value, list):
|
||||||
|
for i, elem in enumerate(value):
|
||||||
|
if isinstance(elem, EXPRESSION):
|
||||||
|
new_elem = __apply_optimizations(elem, optimizations)
|
||||||
|
if new_elem is not elem:
|
||||||
|
value[i] = new_elem
|
||||||
|
|
||||||
|
result: EXPRESSION = node
|
||||||
|
for opt in optimizations:
|
||||||
|
result = opt.apply(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Stores the active optimizations
|
||||||
|
ACTIVE_OPTIMIZATIONS: list[Optimization] = [
|
||||||
|
DeadAssignmentElimination(),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Apply optimizations to the given AST node
|
||||||
|
def optimize(ast: EXPRESSION) -> EXPRESSION:
|
||||||
|
for opt in ACTIVE_OPTIMIZATIONS:
|
||||||
|
opt.setup(ast)
|
||||||
|
return __apply_optimizations(ast, ACTIVE_OPTIMIZATIONS)
|
||||||
9
Project-02-03-04-05/triplaprograms/getOptimized.tripla
Normal file
9
Project-02-03-04-05/triplaprograms/getOptimized.tripla
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
let f(x, y)
|
||||||
|
{
|
||||||
|
let g(x)
|
||||||
|
{
|
||||||
|
y = x + 7
|
||||||
|
}
|
||||||
|
in x = g(5); y
|
||||||
|
}
|
||||||
|
in f(1, 2)
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
let g(a) {
|
let g(a) {
|
||||||
a*a
|
a*a
|
||||||
} in g(5)
|
} in b = g(5)
|
||||||
Reference in New Issue
Block a user