llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

Other patterns where clang is not optimal for powi (with fast-math)

Open k-arrows opened this issue 1 year ago • 4 comments

There have been a few missed-optimization issues with pow(x, n) where n is an integer. Here, I will provide some other patterns which aren't mentioned in the existing issues.

Test case(1): https://godbolt.org/z/WGdxTWK6G

#include<math.h>

double f1(double a)
{
   return pow(a, 5) / pow(a, 2);
}

double g1(double a)
{
   return pow(a, 3);
}

If we rewrite / pow(a, 2) as * pow(a, -2), we won't have a problem.

Test case(2): https://godbolt.org/z/W6nWzhfss

#include<math.h>

double f2(double a, double b)
{
   return pow(a, -2) * pow(b, -2);
}

double g2(double a, double b)
{
   return pow(a * b, -2);
}

Related existing issues: https://github.com/llvm/llvm-project/issues/67216 https://github.com/llvm/llvm-project/issues/69862

k-arrows avatar Jan 06 '24 03:01 k-arrows

I think this is a backend issue. After the middleend, the optimizer compiles the code to the following:

define dso_local nofpclass(nan inf) double @f1(double noundef nofpclass(nan inf) %a) local_unnamed_addr {
entry:
  tail call void @llvm.dbg.value(metadata double %a, metadata !16, metadata !DIExpression())
  %0 = tail call fast double @llvm.powi.f64.i32(double %a, i32 5)
  %square = fmul fast double %a, %a
  %div = fdiv fast double %0, %square
  ret double %div
}

I don't think the optimizer can simplify any further.

gandhi56 avatar Jan 07 '24 04:01 gandhi56

@llvm/issue-subscribers-backend-x86

Author: None (k-arrows)

There have been a few missed-optimization issues with `pow(x, n)` where `n` is an integer. Here, I will provide some other patterns which aren't mentioned in the existing issues.

Test case(1): https://godbolt.org/z/WGdxTWK6G

#include&lt;math.h&gt;

double f1(double a)
{
   return pow(a, 5) / pow(a, 2);
}

double g1(double a)
{
   return pow(a, 3);
}

If we rewrite / pow(a, 2) as * pow(a, -2), we won't have a problem.

Test case(2): https://godbolt.org/z/W6nWzhfss

#include&lt;math.h&gt;

double f2(double a, double b)
{
   return pow(a, -2) * pow(b, -2);
}

double g2(double a, double b)
{
   return pow(a * b, -2);
}

Related existing issues: https://github.com/llvm/llvm-project/issues/67216 https://github.com/llvm/llvm-project/issues/69862

llvmbot avatar Jan 09 '24 16:01 llvmbot

aarch64 also has such issue, https://godbolt.org/z/T6KqKKfsP

vfdff avatar Mar 24 '24 09:03 vfdff

@llvm/issue-subscribers-backend-aarch64

Author: None (k-arrows)

There have been a few missed-optimization issues with `pow(x, n)` where `n` is an integer. Here, I will provide some other patterns which aren't mentioned in the existing issues.

Test case(1): https://godbolt.org/z/WGdxTWK6G

#include&lt;math.h&gt;

double f1(double a)
{
   return pow(a, 5) / pow(a, 2);
}

double g1(double a)
{
   return pow(a, 3);
}

If we rewrite / pow(a, 2) as * pow(a, -2), we won't have a problem.

Test case(2): https://godbolt.org/z/W6nWzhfss

#include&lt;math.h&gt;

double f2(double a, double b)
{
   return pow(a, -2) * pow(b, -2);
}

double g2(double a, double b)
{
   return pow(a * b, -2);
}

Related existing issues: https://github.com/llvm/llvm-project/issues/67216 https://github.com/llvm/llvm-project/issues/69862

llvmbot avatar Mar 24 '24 14:03 llvmbot

The above case failed optimize because pow(a, 2) is transform into fma for small value, so pow(a, 500) / pow(a, 200) can transform into pow(a, 300) , https://godbolt.org/z/qqeYbjWfs

vfdff avatar Mar 28 '24 11:03 vfdff