mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
HW5 (3)
This commit is contained in:
172
src/opt/gvn.rs
172
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<FunctionDefinition> 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<FunctionDefinition> for GvnInner {
|
||||
}
|
||||
changed = replace_exit_operands(&mut block.exit, &replaces) || changed;
|
||||
|
||||
result = result || changed;
|
||||
|
||||
if !changed {
|
||||
break;
|
||||
}
|
||||
@@ -68,7 +73,7 @@ impl Optimize<FunctionDefinition> 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<RegisterId, usize>,
|
||||
register_table: &mut HashMap<RegisterId, NumberOrConstant>,
|
||||
expression_table: &HashMap<Expression, usize>,
|
||||
leader_table: &mut HashMap<usize, RegisterId>,
|
||||
) -> usize {
|
||||
leader_table: &mut HashMap<usize, RegisterOrConstant>,
|
||||
) -> 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<RegisterId, usize>,
|
||||
register_table: &HashMap<RegisterId, NumberOrConstant>,
|
||||
expression_table: &mut HashMap<Expression, usize>,
|
||||
) -> 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<BlockId, Vec<(BlockId, JumpArg)>>,
|
||||
domtree: &Domtree,
|
||||
register_table: &mut HashMap<RegisterId, usize>,
|
||||
register_table: &mut HashMap<RegisterId, NumberOrConstant>,
|
||||
expression_table: &mut HashMap<Expression, usize>,
|
||||
leader_tables: &mut HashMap<BlockId, HashMap<usize, RegisterId>>,
|
||||
leader_tables: &mut HashMap<BlockId, HashMap<usize, RegisterOrConstant>>,
|
||||
replaces: &mut HashMap<RegisterId, ir::Operand>,
|
||||
) {
|
||||
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::<HashSet<_>>();
|
||||
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<RegisterId, usize>,
|
||||
register_table: &mut HashMap<RegisterId, NumberOrConstant>,
|
||||
expression_table: &HashMap<Expression, usize>,
|
||||
leader_table: &mut HashMap<usize, RegisterId>,
|
||||
leader_table: &mut HashMap<usize, RegisterOrConstant>,
|
||||
) -> 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()),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user