mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
HW8 (2)
InferenceGraph 구현
This commit is contained in:
@@ -5,7 +5,7 @@ use std::ops::Deref;
|
|||||||
use lang_c::ast;
|
use lang_c::ast;
|
||||||
|
|
||||||
use crate::ir::HasDtype;
|
use crate::ir::HasDtype;
|
||||||
use crate::opt::opt_utils;
|
use crate::opt::opt_utils::*;
|
||||||
use crate::{Translate, asm, ir};
|
use crate::{Translate, asm, ir};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@@ -35,6 +35,167 @@ impl Translate<ir::TranslationUnit> for Asmgen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InferenceGraph {
|
||||||
|
edges: HashSet<(ir::RegisterId, ir::RegisterId)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InferenceGraph {
|
||||||
|
fn new(code: &ir::FunctionDefinition) -> Self {
|
||||||
|
let cfg = make_cfg(code);
|
||||||
|
let reverse_cfg = reverse_cfg(&cfg);
|
||||||
|
let domtree = Domtree::new(code.bid_init, &cfg, &reverse_cfg);
|
||||||
|
|
||||||
|
let mut lives = HashMap::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
for bid in domtree.rpo() {
|
||||||
|
let block = &code.blocks[bid];
|
||||||
|
let len = block.instructions.len();
|
||||||
|
let mut uses = HashSet::new();
|
||||||
|
|
||||||
|
for (i, inst) in block.instructions.iter().enumerate() {
|
||||||
|
match inst.deref() {
|
||||||
|
ir::Instruction::BinOp { lhs, rhs, .. } => {
|
||||||
|
mark_as_used(lhs, &mut uses);
|
||||||
|
mark_as_used(rhs, &mut uses);
|
||||||
|
}
|
||||||
|
ir::Instruction::UnaryOp { operand, .. } => {
|
||||||
|
mark_as_used(operand, &mut uses);
|
||||||
|
}
|
||||||
|
ir::Instruction::Store { ptr, value } => {
|
||||||
|
mark_as_used(ptr, &mut uses);
|
||||||
|
mark_as_used(value, &mut uses);
|
||||||
|
}
|
||||||
|
ir::Instruction::Load { ptr } => {
|
||||||
|
mark_as_used(ptr, &mut uses);
|
||||||
|
}
|
||||||
|
ir::Instruction::Call { callee, args, .. } => {
|
||||||
|
mark_as_used(callee, &mut uses);
|
||||||
|
for arg in args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::Instruction::TypeCast { value, .. } => {
|
||||||
|
mark_as_used(value, &mut uses);
|
||||||
|
}
|
||||||
|
ir::Instruction::GetElementPtr { ptr, offset, .. } => {
|
||||||
|
mark_as_used(ptr, &mut uses);
|
||||||
|
mark_as_used(offset, &mut uses);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut next_lives = lives
|
||||||
|
.entry(ir::RegisterId::temp(*bid, i + 1))
|
||||||
|
.or_insert_with(HashSet::new)
|
||||||
|
.clone();
|
||||||
|
let _ = next_lives.remove(&ir::RegisterId::temp(*bid, i));
|
||||||
|
uses.extend(next_lives);
|
||||||
|
changed = extend_set(
|
||||||
|
lives
|
||||||
|
.entry(ir::RegisterId::temp(*bid, i))
|
||||||
|
.or_insert_with(HashSet::new),
|
||||||
|
std::mem::take(&mut uses),
|
||||||
|
) || changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut uses = HashSet::new();
|
||||||
|
match &block.exit {
|
||||||
|
ir::BlockExit::Jump { arg } => {
|
||||||
|
for arg in &arg.args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::BlockExit::ConditionalJump {
|
||||||
|
condition,
|
||||||
|
arg_then,
|
||||||
|
arg_else,
|
||||||
|
} => {
|
||||||
|
mark_as_used(condition, &mut uses);
|
||||||
|
for arg in &arg_then.args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
for arg in &arg_else.args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::BlockExit::Switch {
|
||||||
|
value,
|
||||||
|
default,
|
||||||
|
cases,
|
||||||
|
} => {
|
||||||
|
mark_as_used(value, &mut uses);
|
||||||
|
for arg in &default.args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
for (_, arg) in cases {
|
||||||
|
for arg in &arg.args {
|
||||||
|
mark_as_used(arg, &mut uses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::BlockExit::Return { value } => {
|
||||||
|
mark_as_used(value, &mut uses);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
let successors = cfg[bid].iter().map(|arg| arg.bid).collect::<Vec<_>>();
|
||||||
|
let mut successor_lives = HashSet::<ir::RegisterId>::new();
|
||||||
|
for succ in &successors {
|
||||||
|
if let Some(succ_lives) = lives.get(&ir::RegisterId::temp(*succ, 0)) {
|
||||||
|
successor_lives.extend(succ_lives);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uses.extend(successor_lives);
|
||||||
|
changed = extend_set(
|
||||||
|
lives
|
||||||
|
.entry(ir::RegisterId::temp(*bid, len))
|
||||||
|
.or_insert_with(HashSet::new),
|
||||||
|
uses,
|
||||||
|
) || changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !changed {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut edges = HashSet::new();
|
||||||
|
|
||||||
|
for (_, lives) in &lives {
|
||||||
|
for rid1 in lives {
|
||||||
|
for rid2 in lives {
|
||||||
|
if rid1 != rid2 {
|
||||||
|
let _ = edges.insert((*rid1, *rid2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Inference graph: {:?}", edges);
|
||||||
|
|
||||||
|
InferenceGraph { edges }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_as_used(operand: &ir::Operand, uses: &mut HashSet<ir::RegisterId>) {
|
||||||
|
if let ir::Operand::Register { rid, .. } = operand {
|
||||||
|
if !matches!(rid, ir::RegisterId::Local { .. }) {
|
||||||
|
let _ = uses.insert(*rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extend_set(set: &mut HashSet<ir::RegisterId>, other: HashSet<ir::RegisterId>) -> bool {
|
||||||
|
let len = set.len();
|
||||||
|
set.extend(other);
|
||||||
|
set.len() != len
|
||||||
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
insts: Vec<asm::Instruction>,
|
insts: Vec<asm::Instruction>,
|
||||||
stack_offsets: HashMap<ir::RegisterId, u64>,
|
stack_offsets: HashMap<ir::RegisterId, u64>,
|
||||||
@@ -95,6 +256,9 @@ impl Asmgen {
|
|||||||
definition,
|
definition,
|
||||||
} => {
|
} => {
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
|
// TEMP
|
||||||
|
let graph = InferenceGraph::new(definition);
|
||||||
|
|
||||||
let mut context = self.translate_prologue(signature, definition, structs);
|
let mut context = self.translate_prologue(signature, definition, structs);
|
||||||
self.translate_block(
|
self.translate_block(
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ impl Domtree {
|
|||||||
};
|
};
|
||||||
for (bid_pred, _) in preds {
|
for (bid_pred, _) in preds {
|
||||||
let mut runner = *bid_pred;
|
let mut runner = *bid_pred;
|
||||||
while !Self::dominates(&idoms, runner, *bid) {
|
while idoms.contains_key(&runner) && !Self::dominates(&idoms, runner, *bid) {
|
||||||
frontiers.entry(runner).or_insert_with(Vec::new).push(*bid);
|
frontiers.entry(runner).or_insert_with(Vec::new).push(*bid);
|
||||||
runner = idoms[&runner];
|
runner = idoms[&runner];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user