-
Notifications
You must be signed in to change notification settings - Fork 398
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
Fix fmin/fmax/dmin/dmax node simplifier for const 0s #7471
Fix fmin/fmax/dmin/dmax node simplifier for const 0s #7471
Conversation
823c8ed
to
1def696
Compare
fmax = secondChild->getFloat(); | ||
if (first == second && first == 0) | ||
{ | ||
int firstBits = *(int *)(&first); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use reinterpret_cast here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, I believe its not guaranteed that float
is 32 bits or, more importantly, that int
and float
are the same size right (same for double
and long
or long long
)? Do we have an int
type that's typedefed
or #defined
so that its the same size as float
, or do I have to add some more logic to work with the proper size?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You did change the reinterpret_cast to use int32_t right, that would use 4 bytes for int32_t. I think it is fair to assume that float
will be binary floating point usually following IEEE-754 binary32 format
. You can also call node->getFloatBits
that would return bits representation of floating point value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I believe similar simplification for Postive and Negative floats were done in fdivSimplifier
in same file, you can take a look at that as well to see how special case negative / positive zero is coded, also checkout [1]
[1]. https://github.com/eclipse/omr/blob/master/compiler/il/OMRDataTypes.hpp
{ | ||
int firstBits = *(int *)(&first); | ||
int secondBits = *(int *)(&second); | ||
int sign = firstBits & nZeroBits; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to. zero out remaining bits here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't need to right? the bitwise And with nZeroBits
should zero all but the most significant bit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant, if the float is negative 0, can that be represented by some other bit pattern other than 0x80000000
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should only be 1 representation for -0 for all floating point representations (whether it's binary interchange format or decimal interchange format [both for decimal and binary encoding formats of the significand]). If the system uses fixed-point as the underlying type of float then there is no -0, and 0 is just 0x0 which should still work
{ | ||
fmin = firstChild->getFloat(); | ||
fmax = secondChild->getFloat(); | ||
if (first == second && first == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering, if GCC or other compiler adheres to IEE-754, then this condition would be incorrect right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yes in that case it would not work. Changed it to compare as ints instead and put as first if condition (no nesting)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you mean if other compilers do NOT adhere to IEEE-754? 0 == -0 is true for IEEE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So comparison of +0/-0 should return true
if compiler is following IEEE-754. I asked the question to confirm this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have not worked out on edge cases, can following check work ?
if (first > second || (firstBits == pZeroBits && secondBits == nZeroBits))
fmax = first
fmin = second
else // first < second, first == second , (first == nZeroBits && second dontCare)
fmax = second
fmin = first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup that'll work. Still need the additional checks for NaNs though, since both max and min need to evaluate to the same NaN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the previous implementation before your fix did that.
max = secondChild->getDouble(); | ||
if (first == second && first == 0) | ||
{ | ||
long long firstBits = *(long *)(&first); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comments as Floats
0aa4f79
to
d044d58
Compare
float second = secondChild->getFloat(); | ||
int32_t firstBits = *reinterpret_cast<int32_t *>(&first); | ||
int32_t secondBits = *reinterpret_cast<int32_t *>(&second); | ||
int32_t nZeroBits = 0x80000000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need to use variable to hold this values (bits representation of negative and positive 0.0F).
if ((firstBits == pZeroBits || firstBits == nZeroBits) && (secondBits == pZeroBits || secondBits == nZeroBits)) | ||
{ | ||
int32_t sign = firstBits & nZeroBits; | ||
fmin = sign < 0 ? first : second; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of thoughts here, do we really need to know sign here? Also I feel we can study the cases and can achieve what we want to in two conditional block only (We can try to avoid if/else if/else if possible).
double second = secondChild->getDouble(); | ||
int64_t firstBits = *reinterpret_cast<int64_t *>(&first); | ||
int64_t secondBits = *reinterpret_cast<int64_t *>(&second); | ||
int64_t nZeroBits = 0x8000000000000000L; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comments as above.
d044d58
to
cdaab4c
Compare
2a24202
to
dfec87e
Compare
uint32_t firstBits = firstChild->getFloatBits(); | ||
uint32_t secondBits = secondChild->getFloatBits(); | ||
|
||
if (first != first) // this is true only for NaNs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand this comparison that you did, but actually prefer what we had originally. That is more readable and checks bit pattern as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be better to change the implementation of isNaNFloat and isDoubleFloat to use value != value
? Or is there some other reason why we check the bit pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as I said, I understand value != value
will be true for NaN, I think the explicit check is the preferred way, as if you go through other compiler documentation, it says you can use it but explicit is the preferred way. Also we would be in near future look into this code for NaNs so we should try to address that in other PR and keep this PR limited to what we want to fix.
dfec87e
to
5947bbd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last nitpick, seems OK to me
} | ||
else if (first > second || (firstBits == 0 && secondBits == FLOAT_NEG_ZERO)) | ||
{ | ||
fmax = first; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra indentation here and at other places.
5947bbd
to
40b9623
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
jenkins build all |
seems like the git clones all failed @r30shah ? Can you rerun please? |
jenkins build all |
@hzongaro Can I request your review on this change and if you are OK with it, can you merge this change as well? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the changes look good. I just had a suggestion for a comment that might be helpful.
Also, may I ask you to adjust the commit comment per the Commit Guidelines? In particular, lines in the body should be no more than 72 colums long, and the header should use imperative to describe the change - perhaps something like, Correct simplification of signed zero for floating point min and max
40b9623
to
3b51547
Compare
- fmax/dmax(+0, -0) now folds to +0, fmin/dmin(+0, -0) to -0 - (previous version returned 2nd arg on fmax/dmax nodes and 1st arg on fmin/dmin nodes Signed-off-by: Matthew Hall <[email protected]>
3b51547
to
be71516
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Thanks!
The latest updates were only to comments and previous test runs were successful, so there's no need to rerun testing. Merging. |
The
fmaxminSimplifier
anddmaxminSimplifier
methods were returning the wrong value when given (+0, -0). This change handles +-0 edge case to return the 0 with the correct sign (+0 is strictly greater than -0).Supports change in #7464 and eclipse-openj9/openj9#20185 (needed for 20185 to pass)
@r30shah