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
25 changes: 25 additions & 0 deletions crates/nargo/tests/test_data/9_conditional/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]){
}
}

//Regression for to_bits() constant evaluation
let arr : [u8; 2] = [ 1, 2 ];
// binary array representation of u8 1
let as_bits_hardcode_1 = [1, 0];
let mut c1 = 0;
for i in 0..2 {
let mut as_bits = std::to_bits(arr[i] as Field, 2);
c1 = c1 + as_bits[0] as Field;

if i == 0 {
constrain arr[i] == 1;// 1
for k in 0..2 {
constrain as_bits_hardcode_1[k] == as_bits[k];
};
}
if i == 1 {
constrain arr[i] == 2;//2
for k in 0..2 {
constrain as_bits_hardcode_1[k] != as_bits[k];
};
}
};
constrain c1==1;

//Test case for short-circuit
let mut data = [0 as u32; 32];
let mut ba = a;
Expand All @@ -68,6 +92,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]){
};
constrain data[31] == 0;
constrain ba != 13;

if a == 3 {
c = test4();
}
Expand Down
3 changes: 1 addition & 2 deletions crates/noirc_evaluator/src/ssa/code_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,7 @@ impl IRGenerator {
//Exit block
let exit_block =
block::new_unsealed_block(&mut self.context, block::BlockType::IfJoin, true);

self.context[entry_block].dominated.push(exit_block);
self.context[exit_block].dominator = Some(entry_block);

//Else block
self.context.current_block = entry_block;
Expand Down
2 changes: 1 addition & 1 deletion crates/noirc_evaluator/src/ssa/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ fn block_overflow(
//we may do that in future when the max_map becomes more used elsewhere (for other optim)
}

let old_ins = ctx.try_get_mut_instruction(id).unwrap();
let old_ins = ctx.try_get_mut_instruction(ins.id).unwrap();
*old_ins = ins;
}

Expand Down
70 changes: 36 additions & 34 deletions crates/noirc_evaluator/src/ssa/optim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use acvm::FieldElement;
use crate::errors::RuntimeError;

use super::{
acir_gen::InternalVar,
anchor::{Anchor, CseAction},
block::BlockId,
context::SsaContext,
Expand Down Expand Up @@ -48,25 +47,13 @@ pub fn simplify(ctx: &mut SsaContext, ins: &mut Instruction) -> Result<(), Runti
return Ok(());
}

match &mut ins.operation {
Operation::Binary(binary) => {
if let NodeEval::Const(r_const, r_type) = NodeEval::from_id(ctx, binary.rhs) {
if binary.operator == BinaryOp::Div {
binary.rhs = ctx.get_or_create_const(r_const.inverse(), r_type);
binary.operator = BinaryOp::Mul;
}
if let Operation::Binary(binary) = &mut ins.operation {
if let NodeEval::Const(r_const, r_type) = NodeEval::from_id(ctx, binary.rhs) {
if binary.operator == BinaryOp::Div {
binary.rhs = ctx.get_or_create_const(r_const.inverse(), r_type);
binary.operator = BinaryOp::Mul;
}
}
Operation::Intrinsic(opcode, args) => {
let args = args
.iter()
.map(|arg| NodeEval::from_id(ctx, *arg).into_const_value().map(|f| f.to_u128()));

if let Some(args) = args.collect() {
ins.mark = Mark::ReplaceWith(evaluate_intrinsic(ctx, *opcode, args, &ins.res_type));
}
}
_ => (),
}

Ok(())
Expand All @@ -77,30 +64,28 @@ fn evaluate_intrinsic(
op: acvm::acir::OPCODE,
args: Vec<u128>,
res_type: &ObjectType,
) -> NodeId {
block_id: BlockId,
) -> Vec<NodeId> {
match op {
acvm::acir::OPCODE::ToBits => {
let bit_count = args[1] as u32;
let mut result = Vec::new();

if let ObjectType::Pointer(a) = res_type {
let new_var = super::node::Variable {
id: NodeId::dummy(),
obj_type: super::node::ObjectType::Pointer(*a),
name: op.to_string(),
root: None,
def: None,
witness: None,
parent_block: ctx.current_block,
};

for i in 0..bit_count {
if args[0] & (1 << i) != 0 {
ctx.mem[*a].values.push(InternalVar::from(FieldElement::one()));
let index = ctx.get_or_create_const(
FieldElement::from(i as i128),
ObjectType::NativeField,
);
let op = if args[0] & (1 << i) != 0 {
Operation::Store { array_id: *a, index, value: ctx.one() }
} else {
ctx.mem[*a].values.push(InternalVar::from(FieldElement::zero()));
}
Operation::Store { array_id: *a, index, value: ctx.zero() }
};
let i = Instruction::new(op, ObjectType::NotAnObject, Some(block_id));
result.push(ctx.add_instruction(i));
}
return ctx.add_variable(new_var, None);
return result;
}
unreachable!();
}
Expand Down Expand Up @@ -353,6 +338,23 @@ fn cse_block_with_anchor(

let mut update2 = update.clone();
simplify(ctx, &mut update2)?;
//cannot simplify to_bits() in the previous call because it get replaced with multiple instructions
if let Operation::Intrinsic(opcode, args) = &update2.operation {
let args = args.iter().map(|arg| {
NodeEval::from_id(ctx, *arg).into_const_value().map(|f| f.to_u128())
});

if let Some(args) = args.collect() {
update2.mark = Mark::Deleted;
new_list.extend(evaluate_intrinsic(
ctx,
*opcode,
args,
&update2.res_type,
block_id,
));
}
}
let update3 = ctx.get_mut_instruction(*ins_id);
*update3 = update2;
}
Expand Down