Skip to content
Merged
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
57 changes: 25 additions & 32 deletions compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl Ssa {
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) fn fold_constants(mut self) -> Ssa {
for function in self.functions.values_mut() {
function.constant_fold(false, None);
function.constant_fold(false, &mut None);
}
self
}
Expand All @@ -62,7 +62,7 @@ impl Ssa {
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) fn fold_constants_using_constraints(mut self) -> Ssa {
for function in self.functions.values_mut() {
function.constant_fold(true, None);
function.constant_fold(true, &mut None);
}
self
}
Expand All @@ -79,9 +79,21 @@ impl Ssa {
brillig_functions.insert(*func_id, cloned_function);
};
}
let mut interpreter = if brillig_functions.is_empty() {
None
} else {
let mut interpreter = Interpreter::new_from_functions(
&brillig_functions,
InterpreterOptions { no_foreign_calls: true, ..Default::default() },
std::io::empty(),
);
// Interpret globals once so that we do not have to repeat this computation on every Brillig call.
interpreter.interpret_globals().expect("ICE: Interpreter failed to interpret globals");
Some(interpreter)
};

for function in self.functions.values_mut() {
function.constant_fold(false, Some(&brillig_functions));
function.constant_fold(false, &mut interpreter);
}

self
Expand All @@ -94,9 +106,9 @@ impl Function {
pub(crate) fn constant_fold(
&mut self,
use_constraint_info: bool,
brillig_info: Option<&BTreeMap<FunctionId, Function>>,
interpreter: &mut Option<Interpreter<Empty>>,
) {
let mut context = Context::new(use_constraint_info, brillig_info);
let mut context = Context::new(use_constraint_info);
let mut dom = DominatorTree::with_function(self);
context.block_queue.push_back(self.entry_block());

Expand All @@ -106,7 +118,7 @@ impl Function {
}

context.visited_blocks.insert(block);
context.fold_constants_in_block(self, &mut dom, block);
context.fold_constants_in_block(self, &mut dom, block, interpreter);
}

#[cfg(debug_assertions)]
Expand All @@ -122,7 +134,7 @@ fn constant_folding_post_check(context: &Context, dfg: &DataFlowGraph) {
);
}

struct Context<'a> {
struct Context {
use_constraint_info: bool,
/// Maps pre-folded ValueIds to the new ValueIds obtained by re-inserting the instruction.
visited_blocks: HashSet<BasicBlockId>,
Expand All @@ -141,8 +153,6 @@ struct Context<'a> {
cached_instruction_results: InstructionResultCache,

values_to_replace: ValueMapping,

interpreter: Option<Interpreter<'a, Empty>>,
}

/// Records a simplified equivalents of an [`Instruction`] in the blocks
Expand Down Expand Up @@ -207,35 +217,15 @@ struct ResultCache {
result: Option<(BasicBlockId, Vec<ValueId>)>,
}

impl<'brillig> Context<'brillig> {
fn new(
use_constraint_info: bool,
brillig_functions: Option<&'brillig BTreeMap<FunctionId, Function>>,
) -> Self {
let interpreter = brillig_functions.and_then(|brillig_functions| {
if brillig_functions.is_empty() {
None
} else {
let mut interpreter = Interpreter::new_from_functions(
brillig_functions,
InterpreterOptions { no_foreign_calls: true, ..Default::default() },
std::io::empty(),
);
// Interpret globals once so that we do not have to repeat this computation on every Brillig call.
interpreter
.interpret_globals()
.expect("ICE: Interpreter failed to interpret globals");
Some(interpreter)
}
});
impl Context {
fn new(use_constraint_info: bool) -> Self {
Self {
use_constraint_info,
visited_blocks: Default::default(),
block_queue: Default::default(),
constraint_simplification_mappings: Default::default(),
cached_instruction_results: Default::default(),
values_to_replace: Default::default(),
interpreter,
}
}

Expand All @@ -244,6 +234,7 @@ impl<'brillig> Context<'brillig> {
function: &mut Function,
dom: &mut DominatorTree,
block_id: BasicBlockId,
interpreter: &mut Option<Interpreter<Empty>>,
) {
let instructions = function.dfg[block_id].take_instructions();

Expand All @@ -261,6 +252,7 @@ impl<'brillig> Context<'brillig> {
block_id,
instruction_id,
&mut side_effects_enabled_var,
interpreter,
);
}

Expand Down Expand Up @@ -305,6 +297,7 @@ impl<'brillig> Context<'brillig> {
mut block: BasicBlockId,
id: InstructionId,
side_effects_enabled_var: &mut ValueId,
interpreter: &mut Option<Interpreter<Empty>>,
) {
let constraint_simplification_mapping = self.get_constraint_map(*side_effects_enabled_var);
let dfg = &mut function.dfg;
Expand Down Expand Up @@ -364,7 +357,7 @@ impl<'brillig> Context<'brillig> {
&instruction,
block,
dfg,
self.interpreter.as_mut(),
interpreter.as_mut(),
)
// Otherwise, try inserting the instruction again to apply any optimizations using the newly resolved inputs.
.unwrap_or_else(|| {
Expand Down
Loading