constified is_Phi
[libfirm] / ir / ana / callgraph.c
index 41b9f7a..ed0b279 100644 (file)
@@ -9,8 +9,16 @@
  * Copyright:   (c) 2004 Universität Karlsruhe
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
-
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <stdlib.h>
+
 #include "callgraph.h"
 
 #include "irloop_t.h"
@@ -18,6 +26,8 @@
 #include "irgraph_t.h"
 #include "irnode_t.h"
 
+#include "cgana.h"
+
 #include "array.h"
 #include "pmap.h"
 
@@ -128,7 +138,12 @@ int get_irg_callee_loop_depth(ir_graph *irg, int pos) {
 
 /* --------------------- Compute the callgraph ------------------------ */
 
+/* Hash an address */
+#define HASH_ADDRESS(adr)       (((unsigned)(adr)) >> 3)
 
+/**
+ * Walker called by compute_callgraph()
+ */
 static void ana_Call(ir_node *n, void *env) {
   int i, n_callees;
   ir_graph *irg;
@@ -139,19 +154,18 @@ static void ana_Call(ir_node *n, void *env) {
   n_callees = get_Call_n_callees(n);
   for (i = 0; i < n_callees; ++i) {
     entity *callee_e = get_Call_callee(n, i);
-    if (callee_e) {  /* Null for unknown caller */
-      ir_graph *callee = get_entity_irg(callee_e);
+    ir_graph *callee = get_entity_irg(callee_e);
+    if (callee) {  /* For unknown caller */
       pset_insert((pset *)callee->callers, irg, (unsigned)irg >> 3);
-
       ana_entry buf = { callee, NULL, 0};
-      ana_entry *found = pset_find((pset *)irg->callees, &buf, (unsigned)callee >> 3);
+      ana_entry *found = pset_find((pset *)irg->callees, &buf, HASH_ADDRESS(callee));
       if (found) {  /* add Call node to list, compute new nesting. */
       } else { /* New node, add Call node and init nesting. */
        found = (ana_entry *) obstack_alloc (irg->obst, sizeof (ana_entry));
        found->irg = callee;
        found->call_list = NULL;
        found->max_depth = 0;
-       pset_insert((pset *)irg->callees, found, (unsigned)callee >> 3);
+       pset_insert((pset *)irg->callees, found, HASH_ADDRESS(callee));
       }
       int depth = get_loop_depth(get_irn_loop(get_nodes_block(n)));
       found->max_depth = (depth > found->max_depth) ? depth : found->max_depth;
@@ -159,14 +173,14 @@ static void ana_Call(ir_node *n, void *env) {
   }
 }
 
-/* compare two ir graphs */
+/** compare two ir graphs in a ana_entry */
 static int ana_entry_cmp(const void *elt, const void *key) {
-  ana_entry *e1 = (ana_entry *)elt;
-  ana_entry *e2 = (ana_entry *)key;
+  const ana_entry *e1 = elt;
+  const ana_entry *e2 = key;
   return e1->irg != e2->irg;
 }
 
-/* compare two ir graphs */
+/** compare two ir graphs */
 static int graph_cmp(const void *elt, const void *key) {
   return elt != key;
 }
@@ -176,7 +190,7 @@ static int graph_cmp(const void *elt, const void *key) {
 void compute_callgraph(void) {
   int i, n_irgs = get_irp_n_irgs();
 
-  assert(interprocedural_view == 0);  /* Else walking will not reach the Call nodes. */
+  assert(! get_interprocedural_view());  /* Else walking will not reach the Call nodes. */
 
   /* initialize */
   free_callgraph();
@@ -233,8 +247,8 @@ void free_callgraph(void) {
     ir_graph *irg = get_irp_irg(i);
     if (irg->callees) DEL_ARR_F(irg->callees);
     if (irg->callers) DEL_ARR_F(irg->callers);
-    if (irg->callee_isbe) DEL_ARR_F(irg->callee_isbe);
-    if (irg->caller_isbe) DEL_ARR_F(irg->caller_isbe);
+    if (irg->callee_isbe) free(irg->callee_isbe);
+    if (irg->caller_isbe) free(irg->caller_isbe);
     irg->callees = NULL;
     irg->callers = NULL;
     irg->callee_isbe = NULL;
@@ -520,7 +534,6 @@ init_scc (void) {
     set_irg_link(get_irp_irg(i), new_scc_info());
     get_irp_irg(i)->callgraph_recursion_depth = 0;
     get_irp_irg(i)->callgraph_loop_depth = 0;
-    get_irp_irg(i)->callgraph_weighted_loop_depth = 0;
   }
 }
 
@@ -587,8 +600,8 @@ is_endless_head (ir_graph *n, ir_graph *root)
 static bool
 is_ip_head (ir_graph *n, ir_graph *pred)
 {
-  int iv_rem = interprocedural_view;
-  interprocedural_view = 1;
+  int iv_rem = get_interprocedural_view();
+  set_interprocedural_view(true);
   ir_node *sblock = get_irg_start_block(n);
   int i, arity = get_Block_n_cfgpreds(sblock);
   int is_be = 0;
@@ -610,7 +623,7 @@ is_ip_head (ir_graph *n, ir_graph *pred)
     }
   }
 
-  interprocedural_view = iv_rem;
+  set_interprocedural_view(iv_rem);
   return is_be;
 }
 
@@ -891,12 +904,27 @@ static void reset_isbe(void) {
 
 void compute_loop_depth (ir_graph *irg, void *env) {
   int current_nesting = *(int *) env;
+  int old_nesting = irg->callgraph_loop_depth;
+  int old_visited = get_cg_irg_visited(irg);
   int i, n_callees;
 
+  //return ;
+
   if (cg_irg_visited(irg)) return;
+
   mark_cg_irg_visited(irg);
 
-  if (current_nesting == 0 || irg->callgraph_loop_depth < current_nesting) {
+  //printf(" old: %d new %d master %d", old_visited, get_cg_irg_visited(irg), master_cg_visited); DDMG(irg);
+
+
+  if (old_nesting < current_nesting)
+    irg->callgraph_loop_depth = current_nesting;
+
+  if (current_nesting > irp->max_callgraph_loop_depth)
+    irp->max_callgraph_loop_depth = current_nesting;
+
+  if ((old_visited +1 < get_cg_irg_visited(irg)) ||   /* not yet visited */
+      (old_nesting < current_nesting)) {        /* propagate larger nesting */
     /* Don't walk the graph, but a tree that is an unfolded graph. */
     n_callees = get_irg_n_callees(irg);
     for (i = 0; i < n_callees; i++) {
@@ -907,9 +935,6 @@ void compute_loop_depth (ir_graph *irg, void *env) {
     }
   }
 
-  if (irg->callgraph_loop_depth < current_nesting)
-    irg->callgraph_loop_depth = current_nesting;
-
   set_cg_irg_visited(irg, master_cg_visited-1);
 }
 
@@ -956,13 +981,14 @@ static int in_stack(ana_entry2 *e, ir_loop *g) {
 void compute_rec_depth (ir_graph *irg, void *env) {
   ana_entry2 *e = (ana_entry2 *)env;
   ir_loop *l = irg->l;
-  int depth;
+  int depth, old_depth = irg->callgraph_recursion_depth;
   int i, n_callees;
   int pushed = 0;
 
   if (cg_irg_visited(irg)) return;
   mark_cg_irg_visited(irg);
 
+  /* -- compute and set the new nesting value -- */
   if ((l != irp->outermost_cg_loop) && !in_stack(e, l)) {
     push2(e, l);
     e->recursion_nesting++;
@@ -970,7 +996,14 @@ void compute_rec_depth (ir_graph *irg, void *env) {
   }
   depth = e->recursion_nesting;
 
-  if (depth == 0 || irg->callgraph_recursion_depth < depth) {
+  if (old_depth < depth)
+    irg->callgraph_recursion_depth = depth;
+
+  if (depth > irp->max_callgraph_recursion_depth)
+    irp->max_callgraph_recursion_depth = depth;
+
+  /* -- spread the nesting value -- */
+  if (depth == 0 || old_depth < depth) {
     /* Don't walk the graph, but a tree that is an unfolded graph. */
     n_callees = get_irg_n_callees(irg);
     for (i = 0; i < n_callees; i++) {
@@ -979,9 +1012,7 @@ void compute_rec_depth (ir_graph *irg, void *env) {
     }
   }
 
-  if (irg->callgraph_recursion_depth < depth)
-    irg->callgraph_recursion_depth = depth;
-
+  /* -- clean up -- */
   if (pushed) {
     pop2(e);
     e->recursion_nesting--;
@@ -1032,38 +1063,52 @@ void find_callgraph_recursions(void) {
     }
   }
 
-  /* -- Schleifentiefe berechnen -- */
+  /* -- compute the loop depth  -- */
   int current_nesting = 0;
+  irp->max_callgraph_loop_depth = 0;
   master_cg_visited += 2;
+  //printf (" ** starting at      "); DDMG(get_irp_main_irg());
   compute_loop_depth(get_irp_main_irg(), &current_nesting);
   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_cg_irg_visited(irg) < master_cg_visited-1) &&
+       get_irg_n_callers(irg) == 0) {
       compute_loop_depth(irg, &current_nesting);
+      //printf (" ** starting at      "); DDMG(irg);
+    }
   }
   for (i = 0; i < n_irgs; i++) {
     ir_graph *irg = get_irp_irg(i);
-    if (get_cg_irg_visited(irg) < master_cg_visited-1)
+    if (get_cg_irg_visited(irg) < master_cg_visited-1) {
       compute_loop_depth(irg, &current_nesting);
+      //printf (" ** starting at      "); DDMG(irg);
+    }
   }
 
-  /* -- Rekursionstiefe berechnen -- */
+  /* -- compute the recursion depth -- */
   ana_entry2 e;
   e.loop_stack = NEW_ARR_F(ir_loop *, 0);
   e.tos = 0;
   e.recursion_nesting = 0;
+  irp->max_callgraph_recursion_depth = 0;
 
   master_cg_visited += 2;
   compute_rec_depth(get_irp_main_irg(), &e);
+  //printf (" ++ starting at "); DDMG(get_irp_main_irg());
   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_cg_irg_visited(irg) < master_cg_visited-1) &&
+       get_irg_n_callers(irg) == 0) {
       compute_rec_depth(irg, &e);
+      //printf (" ++ starting at "); DDMG(irg);
+    }
   }
   for (i = 0; i < n_irgs; i++) {
     ir_graph *irg = get_irp_irg(i);
-    if (get_cg_irg_visited(irg) < master_cg_visited-1)
+    if (get_cg_irg_visited(irg) < master_cg_visited-1) {
       compute_rec_depth(irg, &e);
+      //printf (" ++ starting at "); DDMG(irg);
+    }
   }
 
   DEL_ARR_F(e.loop_stack);
@@ -1088,3 +1133,19 @@ int       get_irg_recursion_depth(ir_graph *irg) {
   assert(irp->callgraph_state == irp_callgraph_and_calltree_consistent);
   return irg->callgraph_recursion_depth;
 }
+
+void analyse_loop_nesting_depth(void) {
+  entity **free_methods = NULL;
+  int arr_len;
+
+  /* establish preconditions. */
+  if (get_irp_callee_info_state() != irg_callee_info_consistent) {
+    cgana(&arr_len, &free_methods);
+  }
+
+  if (irp_callgraph_consistent != get_irp_callgraph_state()) {
+    compute_callgraph();
+  }
+
+  find_callgraph_recursions();
+}