mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 15:08:52 +00:00
HW3 (2)
This commit is contained in:
@@ -32,13 +32,12 @@ pub struct SimplifyCfgEmpty {}
|
|||||||
|
|
||||||
impl Optimize<FunctionDefinition> for SimplifyCfgConstProp {
|
impl Optimize<FunctionDefinition> for SimplifyCfgConstProp {
|
||||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||||
code.blocks.iter_mut().any(|(_, block)| {
|
code.blocks.values_mut().fold(false, |mut result, block| {
|
||||||
if let Some(exit) = self.simplify_block_exit(&block.exit) {
|
if let Some(new_exit) = self.simplify_block_exit(&block.exit) {
|
||||||
block.exit = exit;
|
block.exit = new_exit;
|
||||||
true
|
result = true;
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,9 +46,11 @@ impl Optimize<FunctionDefinition> for SimplifyCfgReach {
|
|||||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||||
let graph = make_cfg(code);
|
let graph = make_cfg(code);
|
||||||
let mut visited = HashSet::new();
|
let mut visited = HashSet::new();
|
||||||
|
let mut queue = Vec::new();
|
||||||
|
|
||||||
let mut queue = vec![code.bid_init];
|
|
||||||
let _ = visited.insert(code.bid_init);
|
let _ = visited.insert(code.bid_init);
|
||||||
|
queue.push(code.bid_init);
|
||||||
|
|
||||||
while let Some(bid) = queue.pop() {
|
while let Some(bid) = queue.pop() {
|
||||||
if let Some(args) = graph.get(&bid) {
|
if let Some(args) = graph.get(&bid) {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
@@ -60,9 +61,9 @@ impl Optimize<FunctionDefinition> for SimplifyCfgReach {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let size_org = code.blocks.len();
|
let blocks_org = code.blocks.len();
|
||||||
code.blocks.retain(|bid, _| visited.contains(bid));
|
code.blocks.retain(|bid, _| visited.contains(bid));
|
||||||
code.blocks.len() < size_org
|
code.blocks.len() < blocks_org
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ impl Optimize<FunctionDefinition> for SimplifyCfgMerge {
|
|||||||
let mut indegrees = HashMap::new();
|
let mut indegrees = HashMap::new();
|
||||||
for args in graph.values() {
|
for args in graph.values() {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
*indegrees.entry(arg.bid).or_insert(0) += 1usize;
|
*indegrees.entry(arg.bid).or_default() += 1usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,26 +85,26 @@ impl Optimize<FunctionDefinition> for SimplifyCfgMerge {
|
|||||||
if let BlockExit::Jump { arg } = &block_from.exit {
|
if let BlockExit::Jump { arg } = &block_from.exit {
|
||||||
let bid_to = arg.bid;
|
let bid_to = arg.bid;
|
||||||
if *bid_from != bid_to && indegrees.get(&bid_to) == Some(&1) {
|
if *bid_from != bid_to && indegrees.get(&bid_to) == Some(&1) {
|
||||||
let bid_merge_target = *merged_to.get(bid_from).unwrap_or(bid_from);
|
let bid_from = *merged_to.get(bid_from).unwrap_or(bid_from);
|
||||||
merged_from
|
merged_from
|
||||||
.entry(bid_merge_target)
|
.entry(bid_from)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(bid_to);
|
.push(bid_to);
|
||||||
let _ = merged_to.insert(bid_to, bid_merge_target);
|
let _ = merged_to.insert(bid_to, bid_from);
|
||||||
|
|
||||||
if let Some(mut bids_from) = merged_from.remove(&bid_to) {
|
if let Some(mut bids_merged) = merged_from.remove(&bid_to) {
|
||||||
merged_from
|
merged_from
|
||||||
.entry(bid_merge_target)
|
.get_mut(&bid_from)
|
||||||
.or_insert(Vec::new())
|
.unwrap()
|
||||||
.append(&mut bids_from);
|
.append(&mut bids_merged);
|
||||||
merged_to.iter_mut().map(|(_, merged_to)| {
|
merged_to.values_mut().for_each(|merged_to| {
|
||||||
if *merged_to == bid_to {
|
if *merged_to == bid_to {
|
||||||
*merged_to = bid_merge_target;
|
*merged_to = bid_from;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_to = code.blocks.get(&bid_to).unwrap();
|
let block_to = &code.blocks[&bid_to];
|
||||||
for (i, (a, p)) in izip!(&arg.args, block_to.phinodes.iter()).enumerate() {
|
for (i, (a, p)) in izip!(&arg.args, block_to.phinodes.iter()).enumerate() {
|
||||||
let from = RegisterId::arg(bid_to, i);
|
let from = RegisterId::arg(bid_to, i);
|
||||||
let _unused = replaces.insert(from, a.clone());
|
let _unused = replaces.insert(from, a.clone());
|
||||||
@@ -112,31 +113,29 @@ impl Optimize<FunctionDefinition> for SimplifyCfgMerge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bid_merge_target, bids_merge_from) in &merged_from {
|
for (bid_merge_to, bids_merge_from) in &merged_from {
|
||||||
let blocks_merge_from = bids_merge_from
|
let blocks_merge_from = bids_merge_from
|
||||||
.iter()
|
.iter()
|
||||||
.map(|bid| code.blocks.get(bid).unwrap().clone())
|
.map(|bid| code.blocks.get(bid).unwrap().clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let block_merge_target = code.blocks.get_mut(bid_merge_target).unwrap();
|
let block_merge_to = code.blocks.get_mut(bid_merge_to).unwrap();
|
||||||
let mut i = block_merge_target.instructions.len();
|
let mut i = block_merge_to.instructions.len();
|
||||||
|
|
||||||
for (bid, block) in bids_merge_from.iter().zip(blocks_merge_from) {
|
for (bid, block) in bids_merge_from.iter().zip(blocks_merge_from) {
|
||||||
for (j, inst) in block.instructions.iter().enumerate() {
|
for (j, inst) in block.instructions.iter().enumerate() {
|
||||||
let dtype = inst.dtype();
|
let dtype = inst.dtype();
|
||||||
block_merge_target.instructions.push(inst.clone());
|
block_merge_to.instructions.push(inst.clone());
|
||||||
|
|
||||||
let from = RegisterId::temp(*bid, j);
|
let from = RegisterId::temp(*bid, j);
|
||||||
let to = Operand::register(RegisterId::temp(*bid_merge_target, i), dtype);
|
let to = Operand::register(RegisterId::temp(*bid_merge_to, i), dtype);
|
||||||
let _unused = replaces.insert(from, to);
|
let _unused = replaces.insert(from, to);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_merge_target.exit = block.exit;
|
block_merge_to.exit = block.exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code.blocks.retain(|bid, _| !merged_to.contains_key(bid));
|
|
||||||
|
|
||||||
for (bid, block) in &mut code.blocks {
|
for (bid, block) in &mut code.blocks {
|
||||||
for inst in block.instructions.iter_mut() {
|
for inst in block.instructions.iter_mut() {
|
||||||
replace_instruction_operands(inst, &replaces);
|
replace_instruction_operands(inst, &replaces);
|
||||||
@@ -144,6 +143,7 @@ impl Optimize<FunctionDefinition> for SimplifyCfgMerge {
|
|||||||
replace_exit_operands(&mut block.exit, &replaces);
|
replace_exit_operands(&mut block.exit, &replaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code.blocks.retain(|bid, _| !merged_to.contains_key(bid));
|
||||||
!merged_to.is_empty()
|
!merged_to.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,9 +156,9 @@ impl Optimize<FunctionDefinition> for SimplifyCfgEmpty {
|
|||||||
.filter(|(_, block)| block.phinodes.is_empty() && block.instructions.is_empty())
|
.filter(|(_, block)| block.phinodes.is_empty() && block.instructions.is_empty())
|
||||||
.map(|(bid, block)| (*bid, block.clone()))
|
.map(|(bid, block)| (*bid, block.clone()))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
code.blocks
|
code.blocks.values_mut().fold(false, |result, block| {
|
||||||
.iter_mut()
|
self.simplify_block_exit(&mut block.exit, &empty_blocks) || result
|
||||||
.any(|(_, block)| self.simplify_block_exit(&mut block.exit, &empty_blocks))
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,18 +174,16 @@ impl SimplifyCfgConstProp {
|
|||||||
Some(BlockExit::Jump {
|
Some(BlockExit::Jump {
|
||||||
arg: arg_then.clone(),
|
arg: arg_then.clone(),
|
||||||
})
|
})
|
||||||
} else if let Some(condition) = condition.get_constant() {
|
|
||||||
match condition {
|
|
||||||
Constant::Int { value: 0, .. } => Some(BlockExit::Jump {
|
|
||||||
arg: arg_else.clone(),
|
|
||||||
}),
|
|
||||||
Constant::Int { value: 1, .. } => Some(BlockExit::Jump {
|
|
||||||
arg: arg_then.clone(),
|
|
||||||
}),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
condition.get_constant().and_then(|condition| {
|
||||||
|
Some(BlockExit::Jump {
|
||||||
|
arg: match condition {
|
||||||
|
Constant::Int { value: 0, .. } => arg_else.clone(),
|
||||||
|
Constant::Int { value: 1, .. } => arg_then.clone(),
|
||||||
|
_ => return None,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BlockExit::Switch {
|
BlockExit::Switch {
|
||||||
@@ -234,13 +232,12 @@ impl SimplifyCfgEmpty {
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
match exit {
|
match exit {
|
||||||
BlockExit::Jump { arg } => {
|
BlockExit::Jump { arg } => {
|
||||||
let block = if let Some(empty_block) = empty_blocks.get(&arg.bid) {
|
if let Some(empty_block) = empty_blocks.get(&arg.bid) {
|
||||||
empty_block
|
*exit = empty_block.exit.clone();
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
return false;
|
false
|
||||||
};
|
}
|
||||||
*exit = block.exit.clone();
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
BlockExit::ConditionalJump {
|
BlockExit::ConditionalJump {
|
||||||
arg_then, arg_else, ..
|
arg_then, arg_else, ..
|
||||||
@@ -251,9 +248,9 @@ impl SimplifyCfgEmpty {
|
|||||||
}
|
}
|
||||||
BlockExit::Switch { default, cases, .. } => {
|
BlockExit::Switch { default, cases, .. } => {
|
||||||
let changed1 = self.simplify_jump_arg(default, empty_blocks);
|
let changed1 = self.simplify_jump_arg(default, empty_blocks);
|
||||||
let changed2 = cases
|
let changed2 = cases.iter_mut().fold(false, |result, (_, arg)| {
|
||||||
.iter_mut()
|
self.simplify_jump_arg(arg, empty_blocks) || result
|
||||||
.any(|c| self.simplify_jump_arg(&mut c.1, empty_blocks));
|
});
|
||||||
changed1 || changed2
|
changed1 || changed2
|
||||||
}
|
}
|
||||||
BlockExit::Return { .. } | BlockExit::Unreachable => false,
|
BlockExit::Return { .. } | BlockExit::Unreachable => false,
|
||||||
@@ -287,19 +284,6 @@ fn make_cfg(fdef: &FunctionDefinition) -> HashMap<BlockId, Vec<JumpArg>> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn reverse_cfg(cfg: &HashMap<BlockId, Vec<JumpArg>>) -> HashMap<BlockId, Vec<(BlockId, JumpArg)>> {
|
|
||||||
// let mut result = HashMap::new();
|
|
||||||
// for (bid, jumps) in cfg {
|
|
||||||
// for jump in jumps {
|
|
||||||
// result
|
|
||||||
// .entry(jump.bid)
|
|
||||||
// .or_insert_with(Vec::new)
|
|
||||||
// .push((*bid, jump.clone()))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// result
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn replace_instruction_operands(inst: &mut Instruction, replaces: &HashMap<RegisterId, Operand>) {
|
fn replace_instruction_operands(inst: &mut Instruction, replaces: &HashMap<RegisterId, Operand>) {
|
||||||
match inst {
|
match inst {
|
||||||
Instruction::BinOp { lhs, rhs, .. } => {
|
Instruction::BinOp { lhs, rhs, .. } => {
|
||||||
@@ -329,21 +313,15 @@ fn replace_instruction_operands(inst: &mut Instruction, replaces: &HashMap<Regis
|
|||||||
replace_operand(ptr, replaces);
|
replace_operand(ptr, replaces);
|
||||||
replace_operand(offset, replaces);
|
replace_operand(offset, replaces);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_exit_operands(exit: &mut BlockExit, replaces: &HashMap<RegisterId, Operand>) {
|
fn replace_exit_operands(exit: &mut BlockExit, replaces: &HashMap<RegisterId, Operand>) {
|
||||||
match exit {
|
match exit {
|
||||||
BlockExit::ConditionalJump { condition, .. } => {
|
BlockExit::ConditionalJump { condition, .. } => replace_operand(condition, replaces),
|
||||||
replace_operand(condition, replaces);
|
BlockExit::Switch { value, .. } => replace_operand(value, replaces),
|
||||||
}
|
BlockExit::Return { value } => replace_operand(value, replaces),
|
||||||
BlockExit::Switch { value, .. } => {
|
|
||||||
replace_operand(value, replaces);
|
|
||||||
}
|
|
||||||
BlockExit::Return { value } => {
|
|
||||||
replace_operand(value, replaces);
|
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -351,7 +329,7 @@ fn replace_exit_operands(exit: &mut BlockExit, replaces: &HashMap<RegisterId, Op
|
|||||||
fn replace_operand(operand: &mut Operand, replaces: &HashMap<RegisterId, Operand>) {
|
fn replace_operand(operand: &mut Operand, replaces: &HashMap<RegisterId, Operand>) {
|
||||||
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) {
|
||||||
std::mem::replace(operand, new_operand.clone());
|
*operand = new_operand.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user