exists. */
static inline HOST_WIDE_INT
-avg_loop_niter (struct loop *loop)
+avg_loop_niter (class loop *loop)
{
HOST_WIDE_INT niter = estimated_stmt_executions_int (loop);
if (niter == -1)
};
/* Cost of a computation. */
-struct comp_cost
+class comp_cost
{
+public:
comp_cost (): cost (0), complexity (0), scratch (0)
{}
struct iv_inv_expr_ent;
/* The candidate - cost pair. */
-struct cost_pair
+class cost_pair
{
+public:
struct iv_cand *cand; /* The candidate. */
comp_cost cost; /* The cost. */
enum tree_code comp; /* For iv elimination, the comparison. */
/* Number of IV candidates in the cost_map. */
unsigned n_map_members;
/* The costs wrto the iv candidates. */
- struct cost_pair *cost_map;
+ class cost_pair *cost_map;
/* The selected candidate for the group. */
struct iv_cand *selected;
/* Uses in the group. */
};
/* Hashtable entry for common candidate derived from iv uses. */
-struct iv_common_cand
+class iv_common_cand
{
+public:
tree base;
tree step;
/* IV uses from which this common candidate is derived. */
struct ivopts_data
{
/* The currently optimized loop. */
- struct loop *current_loop;
+ class loop *current_loop;
location_t loop_loc;
/* Numbers of iterations for all exits of the current loop. */
/* The common candidates. */
vec<iv_common_cand *> iv_common_cands;
+ /* Hash map recording base object information of tree exp. */
+ hash_map<tree, tree> *base_object_map;
+
/* The maximum invariant variable id. */
unsigned max_inv_var_id;
/* An assignment of iv candidates to uses. */
-struct iv_ca
+class iv_ca
{
+public:
/* The number of uses covered by the assignment. */
unsigned upto;
unsigned bad_groups;
/* Candidate assigned to a use, together with the related costs. */
- struct cost_pair **cand_for_group;
+ class cost_pair **cand_for_group;
/* Number of times each candidate is used. */
unsigned *n_cand_uses;
struct iv_group *group;
/* An old assignment (for rollback purposes). */
- struct cost_pair *old_cp;
+ class cost_pair *old_cp;
/* A new assignment. */
- struct cost_pair *new_cp;
+ class cost_pair *new_cp;
/* Next change in the list. */
struct iv_ca_delta *next;
/* The single loop exit if it dominates the latch, NULL otherwise. */
edge
-single_dom_exit (struct loop *loop)
+single_dom_exit (class loop *loop)
{
edge exit = single_exit (loop);
emitted in LOOP. */
static bool
-stmt_after_ip_normal_pos (struct loop *loop, gimple *stmt)
+stmt_after_ip_normal_pos (class loop *loop, gimple *stmt)
{
basic_block bb = ip_normal_pos (loop), sbb = gimple_bb (stmt);
CAND is incremented in LOOP. */
static bool
-stmt_after_increment (struct loop *loop, struct iv_cand *cand, gimple *stmt)
+stmt_after_increment (class loop *loop, struct iv_cand *cand, gimple *stmt)
{
switch (cand->pos)
{
}
}
-/* Returns true if EXP is a ssa name that occurs in an abnormal phi node. */
+/* walk_tree callback for contains_abnormal_ssa_name_p. */
-static bool
-abnormal_ssa_name_p (tree exp)
+static tree
+contains_abnormal_ssa_name_p_1 (tree *tp, int *walk_subtrees, void *)
{
- if (!exp)
- return false;
-
- if (TREE_CODE (exp) != SSA_NAME)
- return false;
-
- return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
-}
+ if (TREE_CODE (*tp) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*tp))
+ return *tp;
-/* Returns false if BASE or INDEX contains a ssa name that occurs in an
- abnormal phi node. Callback for for_each_index. */
+ if (!EXPR_P (*tp))
+ *walk_subtrees = 0;
-static bool
-idx_contains_abnormal_ssa_name_p (tree base, tree *index,
- void *data ATTRIBUTE_UNUSED)
-{
- if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
- {
- if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
- return false;
- if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
- return false;
- }
-
- return !abnormal_ssa_name_p (*index);
+ return NULL_TREE;
}
/* Returns true if EXPR contains a ssa name that occurs in an
bool
contains_abnormal_ssa_name_p (tree expr)
{
- enum tree_code code;
- enum tree_code_class codeclass;
-
- if (!expr)
- return false;
-
- code = TREE_CODE (expr);
- codeclass = TREE_CODE_CLASS (code);
-
- if (code == CALL_EXPR)
- {
- tree arg;
- call_expr_arg_iterator iter;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
- if (contains_abnormal_ssa_name_p (arg))
- return true;
- return false;
- }
-
- if (code == SSA_NAME)
- return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
-
- if (code == INTEGER_CST
- || is_gimple_min_invariant (expr))
- return false;
-
- if (code == ADDR_EXPR)
- return !for_each_index (&TREE_OPERAND (expr, 0),
- idx_contains_abnormal_ssa_name_p,
- NULL);
-
- if (code == COND_EXPR)
- return contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0))
- || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1))
- || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 2));
-
- switch (codeclass)
- {
- case tcc_binary:
- case tcc_comparison:
- if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
- return true;
-
- /* Fallthru. */
- case tcc_unary:
- if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
- return true;
-
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return false;
+ return walk_tree_without_duplicates
+ (&expr, contains_abnormal_ssa_name_p_1, NULL) != NULL_TREE;
}
/* Returns the structure describing number of iterations determined from
EXIT of DATA->current_loop, or NULL if something goes wrong. */
-static struct tree_niter_desc *
+static class tree_niter_desc *
niter_for_exit (struct ivopts_data *data, edge exit)
{
- struct tree_niter_desc *desc;
+ class tree_niter_desc *desc;
tree_niter_desc **slot;
if (!data->niters)
/* 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
create overlapping life ranges for them (PR 27283). */
- desc = XNEW (struct tree_niter_desc);
+ desc = XNEW (class tree_niter_desc);
if (!number_of_iterations_exit (data->current_loop,
exit, desc, true)
|| contains_abnormal_ssa_name_p (desc->niter))
single dominating exit of DATA->current_loop, or NULL if something
goes wrong. */
-static struct tree_niter_desc *
+static class tree_niter_desc *
niter_for_single_dom_exit (struct ivopts_data *data)
{
edge exit = single_dom_exit (data->current_loop);
data->vcands.create (20);
data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10);
data->name_expansion_cache = NULL;
+ data->base_object_map = NULL;
data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (10);
data->iv_common_cands.create (20);
decl_rtl_to_reset.create (20);
gcc_obstack_init (&data->iv_obstack);
}
-/* Returns a memory object to that EXPR points. In case we are able to
- determine that it does not point to any such object, NULL is returned. */
+/* walk_tree callback for determine_base_object. */
static tree
-determine_base_object (tree expr)
+determine_base_object_1 (tree *tp, int *walk_subtrees, void *wdata)
{
- enum tree_code code = TREE_CODE (expr);
- tree base, obj;
-
- /* If this is a pointer casted to any type, we need to determine
- the base object for the pointer; so handle conversions before
- throwing away non-pointer expressions. */
- if (CONVERT_EXPR_P (expr))
- return determine_base_object (TREE_OPERAND (expr, 0));
-
- if (!POINTER_TYPE_P (TREE_TYPE (expr)))
- return NULL_TREE;
-
- switch (code)
+ tree_code code = TREE_CODE (*tp);
+ tree obj = NULL_TREE;
+ if (code == ADDR_EXPR)
{
- case INTEGER_CST:
- return NULL_TREE;
-
- case ADDR_EXPR:
- obj = TREE_OPERAND (expr, 0);
- base = get_base_address (obj);
-
+ tree base = get_base_address (TREE_OPERAND (*tp, 0));
if (!base)
- return expr;
-
- if (TREE_CODE (base) == MEM_REF)
- return determine_base_object (TREE_OPERAND (base, 0));
+ obj = *tp;
+ else if (TREE_CODE (base) != MEM_REF)
+ obj = fold_convert (ptr_type_node, build_fold_addr_expr (base));
+ }
+ else if (code == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*tp)))
+ obj = fold_convert (ptr_type_node, *tp);
- return fold_convert (ptr_type_node,
- build_fold_addr_expr (base));
+ if (!obj)
+ {
+ if (!EXPR_P (*tp))
+ *walk_subtrees = 0;
- case POINTER_PLUS_EXPR:
- return determine_base_object (TREE_OPERAND (expr, 0));
+ return NULL_TREE;
+ }
+ /* Record special node for multiple base objects and stop. */
+ if (*static_cast<tree *> (wdata))
+ {
+ *static_cast<tree *> (wdata) = integer_zero_node;
+ return integer_zero_node;
+ }
+ /* Record the base object and continue looking. */
+ *static_cast<tree *> (wdata) = obj;
+ return NULL_TREE;
+}
- case PLUS_EXPR:
- case MINUS_EXPR:
- /* Pointer addition is done solely using POINTER_PLUS_EXPR. */
- gcc_unreachable ();
+/* Returns a memory object to that EXPR points with caching. Return NULL if we
+ are able to determine that it does not point to any such object; specially
+ return integer_zero_node if EXPR contains multiple base objects. */
- default:
- if (POLY_INT_CST_P (expr))
- return NULL_TREE;
- return fold_convert (ptr_type_node, expr);
+static tree
+determine_base_object (struct ivopts_data *data, tree expr)
+{
+ tree *slot, obj = NULL_TREE;
+ if (data->base_object_map)
+ {
+ if ((slot = data->base_object_map->get(expr)) != NULL)
+ return *slot;
}
+ else
+ data->base_object_map = new hash_map<tree, tree>;
+
+ (void) walk_tree_without_duplicates (&expr, determine_base_object_1, &obj);
+ data->base_object_map->put (expr, obj);
+ return obj;
}
/* Return true if address expression with non-DECL_P operand appears
}
iv->base = base;
- iv->base_object = determine_base_object (base);
+ iv->base_object = determine_base_object (data, base);
iv->step = step;
iv->biv_p = false;
iv->nonlin_use = NULL;
affine_iv iv;
tree step, type, base, stop;
bool found = false;
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
gphi_iterator psi;
for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
gimple *def;
tree var;
struct iv *iv, *incr_iv;
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
basic_block incr_bb;
gphi_iterator psi;
find_givs_in_stmt_scev (struct ivopts_data *data, gimple *stmt, affine_iv *iv)
{
tree lhs, stop;
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
iv->base = NULL_TREE;
iv->step = NULL_TREE;
static void
find_givs (struct ivopts_data *data)
{
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
basic_block *body = get_loop_body_in_dom_order (loop);
unsigned i;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- struct tree_niter_desc *niter = niter_for_single_dom_exit (data);
+ class tree_niter_desc *niter = niter_for_single_dom_exit (data);
if (niter)
{
outside of the returned loop. Returns NULL if EXPR is not
even obviously invariant in LOOP. */
-struct loop *
-outermost_invariant_loop_for_expr (struct loop *loop, tree expr)
+class loop *
+outermost_invariant_loop_for_expr (class loop *loop, tree expr)
{
basic_block def_bb;
unsigned i, len;
len = TREE_OPERAND_LENGTH (expr);
for (i = 0; i < len; i++)
{
- struct loop *ivloop;
+ class loop *ivloop;
if (!TREE_OPERAND (expr, i))
continue;
should not be the function body. */
bool
-expr_invariant_in_loop_p (struct loop *loop, tree expr)
+expr_invariant_in_loop_p (class loop *loop, tree expr)
{
basic_block def_bb;
unsigned i, len;
struct iv *iv;
bool use_overflow_semantics = false;
tree step, iv_base, iv_step, lbound, off;
- struct loop *loop = dta->ivopts_data->current_loop;
+ class loop *loop = dta->ivopts_data->current_loop;
/* If base is a component ref, require that the offset of the reference
be invariant. */
switch (gimple_call_internal_fn (call))
{
case IFN_MASK_LOAD:
+ case IFN_MASK_LOAD_LANES:
if (op_p == gimple_call_arg_ptr (call, 0))
return TREE_TYPE (gimple_call_lhs (call));
return NULL_TREE;
case IFN_MASK_STORE:
+ case IFN_MASK_STORE_LANES:
if (op_p == gimple_call_arg_ptr (call, 0))
return TREE_TYPE (gimple_call_arg (call, 3));
return NULL_TREE;
is already nonempty. */
static bool
-allow_ip_end_pos_p (struct loop *loop)
+allow_ip_end_pos_p (class loop *loop)
{
if (!ip_normal_pos (loop))
return true;
record_common_cand (struct ivopts_data *data, tree base,
tree step, struct iv_use *use)
{
- struct iv_common_cand ent;
- struct iv_common_cand **slot;
+ class iv_common_cand ent;
+ class iv_common_cand **slot;
ent.base = base;
ent.step = step;
common_cand_cmp (const void *p1, const void *p2)
{
unsigned n1, n2;
- const struct iv_common_cand *const *const ccand1
- = (const struct iv_common_cand *const *)p1;
- const struct iv_common_cand *const *const ccand2
- = (const struct iv_common_cand *const *)p2;
+ const class iv_common_cand *const *const ccand1
+ = (const class iv_common_cand *const *)p1;
+ const class iv_common_cand *const *const ccand2
+ = (const class iv_common_cand *const *)p2;
n1 = (*ccand1)->uses.length ();
n2 = (*ccand2)->uses.length ();
data->iv_common_cands.qsort (common_cand_cmp);
for (i = 0; i < data->iv_common_cands.length (); i++)
{
- struct iv_common_cand *ptr = data->iv_common_cands[i];
+ class iv_common_cand *ptr = data->iv_common_cands[i];
/* Only add IV candidate if it's derived from multiple uses. */
if (ptr->uses.length () <= 1)
basetype = sizetype;
record_common_cand (data, build_int_cst (basetype, 0), iv->step, use);
+ /* Compare the cost of an address with an unscaled index with the cost of
+ an address with a scaled index and add candidate if useful. */
+ poly_int64 step;
+ if (use != NULL
+ && poly_int_tree_p (iv->step, &step)
+ && address_p (use->type))
+ {
+ poly_int64 new_step;
+ unsigned int fact = preferred_mem_scale_factor
+ (use->iv->base,
+ TYPE_MODE (use->mem_type),
+ optimize_loop_for_speed_p (data->current_loop));
+
+ if (fact != 1
+ && multiple_p (step, fact, &new_step))
+ add_candidate (data, size_int (0),
+ wide_int_to_tree (sizetype, new_step),
+ true, NULL);
+ }
+
/* Record common candidate with constant offset stripped in base.
Like the use itself, we also add candidate directly for it. */
base = strip_offset (iv->base, &offset);
}
group->n_map_members = size;
- group->cost_map = XCNEWVEC (struct cost_pair, size);
+ group->cost_map = XCNEWVEC (class cost_pair, size);
}
}
/* Gets cost of (GROUP, CAND) pair. */
-static struct cost_pair *
+static class cost_pair *
get_group_iv_cost (struct ivopts_data *data, struct iv_group *group,
struct iv_cand *cand)
{
unsigned i, s;
- struct cost_pair *ret;
+ class cost_pair *ret;
if (!cand)
return NULL;
return NULL_TREE;
}
+/* Predict whether the given loop will be transformed in the RTL
+ doloop_optimize pass. Attempt to duplicate some doloop_optimize checks.
+ This is only for target independent checks, see targetm.predict_doloop_p
+ for the target dependent ones.
+
+ Note that according to some initial investigation, some checks like costly
+ niter check and invalid stmt scanning don't have much gains among general
+ cases, so keep this as simple as possible first.
+
+ Some RTL specific checks seems unable to be checked in gimple, if any new
+ checks or easy checks _are_ missing here, please add them. */
+
+static bool ATTRIBUTE_UNUSED
+generic_predict_doloop_p (struct ivopts_data *data)
+{
+ class loop *loop = data->current_loop;
+
+ /* Call target hook for target dependent checks. */
+ if (!targetm.predict_doloop_p (loop))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " target specific checks.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check iteration description to know it's
+ suitable or not. Keep it as simple as possible, feel free to extend it
+ if you find any multiple exits cases matter. */
+ edge exit = single_dom_exit (loop);
+ class tree_niter_desc *niter_desc;
+ if (!exit || !(niter_desc = niter_for_exit (data, exit)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " unexpected niters.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check whether iteration count too small
+ and not profitable. */
+ HOST_WIDE_INT est_niter = get_estimated_loop_iterations_int (loop);
+ if (est_niter == -1)
+ est_niter = get_likely_max_loop_iterations_int (loop);
+ if (est_niter >= 0 && est_niter < 3)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Predict doloop failure due to"
+ " too few iterations (%u).\n",
+ (unsigned int) est_niter);
+ return false;
+ }
+
+ return true;
+}
+
/* Determines cost of the computation of EXPR. */
static unsigned
/* Returns variable containing the value of candidate CAND at statement AT. */
static tree
-var_at_stmt (struct loop *loop, struct iv_cand *cand, gimple *stmt)
+var_at_stmt (class loop *loop, struct iv_cand *cand, gimple *stmt)
{
if (stmt_after_increment (loop, cand, stmt))
return cand->var_after;
non-null. Returns false if USE cannot be expressed using CAND. */
static bool
-get_computation_aff_1 (struct loop *loop, gimple *at, struct iv_use *use,
- struct iv_cand *cand, struct aff_tree *aff_inv,
- struct aff_tree *aff_var, widest_int *prat = NULL)
+get_computation_aff_1 (class loop *loop, gimple *at, struct iv_use *use,
+ struct iv_cand *cand, class aff_tree *aff_inv,
+ class aff_tree *aff_var, widest_int *prat = NULL)
{
tree ubase = use->iv->base, ustep = use->iv->step;
tree cbase = cand->iv->base, cstep = cand->iv->step;
form into AFF. Returns false if USE cannot be expressed using CAND. */
static bool
-get_computation_aff (struct loop *loop, gimple *at, struct iv_use *use,
- struct iv_cand *cand, struct aff_tree *aff)
+get_computation_aff (class loop *loop, gimple *at, struct iv_use *use,
+ struct iv_cand *cand, class aff_tree *aff)
{
aff_tree aff_var;
CAND at statement AT in LOOP. The computation is unshared. */
static tree
-get_computation_at (struct loop *loop, gimple *at,
+get_computation_at (class loop *loop, gimple *at,
struct iv_use *use, struct iv_cand *cand)
{
aff_tree aff;
stores it to VAL. */
static void
-cand_value_at (struct loop *loop, struct iv_cand *cand, gimple *at, tree niter,
+cand_value_at (class loop *loop, struct iv_cand *cand, gimple *at, tree niter,
aff_tree *val)
{
aff_tree step, delta, nit;
static enum tree_code
iv_elimination_compare (struct ivopts_data *data, struct iv_use *use)
{
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
basic_block ex_bb;
edge exit;
static bool
iv_elimination_compare_lt (struct ivopts_data *data,
struct iv_cand *cand, enum tree_code *comp_p,
- struct tree_niter_desc *niter)
+ class tree_niter_desc *niter)
{
tree cand_type, a, b, mbz, nit_type = TREE_TYPE (niter->niter), offset;
- struct aff_tree nit, tmpa, tmpb;
+ class aff_tree nit, tmpa, tmpb;
enum tree_code comp;
HOST_WIDE_INT step;
basic_block ex_bb;
edge exit;
tree period;
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
aff_tree bnd;
- struct tree_niter_desc *desc = NULL;
+ class tree_niter_desc *desc = NULL;
if (TREE_CODE (cand->iv->step) != INTEGER_CST)
return false;
gphi *phi;
gphi_iterator psi;
tree op;
- struct loop *loop = data->current_loop;
+ class loop *loop = data->current_loop;
bitmap_iterator bi;
if (dump_file && (dump_flags & TDF_DETAILS))
/* Returns true if A is a cheaper cost pair than B. */
static bool
-cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b)
+cheaper_cost_pair (class cost_pair *a, class cost_pair *b)
{
if (!a)
return false;
for more expensive, equal and cheaper respectively. */
static int
-compare_cost_pair (struct cost_pair *a, struct cost_pair *b)
+compare_cost_pair (class cost_pair *a, class cost_pair *b)
{
if (cheaper_cost_pair (a, b))
return -1;
/* Returns candidate by that USE is expressed in IVS. */
-static struct cost_pair *
-iv_ca_cand_for_group (struct iv_ca *ivs, struct iv_group *group)
+static class cost_pair *
+iv_ca_cand_for_group (class iv_ca *ivs, struct iv_group *group)
{
return ivs->cand_for_group[group->id];
}
/* Computes the cost field of IVS structure. */
static void
-iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
+iv_ca_recount_cost (struct ivopts_data *data, class iv_ca *ivs)
{
comp_cost cost = ivs->cand_use_cost;
and IVS. */
static void
-iv_ca_set_remove_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
+iv_ca_set_remove_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
{
bitmap_iterator bi;
unsigned iid;
/* 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,
+iv_ca_set_no_cp (struct ivopts_data *data, class iv_ca *ivs,
struct iv_group *group)
{
unsigned gid = group->id, cid;
- struct cost_pair *cp;
+ class cost_pair *cp;
cp = ivs->cand_for_group[gid];
if (!cp)
IVS. */
static void
-iv_ca_set_add_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
+iv_ca_set_add_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
{
bitmap_iterator bi;
unsigned iid;
/* Set cost pair for GROUP in set IVS to CP. */
static void
-iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs,
- struct iv_group *group, struct cost_pair *cp)
+iv_ca_set_cp (struct ivopts_data *data, class iv_ca *ivs,
+ struct iv_group *group, class cost_pair *cp)
{
unsigned gid = group->id, cid;
set IVS don't give any result. */
static void
-iv_ca_add_group (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_add_group (struct ivopts_data *data, class iv_ca *ivs,
struct iv_group *group)
{
- struct cost_pair *best_cp = NULL, *cp;
+ class cost_pair *best_cp = NULL, *cp;
bitmap_iterator bi;
unsigned i;
struct iv_cand *cand;
/* Get cost for assignment IVS. */
static comp_cost
-iv_ca_cost (struct iv_ca *ivs)
+iv_ca_cost (class iv_ca *ivs)
{
/* This was a conditional expression but it triggered a bug in
Sun C 5.5. */
respectively. */
static int
-iv_ca_compare_deps (struct ivopts_data *data, struct iv_ca *ivs,
- struct iv_group *group, struct cost_pair *old_cp,
- struct cost_pair *new_cp)
+iv_ca_compare_deps (struct ivopts_data *data, class iv_ca *ivs,
+ struct iv_group *group, class cost_pair *old_cp,
+ class cost_pair *new_cp)
{
gcc_assert (old_cp && new_cp && old_cp != new_cp);
unsigned old_n_invs = ivs->n_invs;
it before NEXT. */
static struct iv_ca_delta *
-iv_ca_delta_add (struct iv_group *group, struct cost_pair *old_cp,
- struct cost_pair *new_cp, struct iv_ca_delta *next)
+iv_ca_delta_add (struct iv_group *group, class cost_pair *old_cp,
+ class cost_pair *new_cp, struct iv_ca_delta *next)
{
struct iv_ca_delta *change = XNEW (struct iv_ca_delta);
reverted instead. */
static void
-iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_delta_commit (struct ivopts_data *data, class iv_ca *ivs,
struct iv_ca_delta *delta, bool forward)
{
- struct cost_pair *from, *to;
+ class cost_pair *from, *to;
struct iv_ca_delta *act;
if (!forward)
/* Returns true if CAND is used in IVS. */
static bool
-iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand)
+iv_ca_cand_used_p (class iv_ca *ivs, struct iv_cand *cand)
{
return ivs->n_cand_uses[cand->id] > 0;
}
/* Returns number of induction variable candidates in the set IVS. */
static unsigned
-iv_ca_n_cands (struct iv_ca *ivs)
+iv_ca_n_cands (class iv_ca *ivs)
{
return ivs->n_cands;
}
/* Allocates new iv candidates assignment. */
-static struct iv_ca *
+static class iv_ca *
iv_ca_new (struct ivopts_data *data)
{
- struct iv_ca *nw = XNEW (struct iv_ca);
+ class iv_ca *nw = XNEW (class iv_ca);
nw->upto = 0;
nw->bad_groups = 0;
- nw->cand_for_group = XCNEWVEC (struct cost_pair *,
+ nw->cand_for_group = XCNEWVEC (class cost_pair *,
data->vgroups.length ());
nw->n_cand_uses = XCNEWVEC (unsigned, data->vcands.length ());
nw->cands = BITMAP_ALLOC (NULL);
/* Free memory occupied by the set IVS. */
static void
-iv_ca_free (struct iv_ca **ivs)
+iv_ca_free (class iv_ca **ivs)
{
free ((*ivs)->cand_for_group);
free ((*ivs)->n_cand_uses);
/* Dumps IVS to FILE. */
static void
-iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
+iv_ca_dump (struct ivopts_data *data, FILE *file, class iv_ca *ivs)
{
unsigned i;
comp_cost cost = iv_ca_cost (ivs);
for (i = 0; i < ivs->upto; i++)
{
struct iv_group *group = data->vgroups[i];
- struct cost_pair *cp = iv_ca_cand_for_group (ivs, group);
+ class cost_pair *cp = iv_ca_cand_for_group (ivs, group);
if (cp)
fprintf (file, " group:%d --> iv_cand:%d, cost=("
"%" PRId64 ",%d)\n", group->id, cp->cand->id,
the function will try to find a solution with mimimal iv candidates. */
static comp_cost
-iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_extend (struct ivopts_data *data, class iv_ca *ivs,
struct iv_cand *cand, struct iv_ca_delta **delta,
unsigned *n_ivs, bool min_ncand)
{
unsigned i;
comp_cost cost;
struct iv_group *group;
- struct cost_pair *old_cp, *new_cp;
+ class cost_pair *old_cp, *new_cp;
*delta = NULL;
for (i = 0; i < ivs->upto; i++)
the candidate with which we start narrowing. */
static comp_cost
-iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_narrow (struct ivopts_data *data, class iv_ca *ivs,
struct iv_cand *cand, struct iv_cand *start,
struct iv_ca_delta **delta)
{
unsigned i, ci;
struct iv_group *group;
- struct cost_pair *old_cp, *new_cp, *cp;
+ class cost_pair *old_cp, *new_cp, *cp;
bitmap_iterator bi;
struct iv_cand *cnd;
comp_cost cost, best_cost, acost;
differences in DELTA. */
static comp_cost
-iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_prune (struct ivopts_data *data, class iv_ca *ivs,
struct iv_cand *except_cand, struct iv_ca_delta **delta)
{
bitmap_iterator bi;
cheaper local cost for GROUP than BEST_CP. Return pointer to
the corresponding cost_pair, otherwise just return BEST_CP. */
-static struct cost_pair*
+static class cost_pair*
cheaper_cost_with_cand (struct ivopts_data *data, struct iv_group *group,
unsigned int cand_idx, struct iv_cand *old_cand,
- struct cost_pair *best_cp)
+ class cost_pair *best_cp)
{
struct iv_cand *cand;
- struct cost_pair *cp;
+ class cost_pair *cp;
gcc_assert (old_cand != NULL && best_cp != NULL);
if (cand_idx == old_cand->id)
candidate replacement in list DELTA. */
static comp_cost
-iv_ca_replace (struct ivopts_data *data, struct iv_ca *ivs,
+iv_ca_replace (struct ivopts_data *data, class iv_ca *ivs,
struct iv_ca_delta **delta)
{
bitmap_iterator bi, bj;
struct iv_cand *cand;
comp_cost orig_cost, acost;
struct iv_ca_delta *act_delta, *tmp_delta;
- struct cost_pair *old_cp, *best_cp = NULL;
+ class cost_pair *old_cp, *best_cp = NULL;
*delta = NULL;
orig_cost = iv_ca_cost (ivs);
based on any memory object. */
static bool
-try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
+try_add_cand_for (struct ivopts_data *data, class iv_ca *ivs,
struct iv_group *group, bool originalp)
{
comp_cost best_cost, act_cost;
bitmap_iterator bi;
struct iv_cand *cand;
struct iv_ca_delta *best_delta = NULL, *act_delta;
- struct cost_pair *cp;
+ class cost_pair *cp;
iv_ca_add_group (data, ivs, group);
best_cost = iv_ca_cost (ivs);
/* Finds an initial assignment of candidates to uses. */
-static struct iv_ca *
+static class iv_ca *
get_initial_solution (struct ivopts_data *data, bool originalp)
{
unsigned i;
- struct iv_ca *ivs = iv_ca_new (data);
+ class iv_ca *ivs = iv_ca_new (data);
for (i = 0; i < data->vgroups.length (); i++)
if (!try_add_cand_for (data, ivs, data->vgroups[i], originalp))
static bool
try_improve_iv_set (struct ivopts_data *data,
- struct iv_ca *ivs, bool *try_replace_p)
+ class iv_ca *ivs, bool *try_replace_p)
{
unsigned i, n_ivs;
comp_cost acost, best_cost = iv_ca_cost (ivs);
greedy heuristic -- we try to replace at most one candidate in the selected
solution and remove the unused ivs while this improves the cost. */
-static struct iv_ca *
+static class iv_ca *
find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp)
{
- struct iv_ca *set;
+ class iv_ca *set;
bool try_replace_p = true;
/* Get the initial solution. */
return set;
}
-static struct iv_ca *
+static class iv_ca *
find_optimal_iv_set (struct ivopts_data *data)
{
unsigned i;
comp_cost cost, origcost;
- struct iv_ca *set, *origset;
+ class iv_ca *set, *origset;
/* Determine the cost based on a strategy that starts with original IVs,
and try again using a strategy that prefers candidates not based
/* Creates new induction variables described in SET. */
static void
-create_new_ivs (struct ivopts_data *data, struct iv_ca *set)
+create_new_ivs (struct ivopts_data *data, class iv_ca *set)
{
unsigned i;
struct iv_cand *cand;
{
case IFN_MASK_LOAD:
case IFN_MASK_STORE:
+ case IFN_MASK_LOAD_LANES:
+ case IFN_MASK_STORE_LANES:
/* The second argument contains the correct alias type. */
gcc_assert (use->op_p = gimple_call_arg_ptr (call, 0));
return TREE_TYPE (gimple_call_arg (call, 1));
gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
enum tree_code compare;
struct iv_group *group = data->vgroups[use->group_id];
- struct cost_pair *cp = get_group_iv_cost (data, group, cand);
+ class cost_pair *cp = get_group_iv_cost (data, group, cand);
bound = cp->value;
if (bound)
}
}
-/* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback
+/* Frees memory occupied by class tree_niter_desc in *VALUE. Callback
for hash_map::traverse. */
bool
delete data->inv_expr_tab;
data->inv_expr_tab = NULL;
free_affine_expand_cache (&data->name_expansion_cache);
+ if (data->base_object_map)
+ delete data->base_object_map;
delete data->iv_common_cand_tab;
data->iv_common_cand_tab = NULL;
data->iv_common_cands.release ();
/* Optimizes the LOOP. Returns true if anything changed. */
static bool
-tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
+tree_ssa_iv_optimize_loop (struct ivopts_data *data, class loop *loop,
bitmap toremove)
{
bool changed = false;
- struct iv_ca *iv_ca;
+ class iv_ca *iv_ca;
edge exit = single_dom_exit (loop);
basic_block *body;
void
tree_ssa_iv_optimize (void)
{
- struct loop *loop;
+ class loop *loop;
struct ivopts_data data;
auto_bitmap toremove;