[PATCH] D102574: [InstCombine] Missed optimization for pow(x, y) * pow(x, z) with fast-math
Daniil Seredkin via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun May 16 04:03:21 PDT 2021
vdsered created this revision.
vdsered added reviewers: spatel, Quolyk.
vdsered added a project: LLVM.
Herald added a subscriber: hiraditya.
vdsered requested review of this revision.
Herald added a subscriber: llvm-commits.
If fast-math is set, then LLVM is free to do the following transformation pow(x, y) * pow(x, z) -> pow(x, y + z). This patch adds tests for this transformation and its implementation. See more https://bugs.llvm.org/show_bug.cgi?id=47205
It handles two cases
1. When operands of fmul are different instructions
%4 = call fast float @llvm.pow.f32(float %0, float %1)
%5 = call fast float @llvm.pow.f32(float %0, float %2)
%6 = fmul fast float %5, %4
-->
%3 = fadd fast float %1, %2
%4 = call fast float @llvm.pow.f32(float %0, float %3)
2. When operands of fmul are the same instruction
%4 = call fast float @llvm.pow.f32(float %0, float %1)
%5 = fmul fast float %4, %4
-->
%3 = fadd fast float %1, %1
%4 = call fast float @llvm.pow.f32(float %0, float %3)
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D102574
Files:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/test/Transforms/InstCombine/fmul-pow.ll
Index: llvm/test/Transforms/InstCombine/fmul-pow.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul-pow.ll
+++ llvm/test/Transforms/InstCombine/fmul-pow.ll
@@ -78,13 +78,23 @@
define double @pow_ab_x_pow_ac_reassoc(double %a, double %b, double %c) {
; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc(
-; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])
-; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP2]], [[TMP1]]
-; CHECK-NEXT: ret double [[MUL]]
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[C:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
+; CHECK-NEXT: ret double [[TMP2]]
;
%1 = call double @llvm.pow.f64(double %a, double %b)
%2 = call double @llvm.pow.f64(double %a, double %c)
%mul = fmul reassoc double %2, %1
ret double %mul
}
+
+define double @pow_ab_reassoc(double %a, double %b) {
+; CHECK-LABEL: @pow_ab_reassoc(
+; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[B:%.*]], [[B]]
+; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
+; CHECK-NEXT: ret double [[TMP2]]
+;
+ %1 = call double @llvm.pow.f64(double %a, double %b)
+ %mul = fmul reassoc double %1, %1
+ ret double %mul
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -462,6 +462,28 @@
return replaceInstUsesWith(I, V);
if (I.hasAllowReassoc()) {
+ // pow(x, y) * pow(x, z) -> pow(x, y + z)
+ // If operands of fmul are equal and they have exactly two uses, then
+ // they have one user. It is useful for a case like the one below
+ //
+ // %2 = pow %0, %1
+ // %3 = fmul %2, %2
+ // -->
+ // %2 = fadd %1, %1
+ // %3 = pow %0, %2
+ if (Op0->hasOneUse() || Op1->hasOneUse() ||
+ (Op1 == Op0 && Op1->hasNUses(2))) {
+ Value *X, *Y, *Z;
+ if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))))
+ if (match(Op1,
+ m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
+ auto NewExpo = Builder.CreateFAdd(Y, Z);
+ auto NewPow = Builder.CreateIntrinsic(Intrinsic::pow, {X->getType()},
+ {X, NewExpo});
+ return replaceInstUsesWith(I, NewPow);
+ }
+ }
+
// Reassociate constant RHS with another constant to form constant
// expression.
if (match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D102574.345697.patch
Type: text/x-patch
Size: 2802 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210516/0a29e118/attachment.bin>
More information about the llvm-commits
mailing list