Commit 577d6588 by Richard Biener Committed by Richard Biener

re PR tree-optimization/88597 (Compile time hog w/ -O1 -fpeel-loops)

2019-02-01  Richard Biener  <rguenther@suse.de>

	PR middle-end/88597
	* tree-scalar-evolution.c (analyze_scalar_evolution): Set up
	the instantiate cache.
	(instantiate_scev_binary): Elide second operand procesing
	if equal to the first.
	* tree-chrec.c (chrec_contains_symbols): Add visited set.
	(chrec_contains_undetermined): Likewise.
	(tree_contains_chrecs): Likewise.

	* gcc.dg/torture/pr88597.c: New testcase.

From-SVN: r268449
parent 61a8637c
2019-02-01 Richard Biener <rguenther@suse.de>
PR middle-end/88597
* tree-scalar-evolution.c (analyze_scalar_evolution): Set up
the instantiate cache.
(instantiate_scev_binary): Elide second operand procesing
if equal to the first.
* tree-chrec.c (chrec_contains_symbols): Add visited set.
(chrec_contains_undetermined): Likewise.
(tree_contains_chrecs): Likewise.
2019-02-01 Jan Hubicka <hubicka@ucw.cz> 2019-02-01 Jan Hubicka <hubicka@ucw.cz>
* parms.def (MAX_INLINE_INSNS_SINGLE): Reduce from 400 to 200. * parms.def (MAX_INLINE_INSNS_SINGLE): Reduce from 400 to 200.
......
2019-02-01 Richard Biener <rguenther@suse.de> 2019-02-01 Richard Biener <rguenther@suse.de>
PR middle-end/88597
* gcc.dg/torture/pr88597.c: New testcase.
2019-02-01 Richard Biener <rguenther@suse.de>
PR tree-optimization/85497 PR tree-optimization/85497
* gcc.dg/graphite/pr85497.c: New testcase. * gcc.dg/graphite/pr85497.c: New testcase.
......
/* { dg-do compile } */
/* { dg-additional-options "-fpeel-loops --param max-completely-peel-times=30" } */
int
un (int dd)
{
int nz, q8;
for (nz = 0; nz < 3; ++nz)
{
int s2;
q8 = dd;
for (s2 = 0; s2 < 28; ++s2)
q8 *= q8;
}
return q8;
}
...@@ -934,8 +934,8 @@ is_multivariate_chrec (const_tree chrec) ...@@ -934,8 +934,8 @@ is_multivariate_chrec (const_tree chrec)
/* Determines whether the chrec contains symbolic names or not. */ /* Determines whether the chrec contains symbolic names or not. */
bool static bool
chrec_contains_symbols (const_tree chrec) chrec_contains_symbols (const_tree chrec, hash_set<const_tree> &visited)
{ {
int i, n; int i, n;
...@@ -954,15 +954,22 @@ chrec_contains_symbols (const_tree chrec) ...@@ -954,15 +954,22 @@ chrec_contains_symbols (const_tree chrec)
n = TREE_OPERAND_LENGTH (chrec); n = TREE_OPERAND_LENGTH (chrec);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (chrec_contains_symbols (TREE_OPERAND (chrec, i))) if (chrec_contains_symbols (TREE_OPERAND (chrec, i), visited))
return true; return true;
return false; return false;
} }
bool
chrec_contains_symbols (const_tree chrec)
{
hash_set<const_tree> visited;
return chrec_contains_symbols (chrec, visited);
}
/* Determines whether the chrec contains undetermined coefficients. */ /* Determines whether the chrec contains undetermined coefficients. */
bool static bool
chrec_contains_undetermined (const_tree chrec) chrec_contains_undetermined (const_tree chrec, hash_set<const_tree> &visited)
{ {
int i, n; int i, n;
...@@ -972,19 +979,29 @@ chrec_contains_undetermined (const_tree chrec) ...@@ -972,19 +979,29 @@ chrec_contains_undetermined (const_tree chrec)
if (chrec == NULL_TREE) if (chrec == NULL_TREE)
return false; return false;
if (visited.add (chrec))
return false;
n = TREE_OPERAND_LENGTH (chrec); n = TREE_OPERAND_LENGTH (chrec);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (chrec_contains_undetermined (TREE_OPERAND (chrec, i))) if (chrec_contains_undetermined (TREE_OPERAND (chrec, i), visited))
return true; return true;
return false; return false;
} }
bool
chrec_contains_undetermined (const_tree chrec)
{
hash_set<const_tree> visited;
return chrec_contains_undetermined (chrec, visited);
}
/* Determines whether the tree EXPR contains chrecs, and increment /* Determines whether the tree EXPR contains chrecs, and increment
SIZE if it is not a NULL pointer by an estimation of the depth of SIZE if it is not a NULL pointer by an estimation of the depth of
the tree. */ the tree. */
bool static bool
tree_contains_chrecs (const_tree expr, int *size) tree_contains_chrecs (const_tree expr, int *size, hash_set<const_tree> &visited)
{ {
int i, n; int i, n;
...@@ -999,11 +1016,19 @@ tree_contains_chrecs (const_tree expr, int *size) ...@@ -999,11 +1016,19 @@ tree_contains_chrecs (const_tree expr, int *size)
n = TREE_OPERAND_LENGTH (expr); n = TREE_OPERAND_LENGTH (expr);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (tree_contains_chrecs (TREE_OPERAND (expr, i), size)) if (tree_contains_chrecs (TREE_OPERAND (expr, i), size, visited))
return true; return true;
return false; return false;
} }
bool
tree_contains_chrecs (const_tree expr, int *size)
{
hash_set<const_tree> visited;
return tree_contains_chrecs (expr, size, visited);
}
/* Recursive helper function. */ /* Recursive helper function. */
static bool static bool
......
...@@ -380,6 +380,37 @@ find_var_scev_info (basic_block instantiated_below, tree var) ...@@ -380,6 +380,37 @@ find_var_scev_info (basic_block instantiated_below, tree var)
return &res->chrec; return &res->chrec;
} }
/* Hashtable helpers for a temporary hash-table used when
analyzing a scalar evolution, instantiating a CHREC or
resolving mixers. */
struct instantiate_cache_type
{
htab_t map;
vec<scev_info_str> entries;
instantiate_cache_type () : map (NULL), entries (vNULL) {}
~instantiate_cache_type ();
tree get (unsigned slot) { return entries[slot].chrec; }
void set (unsigned slot, tree chrec) { entries[slot].chrec = chrec; }
};
instantiate_cache_type::~instantiate_cache_type ()
{
if (map != NULL)
{
htab_delete (map);
entries.release ();
}
}
/* Cache to avoid infinite recursion when instantiating an SSA name.
Live during the outermost analyze_scalar_evolution, instantiate_scev
or resolve_mixers call. */
static instantiate_cache_type *global_cache;
/* Return true when CHREC contains symbolic names defined in /* Return true when CHREC contains symbolic names defined in
LOOP_NB. */ LOOP_NB. */
...@@ -2117,7 +2148,22 @@ analyze_scalar_evolution (struct loop *loop, tree var) ...@@ -2117,7 +2148,22 @@ analyze_scalar_evolution (struct loop *loop, tree var)
res = get_scalar_evolution (block_before_loop (loop), var); res = get_scalar_evolution (block_before_loop (loop), var);
if (res == chrec_not_analyzed_yet) if (res == chrec_not_analyzed_yet)
res = analyze_scalar_evolution_1 (loop, var); {
/* We'll recurse into instantiate_scev, avoid tearing down the
instantiate cache repeatedly and keep it live from here. */
bool destr = false;
if (!global_cache)
{
global_cache = new instantiate_cache_type;
destr = true;
}
res = analyze_scalar_evolution_1 (loop, var);
if (destr)
{
delete global_cache;
global_cache = NULL;
}
}
if (dump_file && (dump_flags & TDF_SCEV)) if (dump_file && (dump_flags & TDF_SCEV))
fprintf (dump_file, ")\n"); fprintf (dump_file, ")\n");
...@@ -2231,34 +2277,6 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop, ...@@ -2231,34 +2277,6 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
} }
/* Hashtable helpers for a temporary hash-table used when
instantiating a CHREC or resolving mixers. For this use
instantiated_below is always the same. */
struct instantiate_cache_type
{
htab_t map;
vec<scev_info_str> entries;
instantiate_cache_type () : map (NULL), entries (vNULL) {}
~instantiate_cache_type ();
tree get (unsigned slot) { return entries[slot].chrec; }
void set (unsigned slot, tree chrec) { entries[slot].chrec = chrec; }
};
instantiate_cache_type::~instantiate_cache_type ()
{
if (map != NULL)
{
htab_delete (map);
entries.release ();
}
}
/* Cache to avoid infinite recursion when instantiating an SSA name.
Live during the outermost instantiate_scev or resolve_mixers call. */
static instantiate_cache_type *global_cache;
/* Computes a hash function for database element ELT. */ /* Computes a hash function for database element ELT. */
static inline hashval_t static inline hashval_t
...@@ -2562,10 +2580,18 @@ instantiate_scev_binary (edge instantiate_below, ...@@ -2562,10 +2580,18 @@ instantiate_scev_binary (edge instantiate_below,
if (op0 == chrec_dont_know) if (op0 == chrec_dont_know)
return chrec_dont_know; return chrec_dont_know;
op1 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop, /* While we eventually compute the same op1 if c0 == c1 the process
c1, fold_conversions, size_expr); of doing this is expensive so the following short-cut prevents
if (op1 == chrec_dont_know) exponential compile-time behavior. */
return chrec_dont_know; if (c0 != c1)
{
op1 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop,
c1, fold_conversions, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
}
else
op1 = op0;
if (c0 != op0 if (c0 != op0
|| c1 != op1) || c1 != op1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment