ircfscc: remove is_outermost_StartBlock check - it was broken and apparently unnecessary
[libfirm] / ir / ana / analyze_irg_args.c
index 1769fd7..17b8c69 100644 (file)
  * @author     Beyhan Veliev
  * @version    $Id$
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
+#include <stdlib.h>
 
 #include "irouts.h"
 #include "irnode_t.h"
 #include "irmode_t.h"
-#include "array.h"
+#include "array_t.h"
 #include "irprog.h"
 #include "entity_t.h"
-#include "xmalloc.h"
 
 #include "analyze_irg_args.h"
 
-static char v;
-static void *VISITED = &v;
-
 /**
  * Walk recursive the successors of a graph argument
  * with mode reference and mark if it will be read,
@@ -52,18 +44,19 @@ static void *VISITED = &v;
  * @param arg   The graph argument with mode reference,
  *             that must be checked.
  */
-static unsigned analyze_arg(ir_node *arg, unsigned bits) {
+static ptr_access_kind analyze_arg(ir_node *arg, ptr_access_kind bits)
+{
        int i, p;
        ir_node *succ;
 
        /* We must visit a node once to avoid endless recursion.*/
-       set_irn_link(arg, VISITED);
+       mark_irn_visited(arg);
 
        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)
+               if (irn_visited(succ))
                        continue;
 
                /* We should not walk over the memory edge.*/
@@ -85,7 +78,6 @@ static unsigned analyze_arg(ir_node *arg, unsigned bits) {
                                /* Hmm: not sure what this is, most likely a read */
                                bits |= ptr_access_read;
                        } else {
-                               ir_op *op = get_irn_op(ptr);
                                ir_entity *meth_ent;
 
                                if (is_Global(ptr)) {
@@ -182,7 +174,8 @@ static unsigned analyze_arg(ir_node *arg, unsigned bits) {
  *
  * @param irg   The ir graph to analyze.
  */
-static void analyze_ent_args(ir_entity *ent) {
+static void analyze_ent_args(ir_entity *ent)
+{
        ir_graph *irg;
        ir_node *irg_args, *arg;
        ir_mode *arg_mode;
@@ -266,7 +259,8 @@ static void analyze_ent_args(ir_entity *ent) {
  *
  * @param irg   The ir graph to analyze.
  */
-void analyze_irg_args(ir_graph *irg) {
+void analyze_irg_args(ir_graph *irg)
+{
        ir_entity *ent;
 
        if (irg == get_const_code_irg())
@@ -284,13 +278,13 @@ void analyze_irg_args(ir_graph *irg) {
  * Compute for a method with pointer parameter(s)
  * if they will be read or written.
  */
-ptr_access_kind get_method_param_access(ir_entity *ent, int pos)
+ptr_access_kind get_method_param_access(ir_entity *ent, size_t pos)
 {
 #ifndef NDEBUG
        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)));
+       assert(is_variadic || pos < get_method_n_params(mtp));
 #endif
 
        if (ent->attr.mtd_attr.param_access) {
@@ -323,30 +317,35 @@ enum args_weight {
  *
  * @param arg  The parameter them weight muss be computed.
  */
-static unsigned calc_method_param_weight(ir_node *arg) {
-       int      i;
+static unsigned calc_method_param_weight(ir_node *arg)
+{
+       int      i, j, k;
        ir_node  *succ, *op;
        unsigned weight = null_weight;
 
        /* We mark the nodes to avoid endless recursion */
-       set_irn_link(arg, VISITED);
+       mark_irn_visited(arg);
 
        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)
+               if (irn_visited(succ))
                        continue;
 
                /* We should not walk over the memory edge.*/
                if (get_irn_mode(succ) == mode_M)
                        continue;
 
-               if (is_Call(succ) && get_Call_ptr(succ) == arg) {
-                       /* the arguments is used as an pointer input for a call,
-                          we can probably change an indirect Call into a direct one. */
-                       weight += indirect_call_weight;
-               } else if (is_Cmp(succ)) {
+               switch (get_irn_opcode(succ)) {
+               case iro_Call:
+                       if (get_Call_ptr(succ) == arg) {
+                               /* the arguments is used as an pointer input for a call,
+                                  we can probably change an indirect Call into a direct one. */
+                               weight += indirect_call_weight;
+                       }
+                       break;
+               case iro_Cmp:
                        /* We have reached a cmp and we must increase the
                           weight with the cmp_weight. */
                        if (get_Cmp_left(succ) == arg)
@@ -358,30 +357,59 @@ static unsigned calc_method_param_weight(ir_node *arg) {
                                weight += const_cmp_weight;
                        } else
                                weight += cmp_weight;
-               } else if (is_Cond(succ)) {
+                       break;
+               case iro_Cond:
                        /* the argument is used for a SwitchCond, a big win */
                        weight += const_cmp_weight * get_irn_n_outs(succ);
-               } 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)) {
+                       break;
+               case iro_Id:
+                       /* when looking backward we might find Id nodes */
+                       weight += calc_method_param_weight(succ);
+                       break;
+               case iro_Tuple:
+                       /* unoptimized tuple */
+                       for (j = get_Tuple_n_preds(succ) - 1; j >= 0; --j) {
+                               ir_node *pred = get_Tuple_pred(succ, j);
+                               if (pred == arg) {
+                                       /* look for Proj(j) */
+                                       for (k = get_irn_n_outs(succ) - 1; k >= 0; --k) {
+                                               ir_node *succ_succ = get_irn_out(succ, k);
+                                               if (is_Proj(succ_succ)) {
+                                                       if (get_Proj_proj(succ_succ) == j) {
+                                                               /* found */
+                                                               weight += calc_method_param_weight(succ_succ);
+                                                       }
+                                               } else {
+                                                       /* this should NOT happen */
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               default:
+                       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);
-                       } 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);
+                       }
+                       break;
                }
        }
        set_irn_link(arg, NULL);
@@ -393,7 +421,8 @@ static unsigned calc_method_param_weight(ir_node *arg) {
  *
  * @param ent  The entity of the ir_graph.
  */
-static void analyze_method_params_weight(ir_entity *ent) {
+static void analyze_method_params_weight(ir_entity *ent)
+{
        ir_type  *mtp;
        ir_graph *irg;
        int      nparams, i, proj_nr;
@@ -423,18 +452,11 @@ static void analyze_method_params_weight(ir_entity *ent) {
        assure_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->attr.mtd_attr.param_weight[proj_nr]  += calc_method_param_weight(arg);
+               ent->attr.mtd_attr.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
 }
 
 /*
@@ -443,15 +465,15 @@ static void analyze_method_params_weight(ir_entity *ent) {
  * higher optimization with procedure cloning.
  *
  * The values are calculation on demand only.
+ *
+ * @param ent  the entity to analyze
+ * @param pos  the argument number
+ *
+ * @return the parameter weight or null_weight if pos is greater
+ * than the number of arguments.
  */
-unsigned get_method_param_weight(ir_entity *ent, int pos)
+unsigned get_method_param_weight(ir_entity *ent, size_t pos)
 {
-#ifndef NDEBUG
-       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)));
-#endif
-
        if (ent->attr.mtd_attr.param_weight) {
                if (pos < ARR_LEN(ent->attr.mtd_attr.param_weight))
                        return ent->attr.mtd_attr.param_weight[pos];
@@ -473,13 +495,18 @@ unsigned get_method_param_weight(ir_entity *ent, int pos)
  *
  * @param irg The ir graph to analyze.
  */
-void analyze_irg_args_weight(ir_graph *irg) {
-       ir_entity *ent;
+void analyze_irg_args_weight(ir_graph *irg)
+{
+       ir_entity *entity = get_irg_entity(irg);
+       if (entity == NULL)
+               return;
 
-       ent = get_irg_entity(irg);
-       if (ent == NULL)
+       assert(is_method_entity(entity));
+       if (entity->attr.mtd_attr.param_weight != NULL)
                return;
 
-       if (! ent->attr.mtd_attr.param_weight)
-               analyze_method_params_weight(ent);
+       ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
+       inc_irg_visited(irg);
+       analyze_method_params_weight(entity);
+       ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
 }