[llvm] [InstCombine] Shrink fast logarithm intrinsics to float (PR #228805)

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 18:42:57 PDT 2026


https://github.com/davidbolvansky created https://github.com/llvm/llvm-project/pull/228805

Allow the existing unsafe double-to-float shrink for `llvm.log`, `llvm.log2` and `llvm.log10`. The current libc availability check looks for names such as `llvm.log10.f64f`, so it blocks intrinsic overloads. Keep the existing fast-math, input-precision and result-use requirements.

Motivated by LAME's `calc_noise`, where Clang calls double `log10` but GCC calls `log10f`. On an M1 Pro, the actual LLVM patch reduces full encoding from 5.965 s to 5.844 s (**2.0% less time**, five-round medians), with byte-identical MP3 output in this benchmark.

Implemented with assistance from OpenAI Codex.


>From 44d29b7e245ad676175aaa27878e61a1b27b7a16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sun, 4 Oct 2026 03:35:03 +0200
Subject: [PATCH 1/2] [InstCombine] Cover shrinking logarithm intrinsics to
 float

---
 .../log-intrinsic-double-float-shrink.ll      | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll

diff --git a/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll b/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
new file mode 100644
index 0000000000000..c3c4b3e8598f2
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+; Logarithm intrinsics have an overloaded float version regardless of libc names.
+define float @log_shrink(float %x) {
+; CHECK-LABEL: define float @log_shrink(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+  %ext = fpext float %x to double
+  %log = call fast double @llvm.log.f64(double %ext)
+  %trunc = fptrunc double %log to float
+  ret float %trunc
+}
+
+define float @log2_shrink(float %x) {
+; CHECK-LABEL: define float @log2_shrink(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log2.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+  %ext = fpext float %x to double
+  %log = call fast double @llvm.log2.f64(double %ext)
+  %trunc = fptrunc double %log to float
+  ret float %trunc
+}
+
+define float @log10_shrink(float %x) {
+; CHECK-LABEL: define float @log10_shrink(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log10.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+  %ext = fpext float %x to double
+  %log = call fast double @llvm.log10.f64(double %ext)
+  %trunc = fptrunc double %log to float
+  ret float %trunc
+}
+
+; Preserve precision without the existing unsafe FP shrink permission.
+define float @log10_no_fast_math(float %x) {
+; CHECK-LABEL: define float @log10_no_fast_math(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
+; CHECK-NEXT:    [[LOG:%.*]] = call double @llvm.log10.f64(double [[EXT]])
+; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    ret float [[TRUNC]]
+;
+  %ext = fpext float %x to double
+  %log = call double @llvm.log10.f64(double %ext)
+  %trunc = fptrunc double %log to float
+  ret float %trunc
+}
+
+; A double result cannot be shrunk merely because the argument was float.
+define double @log10_double_result(float %x) {
+; CHECK-LABEL: define double @log10_double_result(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log10.f64(double [[EXT]])
+; CHECK-NEXT:    ret double [[LOG]]
+;
+  %ext = fpext float %x to double
+  %log = call fast double @llvm.log10.f64(double %ext)
+  ret double %log
+}
+
+declare double @llvm.log.f64(double)
+declare double @llvm.log2.f64(double)
+declare double @llvm.log10.f64(double)

>From 78abcd945879dccc473b1343ac1c2793dedcc82f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sun, 4 Oct 2026 03:42:33 +0200
Subject: [PATCH 2/2] [InstCombine] Shrink fast logarithm intrinsics to float

---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp |  2 +-
 .../InstCombine/double-float-shrink-1.ll      | 34 ++++++++++++++-----
 .../log-intrinsic-double-float-shrink.ll      | 12 ++-----
 3 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 6679a0fc4348b..e6668d50e4a0e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2688,7 +2688,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
   Module *Mod = Log->getModule();
   Type *Ty = Log->getType();
 
-  if (UnsafeFPShrink && hasFloatVersion(Mod, LogNm))
+  if (UnsafeFPShrink && (LogFn->isIntrinsic() || hasFloatVersion(Mod, LogNm)))
     if (Value *Ret = optimizeUnaryDoubleFP(Log, B, TLI, true))
       return Ret;
 
diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
index 3b1d1ad016a4f..793e8066e2a0b 100644
--- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
+++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
@@ -248,11 +248,20 @@ define double @exp10_test2(float %f)   {
 }
 
 define float @log_test1(float %f)   {
-; CHECK-LABEL: @log_test1(
-; LINUX-NEXT:    [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F:%.*]])
+; LINUX-LABEL: define float @log_test1(
+; LINUX-SAME: float [[F:%.*]]) {
+; LINUX-NEXT:    [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F]])
 ; LINUX-NEXT:    ret float [[LOGF]]
-; MS32:          [[LOGF:%.*]] = call fast double @llvm.log.f64(double [[F:%.*]])
-; MS64-NEXT:     [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F:%.*]])
+;
+; MS64-LABEL: define float @log_test1(
+; MS64-SAME: float [[F:%.*]]) {
+; MS64-NEXT:    [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F]])
+; MS64-NEXT:    ret float [[LOGF]]
+;
+; MS32-LABEL: define float @log_test1(
+; MS32-SAME: float [[F:%.*]]) {
+; MS32-NEXT:    [[TMP1:%.*]] = call fast float @llvm.log.f32(float [[F]])
+; MS32-NEXT:    ret float [[TMP1]]
 ;
   %conv = fpext float %f to double
   %call = call fast double @log(double %conv)
@@ -272,11 +281,20 @@ define double @log_test2(float %f)   {
 }
 
 define float @log10_test1(float %f)   {
-; CHECK-LABEL: @log10_test1(
-; LINUX-NEXT:    [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F:%.*]])
+; LINUX-LABEL: define float @log10_test1(
+; LINUX-SAME: float [[F:%.*]]) {
+; LINUX-NEXT:    [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F]])
 ; LINUX-NEXT:    ret float [[LOG10F]]
-; MS32:          [[LOG10F:%.*]] = call fast double @llvm.log10.f64(double [[F:%.*]])
-; MS64-NEXT:     [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F:%.*]])
+;
+; MS64-LABEL: define float @log10_test1(
+; MS64-SAME: float [[F:%.*]]) {
+; MS64-NEXT:    [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F]])
+; MS64-NEXT:    ret float [[LOG10F]]
+;
+; MS32-LABEL: define float @log10_test1(
+; MS32-SAME: float [[F:%.*]]) {
+; MS32-NEXT:    [[TMP1:%.*]] = call fast float @llvm.log10.f32(float [[F]])
+; MS32-NEXT:    ret float [[TMP1]]
 ;
   %conv = fpext float %f to double
   %call = call fast double @log10(double %conv)
diff --git a/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll b/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
index c3c4b3e8598f2..011019b669a01 100644
--- a/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
+++ b/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
@@ -5,9 +5,7 @@
 define float @log_shrink(float %x) {
 ; CHECK-LABEL: define float @log_shrink(
 ; CHECK-SAME: float [[X:%.*]]) {
-; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log.f64(double [[EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    [[TRUNC:%.*]] = call fast float @llvm.log.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %ext = fpext float %x to double
@@ -19,9 +17,7 @@ define float @log_shrink(float %x) {
 define float @log2_shrink(float %x) {
 ; CHECK-LABEL: define float @log2_shrink(
 ; CHECK-SAME: float [[X:%.*]]) {
-; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log2.f64(double [[EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    [[TRUNC:%.*]] = call fast float @llvm.log2.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %ext = fpext float %x to double
@@ -33,9 +29,7 @@ define float @log2_shrink(float %x) {
 define float @log10_shrink(float %x) {
 ; CHECK-LABEL: define float @log10_shrink(
 ; CHECK-SAME: float [[X:%.*]]) {
-; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X]] to double
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log10.f64(double [[EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[LOG]] to float
+; CHECK-NEXT:    [[TRUNC:%.*]] = call fast float @llvm.log10.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %ext = fpext float %x to double



More information about the llvm-commits mailing list