* Manually rename BasicBlock to BlockPredecessor BasicBlock is a pair of (Ebb, Inst) that is used to represent the basic block subcomponent of an Ebb that is a predecessor to an Ebb. Eventually we will be able to remove this struct, but for now it makes sense to give it a non-conflicting name so that we can start to transition Ebb to represent a basic block. I have not updated any comments that refer to BasicBlock, as eventually we will remove BlockPredecessor and replace with Block, which is a basic block, so the comments will become correct. * Manually rename SSABuilder block types to avoid conflict SSABuilder has its own Block and BlockData types. These along with associated identifier will cause conflicts in a later commit, so they are renamed to be more verbose here. * Automatically rename 'Ebb' to 'Block' in *.rs * Automatically rename 'EBB' to 'block' in *.rs * Automatically rename 'ebb' to 'block' in *.rs * Automatically rename 'extended basic block' to 'basic block' in *.rs * Automatically rename 'an basic block' to 'a basic block' in *.rs * Manually update comment for `Block` `Block`'s wikipedia article required an update. * Automatically rename 'an `Block`' to 'a `Block`' in *.rs * Automatically rename 'extended_basic_block' to 'basic_block' in *.rs * Automatically rename 'ebb' to 'block' in *.clif * Manually rename clif constant that contains 'ebb' as substring to avoid conflict * Automatically rename filecheck uses of 'EBB' to 'BB' 'regex: EBB' -> 'regex: BB' '$EBB' -> '$BB' * Automatically rename 'EBB' 'Ebb' to 'block' in *.clif * Automatically rename 'an block' to 'a block' in *.clif * Fix broken testcase when function name length increases Test function names are limited to 16 characters. This causes the new longer name to be truncated and fail a filecheck test. An outdated comment was also fixed.
70 lines
2.4 KiB
Rust
70 lines
2.4 KiB
Rust
//! A Dead-Code Elimination (DCE) pass.
|
|
//!
|
|
//! Dead code here means instructions that have no side effects and have no
|
|
//! result values used by other instructions.
|
|
|
|
use crate::cursor::{Cursor, FuncCursor};
|
|
use crate::dominator_tree::DominatorTree;
|
|
use crate::entity::EntityRef;
|
|
use crate::ir::instructions::InstructionData;
|
|
use crate::ir::{DataFlowGraph, Function, Inst, Opcode};
|
|
use crate::timing;
|
|
|
|
/// Test whether the given opcode is unsafe to even consider for DCE.
|
|
fn trivially_unsafe_for_dce(opcode: Opcode) -> bool {
|
|
opcode.is_call()
|
|
|| opcode.is_branch()
|
|
|| opcode.is_terminator()
|
|
|| opcode.is_return()
|
|
|| opcode.can_trap()
|
|
|| opcode.other_side_effects()
|
|
|| opcode.can_store()
|
|
}
|
|
|
|
/// Preserve instructions with used result values.
|
|
fn any_inst_results_used(inst: Inst, live: &[bool], dfg: &DataFlowGraph) -> bool {
|
|
dfg.inst_results(inst).iter().any(|v| live[v.index()])
|
|
}
|
|
|
|
/// Load instructions without the `notrap` flag are defined to trap when
|
|
/// operating on inaccessible memory, so we can't DCE them even if the
|
|
/// loaded value is unused.
|
|
fn is_load_with_defined_trapping(opcode: Opcode, data: &InstructionData) -> bool {
|
|
if !opcode.can_load() {
|
|
return false;
|
|
}
|
|
match *data {
|
|
InstructionData::StackLoad { .. } => false,
|
|
InstructionData::Load { flags, .. } => !flags.notrap(),
|
|
_ => true,
|
|
}
|
|
}
|
|
|
|
/// Perform DCE on `func`.
|
|
pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) {
|
|
let _tt = timing::dce();
|
|
debug_assert!(domtree.is_valid());
|
|
|
|
let mut live = vec![false; func.dfg.num_values()];
|
|
for &block in domtree.cfg_postorder() {
|
|
let mut pos = FuncCursor::new(func).at_bottom(block);
|
|
while let Some(inst) = pos.prev_inst() {
|
|
{
|
|
let data = &pos.func.dfg[inst];
|
|
let opcode = data.opcode();
|
|
if trivially_unsafe_for_dce(opcode)
|
|
|| is_load_with_defined_trapping(opcode, &data)
|
|
|| any_inst_results_used(inst, &live, &pos.func.dfg)
|
|
{
|
|
for arg in pos.func.dfg.inst_args(inst) {
|
|
let v = pos.func.dfg.resolve_aliases(*arg);
|
|
live[v.index()] = true;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
pos.remove_inst();
|
|
}
|
|
}
|
|
}
|