Skip to content

Commit

Permalink
jumpthreading: Inline jumps
Browse files Browse the repository at this point in the history
  • Loading branch information
afonso360 committed Jun 22, 2024
1 parent cf45229 commit d1ff87d
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 15 deletions.
2 changes: 1 addition & 1 deletion cranelift/codegen/src/flowgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::timing;
use core::mem;

/// A basic block denoted by its enclosing Block and last instruction.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BlockPredecessor {
/// Enclosing Block key.
pub block: Block,
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/inst_predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn is_load_with_defined_trapping(opcode: Opcode, data: &InstructionData) -> bool
/// Does the given instruction have any side-effect that would preclude it from being removed when
/// its value is unused?
#[inline(always)]
fn has_side_effect(func: &Function, inst: Inst) -> bool {
pub(crate) fn has_side_effect(func: &Function, inst: Inst) -> bool {
let data = &func.dfg.insts[inst];
let opcode = data.opcode();
trivially_has_side_effects(opcode) || is_load_with_defined_trapping(opcode, data)
Expand Down
12 changes: 12 additions & 0 deletions cranelift/codegen/src/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,18 @@ impl DataFlowGraph {
self.insts[inst].map_values(&mut self.value_lists, &mut self.jump_tables, body);
}

/// Map a function over the branch destinations of the instruction.
pub fn map_inst_branch_destinations<F>(&mut self, inst: Inst, body: F)
where
F: FnMut(BlockCall, Block, &[Value]) -> BlockCall,
{
self.insts[inst].map_branch_destinations(
&mut self.value_lists,
&mut self.jump_tables,
body,
);
}

/// Overwrite the instruction's value references with values from the iterator.
/// NOTE: the iterator provided is expected to yield at least as many values as the instruction
/// currently has.
Expand Down
28 changes: 26 additions & 2 deletions cranelift/codegen/src/ir/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,18 @@ impl Opcode {
pub fn constraints(self) -> OpcodeConstraints {
OPCODE_CONSTRAINTS[self as usize - 1]
}

/// Test whether the given opcode is unsafe to even consider as side-effect-free.
#[inline(always)]
pub fn trivially_has_side_effects(self) -> bool {
self.is_call()
|| self.is_branch()
|| self.is_terminator()
|| self.is_return()
|| self.can_trap()
|| self.other_side_effects()
|| self.can_store()
}
}

// This trait really belongs in cranelift-reader where it is used by the `.clif` file parser, but since
Expand Down Expand Up @@ -312,8 +324,6 @@ impl InstructionData {
}

/// Get a mutable slice of the destinations of this instruction, if it's a branch.
///
/// `br_table` returns the empty slice.
pub fn branch_destination_mut<'a>(
&'a mut self,
jump_tables: &'a mut ir::JumpTables,
Expand Down Expand Up @@ -353,6 +363,20 @@ impl InstructionData {
}
}

/// Replace the block calls used in this instruction.
pub fn map_branch_destinations(
&mut self,
pool: &mut ValueListPool,
jump_tables: &mut ir::JumpTables,
mut f: impl FnMut(BlockCall, Block, &[Value]) -> BlockCall,
) {
for call in self.branch_destination_mut(jump_tables) {
let block = call.block(pool);
let args = call.args_slice(pool);
*call = f(*call, block, args)
}
}

/// If this is a trapping instruction, get its trap code. Otherwise, return
/// `None`.
pub fn trap_code(&self) -> Option<TrapCode> {
Expand Down
Loading

0 comments on commit d1ff87d

Please sign in to comment.