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.

Reply via email to