mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
HW6 (1)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use core::ops::Deref;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::opt::opt_utils::*;
|
||||
@@ -12,6 +13,190 @@ pub struct DeadcodeInner {}
|
||||
|
||||
impl Optimize<FunctionDefinition> for DeadcodeInner {
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
let mut used_allocations = HashSet::new();
|
||||
let mut used_registers = HashSet::new();
|
||||
|
||||
for (bid, block) in &code.blocks {
|
||||
for (i, inst) in block.instructions.iter().enumerate() {
|
||||
match inst.deref() {
|
||||
Instruction::BinOp { lhs, rhs, .. } => {
|
||||
mark_as_used(lhs, &mut used_allocations, &mut used_registers);
|
||||
mark_as_used(rhs, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
Instruction::UnaryOp { operand, .. } => {
|
||||
mark_as_used(operand, &mut used_allocations, &mut used_registers)
|
||||
}
|
||||
Instruction::Store { ptr, value } => {
|
||||
mark_as_used(ptr, &mut used_allocations, &mut used_registers);
|
||||
mark_as_used(value, &mut used_allocations, &mut used_registers);
|
||||
// mark_as_used(
|
||||
// &Operand::register(RegisterId::temp(*bid, i), inst.dtype()),
|
||||
// &mut used_allocations,
|
||||
// &mut used_registers,
|
||||
// );
|
||||
}
|
||||
Instruction::Load { ptr } => {
|
||||
mark_as_used(ptr, &mut used_allocations, &mut used_registers)
|
||||
}
|
||||
Instruction::Call { callee, args, .. } => {
|
||||
mark_as_used(callee, &mut used_allocations, &mut used_registers);
|
||||
for arg in args {
|
||||
mark_as_used(arg, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
// mark_as_used(
|
||||
// &Operand::register(RegisterId::temp(*bid, i), inst.dtype()),
|
||||
// &mut used_allocations,
|
||||
// &mut used_registers,
|
||||
// );
|
||||
}
|
||||
Instruction::TypeCast { value, .. } => {
|
||||
mark_as_used(value, &mut used_allocations, &mut used_registers)
|
||||
}
|
||||
Instruction::GetElementPtr { ptr, offset, .. } => {
|
||||
mark_as_used(ptr, &mut used_allocations, &mut used_registers);
|
||||
mark_as_used(offset, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
match &block.exit {
|
||||
BlockExit::Jump { arg } => {
|
||||
mark_jump_args_as_used(arg, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
BlockExit::ConditionalJump {
|
||||
condition,
|
||||
arg_then,
|
||||
arg_else,
|
||||
} => {
|
||||
mark_as_used(condition, &mut used_allocations, &mut used_registers);
|
||||
mark_jump_args_as_used(arg_then, &mut used_allocations, &mut used_registers);
|
||||
mark_jump_args_as_used(arg_else, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
BlockExit::Switch {
|
||||
value,
|
||||
default,
|
||||
cases,
|
||||
} => {
|
||||
mark_as_used(value, &mut used_allocations, &mut used_registers);
|
||||
mark_jump_args_as_used(default, &mut used_allocations, &mut used_registers);
|
||||
for (_, arg) in cases {
|
||||
mark_jump_args_as_used(arg, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
}
|
||||
BlockExit::Return { value } => {
|
||||
mark_as_used(value, &mut used_allocations, &mut used_registers);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
println!("{used_allocations:?} /// {used_registers:?}");
|
||||
|
||||
let mut replaces = HashMap::new();
|
||||
|
||||
let survived_allocations = code
|
||||
.allocations
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(aid, _)| used_allocations.contains(aid))
|
||||
.collect::<Vec<_>>();
|
||||
if survived_allocations.len() != code.allocations.len() {
|
||||
for (new_aid, (old_aid, dtype)) in survived_allocations.iter().enumerate() {
|
||||
let _unused = replaces.insert(
|
||||
RegisterId::local(*old_aid),
|
||||
Operand::register(
|
||||
RegisterId::local(new_aid),
|
||||
Dtype::pointer((*dtype).deref().clone()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
code.allocations = survived_allocations
|
||||
.into_iter()
|
||||
.map(|(_, dtype)| dtype.clone())
|
||||
.collect();
|
||||
}
|
||||
|
||||
for (bid, block) in &mut code.blocks {
|
||||
let nop_instructions = block
|
||||
.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(iid, inst)| match (*inst).deref() {
|
||||
Instruction::Nop => Some(iid),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let survived_instructions = block
|
||||
.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(iid, inst)| {
|
||||
(used_registers.contains(&RegisterId::temp(*bid, *iid))
|
||||
&& !nop_instructions.contains(iid))
|
||||
|| !inst.has_no_side_effects()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if survived_instructions.len() != block.instructions.len() {
|
||||
for (new_iid, (old_iid, inst)) in survived_instructions.iter().enumerate() {
|
||||
let _unused = replaces.insert(
|
||||
RegisterId::temp(*bid, *old_iid),
|
||||
Operand::register(RegisterId::temp(*bid, new_iid), inst.dtype()),
|
||||
);
|
||||
}
|
||||
|
||||
for iid_nop in &nop_instructions {
|
||||
let _unused = replaces.insert(
|
||||
RegisterId::temp(*bid, *iid_nop),
|
||||
Operand::constant(Constant::unit()),
|
||||
);
|
||||
}
|
||||
|
||||
block.instructions = survived_instructions
|
||||
.into_iter()
|
||||
.map(|(_, inst)| inst.clone())
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
for (bid, block) in code.blocks.iter_mut() {
|
||||
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;
|
||||
}
|
||||
|
||||
!replaces.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_as_used(
|
||||
operand: &Operand,
|
||||
used_allocations: &mut HashSet<usize>,
|
||||
used_registers: &mut HashSet<RegisterId>,
|
||||
) {
|
||||
match operand {
|
||||
Operand::Register { rid, .. } => match rid {
|
||||
RegisterId::Local { aid } => {
|
||||
let _ = used_allocations.insert(*aid);
|
||||
}
|
||||
_ => {
|
||||
let _ = used_registers.insert(*rid);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_jump_args_as_used(
|
||||
arg: &JumpArg,
|
||||
used_allocations: &mut HashSet<usize>,
|
||||
used_registers: &mut HashSet<RegisterId>,
|
||||
) {
|
||||
for arg in &arg.args {
|
||||
mark_as_used(arg, used_allocations, used_registers);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user