Commit e2102efc by Xinliang David Li Committed by Xinliang David Li

Multiple exit loop handling in ivopts. Regression tested on x86-64/linux

From-SVN: r162585
parent 01d2a0c1
2010-07-27 Xinliang David Li <davidxl@google.com>
* tree-ssa-loop-ivopts.c (niter_for_exit): New parameter.
(niter_for_single_dom_exit): Passes additional parameter.
(iv_period): Fix comments.
(may_eliminate_iv): Handles multiple exit loops properly.
(free_tree_niter_desc): New function.
(free_loop_data): Frees up loop iteration descriptors.
2010-07-27 Jakub Jelinek <jakub@redhat.com>
PR target/44542
......
......@@ -718,9 +718,10 @@ contains_abnormal_ssa_name_p (tree expr)
EXIT of DATA->current_loop, or NULL if something goes wrong. */
static tree
niter_for_exit (struct ivopts_data *data, edge exit)
niter_for_exit (struct ivopts_data *data, edge exit,
struct tree_niter_desc **desc_p)
{
struct tree_niter_desc desc;
struct tree_niter_desc* desc = NULL;
tree niter;
void **slot;
......@@ -739,19 +740,24 @@ niter_for_exit (struct ivopts_data *data, edge exit)
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). */
desc = XNEW (struct tree_niter_desc);
if (number_of_iterations_exit (data->current_loop,
exit, &desc, true)
&& integer_zerop (desc.may_be_zero)
&& !contains_abnormal_ssa_name_p (desc.niter))
niter = desc.niter;
exit, desc, true)
&& integer_zerop (desc->may_be_zero)
&& !contains_abnormal_ssa_name_p (desc->niter))
niter = desc->niter;
else
niter = NULL_TREE;
*pointer_map_insert (data->niters, exit) = niter;
desc->niter = niter;
slot = pointer_map_insert (data->niters, exit);
*slot = desc;
}
else
niter = (tree) *slot;
niter = ((struct tree_niter_desc *) *slot)->niter;
if (desc_p)
*desc_p = (struct tree_niter_desc *) *slot;
return niter;
}
......@@ -767,7 +773,7 @@ niter_for_single_dom_exit (struct ivopts_data *data)
if (!exit)
return NULL;
return niter_for_exit (data, exit);
return niter_for_exit (data, exit, NULL);
}
/* Initializes data structures used by the iv optimization pass, stored
......@@ -4005,15 +4011,20 @@ iv_period (struct iv *iv)
gcc_assert (step && TREE_CODE (step) == INTEGER_CST);
/* Period of the iv is gcd (step, type range). Since type range is power
of two, it suffices to determine the maximum power of two that divides
step. */
pow2div = num_ending_zeros (step);
type = unsigned_type_for (TREE_TYPE (step));
/* Period of the iv is lcm (step, type_range)/step -1,
i.e., N*type_range/step - 1. Since type range is power
of two, N == (step >> num_of_ending_zeros_binary (step),
so the final result is
(type_range >> num_of_ending_zeros_binary (step)) - 1
*/
pow2div = num_ending_zeros (step);
period = build_low_bits_mask (type,
(TYPE_PRECISION (type)
- tree_low_cst (pow2div, 1)));
(TYPE_PRECISION (type)
- tree_low_cst (pow2div, 1)));
return period;
}
......@@ -4047,6 +4058,7 @@ may_eliminate_iv (struct ivopts_data *data,
tree nit, period;
struct loop *loop = data->current_loop;
aff_tree bnd;
struct tree_niter_desc *desc = NULL;
if (TREE_CODE (cand->iv->step) != INTEGER_CST)
return false;
......@@ -4065,7 +4077,7 @@ may_eliminate_iv (struct ivopts_data *data,
if (flow_bb_inside_loop_p (loop, exit->dest))
return false;
nit = niter_for_exit (data, exit);
nit = niter_for_exit (data, exit, &desc);
if (!nit)
return false;
......@@ -4077,27 +4089,46 @@ may_eliminate_iv (struct ivopts_data *data,
/* If the number of iterations is constant, compare against it directly. */
if (TREE_CODE (nit) == INTEGER_CST)
{
if (!tree_int_cst_lt (nit, period))
return false;
/* See cand_value_at. */
if (stmt_after_increment (loop, cand, use->stmt))
{
if (!tree_int_cst_lt (nit, period))
return false;
}
else
{
if (tree_int_cst_lt (period, nit))
return false;
}
}
/* If not, and if this is the only possible exit of the loop, see whether
we can get a conservative estimate on the number of iterations of the
entire loop and compare against that instead. */
else if (loop_only_exit_p (loop, exit))
else
{
double_int period_value, max_niter;
if (!estimated_loop_iterations (loop, true, &max_niter))
return false;
max_niter = desc->max;
if (stmt_after_increment (loop, cand, use->stmt))
max_niter = double_int_add (max_niter, double_int_one);
period_value = tree_to_double_int (period);
if (double_int_ucmp (max_niter, period_value) >= 0)
return false;
if (double_int_ucmp (max_niter, period_value) > 0)
{
/* See if we can take advantage of infered loop bound information. */
if (loop_only_exit_p (loop, exit))
{
if (!estimated_loop_iterations (loop, true, &max_niter))
return false;
/* The loop bound is already adjusted by adding 1. */
if (double_int_ucmp (max_niter, period_value) > 0)
return false;
}
else
return false;
}
}
/* Otherwise, punt. */
else
return false;
cand_value_at (loop, cand, use->stmt, nit, &bnd);
*bound = aff_combination_to_tree (&bnd);
......@@ -4108,6 +4139,7 @@ may_eliminate_iv (struct ivopts_data *data,
return true;
}
/* Determines cost of basing replacement of USE on CAND in a condition. */
static bool
......@@ -5779,6 +5811,19 @@ remove_unused_ivs (struct ivopts_data *data)
BITMAP_FREE (toremove);
}
/* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback
for pointer_map_traverse. */
static bool
free_tree_niter_desc (const void *key ATTRIBUTE_UNUSED, void **value,
void *data ATTRIBUTE_UNUSED)
{
struct tree_niter_desc *const niter = (struct tree_niter_desc *) *value;
free (niter);
return true;
}
/* Frees data allocated by the optimization of a single loop. */
static void
......@@ -5790,6 +5835,7 @@ free_loop_data (struct ivopts_data *data)
if (data->niters)
{
pointer_map_traverse (data->niters, free_tree_niter_desc, NULL);
pointer_map_destroy (data->niters);
data->niters = NULL;
}
......
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