[llvm] Add log-pow simplification for FP exponent edge case. (PR #76641)

via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 30 15:22:34 PST 2023


https://github.com/tanmaysachan created https://github.com/llvm/llvm-project/pull/76641

Fixes https://github.com/llvm/llvm-project/issues/76549

The cause of the optimization miss was -
1. `optimizePow` converting almost integer FP exponents to integer, and turning `pow` to `powi`.
2. `optimizeLog` not accepting `Intrinsic::powi` as a target.

This patch converts constantInt back to constantFP where applicable and adds a test.

>From f83d0eb6c021258110ada1318a67f996ce9e4904 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Sun, 31 Dec 2023 04:41:23 +0530
Subject: [PATCH] Add log-pow simplification for FP exponent edge case.

* Current simplification of pow rounds constant FP exponents to integers if close, and invokes powi(), which blocks `log(pow(x, y)) --> y * log(x)` optimization.
* This patch converts the Integer constant back to FP for log-pow simplification and adds a test-case.
---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp |  8 ++++++--
 llvm/test/Transforms/InstCombine/log-pow.ll    | 11 +++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 760a626c8b6fcb..d2d1518431792c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2495,13 +2495,17 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
 
   // log(pow(x,y)) -> y*log(x)
   AttributeList NoAttrs;
-  if (ArgLb == PowLb || ArgID == Intrinsic::pow) {
+  if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {
     Value *LogX =
         Log->doesNotAccessMemory()
             ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty),
                            Arg->getOperand(0), "log")
             : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
-    Value *MulY = B.CreateFMul(Arg->getArgOperand(1), LogX, "mul");
+    Value *Y = Arg->getArgOperand(1);
+    // If power is integer constant, convert to FP for FMul.
+    if (ConstantInt *C = dyn_cast<ConstantInt>(Y))
+      Y = ConstantFP::get(Ty, C->getSExtValue());
+    Value *MulY = B.CreateFMul(Y, LogX, "mul");
     // Since pow() may have side effects, e.g. errno,
     // dead code elimination may not be trusted to remove it.
     substituteInParent(Arg, MulY);
diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index 58f04da280beee..34b44073fbee32 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -12,6 +12,17 @@ define double @log_pow(double %x, double %y) {
   ret double %log
 }
 
+define double @log_pow_const(double %x) {
+; CHECK-LABEL: @log_pow_const(
+; CHECK-NEXT:    [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[LOG1]], -3.000000e+00
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %pow = call fast double @pow(double %x, double -3.000000e+00)
+  %log = call fast double @log(double %pow)
+  ret double %log
+}
+
 define float @log10f_powf(float %x, float %y) {
 ; CHECK-LABEL: @log10f_powf(
 ; CHECK-NEXT:    [[LOG1:%.*]] = call fast float @llvm.log10.f32(float [[X:%.*]])



More information about the llvm-commits mailing list