This is an archive of the discontinued LLVM Phabricator instance.

Instcombile min/max intrinsics calls
Needs ReviewPublic

Authored by karthikthecool on Jun 8 2016, 7:45 AM.

Details

Summary

Adding a small patch to fold the following min/max intrinsics calls-

  1. fmin(x, fmax(x, y)) -> select isnan(x)?y:x
  2. fmax(x, fmin(x, y)) -> select isnan(x)?y:x

Thanks

Diff Detail

Event Timeline

karthikthecool retitled this revision from to Instcombile min/max intrinsics calls.
karthikthecool updated this object.
karthikthecool set the repository for this revision to rL LLVM.
karthikthecool added a subscriber: llvm-commits.
escha added a subscriber: escha.Jun 8 2016, 8:25 AM

Counterexample:

x = NaN

y = 0

fmin(x, fmax(x, y)) -> x ?
fmin(x, fmax(NaN, 0)) -> x ?
fmin(NaN, 0) -> x ?
fmin(NaN, 0) -> 0
0 != x

Thanks escha for the counter example. I will handle NaN case properly.
Apart from that it should work properly right?

karthikthecool updated this object.
karthikthecool removed rL LLVM as the repository for this revision.

Update the patch to handle NaN's.
As escha suggested the previous code will fail in case on NaN.
We will need runtime checks to see if the value is NaN and select X or Y accordingly.

We eliminate 2 intinsic function call with a compare and select instruction.
Please let me know your valuable inputs on the same and if it requires any modifications.

Thanks and Regards
Karthik Bhat

arsenm edited edge metadata.Jun 9 2016, 4:41 PM

Should have some tests with known non-nan cases

majnemer edited edge metadata.Jun 9 2016, 5:01 PM

I believe you can also check for nnan on the fmin/fmax to further improve the IR.

Hi David, Matt,
Thanks a lot for the review comments. Please find my comments below-

@Matt: I have already added test cases for non nan cases which are ( maxnum_x_y_minnum_y, innum_x_maxnum_x_y. minnum_x_y_maxnum_y, maxnum_x_minnum_x_y) respectively. I feel these should cover all the 4 cases for which patch was added. Please let me know if more test cases are required.

@david: fmin/fmax already handle nan when we can deduce a parameter as "nan at compile time".
If we were to add check at runtime the code will look something like -

fmin(x,y) -> if(isnan(x|y)) ? ( if(isnan(x)) ? y : x) : fmin(x,y)

for non nan cases which i believe will be mostly called we will have one extra compare and select instruction in addition to the normal fmin call.
I feel it may not be worth adding this runtime check. But please let me know if you feel otherwise. I can update the code accordingly.

Thanks again for your review comments. Please let me know your valuable inputs on the comments above.

Regards
Karthik

Hi David, Matt,
Thanks a lot for the review comments. Please find my comments below-

@Matt: I have already added test cases for non nan cases which are ( maxnum_x_y_minnum_y, innum_x_maxnum_x_y. minnum_x_y_maxnum_y, maxnum_x_minnum_x_y) respectively. I feel these should cover all the 4 cases for which patch was added. Please let me know if more test cases are required.

@david: fmin/fmax already handle nan when we can deduce a parameter as "nan at compile time".
If we were to add check at runtime the code will look something like -

fmin(x,y) -> if(isnan(x|y)) ? ( if(isnan(x)) ? y : x) : fmin(x,y)

for non nan cases which i believe will be mostly called we will have one extra compare and select instruction in addition to the normal fmin call.
I feel it may not be worth adding this runtime check. But please let me know if you feel otherwise. I can update the code accordingly.

I am saying that there are situations where we know a-priori that the fmax/fmin call will observe a nan due to annotations on the call that _cannot_ be deduced through other data flow analysis. I would just check that the call is marked nnan and choose not to emit a select in those situations.

Thanks again for your review comments. Please let me know your valuable inputs on the comments above.

Regards
Karthik

karthikthecool edited edge metadata.

Thanks David for the comments. I get your point now. Updated the code to incorporate comment.

Please let me know if you have any other feedback.
Thanks and Regards
Karthik Bhat

Ping..

Thanks
Karthik

majnemer added inline comments.Jun 15 2016, 11:08 AM
lib/Transforms/InstCombine/InstCombineCalls.cpp
1013–1014

Couldn't this case live in InstructionSimplify?

karthikthecool added inline comments.Jun 15 2016, 6:37 PM
lib/Transforms/InstCombine/InstCombineCalls.cpp
1013–1014

Hi David,
Thanks for the comments.
Since in simplifyMinnumMaxnum we use
replaceInstUsesWith i thought we can reuse the same code here..
Also i feel handling fmin/fmax cases here in this single function would keep changes limited to one place.
But please let me knw if you feel this place is incorrect I will try to move these into instsimplify.
Thanks again for your time and review comments.
Regards
Karthik

Ping..
Updated diff.

I discovered that the libcall already does this nnan compare + select canonicalization (although I don't get the rationale for it, the opposite seems preferable). Are you still working on this patch?

arsenm resigned from this revision.Feb 21 2019, 6:55 PM