/**
* Walk recursive the successors of a graph argument
- * with mode reference and mark in the "irg_args" if it will be read,
+ * with mode reference and mark if it will be read,
* written or stored.
*
* @param arg The graph argument with mode reference,
"Call" isn't computed else we analyze that graph. If our
reference is the address of this
Call node that mean the reference will be read.*/
- if (get_irn_op(succ) == op_Call) {
- ir_node *Call_ptr = get_Call_ptr(succ);
+ switch (get_irn_opcode(succ)) {
- if (Call_ptr == arg) {
+ case iro_Call: {
+ ir_node *ptr = get_Call_ptr(succ);
+
+ if (ptr == arg) {
/* Hmm: not sure what this is, most likely a read */
bits |= ptr_access_read;
}
- else if (op_SymConst == get_irn_op(Call_ptr) &&
- get_SymConst_kind(Call_ptr) == symconst_addr_ent) {
- entity *meth_ent = get_SymConst_entity(Call_ptr);
-
- for (p = get_Call_n_params(succ) - 1; p >= 0; --p){
- if (get_Call_param(succ, p) == arg) {
- /* an arg can be used more than once ! */
- bits |= get_method_param_access(meth_ent, p);
- }
- }
- } else /* can do anything */
- bits |= ptr_access_all;
+ else {
+ ir_op *op = get_irn_op(ptr);
+ entity *meth_ent;
+
+ if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
+ meth_ent = get_SymConst_entity(ptr);
+
+ for (p = get_Call_n_params(succ) - 1; p >= 0; --p) {
+ if (get_Call_param(succ, p) == arg) {
+ /* an arg can be used more than once ! */
+ bits |= get_method_param_access(meth_ent, p);
+ }
+ }
+ }
+ else if (op == op_Sel && get_irp_callee_info_state() == irg_callee_info_consistent) {
+ /* is be a polymorphic call but callee information is available */
+ int i, n_params = get_Call_n_params(succ);
+
+ /* simply look into ALL possible callees */
+ for (i = get_Call_n_callees(succ) - 1; i >= 0; --i) {
+ meth_ent = get_Call_callee(succ, i);
+
+ /* unknown_entity is used to signal that we don't know what is called */
+ if (meth_ent == unknown_entity) {
+ bits |= ptr_access_all;
+ break;
+ }
+
+ for (p = n_params - 1; p >= 0; --p) {
+ if (get_Call_param(succ, p) == arg) {
+ /* an arg can be used more than once ! */
+ bits |= get_method_param_access(meth_ent, p);
+ }
+ }
+ }
+ }
+ else /* can do anything */
+ bits |= ptr_access_all;
+ }
/* search stops here anyway */
continue;
}
- else if (get_irn_op(succ) == op_Store) {
+ case iro_Store:
/* We have reached a Store node => the reference is written or stored. */
if (get_Store_ptr(succ) == arg) {
/* written to */
/* search stops here anyway */
continue;
- }
- else if (get_irn_op(succ) == op_Load) {
+
+ case iro_Load:
/* We have reached a Load node => the reference is read. */
bits |= ptr_access_read;
/* search stops here anyway */
continue;
- }
- else if (get_irn_op(succ) == op_Conv) {
+
+ case iro_Conv:
/* our address is casted into something unknown. Break our search. */
- return ptr_access_all;
+ bits = ptr_access_all;
+ break;
+
+ default:
+ break;
}
/* If we know that, the argument will be read, write and stored, we
can break the recursion.*/
- if (bits == ptr_access_all)
- return ptr_access_all;
+ if (bits == ptr_access_all) {
+ bits = ptr_access_all;
+ break;
+ }
/*
* A calculation that do not lead to a reference mode ends our search.
return bits;
}
-
/**
* Check if a argument of the ir graph with mode
* reference is read, write or both.
ir_mode *arg_mode;
int nparams, i;
long proj_nr;
- type *mtp;
+ ir_type *mtp;
ptr_access_kind *rw_info;
mtp = get_entity_type(ent);
irg = get_entity_irg(ent);
- /* we have not yet analysed the graph, set ALL access for pointer args */
+ /* we have not yet analyzed the graph, set ALL access for pointer args */
for (i = nparams - 1; i >= 0; --i)
ent->param_access[i] =
is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_all : ptr_access_none;
/* Call algorithm that computes the out edges */
if (get_irg_outs_state(irg) != outs_consistent)
- compute_outs(irg);
+ compute_irg_outs(irg);
irg_args = get_irg_args(irg);
/* copy the temporary info */
memcpy(ent->param_access, rw_info, nparams * sizeof(ent->param_access[0]));
+#if 0
printf("\n%s:\n", get_entity_name(ent));
for (i = 0; i < nparams; ++i) {
if (is_Pointer_type(get_method_param_type(mtp, i)))
printf("\n");
}
}
+#endif
+}
+
+/**
+ * Analyze how pointer arguments of a given
+ * ir graph are accessed.
+ *
+ * @param irg The ir graph to analyze.
+ */
+void analyze_irg_args(ir_graph *irg)
+{
+ entity *ent;
+
+ if (irg == get_const_code_irg())
+ return;
+
+ ent = get_irg_entity(irg);
+ if (! ent)
+ return;
+
+ if (! ent->param_access)
+ analyze_ent_args(ent);
}
/*
*/
ptr_access_kind get_method_param_access(entity *ent, int pos)
{
- type *mtp = get_entity_type(ent);
- int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
+ ir_type *mtp = get_entity_type(ent);
+ int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
return ptr_access_all;
}
+enum args_weight {
+ null_weight = 0, /**< If can't be anything optimized. */
+ binop_weight = 1, /**< If the argument have mode_weight and take part in binop. */
+ const_binop_weight = 1, /**< If the argument have mode_weight and take part in binop with a constant.*/
+ cmp_weight = 4, /**< If the argument take part in cmp. */
+ const_cmp_weight = 10 /**< If the argument take part in cmp with a constant. */
+};
+
/**
- * Analyze how pointer arguments of a given
- * ir graph are accessed.
+ * Compute the weight of a method parameter
*
- * @param irg The ir graph to analyze.
+ * @param arg The parameter them weight muss be computed.
*/
-void analyze_irg_args(ir_graph *irg)
+static float calc_method_param_weight(ir_node *arg)
{
- entity *ent;
+ int i;
+ ir_node *succ, *op;
+ float weight = null_weight;
- if (irg == get_const_code_irg())
+ /* We mark the nodes to avoid endless recursion */
+ set_irn_link(arg, VISITED);
+
+ for (i = get_irn_n_outs(arg) - 1; i >= 0; i--) {
+ succ = get_irn_out(arg, i);
+
+ /* We was here.*/
+ if (get_irn_link(succ) == VISITED)
+ continue;
+
+ /* We should not walk over the memory edge.*/
+ if (get_irn_mode(succ) == mode_M)
+ continue;
+
+ /* We have reached a cmp and we must increase the
+ weight with the cmp_weight.*/
+ if (get_irn_op(succ) == op_Cmp) {
+
+ if (get_Cmp_left(succ) == arg)
+ op = get_Cmp_right(succ);
+ else
+ op = get_Cmp_left(succ);
+
+ if (is_irn_constlike(op)) {
+ weight += const_cmp_weight;
+ }
+ else
+ weight += cmp_weight;
+ }
+ else if (is_binop(succ)) {
+ /* We have reached a binop and we must increase the
+ weight with the binop_weight. If the other operand of the
+ binop is a constant we increase the weight with const_binop_weight
+ and call the function recursive.
+ */
+ if (get_binop_left(succ) == arg)
+ op = get_binop_right(succ);
+ else
+ op = get_binop_left(succ);
+
+ if (is_irn_constlike(op)) {
+ weight += const_binop_weight;
+ weight += calc_method_param_weight(succ);
+ }
+ else
+ weight += binop_weight;
+ } else if (is_unop(succ)) {
+ /* We have reached a binop and we must increase the
+ weight with the const_binop_weight and call the function recursive.*/
+ weight += const_binop_weight;
+ weight += calc_method_param_weight(succ);
+ }
+ }
+ set_irn_link(arg, NULL);
+ return weight;
+}
+
+/**
+ * Set a weight for each argument of a ir_graph.
+ * The args with a greater weight are good for optimize.
+ *
+ * @param ent The entity of the ir_graph.
+ */
+static void analyze_method_params_weight(entity *ent)
+{
+ ir_type *mtp;
+ ir_graph *irg;
+ int nparams, i, proj_nr;
+ ir_node *irg_args, *arg;
+
+ mtp = get_entity_type(ent);
+ nparams = get_method_n_params(mtp);
+
+ /* allocate a new array. currently used as 'analysed' flag */
+ ent->param_weight = NEW_ARR_F(float, nparams);
+
+ /* If the method haven't parameters we have
+ * nothing to do.
+ */
+ if (nparams <= 0)
return;
+ irg = get_entity_irg(ent);
+
+ /* First we initialize the parameter weight with 0. */
+ for (i = nparams - 1; i >= 0; i--)
+ ent->param_weight[i] = null_weight;
+
+ if (! irg) {
+ /* no graph, no better info */
+ return;
+ }
+
+ /* Call algorithm that computes the out edges */
+ if (get_irg_outs_state(irg) != outs_consistent)
+ compute_irg_outs(irg);
+
+ irg_args = get_irg_args(irg);
+
+ for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
+ arg = get_irn_out(irg_args, i);
+ proj_nr = get_Proj_proj(arg);
+ ent->param_weight[proj_nr] += calc_method_param_weight(arg);
+ }
+
+#if 0
+ printf("\n%s:\n", get_entity_name(ent));
+ for (i = nparams - 1; i >= 0; --i)
+ printf("The weight of argument %i is %f \n", i, ent->param_weight[i]);
+#endif
+}
+
+/*
+ * Compute for a method with pointer parameter(s)
+ * if they will be read or written.
+ */
+float get_method_param_weight(entity *ent, int pos)
+{
+ ir_type *mtp = get_entity_type(ent);
+ int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
+
+ assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
+
+ if (ent->param_weight) {
+ if (pos < ARR_LEN(ent->param_weight))
+ return ent->param_weight[pos];
+ else
+ return 0.0f;
+ }
+
+ analyze_method_params_weight(ent);
+
+ if (pos < ARR_LEN(ent->param_weight))
+ return ent->param_weight[pos];
+ else
+ return 0.0f;
+}
+
+
+/**
+ * Analyze argument's weight of a given
+ * ir graph.
+ *
+ * @param irg The ir graph to analyze.
+ */
+void analyze_irg_args_weight(ir_graph *irg)
+{
+ entity *ent;
+
ent = get_irg_entity(irg);
if (! ent)
return;
- if (! ent->param_access)
- analyze_ent_args(ent);
+ if (! ent->param_weight)
+ analyze_method_params_weight(ent);
}