Skip to content

Commit 37683cc

Browse files
committed
cranelift-frontend: Propagate needs-stack-map from variables to values during finalization
Rather than trying to propagate the needs-stack-map bit from variables to values online, while we are building the IR and defining and using variables, wait until the function is being finalized, and then propagate everything all at once. This avoids potential repeated work and is easier to ensure that it is complete and covers all values associated with a variable, since by the time we are finalizing the function, we won't add any new values for a variable that we will need to keep track of and propagate this information to. This also means that we can remove the `params_added_to_blocks` vector from the SSA side effects structure, since it was only used to online-update the `stack_map_values` set.
1 parent 3f53021 commit 37683cc

File tree

3 files changed

+23
-31
lines changed

3 files changed

+23
-31
lines changed

cranelift/frontend/src/frontend.rs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,6 @@ impl<'a> FunctionBuilder<'a> {
473473
};
474474
self.handle_ssa_side_effects(side_effects);
475475

476-
// If the variable was declared as needing stack maps, then we should
477-
// have propagated that to the value as well.
478-
if cfg!(debug_assertions) && self.func_ctx.stack_map_vars.contains(var) {
479-
assert!(self.func_ctx.stack_map_values.contains(val));
480-
}
481-
482476
Ok(val)
483477
}
484478

@@ -494,6 +488,8 @@ impl<'a> FunctionBuilder<'a> {
494488
/// an error if the value supplied does not match the type the variable was
495489
/// declared to have.
496490
pub fn try_def_var(&mut self, var: Variable, val: Value) -> Result<(), DefVariableError> {
491+
log::trace!("try_def_var: {var:?} = {val:?}");
492+
497493
let var_ty = *self
498494
.func_ctx
499495
.types
@@ -503,11 +499,6 @@ impl<'a> FunctionBuilder<'a> {
503499
return Err(DefVariableError::TypeMismatch(var, val));
504500
}
505501

506-
// If `var` needs inclusion in stack maps, then `val` does too.
507-
if self.func_ctx.stack_map_vars.contains(var) {
508-
self.declare_value_needs_stack_map(val);
509-
}
510-
511502
self.func_ctx.ssa.def_var(var, val, self.position.unwrap());
512503
Ok(())
513504
}
@@ -720,6 +711,18 @@ impl<'a> FunctionBuilder<'a> {
720711
}
721712
}
722713

714+
// Propagate the needs-stack-map bit from variables to each of their
715+
// associated values.
716+
for var in self.func_ctx.stack_map_vars.keys() {
717+
for val in self.func_ctx.ssa.values_for_var(var) {
718+
debug_assert_eq!(self.func.dfg.value_type(val), self.func_ctx.types[var]);
719+
self.func_ctx.stack_map_values.insert(val);
720+
}
721+
}
722+
723+
// If we have any values that need inclusion in stack maps, then we need
724+
// to run our pass to spill those values to the stack at safepoints and
725+
// generate stack maps.
723726
if !self.func_ctx.stack_map_values.is_empty() {
724727
self.func_ctx
725728
.safepoints
@@ -1180,24 +1183,13 @@ impl<'a> FunctionBuilder<'a> {
11801183
fn handle_ssa_side_effects(&mut self, side_effects: SideEffects) {
11811184
let SideEffects {
11821185
instructions_added_to_blocks,
1183-
params_added_to_blocks,
11841186
} = side_effects;
11851187

11861188
for modified_block in instructions_added_to_blocks {
11871189
if self.is_pristine(modified_block) {
11881190
self.func_ctx.status[modified_block] = BlockStatus::Partial;
11891191
}
11901192
}
1191-
1192-
// Propagate needs-inclusion-in-stack-maps metadata from variables to
1193-
// their block parameter SSA values.
1194-
if !self.func_ctx.stack_map_vars.is_empty() {
1195-
for (val, var) in params_added_to_blocks {
1196-
if self.func_ctx.stack_map_vars.contains(var) {
1197-
self.func_ctx.stack_map_values.insert(val);
1198-
}
1199-
}
1200-
}
12011193
}
12021194
}
12031195

cranelift/frontend/src/ssa.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,14 @@ pub struct SideEffects {
6767
/// This field signals if it is the case and return the `Block` to which the initialization has
6868
/// been added.
6969
pub instructions_added_to_blocks: Vec<Block>,
70-
71-
/// When a variable does not have a single, dominating definition of a use,
72-
/// we must insert block parameters to control-flow join points. This field
73-
/// contains all of the block parameters we inserted, along with the
74-
/// variable that they are associated with.
75-
pub params_added_to_blocks: Vec<(Value, Variable)>,
7670
}
7771

7872
impl SideEffects {
7973
fn is_empty(&self) -> bool {
8074
let Self {
8175
instructions_added_to_blocks,
82-
params_added_to_blocks,
8376
} = self;
84-
instructions_added_to_blocks.is_empty() && params_added_to_blocks.is_empty()
77+
instructions_added_to_blocks.is_empty()
8578
}
8679
}
8780

@@ -195,6 +188,12 @@ fn emit_zero(ty: Type, mut cur: FuncCursor) -> Value {
195188
/// Phi functions.
196189
///
197190
impl SSABuilder {
191+
/// Get all of the values associated with the given variable that we have
192+
/// inserted in the function thus far.
193+
pub fn values_for_var(&self, var: Variable) -> impl Iterator<Item = Value> + '_ {
194+
self.variables[var].values().filter_map(|v| v.expand())
195+
}
196+
198197
/// Declares a new definition of a variable in a given basic block.
199198
/// The SSA value is passed as an argument because it should be created with
200199
/// `ir::DataFlowGraph::append_result`.
@@ -318,7 +317,6 @@ impl SSABuilder {
318317
// find a usable definition. So create one.
319318
let val = func.dfg.append_block_param(block, ty);
320319
var_defs[block] = PackedOption::from(val);
321-
self.side_effects.params_added_to_blocks.push((val, var));
322320

323321
// Now every predecessor needs to pass its definition of this variable to the newly added
324322
// block parameter. To do that we have to "recursively" call `use_var`, but there are two

fuzz/fuzz_targets/cranelift-icache.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub struct FunctionWithIsa {
4343

4444
impl FunctionWithIsa {
4545
pub fn generate(u: &mut Unstructured) -> anyhow::Result<Self> {
46+
let _ = env_logger::try_init();
47+
4648
// We filter out targets that aren't supported in the current build
4749
// configuration after randomly choosing one, instead of randomly choosing
4850
// a supported one, so that the same fuzz input works across different build

0 commit comments

Comments
 (0)