https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127242
Bug ID: 127242
Summary: fre invalidates only the SCEV cache (scev_reset_htab),
leaving nb_iterations_upper_bound stale
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: stevebezalel215 at gmail dot com
Target Milestone: ---
Missed optimization observed in C test suite
gcc.dg/tree-ssa/if-to-switch-8.c, unmodified from the testsuite:
$ gcc -O2 -funswitch-loops -fno-tree-loop-im -c if-to-switch-8.c
(-funswitch-loops creates the peeled copies fre later folds;
-fno-tree-loop-im keeps lim from reshaping the loop first.)
The fre instance running right after cunroll (192t.fre4) folds the
peeled-copy exit tests from IV comparisons into direct comparisons
against the bound, dropping the IVs entirely:
- # i_48 = PHI <0(64)>
- i_60 = i_48 + 1;
- if (i_60 < a.1_18)
+ if (a.1_18 > 1)
After this a fresh estimate_numbers_of_iterations proves the latch
executes at most 2147483646 times; the cache still holds 4294967294.
fre knows it invalidated scalar evolution -- tree-ssa-sccvn.cc:9356 calls
scev_reset_htab () -- but that clears only the SCEV memo, not the caches
derived from it (loop->nb_iterations, bounds, nb_iterations_upper_bound,
estimate_state). Since estimate_numbers_of_iterations early-returns
whenever estimate_state != EST_NOT_COMPUTED, the loose value is sticky
for the rest of the compilation. fre's peers handle exactly this with
free_numbers_of_iterations_estimates on change:
/* tree-ssa-copy.cc:538 */
bool changed = copy_folder.substitute_and_fold ();
if (changed)
free_numbers_of_iterations_estimates (cfun);
/* tree-ssa-dce.cc:2050 */
if (something_changed)
free_numbers_of_iterations_estimates (cfun);
Record_niter_bound keeps a minimum so a tight bound proved early is not
lost, but this cached value is *looser* than a fresh recompute, so keeping
it serves no purpose.