Skip to content

Commit

Permalink
feat: Sync from noir (#10755)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
chore: Add `Instruction::map_values_mut`
(noir-lang/noir#6756)
chore: Do not print entire functions when running debug trace
(noir-lang/noir#6814)
chore(ci): Active rollup circuits in compilation report
(noir-lang/noir#6813)
feat(ssa): Bring back tracking of RC instructions during DIE
(noir-lang/noir#6783)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <[email protected]>
  • Loading branch information
AztecBot and TomAFrench authored Dec 16, 2024
1 parent 64d5f2b commit 308c5ce
Show file tree
Hide file tree
Showing 14 changed files with 368 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
eb975ab28fb056cf92859377c02f2bb1a608eda3
e88deaf4890a3c6d6af8b0760e952d10573c004d
5 changes: 2 additions & 3 deletions noir/noir-repo/.github/workflows/reports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,8 @@ jobs:
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset }
# TODO: Bring these back once they no longer time out
# - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private }
# - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public }

name: External repo compilation report - ${{ matrix.project.repo }}/${{ matrix.project.path }}
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn optimize<F: AcirField>(acir: Circuit<F>) -> (Circuit<F>, AcirTransformati
/// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`].
///
/// Accepts an injected `acir_opcode_positions` to allow optimizations to be applied in a loop.
#[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir))]
#[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir, acir_opcode_positions))]
pub(super) fn optimize_internal<F: AcirField>(
acir: Circuit<F>,
acir_opcode_positions: Vec<usize>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ impl DependencyContext {
function: &Function,
all_functions: &BTreeMap<FunctionId, Function>,
) {
trace!("processing instructions of block {} of function {}", block, function);
trace!("processing instructions of block {} of function {}", block, function.id());

for instruction in function.dfg[block].instructions() {
let mut arguments = Vec::new();
Expand Down Expand Up @@ -319,11 +319,7 @@ impl DependencyContext {
Value::Function(callee) => match all_functions[&callee].runtime() {
RuntimeType::Brillig(_) => {
// Record arguments/results for each Brillig call for the check
trace!(
"Brillig function {} called at {}",
all_functions[&callee],
instruction
);

self.tainted.insert(
*instruction,
BrilligTaintedIds::new(&arguments, &results),
Expand Down Expand Up @@ -376,7 +372,7 @@ impl DependencyContext {
}
}

trace!("resulting Brillig involved values: {:?}", self.tainted);
trace!("Number tainted Brillig calls: {}", self.tainted.len());
}

/// Every Brillig call not properly constrained should remain in the tainted set
Expand All @@ -392,7 +388,11 @@ impl DependencyContext {
})
.collect();

trace!("making following reports for function {}: {:?}", function.name(), warnings);
trace!(
"making {} under constrained reports for function {}",
warnings.len(),
function.name()
);
warnings
}

Expand All @@ -407,8 +407,6 @@ impl DependencyContext {
/// Check if any of the recorded Brillig calls have been properly constrained
/// by given values after recording partial constraints, if so stop tracking them
fn clear_constrained(&mut self, constrained_values: &[ValueId], function: &Function) {
trace!("attempting to clear Brillig calls constrained by values: {:?}", constrained_values);

// Remove numeric constants
let constrained_values =
constrained_values.iter().filter(|v| function.dfg.get_numeric_constant(**v).is_none());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ impl DataBus {
DataBus { call_data, return_data: self.return_data.map(&mut f) }
}

/// Updates the databus values in place with the provided function
pub(crate) fn map_values_mut(&mut self, mut f: impl FnMut(ValueId) -> ValueId) {
for cd in self.call_data.iter_mut() {
cd.array_id = f(cd.array_id);

// Can't mutate a hashmap's keys so we need to collect into a new one.
cd.index_map = cd.index_map.iter().map(|(k, v)| (f(*k), *v)).collect();
}

if let Some(data) = self.return_data.as_mut() {
*data = f(*data);
}
}

pub(crate) fn call_data_array(&self) -> Vec<(u32, ValueId)> {
self.call_data.iter().map(|cd| (cd.call_data_id, cd.array_id)).collect()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,24 @@ impl<'f> FunctionInserter<'f> {

/// Get an instruction and make sure all the values in it are freshly resolved.
pub(crate) fn map_instruction(&mut self, id: InstructionId) -> (Instruction, CallStack) {
(
self.function.dfg[id].clone().map_values(|id| self.resolve(id)),
self.function.dfg.get_call_stack(id),
)
let mut instruction = self.function.dfg[id].clone();
instruction.map_values_mut(|id| self.resolve(id));
(instruction, self.function.dfg.get_call_stack(id))
}

/// Maps a terminator in place, replacing any ValueId in the terminator with the
/// resolved version of that value id from this FunctionInserter's internal value mapping.
pub(crate) fn map_terminator_in_place(&mut self, block: BasicBlockId) {
let mut terminator = self.function.dfg[block].take_terminator();
terminator.mutate_values(|value| self.resolve(value));
terminator.map_values_mut(|value| self.resolve(value));
self.function.dfg[block].set_terminator(terminator);
}

/// Maps the data bus in place, replacing any ValueId in the data bus with the
/// resolved version of that value id from this FunctionInserter's internal value mapping.
pub(crate) fn map_data_bus_in_place(&mut self) {
let data_bus = self.function.dfg.data_bus.clone();
let data_bus = data_bus.map_values(|value| self.resolve(value));
let mut data_bus = self.function.dfg.data_bus.clone();
data_bus.map_values_mut(|value| self.resolve(value));
self.function.dfg.data_bus = data_bus;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,70 @@ impl Instruction {
}
}

/// Maps each ValueId inside this instruction to a new ValueId in place.
pub(crate) fn map_values_mut(&mut self, mut f: impl FnMut(ValueId) -> ValueId) {
match self {
Instruction::Binary(binary) => {
binary.lhs = f(binary.lhs);
binary.rhs = f(binary.rhs);
}
Instruction::Cast(value, _) => *value = f(*value),
Instruction::Not(value) => *value = f(*value),
Instruction::Truncate { value, bit_size: _, max_bit_size: _ } => {
*value = f(*value);
}
Instruction::Constrain(lhs, rhs, assert_message) => {
*lhs = f(*lhs);
*rhs = f(*rhs);
if let Some(ConstrainError::Dynamic(_, _, payload_values)) = assert_message {
for value in payload_values {
*value = f(*value);
}
}
}
Instruction::Call { func, arguments } => {
*func = f(*func);
for argument in arguments {
*argument = f(*argument);
}
}
Instruction::Allocate => (),
Instruction::Load { address } => *address = f(*address),
Instruction::Store { address, value } => {
*address = f(*address);
*value = f(*value);
}
Instruction::EnableSideEffectsIf { condition } => {
*condition = f(*condition);
}
Instruction::ArrayGet { array, index } => {
*array = f(*array);
*index = f(*index);
}
Instruction::ArraySet { array, index, value, mutable: _ } => {
*array = f(*array);
*index = f(*index);
*value = f(*value);
}
Instruction::IncrementRc { value } => *value = f(*value),
Instruction::DecrementRc { value } => *value = f(*value),
Instruction::RangeCheck { value, max_bit_size: _, assert_message: _ } => {
*value = f(*value);
}
Instruction::IfElse { then_condition, then_value, else_condition, else_value } => {
*then_condition = f(*then_condition);
*then_value = f(*then_value);
*else_condition = f(*else_condition);
*else_value = f(*else_value);
}
Instruction::MakeArray { elements, typ: _ } => {
for element in elements.iter_mut() {
*element = f(*element);
}
}
}
}

/// Applies a function to each input value this instruction holds.
pub(crate) fn for_each_value<T>(&self, mut f: impl FnMut(ValueId) -> T) {
match self {
Expand Down Expand Up @@ -1193,7 +1257,7 @@ impl TerminatorInstruction {
}

/// Mutate each ValueId to a new ValueId using the given mapping function
pub(crate) fn mutate_values(&mut self, mut f: impl FnMut(ValueId) -> ValueId) {
pub(crate) fn map_values_mut(&mut self, mut f: impl FnMut(ValueId) -> ValueId) {
use TerminatorInstruction::*;
match self {
JmpIf { condition, .. } => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ impl<'brillig> Context<'brillig> {
dom: &mut DominatorTree,
constraint_simplification_mapping: &HashMap<ValueId, SimplificationCache>,
) -> Instruction {
let instruction = dfg[instruction_id].clone();
let mut instruction = dfg[instruction_id].clone();

// Alternate between resolving `value_id` in the `dfg` and checking to see if the resolved value
// has been constrained to be equal to some simpler value in the current block.
Expand Down Expand Up @@ -400,9 +400,10 @@ impl<'brillig> Context<'brillig> {
}

// Resolve any inputs to ensure that we're comparing like-for-like instructions.
instruction.map_values(|value_id| {
instruction.map_values_mut(|value_id| {
resolve_cache(block, dfg, dom, constraint_simplification_mapping, value_id)
})
});
instruction
}

/// Pushes a new [`Instruction`] into the [`DataFlowGraph`] which applies any optimizations
Expand Down
Loading

0 comments on commit 308c5ce

Please sign in to comment.