re PR tree-optimization/34244 (VRP/SCEV miscompiles Firefox)

PR tree-optimization/34244
	* tree-vrp.c (adjust_range_with_scev): Clear scev cache.
	(record_numbers_of_iterations): New function.
	(execute_vrp): Cache the numbers of iterations of loops.
	* tree-scalar-evolution.c (scev_reset_except_niters):
	New function.
	(scev_reset): Use scev_reset_except_niters.
	* tree-scalar-evolution.h (scev_reset_except_niters): Declare.

	* gcc.dg/tree-ssa/pr34244.c: New test.

From-SVN: r130527
This commit is contained in:
Zdenek Dvorak 2007-11-30 01:32:04 +01:00 committed by Zdenek Dvorak
parent 54bded776c
commit 13285d512d
6 changed files with 191 additions and 1 deletions

View File

@ -1,3 +1,14 @@
2007-11-29 Zdenek Dvorak <ook@ucw.cz>
PR tree-optimization/34244
* tree-vrp.c (adjust_range_with_scev): Clear scev cache.
(record_numbers_of_iterations): New function.
(execute_vrp): Cache the numbers of iterations of loops.
* tree-scalar-evolution.c (scev_reset_except_niters):
New function.
(scev_reset): Use scev_reset_except_niters.
* tree-scalar-evolution.h (scev_reset_except_niters): Declare.
2007-11-29 Jan Hubicka <jh@suse.cz>
Jakub Jelinek <jakub@redhat.com>

View File

@ -1,3 +1,8 @@
2007-11-29 Zdenek Dvorak <ook@ucw.cz>
PR tree-optimization/34244
* gcc.dg/tree-ssa/pr34244.c: New test.
2007-11-29 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/33434

View File

@ -0,0 +1,130 @@
/* PR tree-optimization/34244 */
/* { dg-do run } */
/* { dg-options "-O2 " } */
int __attribute__((noinline)) GetParent(void)
{
static int count = 0;
count++;
switch (count)
{
case 1:
case 3:
case 4:
return 1;
default:
return 0;
}
}
int __attribute__((noinline)) FindCommonAncestor(int aNode1, int aNode2)
{
if (aNode1 && aNode2) {
int offset = 0;
int anc1 = aNode1;
for (;;) {
++offset;
int parent = GetParent();
if (!parent)
break;
anc1 = parent;
}
int anc2 = aNode2;
for (;;) {
--offset;
int parent = GetParent();
if (!parent)
break;
anc2 = parent;
}
if (anc1 == anc2) {
anc1 = aNode1;
anc2 = aNode2;
while (offset > 0) {
anc1 = GetParent();
--offset;
}
while (offset < 0) {
anc2 = GetParent();
++offset;
}
while (anc1 != anc2) {
anc1 = GetParent();
anc2 = GetParent();
}
return anc1;
}
}
return 0;
}
extern void abort (void);
int main()
{
if (FindCommonAncestor (1, 1) != 0)
abort ();
return 0;
}
/* PR tree-optimization/34244 */
/* { dg-do run } */
/* { dg-options "-O2 " } */
int __attribute__((noinline)) GetParent(void)
{
static int count = 0;
count++;
switch (count)
{
case 1:
case 3:
case 4:
return 1;
default:
return 0;
}
}
int __attribute__((noinline)) FindCommonAncestor(int aNode1, int aNode2)
{
if (aNode1 && aNode2) {
int offset = 0;
int anc1 = aNode1;
for (;;) {
++offset;
int parent = GetParent();
if (!parent)
break;
anc1 = parent;
}
int anc2 = aNode2;
for (;;) {
--offset;
int parent = GetParent();
if (!parent)
break;
anc2 = parent;
}
if (anc1 == anc2) {
anc1 = aNode1;
anc2 = aNode2;
while (offset > 0) {
anc1 = GetParent();
--offset;
}
while (offset < 0) {
anc2 = GetParent();
++offset;
}
while (anc1 != anc2) {
anc1 = GetParent();
anc2 = GetParent();
}
return anc1;
}
}
return 0;
}
extern void abort (void);
int main()
{
if (FindCommonAncestor (1, 1) != 0)
abort ();
return 0;
}

View File

@ -2608,6 +2608,16 @@ scev_initialize (void)
}
}
/* Clean the scalar evolution analysis cache, but preserve the cached
numbers of iterations for the loops. */
void
scev_reset_except_niters (void)
{
if (scalar_evolution_info)
htab_empty (scalar_evolution_info);
}
/* Cleans up the information cached by the scalar evolutions analysis. */
void
@ -2619,7 +2629,8 @@ scev_reset (void)
if (!scalar_evolution_info || !current_loops)
return;
htab_empty (scalar_evolution_info);
scev_reset_except_niters ();
FOR_EACH_LOOP (li, loop, 0)
{
loop->nb_iterations = NULL_TREE;

View File

@ -27,6 +27,7 @@ extern tree get_loop_exit_condition (const struct loop *);
extern void scev_initialize (void);
extern void scev_reset (void);
extern void scev_reset_except_niters (void);
extern void scev_finalize (void);
extern tree analyze_scalar_evolution (struct loop *, tree);
extern tree instantiate_parameters (struct loop *, tree);

View File

@ -2636,6 +2636,13 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
if (vr->type == VR_ANTI_RANGE)
return;
/* Ensure that there are not values in the scev cache based on assumptions
on ranges of ssa names that were changed
(in set_value_range/set_value_range_to_varying). Preserve cached numbers
of iterations, that were computed before the start of VRP (we do not
recompute these each time to save the compile time). */
scev_reset_except_niters ();
chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var));
/* Like in PR19590, scev can return a constant function. */
@ -6047,6 +6054,20 @@ vrp_finalize (void)
vr_phi_edge_counts = NULL;
}
/* Calculates number of iterations for all loops, to ensure that they are
cached. */
static void
record_numbers_of_iterations (void)
{
loop_iterator li;
struct loop *loop;
FOR_EACH_LOOP (li, loop, 0)
{
number_of_latch_executions (loop);
}
}
/* Main entry point to VRP (Value Range Propagation). This pass is
loosely based on J. R. C. Patterson, ``Accurate Static Branch
@ -6101,6 +6122,17 @@ execute_vrp (void)
insert_range_assertions ();
/* Compute the # of iterations for each loop before we start the VRP
analysis. The value ranges determined by VRP are used in expression
simplification, that is also used by the # of iterations analysis.
However, in the middle of the VRP analysis, the value ranges do not take
all the possible paths in CFG into account, so they do not have to be
correct, and the # of iterations analysis can obtain wrong results.
This is a problem, since the results of the # of iterations analysis
are cached, so these mistakes would not be corrected when the value
ranges are corrected. */
record_numbers_of_iterations ();
vrp_initialize ();
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
vrp_finalize ();