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

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 18:43:34 PDT 2026


=?utf-8?q?Dávid_Bolvanský?= <david.bolvansky at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/228805 at github.com>


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Dávid Bolvanský (davidbolvansky)

<details>
<summary>Changes</summary>

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.


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


3 Files Affected:

- (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+1-1) 
- (modified) llvm/test/Transforms/InstCombine/double-float-shrink-1.ll (+26-8) 
- (added) llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll (+71) 


``````````diff
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
new file mode 100644
index 0000000000000..011019b669a01
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/log-intrinsic-double-float-shrink.ll
@@ -0,0 +1,71 @@
+; 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:    [[TRUNC:%.*]] = call fast float @llvm.log.f32(float [[X]])
+; 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:    [[TRUNC:%.*]] = call fast float @llvm.log2.f32(float [[X]])
+; 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:    [[TRUNC:%.*]] = call fast float @llvm.log10.f32(float [[X]])
+; 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)

``````````

</details>


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


More information about the llvm-commits mailing list