[llvm] [InstSimplify] Optimize maximumnum and minimumnum (PR #139581)
Artem Belevich via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 15 14:18:08 PDT 2025
================
@@ -6725,36 +6735,138 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
if (Q.isUndefValue(Op1))
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;
-
- // In the following folds, inf can be replaced with the largest finite
- // float, if the ninf flag is set.
- const APFloat *C;
- if (match(Op1, m_APFloat(C)) &&
- (C->isInfinity() || (Call && Call->hasNoInfs() && C->isLargest()))) {
- // minnum(X, -inf) -> -inf
- // maxnum(X, +inf) -> +inf
- // minimum(X, -inf) -> -inf if nnan
- // maximum(X, +inf) -> +inf if nnan
- if (C->isNegative() == IsMin &&
- (!PropagateNaN || (Call && Call->hasNoNaNs())))
- return ConstantFP::get(ReturnType, *C);
-
- // minnum(X, +inf) -> X if nnan
- // maxnum(X, -inf) -> X if nnan
- // minimum(X, +inf) -> X
- // maximum(X, -inf) -> X
- if (C->isNegative() != IsMin &&
- (PropagateNaN || (Call && Call->hasNoNaNs())))
- return Op0;
+ if (Constant *C = dyn_cast<Constant>(Op1)) {
+ bool PropagateNaN =
+ IID == Intrinsic::minimum || IID == Intrinsic::maximum;
+ bool PropagateSNaN = IID == Intrinsic::minnum || IID == Intrinsic::maxnum;
+ bool IsMin = IID == Intrinsic::minimum || IID == Intrinsic::minnum ||
+ IID == Intrinsic::minimumnum;
+
+ // Get the optimized value for a constant scalar input. The result may
+ // indicate either to use the non-const LHS value, or return a pointer
+ // to a new constant value to use instead of the input (after e.g.
+ // quieting NaNs). Returns empty optional value if it cannot be optimized.
+ typedef struct {
+ bool UseNonConstVal;
+ Constant *NewConstVal;
+ } OptResult;
+ auto GetOptResultFor = [PropagateNaN, PropagateSNaN, IsMin,
+ Call](Constant *C) -> std::optional<OptResult> {
+ auto UseNonConstVal = []() -> OptResult { return {true, nullptr}; };
+ auto UseConstVal = [](Constant *C) -> OptResult { return {false, C}; };
+
+ // min/max(opt, poison) -> poison
+ if (isa<UndefValue>(C))
+ return UseConstVal(C);
+
+ const ConstantFP *CFP = dyn_cast<ConstantFP>(C);
+ if (!CFP)
+ return {};
+ APFloat CAPF = CFP->getValueAPF();
+
+ // minnum(x, qnan) -> x
+ // maxnum(x, qnan) -> x
+ // minnum(x, snan) -> qnan
+ // maxnum(x, snan) -> qnan
+ // minimum(X, nan) -> qnan
+ // maximum(X, nan) -> qnan
+ // minimumnum(X, nan) -> x
+ // maximumnum(X, nan) -> x
+ if (CAPF.isNaN()) {
+ if (PropagateNaN || (PropagateSNaN && CAPF.isSignaling()))
+ return UseConstVal(ConstantFP::get(C->getType(), CAPF.makeQuiet()));
+ else
+ return UseNonConstVal();
+ }
+
+ if (CAPF.isInfinity() ||
+ (Call && Call->hasNoInfs() && CAPF.isLargest())) {
+ // minnum(X, -inf) -> -inf (ignoring sNaN -> qNaN propagation)
+ // maxnum(X, +inf) -> +inf (ignoring sNaN -> qNaN propagation)
+ // minimum(X, -inf) -> -inf if nnan
+ // maximum(X, +inf) -> +inf if nnan
+ // minimumnum(X, -inf) -> -inf
+ // maximumnum(X, +inf) -> +inf
+ if (CAPF.isNegative() == IsMin &&
+ (!PropagateNaN || (Call && Call->hasNoNaNs())))
+ return UseConstVal(C);
+
+ // minnum(X, +inf) -> X if nnan
+ // maxnum(X, -inf) -> X if nnan
+ // minimum(X, +inf) -> X (ignoring quieting of sNaNs)
+ // maximum(X, -inf) -> X (ignoring quieting of sNaNs)
+ // maximumnum(X, -inf) -> X if nnan
+ // minimumnum(X, +inf) -> X if nnan
----------------
Artem-B wrote:
Nit: different man/mix order is different than min/max order for the intrinsics above.
https://github.com/llvm/llvm-project/pull/139581
More information about the llvm-commits
mailing list