Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bubble up Instruction::Constrains to be applied as early as possible. #4065

Merged
merged 4 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub(crate) fn optimize_into_acir(
.run_pass(Ssa::mem2reg, "After Mem2Reg:")
.run_pass(Ssa::fold_constants, "After Constant Folding:")
.run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:")
.run_pass(Ssa::bubble_up_constrains, "After Constraint Bubbling:")
.finish();

let brillig = ssa.to_brillig(print_brillig_trace);
Expand Down
43 changes: 43 additions & 0 deletions compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::ssa::{ir::instruction::Instruction, ssa_gen::Ssa};

impl Ssa {
/// A simple SSA pass to go through each instruction and move every `Instruction::Constrain` to immediately
/// after when all of its inputs are available.
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) fn bubble_up_constrains(mut self) -> Ssa {
for function in self.functions.values_mut() {
for block in function.reachable_blocks() {
let instructions = function.dfg[block].take_instructions();
let mut filtered_instructions = Vec::with_capacity(instructions.len());

let dfg = &function.dfg;
for instruction in instructions {
let (lhs, rhs) = match dfg[instruction] {
Instruction::Constrain(lhs, rhs, ..) => (lhs, rhs),
_ => {
filtered_instructions.push(instruction);
continue;
}
};

let index = filtered_instructions
.iter()
.rev()
.position(|instruction_id| {
let results = dfg.instruction_results(*instruction_id).to_vec();
results.contains(&lhs) || results.contains(&rhs)
})
// We iterate through the previous instructions in reverse order so the index is from the
// back of the vector. Subtract from vector length to get correct index.
.map(|reversed_index| filtered_instructions.len() - reversed_index)
.unwrap_or(filtered_instructions.len());

filtered_instructions.insert(index, instruction);
}

*function.dfg[block].instructions_mut() = filtered_instructions;
}
}
self
}
}
1 change: 1 addition & 0 deletions compiler/noirc_evaluator/src/ssa/opt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! Generally, these passes are also expected to minimize the final amount of instructions.
mod array_use;
mod assert_constant;
mod bubble_up_constrains;
mod constant_folding;
mod defunctionalize;
mod die;
Expand Down
Loading