Skip to content

Commit

Permalink
Fix mod by zero constant folding (#6112)
Browse files Browse the repository at this point in the history
## Description

This PR fixes a problem with constant folding optimization pass with the
mod operator. Unfortunately, we were not checking that the RHS was not
zero. So expressions like `mod 1 0` were packing the compiler.

## Checklist

- [ ] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [ ] I have requested a review from the relevant team or maintainers.
  • Loading branch information
xunilrj authored Jun 13, 2024
1 parent e3eb823 commit be5e134
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
5 changes: 3 additions & 2 deletions sway-ir/src/optimize/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ fn combine_binary_op(context: &mut Context, function: &Function) -> bool {
(Xor, Uint(l), Uint(r)) => Some(Uint(l ^ r)),
(Xor, U256(l), U256(r)) => Some(U256(l ^ r)),

(Mod, Uint(l), Uint(r)) => Some(Uint(l % r)),
(Mod, U256(l), U256(r)) => Some(U256(l % r)),
(Mod, Uint(l), Uint(r)) => l.checked_rem(*r).map(Uint),
(Mod, U256(l), U256(r)) => l.checked_rem(r).map(U256),

(Rsh, Uint(l), Uint(r)) => u32::try_from(*r)
.ok()
Expand Down Expand Up @@ -350,6 +350,7 @@ mod tests {
assert_operator("u64", "sub", "0", Some("1"), None);
assert_operator("u64", "mul", &u64::MAX.to_string(), Some("2"), None);
assert_operator("u64", "div", "1", Some("0"), None);
assert_operator("u64", "mod", "1", Some("0"), None);

assert_operator("u64", "rsh", "1", Some("64"), None);
assert_operator("u64", "lsh", "1", Some("64"), None);
Expand Down
8 changes: 8 additions & 0 deletions sway-types/src/u256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ impl U256 {
let r = (&self.0).shl(other);
(r.bits() <= 256).then_some(Self(r))
}

pub fn checked_rem(&self, other: &U256) -> Option<U256> {
if other.0 == BigUint::ZERO {
None
} else {
Some(U256(&self.0 % &other.0))
}
}
}

impl std::fmt::Display for U256 {
Expand Down

0 comments on commit be5e134

Please sign in to comment.