Skip to content
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
6 changes: 6 additions & 0 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ pub struct CompileOptions {
#[arg(long, hide = true)]
pub show_ssa_pass: Vec<String>,

/// Do not print an SSA pass if it didn't produce changes.
#[arg(long, hide = true)]
pub hide_unchanged_ssa: bool,

/// Emit source file locations when emitting debug information for the SSA IR to stdout.
/// By default, source file locations won't be shown.
#[arg(long, hide = true)]
Expand Down Expand Up @@ -232,6 +236,7 @@ impl Default for CompileOptions {
force_compile: false,
show_ssa: false,
show_ssa_pass: Vec::new(),
hide_unchanged_ssa: false,
with_ssa_locations: false,
show_contract_fn: None,
skip_ssa_pass: Vec::new(),
Expand Down Expand Up @@ -296,6 +301,7 @@ impl CompileOptions {
max_bytecode_increase_percent: self.max_bytecode_increase_percent,
force_unroll_threshold: self.force_unroll_threshold,
skip_passes: self.skip_ssa_pass.clone(),
ssa_logging_hide_unchanged: self.hide_unchanged_ssa,
}
}
}
Expand Down
33 changes: 31 additions & 2 deletions compiler/noirc_evaluator/src/ssa/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ pub struct SsaBuilder<'local> {
ssa: Ssa,
/// Options to control which SSA passes to print.
ssa_logging: SsaLogging,
/// Whether to skip printing an SSA pass if it didn't produce any changes.
ssa_logging_hide_unchanged: bool,
/// Records the last SSA printed. This is used to avoid printing the result of an
/// SSA pass if it didn't produce any changes compared to the previous SSA.
last_ssa_printed: Option<String>,
/// Whether to print the amount of time it took to run individual SSA passes.
print_codegen_timings: bool,
/// Counters indexed by the message in the SSA pass, so we can distinguish between multiple
Expand All @@ -94,6 +99,7 @@ impl<'local> SsaBuilder<'local> {
pub fn from_program(
program: Program,
ssa_logging: SsaLogging,
ssa_logging_hide_unchanged: bool,
print_codegen_timings: bool,
emit_ssa: &Option<PathBuf>,
files: Option<&'local fm::FileManager>,
Expand All @@ -108,17 +114,27 @@ impl<'local> SsaBuilder<'local> {
let ssa_path = emit_ssa.with_extension("ssa.json");
write_to_file(&serde_json::to_vec(&ssa).unwrap(), &ssa_path);
}
Ok(Self::from_ssa(ssa, ssa_logging, print_codegen_timings, files).print("Initial SSA"))
Ok(Self::from_ssa(
ssa,
ssa_logging,
ssa_logging_hide_unchanged,
print_codegen_timings,
files,
)
.print("Initial SSA"))
}

pub fn from_ssa(
ssa: Ssa,
ssa_logging: SsaLogging,
ssa_logging_hide_unchanged: bool,
print_codegen_timings: bool,
files: Option<&'local fm::FileManager>,
) -> Self {
Self {
ssa_logging,
ssa_logging_hide_unchanged,
last_ssa_printed: None,
print_codegen_timings,
ssa,
files,
Expand Down Expand Up @@ -193,7 +209,20 @@ impl<'local> SsaBuilder<'local> {
}

if print_ssa_pass {
println_to_stdout!("After {msg}:\n{}", self.ssa.print_with(self.files));
let printed_ssa = format!("{}", self.ssa.print_with(self.files));
let skip_print = self.ssa_logging_hide_unchanged
&& self
.last_ssa_printed
.as_ref()
.is_some_and(|last_ssa_printed| last_ssa_printed == &printed_ssa);

if !skip_print {
println_to_stdout!("After {msg}:\n{printed_ssa}");
}

if self.ssa_logging_hide_unchanged {
self.last_ssa_printed = Some(printed_ssa);
}
}
self
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/noirc_evaluator/src/ssa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub struct SsaEvaluatorOptions {
/// Emit debug information for the intermediate SSA IR
pub ssa_logging: SsaLogging,

/// Whether to skip printing an SSA pass if it didn't produce any changes.
pub ssa_logging_hide_unchanged: bool,

/// Options affecting Brillig code generation.
pub brillig_options: BrilligOptions,

Expand Down Expand Up @@ -376,6 +379,7 @@ pub fn optimize_into_acir(
let builder = SsaBuilder::from_program(
program,
options.ssa_logging.clone(),
options.ssa_logging_hide_unchanged,
options.print_codegen_timings,
&options.emit_ssa,
files,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ mod tests {
max_bytecode_increase_percent: None,
force_unroll_threshold: FORCE_UNROLL_THRESHOLD,
skip_passes: Vec::new(),
ssa_logging_hide_unchanged: false,
};
let pipeline = primary_passes(&options);
for pass in pipeline {
Expand Down
9 changes: 8 additions & 1 deletion compiler/noirc_evaluator/src/ssa/opt/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,16 @@ mod tests {
max_bytecode_increase_percent: None,
force_unroll_threshold: FORCE_UNROLL_THRESHOLD,
skip_passes: Default::default(),
ssa_logging_hide_unchanged: false,
};

let builder = SsaBuilder::from_ssa(ssa, options.ssa_logging.clone(), false, None);
let builder = SsaBuilder::from_ssa(
ssa,
options.ssa_logging.clone(),
options.ssa_logging_hide_unchanged,
false,
None,
);
Ok(builder.run_passes(&primary_passes(options))?.finish())
}

Expand Down
1 change: 1 addition & 0 deletions tooling/ast_fuzzer/fuzz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub fn default_ssa_options() -> SsaEvaluatorOptions {
max_bytecode_increase_percent: None,
force_unroll_threshold: FORCE_UNROLL_THRESHOLD,
skip_passes: Default::default(),
ssa_logging_hide_unchanged: false,
}
}

Expand Down
1 change: 1 addition & 0 deletions tooling/ast_fuzzer/tests/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ fn arb_ssa_roundtrip() {
max_bytecode_increase_percent: None,
force_unroll_threshold: FORCE_UNROLL_THRESHOLD,
skip_passes: Default::default(),
ssa_logging_hide_unchanged: false,
};
let pipeline = primary_passes(&options);
let last_pass = u.choose_index(pipeline.len())?;
Expand Down
1 change: 1 addition & 0 deletions tooling/ast_fuzzer/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ fn arb_program_can_be_executed() {
max_bytecode_increase_percent: None,
force_unroll_threshold: FORCE_UNROLL_THRESHOLD,
skip_passes: Default::default(),
ssa_logging_hide_unchanged: false,
};

// Print the AST if something goes wrong, then panic.
Expand Down
54 changes: 44 additions & 10 deletions tooling/nargo_cli/src/cli/interpret_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ pub(crate) fn run(args: InterpretCommand, workspace: Workspace) -> Result<(), Cl
};
let file_manager =
if args.compile_options.with_ssa_locations { Some(&file_manager) } else { None };
let mut last_ssa_printed: Option<String> = None;

is_ok &= print_and_interpret_ssa(
ssa_options,
Expand All @@ -150,6 +151,7 @@ pub(crate) fn run(args: InterpretCommand, workspace: Workspace) -> Result<(), Cl
&ssa_return,
interpreter_options,
file_manager,
&mut last_ssa_printed,
)?;

// Run SSA passes in the pipeline and interpret the ones we are interested in.
Expand All @@ -173,6 +175,7 @@ pub(crate) fn run(args: InterpretCommand, workspace: Workspace) -> Result<(), Cl
&ssa_return,
interpreter_options,
file_manager,
&mut last_ssa_printed,
)?;
}
}
Expand Down Expand Up @@ -238,15 +241,41 @@ fn msg_matches(patterns: &[String], msg: &str) -> bool {
patterns.iter().any(|p| msg.contains(&p.to_lowercase()))
}

fn print_ssa(options: &SsaEvaluatorOptions, ssa: &mut Ssa, msg: &str, fm: Option<&FileManager>) {
let print = match options.ssa_logging {
SsaLogging::All => true,
SsaLogging::None => false,
SsaLogging::Contains(ref ps) => msg_matches(ps, msg),
};
if print {
/// Prints the SSA (if it needs to be printed) and returns whether the SSA needs
/// to be interpreted afterwards (it doesn't need to if the SSA passes are being
/// printed and the user asked to skip SSA passes that don't produce changes).
fn print_ssa(
options: &SsaEvaluatorOptions,
ssa: &mut Ssa,
msg: &str,
files: Option<&FileManager>,
last_ssa_printed: &mut Option<String>,
) -> bool {
let print_ssa_pass = options.ssa_logging.matches(msg);

// Always normalize if we are going to print at least one of the passes
if !matches!(options.ssa_logging, SsaLogging::None) {
ssa.normalize_ids();
println!("After {msg}:\n{}", ssa.print_with(fm));
}

if print_ssa_pass {
let printed_ssa = format!("{}", ssa.print_with(files));
let skip_print = options.ssa_logging_hide_unchanged
&& last_ssa_printed
.as_ref()
.is_some_and(|last_ssa_printed| last_ssa_printed == &printed_ssa);

if !skip_print {
println!("After {msg}:\n{printed_ssa}");
}

if options.ssa_logging_hide_unchanged {
*last_ssa_printed = Some(printed_ssa);
}

!skip_print
} else {
true
}
}

Expand Down Expand Up @@ -305,9 +334,14 @@ fn print_and_interpret_ssa(
return_value: &Option<Vec<Value>>,
interpreter_options: InterpreterOptions,
fm: Option<&FileManager>,
last_ssa_printed: &mut Option<String>,
) -> Result<bool, CliError> {
print_ssa(options, ssa, msg, fm);
interpret_ssa(passes_to_interpret, ssa, msg, args, return_value, interpreter_options)
let must_interpret = print_ssa(options, ssa, msg, fm, last_ssa_printed);
if must_interpret {
interpret_ssa(passes_to_interpret, ssa, msg, args, return_value, interpreter_options)
} else {
Ok(true)
}
}

fn flatten_databus_values(values: Vec<Value>) -> Vec<Value> {
Expand Down
2 changes: 2 additions & 0 deletions tooling/ssa_executor/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ pub fn optimize_ssa_into_acir(
}));
let result = std::panic::catch_unwind(AssertUnwindSafe(|| {
validate_ssa(&ssa);

let builder = SsaBuilder::from_ssa(
ssa,
options.ssa_logging.clone(),
options.ssa_logging_hide_unchanged,
options.print_codegen_timings,
None,
);
Expand Down
12 changes: 11 additions & 1 deletion tooling/ssa_verification/src/acir_instruction_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,16 @@ impl InstructionArtifacts {
/// Converts SSA to ACIR program
fn ssa_to_acir_program(ssa: Ssa) -> AcirProgram<FieldElement> {
// third brillig names, fourth errors
let builder = SsaBuilder::from_ssa(ssa, SsaLogging::None, false, None);
let ssa_logging_hide_unchanged = false;
let print_codegen_timings = false;
let files = None;
let builder = SsaBuilder::from_ssa(
ssa,
SsaLogging::None,
ssa_logging_hide_unchanged,
print_codegen_timings,
files,
);
let ssa_evaluator_options = SsaEvaluatorOptions {
ssa_logging: SsaLogging::None,
print_codegen_timings: false,
Expand All @@ -250,6 +259,7 @@ fn ssa_to_acir_program(ssa: Ssa) -> AcirProgram<FieldElement> {
brillig_options: BrilligOptions::default(),
enable_brillig_constraints_check_lookback: false,
skip_passes: vec![],
ssa_logging_hide_unchanged: false,
};
let (acir_functions, brillig, _) = match optimize_ssa_builder_into_acir(
builder,
Expand Down
Loading