Skip to content

Commit

Permalink
feat: replace bitwise ANDs used for truncation with `Instruction::Tru…
Browse files Browse the repository at this point in the history
…ncate`
  • Loading branch information
TomAFrench committed Feb 10, 2024
1 parent b41ce8b commit 4cf68ec
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
26 changes: 26 additions & 0 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,32 @@ impl Binary {
let instruction = Instruction::binary(BinaryOp::Mul, self.lhs, self.rhs);
return SimplifyResult::SimplifiedToInstruction(instruction);
}
if operand_type.is_unsigned() {
// It's common in other programming languages to truncate values to a certain bit size using
// a bitwise AND with a bit mask. However this operation is quite inefficient inside a snark.
//
// We then replace this bitwise operation with an equivalent truncation instruction.
match (lhs, rhs) {
(Some(bitmask), None) | (None, Some(bitmask)) => {
// This substitution requires the bitmask to retain all of the lower bits.
// The bitmask must then be one less than a power of 2.
let bitmask_plus_one = bitmask.to_u128() + 1;
if bitmask_plus_one.is_power_of_two() {
let value = if lhs.is_some() { self.rhs } else { self.lhs };
let num_bits = bitmask_plus_one.ilog2();
return SimplifyResult::SimplifiedToInstruction(
Instruction::Truncate {
value,
bit_size: num_bits,
max_bit_size: operand_type.bit_size(),
},
);
}
}

_ => (),
}
}
}
BinaryOp::Or => {
if lhs_is_zero {
Expand Down
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"bincode",
"bindgen",
"bitand",
"bitmask",
"blackbox",
"boilerplate",
"boilerplates",
Expand Down Expand Up @@ -83,6 +84,7 @@
"higher-kinded",
"Hindley-Milner",
"idents",
"ilog",
"impls",
"indexmap",
"injective",
Expand Down

0 comments on commit 4cf68ec

Please sign in to comment.