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

fix: Do not emit range check for multiplication by bool #6983

Merged
merged 9 commits into from
Jan 8, 2025
45 changes: 42 additions & 3 deletions compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2028,7 +2028,11 @@ impl<'a> Context<'a> {
"attempt to subtract with overflow".to_string()
}
BinaryOp::Mul => {
if bit_size == 1 || max_lhs_bits + max_rhs_bits <= bit_size {
if bit_size == 1
|| max_lhs_bits + max_rhs_bits <= bit_size
|| max_lhs_bits == 1
|| max_rhs_bits == 1
{
// Either performing boolean multiplication (which cannot overflow),
// or `lhs` and `rhs` have both been casted up from smaller types and so cannot overflow.
return Ok(());
Expand Down Expand Up @@ -2888,8 +2892,9 @@ mod test {
use acvm::{
acir::{
circuit::{
brillig::BrilligFunctionId, opcodes::AcirFunctionId, ExpressionWidth, Opcode,
OpcodeLocation,
brillig::BrilligFunctionId,
opcodes::{AcirFunctionId, BlackBoxFuncCall},
ExpressionWidth, Opcode, OpcodeLocation,
},
native_types::Witness,
},
Expand All @@ -2913,6 +2918,8 @@ mod test {
},
};

use super::Ssa;

fn build_basic_foo_with_return(
builder: &mut FunctionBuilder,
foo_id: FunctionId,
Expand Down Expand Up @@ -3659,4 +3666,36 @@ mod test {
"Should have {expected_num_normal_calls} BrilligCall opcodes to normal Brillig functions but got {num_normal_brillig_calls}"
);
}

#[test]
fn multiply_with_bool_should_not_emit_range_check() {
let src = "
acir(inline) fn main f0 {
b0(v0: bool, v1: u32):
enable_side_effects v0
v2 = cast v0 as u32
v3 = mul v2, v1
return v3
}
";
let ssa = Ssa::from_str(src).unwrap();
let brillig = ssa.to_brillig(false);

let (mut acir_functions, _brillig_functions, _, _) = ssa
.into_acir(&brillig, ExpressionWidth::default())
.expect("Should compile manually written SSA into ACIR");

assert_eq!(acir_functions.len(), 1);

let opcodes = acir_functions[0].take_opcodes();

for opcode in opcodes {
if let Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) = opcode {
assert!(
input.to_witness().0 <= 1,
"only input witnesses should have range checks: {opcode:?}"
);
}
}
}
}
Loading