llvm-project
llvm-project copied to clipboard
Other patterns where clang is not optimal for powi (with fast-math)
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
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.
@llvm/issue-subscribers-backend-x86
Author: None (k-arrows)
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
aarch64 also has such issue, https://godbolt.org/z/T6KqKKfsP
@llvm/issue-subscribers-backend-aarch64
Author: None (k-arrows)
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
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