diff --git a/src/opt/gvn.rs b/src/opt/gvn.rs index 5c0fed6..9c8b832 100644 --- a/src/opt/gvn.rs +++ b/src/opt/gvn.rs @@ -5,6 +5,7 @@ use std::ops::DerefMut; use itertools::izip; use lang_c::ast; +use crate::asm::Register; use crate::ir::*; use crate::opt::opt_utils::*; use crate::opt::*; @@ -52,6 +53,8 @@ impl Optimize for GvnInner { println!("replaces: {replaces:?}"); + let mut result = false; + for (bid, block) in code.blocks.iter_mut() { loop { let mut changed = false; @@ -60,6 +63,8 @@ impl Optimize for GvnInner { } changed = replace_exit_operands(&mut block.exit, &replaces) || changed; + result = result || changed; + if !changed { break; } @@ -68,7 +73,7 @@ impl Optimize for GvnInner { println!("hihi2"); - false // TODO + result } } @@ -89,24 +94,38 @@ enum Expression { op: ast::UnaryOperator, operand: Operand, }, + TypeCast { + value: Operand, + target_dtype: Dtype, + }, + GetElementPtr { + ptr: Operand, + offset: Operand, + dtype: Dtype, + }, } fn get_register_number( rid: RegisterId, - register_table: &mut HashMap, + register_table: &mut HashMap, expression_table: &HashMap, - leader_table: &mut HashMap, -) -> usize { + leader_table: &mut HashMap, +) -> NumberOrConstant { let len = register_table.len() + expression_table.len(); - let number = *register_table.entry(rid).or_insert(len); - let _ = leader_table.insert(number, rid); - println!("[REG] {number}={rid:?}"); + let number = register_table + .entry(rid) + .or_insert(NumberOrConstant::Number(len)) + .clone(); + if let NumberOrConstant::Number(number) = number { + let _unused = leader_table.insert(number, RegisterOrConstant::Register(rid)); + } + println!("[REG] {number:?}={rid:?}"); number } fn get_expression_number( expr: Expression, - register_table: &HashMap, + register_table: &HashMap, expression_table: &mut HashMap, ) -> usize { let len = register_table.len() + expression_table.len(); @@ -115,14 +134,26 @@ fn get_expression_number( number } +#[derive(Clone, Debug)] +enum RegisterOrConstant { + Register(RegisterId), + Constant(Constant), +} + +#[derive(Clone, Debug, Hash, Eq, PartialEq)] +enum NumberOrConstant { + Number(usize), + Constant(Constant), +} + fn traverse_rpo( bid: BlockId, code: &mut FunctionDefinition, reverse_cfg: &mut HashMap>, domtree: &Domtree, - register_table: &mut HashMap, + register_table: &mut HashMap, expression_table: &mut HashMap, - leader_tables: &mut HashMap>, + leader_tables: &mut HashMap>, replaces: &mut HashMap, ) { println!("bid: {bid}"); @@ -140,26 +171,34 @@ fn traverse_rpo( if let Some(ref predecessors) = predecessors { for (aid, _) in block.phinodes.iter().enumerate() { let rid = RegisterId::arg(bid, aid); - if !predecessors - .iter() - .all(|(_, arg)| arg.args[aid].get_register().is_some()) - { - continue; - } - let numbers = predecessors .iter() - .filter_map(|(_, arg)| arg.args[aid].get_register()) - .map(|(rid, _)| { - get_register_number(*rid, register_table, expression_table, &mut leader_table) + .map(|(_, arg)| match &arg.args[aid] { + ir::Operand::Constant(constant) => NumberOrConstant::Constant(constant.clone()), + ir::Operand::Register { rid, .. } => get_register_number( + *rid, + register_table, + expression_table, + &mut 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); + let number = numbers.iter().next().unwrap().clone(); + match number { + NumberOrConstant::Number(number) => { + let _unused = register_table.insert(rid, NumberOrConstant::Number(number)); + let _unused = + leader_table.insert(number, RegisterOrConstant::Register(rid)); + } + NumberOrConstant::Constant(constant) => { + let _unused = + register_table.insert(rid, NumberOrConstant::Constant(constant.clone())); + let _unused = replaces.insert(rid, ir::Operand::constant(constant.clone())); + } + } } else { - let _ = + let _unused = get_register_number(rid, register_table, expression_table, &mut leader_table); } } @@ -193,6 +232,33 @@ fn traverse_rpo( &mut leader_table, ), }, + Instruction::TypeCast { + value, + target_dtype, + } => Expression::TypeCast { + value: ir_operand_to_gvn_operand( + value, + register_table, + expression_table, + &mut leader_table, + ), + target_dtype: target_dtype.clone(), + }, + Instruction::GetElementPtr { ptr, offset, dtype } => Expression::GetElementPtr { + ptr: ir_operand_to_gvn_operand( + ptr, + register_table, + expression_table, + &mut leader_table, + ), + offset: ir_operand_to_gvn_operand( + offset, + register_table, + expression_table, + &mut leader_table, + ), + dtype: dtype.clone(), + }, _ => continue, }; let number = get_expression_number(expr, register_table, expression_table); @@ -201,10 +267,16 @@ fn traverse_rpo( println!("{i} {number} {expression_table:?} {leader_table:?}"); if let Some(leader_value) = leader_table.get(&number) { - // *inst.deref_mut() = Instruction::Nop; - let _ = register_table.insert(rid, number); - let _unused = replaces.insert(rid, ir::Operand::register(*leader_value, inst.dtype())); - // println!("왜 않?"); + match leader_value { + RegisterOrConstant::Register(leader_value) => { + let _unused = register_table.insert(rid, NumberOrConstant::Number(number)); + let _unused = + replaces.insert(rid, ir::Operand::register(*leader_value, inst.dtype())); + } + RegisterOrConstant::Constant(constant) => { + let _unused = replaces.insert(rid, ir::Operand::constant(constant.clone())); + } + } } else { if let Some(ref mut predecessors) = predecessors { println!("하위 {predecessors:?} {leader_tables:?}"); @@ -218,18 +290,28 @@ fn traverse_rpo( let phinode_index = block.phinodes.len(); block.phinodes.push(Named::new(None, inst.dtype())); - let _ = register_table.insert(RegisterId::arg(bid, phinode_index), number); - let _ = leader_table.insert(number, RegisterId::arg(bid, phinode_index)); + let _unused = register_table.insert( + RegisterId::arg(bid, phinode_index), + NumberOrConstant::Number(number), + ); + let _unused = leader_table.insert( + number, + RegisterOrConstant::Register(RegisterId::arg(bid, phinode_index)), + ); let _unused = replaces.insert( rid, ir::Operand::register(RegisterId::arg(bid, phinode_index), inst.dtype()), ); for (bid_predecessor, jump_arg) in predecessors.iter_mut() { - let new_arg = ir::Operand::register( - leader_tables[bid_predecessor][&number], - inst.dtype(), - ); + let new_arg = match &leader_tables[bid_predecessor][&number] { + RegisterOrConstant::Register(rid) => { + ir::Operand::register(*rid, inst.dtype()) + } + RegisterOrConstant::Constant(constant) => { + ir::Operand::constant(constant.clone()) + } + }; jump_arg.args.push(new_arg.clone()); let _ = phinode_allocs .entry(*bid_predecessor) @@ -241,8 +323,8 @@ fn traverse_rpo( } } - let _ = leader_table.insert(number, rid); - let _ = register_table.insert(rid, number); + let _unused = leader_table.insert(number, RegisterOrConstant::Register(rid)); + let _unused = register_table.insert(rid, NumberOrConstant::Number(number)); } } @@ -272,17 +354,19 @@ fn traverse_rpo( fn ir_operand_to_gvn_operand( operand: &ir::Operand, - register_table: &mut HashMap, + register_table: &mut HashMap, expression_table: &HashMap, - leader_table: &mut HashMap, + leader_table: &mut HashMap, ) -> Operand { match operand { - ir::Operand::Register { rid, .. } => Operand::Number(get_register_number( - *rid, - register_table, - expression_table, - leader_table, - )), + ir::Operand::Register { rid, .. } => { + match get_register_number(*rid, register_table, expression_table, leader_table) { + NumberOrConstant::Number(number) => Operand::Number(number), + NumberOrConstant::Constant(constant) => { + Operand::IrOperand(ir::Operand::Constant(constant)) + } + } + } _ => Operand::IrOperand(operand.clone()), } }