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: Sync from noir #11138

Merged
merged 28 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b590871
[1 changes] feat!: require trait primitive functions/calls to have th…
Jan 9, 2025
a8a7cba
chore: apply sync fixes
Jan 9, 2025
e791a61
Merge branch 'master' into sync-noir
TomAFrench Jan 9, 2025
a240753
.
TomAFrench Jan 9, 2025
5e46b37
.
TomAFrench Jan 9, 2025
e02ffac
Merge branch 'master' into sync-noir
TomAFrench Jan 9, 2025
a95a252
.
TomAFrench Jan 9, 2025
479c38b
[1 changes] fix: require generic trait impls to be in scope to call t…
Jan 10, 2025
e9c5985
chore: apply sync fixes
Jan 10, 2025
271966d
fix: require generic trait impls to be in scope to call them (https:/…
Jan 10, 2025
f93468f
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
273e594
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
cd0972b
[1 changes] feat: unchecked math operations in SSA (https://github.co…
Jan 10, 2025
68ba915
chore: apply sync fixes
Jan 10, 2025
3313783
feat: unchecked math operations in SSA (https://github.com/noir-lang/…
Jan 10, 2025
7db0b11
.
TomAFrench Jan 10, 2025
d7f8bb3
.
TomAFrench Jan 10, 2025
d876b5f
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
2b2f306
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
948aa4d
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
65969cb
Merge branch 'master' into sync-noir
TomAFrench Jan 10, 2025
0f02951
[1 changes] feat: SSA globals in monomorphization and SSA gen (https…
Jan 11, 2025
0ea85f5
chore: apply sync fixes
Jan 11, 2025
d10c025
feat: SSA globals in monomorphization and SSA gen (https://github.co…
Jan 11, 2025
7be7e78
Merge branch 'master' into sync-noir
TomAFrench Jan 11, 2025
19bb8f5
.
TomAFrench Jan 11, 2025
008d474
.
TomAFrench Jan 11, 2025
f435c39
.
TomAFrench Jan 11, 2025
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
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f6ed6aa9f469c719ca47d01e3118f37cedde0f9e
db28cb9ffb710c286b54dbfcf57292ae3dffb03d
4 changes: 2 additions & 2 deletions noir/noir-repo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1892,6 +1892,9 @@ impl<'a> Context<'a> {
Value::Instruction { .. } | Value::Param { .. } => {
unreachable!("ICE: Should have been in cache {value_id} {value:?}")
}
Value::Global(_) => {
unreachable!("ICE: All globals should have been inlined");
}
};
self.ssa_values.insert(value_id, acir_value.clone());
acir_value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,10 @@ impl<'block> BrilligBlock<'block> {
}
}
}
Value::Instruction { .. } | Value::Param { .. } | Value::NumericConstant { .. } => {
Value::Instruction { .. }
| Value::Param { .. }
| Value::NumericConstant { .. }
| Value::Global(_) => {
unreachable!("unsupported function call type {:?}", dfg[*func])
}
},
Expand Down Expand Up @@ -795,7 +798,7 @@ impl<'block> BrilligBlock<'block> {
self.brillig_context.deallocate_register(rc_register);
}
Instruction::EnableSideEffectsIf { .. } => {
todo!("enable_side_effects not supported by brillig")
unreachable!("enable_side_effects not supported by brillig")
}
Instruction::IfElse { .. } => {
unreachable!("IfElse instructions should not be possible in brillig")
Expand Down Expand Up @@ -1557,6 +1560,9 @@ impl<'block> BrilligBlock<'block> {
let value = &dfg[value_id];

match value {
Value::Global(_) => {
unreachable!("ICE: All globals should have been inlined");
}
Value::Param { .. } | Value::Instruction { .. } => {
// All block parameters and instruction results should have already been
// converted to registers so we fetch from the cache.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ pub(crate) fn collect_variables_of_value(
let value = &dfg[value_id];

match value {
Value::Instruction { .. } | Value::Param { .. } | Value::NumericConstant { .. } => {
Some(value_id)
}
Value::Instruction { .. }
| Value::Param { .. }
| Value::NumericConstant { .. }
| Value::Global(_) => Some(value_id),
// Functions are not variables in a defunctionalized SSA. Only constant function values should appear.
Value::ForeignFunction(_) | Value::Function(_) | Value::Intrinsic(..) => None,
}
Expand Down
2 changes: 1 addition & 1 deletion noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ impl SsaBuilder {
let ssa_path = emit_ssa.with_extension("ssa.json");
write_to_file(&serde_json::to_vec(&ssa).unwrap(), &ssa_path);
}
Ok(SsaBuilder { ssa_logging, print_codegen_timings, ssa }.print("Initial SSA:"))
Ok(SsaBuilder { ssa_logging, print_codegen_timings, ssa }.print("Initial SSA"))
}

fn finish(self) -> Ssa {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ impl DependencyContext {
}
Value::Instruction { .. }
| Value::NumericConstant { .. }
| Value::Param { .. } => {
| Value::Param { .. }
| Value::Global(_) => {
panic!(
"calling non-function value with ID {func_id} in function {}",
function.name()
Expand Down Expand Up @@ -618,7 +619,8 @@ impl Context {
}
Value::Instruction { .. }
| Value::NumericConstant { .. }
| Value::Param { .. } => {
| Value::Param { .. }
| Value::Global(_) => {
panic!("At the point we are running disconnect there shouldn't be any other values as arguments")
}
}
Expand Down
22 changes: 20 additions & 2 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use iter_extended::vecmap;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::DisplayFromStr;
use tracing::warn;

/// The DataFlowGraph contains most of the actual data in a function including
/// its blocks, instructions, and values. This struct is largely responsible for
Expand Down Expand Up @@ -181,7 +182,16 @@ impl DataFlowGraph {

/// Check if the function runtime would simply ignore this instruction.
pub(crate) fn is_handled_by_runtime(&self, instruction: &Instruction) -> bool {
!(self.runtime().is_acir() && instruction.is_brillig_only())
match self.runtime() {
RuntimeType::Acir(_) => !matches!(
instruction,
Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. }
),
RuntimeType::Brillig(_) => !matches!(
instruction,
Instruction::EnableSideEffectsIf { .. } | Instruction::IfElse { .. }
),
}
}

fn insert_instruction_without_simplification(
Expand All @@ -205,7 +215,7 @@ impl DataFlowGraph {
call_stack: CallStackId,
) -> InsertInstructionResult {
if !self.is_handled_by_runtime(&instruction_data) {
return InsertInstructionResult::InstructionRemoved;
panic!("Attempted to insert instruction not handled by runtime: {instruction_data:?}");
}

let id = self.insert_instruction_without_simplification(
Expand All @@ -228,6 +238,7 @@ impl DataFlowGraph {
call_stack: CallStackId,
) -> InsertInstructionResult {
if !self.is_handled_by_runtime(&instruction) {
warn!("Attempted to insert instruction not handled by runtime: {instruction:?}");
return InsertInstructionResult::InstructionRemoved;
}

Expand Down Expand Up @@ -326,6 +337,10 @@ impl DataFlowGraph {
id
}

pub(crate) fn make_global(&mut self, typ: Type) -> ValueId {
self.values.insert(Value::Global(typ))
}

/// Gets or creates a ValueId for the given FunctionId.
pub(crate) fn import_function(&mut self, function: FunctionId) -> ValueId {
if let Some(existing) = self.functions.get(&function) {
Expand Down Expand Up @@ -614,6 +629,9 @@ impl DataFlowGraph {
}
_ => false,
},
// TODO: Make this true and handle instruction simplifications with globals.
// Currently all globals are inlined as a temporary measure so this is fine to have as false.
Value::Global(_) => false,
_ => true,
}
}
Expand Down
22 changes: 12 additions & 10 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) struct Function {
/// Name of the function for debugging only
name: String,

id: FunctionId,
id: Option<FunctionId>,

/// The DataFlowGraph holds the majority of data pertaining to the function
/// including its blocks, instructions, and values.
Expand All @@ -90,14 +90,22 @@ impl Function {
pub(crate) fn new(name: String, id: FunctionId) -> Self {
let mut dfg = DataFlowGraph::default();
let entry_block = dfg.make_block();
Self { name, id, entry_block, dfg }
Self { name, id: Some(id), entry_block, dfg }
}

/// Globals are generated using the same codegen process as functions.
/// To avoid a recursive global context we should create a pseudo function to mock a globals context.
pub(crate) fn new_for_globals() -> Self {
let mut dfg = DataFlowGraph::default();
let entry_block = dfg.make_block();
Self { name: "globals".to_owned(), id: None, entry_block, dfg }
}

/// Creates a new function as a clone of the one passed in with the passed in id.
pub(crate) fn clone_with_id(id: FunctionId, another: &Function) -> Self {
let dfg = another.dfg.clone();
let entry_block = another.entry_block;
Self { name: another.name.clone(), id, entry_block, dfg }
Self { name: another.name.clone(), id: Some(id), entry_block, dfg }
}

/// Takes the signature (function name & runtime) from a function but does not copy the body.
Expand All @@ -115,7 +123,7 @@ impl Function {

/// The id of the function.
pub(crate) fn id(&self) -> FunctionId {
self.id
self.id.expect("FunctionId should be initialized")
}

/// Runtime type of the function.
Expand Down Expand Up @@ -228,12 +236,6 @@ pub(crate) struct Signature {
pub(crate) returns: Vec<Type>,
}

impl std::fmt::Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
super::printer::display_function(self, f)
}
}

#[test]
fn sign_smoke() {
let mut signature = Signature::default();
Expand Down
71 changes: 57 additions & 14 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! This file is for pretty-printing the SSA IR in a human-readable form for debugging.
use std::fmt::{Formatter, Result};
use std::fmt::{Display, Formatter, Result};

use acvm::acir::AcirField;
use im::Vector;
use iter_extended::vecmap;

use crate::ssa::ir::types::{NumericType, Type};
use crate::ssa::{
ir::types::{NumericType, Type},
Ssa,
};

use super::{
basic_block::BasicBlockId,
Expand All @@ -15,8 +18,42 @@ use super::{
value::{Value, ValueId},
};

impl Display for Ssa {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
for (id, global_value) in self.globals.dfg.values_iter() {
match global_value {
Value::NumericConstant { constant, typ } => {
writeln!(f, "g{} = {typ} {constant}", id.to_u32())?;
}
Value::Instruction { instruction, .. } => {
display_instruction(&self.globals.dfg, *instruction, true, f)?;
}
Value::Global(_) => {
panic!("Value::Global should only be in the function dfg");
}
_ => panic!("Expected only numeric constant or instruction"),
};
}

if self.globals.dfg.values_iter().len() > 0 {
writeln!(f)?;
}

for function in self.functions.values() {
writeln!(f, "{function}")?;
}
Ok(())
}
}

impl Display for Function {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
display_function(self, f)
}
}

/// Helper function for Function's Display impl to pretty-print the function with the given formatter.
pub(crate) fn display_function(function: &Function, f: &mut Formatter) -> Result {
fn display_function(function: &Function, f: &mut Formatter) -> Result {
writeln!(f, "{} fn {} {} {{", function.runtime(), function.name(), function.id())?;
for block_id in function.reachable_blocks() {
display_block(&function.dfg, block_id, f)?;
Expand All @@ -25,17 +62,13 @@ pub(crate) fn display_function(function: &Function, f: &mut Formatter) -> Result
}

/// Display a single block. This will not display the block's successors.
pub(crate) fn display_block(
dfg: &DataFlowGraph,
block_id: BasicBlockId,
f: &mut Formatter,
) -> Result {
fn display_block(dfg: &DataFlowGraph, block_id: BasicBlockId, f: &mut Formatter) -> Result {
let block = &dfg[block_id];

writeln!(f, " {}({}):", block_id, value_list_with_types(dfg, block.parameters()))?;

for instruction in block.instructions() {
display_instruction(dfg, *instruction, f)?;
display_instruction(dfg, *instruction, false, f)?;
}

display_terminator(dfg, block.terminator(), f)
Expand All @@ -53,6 +86,9 @@ fn value(dfg: &DataFlowGraph, id: ValueId) -> String {
Value::Intrinsic(intrinsic) => intrinsic.to_string(),
Value::ForeignFunction(function) => function.clone(),
Value::Param { .. } | Value::Instruction { .. } => id.to_string(),
Value::Global(_) => {
format!("g{}", id.to_u32())
}
}
}

Expand All @@ -72,7 +108,7 @@ fn value_list(dfg: &DataFlowGraph, values: &[ValueId]) -> String {
}

/// Display a terminator instruction
pub(crate) fn display_terminator(
fn display_terminator(
dfg: &DataFlowGraph,
terminator: Option<&TerminatorInstruction>,
f: &mut Formatter,
Expand Down Expand Up @@ -107,17 +143,24 @@ pub(crate) fn display_terminator(
}

/// Display an arbitrary instruction
pub(crate) fn display_instruction(
fn display_instruction(
dfg: &DataFlowGraph,
instruction: InstructionId,
in_global_space: bool,
f: &mut Formatter,
) -> Result {
// instructions are always indented within a function
write!(f, " ")?;
if !in_global_space {
// instructions are always indented within a function
write!(f, " ")?;
}

let results = dfg.instruction_results(instruction);
if !results.is_empty() {
write!(f, "{} = ", value_list(dfg, results))?;
let mut value_list = value_list(dfg, results);
if in_global_space {
value_list = value_list.replace('v', "g");
}
write!(f, "{} = ", value_list)?;
}

display_instruction_inner(dfg, &dfg[instruction], results, f)
Expand Down
4 changes: 4 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ pub(crate) enum Value {
/// ForeignFunction's always have the type Type::Function and have similar semantics to Function,
/// other than generating different backend operations and being only accessible through Brillig.
ForeignFunction(String),

/// This Value indicates we have a reserved slot that needs to be accessed in a separate global context
Global(Type),
}

impl Value {
Expand All @@ -64,6 +67,7 @@ impl Value {
Value::Function { .. } | Value::Intrinsic { .. } | Value::ForeignFunction { .. } => {
Cow::Owned(Type::Function)
}
Value::Global(typ) => Cow::Borrowed(typ),
}
}
}
Loading
Loading