InferenceGraph 구현
This commit is contained in:
static
2025-06-16 17:27:06 +00:00
parent c3d6e303a5
commit e3ab187dea
2 changed files with 166 additions and 2 deletions

View File

@@ -5,7 +5,7 @@ use std::ops::Deref;
use lang_c::ast;
use crate::ir::HasDtype;
use crate::opt::opt_utils;
use crate::opt::opt_utils::*;
use crate::{Translate, asm, ir};
#[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 {
insts: Vec<asm::Instruction>,
stack_offsets: HashMap<ir::RegisterId, u64>,
@@ -95,6 +256,9 @@ impl Asmgen {
definition,
} => {
if let Some(definition) = definition {
// TEMP
let graph = InferenceGraph::new(definition);
let mut context = self.translate_prologue(signature, definition, structs);
self.translate_block(
name,

View File

@@ -122,7 +122,7 @@ impl Domtree {
};
for (bid_pred, _) in preds {
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);
runner = idoms[&runner];
}