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

cranelift: Implement PartialEq on Ieee{32,64} #4849

Merged
merged 4 commits into from
Sep 2, 2022

Conversation

afonso360
Copy link
Contributor

@afonso360 afonso360 commented Sep 2, 2022

👋 Hey,

This fixes #4828 by implementing PartialEq in terms of float values for the Ieee{32,64} types.

Previously PartialEq was auto derived. This means that it was implemented in terms of PartialEq in a u32.

This is not correct for floats because NaN != NaN.

PartialOrd was manually implemented in 6d50099, but it seems like it was an oversight to leave PartialEq out until now.

The test suite depends on the previous behaviour so we adjust it to keep comparing bits instead of floats.

cc: @jameysharp

Some of these are disabled on aarch64 due to not being implemented yet.
Previously `PartialEq` was auto derived. This means that it was implemented in terms of PartialEq in a u32.

This is not correct for floats because `NaN != NaN`.

PartialOrd was manually implemented in 6d50099, but it seems like it was an oversight to leave PartialEq out until now.

The test suite depends on the previous behaviour so we adjust it to keep comparing bits instead of floats.
@github-actions github-actions bot added the cranelift Issues related to the Cranelift code generator label Sep 2, 2022
@afonso360
Copy link
Contributor Author

afonso360 commented Sep 2, 2022

For anyone else wondering why we use Ieee{32,64} like I was (since it looks like we are just slowly reimplementing f32/f64). I found this thread #2251 (comment) where it appears that some float behaviour may change according to each arch, so this struct is intended to normalize that behaviour across arches.

Copy link
Contributor

@jameysharp jameysharp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic work here, Afonso. Every question I had was already answered either by a comment in the code or by your PR comments; you've already opened an issue about the unimplemented aarch64 comparisons; and you've dramatically expanded the test cases for fcmp.

Now I want a comment on Ieee32/Ieee64 pointing at the discussion you found, but I'm too excited to merge this to wait for that. 😁

@jameysharp jameysharp merged commit f30a7eb into bytecodealliance:main Sep 2, 2022
@jameysharp
Copy link
Contributor

Awww, cranelift-fuzzgen needs a fix similar to the test suite runner, because it also expects bitwise equality for NaNs when comparing results.

@afonso360
Copy link
Contributor Author

afonso360 commented Sep 2, 2022

Huh, that is true! I was thinking about implementing a wrapper type over Vec<DataValue> like RunResult or something like that so that we don't have to duplicate the comparison function, what do you think about that?

Edit: Although Result has its own meaning, so we that's probably not the best name. And we already have a RunResult in fuzzgen.

@jameysharp
Copy link
Contributor

I have a fix I'm testing now. I've added a bitwise_eq method to DataValue to share most of the logic. Then in cranelift-fuzzgen I've implemented PartialEq on RunResult in terms of bitwise_eq, and written similar code in compare_results. I don't feel bad about duplicating l.len() == r.len() && l.iter().zip(r).all(|(l, r)| l.bitwise_eq(r)).

@afonso360
Copy link
Contributor Author

afonso360 commented Sep 2, 2022

Hah! We implemented the same thing! 😄

image

Down to the same name and everything!

@jameysharp
Copy link
Contributor

Hah, nice! Ooh, I like your doc comment better than mine though. 😁

BTW I only noticed while looking into this that compare_results doesn't check if the vectors have the same length. Maybe there's a check earlier that makes it unnecessary? But anywhere I see .zip, if different lengths could matter then I like to see an explicit check.

Do you want to open a PR for this? Here's the key bit I did in cranelift-fuzzgen:

impl PartialEq for RunResult {
    fn eq(&self, other: &Self) -> bool {
        if let (RunResult::Success(l), RunResult::Success(r)) = (self, other) {
            l.len() == r.len() && l.iter().zip(r).all(|(l, r)| l.bitwise_eq(r))
        } else {
            false
        }
    }
}

Then remove the RunResult::unwrap implementation and just do assert_eq!(int_res, host_res); at the end.

@alexcrichton
Copy link
Member

FYI I think this is the cause of #4857

jameysharp added a commit to jameysharp/wasmtime that referenced this pull request Sep 2, 2022
This fixes bytecodealliance#4857 by partially reverting bytecodealliance#4849.

It turns out that Ieee32 and Ieee64 need bitwise equality semantics so
they can be used as hash-table keys.

Moving the IEEE754 semantics up a layer to DataValue makes sense in
conjunction with bytecodealliance#4855, where we introduced a DataValue::bitwise_eq
alternative implementation of equality for those cases where users of
DataValue still want the bitwise equality semantics.
jameysharp added a commit that referenced this pull request Sep 3, 2022
* cranelift-codegen: Remove all uses of DataValue

This type is only used by the interpreter, cranelift-fuzzgen, and
filetests. I haven't found another convenient crate for those to all
depend on where this type can live instead, but this small refactor at
least makes it obvious that code generation does not in any way depend
on the implementation of this type.

* Make DataValue, not Ieee32/64, respect IEEE754

This fixes #4857 by partially reverting #4849.

It turns out that Ieee32 and Ieee64 need bitwise equality semantics so
they can be used as hash-table keys.

Moving the IEEE754 semantics up a layer to DataValue makes sense in
conjunction with #4855, where we introduced a DataValue::bitwise_eq
alternative implementation of equality for those cases where users of
DataValue still want the bitwise equality semantics.

* cranelift-interpreter: Use eq/ord from DataValue

This fixes #4828, again, now that the comparison operators on DataValue
have the right IEEE754 semantics.

* Add regression test from issue #4857
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cranelift-fuzzgen fuzzbug: fcmp gives wrong answer on NaN
3 participants