Skip to content

Commit

Permalink
use 128 bits for constant bit shift
Browse files Browse the repository at this point in the history
  • Loading branch information
guipublic committed Nov 27, 2023
1 parent 70ccb7e commit 53bfcfc
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 26 deletions.
51 changes: 25 additions & 26 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,32 +282,31 @@ impl FunctionBuilder {
) -> ValueId {
let base = self.field_constant(FieldElement::from(2_u128));
let typ = self.current_function.dfg.type_of_value(lhs);
let (max_bit, pow) = if let Some(rhs_constant) =
self.current_function.dfg.get_numeric_constant(rhs)
{
// Happy case is that we know precisely by how many bits the the integer will
// increase: lhs_bit_size + rhs
let (rhs_bit_size_pow_2, overflows) =
2_u32.overflowing_pow(rhs_constant.to_u128() as u32);
if overflows {
let zero = self.numeric_constant(FieldElement::zero(), typ);
return InsertInstructionResult::SimplifiedTo(zero).first();
}
let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2 as u128), typ);
(bit_size + (rhs_constant.to_u128() as u32), pow)
} else {
// we use a predicate to nullify the result in case of overflow
let bit_size_var =
self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone());
let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var);
let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1));
let predicate = self.insert_binary(overflow, BinaryOp::Eq, one);
let predicate = self.insert_cast(predicate, typ.clone());

let pow = self.pow(base, rhs);
let pow = self.insert_cast(pow, typ);
(FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow))
};
let (max_bit, pow) =
if let Some(rhs_constant) = self.current_function.dfg.get_numeric_constant(rhs) {
// Happy case is that we know precisely by how many bits the the integer will
// increase: lhs_bit_size + rhs
let (rhs_bit_size_pow_2, overflows) =
2_u128.overflowing_pow(rhs_constant.to_u128() as u32);
if overflows {
let zero = self.numeric_constant(FieldElement::zero(), typ);
return InsertInstructionResult::SimplifiedTo(zero).first();
}
let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2), typ);
(bit_size + (rhs_constant.to_u128() as u32), pow)
} else {
// we use a predicate to nullify the result in case of overflow
let bit_size_var =
self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone());
let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var);
let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1));
let predicate = self.insert_binary(overflow, BinaryOp::Eq, one);
let predicate = self.insert_cast(predicate, typ.clone());

let pow = self.pow(base, rhs);
let pow = self.insert_cast(pow, typ);
(FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow))
};

let instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul });
if max_bit <= bit_size {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ fn main(x: u64) {

//regression for 3481
assert(x << 63 == 0);

assert_eq((1 as u56) << (32 as u56), 0x0100000000);
}

fn regression_2250() {
Expand Down

0 comments on commit 53bfcfc

Please sign in to comment.