[llvm] [InstCombine] Add log-pow simplification for FP exponent edge case. (PR #76641)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 30 17:02:02 PST 2023
https://github.com/tanmaysachan updated https://github.com/llvm/llvm-project/pull/76641
>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 1/2] 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:%.*]])
>From 9a3dbca7f9e719a6ecdab32c1136cdf83b028af6 Mon Sep 17 00:00:00 2001
From: tanmaysachan <tnmysachan at gmail.com>
Date: Sun, 31 Dec 2023 06:31:48 +0530
Subject: [PATCH 2/2] Add nonconst test; handle int to fp nonconst cast
---
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 10 +++++++---
llvm/test/Transforms/InstCombine/log-pow.ll | 18 +++++++++++++++---
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d2d1518431792c..5aaa1d9d09ce3d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2502,9 +2502,13 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
Arg->getOperand(0), "log")
: emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
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());
+ // Cast exponent to FP if integer.
+ if (ArgID == Intrinsic::powi) {
+ if (ConstantInt *C = dyn_cast<ConstantInt>(Y))
+ Y = ConstantFoldCastOperand(Instruction::SIToFP, C, Log->getType(), DL);
+ else
+ Y = B.CreateCast(Instruction::SIToFP, Y, Ty, "cast");
+ }
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.
diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index 34b44073fbee32..c4972f5a0253cb 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -12,13 +12,24 @@ define double @log_pow(double %x, double %y) {
ret double %log
}
-define double @log_pow_const(double %x) {
-; CHECK-LABEL: @log_pow_const(
+define double @log_powi_const(double %x) {
+; CHECK-LABEL: @log_powi_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)
+ %pow = call fast double @llvm.powi.f64.i32(double %x, i32 -3)
+ %log = call fast double @log(double %pow)
+ ret double %log
+}
+
+define double @log_powi_nonconst(double %x, i32 %y) {
+; CHECK-LABEL: @log_powi_nonconst(
+; CHECK-NEXT: [[LOG1:%.*]] = call fast double @llvm.log.f64(double [[X:%.*]])
+; CHECK-NEXT: [[CAST:%.*]] = sitofp i32 [[Y:%.*]] to double
+; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[LOG1]], [[CAST]]
+; CHECK-NEXT: ret double [[MUL]]
+ %pow = call fast double @llvm.powi.f64.i32(double %x, i32 %y)
%log = call fast double @log(double %pow)
ret double %log
}
@@ -139,6 +150,7 @@ declare float @exp10f(float) #0
declare <2 x float> @llvm.exp2.v2f32(<2 x float>)
declare double @pow(double, double) #0
declare float @powf(float, float) #0
+declare double @llvm.powi.f64.i32(double, i32) #0
declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
attributes #0 = { nounwind readnone }
More information about the llvm-commits
mailing list