Improved constant folding for scalar evolution.
authorRoger Sayle <roger@nextmovesoftware.com>
Tue, 10 May 2022 08:38:47 +0000 (09:38 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Tue, 10 May 2022 08:38:47 +0000 (09:38 +0100)
commitdd3c7873a61019e993ee8b79e3695722b13cf945
tree9a7625741a3e4a3e4910524dbf51d0cbd1d19572
parent37083a8d9c68b88b84c8c0d32f4d7b170d6dc6ef
Improved constant folding for scalar evolution.

This patch adds a small (follow-up) optimization to chrec_apply for
linear chrecs to clean-up the final value expressions sometimes generated
by GCC's scalar evolution pass.  The transformation of A+(X-1)*A into
A*X is usually unsafe with respect to overflow (see PR92712), and so
can't be performed by match.pd (or fold-const).  However, during scalar
evolution's evaluation of recurrences it's known that X-1 can't be negative
(in fact X-1 is unsigned even when A is signed), hence this optimization
can be applied.  Interestingly, this expression does get simplified in
later passes once the range of X-1 is bounded by VRP, but that occurs
long after the decision of whether to perform final value replacement,
which is based on the complexity of this expression.

The motivating test case is the optimization of the loop (from comment

int square(int x) {
  int result = 0;
  for (int i = 0; i < x; ++i)
    result += x;
  return result;
}

which is currently optimized, with final value replacement to:

  final value replacement:
   with expr: (int) ((unsigned int) x_3(D) + 4294967295) * x_3(D) + x_3(D)

but with this patch it first gets simplified further:

  final value replacement:
   with expr: x_3(D) * x_3(D)

2022-05-10  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
* tree-chrec.cc (chrec_apply): Attempt to fold the linear chrec
"{a, +, a} (x-1)" as "a*x", as the number of loop iterations, x-1,
can't be negative.

gcc/testsuite/ChangeLog
* gcc.dg/tree-ssa/pr65855-2.c: New test case.
gcc/testsuite/gcc.dg/tree-ssa/pr65855-2.c [new file with mode: 0644]
gcc/tree-chrec.cc