Skip to content

Commit

Permalink
feat(ssa): Simplify signed casts (#6166)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves <!-- Link to GitHub Issue -->

Small optimization I noticed while working on other tasks.

## Summary\*

We currently simplify when casting to a field or an unsigned type. We
can also simplify when casting to a signed type. This is an initial
version that is quite conservative in the simplification. If we we have
a constant that is below `2^(bit_size-1)` when casting to a signed type
we return the constant with the new signed type. I also added the case
of signed -> field as this can be the same as going unsigned -> field.

## Additional Context



## Documentation\*

Check one:
- [X] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [X] I have tested the changes locally.
- [X] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
vezenovm authored Sep 27, 2024
1 parent fcdbcb9 commit eec3a61
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ pub(super) fn simplify_cast(
SimplifiedTo(value)
}
(
Type::Numeric(NumericType::Unsigned { .. }),
Type::Numeric(NumericType::Unsigned { .. } | NumericType::Signed { .. }),
Type::Numeric(NumericType::NativeField),
) => {
// Unsigned -> Field: redefine same constant as Field
// Unsigned/Signed -> Field: redefine same constant as Field
SimplifiedTo(dfg.make_constant(constant, dst_typ.clone()))
}
(
Expand All @@ -48,6 +48,24 @@ pub(super) fn simplify_cast(
let truncated = FieldElement::from_be_bytes_reduce(&truncated.to_bytes_be());
SimplifiedTo(dfg.make_constant(truncated, dst_typ.clone()))
}
(
Type::Numeric(
NumericType::NativeField
| NumericType::Unsigned { .. }
| NumericType::Signed { .. },
),
Type::Numeric(NumericType::Signed { bit_size }),
) => {
// Field/Unsigned -> signed
// We only simplify to signed when we are below the maximum signed integer of the destination type.
let integer_modulus = BigUint::from(2u128).pow(*bit_size - 1);
let constant_uint: BigUint = BigUint::from_bytes_be(&constant.to_be_bytes());
if constant_uint < integer_modulus {
SimplifiedTo(dfg.make_constant(constant, dst_typ.clone()))
} else {
None
}
}
_ => None,
}
} else if *dst_typ == dfg.type_of_value(value) {
Expand Down

0 comments on commit eec3a61

Please sign in to comment.