Commit b1b02be2 by Zdenek Dvorak

Makefile.in (tree-ssa-loop-ivopts.o): Add sbitmap.h dependency.

	* Makefile.in (tree-ssa-loop-ivopts.o): Add sbitmap.h dependency.
	* tree-ssa-loop-ivopts.c (struct iv_use): Change semantics of
	related_cands.
	(struct iv_ca, struct iv_ca_delta): New types.
	(tree_ssa_iv_optimize_init): Allocate important_candidates bitmap.
	(record_important_candidates): New.
	(find_iv_candidates): Call record_important_candidates.
	(alloc_use_cost_map): Derive size only from important candidates.
	(set_use_iv_cost, get_use_iv_cost): Use hash-like mechanism to speed
	up searches.
	(determine_use_iv_cost_generic, determine_use_iv_cost_address,
	determine_use_iv_cost_condition, determine_use_iv_cost_outer,
	determine_use_iv_cost): Return whether the use can be expressed by
	the candidate.
	(determine_use_iv_costs): Prune useless candidates from relate_cands
	bitmaps.
	(find_best_candidate, set_cost_up_to, set_cost): Removed.
	(cheaper_cost_pair, iv_ca_recount_cost, iv_ca_set_no_cp,
	iv_ca_set_cp, iv_ca_add_use, iv_ca_cost, iv_ca_has_deps,
	iv_ca_delta_add, iv_ca_cand_for_use, iv_ca_delta_commit,
	iv_ca_cand_used_p, iv_ca_delta_free, iv_ca_new, iv_ca_free,
	iv_ca_dump, iv_ca_extend, iv_ca_narrow): New functions.
	(try_add_cand_for, get_initial_solution, try_improve_iv_set,
	find_optimal_iv_set, create_new_ivs, tree_ssa_iv_optimize_loop):
	Use new iv set representation.
	(free_loop_data): clear important_candidates bitmap.
	(tree_ssa_iv_optimize_finalize): Free important_candidates bitmap.

From-SVN: r90306
parent 3a723ff6
...@@ -1714,7 +1714,7 @@ tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \ ...@@ -1714,7 +1714,7 @@ tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) varray.h $(EXPR_H) \ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) varray.h $(EXPR_H) \
output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \ output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \ tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
cfgloop.h $(PARAMS_H) cfgloop.h $(PARAMS_H) sbitmap.h
tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \ output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
......
...@@ -158,7 +158,8 @@ struct iv_use ...@@ -158,7 +158,8 @@ struct iv_use
struct iv *iv; /* The induction variable it is based on. */ struct iv *iv; /* The induction variable it is based on. */
tree stmt; /* Statement in that it occurs. */ tree stmt; /* Statement in that it occurs. */
tree *op_p; /* The place where it occurs. */ tree *op_p; /* The place where it occurs. */
bitmap related_cands; /* The set of "related" iv candidates. */ bitmap related_cands; /* The set of "related" iv candidates, plus the common
important ones. */
unsigned n_map_members; /* Number of candidates in the cost_map list. */ unsigned n_map_members; /* Number of candidates in the cost_map list. */
struct cost_pair *cost_map; struct cost_pair *cost_map;
...@@ -227,6 +228,58 @@ struct ivopts_data ...@@ -227,6 +228,58 @@ struct ivopts_data
bool consider_all_candidates; bool consider_all_candidates;
}; };
/* An assignment of iv candidates to uses. */
struct iv_ca
{
/* The number of uses covered by the assignment. */
unsigned upto;
/* Number of uses that cannot be expressed by the candidates in the set. */
unsigned bad_uses;
/* Candidate assigned to a use, together with the related costs. */
struct cost_pair **cand_for_use;
/* Number of times each candidate is used. */
unsigned *n_cand_uses;
/* The candidates used. */
bitmap cands;
/* Total number of registers needed. */
unsigned n_regs;
/* Total cost of expressing uses. */
unsigned cand_use_cost;
/* Total cost of candidates. */
unsigned cand_cost;
/* Number of times each invariant is used. */
unsigned *n_invariant_uses;
/* Total cost of the assignment. */
unsigned cost;
};
/* Difference of two iv candidate assignments. */
struct iv_ca_delta
{
/* Changed use. */
struct iv_use *use;
/* An old assignment (for rollback purposes). */
struct cost_pair *old_cp;
/* A new assignment. */
struct cost_pair *new_cp;
/* Next change in the list. */
struct iv_ca_delta *next_change;
};
/* Bound on number of candidates below that all candidates are considered. */ /* Bound on number of candidates below that all candidates are considered. */
#define CONSIDER_ALL_CANDIDATES_BOUND \ #define CONSIDER_ALL_CANDIDATES_BOUND \
...@@ -589,6 +642,7 @@ tree_ssa_iv_optimize_init (struct loops *loops, struct ivopts_data *data) ...@@ -589,6 +642,7 @@ tree_ssa_iv_optimize_init (struct loops *loops, struct ivopts_data *data)
data->version_info = xcalloc (data->version_info_size, data->version_info = xcalloc (data->version_info_size,
sizeof (struct version_info)); sizeof (struct version_info));
data->relevant = BITMAP_XMALLOC (); data->relevant = BITMAP_XMALLOC ();
data->important_candidates = BITMAP_XMALLOC ();
data->max_inv_id = 0; data->max_inv_id = 0;
for (i = 1; i < loops->num; i++) for (i = 1; i < loops->num; i++)
...@@ -1889,6 +1943,45 @@ add_derived_ivs_candidates (struct ivopts_data *data) ...@@ -1889,6 +1943,45 @@ add_derived_ivs_candidates (struct ivopts_data *data)
} }
} }
/* Record important candidates and add them to related_cands bitmaps
if needed. */
static void
record_important_candidates (struct ivopts_data *data)
{
unsigned i;
struct iv_use *use;
for (i = 0; i < n_iv_cands (data); i++)
{
struct iv_cand *cand = iv_cand (data, i);
if (cand->important)
bitmap_set_bit (data->important_candidates, i);
}
data->consider_all_candidates = (n_iv_cands (data)
<= CONSIDER_ALL_CANDIDATES_BOUND);
if (data->consider_all_candidates)
{
/* We will not need "related_cands" bitmaps in this case,
so release them to decrease peak memory consumption. */
for (i = 0; i < n_iv_uses (data); i++)
{
use = iv_use (data, i);
BITMAP_XFREE (use->related_cands);
}
}
else
{
/* Add important candidates to the related_cands bitmaps. */
for (i = 0; i < n_iv_uses (data); i++)
bitmap_ior_into (iv_use (data, i)->related_cands,
data->important_candidates);
}
}
/* Finds the candidates for the induction variables. */ /* Finds the candidates for the induction variables. */
static void static void
...@@ -1902,6 +1995,9 @@ find_iv_candidates (struct ivopts_data *data) ...@@ -1902,6 +1995,9 @@ find_iv_candidates (struct ivopts_data *data)
/* Add induction variables derived from uses. */ /* Add induction variables derived from uses. */
add_derived_ivs_candidates (data); add_derived_ivs_candidates (data);
/* Record the important candidates. */
record_important_candidates (data);
} }
/* Allocates the data structure mapping the (use, candidate) pairs to costs. /* Allocates the data structure mapping the (use, candidate) pairs to costs.
...@@ -1911,17 +2007,7 @@ find_iv_candidates (struct ivopts_data *data) ...@@ -1911,17 +2007,7 @@ find_iv_candidates (struct ivopts_data *data)
static void static void
alloc_use_cost_map (struct ivopts_data *data) alloc_use_cost_map (struct ivopts_data *data)
{ {
unsigned i, n_imp = 0, size, j; unsigned i, size, s, j;
if (!data->consider_all_candidates)
{
for (i = 0; i < n_iv_cands (data); i++)
{
struct iv_cand *cand = iv_cand (data, i);
if (cand->important)
n_imp++;
}
}
for (i = 0; i < n_iv_uses (data); i++) for (i = 0; i < n_iv_uses (data); i++)
{ {
...@@ -1929,20 +2015,21 @@ alloc_use_cost_map (struct ivopts_data *data) ...@@ -1929,20 +2015,21 @@ alloc_use_cost_map (struct ivopts_data *data)
bitmap_iterator bi; bitmap_iterator bi;
if (data->consider_all_candidates) if (data->consider_all_candidates)
{ size = n_iv_cands (data);
size = n_iv_cands (data);
use->n_map_members = size;
}
else else
{ {
size = n_imp; s = 0;
EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi) EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
{ {
size++; s++;
} }
use->n_map_members = 0;
/* Round up to the power of two, so that moduling by it is fast. */
for (size = 1; size < s; size <<= 1)
continue;
} }
use->n_map_members = size;
use->cost_map = xcalloc (size, sizeof (struct cost_pair)); use->cost_map = xcalloc (size, sizeof (struct cost_pair));
} }
} }
...@@ -1955,11 +2042,13 @@ set_use_iv_cost (struct ivopts_data *data, ...@@ -1955,11 +2042,13 @@ set_use_iv_cost (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand, unsigned cost, struct iv_use *use, struct iv_cand *cand, unsigned cost,
bitmap depends_on) bitmap depends_on)
{ {
if (cost == INFTY unsigned i, s;
&& depends_on)
if (cost == INFTY)
{ {
BITMAP_XFREE (depends_on); if (depends_on)
depends_on = NULL; BITMAP_XFREE (depends_on);
return;
} }
if (data->consider_all_candidates) if (data->consider_all_candidates)
...@@ -1970,42 +2059,55 @@ set_use_iv_cost (struct ivopts_data *data, ...@@ -1970,42 +2059,55 @@ set_use_iv_cost (struct ivopts_data *data,
return; return;
} }
if (cost == INFTY) /* n_map_members is a power of two, so this computes modulo. */
return; s = cand->id & (use->n_map_members - 1);
for (i = s; i < use->n_map_members; i++)
if (!use->cost_map[i].cand)
goto found;
for (i = 0; i < s; i++)
if (!use->cost_map[i].cand)
goto found;
gcc_unreachable ();
use->cost_map[use->n_map_members].cand = cand; found:
use->cost_map[use->n_map_members].cost = cost; use->cost_map[i].cand = cand;
use->cost_map[use->n_map_members].depends_on = depends_on; use->cost_map[i].cost = cost;
use->n_map_members++; use->cost_map[i].depends_on = depends_on;
} }
/* Gets cost of (USE, CANDIDATE) pair. Stores the bitmap of dependencies to /* Gets cost of (USE, CANDIDATE) pair. */
DEPENDS_ON. */
static unsigned static struct cost_pair *
get_use_iv_cost (struct ivopts_data *data, get_use_iv_cost (struct ivopts_data *data, struct iv_use *use,
struct iv_use *use, struct iv_cand *cand, bitmap *depends_on) struct iv_cand *cand)
{ {
unsigned i; unsigned i, s;
struct cost_pair *ret;
if (!cand) if (!cand)
return INFTY; return NULL;
if (data->consider_all_candidates) if (data->consider_all_candidates)
i = cand->id;
else
{ {
for (i = 0; i < use->n_map_members; i++) ret = use->cost_map + cand->id;
if (use->cost_map[i].cand == cand) if (!ret->cand)
break; return NULL;
if (i == use->n_map_members) return ret;
return INFTY;
} }
/* n_map_members is a power of two, so this computes modulo. */
s = cand->id & (use->n_map_members - 1);
for (i = s; i < use->n_map_members; i++)
if (use->cost_map[i].cand == cand)
return use->cost_map + i;
if (depends_on) for (i = 0; i < s; i++)
*depends_on = use->cost_map[i].depends_on; if (use->cost_map[i].cand == cand)
return use->cost_map[i].cost; return use->cost_map + i;
return NULL;
} }
/* Returns estimate on cost of computing SEQ. */ /* Returns estimate on cost of computing SEQ. */
...@@ -2948,7 +3050,7 @@ get_computation_cost (struct ivopts_data *data, ...@@ -2948,7 +3050,7 @@ get_computation_cost (struct ivopts_data *data,
/* Determines cost of basing replacement of USE on CAND in a generic /* Determines cost of basing replacement of USE on CAND in a generic
expression. */ expression. */
static void static bool
determine_use_iv_cost_generic (struct ivopts_data *data, determine_use_iv_cost_generic (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
...@@ -2956,11 +3058,13 @@ determine_use_iv_cost_generic (struct ivopts_data *data, ...@@ -2956,11 +3058,13 @@ determine_use_iv_cost_generic (struct ivopts_data *data,
unsigned cost = get_computation_cost (data, use, cand, false, &depends_on); unsigned cost = get_computation_cost (data, use, cand, false, &depends_on);
set_use_iv_cost (data, use, cand, cost, depends_on); set_use_iv_cost (data, use, cand, cost, depends_on);
return cost != INFTY;
} }
/* Determines cost of basing replacement of USE on CAND in an address. */ /* Determines cost of basing replacement of USE on CAND in an address. */
static void static bool
determine_use_iv_cost_address (struct ivopts_data *data, determine_use_iv_cost_address (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
...@@ -2968,6 +3072,8 @@ determine_use_iv_cost_address (struct ivopts_data *data, ...@@ -2968,6 +3072,8 @@ determine_use_iv_cost_address (struct ivopts_data *data,
unsigned cost = get_computation_cost (data, use, cand, true, &depends_on); unsigned cost = get_computation_cost (data, use, cand, true, &depends_on);
set_use_iv_cost (data, use, cand, cost, depends_on); set_use_iv_cost (data, use, cand, cost, depends_on);
return cost != INFTY;
} }
/* Computes value of induction variable IV in iteration NITER. */ /* Computes value of induction variable IV in iteration NITER. */
...@@ -3069,7 +3175,7 @@ may_eliminate_iv (struct loop *loop, ...@@ -3069,7 +3175,7 @@ may_eliminate_iv (struct loop *loop,
/* Determines cost of basing replacement of USE on CAND in a condition. */ /* Determines cost of basing replacement of USE on CAND in a condition. */
static void static bool
determine_use_iv_cost_condition (struct ivopts_data *data, determine_use_iv_cost_condition (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
...@@ -3080,7 +3186,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data, ...@@ -3080,7 +3186,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data,
if (!cand->iv) if (!cand->iv)
{ {
set_use_iv_cost (data, use, cand, INFTY, NULL); set_use_iv_cost (data, use, cand, INFTY, NULL);
return; return false;
} }
if (may_eliminate_iv (data->current_loop, use, cand, &compare, &bound)) if (may_eliminate_iv (data->current_loop, use, cand, &compare, &bound))
...@@ -3089,7 +3195,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data, ...@@ -3089,7 +3195,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data,
unsigned cost = force_var_cost (data, bound, &depends_on); unsigned cost = force_var_cost (data, bound, &depends_on);
set_use_iv_cost (data, use, cand, cost, depends_on); set_use_iv_cost (data, use, cand, cost, depends_on);
return; return cost != INFTY;
} }
/* The induction variable elimination failed; just express the original /* The induction variable elimination failed; just express the original
...@@ -3103,7 +3209,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data, ...@@ -3103,7 +3209,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data,
record_invariant (data, TREE_OPERAND (*use->op_p, 1), true); record_invariant (data, TREE_OPERAND (*use->op_p, 1), true);
} }
determine_use_iv_cost_generic (data, use, cand); return determine_use_iv_cost_generic (data, use, cand);
} }
/* Checks whether it is possible to replace the final value of USE by /* Checks whether it is possible to replace the final value of USE by
...@@ -3135,7 +3241,7 @@ may_replace_final_value (struct loop *loop, struct iv_use *use, tree *value) ...@@ -3135,7 +3241,7 @@ may_replace_final_value (struct loop *loop, struct iv_use *use, tree *value)
/* Determines cost of replacing final value of USE using CAND. */ /* Determines cost of replacing final value of USE using CAND. */
static void static bool
determine_use_iv_cost_outer (struct ivopts_data *data, determine_use_iv_cost_outer (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
...@@ -3150,7 +3256,7 @@ determine_use_iv_cost_outer (struct ivopts_data *data, ...@@ -3150,7 +3256,7 @@ determine_use_iv_cost_outer (struct ivopts_data *data,
if (!may_replace_final_value (loop, use, &value)) if (!may_replace_final_value (loop, use, &value))
{ {
set_use_iv_cost (data, use, cand, INFTY, NULL); set_use_iv_cost (data, use, cand, INFTY, NULL);
return; return false;
} }
depends_on = NULL; depends_on = NULL;
...@@ -3159,7 +3265,7 @@ determine_use_iv_cost_outer (struct ivopts_data *data, ...@@ -3159,7 +3265,7 @@ determine_use_iv_cost_outer (struct ivopts_data *data,
cost /= AVG_LOOP_NITER (loop); cost /= AVG_LOOP_NITER (loop);
set_use_iv_cost (data, use, cand, cost, depends_on); set_use_iv_cost (data, use, cand, cost, depends_on);
return; return cost != INFTY;
} }
exit = single_dom_exit (loop); exit = single_dom_exit (loop);
...@@ -3179,31 +3285,30 @@ determine_use_iv_cost_outer (struct ivopts_data *data, ...@@ -3179,31 +3285,30 @@ determine_use_iv_cost_outer (struct ivopts_data *data,
} }
set_use_iv_cost (data, use, cand, cost, depends_on); set_use_iv_cost (data, use, cand, cost, depends_on);
return cost != INFTY;
} }
/* Determines cost of basing replacement of USE on CAND. */ /* Determines cost of basing replacement of USE on CAND. Returns false
if USE cannot be based on CAND. */
static void static bool
determine_use_iv_cost (struct ivopts_data *data, determine_use_iv_cost (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
switch (use->type) switch (use->type)
{ {
case USE_NONLINEAR_EXPR: case USE_NONLINEAR_EXPR:
determine_use_iv_cost_generic (data, use, cand); return determine_use_iv_cost_generic (data, use, cand);
break;
case USE_OUTER: case USE_OUTER:
determine_use_iv_cost_outer (data, use, cand); return determine_use_iv_cost_outer (data, use, cand);
break;
case USE_ADDRESS: case USE_ADDRESS:
determine_use_iv_cost_address (data, use, cand); return determine_use_iv_cost_address (data, use, cand);
break;
case USE_COMPARE: case USE_COMPARE:
determine_use_iv_cost_condition (data, use, cand); return determine_use_iv_cost_condition (data, use, cand);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -3218,28 +3323,10 @@ determine_use_iv_costs (struct ivopts_data *data) ...@@ -3218,28 +3323,10 @@ determine_use_iv_costs (struct ivopts_data *data)
unsigned i, j; unsigned i, j;
struct iv_use *use; struct iv_use *use;
struct iv_cand *cand; struct iv_cand *cand;
bitmap to_clear = BITMAP_XMALLOC ();
data->consider_all_candidates = (n_iv_cands (data)
<= CONSIDER_ALL_CANDIDATES_BOUND);
alloc_use_cost_map (data); alloc_use_cost_map (data);
if (!data->consider_all_candidates)
{
/* Add the important candidate entries. */
for (j = 0; j < n_iv_cands (data); j++)
{
cand = iv_cand (data, j);
if (!cand->important)
continue;
for (i = 0; i < n_iv_uses (data); i++)
{
use = iv_use (data, i);
determine_use_iv_cost (data, use, cand);
}
}
}
for (i = 0; i < n_iv_uses (data); i++) for (i = 0; i < n_iv_uses (data); i++)
{ {
use = iv_use (data, i); use = iv_use (data, i);
...@@ -3259,12 +3346,19 @@ determine_use_iv_costs (struct ivopts_data *data) ...@@ -3259,12 +3346,19 @@ determine_use_iv_costs (struct ivopts_data *data)
EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi) EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
{ {
cand = iv_cand (data, j); cand = iv_cand (data, j);
if (!cand->important) if (!determine_use_iv_cost (data, use, cand))
determine_use_iv_cost (data, use, cand); bitmap_set_bit (to_clear, j);
} }
/* Remove the candidates for that the cost is infinite from
the list of related candidates. */
bitmap_and_compl_into (use->related_cands, to_clear);
bitmap_clear (to_clear);
} }
} }
BITMAP_XFREE (to_clear);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Use-candidate costs:\n"); fprintf (dump_file, "Use-candidate costs:\n");
...@@ -3451,159 +3545,476 @@ determine_set_costs (struct ivopts_data *data) ...@@ -3451,159 +3545,476 @@ determine_set_costs (struct ivopts_data *data)
} }
} }
/* Finds a best candidate for USE and stores it to CAND. The candidates are /* Returns true if A is a cheaper cost pair than B. */
taken from the set SOL and they may depend on invariants in the set INV.
The really used candidate and invariants are noted to USED_IVS and
USED_INV. */
static unsigned static bool
find_best_candidate (struct ivopts_data *data, cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b)
struct iv_use *use, bitmap sol, bitmap inv,
bitmap used_ivs, bitmap used_inv, struct iv_cand **cand)
{ {
unsigned c, d; if (!a)
unsigned best_cost = INFTY, cost; return false;
struct iv_cand *cnd = NULL, *acnd;
bitmap depends_on = NULL, asol;
bitmap_iterator bi, bi1;
if (data->consider_all_candidates) if (!b)
asol = sol; return true;
else
if (a->cost < b->cost)
return true;
if (a->cost > b->cost)
return false;
/* In case the costs are the same, prefer the cheaper candidate. */
if (a->cand->cost < b->cand->cost)
return true;
return false;
}
/* Computes the cost field of IVS structure. */
static void
iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
{
unsigned cost = 0;
cost += ivs->cand_use_cost;
cost += ivs->cand_cost;
cost += ivopts_global_cost_for_size (data, ivs->n_regs);
ivs->cost = cost;
}
/* Set USE not to be expressed by any candidate in IVS. */
static void
iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_use *use)
{
unsigned uid = use->id, cid, iid;
bitmap deps;
struct cost_pair *cp;
bitmap_iterator bi;
cp = ivs->cand_for_use[uid];
if (!cp)
return;
cid = cp->cand->id;
ivs->bad_uses++;
ivs->cand_for_use[uid] = NULL;
ivs->n_cand_uses[cid]--;
if (ivs->n_cand_uses[cid] == 0)
{ {
asol = BITMAP_XMALLOC (); bitmap_clear_bit (ivs->cands, cid);
/* Do not count the pseudocandidates. */
if (cp->cand->iv)
ivs->n_regs--;
ivs->cand_cost -= cp->cand->cost;
}
ivs->cand_use_cost -= cp->cost;
deps = cp->depends_on;
bitmap_ior (asol, data->important_candidates, use->related_cands); if (deps)
bitmap_and_into (asol, sol); {
EXECUTE_IF_SET_IN_BITMAP (deps, 0, iid, bi)
{
ivs->n_invariant_uses[iid]--;
if (ivs->n_invariant_uses[iid] == 0)
ivs->n_regs--;
}
} }
EXECUTE_IF_SET_IN_BITMAP (asol, 0, c, bi) iv_ca_recount_cost (data, ivs);
}
/* Set cost pair for USE in set IVS to CP. */
static void
iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_use *use, struct cost_pair *cp)
{
unsigned uid = use->id, cid, iid;
bitmap deps;
bitmap_iterator bi;
if (ivs->cand_for_use[uid] == cp)
return;
if (ivs->cand_for_use[uid])
iv_ca_set_no_cp (data, ivs, use);
if (cp)
{ {
acnd = iv_cand (data, c); cid = cp->cand->id;
cost = get_use_iv_cost (data, use, acnd, &depends_on);
if (cost == INFTY) ivs->bad_uses--;
continue; ivs->cand_for_use[uid] = cp;
if (cost > best_cost) ivs->n_cand_uses[cid]++;
continue; if (ivs->n_cand_uses[cid] == 1)
if (cost == best_cost)
{ {
/* Prefer the cheaper iv. */ bitmap_set_bit (ivs->cands, cid);
if (acnd->cost >= cnd->cost) /* Do not count the pseudocandidates. */
continue; if (cp->cand->iv)
ivs->n_regs++;
ivs->cand_cost += cp->cand->cost;
} }
if (depends_on) ivs->cand_use_cost += cp->cost;
deps = cp->depends_on;
if (deps)
{ {
EXECUTE_IF_AND_COMPL_IN_BITMAP (depends_on, inv, 0, d, bi1) EXECUTE_IF_SET_IN_BITMAP (deps, 0, iid, bi)
{ {
goto next_cand; ivs->n_invariant_uses[iid]++;
if (ivs->n_invariant_uses[iid] == 1)
ivs->n_regs++;
} }
if (used_inv)
bitmap_ior_into (used_inv, depends_on);
} }
cnd = acnd; iv_ca_recount_cost (data, ivs);
best_cost = cost;
next_cand: ;
} }
}
/* Extend set IVS by expressing USE by some of the candidates in it
if possible. */
static void
iv_ca_add_use (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_use *use)
{
struct cost_pair *best_cp = NULL, *cp;
bitmap_iterator bi;
unsigned i;
if (cnd && used_ivs) gcc_assert (ivs->upto >= use->id);
bitmap_set_bit (used_ivs, cnd->id);
if (ivs->upto == use->id)
{
ivs->upto++;
ivs->bad_uses++;
}
if (cand) EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, i, bi)
*cand = cnd; {
cp = get_use_iv_cost (data, use, iv_cand (data, i));
if (!data->consider_all_candidates) if (cheaper_cost_pair (cp, best_cp))
BITMAP_XFREE (asol); best_cp = cp;
}
return best_cost; iv_ca_set_cp (data, ivs, use, best_cp);
} }
/* Returns cost of set of ivs SOL + invariants INV. Removes unnecessary /* Get cost for assignment IVS. */
induction variable candidates and invariants from the sets. Only
uses 0 .. MAX_USE - 1 are taken into account. */
static unsigned static unsigned
set_cost_up_to (struct ivopts_data *data, bitmap sol, bitmap inv, iv_ca_cost (struct iv_ca *ivs)
unsigned max_use) {
return (ivs->bad_uses ? INFTY : ivs->cost);
}
/* Returns true if all dependences of CP are among invariants in IVS. */
static bool
iv_ca_has_deps (struct iv_ca *ivs, struct cost_pair *cp)
{ {
unsigned i; unsigned i;
unsigned cost = 0, size = 0, acost;
struct iv_use *use;
struct iv_cand *cand;
bitmap used_ivs = BITMAP_XMALLOC (), used_inv = BITMAP_XMALLOC ();
bitmap_iterator bi; bitmap_iterator bi;
for (i = 0; i < max_use; i++) if (!cp->depends_on)
return true;
EXECUTE_IF_SET_IN_BITMAP (cp->depends_on, 0, i, bi)
{ {
use = iv_use (data, i); if (ivs->n_invariant_uses[i] == 0)
acost = find_best_candidate (data, use, sol, inv, return false;
used_ivs, used_inv, NULL); }
if (acost == INFTY)
return true;
}
/* Creates change of expressing USE by NEW_CP instead of OLD_CP and chains
it before NEXT_CHANGE. */
static struct iv_ca_delta *
iv_ca_delta_add (struct iv_use *use, struct cost_pair *old_cp,
struct cost_pair *new_cp, struct iv_ca_delta *next_change)
{
struct iv_ca_delta *change = xmalloc (sizeof (struct iv_ca_delta));
change->use = use;
change->old_cp = old_cp;
change->new_cp = new_cp;
change->next_change = next_change;
return change;
}
/* Returns candidate by that USE is expressed in IVS. */
static struct cost_pair *
iv_ca_cand_for_use (struct iv_ca *ivs, struct iv_use *use)
{
return ivs->cand_for_use[use->id];
}
/* Commit changes in DELTA to IVS. If FORWARD is false, the changes are
reverted instead. */
static void
iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_ca_delta *delta, bool forward)
{
struct cost_pair *from, *to;
for (; delta; delta = delta->next_change)
{
if (forward)
{ {
BITMAP_XFREE (used_ivs); from = delta->old_cp;
BITMAP_XFREE (used_inv); to = delta->new_cp;
return INFTY; }
else
{
from = delta->new_cp;
to = delta->old_cp;
} }
cost += acost;
gcc_assert (iv_ca_cand_for_use (ivs, delta->use) == from);
iv_ca_set_cp (data, ivs, delta->use, to);
} }
}
EXECUTE_IF_SET_IN_BITMAP (used_ivs, 0, i, bi) /* Returns true if CAND is used in IVS. */
{
cand = iv_cand (data, i);
/* Do not count the pseudocandidates. */ static bool
if (cand->iv) iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand)
size++; {
return ivs->n_cand_uses[cand->id] > 0;
}
cost += cand->cost; /* Free the list of changes DELTA. */
}
EXECUTE_IF_SET_IN_BITMAP (used_inv, 0, i, bi) static void
iv_ca_delta_free (struct iv_ca_delta **delta)
{
struct iv_ca_delta *act, *next;
for (act = *delta; act; act = next)
{ {
size++; next = act->next_change;
free (act);
} }
cost += ivopts_global_cost_for_size (data, size);
bitmap_copy (sol, used_ivs); *delta = NULL;
bitmap_copy (inv, used_inv); }
/* Allocates new iv candidates assignment. */
static struct iv_ca *
iv_ca_new (struct ivopts_data *data)
{
struct iv_ca *nw = xmalloc (sizeof (struct iv_ca));
BITMAP_XFREE (used_ivs); nw->upto = 0;
BITMAP_XFREE (used_inv); nw->bad_uses = 0;
nw->cand_for_use = xcalloc (n_iv_uses (data), sizeof (struct cost_pair *));
nw->n_cand_uses = xcalloc (n_iv_cands (data), sizeof (unsigned));
nw->cands = BITMAP_XMALLOC ();
nw->n_regs = 0;
nw->cand_use_cost = 0;
nw->cand_cost = 0;
nw->n_invariant_uses = xcalloc (data->max_inv_id + 1, sizeof (unsigned));
nw->cost = 0;
return nw;
}
/* Free memory occupied by the set IVS. */
static void
iv_ca_free (struct iv_ca **ivs)
{
free ((*ivs)->cand_for_use);
free ((*ivs)->n_cand_uses);
BITMAP_XFREE ((*ivs)->cands);
free ((*ivs)->n_invariant_uses);
free (*ivs);
*ivs = NULL;
}
/* Dumps IVS to FILE. */
static void
iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
{
const char *pref = " invariants ";
unsigned i;
fprintf (file, " cost %d\n", iv_ca_cost (ivs));
bitmap_print (file, ivs->cands, " candidates ","\n");
for (i = 1; i <= data->max_inv_id; i++)
if (ivs->n_invariant_uses[i])
{
fprintf (file, "%s%d", pref, i);
pref = ", ";
}
fprintf (file, "\n");
}
/* Try changing candidate in IVS to CAND for each use. Return cost of the
new set, and store differences in DELTA. */
static unsigned
iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_cand *cand, struct iv_ca_delta **delta)
{
unsigned i, cost;
struct iv_use *use;
struct cost_pair *old_cp, *new_cp;
*delta = NULL;
for (i = 0; i < ivs->upto; i++)
{
use = iv_use (data, i);
old_cp = iv_ca_cand_for_use (ivs, use);
if (old_cp
&& old_cp->cand == cand)
continue;
new_cp = get_use_iv_cost (data, use, cand);
if (!new_cp)
continue;
if (!iv_ca_has_deps (ivs, new_cp))
continue;
if (!cheaper_cost_pair (new_cp, old_cp))
continue;
*delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
}
iv_ca_delta_commit (data, ivs, *delta, true);
cost = iv_ca_cost (ivs);
iv_ca_delta_commit (data, ivs, *delta, false);
return cost; return cost;
} }
/* Computes cost of set of ivs SOL + invariants INV. Removes unnecessary /* Try narowing set IVS by removing CAND. Return the cost of
induction variable candidates and invariants from the sets. */ the new set and store the differences in DELTA. */
static unsigned static unsigned
set_cost (struct ivopts_data *data, bitmap sol, bitmap inv) iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_cand *cand, struct iv_ca_delta **delta)
{ {
return set_cost_up_to (data, sol, inv, n_iv_uses (data)); unsigned i, ci;
struct iv_use *use;
struct cost_pair *old_cp, *new_cp, *cp;
bitmap_iterator bi;
struct iv_cand *cnd;
unsigned cost;
*delta = NULL;
for (i = 0; i < n_iv_uses (data); i++)
{
use = iv_use (data, i);
old_cp = iv_ca_cand_for_use (ivs, use);
if (old_cp->cand != cand)
continue;
new_cp = NULL;
if (data->consider_all_candidates)
{
EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, ci, bi)
{
if (ci == cand->id)
continue;
cnd = iv_cand (data, ci);
cp = get_use_iv_cost (data, use, cnd);
if (!cp)
continue;
if (!iv_ca_has_deps (ivs, cp))
continue;
if (!cheaper_cost_pair (cp, new_cp))
continue;
new_cp = cp;
}
}
else
{
EXECUTE_IF_AND_IN_BITMAP (use->related_cands, ivs->cands, 0, ci, bi)
{
if (ci == cand->id)
continue;
cnd = iv_cand (data, ci);
cp = get_use_iv_cost (data, use, cnd);
if (!cp)
continue;
if (!iv_ca_has_deps (ivs, cp))
continue;
if (!cheaper_cost_pair (cp, new_cp))
continue;
new_cp = cp;
}
}
if (!new_cp)
{
iv_ca_delta_free (delta);
return INFTY;
}
*delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
}
iv_ca_delta_commit (data, ivs, *delta, true);
cost = iv_ca_cost (ivs);
iv_ca_delta_commit (data, ivs, *delta, false);
return cost;
} }
/* Tries to extend the sets IVS and INV in the best possible way in order /* Tries to extend the sets IVS in the best possible way in order
to express the USE. */ to express the USE. */
static bool static bool
try_add_cand_for (struct ivopts_data *data, bitmap ivs, bitmap inv, try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
struct iv_use *use) struct iv_use *use)
{ {
unsigned best_cost = set_cost_up_to (data, ivs, inv, use->id + 1), act_cost; unsigned best_cost, act_cost;
bitmap best_ivs = BITMAP_XMALLOC ();
bitmap best_inv = BITMAP_XMALLOC ();
bitmap act_ivs = BITMAP_XMALLOC ();
bitmap act_inv = BITMAP_XMALLOC ();
unsigned i; unsigned i;
struct cost_pair *cp;
bitmap_iterator bi; bitmap_iterator bi;
struct iv_cand *cand; struct iv_cand *cand;
bitmap depends_on; struct iv_ca_delta *best_delta = NULL, *act_delta;
struct cost_pair *cp;
iv_ca_add_use (data, ivs, use);
best_cost = iv_ca_cost (ivs);
bitmap_copy (best_ivs, ivs); cp = iv_ca_cand_for_use (ivs, use);
bitmap_copy (best_inv, inv); if (cp)
{
best_delta = iv_ca_delta_add (use, NULL, cp, NULL);
iv_ca_set_no_cp (data, ivs, use);
}
/* First try important candidates. Only if it fails, try the specific ones. /* First try important candidates. Only if it fails, try the specific ones.
Rationale -- in loops with many variables the best choice often is to use Rationale -- in loops with many variables the best choice often is to use
...@@ -3617,23 +4028,27 @@ try_add_cand_for (struct ivopts_data *data, bitmap ivs, bitmap inv, ...@@ -3617,23 +4028,27 @@ try_add_cand_for (struct ivopts_data *data, bitmap ivs, bitmap inv,
{ {
cand = iv_cand (data, i); cand = iv_cand (data, i);
if (get_use_iv_cost (data, use, cand, &depends_on) == INFTY) if (iv_ca_cand_used_p (ivs, cand))
continue; continue;
bitmap_copy (act_ivs, ivs); cp = get_use_iv_cost (data, use, cand);
bitmap_set_bit (act_ivs, cand->id); if (!cp)
if (depends_on) continue;
bitmap_ior (act_inv, inv, depends_on);
else iv_ca_set_cp (data, ivs, use, cp);
bitmap_copy (act_inv, inv); act_cost = iv_ca_extend (data, ivs, cand, &act_delta);
act_cost = set_cost_up_to (data, act_ivs, act_inv, use->id + 1); iv_ca_set_no_cp (data, ivs, use);
act_delta = iv_ca_delta_add (use, NULL, cp, act_delta);
if (act_cost < best_cost) if (act_cost < best_cost)
{ {
best_cost = act_cost; best_cost = act_cost;
bitmap_copy (best_ivs, act_ivs);
bitmap_copy (best_inv, act_inv); iv_ca_delta_free (&best_delta);
best_delta = act_delta;
} }
else
iv_ca_delta_free (&act_delta);
} }
if (best_cost == INFTY) if (best_cost == INFTY)
...@@ -3641,132 +4056,96 @@ try_add_cand_for (struct ivopts_data *data, bitmap ivs, bitmap inv, ...@@ -3641,132 +4056,96 @@ try_add_cand_for (struct ivopts_data *data, bitmap ivs, bitmap inv,
for (i = 0; i < use->n_map_members; i++) for (i = 0; i < use->n_map_members; i++)
{ {
cp = use->cost_map + i; cp = use->cost_map + i;
if (cp->cost == INFTY) cand = cp->cand;
if (!cand)
continue; continue;
/* Already tried this. */ /* Already tried this. */
if (cp->cand->important) if (cand->important)
continue;
if (iv_ca_cand_used_p (ivs, cand))
continue; continue;
bitmap_copy (act_ivs, ivs); act_delta = NULL;
bitmap_set_bit (act_ivs, cp->cand->id); iv_ca_set_cp (data, ivs, use, cp);
if (cp->depends_on) act_cost = iv_ca_extend (data, ivs, cand, &act_delta);
bitmap_ior (act_inv, inv, cp->depends_on); iv_ca_set_no_cp (data, ivs, use);
else act_delta = iv_ca_delta_add (use, iv_ca_cand_for_use (ivs, use),
bitmap_copy (act_inv, inv); cp, act_delta);
act_cost = set_cost_up_to (data, act_ivs, act_inv, use->id + 1);
if (act_cost < best_cost) if (act_cost < best_cost)
{ {
best_cost = act_cost; best_cost = act_cost;
bitmap_copy (best_ivs, act_ivs);
bitmap_copy (best_inv, act_inv); if (best_delta)
iv_ca_delta_free (&best_delta);
best_delta = act_delta;
} }
else
iv_ca_delta_free (&act_delta);
} }
} }
bitmap_copy (ivs, best_ivs); iv_ca_delta_commit (data, ivs, best_delta, true);
bitmap_copy (inv, best_inv); iv_ca_delta_free (&best_delta);
BITMAP_XFREE (best_ivs);
BITMAP_XFREE (best_inv);
BITMAP_XFREE (act_ivs);
BITMAP_XFREE (act_inv);
return (best_cost != INFTY); return (best_cost != INFTY);
} }
/* Finds an initial set of IVS and invariants INV. We do this by simply /* Finds an initial assignment of candidates to uses. */
choosing the best candidate for each use. */
static unsigned static struct iv_ca *
get_initial_solution (struct ivopts_data *data, bitmap ivs, bitmap inv) get_initial_solution (struct ivopts_data *data)
{ {
struct iv_ca *ivs = iv_ca_new (data);
unsigned i; unsigned i;
for (i = 0; i < n_iv_uses (data); i++) for (i = 0; i < n_iv_uses (data); i++)
if (!try_add_cand_for (data, ivs, inv, iv_use (data, i))) if (!try_add_cand_for (data, ivs, iv_use (data, i)))
return INFTY; {
iv_ca_free (&ivs);
return NULL;
}
return set_cost (data, ivs, inv); return ivs;
} }
/* Tries to improve set of induction variables IVS and invariants INV to get /* Tries to improve set of induction variables IVS. */
it better than COST. */
static bool static bool
try_improve_iv_set (struct ivopts_data *data, try_improve_iv_set (struct ivopts_data *data, struct iv_ca *ivs)
bitmap ivs, bitmap inv, unsigned *cost)
{ {
unsigned i, acost; unsigned i, acost, best_cost = iv_ca_cost (ivs);
bitmap new_ivs = BITMAP_XMALLOC (), new_inv = BITMAP_XMALLOC (); struct iv_ca_delta *best_delta = NULL, *act_delta;
bitmap best_new_ivs = NULL, best_new_inv = NULL; struct iv_cand *cand;
/* Try altering the set of induction variables by one. */ /* Try altering the set of induction variables by one. */
for (i = 0; i < n_iv_cands (data); i++) for (i = 0; i < n_iv_cands (data); i++)
{ {
bitmap_copy (new_ivs, ivs); cand = iv_cand (data, i);
bitmap_copy (new_inv, inv);
if (iv_ca_cand_used_p (ivs, cand))
if (bitmap_bit_p (ivs, i)) acost = iv_ca_narrow (data, ivs, cand, &act_delta);
bitmap_clear_bit (new_ivs, i);
else else
bitmap_set_bit (new_ivs, i); acost = iv_ca_extend (data, ivs, cand, &act_delta);
acost = set_cost (data, new_ivs, new_inv);
if (acost >= *cost)
continue;
if (!best_new_ivs) if (acost < best_cost)
{ {
best_new_ivs = BITMAP_XMALLOC (); best_cost = acost;
best_new_inv = BITMAP_XMALLOC (); if (best_delta)
iv_ca_delta_free (&best_delta);
best_delta = act_delta;
} }
*cost = acost;
bitmap_copy (best_new_ivs, new_ivs);
bitmap_copy (best_new_inv, new_inv);
}
/* Ditto for invariants. */
for (i = 1; i <= data->max_inv_id; i++)
{
if (ver_info (data, i)->has_nonlin_use)
continue;
bitmap_copy (new_ivs, ivs);
bitmap_copy (new_inv, inv);
if (bitmap_bit_p (inv, i))
bitmap_clear_bit (new_inv, i);
else else
bitmap_set_bit (new_inv, i); iv_ca_delta_free (&act_delta);
acost = set_cost (data, new_ivs, new_inv);
if (acost >= *cost)
continue;
if (!best_new_ivs)
{
best_new_ivs = BITMAP_XMALLOC ();
best_new_inv = BITMAP_XMALLOC ();
}
*cost = acost;
bitmap_copy (best_new_ivs, new_ivs);
bitmap_copy (best_new_inv, new_inv);
} }
BITMAP_XFREE (new_ivs); if (!best_delta)
BITMAP_XFREE (new_inv);
if (!best_new_ivs)
return false; return false;
bitmap_copy (ivs, best_new_ivs); iv_ca_delta_commit (data, ivs, best_delta, true);
bitmap_copy (inv, best_new_inv); iv_ca_delta_free (&best_delta);
BITMAP_XFREE (best_new_ivs);
BITMAP_XFREE (best_new_inv);
return true; return true;
} }
...@@ -3774,67 +4153,46 @@ try_improve_iv_set (struct ivopts_data *data, ...@@ -3774,67 +4153,46 @@ try_improve_iv_set (struct ivopts_data *data,
greedy heuristic -- we try to replace at most one candidate in the selected greedy heuristic -- we try to replace at most one candidate in the selected
solution and remove the unused ivs while this improves the cost. */ solution and remove the unused ivs while this improves the cost. */
static bitmap static struct iv_ca *
find_optimal_iv_set (struct ivopts_data *data) find_optimal_iv_set (struct ivopts_data *data)
{ {
unsigned cost, i; unsigned i;
bitmap set = BITMAP_XMALLOC (); struct iv_ca *set;
bitmap inv = BITMAP_XMALLOC ();
struct iv_use *use; struct iv_use *use;
data->important_candidates = BITMAP_XMALLOC (); /* Get the initial solution. */
for (i = 0; i < n_iv_cands (data); i++) set = get_initial_solution (data);
{ if (!set)
struct iv_cand *cand = iv_cand (data, i);
if (cand->important)
bitmap_set_bit (data->important_candidates, i);
}
/* Set the upper bound. */
cost = get_initial_solution (data, set, inv);
if (cost == INFTY)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Unable to substitute for ivs, failed.\n"); fprintf (dump_file, "Unable to substitute for ivs, failed.\n");
BITMAP_XFREE (inv);
BITMAP_XFREE (set);
return NULL; return NULL;
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Initial set of candidates (cost %d): ", cost); fprintf (dump_file, "Initial set of candidates:\n");
bitmap_print (dump_file, set, "", ""); iv_ca_dump (data, dump_file, set);
fprintf (dump_file, " invariants ");
bitmap_print (dump_file, inv, "", "");
fprintf (dump_file, "\n");
} }
while (try_improve_iv_set (data, set, inv, &cost)) while (try_improve_iv_set (data, set))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Improved to (cost %d): ", cost); fprintf (dump_file, "Improved to:\n");
bitmap_print (dump_file, set, "", ""); iv_ca_dump (data, dump_file, set);
fprintf (dump_file, " invariants ");
bitmap_print (dump_file, inv, "", "");
fprintf (dump_file, "\n");
} }
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Final cost %d\n\n", cost); fprintf (dump_file, "Final cost %d\n\n", iv_ca_cost (set));
for (i = 0; i < n_iv_uses (data); i++) for (i = 0; i < n_iv_uses (data); i++)
{ {
use = iv_use (data, i); use = iv_use (data, i);
find_best_candidate (data, use, set, inv, NULL, NULL, &use->selected); use->selected = iv_ca_cand_for_use (set, use)->cand;
} }
BITMAP_XFREE (inv);
BITMAP_XFREE (data->important_candidates);
return set; return set;
} }
...@@ -3884,13 +4242,13 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand) ...@@ -3884,13 +4242,13 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
/* Creates new induction variables described in SET. */ /* Creates new induction variables described in SET. */
static void static void
create_new_ivs (struct ivopts_data *data, bitmap set) create_new_ivs (struct ivopts_data *data, struct iv_ca *set)
{ {
unsigned i; unsigned i;
struct iv_cand *cand; struct iv_cand *cand;
bitmap_iterator bi; bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi)
{ {
cand = iv_cand (data, i); cand = iv_cand (data, i);
create_new_iv (data, cand); create_new_iv (data, cand);
...@@ -4422,6 +4780,7 @@ free_loop_data (struct ivopts_data *data) ...@@ -4422,6 +4780,7 @@ free_loop_data (struct ivopts_data *data)
info->inv_id = 0; info->inv_id = 0;
} }
bitmap_clear (data->relevant); bitmap_clear (data->relevant);
bitmap_clear (data->important_candidates);
for (i = 0; i < n_iv_uses (data); i++) for (i = 0; i < n_iv_uses (data); i++)
{ {
...@@ -4484,6 +4843,7 @@ tree_ssa_iv_optimize_finalize (struct loops *loops, struct ivopts_data *data) ...@@ -4484,6 +4843,7 @@ tree_ssa_iv_optimize_finalize (struct loops *loops, struct ivopts_data *data)
free_loop_data (data); free_loop_data (data);
free (data->version_info); free (data->version_info);
BITMAP_XFREE (data->relevant); BITMAP_XFREE (data->relevant);
BITMAP_XFREE (data->important_candidates);
VARRAY_FREE (decl_rtl_to_reset); VARRAY_FREE (decl_rtl_to_reset);
VARRAY_FREE (data->iv_uses); VARRAY_FREE (data->iv_uses);
...@@ -4496,7 +4856,7 @@ static bool ...@@ -4496,7 +4856,7 @@ static bool
tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop) tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
{ {
bool changed = false; bool changed = false;
bitmap iv_set; struct iv_ca *iv_ca;
edge exit; edge exit;
data->current_loop = loop; data->current_loop = loop;
...@@ -4536,13 +4896,14 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop) ...@@ -4536,13 +4896,14 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
determine_set_costs (data); determine_set_costs (data);
/* Find the optimal set of induction variables (item 3, part 2). */ /* Find the optimal set of induction variables (item 3, part 2). */
iv_set = find_optimal_iv_set (data); iv_ca = find_optimal_iv_set (data);
if (!iv_set) if (!iv_ca)
goto finish; goto finish;
changed = true; changed = true;
/* Create the new induction variables (item 4, part 1). */ /* Create the new induction variables (item 4, part 1). */
create_new_ivs (data, iv_set); create_new_ivs (data, iv_ca);
iv_ca_free (&iv_ca);
/* Rewrite the uses (item 4, part 2). */ /* Rewrite the uses (item 4, part 2). */
rewrite_uses (data); rewrite_uses (data);
...@@ -4552,8 +4913,6 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop) ...@@ -4552,8 +4913,6 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
loop_commit_inserts (); loop_commit_inserts ();
BITMAP_XFREE (iv_set);
/* We have changed the structure of induction variables; it might happen /* We have changed the structure of induction variables; it might happen
that definitions in the scev database refer to some of them that were that definitions in the scev database refer to some of them that were
eliminated. */ eliminated. */
......
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