mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
HW5 (1)
This commit is contained in:
189
src/opt/gvn.rs
189
src/opt/gvn.rs
@@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user