Hydrogen-python/Optimizer/Optimizer.py
2025-06-19 09:42:46 +08:00

199 lines
6.1 KiB
Python

# 优化模块
# 第一步: 常量传播
def constant_propagation(quads):
#print("Running Constant Propagation")
value_map = {}
optimized = []
for quad in quads:
op, arg1, arg2, dest = quad
if op == '=' and arg1.isdigit():
# 常量赋值:如 (=, 32, _, _v0)
value_map[dest] = arg1
elif op == '=':
# 变量赋值:如 (=, _v0, _, age)
if arg1 in value_map:
new_quad = ('=', value_map[arg1], '_', dest)
optimized.append(new_quad)
value_map[dest] = value_map[arg1]
else:
optimized.append(quad)
# 如果 dest 不再被使用,可以考虑删除该赋值
else:
# 替换操作数中的变量为已知常量
new_arg1 = value_map.get(arg1, arg1)
new_arg2 = value_map.get(arg2, arg2) if arg2 != '_' else '_'
optimized.append((op, new_arg1, new_arg2, dest))
return optimized
# 第二步: 公共子表达式消除
def common_subexpression_elimination(quads):
#print("Running Common Subexpression Elimination")
expr_map = {}
optimized = []
temp_counter = 0
for quad in quads:
op, arg1, arg2, dest = quad
if op in ['+', '-', '*', '/']:
expr_key = f"{arg1} {op} {arg2}"
if expr_key in expr_map:
# 复用已有结果
reused_var = expr_map[expr_key]
optimized.append(('=', reused_var, '_', dest))
else:
# 新表达式
temp_var = f"_t{temp_counter}"
temp_counter += 1
expr_map[expr_key] = temp_var
optimized.append((op, arg1, arg2, temp_var))
optimized.append(('=', temp_var, '_', dest))
else:
optimized.append(quad)
return optimized
# 第三步: 死代码消除
def dead_code_elimination(quads):
#print("Running Dead Code Elimination")
used_vars = set()
optimized = []
# 第一遍找出所有被使用的变量
for quad in quads:
op, arg1, arg2, dest = quad
if arg1 != '_' and not arg1.isdigit():
used_vars.add(arg1)
if arg2 != '_' and not arg2.isdigit():
used_vars.add(arg2)
# 第二遍删除未使用变量的赋值语句
for quad in quads:
op, arg1, arg2, dest = quad
if op == '=' and dest.startswith('_v') and dest not in used_vars:
continue # 跳过无用的赋值语句
optimized.append(quad)
return optimized
# 第四步: 控制流优化
def control_flow_simplification(quads):
# print("Running Control Flow Simplification")
optimized = []
for quad in quads:
op, arg1, arg2, dest = quad
if op == 'if' and arg2 == 'goto':
if arg1.isdigit():
if arg1 == '1':
optimized.append(('goto', '_', '_', dest))
elif arg1 == '0':
continue # 恒假,跳过该条件跳转
else:
optimized.append(quad)
else:
optimized.append(quad)
return optimized
# 第五步: 寄存器重用
def register_reuse(quads):
#print("Running Register Reuse (Improved)")
# 计算活跃变量信息
live_info = compute_live_vars(quads)
optimized = []
available_temps = [] # 可用于复用的临时变量池
for i, quad in enumerate(quads):
op, arg1, arg2, dest = quad
current_live = live_info[i]
if op == '=':
# 查看当前 dest 是否会被后续使用
is_dest_used_later = dest in current_live
# 如果 dest 不再使用,可以加入可用池
if not is_dest_used_later and dest.startswith('_'):
available_temps.append(dest)
# 尝试复用已死的临时变量
reused = False
for var in list(available_temps):
if var not in [arg1, arg2] and var not in current_live:
# 安全复用
optimized.append(('=', arg1, arg2, var))
available_temps.remove(var)
if var != dest:
available_temps.append(dest) # 原 dest 现在可回收
reused = True
break
if not reused:
optimized.append(quad)
if dest.startswith('_') and dest not in current_live:
available_temps.append(dest)
else:
optimized.append(quad)
return optimized
def compute_live_vars(quads):
"""
活跃变量分析:从后往前推导每个 quad 之后仍会使用的变量
"""
live_vars = set()
live_info = []
for quad in reversed(quads):
op, arg1, arg2, dest = quad
# 先移除 dest 的影响(因为 dest 被重新定义)
if dest in live_vars:
live_vars.remove(dest)
# 如果操作数是变量,则加入活跃集合
if arg1 != '_' and not arg1.isdigit():
live_vars.add(arg1)
if arg2 != '_' and not arg2.isdigit():
live_vars.add(arg2)
# 把当前活跃变量集合复制一份保存下来
live_info.append(live_vars.copy())
# 从后往前遍历,所以需要反转结果
live_info.reverse()
return live_info
# 优化器整合
def optimize(quads):
passes = [
("Constant Propagation", constant_propagation),
("Common Subexpression Elimination", common_subexpression_elimination),
("Dead Code Elimination", dead_code_elimination),
("Control Flow Simplification", control_flow_simplification),
("Register Reuse", register_reuse),
]
for name, opt_func in passes:
# print(f"Running optimization pass: {name}")
quads = opt_func(quads)
return quads
def output_ir_str(quads):
lines = []
for i, quad in enumerate(quads):
op, arg1, arg2, dest = quad
quad = f"({op}, {arg1}, {arg2}, {dest})"
lines.append(f"{i} {quad}")
return "\n".join(lines)