Skip to content

Conversation

@valadaptive
Copy link
Contributor

Unlike fmin and fmax, these are deterministic with regards to signed
zero.

@llvmbot
Copy link
Member

llvmbot commented Dec 4, 2025

@llvm/pr-subscribers-llvm-transforms

Author: None (valadaptive)

Changes

Unlike fmin and fmax, these are deterministic with regards to signed
zero.


Full diff: https://github.com/llvm/llvm-project/pull/170699.diff

2 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h (+1)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+31)
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 4e7c97194cc59..64d2512308935 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -205,6 +205,7 @@ class LibCallSimplifier {
   Value *replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B);
   Value *optimizeExp2(CallInst *CI, IRBuilderBase &B);
   Value *optimizeFMinFMax(CallInst *CI, IRBuilderBase &B);
+  Value *optimizeFMinimumnumFMaximumnum(CallInst *CI, IRBuilderBase &B);
   Value *optimizeLog(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSqrt(CallInst *CI, IRBuilderBase &B);
   Value *optimizeFMod(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d1548694baa27..20d9b03bd87c8 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2543,6 +2543,30 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) {
                                                 CI->getArgOperand(1), FMF));
 }
 
+Value *LibCallSimplifier::optimizeFMinimumnumFMaximumnum(CallInst *CI,
+                                                         IRBuilderBase &B) {
+  Module *M = CI->getModule();
+
+  // If we can shrink the call to a float function rather than a double
+  // function, do that first.
+  Function *Callee = CI->getCalledFunction();
+  StringRef Name = Callee->getName();
+  if ((Name == "fminimum_num" || Name == "fmaximum_num") &&
+      hasFloatVersion(M, Name))
+    if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI))
+      return Ret;
+
+  // The new fminimum_num/fmaximum_num functions, unlike fmin/fmax, *are*
+  // sensitive to the sigh of zero, so we don't change the fast-math flags like
+  // we did for those.
+
+  Intrinsic::ID IID = Callee->getName().starts_with("fminimum_num")
+                          ? Intrinsic::minimumnum
+                          : Intrinsic::maximumnum;
+  return copyFlags(*CI, B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0),
+                                                CI->getArgOperand(1), CI));
+}
+
 Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
   Function *LogFn = Log->getCalledFunction();
   StringRef LogNm = LogFn->getName();
@@ -4123,6 +4147,13 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_fmax:
   case LibFunc_fmaxl:
     return optimizeFMinFMax(CI, Builder);
+  case LibFunc_fminimum_numf:
+  case LibFunc_fminimum_num:
+  case LibFunc_fminimum_numl:
+  case LibFunc_fmaximum_numf:
+  case LibFunc_fmaximum_num:
+  case LibFunc_fmaximum_numl:
+    return optimizeFMinimumnumFMaximumnum(CI, Builder);
   case LibFunc_cabs:
   case LibFunc_cabsf:
   case LibFunc_cabsl:

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing tests

@dtcxzyw dtcxzyw requested a review from arsenm December 5, 2025 15:08
Unlike fmin and fmax, these are deterministic with regards to signed
zero.
@valadaptive valadaptive force-pushed the simplify-fminimummaximum-num branch from 0f7fa39 to 2057460 Compare December 5, 2025 15:38
@llvmbot llvmbot added the llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes label Dec 5, 2025
@valadaptive
Copy link
Contributor Author

I added tests in #170695; I've pulled those in now

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
@dtcxzyw dtcxzyw enabled auto-merge (squash) December 5, 2025 16:11
@dtcxzyw dtcxzyw merged commit 80760b0 into llvm:main Dec 5, 2025
9 of 10 checks passed
// function, do that first.
Function *Callee = CI->getCalledFunction();
StringRef Name = Callee->getName();
if ((Name == "fminimum_num" || Name == "fmaximum_num") &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need the string compare? TargetLibraryInfo should have already parsed this into an enum LibFunc in the caller? Pass that down?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly just adapted this from optimizeFMinFMax above. We could indeed pass in the LibFunc to both functions, although we still need to get the function name to pass into hasFloatVersion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should do that then? I would like to eliminate all string-based libcall logic throughout llvm

honeygoyal pushed a commit to honeygoyal/llvm-project that referenced this pull request Dec 9, 2025
)

Unlike fmin and fmax, these are deterministic with regards to signed
zero.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants