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:
parent
54bded776c
commit
13285d512d
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
130
gcc/testsuite/gcc.dg/tree-ssa/pr34244.c
Normal file
130
gcc/testsuite/gcc.dg/tree-ssa/pr34244.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user