[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