Skip to content

[SimplifyLibCalls] Directly convert fmin/fmax to intrinsics - #177988

Merged
nikic merged 1 commit into
llvm:mainfrom
nikic:slc-fmin-fmax
Feb 9, 2026
Merged

[SimplifyLibCalls] Directly convert fmin/fmax to intrinsics#177988
nikic merged 1 commit into
llvm:mainfrom
nikic:slc-fmin-fmax

Conversation

@nikic

@nikic nikic commented Jan 26, 2026

Copy link
Copy Markdown
Contributor

Drop the custom shrinking code, which we'll also do for intrinsics. Having libcall-only optimizations is confusing, as these are typically directly emitted as intrinsics by the frontend.

@nikic
nikic requested review from arsenm and dtcxzyw January 26, 2026 16:04
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Jan 26, 2026
@llvmbot

llvmbot commented Jan 26, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

Changes

Drop the custom shrinking code, which we'll also do for intrinsics. Having libcall-only optimizations is confusing, as these are typically directly emitted as intrinsics by the frontend.

However, the fold on intrinsics is limited to one-use fpexts, so the behavior is not completely the same:

// m((fpext X), (fpext Y)) -> fpext (m(X, Y))
if (match(Arg0, m_OneUse(m_FPExt(m_Value(X)))) &&
match(Arg1, m_OneUse(m_FPExt(m_Value(Y)))) &&
X->getType() == Y->getType()) {
Value *NewCall =
Builder.CreateBinaryIntrinsic(IID, X, Y, II, II->getName());
return new FPExtInst(NewCall, II->getType());
}

I think we could relax that condition to only one of the fpexts being one-use. Let me know if you want me to do that.


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

3 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h (+1-1)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+4-15)
  • (modified) llvm/test/Transforms/InstCombine/float-shrink-compare.ll (+4-2)
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 64d2512308935..9ba3455254f47 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -204,7 +204,7 @@ class LibCallSimplifier {
   Value *replacePowWithExp(CallInst *Pow, IRBuilderBase &B);
   Value *replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B);
   Value *optimizeExp2(CallInst *CI, IRBuilderBase &B);
-  Value *optimizeFMinFMax(CallInst *CI, IRBuilderBase &B);
+  Value *optimizeFMinFMax(CallInst *CI, IRBuilderBase &B, Intrinsic::ID IID);
   Value *optimizeFMinimumnumFMaximumnum(CallInst *CI, IRBuilderBase &B);
   Value *optimizeLog(CallInst *CI, IRBuilderBase &B);
   Value *optimizeSqrt(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 1e8a184fc51b8..ff05faf1c2200 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2520,17 +2520,8 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
   return Ret;
 }
 
-Value *LibCallSimplifier::optimizeFMinFMax(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 == "fmin" || Name == "fmax") && hasFloatVersion(M, Name))
-    if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI))
-      return Ret;
-
+Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B,
+                                           Intrinsic::ID IID) {
   // The LLVM intrinsics minnum/maxnum correspond to fmin/fmax. Canonicalize to
   // the intrinsics for improved optimization (for example, vectorization).
   // No-signed-zeros is implied by the definitions of fmax/fmin themselves.
@@ -2540,9 +2531,6 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) {
   // might be impractical."
   FastMathFlags FMF = CI->getFastMathFlags();
   FMF.setNoSignedZeros();
-
-  Intrinsic::ID IID = Callee->getName().starts_with("fmin") ? Intrinsic::minnum
-                                                            : Intrinsic::maxnum;
   return copyFlags(*CI, B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0),
                                                 CI->getArgOperand(1), FMF));
 }
@@ -4147,10 +4135,11 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
   case LibFunc_fminf:
   case LibFunc_fmin:
   case LibFunc_fminl:
+    return optimizeFMinFMax(CI, Builder, Intrinsic::minnum);
   case LibFunc_fmaxf:
   case LibFunc_fmax:
   case LibFunc_fmaxl:
-    return optimizeFMinFMax(CI, Builder);
+    return optimizeFMinFMax(CI, Builder, Intrinsic::maxnum);
   case LibFunc_fminimum_numf:
   case LibFunc_fminimum_num:
   case LibFunc_fminimum_numl:
diff --git a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
index 6383feff3a6ee..452df5118a324 100644
--- a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
+++ b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
@@ -507,8 +507,10 @@ define i1 @test19(float %x, float %y, float %z) {
 
 define i1 @test20(float %x, float %y) {
 ; CHECK-LABEL: @test20(
-; CHECK-NEXT:    [[FMINF:%.*]] = call nsz float @llvm.minnum.f32(float [[X:%.*]], float 1.000000e+00)
-; CHECK-NEXT:    [[TMP1:%.*]] = fcmp oeq float [[Y:%.*]], [[FMINF]]
+; CHECK-NEXT:    [[TMP4:%.*]] = fpext float [[Y:%.*]] to double
+; CHECK-NEXT:    [[TMP2:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[TMP3:%.*]] = call nsz double @llvm.minnum.f64(double [[TMP2]], double 1.000000e+00)
+; CHECK-NEXT:    [[TMP1:%.*]] = fcmp oeq double [[TMP3]], [[TMP4]]
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = fpext float %y to double

@github-actions

Copy link
Copy Markdown

🪟 Windows x64 Test Results

  • 130179 tests passed
  • 2883 tests skipped
  • 1 test failed

Failed Tests

(click on a test name to see its output)

LLVM

LLVM.CodeGen/AMDGPU/kernel-args.ll
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
c:\_work\llvm-project\llvm-project\build\bin\llc.exe < C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll -mtriple=amdgcn | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe -check-prefixes=SI C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\llc.exe' -mtriple=amdgcn
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' -check-prefixes=SI 'C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll'
# note: command had no output on stdout or stderr
# RUN: at line 3
c:\_work\llvm-project\llvm-project\build\bin\llc.exe < C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll -mtriple=amdgcn -mcpu=tonga | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe -check-prefixes=VI C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\llc.exe' -mtriple=amdgcn -mcpu=tonga
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' -check-prefixes=VI 'C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll'
# note: command had no output on stdout or stderr
# RUN: at line 4
c:\_work\llvm-project\llvm-project\build\bin\llc.exe < C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll -mtriple=amdgcn--amdhsa -mcpu=gfx900 | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe -check-prefixes=GFX9 C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\llc.exe' -mtriple=amdgcn--amdhsa -mcpu=gfx900
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' -check-prefixes=GFX9 'C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll'
# note: command had no output on stdout or stderr
# RUN: at line 5
c:\_work\llvm-project\llvm-project\build\bin\llc.exe < C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll -mtriple=r600 -mcpu=redwood | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe -check-prefixes=EGCM,EG C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\llc.exe' -mtriple=r600 -mcpu=redwood
# .---command stderr------------
# | LLVM ERROR: Cannot select: t3: f32,ch = load<(non-temporal dereferenceable invariant load (s16), align 4, addrspace 7), sext from f16> t0, Constant:i32<36>, undef:i32
# | In function: f16_arg
# | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
# | Stack dump:
# | 0.	Program arguments: c:\\_work\\llvm-project\\llvm-project\\build\\bin\\llc.exe -mtriple=r600 -mcpu=redwood
# | 1.	Running pass 'Function Pass Manager' on module '<stdin>'.
# | 2.	Running pass 'Unnamed pass: implement Pass::getPassName()' on function '@f16_arg'
# | Exception Code: 0xC000001D
# |  #0 0x00007ff784b83826 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x2c83826)
# |  #1 0x00007ffb9695bb04 (C:\Windows\System32\ucrtbase.dll+0x7bb04)
# |  #2 0x00007ffb9695cad1 (C:\Windows\System32\ucrtbase.dll+0x7cad1)
# |  #3 0x00007ff7825e56ab (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x6e56ab)
# |  #4 0x00007ff7825ae5aa (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x6ae5aa)
# |  #5 0x00007ff7825ad853 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x6ad853)
# |  #6 0x00007ff78259efeb (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x69efeb)
# |  #7 0x00007ff78259dad5 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x69dad5)
# |  #8 0x00007ff78259b6ce (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x69b6ce)
# |  #9 0x00007ff78259ac95 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x69ac95)
# | #10 0x00007ff782596c0c (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x696c0c)
# | #11 0x00007ff782593cf4 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x693cf4)
# | #12 0x00007ff7829311e3 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0xa311e3)
# | #13 0x00007ff7823a61d2 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x4a61d2)
# | #14 0x00007ff7823af2ad (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x4af2ad)
# | #15 0x00007ff7823a6eb1 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x4a6eb1)
# | #16 0x00007ff781f07ab7 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x7ab7)
# | #17 0x00007ff781f04d36 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x4d36)
# | #18 0x00007ff7865a9120 (c:\_work\llvm-project\llvm-project\build\bin\llc.exe+0x46a9120)
# | #19 0x00007ffba00d4cb0 (C:\Windows\System32\KERNEL32.DLL+0x14cb0)
# | #20 0x00007ffba8a7edcb (C:\Windows\SYSTEM32\ntdll.dll+0x7edcb)
# `-----------------------------
# error: command failed with exit status: 0xc000001d
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' -check-prefixes=EGCM,EG 'C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll:5728:13: error: EG-LABEL: expected string not found in input
# | ; EG-LABEL: array_3xi16:
# |             ^
# | <stdin>:2246:13: note: scanning from here
# | array_3xi32: ; @array_3xi32
# |             ^
# | <stdin>:2246:17: note: possible intended match here
# | array_3xi32: ; @array_3xi32
# |                 ^
# | 
# | Input file: <stdin>
# | Check file: C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\AMDGPU\kernel-args.ll
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |               .
# |               .
# |               .
# |            2241:  .long 0 
# |            2242:  .text 
# |            2243:  .globl array_3xi32 ; -- Begin function array_3xi32 
# |            2244:  .p2align 8 
# |            2245:  .type array_3xi32,@function 
# |            2246: array_3xi32: ; @array_3xi32 
# | label:5728'0                 X~~~~~~~~~~~~~~~ error: no match found
# | label:5728'1                     ?            possible intended match
# |            2247: ; %bb.0: 
# | label:5728'0     ~~~~~~~~~
# |            2248:  ALU 0, @10, KC0[], KC1[] 
# | label:5728'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            2249:  TEX 0 @8 
# | label:5728'0     ~~~~~~~~~~
# |            2250:  ALU 9, @11, KC0[CB0:0-32], KC1[] 
# | label:5728'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            2251:  MEM_RAT MSKOR T0.XW, T4.X 
# | label:5728'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |               .
# |               .
# |               .
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

@github-actions

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 168830 tests passed
  • 3008 tests skipped
  • 1 test failed

Failed Tests

(click on a test name to see its output)

LLVM

LLVM.CodeGen/AMDGPU/kernel-args.ll
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll -mtriple=amdgcn | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=SI /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -mtriple=amdgcn
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=SI /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# note: command had no output on stdout or stderr
# RUN: at line 3
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll -mtriple=amdgcn -mcpu=tonga | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=VI /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -mtriple=amdgcn -mcpu=tonga
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=VI /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# note: command had no output on stdout or stderr
# RUN: at line 4
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll -mtriple=amdgcn--amdhsa -mcpu=gfx900 | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=GFX9 /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -mtriple=amdgcn--amdhsa -mcpu=gfx900
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=GFX9 /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# note: command had no output on stdout or stderr
# RUN: at line 5
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll -mtriple=r600 -mcpu=redwood | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=EGCM,EG /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -mtriple=r600 -mcpu=redwood
# .---command stderr------------
# | LLVM ERROR: Cannot select: t3: f32,ch = load<(non-temporal dereferenceable invariant load (s16), align 4, addrspace 7), sext from f16> t0, Constant:i32<36>, undef:i32
# | In function: f16_arg
# | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
# | Stack dump:
# | 0.	Program arguments: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -mtriple=r600 -mcpu=redwood
# | 1.	Running pass 'Function Pass Manager' on module '<stdin>'.
# | 2.	Running pass 'Unnamed pass: implement Pass::getPassName()' on function '@f16_arg'
# |  #0 0x0000000007f5fbf8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Support/Unix/Signals.inc:842:13
# |  #1 0x0000000007f5d325 llvm::sys::RunSignalHandlers() /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Support/Signals.cpp:109:18
# |  #2 0x0000000007f609c1 SignalHandler(int, siginfo_t*, void*) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Support/Unix/Signals.inc:429:38
# |  #3 0x00007a0e60c39330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
# |  #4 0x00007a0e60c92b2c pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x9eb2c)
# |  #5 0x00007a0e60c3927e raise (/lib/x86_64-linux-gnu/libc.so.6+0x4527e)
# |  #6 0x00007a0e60c1c8ff abort (/lib/x86_64-linux-gnu/libc.so.6+0x288ff)
# |  #7 0x0000000007ebf0f5 llvm::report_fatal_error(llvm::Twine const&, bool) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Support/ErrorHandling.cpp:137:5
# |  #8 0x0000000007d3deb7 getValueType /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1116:5
# |  #9 0x0000000007d3deb7 getValueType /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1272:16
# | #10 0x0000000007d3deb7 llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:4594:43
# | #11 0x0000000007d3ce49 back /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/SmallVector.h:315:5
# | #12 0x0000000007d3ce49 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:4512:21
# | #13 0x0000000007d31464 begin /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/SmallVector.h:273:45
# | #14 0x0000000007d31464 end /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/SmallVector.h:275:27
# | #15 0x0000000007d31464 ~SmallVector /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/SmallVector.h:1211:46
# | #16 0x0000000007d31464 llvm::SelectionDAGISel::DoInstructionSelection() /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1397:5
# | #17 0x0000000007d303fe ~TimeRegion /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/Support/Timer.h:167:9
# | #18 0x0000000007d303fe llvm::SelectionDAGISel::CodeGenAndEmitDAG() /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1166:3
# | #19 0x0000000007d2e04e llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1691:8
# | #20 0x0000000007d2b130 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:659:22
# | #21 0x0000000007d28800 llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:400:20
# | #22 0x0000000006f46f13 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:0:10
# | #23 0x00000000074b7175 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1398:27
# | #24 0x00000000074bf122 llvm::FPPassManager::runOnModule(llvm::Module&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1444:13
# | #25 0x00000000074b7c1c runOnModule /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1513:27
# | #26 0x00000000074b7c1c llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:531:44
# | #27 0x0000000004d86eef compileModule(char**, llvm::SmallVectorImpl<llvm::PassPlugin>&, llvm::LLVMContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&) /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/tools/llc/llc.cpp:870:17
# | #28 0x0000000004d841c3 main /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/tools/llc/llc.cpp:458:13
# | #29 0x00007a0e60c1e1ca (/lib/x86_64-linux-gnu/libc.so.6+0x2a1ca)
# | #30 0x00007a0e60c1e28b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28b)
# | #31 0x0000000004d7fce5 _start (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc+0x4d7fce5)
# `-----------------------------
# error: command failed with exit status: -6
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=EGCM,EG /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll:6090:13: error: EG-LABEL: expected string not found in input
# | ; EG-LABEL: byref_natural_align_constant_v16i32_arg:
# |             ^
# | <stdin>:2385:30: note: scanning from here
# | byref_align_constant_i32_arg: ; @byref_align_constant_i32_arg
# |                              ^
# | <stdin>:2385:34: note: possible intended match here
# | byref_align_constant_i32_arg: ; @byref_align_constant_i32_arg
# |                                  ^
# | 
# | Input file: <stdin>
# | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/AMDGPU/kernel-args.ll
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |               .
# |               .
# |               .
# |            2380:  .long 0 
# |            2381:  .text 
# |            2382:  .globl byref_align_constant_i32_arg ; -- Begin function byref_align_constant_i32_arg 
# |            2383:  .p2align 8 
# |            2384:  .type byref_align_constant_i32_arg,@function 
# |            2385: byref_align_constant_i32_arg: ; @byref_align_constant_i32_arg 
# | label:6090'0                                  X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
# | label:6090'1                                      ?                             possible intended match
# |            2386: ; %bb.0: 
# | label:6090'0     ~~~~~~~~~
# |            2387:  ALU 0, @8, KC0[CB0:0-32], KC1[] 
# | label:6090'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            2388:  TEX 0 @6 
# | label:6090'0     ~~~~~~~~~~
# |            2389:  ALU 2, @9, KC0[CB0:0-32], KC1[] 
# | label:6090'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            2390:  MEM_RAT_CACHELESS STORE_RAW T0.X, T2.X, 0 
# | label:6090'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |               .
# |               .
# |               .
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

@dtcxzyw dtcxzyw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we could relax that condition to only one of the fpexts being one-use. Let me know if you want me to do that.

Make sense to me. But relaxing the one-use constraint doesn't restore the test change. Note that the LHS is a constant, and valueHasFloatPrecision is responsible for converting it to float losslessly.

if (ConstantFP *Const = dyn_cast<ConstantFP>(Val)) {
APFloat F = Const->getValueAPF();
bool losesInfo;
(void)F.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
&losesInfo);
if (!losesInfo)
return ConstantFP::get(Const->getContext(), F);
}

@nikic

nikic commented Feb 6, 2026

Copy link
Copy Markdown
Contributor Author

Make sense to me. But relaxing the one-use constraint doesn't restore the test change. Note that the LHS is a constant, and valueHasFloatPrecision is responsible for converting it to float losslessly.

Yeah, not sure what I was looking at when I wrote this...

I've now opened both #179968 (for the constant case) and #180164 (for the multi-use case), both of which are profitable on llvm-opt-benchmark.

nikic added a commit that referenced this pull request Feb 9, 2026
#179968)

Fold `min/max(fpext x, C)` to `fpext(min/max(x, fptrunc C))` in cases
where the truncation of the constant is lossless.

This helps eliminate fpext/fptrunc pairs around min/max and addresses
the regression from #177988.

Proof: https://alive2.llvm.org/ce/z/y_Bcdd
Drop the custom shrinking code, which we'll also do for intrinsics.
Having libcall-only optimizations is confusing, as these are
typically directly emitted as intrinsics by the frontend.
@nikic
nikic enabled auto-merge (squash) February 9, 2026 09:17
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Feb 9, 2026
… fptrunc C)) (#179968)

Fold `min/max(fpext x, C)` to `fpext(min/max(x, fptrunc C))` in cases
where the truncation of the constant is lossless.

This helps eliminate fpext/fptrunc pairs around min/max and addresses
the regression from llvm/llvm-project#177988.

Proof: https://alive2.llvm.org/ce/z/y_Bcdd
@nikic
nikic merged commit 4ef7be9 into llvm:main Feb 9, 2026
10 checks passed
@nikic
nikic deleted the slc-fmin-fmax branch February 9, 2026 10:10
rishabhmadan19 pushed a commit to rishabhmadan19/llvm-project that referenced this pull request Feb 9, 2026
llvm#179968)

Fold `min/max(fpext x, C)` to `fpext(min/max(x, fptrunc C))` in cases
where the truncation of the constant is lossless.

This helps eliminate fpext/fptrunc pairs around min/max and addresses
the regression from llvm#177988.

Proof: https://alive2.llvm.org/ce/z/y_Bcdd
rishabhmadan19 pushed a commit to rishabhmadan19/llvm-project that referenced this pull request Feb 9, 2026
)

Drop the custom shrinking code, which we'll also do for intrinsics.
Having libcall-only optimizations is confusing, as these are typically
directly emitted as intrinsics by the frontend.
nikic added a commit that referenced this pull request Feb 10, 2026
…180555)

Same as #177988, but for
fminimum_num/fmaximum_num. Directly canonicalize these to the
corresponding intrinsics, and let the shrinking happen directly on the
intrinsics.
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Feb 10, 2026
…ntrinsic (#180555)

Same as llvm/llvm-project#177988, but for
fminimum_num/fmaximum_num. Directly canonicalize these to the
corresponding intrinsics, and let the shrinking happen directly on the
intrinsics.
markrvmurray pushed a commit to markrvmurray/llvm-mc6809 that referenced this pull request Jun 14, 2026
…) (#179968)

Fold `min/max(fpext x, C)` to `fpext(min/max(x, fptrunc C))` in cases
where the truncation of the constant is lossless.

This helps eliminate fpext/fptrunc pairs around min/max and addresses
the regression from llvm/llvm-project#177988.

Proof: https://alive2.llvm.org/ce/z/y_Bcdd
markrvmurray pushed a commit to markrvmurray/llvm-mc6809 that referenced this pull request Jun 14, 2026
…180555)

Same as llvm/llvm-project#177988, but for
fminimum_num/fmaximum_num. Directly canonicalize these to the
corresponding intrinsics, and let the shrinking happen directly on the
intrinsics.
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.

3 participants