[llvm] [InstSimplify] Optimize maximumnum and minimumnum (PR #139581)
Lewis Crawford via llvm-commits
llvm-commits at lists.llvm.org
Tue May 13 06:47:08 PDT 2025
================
@@ -6725,32 +6735,43 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
return Op0;
bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum;
- bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum;
-
- // minnum(X, nan) -> X
- // maxnum(X, nan) -> X
- // minimum(X, nan) -> nan
- // maximum(X, nan) -> nan
- if (match(Op1, m_NaN()))
- return PropagateNaN ? propagateNaN(cast<Constant>(Op1)) : Op0;
+ bool PropagateSNaN = IID == Intrinsic::minnum || IID == Intrinsic::maxnum;
+ bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum ||
+ IID == Intrinsic::minimumnum;
+
+ // minnum(x, qnan) -> x
+ // maxnum(x, qnan) -> x
+ // minnum(x, snan) -> qnan
+ // maxnum(x, snan) -> qnan
+ // minimum(X, nan) -> qnan
+ // maximum(X, nan) -> qnan
+ if (match(Op1, m_NaN())) {
+ if (PropagateNaN || (PropagateSNaN && match(Op1, m_sNaN())))
+ return propagateNaN(cast<Constant>(Op1));
----------------
LewisCrawford wrote:
I've rewritten this a little to make it more readable now.
The <sNaN, qNaN> handling is correct, but slightly surprising. <sNaN, qNaN> does not match with m_sNaN(), as it contains an element that is neither sNaN nor undef/poison. In this case, it will treat the incoming sNaN element as if it were a qNaN, and will return:
<x, y> for maxnum (surprising, but technically legal, as we are allowed to tread sNaN as qNaN for optimizations)
<qNaN, qNaN> for maximum
<x, y> for maximumnum
This is legal because of this wording in the langref:
> Floating-point math operations are allowed to treat all NaNs as if they were quiet NaNs. For example, “pow(1.0, SNaN)” may be simplified to 1.0.
I've added tests for this, and updated the comments in the code to explicitly state this now.
https://github.com/llvm/llvm-project/pull/139581
More information about the llvm-commits
mailing list