Skip to content

Commit fbf0638

Browse files
committed
merge w/ master
2 parents c43b9e6 + f19344c commit fbf0638

File tree

26 files changed

+567
-140
lines changed

26 files changed

+567
-140
lines changed

.aztec-sync-commit

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
249e50efafd306fa8cd9005972636adbddbca81e
1+
05cc59fd28b4d0ee89343106e538c0db0e70f52f

.gitattributes

-1
This file was deleted.

compiler/noirc_evaluator/src/brillig/brillig_gen.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub(crate) mod brillig_block_variables;
44
pub(crate) mod brillig_directive;
55
pub(crate) mod brillig_fn;
66
pub(crate) mod brillig_slice_ops;
7+
mod constant_allocation;
78
mod variable_liveness;
89

910
use acvm::FieldElement;

compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs

+47-25
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::sync::Arc;
2929
use super::brillig_black_box::convert_black_box_call;
3030
use super::brillig_block_variables::BlockVariables;
3131
use super::brillig_fn::FunctionContext;
32+
use super::constant_allocation::InstructionLocation;
3233

3334
/// Generate the compilation artifacts for compiling a function into brillig bytecode.
3435
pub(crate) struct BrilligBlock<'block> {
@@ -117,6 +118,13 @@ impl<'block> BrilligBlock<'block> {
117118
terminator_instruction: &TerminatorInstruction,
118119
dfg: &DataFlowGraph,
119120
) {
121+
self.initialize_constants(
122+
&self
123+
.function_context
124+
.constant_allocation
125+
.allocated_at_location(self.block_id, InstructionLocation::Terminator),
126+
dfg,
127+
);
120128
match terminator_instruction {
121129
TerminatorInstruction::JmpIf {
122130
condition,
@@ -244,6 +252,13 @@ impl<'block> BrilligBlock<'block> {
244252
let instruction = &dfg[instruction_id];
245253
self.brillig_context.set_call_stack(dfg.get_call_stack(instruction_id));
246254

255+
self.initialize_constants(
256+
&self.function_context.constant_allocation.allocated_at_location(
257+
self.block_id,
258+
InstructionLocation::Instruction(instruction_id),
259+
),
260+
dfg,
261+
);
247262
match instruction {
248263
Instruction::Binary(binary) => {
249264
let result_var = self.variables.define_single_addr_variable(
@@ -768,9 +783,6 @@ impl<'block> BrilligBlock<'block> {
768783
.brillig_context
769784
.codegen_pre_call_save_registers_prep_args(&argument_registers, &variables_to_save);
770785

771-
// We don't save and restore constants, so we dump them before a external call since the callee might use the registers where they are allocated.
772-
self.variables.dump_constants();
773-
774786
// Call instruction, which will interpret above registers 0..num args
775787
self.brillig_context.add_external_call_instruction(func_id);
776788

@@ -1512,6 +1524,12 @@ impl<'block> BrilligBlock<'block> {
15121524
}
15131525
}
15141526

1527+
fn initialize_constants(&mut self, constants: &[ValueId], dfg: &DataFlowGraph) {
1528+
for &constant_id in constants {
1529+
self.convert_ssa_value(constant_id, dfg);
1530+
}
1531+
}
1532+
15151533
/// Converts an SSA `ValueId` into a `RegisterOrMemory`. Initializes if necessary.
15161534
fn convert_ssa_value(&mut self, value_id: ValueId, dfg: &DataFlowGraph) -> BrilligVariable {
15171535
let value_id = dfg.resolve(value_id);
@@ -1527,23 +1545,31 @@ impl<'block> BrilligBlock<'block> {
15271545
Value::NumericConstant { constant, .. } => {
15281546
// Constants might have been converted previously or not, so we get or create and
15291547
// (re)initialize the value inside.
1530-
if let Some(variable) = self.variables.get_constant(value_id, dfg) {
1531-
variable
1548+
if self.variables.is_allocated(&value_id) {
1549+
self.variables.get_allocation(self.function_context, value_id, dfg)
15321550
} else {
1533-
let new_variable =
1534-
self.variables.allocate_constant(self.brillig_context, value_id, dfg);
1551+
let new_variable = self.variables.define_variable(
1552+
self.function_context,
1553+
self.brillig_context,
1554+
value_id,
1555+
dfg,
1556+
);
15351557

15361558
self.brillig_context
15371559
.const_instruction(new_variable.extract_single_addr(), *constant);
15381560
new_variable
15391561
}
15401562
}
15411563
Value::Array { array, typ } => {
1542-
if let Some(variable) = self.variables.get_constant(value_id, dfg) {
1543-
variable
1564+
if self.variables.is_allocated(&value_id) {
1565+
self.variables.get_allocation(self.function_context, value_id, dfg)
15441566
} else {
1545-
let new_variable =
1546-
self.variables.allocate_constant(self.brillig_context, value_id, dfg);
1567+
let new_variable = self.variables.define_variable(
1568+
self.function_context,
1569+
self.brillig_context,
1570+
value_id,
1571+
dfg,
1572+
);
15471573

15481574
// Initialize the variable
15491575
let pointer = match new_variable {
@@ -1583,8 +1609,12 @@ impl<'block> BrilligBlock<'block> {
15831609
// around values representing function pointers, even though
15841610
// there is no interaction with the function possible given that
15851611
// value.
1586-
let new_variable =
1587-
self.variables.allocate_constant(self.brillig_context, value_id, dfg);
1612+
let new_variable = self.variables.define_variable(
1613+
self.function_context,
1614+
self.brillig_context,
1615+
value_id,
1616+
dfg,
1617+
);
15881618

15891619
self.brillig_context.const_instruction(
15901620
new_variable.extract_single_addr(),
@@ -1732,18 +1762,10 @@ impl<'block> BrilligBlock<'block> {
17321762
self.brillig_context.mov_instruction(write_pointer_register, pointer);
17331763

17341764
for (element_idx, element_id) in data.iter().enumerate() {
1735-
if let Some((constant, typ)) = dfg.get_numeric_constant_with_type(*element_id) {
1736-
self.brillig_context.indirect_const_instruction(
1737-
write_pointer_register,
1738-
typ.bit_size(),
1739-
constant,
1740-
);
1741-
} else {
1742-
let element_variable = self.convert_ssa_value(*element_id, dfg);
1743-
// Store the item in memory
1744-
self.brillig_context
1745-
.codegen_store_variable_in_pointer(write_pointer_register, element_variable);
1746-
}
1765+
let element_variable = self.convert_ssa_value(*element_id, dfg);
1766+
// Store the item in memory
1767+
self.brillig_context
1768+
.codegen_store_variable_in_pointer(write_pointer_register, element_variable);
17471769

17481770
if element_idx != data.len() - 1 {
17491771
// Increment the write_pointer_register

compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs

+17-45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use acvm::FieldElement;
2-
use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet};
2+
use fxhash::FxHashSet as HashSet;
33

44
use crate::{
55
brillig::brillig_ir::{
@@ -22,16 +22,15 @@ use super::brillig_fn::FunctionContext;
2222
#[derive(Debug, Default)]
2323
pub(crate) struct BlockVariables {
2424
available_variables: HashSet<ValueId>,
25-
available_constants: HashMap<ValueId, BrilligVariable>,
2625
}
2726

2827
impl BlockVariables {
2928
/// Creates a BlockVariables instance. It uses the variables that are live in to the block and the global available variables (block parameters)
3029
pub(crate) fn new(live_in: HashSet<ValueId>) -> Self {
31-
BlockVariables { available_variables: live_in, ..Default::default() }
30+
BlockVariables { available_variables: live_in }
3231
}
3332

34-
/// Returns all non-constant variables that have not been removed at this point.
33+
/// Returns all variables that have not been removed at this point.
3534
pub(crate) fn get_available_variables(
3635
&self,
3736
function_context: &FunctionContext,
@@ -48,7 +47,7 @@ impl BlockVariables {
4847
.collect()
4948
}
5049

51-
/// For a given SSA non constant value id, define the variable and return the corresponding cached allocation.
50+
/// For a given SSA value id, define the variable and return the corresponding cached allocation.
5251
pub(crate) fn define_variable(
5352
&mut self,
5453
function_context: &mut FunctionContext,
@@ -97,6 +96,11 @@ impl BlockVariables {
9796
});
9897
}
9998

99+
/// Checks if a variable is allocated.
100+
pub(crate) fn is_allocated(&self, value_id: &ValueId) -> bool {
101+
self.available_variables.contains(value_id)
102+
}
103+
100104
/// For a given SSA value id, return the corresponding cached allocation.
101105
pub(crate) fn get_allocation(
102106
&mut self,
@@ -105,48 +109,16 @@ impl BlockVariables {
105109
dfg: &DataFlowGraph,
106110
) -> BrilligVariable {
107111
let value_id = dfg.resolve(value_id);
108-
if let Some(constant) = self.available_constants.get(&value_id) {
109-
*constant
110-
} else {
111-
assert!(
112-
self.available_variables.contains(&value_id),
113-
"ICE: ValueId {value_id:?} is not available"
114-
);
115-
116-
*function_context
117-
.ssa_value_allocations
118-
.get(&value_id)
119-
.unwrap_or_else(|| panic!("ICE: Value not found in cache {value_id}"))
120-
}
121-
}
122-
123-
/// Creates a constant. Constants are a special case in SSA, since they are "defined" every time they are used.
124-
/// We keep constants block-local.
125-
pub(crate) fn allocate_constant(
126-
&mut self,
127-
brillig_context: &mut BrilligContext<FieldElement, Stack>,
128-
value_id: ValueId,
129-
dfg: &DataFlowGraph,
130-
) -> BrilligVariable {
131-
let value_id = dfg.resolve(value_id);
132-
let constant = allocate_value(value_id, brillig_context, dfg);
133-
self.available_constants.insert(value_id, constant);
134-
constant
135-
}
136112

137-
/// Gets a constant.
138-
pub(crate) fn get_constant(
139-
&mut self,
140-
value_id: ValueId,
141-
dfg: &DataFlowGraph,
142-
) -> Option<BrilligVariable> {
143-
let value_id = dfg.resolve(value_id);
144-
self.available_constants.get(&value_id).cloned()
145-
}
113+
assert!(
114+
self.available_variables.contains(&value_id),
115+
"ICE: ValueId {value_id:?} is not available"
116+
);
146117

147-
/// Removes the allocations of all constants. Constants will need to be reallocated and reinitialized after this.
148-
pub(crate) fn dump_constants(&mut self) {
149-
self.available_constants.clear();
118+
*function_context
119+
.ssa_value_allocations
120+
.get(&value_id)
121+
.unwrap_or_else(|| panic!("ICE: Value not found in cache {value_id}"))
150122
}
151123
}
152124

compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
};
1616
use fxhash::FxHashMap as HashMap;
1717

18-
use super::variable_liveness::VariableLiveness;
18+
use super::{constant_allocation::ConstantAllocation, variable_liveness::VariableLiveness};
1919

2020
pub(crate) struct FunctionContext {
2121
pub(crate) function_id: FunctionId,
@@ -25,6 +25,8 @@ pub(crate) struct FunctionContext {
2525
pub(crate) blocks: Vec<BasicBlockId>,
2626
/// Liveness information for each variable in the function.
2727
pub(crate) liveness: VariableLiveness,
28+
/// Information on where to allocate constants
29+
pub(crate) constant_allocation: ConstantAllocation,
2830
}
2931

3032
impl FunctionContext {
@@ -36,11 +38,15 @@ impl FunctionContext {
3638
reverse_post_order.extend_from_slice(PostOrder::with_function(function).as_slice());
3739
reverse_post_order.reverse();
3840

41+
let constants = ConstantAllocation::from_function(function);
42+
let liveness = VariableLiveness::from_function(function, &constants);
43+
3944
Self {
4045
function_id: id,
4146
ssa_value_allocations: HashMap::default(),
4247
blocks: reverse_post_order,
43-
liveness: VariableLiveness::from_function(function),
48+
liveness,
49+
constant_allocation: constants,
4450
}
4551
}
4652

0 commit comments

Comments
 (0)