Commit 623b8e0a by Martin Liska Committed by Martin Liska

Enhance dumps of IVOPTS

	* tree-ssa-loop-ivopts.c (avg_loop_niter): Fix coding style.
	(struct cost_pair): Change inv_expr_id (int) to inv_expr
	(iv_inv_expr_ent *).
	(struct iv_inv_expr_ent): Comment struct fields.
	(sort_iv_inv_expr_ent): New function.
	(struct ivopts_data): Rename inv_expr_id to max_inv_expr_id.
	(struct iv_ca): Replace used_inv_expr and num_used_inv_expr with
	a hash_map between iv_inv_expr_ent and number of usages.
	(niter_for_exit): Fix coding style.
	(tree_ssa_iv_optimize_init): Use renamed variable.
	(determine_base_object): Fix coding style.
	(alloc_iv): Likewise.
	(find_interesting_uses_outside): Likewise.
	(add_candidate_1): Likewise.
	(add_standard_iv_candidates): Likewise.
	(set_group_iv_cost): Replace inv_expr_id with inv_expr.
	(prepare_decl_rtl): Fix coding style.
	(get_address_cost): Likewise.
	(get_shiftadd_cost): Likewise.
	(force_expr_to_var_cost): Likewise.
	(compare_aff_trees): Likewise.
	(get_expr_id): Restructure the function.
	(get_loop_invariant_expr_id): Renamed to
	get_loop_invariant_expr.
	(get_computation_cost_at): Replace usage of inv_expr_id with
	inv_expr.
	(get_computation_cost): Likewise.
	(determine_group_iv_cost_generic): Likewise.
	(determine_group_iv_cost_address): Likewise.
	(iv_period): Fix coding style.
	(iv_elimination_compare_lt): Likewise.
	(may_eliminate_iv): Likewise.
	(determine_group_iv_cost_cond):  Replace usage of inv_expr_id with
	inv_expr.
	(determine_group_iv_costs): Dump invariant expressions.
	(iv_ca_recount_cost): Use the newly added hash_map.
	(iv_ca_set_remove_invariants): Fix coding style.
	(iv_ca_set_add_invariants): Fix coding style.
	(iv_ca_set_no_cp): Utilize the newly added hash_map for used
	invariants.
	(iv_ca_set_cp): Likewise.
	(iv_ca_new): Initialize the newly added hash_map and remove
	initialization of fields.
	(iv_ca_free): Delete the hash_map.
	(iv_ca_dump): Dump invariant expressions.
	(iv_ca_extend): Fix coding style.
	(try_add_cand_for): Likewise.
	(create_new_ivs): Dump information about # of avg iterations and
	# of used invariant expressions.
	(rewrite_use_compare): Fix coding style.
	(free_loop_data): Set default value for max_inv_expr_id.
	* g++.dg/tree-ssa/ivopts-3.C: Change test-case to follow
	the new format of dump output.

From-SVN: r236200
parent da7674f6
2016-05-13 Martin Liska <mliska@suse.cz>
* tree-ssa-loop-ivopts.c (avg_loop_niter): Fix coding style.
(struct cost_pair): Change inv_expr_id (int) to inv_expr
(iv_inv_expr_ent *).
(struct iv_inv_expr_ent): Comment struct fields.
(sort_iv_inv_expr_ent): New function.
(struct ivopts_data): Rename inv_expr_id to max_inv_expr_id.
(struct iv_ca): Replace used_inv_expr and num_used_inv_expr with
a hash_map between iv_inv_expr_ent and number of usages.
(niter_for_exit): Fix coding style.
(tree_ssa_iv_optimize_init): Use renamed variable.
(determine_base_object): Fix coding style.
(alloc_iv): Likewise.
(find_interesting_uses_outside): Likewise.
(add_candidate_1): Likewise.
(add_standard_iv_candidates): Likewise.
(set_group_iv_cost): Replace inv_expr_id with inv_expr.
(prepare_decl_rtl): Fix coding style.
(get_address_cost): Likewise.
(get_shiftadd_cost): Likewise.
(force_expr_to_var_cost): Likewise.
(compare_aff_trees): Likewise.
(get_expr_id): Restructure the function.
(get_loop_invariant_expr_id): Renamed to
get_loop_invariant_expr.
(get_computation_cost_at): Replace usage of inv_expr_id with
inv_expr.
(get_computation_cost): Likewise.
(determine_group_iv_cost_generic): Likewise.
(determine_group_iv_cost_address): Likewise.
(iv_period): Fix coding style.
(iv_elimination_compare_lt): Likewise.
(may_eliminate_iv): Likewise.
(determine_group_iv_cost_cond): Replace usage of inv_expr_id with
inv_expr.
(determine_group_iv_costs): Dump invariant expressions.
(iv_ca_recount_cost): Use the newly added hash_map.
(iv_ca_set_remove_invariants): Fix coding style.
(iv_ca_set_add_invariants): Fix coding style.
(iv_ca_set_no_cp): Utilize the newly added hash_map for used
invariants.
(iv_ca_set_cp): Likewise.
(iv_ca_new): Initialize the newly added hash_map and remove
initialization of fields.
(iv_ca_free): Delete the hash_map.
(iv_ca_dump): Dump invariant expressions.
(iv_ca_extend): Fix coding style.
(try_add_cand_for): Likewise.
(create_new_ivs): Dump information about # of avg iterations and
# of used invariant expressions.
(rewrite_use_compare): Fix coding style.
(free_loop_data): Set default value for max_inv_expr_id.
2016-05-13 Ilya Enkovich <ilya.enkovich@intel.com> 2016-05-13 Ilya Enkovich <ilya.enkovich@intel.com>
* cse.c (rest_of_handle_cse): Use cleanup_cfg * cse.c (rest_of_handle_cse): Use cleanup_cfg
......
2016-05-13 Martin Liska <mliska@suse.cz>
* g++.dg/tree-ssa/ivopts-3.C: Change test-case to follow
the new format of dump output.
2016-05-13 Ilya Enkovich <ilya.enkovich@intel.com> 2016-05-13 Ilya Enkovich <ilya.enkovich@intel.com>
* gcc.dg/pr71084.c: New test. * gcc.dg/pr71084.c: New test.
......
...@@ -72,4 +72,4 @@ int main ( int , char** ) { ...@@ -72,4 +72,4 @@ int main ( int , char** ) {
// Verify that on x86_64 and i?86 we use a single IV for the innermost loop // Verify that on x86_64 and i?86 we use a single IV for the innermost loop
// { dg-final { scan-tree-dump "Selected IV set for loop \[0-9\]* at \[^ \]*:64, 1 IVs" "ivopts" { target x86_64-*-* i?86-*-* } } } // { dg-final { scan-tree-dump "Selected IV set for loop \[0-9\]* at \[^ \]*:64, 3 avg niters, 1 expressions, 1 IVs" "ivopts" { target x86_64-*-* i?86-*-* } } }
...@@ -129,7 +129,7 @@ avg_loop_niter (struct loop *loop) ...@@ -129,7 +129,7 @@ avg_loop_niter (struct loop *loop)
{ {
niter = max_stmt_executions_int (loop); niter = max_stmt_executions_int (loop);
if (niter == -1 || niter > AVG_LOOP_NITER (loop)) if (niter == -1 || niter > AVG_LOOP_NITER (loop))
return AVG_LOOP_NITER (loop); return AVG_LOOP_NITER (loop);
} }
return niter; return niter;
...@@ -184,6 +184,8 @@ struct comp_cost ...@@ -184,6 +184,8 @@ struct comp_cost
static const comp_cost no_cost = {0, 0, 0}; static const comp_cost no_cost = {0, 0, 0};
static const comp_cost infinite_cost = {INFTY, INFTY, INFTY}; static const comp_cost infinite_cost = {INFTY, INFTY, INFTY};
struct iv_inv_expr_ent;
/* The candidate - cost pair. */ /* The candidate - cost pair. */
struct cost_pair struct cost_pair
{ {
...@@ -195,7 +197,7 @@ struct cost_pair ...@@ -195,7 +197,7 @@ struct cost_pair
the final value of the iv. For iv elimination, the final value of the iv. For iv elimination,
the new bound to compare with. */ the new bound to compare with. */
enum tree_code comp; /* For iv elimination, the comparison. */ enum tree_code comp; /* For iv elimination, the comparison. */
int inv_expr_id; /* Loop invariant expression id. */ iv_inv_expr_ent *inv_expr; /* Loop invariant expression. */
}; };
/* Use. */ /* Use. */
...@@ -307,13 +309,36 @@ iv_common_cand_hasher::equal (const iv_common_cand *ccand1, ...@@ -307,13 +309,36 @@ iv_common_cand_hasher::equal (const iv_common_cand *ccand1,
} }
/* Loop invariant expression hashtable entry. */ /* Loop invariant expression hashtable entry. */
struct iv_inv_expr_ent struct iv_inv_expr_ent
{ {
/* Tree expression of the entry. */
tree expr; tree expr;
/* Unique indentifier. */
int id; int id;
/* Hash value. */
hashval_t hash; hashval_t hash;
}; };
/* Sort iv_inv_expr_ent pair A and B by id field. */
static int
sort_iv_inv_expr_ent (const void *a, const void *b)
{
const iv_inv_expr_ent * const *e1 = (const iv_inv_expr_ent * const *) (a);
const iv_inv_expr_ent * const *e2 = (const iv_inv_expr_ent * const *) (b);
unsigned id1 = (*e1)->id;
unsigned id2 = (*e2)->id;
if (id1 < id2)
return -1;
else if (id1 > id2)
return 1;
else
return 0;
}
/* Hashtable helpers. */ /* Hashtable helpers. */
struct iv_inv_expr_hasher : free_ptr_hash <iv_inv_expr_ent> struct iv_inv_expr_hasher : free_ptr_hash <iv_inv_expr_ent>
...@@ -363,7 +388,7 @@ struct ivopts_data ...@@ -363,7 +388,7 @@ struct ivopts_data
hash_table<iv_inv_expr_hasher> *inv_expr_tab; hash_table<iv_inv_expr_hasher> *inv_expr_tab;
/* Loop invariant expression id. */ /* Loop invariant expression id. */
int inv_expr_id; int max_inv_expr_id;
/* The bitmap of indices in version_info whose value was changed. */ /* The bitmap of indices in version_info whose value was changed. */
bitmap relevant; bitmap relevant;
...@@ -443,12 +468,8 @@ struct iv_ca ...@@ -443,12 +468,8 @@ struct iv_ca
/* Number of times each invariant is used. */ /* Number of times each invariant is used. */
unsigned *n_invariant_uses; unsigned *n_invariant_uses;
/* The array holding the number of uses of each loop /* Hash set with used invariant expression. */
invariant expressions created by ivopt. */ hash_map <iv_inv_expr_ent *, unsigned> *used_inv_exprs;
unsigned *used_inv_expr;
/* The number of created loop invariants. */
unsigned num_used_inv_expr;
/* Total cost of the assignment. */ /* Total cost of the assignment. */
comp_cost cost; comp_cost cost;
...@@ -840,8 +861,8 @@ niter_for_exit (struct ivopts_data *data, edge exit) ...@@ -840,8 +861,8 @@ niter_for_exit (struct ivopts_data *data, edge exit)
if (!slot) if (!slot)
{ {
/* Try to determine number of iterations. We cannot safely work with ssa /* Try to determine number of iterations. We cannot safely work with ssa
names that appear in phi nodes on abnormal edges, so that we do not names that appear in phi nodes on abnormal edges, so that we do not
create overlapping life ranges for them (PR 27283). */ create overlapping life ranges for them (PR 27283). */
desc = XNEW (struct tree_niter_desc); desc = XNEW (struct tree_niter_desc);
if (!number_of_iterations_exit (data->current_loop, if (!number_of_iterations_exit (data->current_loop,
exit, desc, true) exit, desc, true)
...@@ -888,7 +909,7 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data) ...@@ -888,7 +909,7 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data)
data->vgroups.create (20); data->vgroups.create (20);
data->vcands.create (20); data->vcands.create (20);
data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10); data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10);
data->inv_expr_id = 0; data->max_inv_expr_id = 0;
data->name_expansion_cache = NULL; data->name_expansion_cache = NULL;
data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (10); data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (10);
data->iv_common_cands.create (20); data->iv_common_cands.create (20);
...@@ -930,7 +951,7 @@ determine_base_object (tree expr) ...@@ -930,7 +951,7 @@ determine_base_object (tree expr)
return determine_base_object (TREE_OPERAND (base, 0)); return determine_base_object (TREE_OPERAND (base, 0));
return fold_convert (ptr_type_node, return fold_convert (ptr_type_node,
build_fold_addr_expr (base)); build_fold_addr_expr (base));
case POINTER_PLUS_EXPR: case POINTER_PLUS_EXPR:
return determine_base_object (TREE_OPERAND (expr, 0)); return determine_base_object (TREE_OPERAND (expr, 0));
...@@ -989,7 +1010,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step, ...@@ -989,7 +1010,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
By doing this: By doing this:
1) More accurate cost can be computed for address expressions; 1) More accurate cost can be computed for address expressions;
2) Duplicate candidates won't be created for bases in different 2) Duplicate candidates won't be created for bases in different
forms, like &a[0] and &a. */ forms, like &a[0] and &a. */
STRIP_NOPS (expr); STRIP_NOPS (expr);
if ((TREE_CODE (expr) == ADDR_EXPR && !DECL_P (TREE_OPERAND (expr, 0))) if ((TREE_CODE (expr) == ADDR_EXPR && !DECL_P (TREE_OPERAND (expr, 0)))
|| contain_complex_addr_expr (expr)) || contain_complex_addr_expr (expr))
...@@ -2265,7 +2286,7 @@ find_interesting_uses_outside (struct ivopts_data *data, edge exit) ...@@ -2265,7 +2286,7 @@ find_interesting_uses_outside (struct ivopts_data *data, edge exit)
phi = psi.phi (); phi = psi.phi ();
def = PHI_ARG_DEF_FROM_EDGE (phi, exit); def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
if (!virtual_operand_p (def)) if (!virtual_operand_p (def))
find_interesting_uses_op (data, def); find_interesting_uses_op (data, def);
} }
} }
...@@ -2785,8 +2806,8 @@ add_candidate_1 (struct ivopts_data *data, ...@@ -2785,8 +2806,8 @@ add_candidate_1 (struct ivopts_data *data,
if (operand_equal_p (base, cand->iv->base, 0) if (operand_equal_p (base, cand->iv->base, 0)
&& operand_equal_p (step, cand->iv->step, 0) && operand_equal_p (step, cand->iv->step, 0)
&& (TYPE_PRECISION (TREE_TYPE (base)) && (TYPE_PRECISION (TREE_TYPE (base))
== TYPE_PRECISION (TREE_TYPE (cand->iv->base)))) == TYPE_PRECISION (TREE_TYPE (cand->iv->base))))
break; break;
} }
...@@ -2936,14 +2957,14 @@ add_standard_iv_candidates (struct ivopts_data *data) ...@@ -2936,14 +2957,14 @@ add_standard_iv_candidates (struct ivopts_data *data)
/* The same for a double-integer type if it is still fast enough. */ /* The same for a double-integer type if it is still fast enough. */
if (TYPE_PRECISION if (TYPE_PRECISION
(long_integer_type_node) > TYPE_PRECISION (integer_type_node) (long_integer_type_node) > TYPE_PRECISION (integer_type_node)
&& TYPE_PRECISION (long_integer_type_node) <= BITS_PER_WORD) && TYPE_PRECISION (long_integer_type_node) <= BITS_PER_WORD)
add_candidate (data, build_int_cst (long_integer_type_node, 0), add_candidate (data, build_int_cst (long_integer_type_node, 0),
build_int_cst (long_integer_type_node, 1), true, NULL); build_int_cst (long_integer_type_node, 1), true, NULL);
/* The same for a double-integer type if it is still fast enough. */ /* The same for a double-integer type if it is still fast enough. */
if (TYPE_PRECISION if (TYPE_PRECISION
(long_long_integer_type_node) > TYPE_PRECISION (long_integer_type_node) (long_long_integer_type_node) > TYPE_PRECISION (long_integer_type_node)
&& TYPE_PRECISION (long_long_integer_type_node) <= BITS_PER_WORD) && TYPE_PRECISION (long_long_integer_type_node) <= BITS_PER_WORD)
add_candidate (data, build_int_cst (long_long_integer_type_node, 0), add_candidate (data, build_int_cst (long_long_integer_type_node, 0),
build_int_cst (long_long_integer_type_node, 1), true, NULL); build_int_cst (long_long_integer_type_node, 1), true, NULL);
...@@ -3329,7 +3350,7 @@ static void ...@@ -3329,7 +3350,7 @@ static void
set_group_iv_cost (struct ivopts_data *data, set_group_iv_cost (struct ivopts_data *data,
struct iv_group *group, struct iv_cand *cand, struct iv_group *group, struct iv_cand *cand,
comp_cost cost, bitmap depends_on, tree value, comp_cost cost, bitmap depends_on, tree value,
enum tree_code comp, int inv_expr_id) enum tree_code comp, iv_inv_expr_ent *inv_expr)
{ {
unsigned i, s; unsigned i, s;
...@@ -3346,7 +3367,7 @@ set_group_iv_cost (struct ivopts_data *data, ...@@ -3346,7 +3367,7 @@ set_group_iv_cost (struct ivopts_data *data,
group->cost_map[cand->id].depends_on = depends_on; group->cost_map[cand->id].depends_on = depends_on;
group->cost_map[cand->id].value = value; group->cost_map[cand->id].value = value;
group->cost_map[cand->id].comp = comp; group->cost_map[cand->id].comp = comp;
group->cost_map[cand->id].inv_expr_id = inv_expr_id; group->cost_map[cand->id].inv_expr = inv_expr;
return; return;
} }
...@@ -3367,7 +3388,7 @@ found: ...@@ -3367,7 +3388,7 @@ found:
group->cost_map[i].depends_on = depends_on; group->cost_map[i].depends_on = depends_on;
group->cost_map[i].value = value; group->cost_map[i].value = value;
group->cost_map[i].comp = comp; group->cost_map[i].comp = comp;
group->cost_map[i].inv_expr_id = inv_expr_id; group->cost_map[i].inv_expr = inv_expr;
} }
/* Gets cost of (GROUP, CAND) pair. */ /* Gets cost of (GROUP, CAND) pair. */
...@@ -3454,7 +3475,7 @@ prepare_decl_rtl (tree *expr_p, int *ws, void *data) ...@@ -3454,7 +3475,7 @@ prepare_decl_rtl (tree *expr_p, int *ws, void *data)
continue; continue;
obj = *expr_p; obj = *expr_p;
if (DECL_P (obj) && HAS_RTL_P (obj) && !DECL_RTL_SET_P (obj)) if (DECL_P (obj) && HAS_RTL_P (obj) && !DECL_RTL_SET_P (obj))
x = produce_memory_decl_rtl (obj, regno); x = produce_memory_decl_rtl (obj, regno);
break; break;
case SSA_NAME: case SSA_NAME:
...@@ -3908,7 +3929,7 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -3908,7 +3929,7 @@ get_address_cost (bool symbol_present, bool var_present,
} }
} }
if (i == -1) if (i == -1)
off = 0; off = 0;
data->max_offset = off; data->max_offset = off;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -4040,9 +4061,9 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -4040,9 +4061,9 @@ get_address_cost (bool symbol_present, bool var_present,
However, the symbol will have to be loaded in any case before the However, the symbol will have to be loaded in any case before the
loop (and quite likely we have it in register already), so it does not loop (and quite likely we have it in register already), so it does not
make much sense to penalize them too heavily. So make some final make much sense to penalize them too heavily. So make some final
tweaks for the SYMBOL_PRESENT modes: tweaks for the SYMBOL_PRESENT modes:
If VAR_PRESENT is false, and the mode obtained by changing symbol to If VAR_PRESENT is false, and the mode obtained by changing symbol to
var is cheaper, use this mode with small penalty. var is cheaper, use this mode with small penalty.
If VAR_PRESENT is true, try whether the mode with If VAR_PRESENT is true, try whether the mode with
SYMBOL_PRESENT = false is cheaper even with cost of addition, and SYMBOL_PRESENT = false is cheaper even with cost of addition, and
...@@ -4159,7 +4180,7 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -4159,7 +4180,7 @@ get_address_cost (bool symbol_present, bool var_present,
static bool static bool
get_shiftadd_cost (tree expr, machine_mode mode, comp_cost cost0, get_shiftadd_cost (tree expr, machine_mode mode, comp_cost cost0,
comp_cost cost1, tree mult, bool speed, comp_cost *cost) comp_cost cost1, tree mult, bool speed, comp_cost *cost)
{ {
comp_cost res; comp_cost res;
tree op1 = TREE_OPERAND (expr, 1); tree op1 = TREE_OPERAND (expr, 1);
...@@ -4181,10 +4202,10 @@ get_shiftadd_cost (tree expr, machine_mode mode, comp_cost cost0, ...@@ -4181,10 +4202,10 @@ get_shiftadd_cost (tree expr, machine_mode mode, comp_cost cost0,
/* If the target has a cheap shift-and-add or shift-and-sub instruction, /* If the target has a cheap shift-and-add or shift-and-sub instruction,
use that in preference to a shift insn followed by an add insn. */ use that in preference to a shift insn followed by an add insn. */
sa_cost = (TREE_CODE (expr) != MINUS_EXPR sa_cost = (TREE_CODE (expr) != MINUS_EXPR
? shiftadd_cost (speed, mode, m) ? shiftadd_cost (speed, mode, m)
: (mult_in_op1 : (mult_in_op1
? shiftsub1_cost (speed, mode, m) ? shiftsub1_cost (speed, mode, m)
: shiftsub0_cost (speed, mode, m))); : shiftsub0_cost (speed, mode, m)));
res = new_cost (MIN (as_cost, sa_cost), 0); res = new_cost (MIN (as_cost, sa_cost), 0);
res = add_costs (res, mult_in_op1 ? cost0 : cost1); res = add_costs (res, mult_in_op1 ? cost0 : cost1);
...@@ -4316,20 +4337,20 @@ force_expr_to_var_cost (tree expr, bool speed) ...@@ -4316,20 +4337,20 @@ force_expr_to_var_cost (tree expr, bool speed)
case NEGATE_EXPR: case NEGATE_EXPR:
cost = new_cost (add_cost (speed, mode), 0); cost = new_cost (add_cost (speed, mode), 0);
if (TREE_CODE (expr) != NEGATE_EXPR) if (TREE_CODE (expr) != NEGATE_EXPR)
{ {
tree mult = NULL_TREE; tree mult = NULL_TREE;
comp_cost sa_cost; comp_cost sa_cost;
if (TREE_CODE (op1) == MULT_EXPR) if (TREE_CODE (op1) == MULT_EXPR)
mult = op1; mult = op1;
else if (TREE_CODE (op0) == MULT_EXPR) else if (TREE_CODE (op0) == MULT_EXPR)
mult = op0; mult = op0;
if (mult != NULL_TREE if (mult != NULL_TREE
&& cst_and_fits_in_hwi (TREE_OPERAND (mult, 1)) && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1))
&& get_shiftadd_cost (expr, mode, cost0, cost1, mult, && get_shiftadd_cost (expr, mode, cost0, cost1, mult,
speed, &sa_cost)) speed, &sa_cost))
return sa_cost; return sa_cost;
} }
break; break;
CASE_CONVERT: CASE_CONVERT:
...@@ -4543,18 +4564,18 @@ compare_aff_trees (aff_tree *aff1, aff_tree *aff2) ...@@ -4543,18 +4564,18 @@ compare_aff_trees (aff_tree *aff1, aff_tree *aff2)
for (i = 0; i < aff1->n; i++) for (i = 0; i < aff1->n; i++)
{ {
if (aff1->elts[i].coef != aff2->elts[i].coef) if (aff1->elts[i].coef != aff2->elts[i].coef)
return false; return false;
if (!operand_equal_p (aff1->elts[i].val, aff2->elts[i].val, 0)) if (!operand_equal_p (aff1->elts[i].val, aff2->elts[i].val, 0))
return false; return false;
} }
return true; return true;
} }
/* Stores EXPR in DATA->inv_expr_tab, and assigns it an inv_expr_id. */ /* Stores EXPR in DATA->inv_expr_tab, return pointer to iv_inv_expr_ent. */
static int static iv_inv_expr_ent *
get_expr_id (struct ivopts_data *data, tree expr) record_inv_expr (struct ivopts_data *data, tree expr)
{ {
struct iv_inv_expr_ent ent; struct iv_inv_expr_ent ent;
struct iv_inv_expr_ent **slot; struct iv_inv_expr_ent **slot;
...@@ -4562,25 +4583,27 @@ get_expr_id (struct ivopts_data *data, tree expr) ...@@ -4562,25 +4583,27 @@ get_expr_id (struct ivopts_data *data, tree expr)
ent.expr = expr; ent.expr = expr;
ent.hash = iterative_hash_expr (expr, 0); ent.hash = iterative_hash_expr (expr, 0);
slot = data->inv_expr_tab->find_slot (&ent, INSERT); slot = data->inv_expr_tab->find_slot (&ent, INSERT);
if (*slot)
return (*slot)->id;
*slot = XNEW (struct iv_inv_expr_ent); if (!*slot)
(*slot)->expr = expr; {
(*slot)->hash = ent.hash; *slot = XNEW (struct iv_inv_expr_ent);
(*slot)->id = data->inv_expr_id++; (*slot)->expr = expr;
return (*slot)->id; (*slot)->hash = ent.hash;
(*slot)->id = data->max_inv_expr_id++;
}
return *slot;
} }
/* Returns the pseudo expr id if expression UBASE - RATIO * CBASE /* Returns the invariant expression if expression UBASE - RATIO * CBASE
requires a new compiler generated temporary. Returns -1 otherwise. requires a new compiler generated temporary. Returns -1 otherwise.
ADDRESS_P is a flag indicating if the expression is for address ADDRESS_P is a flag indicating if the expression is for address
computation. */ computation. */
static int static iv_inv_expr_ent *
get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, get_loop_invariant_expr (struct ivopts_data *data, tree ubase,
tree cbase, HOST_WIDE_INT ratio, tree cbase, HOST_WIDE_INT ratio,
bool address_p) bool address_p)
{ {
aff_tree ubase_aff, cbase_aff; aff_tree ubase_aff, cbase_aff;
tree expr, ub, cb; tree expr, ub, cb;
...@@ -4592,7 +4615,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, ...@@ -4592,7 +4615,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
if ((TREE_CODE (ubase) == INTEGER_CST) if ((TREE_CODE (ubase) == INTEGER_CST)
&& (TREE_CODE (cbase) == INTEGER_CST)) && (TREE_CODE (cbase) == INTEGER_CST))
return -1; return NULL;
/* Strips the constant part. */ /* Strips the constant part. */
if (TREE_CODE (ubase) == PLUS_EXPR if (TREE_CODE (ubase) == PLUS_EXPR
...@@ -4600,7 +4623,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, ...@@ -4600,7 +4623,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
|| TREE_CODE (ubase) == POINTER_PLUS_EXPR) || TREE_CODE (ubase) == POINTER_PLUS_EXPR)
{ {
if (TREE_CODE (TREE_OPERAND (ubase, 1)) == INTEGER_CST) if (TREE_CODE (TREE_OPERAND (ubase, 1)) == INTEGER_CST)
ubase = TREE_OPERAND (ubase, 0); ubase = TREE_OPERAND (ubase, 0);
} }
/* Strips the constant part. */ /* Strips the constant part. */
...@@ -4609,60 +4632,60 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, ...@@ -4609,60 +4632,60 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
|| TREE_CODE (cbase) == POINTER_PLUS_EXPR) || TREE_CODE (cbase) == POINTER_PLUS_EXPR)
{ {
if (TREE_CODE (TREE_OPERAND (cbase, 1)) == INTEGER_CST) if (TREE_CODE (TREE_OPERAND (cbase, 1)) == INTEGER_CST)
cbase = TREE_OPERAND (cbase, 0); cbase = TREE_OPERAND (cbase, 0);
} }
if (address_p) if (address_p)
{ {
if (((TREE_CODE (ubase) == SSA_NAME) if (((TREE_CODE (ubase) == SSA_NAME)
|| (TREE_CODE (ubase) == ADDR_EXPR || (TREE_CODE (ubase) == ADDR_EXPR
&& is_gimple_min_invariant (ubase))) && is_gimple_min_invariant (ubase)))
&& (TREE_CODE (cbase) == INTEGER_CST)) && (TREE_CODE (cbase) == INTEGER_CST))
return -1; return NULL;
if (((TREE_CODE (cbase) == SSA_NAME) if (((TREE_CODE (cbase) == SSA_NAME)
|| (TREE_CODE (cbase) == ADDR_EXPR || (TREE_CODE (cbase) == ADDR_EXPR
&& is_gimple_min_invariant (cbase))) && is_gimple_min_invariant (cbase)))
&& (TREE_CODE (ubase) == INTEGER_CST)) && (TREE_CODE (ubase) == INTEGER_CST))
return -1; return NULL;
} }
if (ratio == 1) if (ratio == 1)
{ {
if (operand_equal_p (ubase, cbase, 0)) if (operand_equal_p (ubase, cbase, 0))
return -1; return NULL;
if (TREE_CODE (ubase) == ADDR_EXPR if (TREE_CODE (ubase) == ADDR_EXPR
&& TREE_CODE (cbase) == ADDR_EXPR) && TREE_CODE (cbase) == ADDR_EXPR)
{ {
tree usym, csym; tree usym, csym;
usym = TREE_OPERAND (ubase, 0); usym = TREE_OPERAND (ubase, 0);
csym = TREE_OPERAND (cbase, 0); csym = TREE_OPERAND (cbase, 0);
if (TREE_CODE (usym) == ARRAY_REF) if (TREE_CODE (usym) == ARRAY_REF)
{ {
tree ind = TREE_OPERAND (usym, 1); tree ind = TREE_OPERAND (usym, 1);
if (TREE_CODE (ind) == INTEGER_CST if (TREE_CODE (ind) == INTEGER_CST
&& tree_fits_shwi_p (ind) && tree_fits_shwi_p (ind)
&& tree_to_shwi (ind) == 0) && tree_to_shwi (ind) == 0)
usym = TREE_OPERAND (usym, 0); usym = TREE_OPERAND (usym, 0);
} }
if (TREE_CODE (csym) == ARRAY_REF) if (TREE_CODE (csym) == ARRAY_REF)
{ {
tree ind = TREE_OPERAND (csym, 1); tree ind = TREE_OPERAND (csym, 1);
if (TREE_CODE (ind) == INTEGER_CST if (TREE_CODE (ind) == INTEGER_CST
&& tree_fits_shwi_p (ind) && tree_fits_shwi_p (ind)
&& tree_to_shwi (ind) == 0) && tree_to_shwi (ind) == 0)
csym = TREE_OPERAND (csym, 0); csym = TREE_OPERAND (csym, 0);
} }
if (operand_equal_p (usym, csym, 0)) if (operand_equal_p (usym, csym, 0))
return -1; return NULL;
} }
/* Now do more complex comparison */ /* Now do more complex comparison */
tree_to_aff_combination (ubase, TREE_TYPE (ubase), &ubase_aff); tree_to_aff_combination (ubase, TREE_TYPE (ubase), &ubase_aff);
tree_to_aff_combination (cbase, TREE_TYPE (cbase), &cbase_aff); tree_to_aff_combination (cbase, TREE_TYPE (cbase), &cbase_aff);
if (compare_aff_trees (&ubase_aff, &cbase_aff)) if (compare_aff_trees (&ubase_aff, &cbase_aff))
return -1; return NULL;
} }
tree_to_aff_combination (ub, TREE_TYPE (ub), &ubase_aff); tree_to_aff_combination (ub, TREE_TYPE (ub), &ubase_aff);
...@@ -4671,7 +4694,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, ...@@ -4671,7 +4694,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
aff_combination_scale (&cbase_aff, -1 * ratio); aff_combination_scale (&cbase_aff, -1 * ratio);
aff_combination_add (&ubase_aff, &cbase_aff); aff_combination_add (&ubase_aff, &cbase_aff);
expr = aff_combination_to_tree (&ubase_aff); expr = aff_combination_to_tree (&ubase_aff);
return get_expr_id (data, expr); return record_inv_expr (data, expr);
} }
...@@ -4689,7 +4712,7 @@ get_computation_cost_at (struct ivopts_data *data, ...@@ -4689,7 +4712,7 @@ get_computation_cost_at (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand, struct iv_use *use, struct iv_cand *cand,
bool address_p, bitmap *depends_on, gimple *at, bool address_p, bitmap *depends_on, gimple *at,
bool *can_autoinc, bool *can_autoinc,
int *inv_expr_id) iv_inv_expr_ent **inv_expr)
{ {
tree ubase = use->iv->base, ustep = use->iv->step; tree ubase = use->iv->base, ustep = use->iv->step;
tree cbase, cstep; tree cbase, cstep;
...@@ -4790,17 +4813,17 @@ get_computation_cost_at (struct ivopts_data *data, ...@@ -4790,17 +4813,17 @@ get_computation_cost_at (struct ivopts_data *data,
/* Check to see if any adjustment is needed. */ /* Check to see if any adjustment is needed. */
if (cstepi == 0 && stmt_is_after_inc) if (cstepi == 0 && stmt_is_after_inc)
{ {
aff_tree real_cbase_aff; aff_tree real_cbase_aff;
aff_tree cstep_aff; aff_tree cstep_aff;
tree_to_aff_combination (cbase, TREE_TYPE (real_cbase), tree_to_aff_combination (cbase, TREE_TYPE (real_cbase),
&real_cbase_aff); &real_cbase_aff);
tree_to_aff_combination (cstep, TREE_TYPE (cstep), &cstep_aff); tree_to_aff_combination (cstep, TREE_TYPE (cstep), &cstep_aff);
aff_combination_add (&real_cbase_aff, &cstep_aff); aff_combination_add (&real_cbase_aff, &cstep_aff);
real_cbase = aff_combination_to_tree (&real_cbase_aff); real_cbase = aff_combination_to_tree (&real_cbase_aff);
} }
cost = difference_cost (data, cost = difference_cost (data,
ubase, real_cbase, ubase, real_cbase,
...@@ -4846,13 +4869,13 @@ get_computation_cost_at (struct ivopts_data *data, ...@@ -4846,13 +4869,13 @@ get_computation_cost_at (struct ivopts_data *data,
/* Record setup cost in scrach field. */ /* Record setup cost in scrach field. */
cost.scratch = cost.cost; cost.scratch = cost.cost;
if (inv_expr_id && depends_on && *depends_on) if (inv_expr && depends_on && *depends_on)
{ {
*inv_expr_id = *inv_expr = get_loop_invariant_expr (data, ubase, cbase, ratio,
get_loop_invariant_expr_id (data, ubase, cbase, ratio, address_p); address_p);
/* Clear depends on. */ /* Clear depends on. */
if (*inv_expr_id != -1) if (inv_expr != NULL)
bitmap_clear (*depends_on); bitmap_clear (*depends_on);
} }
/* If we are after the increment, the value of the candidate is higher by /* If we are after the increment, the value of the candidate is higher by
...@@ -4929,11 +4952,11 @@ static comp_cost ...@@ -4929,11 +4952,11 @@ static comp_cost
get_computation_cost (struct ivopts_data *data, get_computation_cost (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand, struct iv_use *use, struct iv_cand *cand,
bool address_p, bitmap *depends_on, bool address_p, bitmap *depends_on,
bool *can_autoinc, int *inv_expr_id) bool *can_autoinc, iv_inv_expr_ent **inv_expr)
{ {
return get_computation_cost_at (data, return get_computation_cost_at (data,
use, cand, address_p, depends_on, use->stmt, use, cand, address_p, depends_on, use->stmt,
can_autoinc, inv_expr_id); can_autoinc, inv_expr);
} }
/* Determines cost of computing the use in GROUP with CAND in a generic /* Determines cost of computing the use in GROUP with CAND in a generic
...@@ -4944,7 +4967,7 @@ determine_group_iv_cost_generic (struct ivopts_data *data, ...@@ -4944,7 +4967,7 @@ determine_group_iv_cost_generic (struct ivopts_data *data,
struct iv_group *group, struct iv_cand *cand) struct iv_group *group, struct iv_cand *cand)
{ {
comp_cost cost; comp_cost cost;
int inv_expr_id = -1; iv_inv_expr_ent *inv_expr = NULL;
bitmap depends_on = NULL; bitmap depends_on = NULL;
struct iv_use *use = group->vuses[0]; struct iv_use *use = group->vuses[0];
...@@ -4956,10 +4979,10 @@ determine_group_iv_cost_generic (struct ivopts_data *data, ...@@ -4956,10 +4979,10 @@ determine_group_iv_cost_generic (struct ivopts_data *data,
cost = no_cost; cost = no_cost;
else else
cost = get_computation_cost (data, use, cand, false, cost = get_computation_cost (data, use, cand, false,
&depends_on, NULL, &inv_expr_id); &depends_on, NULL, &inv_expr);
set_group_iv_cost (data, group, cand, cost, depends_on, set_group_iv_cost (data, group, cand, cost, depends_on,
NULL_TREE, ERROR_MARK, inv_expr_id); NULL_TREE, ERROR_MARK, inv_expr);
return !infinite_cost_p (cost); return !infinite_cost_p (cost);
} }
...@@ -4972,12 +4995,12 @@ determine_group_iv_cost_address (struct ivopts_data *data, ...@@ -4972,12 +4995,12 @@ determine_group_iv_cost_address (struct ivopts_data *data,
unsigned i; unsigned i;
bitmap depends_on; bitmap depends_on;
bool can_autoinc, first = true; bool can_autoinc, first = true;
int inv_expr_id = -1; iv_inv_expr_ent *inv_expr = NULL;
struct iv_use *use = group->vuses[0]; struct iv_use *use = group->vuses[0];
comp_cost sum_cost = no_cost, cost; comp_cost sum_cost = no_cost, cost;
cost = get_computation_cost (data, use, cand, true, cost = get_computation_cost (data, use, cand, true,
&depends_on, &can_autoinc, &inv_expr_id); &depends_on, &can_autoinc, &inv_expr);
sum_cost = cost; sum_cost = cost;
if (!infinite_cost_p (sum_cost) && cand->ainc_use == use) if (!infinite_cost_p (sum_cost) && cand->ainc_use == use)
...@@ -5025,7 +5048,7 @@ determine_group_iv_cost_address (struct ivopts_data *data, ...@@ -5025,7 +5048,7 @@ determine_group_iv_cost_address (struct ivopts_data *data,
sum_cost = add_costs (sum_cost, cost); sum_cost = add_costs (sum_cost, cost);
} }
set_group_iv_cost (data, group, cand, sum_cost, depends_on, set_group_iv_cost (data, group, cand, sum_cost, depends_on,
NULL_TREE, ERROR_MARK, inv_expr_id); NULL_TREE, ERROR_MARK, inv_expr);
return !infinite_cost_p (sum_cost); return !infinite_cost_p (sum_cost);
} }
...@@ -5081,8 +5104,8 @@ iv_period (struct iv *iv) ...@@ -5081,8 +5104,8 @@ iv_period (struct iv *iv)
pow2div = num_ending_zeros (step); pow2div = num_ending_zeros (step);
period = build_low_bits_mask (type, period = build_low_bits_mask (type,
(TYPE_PRECISION (type) (TYPE_PRECISION (type)
- tree_to_uhwi (pow2div))); - tree_to_uhwi (pow2div)));
return period; return period;
} }
...@@ -5215,7 +5238,7 @@ difference_cannot_overflow_p (struct ivopts_data *data, tree base, tree offset) ...@@ -5215,7 +5238,7 @@ difference_cannot_overflow_p (struct ivopts_data *data, tree base, tree offset)
static bool static bool
iv_elimination_compare_lt (struct ivopts_data *data, iv_elimination_compare_lt (struct ivopts_data *data,
struct iv_cand *cand, enum tree_code *comp_p, struct iv_cand *cand, enum tree_code *comp_p,
struct tree_niter_desc *niter) struct tree_niter_desc *niter)
{ {
tree cand_type, a, b, mbz, nit_type = TREE_TYPE (niter->niter), offset; tree cand_type, a, b, mbz, nit_type = TREE_TYPE (niter->niter), offset;
...@@ -5264,10 +5287,10 @@ iv_elimination_compare_lt (struct ivopts_data *data, ...@@ -5264,10 +5287,10 @@ iv_elimination_compare_lt (struct ivopts_data *data,
/* Handle b < a + 1. */ /* Handle b < a + 1. */
if (TREE_CODE (op1) == PLUS_EXPR && integer_onep (TREE_OPERAND (op1, 1))) if (TREE_CODE (op1) == PLUS_EXPR && integer_onep (TREE_OPERAND (op1, 1)))
{ {
a = TREE_OPERAND (op1, 0); a = TREE_OPERAND (op1, 0);
b = TREE_OPERAND (mbz, 0); b = TREE_OPERAND (mbz, 0);
} }
else else
return false; return false;
} }
...@@ -5353,15 +5376,15 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -5353,15 +5376,15 @@ may_eliminate_iv (struct ivopts_data *data,
{ {
/* See cand_value_at. */ /* See cand_value_at. */
if (stmt_after_increment (loop, cand, use->stmt)) if (stmt_after_increment (loop, cand, use->stmt))
{ {
if (!tree_int_cst_lt (desc->niter, period)) if (!tree_int_cst_lt (desc->niter, period))
return false; return false;
} }
else else
{ {
if (tree_int_cst_lt (period, desc->niter)) if (tree_int_cst_lt (period, desc->niter))
return false; return false;
} }
} }
/* If not, and if this is the only possible exit of the loop, see whether /* If not, and if this is the only possible exit of the loop, see whether
...@@ -5373,22 +5396,23 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -5373,22 +5396,23 @@ may_eliminate_iv (struct ivopts_data *data,
max_niter = desc->max; max_niter = desc->max;
if (stmt_after_increment (loop, cand, use->stmt)) if (stmt_after_increment (loop, cand, use->stmt))
max_niter += 1; max_niter += 1;
period_value = wi::to_widest (period); period_value = wi::to_widest (period);
if (wi::gtu_p (max_niter, period_value)) if (wi::gtu_p (max_niter, period_value))
{ {
/* See if we can take advantage of inferred loop bound information. */ /* See if we can take advantage of inferred loop bound
if (data->loop_single_exit_p) information. */
{ if (data->loop_single_exit_p)
if (!max_loop_iterations (loop, &max_niter)) {
return false; if (!max_loop_iterations (loop, &max_niter))
/* The loop bound is already adjusted by adding 1. */ return false;
if (wi::gtu_p (max_niter, period_value)) /* The loop bound is already adjusted by adding 1. */
return false; if (wi::gtu_p (max_niter, period_value))
} return false;
else }
return false; else
} return false;
}
} }
cand_value_at (loop, cand, use->stmt, desc->niter, &bnd); cand_value_at (loop, cand, use->stmt, desc->niter, &bnd);
...@@ -5444,7 +5468,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data, ...@@ -5444,7 +5468,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data,
bitmap depends_on_elim = NULL, depends_on_express = NULL, depends_on; bitmap depends_on_elim = NULL, depends_on_express = NULL, depends_on;
comp_cost elim_cost, express_cost, cost, bound_cost; comp_cost elim_cost, express_cost, cost, bound_cost;
bool ok; bool ok;
int elim_inv_expr_id = -1, express_inv_expr_id = -1, inv_expr_id; iv_inv_expr_ent *elim_inv_expr = NULL, *express_inv_expr = NULL, *inv_expr;
tree *control_var, *bound_cst; tree *control_var, *bound_cst;
enum tree_code comp = ERROR_MARK; enum tree_code comp = ERROR_MARK;
struct iv_use *use = group->vuses[0]; struct iv_use *use = group->vuses[0];
...@@ -5456,18 +5480,18 @@ determine_group_iv_cost_cond (struct ivopts_data *data, ...@@ -5456,18 +5480,18 @@ determine_group_iv_cost_cond (struct ivopts_data *data,
{ {
elim_cost = force_var_cost (data, bound, &depends_on_elim); elim_cost = force_var_cost (data, bound, &depends_on_elim);
if (elim_cost.cost == 0) if (elim_cost.cost == 0)
elim_cost.cost = parm_decl_cost (data, bound); elim_cost.cost = parm_decl_cost (data, bound);
else if (TREE_CODE (bound) == INTEGER_CST) else if (TREE_CODE (bound) == INTEGER_CST)
elim_cost.cost = 0; elim_cost.cost = 0;
/* If we replace a loop condition 'i < n' with 'p < base + n', /* If we replace a loop condition 'i < n' with 'p < base + n',
depends_on_elim will have 'base' and 'n' set, which implies depends_on_elim will have 'base' and 'n' set, which implies
that both 'base' and 'n' will be live during the loop. More likely, that both 'base' and 'n' will be live during the loop. More likely,
'base + n' will be loop invariant, resulting in only one live value 'base + n' will be loop invariant, resulting in only one live value
during the loop. So in that case we clear depends_on_elim and set during the loop. So in that case we clear depends_on_elim and set
elim_inv_expr_id instead. */ elim_inv_expr_id instead. */
if (depends_on_elim && bitmap_count_bits (depends_on_elim) > 1) if (depends_on_elim && bitmap_count_bits (depends_on_elim) > 1)
{ {
elim_inv_expr_id = get_expr_id (data, bound); elim_inv_expr = record_inv_expr (data, bound);
bitmap_clear (depends_on_elim); bitmap_clear (depends_on_elim);
} }
/* The bound is a loop invariant, so it will be only computed /* The bound is a loop invariant, so it will be only computed
...@@ -5497,7 +5521,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data, ...@@ -5497,7 +5521,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data,
express_cost = get_computation_cost (data, use, cand, false, express_cost = get_computation_cost (data, use, cand, false,
&depends_on_express, NULL, &depends_on_express, NULL,
&express_inv_expr_id); &express_inv_expr);
fd_ivopts_data = data; fd_ivopts_data = data;
walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL); walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL);
...@@ -5515,7 +5539,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data, ...@@ -5515,7 +5539,7 @@ determine_group_iv_cost_cond (struct ivopts_data *data,
cost = elim_cost; cost = elim_cost;
depends_on = depends_on_elim; depends_on = depends_on_elim;
depends_on_elim = NULL; depends_on_elim = NULL;
inv_expr_id = elim_inv_expr_id; inv_expr = elim_inv_expr;
} }
else else
{ {
...@@ -5524,11 +5548,11 @@ determine_group_iv_cost_cond (struct ivopts_data *data, ...@@ -5524,11 +5548,11 @@ determine_group_iv_cost_cond (struct ivopts_data *data,
depends_on_express = NULL; depends_on_express = NULL;
bound = NULL_TREE; bound = NULL_TREE;
comp = ERROR_MARK; comp = ERROR_MARK;
inv_expr_id = express_inv_expr_id; inv_expr = express_inv_expr;
} }
set_group_iv_cost (data, group, cand, cost, set_group_iv_cost (data, group, cand, cost,
depends_on, bound, comp, inv_expr_id); depends_on, bound, comp, inv_expr);
if (depends_on_elim) if (depends_on_elim)
BITMAP_FREE (depends_on_elim); BITMAP_FREE (depends_on_elim);
...@@ -5718,14 +5742,31 @@ determine_group_iv_costs (struct ivopts_data *data) ...@@ -5718,14 +5742,31 @@ determine_group_iv_costs (struct ivopts_data *data)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "<Group-candidate Costs>:\n"); fprintf (dump_file, "\n<Invariant Expressions>:\n");
auto_vec <iv_inv_expr_ent *> list (data->inv_expr_tab->elements ());
for (hash_table<iv_inv_expr_hasher>::iterator it
= data->inv_expr_tab->begin (); it != data->inv_expr_tab->end ();
++it)
list.safe_push (*it);
list.qsort (sort_iv_inv_expr_ent);
for (i = 0; i < list.length (); ++i)
{
fprintf (dump_file, "inv_expr %d: \t", i);
print_generic_expr (dump_file, list[i]->expr, TDF_SLIM);
fprintf (dump_file, "\n");
}
fprintf (dump_file, "\n<Group-candidate Costs>:\n");
for (i = 0; i < data->vgroups.length (); i++) for (i = 0; i < data->vgroups.length (); i++)
{ {
group = data->vgroups[i]; group = data->vgroups[i];
fprintf (dump_file, "Group %d:\n", i); fprintf (dump_file, "Group %d:\n", i);
fprintf (dump_file, " cand\tcost\tcompl.\tdepends on\n"); fprintf (dump_file, " cand\tcost\tcompl.\tinv.ex.\tdepends on\n");
for (j = 0; j < group->n_map_members; j++) for (j = 0; j < group->n_map_members; j++)
{ {
if (!group->cost_map[j].cand if (!group->cost_map[j].cand
...@@ -5736,12 +5777,14 @@ determine_group_iv_costs (struct ivopts_data *data) ...@@ -5736,12 +5777,14 @@ determine_group_iv_costs (struct ivopts_data *data)
group->cost_map[j].cand->id, group->cost_map[j].cand->id,
group->cost_map[j].cost.cost, group->cost_map[j].cost.cost,
group->cost_map[j].cost.complexity); group->cost_map[j].cost.complexity);
if (group->cost_map[j].inv_expr != NULL)
fprintf (dump_file, "%d\t",
group->cost_map[j].inv_expr->id);
else
fprintf (dump_file, "\t");
if (group->cost_map[j].depends_on) if (group->cost_map[j].depends_on)
bitmap_print (dump_file, bitmap_print (dump_file,
group->cost_map[j].depends_on, "",""); group->cost_map[j].depends_on, "","");
if (group->cost_map[j].inv_expr_id != -1)
fprintf (dump_file, " inv_expr:%d",
group->cost_map[j].inv_expr_id);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
...@@ -5942,7 +5985,8 @@ iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs) ...@@ -5942,7 +5985,8 @@ iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
cost.cost += ivs->cand_cost; cost.cost += ivs->cand_cost;
cost.cost += ivopts_global_cost_for_size (data, cost.cost += ivopts_global_cost_for_size (data,
ivs->n_regs + ivs->num_used_inv_expr); ivs->n_regs
+ ivs->used_inv_exprs->elements ());
ivs->cost = cost; ivs->cost = cost;
} }
...@@ -5962,7 +6006,7 @@ iv_ca_set_remove_invariants (struct iv_ca *ivs, bitmap invs) ...@@ -5962,7 +6006,7 @@ iv_ca_set_remove_invariants (struct iv_ca *ivs, bitmap invs)
{ {
ivs->n_invariant_uses[iid]--; ivs->n_invariant_uses[iid]--;
if (ivs->n_invariant_uses[iid] == 0) if (ivs->n_invariant_uses[iid] == 0)
ivs->n_regs--; ivs->n_regs--;
} }
} }
...@@ -6000,11 +6044,12 @@ iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs, ...@@ -6000,11 +6044,12 @@ iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs,
iv_ca_set_remove_invariants (ivs, cp->depends_on); iv_ca_set_remove_invariants (ivs, cp->depends_on);
if (cp->inv_expr_id != -1) if (cp->inv_expr != NULL)
{ {
ivs->used_inv_expr[cp->inv_expr_id]--; unsigned *slot = ivs->used_inv_exprs->get (cp->inv_expr);
if (ivs->used_inv_expr[cp->inv_expr_id] == 0) --(*slot);
ivs->num_used_inv_expr--; if (*slot == 0)
ivs->used_inv_exprs->remove (cp->inv_expr);
} }
iv_ca_recount_cost (data, ivs); iv_ca_recount_cost (data, ivs);
} }
...@@ -6024,7 +6069,7 @@ iv_ca_set_add_invariants (struct iv_ca *ivs, bitmap invs) ...@@ -6024,7 +6069,7 @@ iv_ca_set_add_invariants (struct iv_ca *ivs, bitmap invs)
{ {
ivs->n_invariant_uses[iid]++; ivs->n_invariant_uses[iid]++;
if (ivs->n_invariant_uses[iid] == 1) if (ivs->n_invariant_uses[iid] == 1)
ivs->n_regs++; ivs->n_regs++;
} }
} }
...@@ -6064,12 +6109,11 @@ iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs, ...@@ -6064,12 +6109,11 @@ iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs,
ivs->cand_use_cost = add_costs (ivs->cand_use_cost, cp->cost); ivs->cand_use_cost = add_costs (ivs->cand_use_cost, cp->cost);
iv_ca_set_add_invariants (ivs, cp->depends_on); iv_ca_set_add_invariants (ivs, cp->depends_on);
if (cp->inv_expr_id != -1) if (cp->inv_expr != NULL)
{ {
ivs->used_inv_expr[cp->inv_expr_id]++; unsigned *slot = &ivs->used_inv_exprs->get_or_insert (cp->inv_expr);
if (ivs->used_inv_expr[cp->inv_expr_id] == 1) ++(*slot);
ivs->num_used_inv_expr++; }
}
iv_ca_recount_cost (data, ivs); iv_ca_recount_cost (data, ivs);
} }
} }
...@@ -6278,9 +6322,8 @@ iv_ca_new (struct ivopts_data *data) ...@@ -6278,9 +6322,8 @@ iv_ca_new (struct ivopts_data *data)
nw->cand_use_cost = no_cost; nw->cand_use_cost = no_cost;
nw->cand_cost = 0; nw->cand_cost = 0;
nw->n_invariant_uses = XCNEWVEC (unsigned, data->max_inv_id + 1); nw->n_invariant_uses = XCNEWVEC (unsigned, data->max_inv_id + 1);
nw->used_inv_exprs = new hash_map <iv_inv_expr_ent *, unsigned> (13);
nw->cost = no_cost; nw->cost = no_cost;
nw->used_inv_expr = XCNEWVEC (unsigned, data->inv_expr_id + 1);
nw->num_used_inv_expr = 0;
return nw; return nw;
} }
...@@ -6294,7 +6337,7 @@ iv_ca_free (struct iv_ca **ivs) ...@@ -6294,7 +6337,7 @@ iv_ca_free (struct iv_ca **ivs)
free ((*ivs)->n_cand_uses); free ((*ivs)->n_cand_uses);
BITMAP_FREE ((*ivs)->cands); BITMAP_FREE ((*ivs)->cands);
free ((*ivs)->n_invariant_uses); free ((*ivs)->n_invariant_uses);
free ((*ivs)->used_inv_expr); delete ((*ivs)->used_inv_exprs);
free (*ivs); free (*ivs);
*ivs = NULL; *ivs = NULL;
} }
...@@ -6304,13 +6347,13 @@ iv_ca_free (struct iv_ca **ivs) ...@@ -6304,13 +6347,13 @@ iv_ca_free (struct iv_ca **ivs)
static void static void
iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs) iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
{ {
const char *pref = " invariants ";
unsigned i; unsigned i;
comp_cost cost = iv_ca_cost (ivs); comp_cost cost = iv_ca_cost (ivs);
fprintf (file, " cost: %d (complexity %d)\n", cost.cost, cost.complexity); fprintf (file, " cost: %d (complexity %d)\n", cost.cost, cost.complexity);
fprintf (file, " cand_cost: %d\n cand_group_cost: %d (complexity %d)\n", fprintf (file, " cand_cost: %d\n cand_group_cost: %d (complexity %d)\n",
ivs->cand_cost, ivs->cand_use_cost.cost, ivs->cand_use_cost.complexity); ivs->cand_cost, ivs->cand_use_cost.cost,
ivs->cand_use_cost.complexity);
bitmap_print (file, ivs->cands, " candidates: ","\n"); bitmap_print (file, ivs->cands, " candidates: ","\n");
for (i = 0; i < ivs->upto; i++) for (i = 0; i < ivs->upto; i++)
...@@ -6324,12 +6367,24 @@ iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs) ...@@ -6324,12 +6367,24 @@ iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
fprintf (file, " group:%d --> ??\n", group->id); fprintf (file, " group:%d --> ??\n", group->id);
} }
const char *pref = "";
fprintf (file, " invariant variables: ");
for (i = 1; i <= data->max_inv_id; i++) for (i = 1; i <= data->max_inv_id; i++)
if (ivs->n_invariant_uses[i]) if (ivs->n_invariant_uses[i])
{ {
fprintf (file, "%s%d", pref, i); fprintf (file, "%s%d", pref, i);
pref = ", "; pref = ", ";
} }
pref = "";
fprintf (file, "\n invariant expressions: ");
for (hash_map<iv_inv_expr_ent *, unsigned>::iterator it
= ivs->used_inv_exprs->begin (); it != ivs->used_inv_exprs->end (); ++it)
{
fprintf (file, "%s%d", pref, (*it).first->id);
pref = ", ";
}
fprintf (file, "\n\n"); fprintf (file, "\n\n");
} }
...@@ -6366,7 +6421,7 @@ iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs, ...@@ -6366,7 +6421,7 @@ iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs,
continue; continue;
if (!min_ncand && !cheaper_cost_pair (new_cp, old_cp)) if (!min_ncand && !cheaper_cost_pair (new_cp, old_cp))
continue; continue;
*delta = iv_ca_delta_add (group, old_cp, new_cp, *delta); *delta = iv_ca_delta_add (group, old_cp, new_cp, *delta);
} }
...@@ -6670,7 +6725,7 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs, ...@@ -6670,7 +6725,7 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
continue; continue;
if (iv_ca_cand_used_p (ivs, cand)) if (iv_ca_cand_used_p (ivs, cand))
continue; continue;
cp = get_group_iv_cost (data, group, cand); cp = get_group_iv_cost (data, group, cand);
if (!cp) if (!cp)
...@@ -6678,7 +6733,7 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs, ...@@ -6678,7 +6733,7 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
iv_ca_set_cp (data, ivs, group, cp); iv_ca_set_cp (data, ivs, group, cp);
act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL, act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL,
true); true);
iv_ca_set_no_cp (data, ivs, group); iv_ca_set_no_cp (data, ivs, group);
act_delta = iv_ca_delta_add (group, NULL, cp, act_delta); act_delta = iv_ca_delta_add (group, NULL, cp, act_delta);
...@@ -6991,12 +7046,16 @@ create_new_ivs (struct ivopts_data *data, struct iv_ca *set) ...@@ -6991,12 +7046,16 @@ create_new_ivs (struct ivopts_data *data, struct iv_ca *set)
if (data->loop_loc != UNKNOWN_LOCATION) if (data->loop_loc != UNKNOWN_LOCATION)
fprintf (dump_file, " at %s:%d", LOCATION_FILE (data->loop_loc), fprintf (dump_file, " at %s:%d", LOCATION_FILE (data->loop_loc),
LOCATION_LINE (data->loop_loc)); LOCATION_LINE (data->loop_loc));
fprintf (dump_file, ", %lu avg niters",
avg_loop_niter (data->current_loop));
fprintf (dump_file, ", %lu expressions",
set->used_inv_exprs->elements ());
fprintf (dump_file, ", %lu IVs:\n", bitmap_count_bits (set->cands)); fprintf (dump_file, ", %lu IVs:\n", bitmap_count_bits (set->cands));
EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi) EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi)
{ {
cand = data->vcands[i]; cand = data->vcands[i];
dump_cand (dump_file, cand); dump_cand (dump_file, cand);
} }
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
} }
...@@ -7251,10 +7310,10 @@ rewrite_use_compare (struct ivopts_data *data, ...@@ -7251,10 +7310,10 @@ rewrite_use_compare (struct ivopts_data *data,
gimple_seq stmts; gimple_seq stmts;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Replacing exit test: "); fprintf (dump_file, "Replacing exit test: ");
print_gimple_stmt (dump_file, use->stmt, 0, TDF_SLIM); print_gimple_stmt (dump_file, use->stmt, 0, TDF_SLIM);
} }
compare = cp->comp; compare = cp->comp;
bound = unshare_expr (fold_convert (var_type, bound)); bound = unshare_expr (fold_convert (var_type, bound));
op = force_gimple_operand (bound, &stmts, true, NULL_TREE); op = force_gimple_operand (bound, &stmts, true, NULL_TREE);
...@@ -7542,7 +7601,7 @@ free_loop_data (struct ivopts_data *data) ...@@ -7542,7 +7601,7 @@ free_loop_data (struct ivopts_data *data)
decl_rtl_to_reset.truncate (0); decl_rtl_to_reset.truncate (0);
data->inv_expr_tab->empty (); data->inv_expr_tab->empty ();
data->inv_expr_id = 0; data->max_inv_expr_id = 0;
data->iv_common_cand_tab->empty (); data->iv_common_cand_tab->empty ();
data->iv_common_cands.truncate (0); data->iv_common_cands.truncate (0);
......
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