Commit dcccd88d by Zdenek Dvorak Committed by Zdenek Dvorak

re PR tree-optimization/27283 (ICE: SSA corruption - Conflict across an abnormal edge)

	PR tree-optimization/27283
	* tree-ssa-loop-ivopts.c (struct nfe_cache_elt): Store just trees,
	not whole # of iteration descriptions.
	(niter_for_exit): Return just # of iterations.  Fail if # of iterations
	uses abnormal ssa name.
	(niter_for_single_dom_exit): Ditto.
	(find_induction_variables, may_eliminate_iv): Expect niter_for_exit to
	return just the number of iterations.

	* g++.dg/tree-ssa/pr27283.C: New test.

From-SVN: r113427
parent a5dfac10
2006-05-01 Zdenek Dvorak <dvorakz@suse.cz> 2006-05-01 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/27283
* tree-ssa-loop-ivopts.c (struct nfe_cache_elt): Store just trees,
not whole # of iteration descriptions.
(niter_for_exit): Return just # of iterations. Fail if # of iterations
uses abnormal ssa name.
(niter_for_single_dom_exit): Ditto.
(find_induction_variables, may_eliminate_iv): Expect niter_for_exit to
return just the number of iterations.
2006-05-01 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/27144 PR tree-optimization/27144
* tree-ssa-loop-niter.c (derive_constant_upper_bound): New function. * tree-ssa-loop-niter.c (derive_constant_upper_bound): New function.
(record_estimate): Only record constant upper bound. (record_estimate): Only record constant upper bound.
......
2006-05-01 Zdenek Dvorak <dvorakz@suse.cz> 2006-05-01 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/27283
* g++.dg/tree-ssa/pr27283.C: New test.
2006-05-01 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/loop-16.c: New test. * gcc.dg/tree-ssa/loop-16.c: New test.
2006-05-01 Roger Sayle <roger@eyesopen.com> 2006-05-01 Roger Sayle <roger@eyesopen.com>
/* { dg-do compile } */
/* { dg-options "-O2" } */
namespace Gambit
{
template < class T > class Array
{
protected:int mindex, maxdex;
T *data;
int InsertAt (const T & t, int n)
{
T *new_data = new T[++this->maxdex - this->mindex + 1] - this->mindex;
int i;
for (i = this->mindex; i <= n - 1; i++)
new_data[i] = this->data[i];
}
public: Array (unsigned int len = 0):mindex (1), maxdex (len),
data ((len) ? new T[len] -
1 : 0)
{
}
virtual ~ Array ()
{
if (maxdex >= mindex)
delete[](data + mindex);
}
const T & operator[] (int index) const
{
}
int Append (const T & t)
{
return InsertAt (t, this->maxdex + 1);
}
};
}
class gIndexOdometer
{
private:Gambit::Array < int >MinIndices;
Gambit::Array < int >CurIndices;
gIndexOdometer (const Gambit::Array < int >, const Gambit::Array < int >);
void SetIndex (const int &, const int &);
int NoIndices () const;
gIndexOdometer AfterExcisionOf (int &) const;
};
gIndexOdometer
gIndexOdometer::AfterExcisionOf (int &to_be_zapped) const
{
Gambit::Array < int >NewMins, NewMaxs;
int i;
for (i = 1; i <= NoIndices (); i++)
{
NewMins.Append (MinIndices[i]);
}
gIndexOdometer NewOdo (NewMins, NewMaxs);
NewOdo.SetIndex (i, CurIndices[i]);
}
...@@ -643,6 +643,86 @@ stmt_after_increment (struct loop *loop, struct iv_cand *cand, tree stmt) ...@@ -643,6 +643,86 @@ stmt_after_increment (struct loop *loop, struct iv_cand *cand, tree stmt)
} }
} }
/* Returns true if EXP is a ssa name that occurs in an abnormal phi node. */
static bool
abnormal_ssa_name_p (tree exp)
{
if (!exp)
return false;
if (TREE_CODE (exp) != SSA_NAME)
return false;
return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
}
/* Returns false if BASE or INDEX contains a ssa name that occurs in an
abnormal phi node. Callback for for_each_index. */
static bool
idx_contains_abnormal_ssa_name_p (tree base, tree *index,
void *data ATTRIBUTE_UNUSED)
{
if (TREE_CODE (base) == ARRAY_REF)
{
if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
return false;
if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
return false;
}
return !abnormal_ssa_name_p (*index);
}
/* Returns true if EXPR contains a ssa name that occurs in an
abnormal phi node. */
static bool
contains_abnormal_ssa_name_p (tree expr)
{
enum tree_code code;
enum tree_code_class class;
if (!expr)
return false;
code = TREE_CODE (expr);
class = TREE_CODE_CLASS (code);
if (code == SSA_NAME)
return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
if (code == INTEGER_CST
|| is_gimple_min_invariant (expr))
return false;
if (code == ADDR_EXPR)
return !for_each_index (&TREE_OPERAND (expr, 0),
idx_contains_abnormal_ssa_name_p,
NULL);
switch (class)
{
case tcc_binary:
case tcc_comparison:
if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
return true;
/* Fallthru. */
case tcc_unary:
if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
return true;
break;
default:
gcc_unreachable ();
}
return false;
}
/* Element of the table in that we cache the numbers of iterations obtained /* Element of the table in that we cache the numbers of iterations obtained
from exits of the loop. */ from exits of the loop. */
...@@ -651,11 +731,9 @@ struct nfe_cache_elt ...@@ -651,11 +731,9 @@ struct nfe_cache_elt
/* The edge for that the number of iterations is cached. */ /* The edge for that the number of iterations is cached. */
edge exit; edge exit;
/* True if the # of iterations was successfully determined. */ /* Number of iterations corresponding to this exit, or NULL if it cannot be
bool valid_p; determined. */
tree niter;
/* Description of # of iterations. */
struct tree_niter_desc niter;
}; };
/* Hash function for nfe_cache_elt E. */ /* Hash function for nfe_cache_elt E. */
...@@ -678,13 +756,14 @@ nfe_eq (const void *e1, const void *e2) ...@@ -678,13 +756,14 @@ nfe_eq (const void *e1, const void *e2)
return elt1->exit == e2; return elt1->exit == e2;
} }
/* Returns structure describing number of iterations determined from /* Returns tree describing number of iterations determined from
EXIT of DATA->current_loop, or NULL if something goes wrong. */ EXIT of DATA->current_loop, or NULL if something goes wrong. */
static struct tree_niter_desc * static tree
niter_for_exit (struct ivopts_data *data, edge exit) niter_for_exit (struct ivopts_data *data, edge exit)
{ {
struct nfe_cache_elt *nfe_desc; struct nfe_cache_elt *nfe_desc;
struct tree_niter_desc desc;
PTR *slot; PTR *slot;
slot = htab_find_slot_with_hash (data->niters, exit, slot = htab_find_slot_with_hash (data->niters, exit,
...@@ -695,25 +774,31 @@ niter_for_exit (struct ivopts_data *data, edge exit) ...@@ -695,25 +774,31 @@ niter_for_exit (struct ivopts_data *data, edge exit)
{ {
nfe_desc = xmalloc (sizeof (struct nfe_cache_elt)); nfe_desc = xmalloc (sizeof (struct nfe_cache_elt));
nfe_desc->exit = exit; nfe_desc->exit = exit;
nfe_desc->valid_p = number_of_iterations_exit (data->current_loop,
exit, &nfe_desc->niter, /* Try to determine number of iterations. We must know it
true); unconditionally (i.e., without possibility of # of iterations
*slot = nfe_desc; being zero). Also, we cannot safely work with ssa names that
appear in phi nodes on abnormal edges, so that we do not create
overlapping life ranges for them (PR 27283). */
if (number_of_iterations_exit (data->current_loop,
exit, &desc, true)
&& zero_p (desc.may_be_zero)
&& !contains_abnormal_ssa_name_p (desc.niter))
nfe_desc->niter = desc.niter;
else
nfe_desc->niter = NULL_TREE;
} }
else else
nfe_desc = *slot; nfe_desc = *slot;
if (!nfe_desc->valid_p) return nfe_desc->niter;
return NULL;
return &nfe_desc->niter;
} }
/* Returns structure describing number of iterations determined from /* Returns tree describing number of iterations determined from
single dominating exit of DATA->current_loop, or NULL if something single dominating exit of DATA->current_loop, or NULL if something
goes wrong. */ goes wrong. */
static struct tree_niter_desc * static tree
niter_for_single_dom_exit (struct ivopts_data *data) niter_for_single_dom_exit (struct ivopts_data *data)
{ {
edge exit = single_dom_exit (data->current_loop); edge exit = single_dom_exit (data->current_loop);
...@@ -869,86 +954,6 @@ determine_biv_step (tree phi) ...@@ -869,86 +954,6 @@ determine_biv_step (tree phi)
return (zero_p (iv.step) ? NULL_TREE : iv.step); return (zero_p (iv.step) ? NULL_TREE : iv.step);
} }
/* Returns true if EXP is a ssa name that occurs in an abnormal phi node. */
static bool
abnormal_ssa_name_p (tree exp)
{
if (!exp)
return false;
if (TREE_CODE (exp) != SSA_NAME)
return false;
return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
}
/* Returns false if BASE or INDEX contains a ssa name that occurs in an
abnormal phi node. Callback for for_each_index. */
static bool
idx_contains_abnormal_ssa_name_p (tree base, tree *index,
void *data ATTRIBUTE_UNUSED)
{
if (TREE_CODE (base) == ARRAY_REF)
{
if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
return false;
if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
return false;
}
return !abnormal_ssa_name_p (*index);
}
/* Returns true if EXPR contains a ssa name that occurs in an
abnormal phi node. */
static bool
contains_abnormal_ssa_name_p (tree expr)
{
enum tree_code code;
enum tree_code_class class;
if (!expr)
return false;
code = TREE_CODE (expr);
class = TREE_CODE_CLASS (code);
if (code == SSA_NAME)
return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
if (code == INTEGER_CST
|| is_gimple_min_invariant (expr))
return false;
if (code == ADDR_EXPR)
return !for_each_index (&TREE_OPERAND (expr, 0),
idx_contains_abnormal_ssa_name_p,
NULL);
switch (class)
{
case tcc_binary:
case tcc_comparison:
if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
return true;
/* Fallthru. */
case tcc_unary:
if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
return true;
break;
default:
gcc_unreachable ();
}
return false;
}
/* Finds basic ivs. */ /* Finds basic ivs. */
static bool static bool
...@@ -1102,20 +1107,13 @@ find_induction_variables (struct ivopts_data *data) ...@@ -1102,20 +1107,13 @@ find_induction_variables (struct ivopts_data *data)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
struct tree_niter_desc *niter; tree niter = niter_for_single_dom_exit (data);
niter = niter_for_single_dom_exit (data);
if (niter) if (niter)
{ {
fprintf (dump_file, " number of iterations "); fprintf (dump_file, " number of iterations ");
print_generic_expr (dump_file, niter->niter, TDF_SLIM); print_generic_expr (dump_file, niter, TDF_SLIM);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n\n");
fprintf (dump_file, " may be zero if ");
print_generic_expr (dump_file, niter->may_be_zero, TDF_SLIM);
fprintf (dump_file, "\n");
fprintf (dump_file, "\n");
}; };
fprintf (dump_file, "Induction variables:\n\n"); fprintf (dump_file, "Induction variables:\n\n");
...@@ -3954,7 +3952,6 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -3954,7 +3952,6 @@ may_eliminate_iv (struct ivopts_data *data,
{ {
basic_block ex_bb; basic_block ex_bb;
edge exit; edge exit;
struct tree_niter_desc *niter;
tree nit, nit_type; tree nit, nit_type;
tree wider_type, period, per_type; tree wider_type, period, per_type;
struct loop *loop = data->current_loop; struct loop *loop = data->current_loop;
...@@ -3977,12 +3974,10 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -3977,12 +3974,10 @@ may_eliminate_iv (struct ivopts_data *data,
if (flow_bb_inside_loop_p (loop, exit->dest)) if (flow_bb_inside_loop_p (loop, exit->dest))
return false; return false;
niter = niter_for_exit (data, exit); nit = niter_for_exit (data, exit);
if (!niter if (!nit)
|| !zero_p (niter->may_be_zero))
return false; return false;
nit = niter->niter;
nit_type = TREE_TYPE (nit); nit_type = TREE_TYPE (nit);
/* Determine whether we may use the variable to test whether niter iterations /* Determine whether we may use the variable to test whether niter iterations
......
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