- std function-prolog emitter eingebaut
[libfirm] / ir / ana / callgraph.c
index b03a0f0..700dfcb 100644 (file)
  * @date        21.7.2004
  * @version     $Id$
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
-# ifdef HAVE_STDLIB_H
+#include <string.h>
 #include <stdlib.h>
-#endif
 
 #include "callgraph.h"
 
@@ -53,9 +47,9 @@
 #include "irgwalk.h"
 
 static ir_visited_t master_cg_visited = 0;
-static INLINE int cg_irg_visited      (ir_graph *n);
-static INLINE void mark_cg_irg_visited(ir_graph *n);
-static INLINE void set_cg_irg_visited (ir_graph *n, ir_visited_t i);
+static inline int cg_irg_visited      (ir_graph *n);
+static inline void mark_cg_irg_visited(ir_graph *n);
+static inline void set_cg_irg_visited (ir_graph *n, ir_visited_t i);
 
 /** Returns the callgraph state of the program representation. */
 irp_callgraph_state get_irp_callgraph_state(void) {
@@ -68,20 +62,20 @@ void set_irp_callgraph_state(irp_callgraph_state s) {
 }
 
 /* Returns the number of procedures that call the given irg. */
-int get_irg_n_callers(ir_graph *irg) {
+int get_irg_n_callers(const ir_graph *irg) {
        if (irg->callers) return ARR_LEN(irg->callers);
        return -1;
 }
 
 /* Returns the caller at position pos. */
-ir_graph *get_irg_caller(ir_graph *irg, int pos) {
+ir_graph *get_irg_caller(const ir_graph *irg, int pos) {
        assert(pos >= 0 && pos < get_irg_n_callers(irg));
        if (irg->callers) return irg->callers[pos];
        return NULL;
 }
 
 /* Returns non-zero if the caller at position pos is "a backedge", i.e. a recursion. */
-int is_irg_caller_backedge(ir_graph *irg, int pos) {
+int is_irg_caller_backedge(const ir_graph *irg, int pos) {
        assert(pos >= 0 && pos < get_irg_n_callers(irg));
        return irg->caller_isbe != NULL ? rbitset_is_set(irg->caller_isbe, pos) : 0;
 }
@@ -102,7 +96,7 @@ static void set_irg_caller_backedge(ir_graph *irg, ir_graph *caller) {
 }
 
 /* Returns non-zero if the irg has a backedge caller. */
-int has_irg_caller_backedge(ir_graph *irg) {
+int has_irg_caller_backedge(const ir_graph *irg) {
        int i, n_callers = get_irg_n_callers(irg);
 
        if (irg->caller_isbe != NULL) {
@@ -118,7 +112,7 @@ int has_irg_caller_backedge(ir_graph *irg) {
  * Given the position pos_caller of an caller of irg, return
  * irg's callee position on that caller.
  */
-static int reverse_pos(ir_graph *callee, int pos_caller) {
+static int reverse_pos(const ir_graph *callee, int pos_caller) {
        ir_graph *caller = get_irg_caller(callee, pos_caller);
        /* search the other relation for the corresponding edge. */
        int pos_callee = -1;
@@ -136,7 +130,7 @@ static int reverse_pos(ir_graph *callee, int pos_caller) {
 }
 
 /* Returns the maximal loop depth of call nodes that call along this edge. */
-int get_irg_caller_loop_depth(ir_graph *irg, int pos) {
+int get_irg_caller_loop_depth(const ir_graph *irg, int pos) {
        ir_graph *caller     = get_irg_caller(irg, pos);
        int       pos_callee = reverse_pos(irg, pos);
 
@@ -145,26 +139,26 @@ int get_irg_caller_loop_depth(ir_graph *irg, int pos) {
 
 
 /* Returns the number of procedures that are called by the given irg. */
-int get_irg_n_callees(ir_graph *irg) {
+int get_irg_n_callees(const ir_graph *irg) {
        if (irg->callees) return ARR_LEN(irg->callees);
        return -1;
 }
 
 /* Returns the callee at position pos. */
-ir_graph *get_irg_callee(ir_graph *irg, int pos) {
+ir_graph *get_irg_callee(const ir_graph *irg, int pos) {
        assert(pos >= 0 && pos < get_irg_n_callees(irg));
        if (irg->callees) return irg->callees[pos]->irg;
        return NULL;
 }
 
 /* Returns non-zero if the callee at position pos is "a backedge", i.e. a recursion. */
-int is_irg_callee_backedge(ir_graph *irg, int pos) {
+int is_irg_callee_backedge(const ir_graph *irg, int pos) {
        assert(pos >= 0 && pos < get_irg_n_callees(irg));
        return irg->callee_isbe != NULL ? rbitset_is_set(irg->callee_isbe, pos) : 0;
 }
 
 /* Returns non-zero if the irg has a backedge callee. */
-int has_irg_callee_backedge(ir_graph *irg) {
+int has_irg_callee_backedge(const ir_graph *irg) {
        int i, n_callees = get_irg_n_callees(irg);
 
        if (irg->callee_isbe != NULL) {
@@ -189,14 +183,14 @@ static void set_irg_callee_backedge(ir_graph *irg, int pos) {
 }
 
 /* Returns the maximal loop depth of call nodes that call along this edge. */
-int get_irg_callee_loop_depth(ir_graph *irg, int pos) {
+int get_irg_callee_loop_depth(const ir_graph *irg, int pos) {
        assert(pos >= 0 && pos < get_irg_n_callees(irg));
        if (irg->callees) return irg->callees[pos]->max_depth;
        return -1;
 }
 
 
-double get_irg_callee_execution_frequency(ir_graph *irg, int pos) {
+double get_irg_callee_execution_frequency(const ir_graph *irg, int pos) {
        ir_node **arr = irg->callees[pos]->call_list;
        int i, n_Calls = ARR_LEN(arr);
        double freq = 0.0;
@@ -207,14 +201,14 @@ double get_irg_callee_execution_frequency(ir_graph *irg, int pos) {
        return freq;
 }
 
-double get_irg_callee_method_execution_frequency(ir_graph *irg, int pos) {
+double get_irg_callee_method_execution_frequency(const ir_graph *irg, int pos) {
        double call_freq = get_irg_callee_execution_frequency(irg, pos);
        double meth_freq = get_irg_method_execution_frequency(irg);
        return call_freq * meth_freq;
 }
 
 
-double get_irg_caller_method_execution_frequency(ir_graph *irg, int pos) {
+double get_irg_caller_method_execution_frequency(const ir_graph *irg, int pos) {
        ir_graph *caller     = get_irg_caller(irg, pos);
        int       pos_callee = reverse_pos(irg, pos);
 
@@ -255,7 +249,7 @@ static void ana_Call(ir_node *n, void *env) {
                                ARR_APP1(ir_node *, arr, n);
                                found->call_list = arr;
                        } else { /* New node, add Call node and init nesting. */
-                               found = (cg_callee_entry *)obstack_alloc(irg->obst, sizeof(*found));
+                               found = OALLOC(irg->obst, cg_callee_entry);
                                found->irg = callee;
                                found->call_list = NEW_ARR_F(ir_node *, 1);
                                found->call_list[0] = n;
@@ -386,32 +380,23 @@ static void do_walk(ir_graph *irg, callgraph_walk_func *pre, callgraph_walk_func
                post(irg, env);
 }
 
-void callgraph_walk(ir_entity **roots, unsigned n_roots,
-               callgraph_walk_func *pre, callgraph_walk_func *post, void *env) {
-       //int i, n_irgs = get_irp_n_irgs();
-       unsigned r;
+void callgraph_walk(callgraph_walk_func *pre, callgraph_walk_func *post, void *env) {
+       int i, n_irgs = get_irp_n_irgs();
        ++master_cg_visited;
 
-       for (r = 0; r < n_roots; ++r) {
-               ir_graph *irg = get_entity_irg(roots[r]);
-               if (irg == NULL)
-                       continue;
-
-               do_walk(irg, pre, post, env);
-       }
-
-#if 0
-       for (i = 0; i < n_irgs; i++) {
+       /* roots are methods which have no callers in the current program */
+       for (i = 0; i < n_irgs; ++i) {
                ir_graph *irg = get_irp_irg(i);
-               if (!cg_irg_visited(irg) && get_irg_n_callers(irg) == 0)
+
+               if (get_irg_n_callers(irg) == 0)
                        do_walk(irg, pre, post, env);
        }
+
+       /* in case of unreachable call loops we haven't visited some irgs yet */
        for (i = 0; i < n_irgs; i++) {
                ir_graph *irg = get_irp_irg(i);
-               if (!cg_irg_visited(irg))
-                       do_walk(irg, pre, post, env);
+               do_walk(irg, pre, post, env);
        }
-#endif
 }
 
 /* ----------------------------------------------------------------------------------- */
@@ -442,77 +427,75 @@ typedef struct scc_info {
 /**
  * allocates a new scc_info on the obstack
  */
-static INLINE scc_info *new_scc_info(struct obstack *obst) {
-       scc_info *info = obstack_alloc(obst, sizeof(*info));
-       memset(info, 0, sizeof(*info));
-       return info;
+static inline scc_info *new_scc_info(struct obstack *obst) {
+       return OALLOCZ(obst, scc_info);
 }
 
 /**
  * Returns non-zero if a graph was already visited.
  */
-static INLINE int cg_irg_visited(ir_graph *irg) {
+static inline int cg_irg_visited(ir_graph *irg) {
        return irg->self_visited >= master_cg_visited;
 }
 
 /**
  * Marks a graph as visited.
  */
-static INLINE void mark_cg_irg_visited(ir_graph *irg) {
+static inline void mark_cg_irg_visited(ir_graph *irg) {
        irg->self_visited = master_cg_visited;
 }
 
 /**
  * Set a graphs visited flag to i.
  */
-static INLINE void set_cg_irg_visited(ir_graph *irg, ir_visited_t i) {
+static inline void set_cg_irg_visited(ir_graph *irg, ir_visited_t i) {
        irg->self_visited = i;
 }
 
 /**
  * Returns the visited flag of a graph.
  */
-static INLINE ir_visited_t get_cg_irg_visited(ir_graph *irg) {
+static inline ir_visited_t get_cg_irg_visited(ir_graph *irg) {
        return irg->self_visited;
 }
 
-static INLINE void mark_irg_in_stack(ir_graph *irg) {
+static inline void mark_irg_in_stack(ir_graph *irg) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        info->in_stack = 1;
 }
 
-static INLINE void mark_irg_not_in_stack(ir_graph *irg) {
+static inline void mark_irg_not_in_stack(ir_graph *irg) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        info->in_stack = 0;
 }
 
-static INLINE int irg_is_in_stack(ir_graph *irg) {
+static inline int irg_is_in_stack(ir_graph *irg) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        return info->in_stack;
 }
 
-static INLINE void set_irg_uplink(ir_graph *irg, int uplink) {
+static inline void set_irg_uplink(ir_graph *irg, int uplink) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        info->uplink = uplink;
 }
 
-static INLINE int get_irg_uplink(ir_graph *irg) {
+static inline int get_irg_uplink(ir_graph *irg) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        return info->uplink;
 }
 
-static INLINE void set_irg_dfn(ir_graph *irg, int dfn) {
+static inline void set_irg_dfn(ir_graph *irg, int dfn) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        info->dfn = dfn;
 }
 
-static INLINE int get_irg_dfn(ir_graph *irg) {
+static inline int get_irg_dfn(ir_graph *irg) {
        scc_info *info = get_irg_link(irg);
        assert(info && "missing call to init_scc()");
        return info->dfn;
@@ -528,7 +511,7 @@ static int tos = 0;                /**< top of stack */
 /**
  * Initialize the irg stack.
  */
-static INLINE void init_stack(void) {
+static inline void init_stack(void) {
        if (stack) {
                ARR_RESIZE(ir_graph *, stack, 1000);
        } else {
@@ -541,7 +524,7 @@ static INLINE void init_stack(void) {
  * push a graph on the irg stack
  * @param n the graph to be pushed
  */
-static INLINE void push(ir_graph *irg) {
+static inline void push(ir_graph *irg) {
        if (tos == ARR_LEN(stack)) {
                int nlen = ARR_LEN(stack) * 2;
                ARR_RESIZE(ir_node *, stack, nlen);
@@ -553,7 +536,7 @@ static INLINE void push(ir_graph *irg) {
 /**
  * return the topmost graph on the stack and pop it
  */
-static INLINE ir_graph *pop(void) {
+static inline ir_graph *pop(void) {
        ir_graph *irg = stack[--tos];
        mark_irg_not_in_stack(irg);
        return irg;
@@ -563,7 +546,7 @@ static INLINE ir_graph *pop(void) {
  * The nodes up to irg belong to the current loop.
  * Removes them from the stack and adds them to the current loop.
  */
-static INLINE void pop_scc_to_loop(ir_graph *irg) {
+static inline void pop_scc_to_loop(ir_graph *irg) {
        ir_graph *m;
 
        do {
@@ -605,7 +588,7 @@ static void close_loop(ir_loop *l) {
  * Removes and unmarks all nodes up to n from the stack.
  * The nodes must be visited once more to assign them to a scc.
  */
-static INLINE void pop_scc_unmark_visit(ir_graph *n) {
+static inline void pop_scc_unmark_visit(ir_graph *n) {
        ir_graph *m = NULL;
 
        while (m != n) {
@@ -677,7 +660,7 @@ static int is_head(ir_graph *n, ir_graph *root) {
                }
        }
 
-       return some_outof_loop & some_in_loop;
+       return some_outof_loop && some_in_loop;
 }
 
 /**
@@ -706,7 +689,7 @@ static int is_endless_head(ir_graph *n, ir_graph *root)
                        some_in_loop = 1;
                }
        }
-       return !some_outof_loop & some_in_loop;
+       return !some_outof_loop && some_in_loop;
 }
 
 #ifdef INTERPROCEDURAL_VIEW
@@ -940,7 +923,7 @@ static void cgscc(ir_graph *n) {
                /** This marks the backedge, but does it guarantee a correct loop tree? */
                //if (m == n) { set_irg_callee_backedge(n, i); continue; }
 
-               cgscc (m);
+               cgscc(m);
                if (irg_is_in_stack(m)) {
                        /* Uplink of m is smaller if n->m is a backedge.
                           Propagate the uplink to mark the cfloop. */
@@ -1148,7 +1131,7 @@ static void compute_rec_depth(ir_graph *irg, void *env) {
 /* ----------------------------------------------------------------------------------- */
 
 /* Returns the method execution frequency of a graph. */
-double get_irg_method_execution_frequency(ir_graph *irg) {
+double get_irg_method_execution_frequency(const ir_graph *irg) {
        return irg->method_execution_frequency;
 }
 
@@ -1221,7 +1204,7 @@ static void compute_method_execution_frequency(ir_graph *irg, void *env) {
 
 /* Compute the backedges that represent recursions. */
 void find_callgraph_recursions(void) {
-       int i, n_irgs = get_irp_n_irgs();
+       int i, n_irgs;
        struct obstack temp;
 
        reset_isbe();
@@ -1242,6 +1225,7 @@ void find_callgraph_recursions(void) {
 
        ++master_cg_visited;
        cgscc(outermost_ir_graph);
+       n_irgs = get_irp_n_irgs();
        for (i = 0; i < n_irgs; ++i) {
                ir_graph *irg = get_irp_irg(i);
                if (!cg_irg_visited(irg) && get_irg_n_callers(irg) == 0)
@@ -1351,7 +1335,7 @@ void compute_performance_estimates(void) {
 
 /* Returns the maximal loop depth of all paths from an external visible method to
    this irg. */
-int  get_irg_loop_depth(ir_graph *irg) {
+int  get_irg_loop_depth(const ir_graph *irg) {
        assert(irp->callgraph_state == irp_callgraph_consistent ||
                irp->callgraph_state == irp_callgraph_and_calltree_consistent);
        return  irg->callgraph_loop_depth;
@@ -1359,7 +1343,7 @@ int  get_irg_loop_depth(ir_graph *irg) {
 
 /* Returns the maximal recursion depth of all paths from an external visible method to
    this irg. */
-int get_irg_recursion_depth(ir_graph *irg) {
+int get_irg_recursion_depth(const ir_graph *irg) {
        assert(irp->callgraph_state == irp_callgraph_and_calltree_consistent);
        return irg->callgraph_recursion_depth;
 }