Skip to content

Commit 80b11a0

Browse files
authored
Merge 71d4bff into b7c86f4
2 parents b7c86f4 + 71d4bff commit 80b11a0

File tree

9 files changed

+718
-28
lines changed

9 files changed

+718
-28
lines changed

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

+59-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::brillig::brillig_ir::artifact::Label;
22
use crate::brillig::brillig_ir::brillig_variable::{
3-
BrilligArray, BrilligVariable, SingleAddrVariable, type_to_heap_value_type,
3+
BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable, type_to_heap_value_type,
44
};
55

66
use crate::brillig::brillig_ir::registers::RegisterAllocator;
@@ -935,8 +935,64 @@ impl<'block, Registers: RegisterAllocator> BrilligBlock<'block, Registers> {
935935
Instruction::EnableSideEffectsIf { .. } => {
936936
unreachable!("enable_side_effects not supported by brillig")
937937
}
938-
Instruction::IfElse { .. } => {
939-
unreachable!("IfElse instructions should not be possible in brillig")
938+
Instruction::IfElse { then_condition, then_value, else_condition: _, else_value } => {
939+
let then_condition = self.convert_ssa_single_addr_value(*then_condition, dfg);
940+
let then_value = self.convert_ssa_value(*then_value, dfg);
941+
let else_value = self.convert_ssa_value(*else_value, dfg);
942+
let result = self.variables.define_variable(
943+
self.function_context,
944+
self.brillig_context,
945+
dfg.instruction_results(instruction_id)[0],
946+
dfg,
947+
);
948+
match (then_value, else_value) {
949+
(
950+
BrilligVariable::SingleAddr(then_address),
951+
BrilligVariable::SingleAddr(else_address),
952+
) => {
953+
self.brillig_context.conditional_move_instruction(
954+
then_condition,
955+
then_address,
956+
else_address,
957+
result.extract_single_addr(),
958+
);
959+
}
960+
(
961+
BrilligVariable::BrilligArray(then_array),
962+
BrilligVariable::BrilligArray(else_array),
963+
) => {
964+
// Pointer to the array which result from the if-else
965+
let pointer = self.brillig_context.allocate_register();
966+
self.brillig_context.conditional_move_instruction(
967+
then_condition,
968+
SingleAddrVariable::new_usize(then_array.pointer),
969+
SingleAddrVariable::new_usize(else_array.pointer),
970+
SingleAddrVariable::new_usize(pointer),
971+
);
972+
let if_else_array = BrilligArray { pointer, size: then_array.size };
973+
// Copy the if-else array to the result
974+
self.brillig_context
975+
.call_array_copy_procedure(if_else_array, result.extract_array());
976+
}
977+
(
978+
BrilligVariable::BrilligVector(then_vector),
979+
BrilligVariable::BrilligVector(else_vector),
980+
) => {
981+
// Pointer to the vector which result from the if-else
982+
let pointer = self.brillig_context.allocate_register();
983+
self.brillig_context.conditional_move_instruction(
984+
then_condition,
985+
SingleAddrVariable::new_usize(then_vector.pointer),
986+
SingleAddrVariable::new_usize(else_vector.pointer),
987+
SingleAddrVariable::new_usize(pointer),
988+
);
989+
let if_else_vector = BrilligVector { pointer };
990+
// Copy the if-else vector to the result
991+
self.brillig_context
992+
.call_vector_copy_procedure(if_else_vector, result.extract_vector());
993+
}
994+
_ => unreachable!("ICE - then and else values must have the same type"),
995+
}
940996
}
941997
Instruction::MakeArray { elements: array, typ } => {
942998
let value_id = dfg.instruction_results(instruction_id)[0];

compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs

+18
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ impl DebugShow {
126126
debug_println!(self.enable_debug_trace, " MOV {}, {}", destination, source);
127127
}
128128

129+
/// Emits a `conditional mov` instruction.
130+
pub(crate) fn conditional_mov_instruction(
131+
&self,
132+
destination: MemoryAddress,
133+
source_then: MemoryAddress,
134+
source_else: MemoryAddress,
135+
condition: MemoryAddress,
136+
) {
137+
debug_println!(
138+
self.enable_debug_trace,
139+
" {} = MOV if {} then {}, else {}",
140+
destination,
141+
condition,
142+
source_then,
143+
source_else
144+
);
145+
}
146+
129147
/// Emits a `cast` instruction.
130148
pub(crate) fn cast_instruction(
131149
&self,

compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs

+22
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,28 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<
7575
);
7676
}
7777

78+
/// Insert a conditional move instruction
79+
pub(crate) fn conditional_move_instruction(
80+
&mut self,
81+
condition: SingleAddrVariable,
82+
then_address: SingleAddrVariable,
83+
else_address: SingleAddrVariable,
84+
destination: SingleAddrVariable,
85+
) {
86+
self.debug_show.conditional_mov_instruction(
87+
destination.address,
88+
then_address.address,
89+
else_address.address,
90+
condition.address,
91+
);
92+
self.push_opcode(BrilligOpcode::ConditionalMov {
93+
destination: destination.address,
94+
source_a: then_address.address,
95+
source_b: else_address.address,
96+
condition: condition.address,
97+
});
98+
}
99+
78100
fn binary(
79101
&mut self,
80102
lhs: SingleAddrVariable,

compiler/noirc_evaluator/src/ssa.rs

+1
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ fn optimize_all(builder: SsaBuilder, options: &SsaEvaluatorOptions) -> Result<Ss
211211
.run_pass(Ssa::remove_if_else, "Remove IfElse")
212212
.run_pass(Ssa::purity_analysis, "Purity Analysis (2nd)")
213213
.run_pass(Ssa::fold_constants, "Constant Folding")
214+
.run_pass(Ssa::flatten_basic_conditionals, "Simplify conditionals for unconstrained")
214215
.run_pass(Ssa::remove_enable_side_effects, "EnableSideEffectsIf removal")
215216
.run_pass(Ssa::fold_constants_using_constraints, "Constraint Folding")
216217
.run_pass(Ssa::make_constrain_not_equal_instructions, "Adding constrain not equal")

compiler/noirc_evaluator/src/ssa/ir/dfg.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,9 @@ impl DataFlowGraph {
239239
instruction,
240240
Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. }
241241
),
242-
RuntimeType::Brillig(_) => !matches!(
243-
instruction,
244-
Instruction::EnableSideEffectsIf { .. } | Instruction::IfElse { .. }
245-
),
242+
RuntimeType::Brillig(_) => {
243+
!matches!(instruction, Instruction::EnableSideEffectsIf { .. })
244+
}
246245
}
247246
}
248247

@@ -377,6 +376,11 @@ impl DataFlowGraph {
377376
}
378377
}
379378

379+
/// Replace an existing instruction with a new one.
380+
pub(crate) fn set_instruction(&mut self, id: InstructionId, instruction: Instruction) {
381+
self.instructions[id] = instruction;
382+
}
383+
380384
/// Set the value of value_to_replace to refer to the value referred to by new_value.
381385
///
382386
/// This is the preferred method to call for optimizations simplifying

compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs

+25
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ impl<'f> FunctionInserter<'f> {
7979
(instruction, self.function.dfg.get_instruction_call_stack_id(id))
8080
}
8181

82+
/// Get an instruction, map all its values, and replace it with the resolved instruction.
83+
pub(crate) fn map_instruction_in_place(&mut self, id: InstructionId) {
84+
let mut instruction = self.function.dfg[id].clone();
85+
instruction.map_values_mut(|id| self.resolve(id));
86+
self.function.dfg.set_instruction(id, instruction);
87+
}
88+
8289
/// Maps a terminator in place, replacing any ValueId in the terminator with the
8390
/// resolved version of that value id from this FunctionInserter's internal value mapping.
8491
pub(crate) fn map_terminator_in_place(&mut self, block: BasicBlockId) {
@@ -251,4 +258,22 @@ impl<'f> FunctionInserter<'f> {
251258
self.values.entry(*param).or_insert(*new_param);
252259
}
253260
}
261+
262+
/// Merge the internal mapping into the given mapping
263+
/// The merge is guaranteed to be coherent because ambiguous cases are prevented
264+
pub(crate) fn extract_mapping(&self, mapping: &mut HashMap<ValueId, ValueId>) {
265+
for (k, v) in &self.values {
266+
if mapping.contains_key(k) {
267+
unreachable!("cannot merge key");
268+
}
269+
if mapping.contains_key(v) {
270+
unreachable!("cannot merge value");
271+
}
272+
mapping.insert(*k, *v);
273+
}
274+
}
275+
276+
pub(crate) fn set_mapping(&mut self, mapping: HashMap<ValueId, ValueId>) {
277+
self.values = mapping;
278+
}
254279
}

0 commit comments

Comments
 (0)