This commit is contained in:
static
2025-06-01 08:37:49 +00:00
parent ab7d884fd4
commit 9d8e510138
2 changed files with 199 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
use core::ops::Deref; use core::ops::Deref;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::ops::DerefMut;
use itertools::izip; use itertools::izip;
use lang_c::ast; use lang_c::ast;
@@ -15,6 +16,190 @@ pub struct GvnInner {}
impl Optimize<FunctionDefinition> for GvnInner { impl Optimize<FunctionDefinition> for GvnInner {
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool { 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<RegisterId, usize>,
expression_table: &HashMap<Expression, usize>,
leader_table: &mut HashMap<usize, RegisterId>,
) -> 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<RegisterId, usize>,
expression_table: &mut HashMap<Expression, usize>,
) -> 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<BlockId, Vec<(BlockId, JumpArg)>>,
domtree: &Domtree,
register_table: &mut HashMap<RegisterId, usize>,
expression_table: &mut HashMap<Expression, usize>,
leader_tables: &mut HashMap<BlockId, HashMap<usize, RegisterId>>,
replaces: &mut HashMap<RegisterId, ir::Operand>,
) {
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::<HashSet<_>>();
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<RegisterId, usize>,
expression_table: &HashMap<Expression, usize>,
leader_table: &mut HashMap<usize, RegisterId>,
) -> Operand {
match operand {
ir::Operand::Register { rid, .. } => Operand::Number(get_register_number(
*rid,
register_table,
expression_table,
leader_table,
)),
_ => Operand::IrOperand(operand.clone()),
} }
} }

View File

@@ -51,6 +51,7 @@ pub(crate) fn reverse_cfg(
} }
result result
} }
fn traverse_rpo(bid_init: BlockId, cfg: &HashMap<BlockId, Vec<JumpArg>>) -> Vec<BlockId> { fn traverse_rpo(bid_init: BlockId, cfg: &HashMap<BlockId, Vec<JumpArg>>) -> Vec<BlockId> {
fn traverse_po( fn traverse_po(
bid: BlockId, bid: BlockId,
@@ -79,6 +80,7 @@ pub(crate) struct Domtree {
idoms: HashMap<BlockId, BlockId>, idoms: HashMap<BlockId, BlockId>,
inverse_idoms: HashMap<BlockId, HashSet<BlockId>>, inverse_idoms: HashMap<BlockId, HashSet<BlockId>>,
frontiers: HashMap<BlockId, Vec<BlockId>>, frontiers: HashMap<BlockId, Vec<BlockId>>,
rpo: Vec<BlockId>,
} }
impl Domtree { impl Domtree {
@@ -155,6 +157,7 @@ impl Domtree {
idoms, idoms,
inverse_idoms, inverse_idoms,
frontiers, frontiers,
rpo,
} }
} }
@@ -182,6 +185,10 @@ impl Domtree {
pub(crate) fn frontiers(&self, bid: &BlockId) -> Option<&Vec<BlockId>> { pub(crate) fn frontiers(&self, bid: &BlockId) -> Option<&Vec<BlockId>> {
self.frontiers.get(bid) self.frontiers.get(bid)
} }
pub(crate) fn rpo(&self) -> &Vec<BlockId> {
&self.rpo
}
} }
fn intersect_idom( fn intersect_idom(
@@ -208,6 +215,7 @@ pub(crate) fn replace_instruction_operands(
replaces: &HashMap<RegisterId, Operand>, replaces: &HashMap<RegisterId, Operand>,
) -> bool { ) -> bool {
match inst { match inst {
Instruction::Nop => false,
Instruction::BinOp { lhs, rhs, .. } => { Instruction::BinOp { lhs, rhs, .. } => {
let a = replace_operand(lhs, replaces); let a = replace_operand(lhs, replaces);
let b = replace_operand(rhs, replaces); let b = replace_operand(rhs, replaces);
@@ -290,8 +298,10 @@ pub(crate) fn replace_operand(
) -> bool { ) -> bool {
if let Operand::Register { rid, .. } = operand { if let Operand::Register { rid, .. } = operand {
if let Some(new_operand) = replaces.get(rid) { if let Some(new_operand) = replaces.get(rid) {
*operand = new_operand.clone(); if (operand != new_operand) {
return true; *operand = new_operand.clone();
return true;
}
} }
} }
false false