From 9d8e51013828490977ee25c6cb119cf24a09496e Mon Sep 17 00:00:00 2001 From: static Date: Sun, 1 Jun 2025 08:37:49 +0000 Subject: [PATCH] HW5 (1) --- src/opt/gvn.rs | 189 ++++++++++++++++++++++++++++++++++++++++++- src/opt/opt_utils.rs | 14 +++- 2 files changed, 199 insertions(+), 4 deletions(-) diff --git a/src/opt/gvn.rs b/src/opt/gvn.rs index bf95e4a..2c62dec 100644 --- a/src/opt/gvn.rs +++ b/src/opt/gvn.rs @@ -1,5 +1,6 @@ use core::ops::Deref; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; +use std::ops::DerefMut; use itertools::izip; use lang_c::ast; @@ -15,6 +16,190 @@ pub struct GvnInner {} impl Optimize for GvnInner { fn optimize(&mut self, code: &mut FunctionDefinition) -> bool { - todo!() + println!("hihi2352352"); + let cfg = make_cfg(code); + let reverse_cfg = reverse_cfg(&cfg); + let domtree = Domtree::new(code.bid_init, &cfg, &reverse_cfg); + + let mut register_table = HashMap::new(); + let mut expression_table = HashMap::new(); + let mut leader_tables = HashMap::new(); + let init_leader_table = leader_tables.entry(code.bid_init).or_default(); + let mut replaces = HashMap::new(); + + for (aid, _) in code.allocations.iter().enumerate() { + let number = get_register_number( + RegisterId::local(aid), + &mut register_table, + &expression_table, + init_leader_table, + ); + } + println!("hihi4"); + + for bid in domtree.rpo() { + traverse_rpo( + *bid, + code, + &reverse_cfg, + &domtree, + &mut register_table, + &mut expression_table, + &mut leader_tables, + &mut replaces, + ); + } + + println!("replaces: {replaces:?}"); + + for (bid, block) in code.blocks.iter_mut() { + loop { + let mut changed = false; + for inst in block.instructions.iter_mut() { + changed = replace_instruction_operands(inst, &replaces) || changed; + } + changed = replace_exit_operands(&mut block.exit, &replaces) || changed; + + if !changed { + break; + } + } + } + + println!("hihi2"); + + false // TODO + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum Operand { + Number(usize), + IrOperand(ir::Operand), +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum Expression { + BinOp { + op: ast::BinaryOperator, + lhs: Operand, + rhs: Operand, + }, + UnaryOp { + op: ast::UnaryOperator, + operand: Operand, + }, +} + +fn get_register_number( + rid: RegisterId, + register_table: &mut HashMap, + expression_table: &HashMap, + leader_table: &mut HashMap, +) -> usize { + let len = register_table.len() + expression_table.len(); + let number = *register_table.entry(rid).or_insert(len); + let _ = leader_table.insert(number, rid); + number +} + +fn get_expression_number( + expr: Expression, + register_table: &HashMap, + expression_table: &mut HashMap, +) -> usize { + let len = register_table.len() + expression_table.len(); + *expression_table.entry(expr.clone()).or_insert(len) +} + +fn traverse_rpo( + bid: BlockId, + code: &mut FunctionDefinition, + reverse_cfg: &HashMap>, + domtree: &Domtree, + register_table: &mut HashMap, + expression_table: &mut HashMap, + leader_tables: &mut HashMap>, + replaces: &mut HashMap, +) { + println!("bid: {bid}"); + + let block = code.blocks.get_mut(&bid).unwrap(); + let idom_leader_table = domtree + .idom(&bid) + .and_then(|bid_idom| leader_tables.get(bid_idom)) + .cloned() + .unwrap_or_default(); + let leader_table = leader_tables.entry(bid).or_insert(idom_leader_table); + + if let Some(predecessors) = reverse_cfg.get(&bid) { + for (aid, _) in block.phinodes.iter().enumerate() { + let rid = RegisterId::arg(bid, aid); + let numbers = predecessors + .iter() + .filter_map(|(_, arg)| arg.args[aid].get_register()) + .map(|(rid, _)| { + get_register_number(*rid, register_table, expression_table, leader_table) + }) + .collect::>(); + if numbers.len() == 1 { + let number = *numbers.iter().next().unwrap(); + let _ = register_table.insert(rid, number); + let _ = leader_table.insert(number, rid); + } else { + let _ = get_register_number(rid, register_table, expression_table, leader_table); + } + } + } + + for (i, inst) in block.instructions.iter_mut().enumerate() { + let expr = match inst.deref().deref() { + Instruction::BinOp { op, lhs, rhs, .. } => Expression::BinOp { + op: op.clone(), + lhs: ir_operand_to_gvn_operand(lhs, register_table, expression_table, leader_table), + rhs: ir_operand_to_gvn_operand(rhs, register_table, expression_table, leader_table), + }, + Instruction::UnaryOp { op, operand, .. } => Expression::UnaryOp { + op: op.clone(), + operand: ir_operand_to_gvn_operand( + operand, + register_table, + expression_table, + leader_table, + ), + }, + _ => continue, + }; + let number = get_expression_number(expr, register_table, expression_table); + let rid = RegisterId::temp(bid, i); + + println!("{i} {number} {expression_table:?} {leader_table:?}"); + + if let Some(leader_value) = leader_table.get(&number) { + // *inst.deref_mut() = Instruction::Nop; + let _unused = replaces.insert(rid, ir::Operand::register(*leader_value, inst.dtype())); + println!("왜 않?"); + } else { + let _ = leader_table.insert(number, rid); + } + + // TODO: Phinode insert + } +} + +fn ir_operand_to_gvn_operand( + operand: &ir::Operand, + register_table: &mut HashMap, + expression_table: &HashMap, + leader_table: &mut HashMap, +) -> Operand { + match operand { + ir::Operand::Register { rid, .. } => Operand::Number(get_register_number( + *rid, + register_table, + expression_table, + leader_table, + )), + _ => Operand::IrOperand(operand.clone()), } } diff --git a/src/opt/opt_utils.rs b/src/opt/opt_utils.rs index 49d1c7b..80d6a7b 100644 --- a/src/opt/opt_utils.rs +++ b/src/opt/opt_utils.rs @@ -51,6 +51,7 @@ pub(crate) fn reverse_cfg( } result } + fn traverse_rpo(bid_init: BlockId, cfg: &HashMap>) -> Vec { fn traverse_po( bid: BlockId, @@ -79,6 +80,7 @@ pub(crate) struct Domtree { idoms: HashMap, inverse_idoms: HashMap>, frontiers: HashMap>, + rpo: Vec, } impl Domtree { @@ -155,6 +157,7 @@ impl Domtree { idoms, inverse_idoms, frontiers, + rpo, } } @@ -182,6 +185,10 @@ impl Domtree { pub(crate) fn frontiers(&self, bid: &BlockId) -> Option<&Vec> { self.frontiers.get(bid) } + + pub(crate) fn rpo(&self) -> &Vec { + &self.rpo + } } fn intersect_idom( @@ -208,6 +215,7 @@ pub(crate) fn replace_instruction_operands( replaces: &HashMap, ) -> bool { match inst { + Instruction::Nop => false, Instruction::BinOp { lhs, rhs, .. } => { let a = replace_operand(lhs, replaces); let b = replace_operand(rhs, replaces); @@ -290,8 +298,10 @@ pub(crate) fn replace_operand( ) -> bool { if let Operand::Register { rid, .. } = operand { if let Some(new_operand) = replaces.get(rid) { - *operand = new_operand.clone(); - return true; + if (operand != new_operand) { + *operand = new_operand.clone(); + return true; + } } } false