https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128511
Bug ID: 128511
Summary: chrec_fold_multiply_poly_poly mishandles polynomial
CHREC_RIGHT
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ptomsich at gcc dot gnu.org
Target Milestone: ---
Observed on 15.2.1 and trunk @ 06c476d19270
Final value replacement computes a wrong value for a reduction whose loop body
is the product of two polynomials in the induction variable, when at least one
of the factors is itself of degree >= 2.
$ cat pr.c
int main (void)
{
int r = 0;
for (int i = 0; i < 100; i++)
r += i * i - i * i * i;
__builtin_printf ("%d\n", r);
return 0;
}
$ gcc -O0 pr.c && ./a.out
-24174150
$ gcc -O2 pr.c && ./a.out
-16008300
The correct value is sum_{i<100} (i^2 - i^3) = 328350 - 24502500 =
-24174150. Reproduces at -O2 and -O3 with gcc 15.2.1 (Fedora) and with
trunk at 06c476d19270 on aarch64-linux-gnu. -fno-tree-scev-cprop gives
the correct result. A smaller trip count behaves the same once complete
unrolling is prevented: with n = 6 and
-O2 -fdisable-tree-cunrolli -fdisable-tree-cunroll the result is -100
instead of -170. The same wrong value comes out when the loop sits in a
function with the trip count known only after inlining, which is how I
ran into it (a devirtualized std::function handler inlined into a loop).
Sums of a single power are fine (sum i^2, i^3, i^4 are all correct); it
takes the product of a linear and a quadratic CHREC.