Some more cleanup: Put the return type and other specifiers on the same line as the...
[libfirm] / ir / opt / ircgopt.c
index a06be95..eca8ffb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -30,9 +30,7 @@
  * der nicht erreichbaren Methoden wird aus der Abschätzung der
  * Aufrufrelation bestimmt.
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include "ircgopt.h"
 
 #include "irloop_t.h"
 #include "irflag_t.h"
 #include "ircons.h"
+#include "cgana.h"
 #include "irtools.h"
+#include "irpass.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg);
 
 /**
  * Walker: adds Call operations to a head's link list.
  */
-static void collect_call(ir_node * node, void *env) {
-  ir_node *head = env;
+static void collect_call(ir_node *node, void *env)
+{
+       ir_node *head = env;
+
+       if (is_Call(node)) {
+               set_irn_link(node, get_irn_link(head));
+               set_irn_link(head, node);
+       }
+}
 
-  if (get_irn_op(node) == op_Call) {
-    set_irn_link(node, get_irn_link(head));
-    set_irn_link(head, node);
-  }
+/* garbage collect methods: mark and remove */
+void gc_irgs(int n_keep, ir_entity ** keep_arr)
+{
+       void * MARK = &MARK; /* @@@ gefaehrlich!!! Aber wir markieren hoechstens zu viele ... */
+       int i;
+
+       FIRM_DBG_REGISTER(dbg, "firm.opt.cgopt");
+
+       if (n_keep >= get_irp_n_irgs()) {
+               /* Shortcut. Obviously we have to keep all methods. */
+               return;
+       }
+
+       DB((dbg, LEVEL_1, "dead method elimination\n"));
+
+       /* Mark entities that are alive.  */
+       if (n_keep > 0) {
+               ir_entity **marked = NEW_ARR_F(ir_entity *, n_keep);
+               for (i = 0; i < n_keep; ++i) {
+                       marked[i] = keep_arr[i];
+                       set_entity_link(marked[i], MARK);
+                       DB((dbg, LEVEL_1, "  method %+F kept alive.\n", marked[i]));
+               }
+
+               for (i = 0; i < ARR_LEN(marked); ++i) {
+                       ir_graph *irg = get_entity_irg(marked[i]);
+                       ir_node *node;
+
+                       if (irg == NULL)
+                               continue;
+
+                       node = get_irg_end(irg);
+
+                       /* collect calls */
+                       ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
+                       irg_walk_graph(irg, firm_clear_link, collect_call, node);
+
+                       /* iterate calls */
+                       for (node = get_irn_link(node); node; node = get_irn_link(node)) {
+                               int i;
+                               assert(is_Call(node));
+
+                               for (i = get_Call_n_callees(node) - 1; i >= 0; --i) {
+                                       ir_entity *ent = get_Call_callee(node, i);
+
+                                       if (get_entity_irg(ent) && get_entity_link(ent) != MARK) {
+                                               set_entity_link(ent, MARK);
+                                               ARR_APP1(ir_entity *, marked, ent);
+
+                                               DB((dbg, LEVEL_1, "  method %+F can be called from Call %+F: kept alive.\n",
+                                                       ent, node));
+                                       }
+                               }
+                       }
+                       ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
+               }
+               DEL_ARR_F(marked);
+       }
+
+       /* clean */
+       for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+               ir_graph  *irg = get_irp_irg(i);
+               ir_entity *ent = get_irg_entity(irg);
+
+               if (get_entity_link(ent) == MARK)
+                       continue;
+
+               DB((dbg, LEVEL_1, "  freeing method %+F\n",     ent));
+               remove_irp_irg(irg);
+
+               remove_class_member(get_entity_owner(ent), ent);
+       }
 }
 
-static void make_entity_to_description(type_or_ent *tore, void *env) {
-  if (get_kind(tore) == k_entity) {
-    ir_entity *ent = (ir_entity *)tore;
-
-    if ((is_Method_type(get_entity_type(ent)))                        &&
-        (get_entity_peculiarity(ent) != peculiarity_description)      &&
-        (get_entity_visibility(ent)  != visibility_external_allocated)   ) {
-      ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(ent));
-      if (get_entity_link(impl) != env) {
-        set_entity_peculiarity(ent, peculiarity_description);
-      }
-    }
-  }
+/**
+ * Wrapper for running gc_irgs() as an ir_prog pass.
+ */
+static void pass_wrapper(void)
+{
+    ir_entity **keep_methods;
+    int         arr_len;
+
+    /* Analysis that finds the free methods,
+       i.e. methods that are dereferenced.
+       Optimizes polymorphic calls :-). */
+    cgana(&arr_len, &keep_methods);
+
+    /* Remove methods that are never called. */
+    gc_irgs(arr_len, keep_methods);
+
+    free(keep_methods);
 }
 
-/* garbage collect methods: mark and remove */
-void gc_irgs(int n_keep, ir_entity ** keep_arr) {
-  void * MARK = &MARK; /* @@@ gefaehrlich!!! Aber wir markieren hoechstens zu viele ... */
-  int i;
-
-  FIRM_DBG_REGISTER(dbg, "firm.opt.cgopt");
-
-  if (n_keep >= get_irp_n_irgs()) {
-    /* Shortcut. Obviously we have to keep all methods. */
-    return;
-  }
-
-  /* Mark entities that are alive.  */
-  if (n_keep > 0) {
-    ir_entity ** marked = NEW_ARR_F(ir_entity *, n_keep);
-    for (i = 0; i < n_keep; ++i) {
-      marked[i] = keep_arr[i];
-      set_entity_link(marked[i], MARK);
-      DB((dbg, LEVEL_2, "dead method elimination: method %s kept alive.\n",
-          get_entity_ld_name(marked[i])));
-    }
-
-    for (i = 0; i < ARR_LEN(marked); ++i) {
-      /* check for extern methods, these don't have an IRG */
-      if (get_entity_visibility(marked[i]) != visibility_external_allocated) {
-        ir_graph * irg = get_entity_irg(marked[i]);
-        ir_node * node = get_irg_end(irg);
-
-        /* collect calls */
-        irg_walk_graph(irg, firm_clear_link, collect_call, node);
-
-        /* iterate calls */
-        for (node = get_irn_link(node); node; node = get_irn_link(node)) {
-          int i;
-          assert(get_irn_op(node) == op_Call);
-
-          for (i = get_Call_n_callees(node) - 1; i >= 0; --i) {
-            ir_entity * ent = get_Call_callee(node, i);
-
-            if (get_entity_irg(ent) && get_entity_link(ent) != MARK) {
-              set_entity_link(ent, MARK);
-              ARR_APP1(ir_entity *, marked, ent);
-
-              DB((dbg, LEVEL_2, "dead method elimination: method %s can be "
-                   "called from Call %ld: kept alive.\n",
-                      get_entity_ld_name(ent), get_irn_node_nr(node)));
-            }
-          }
-        }
-      }
-    }
-    DEL_ARR_F(marked);
-  }
-
-  /* clean */
-  type_walk(make_entity_to_description, NULL, MARK);
-  for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
-    ir_graph * irg = get_irp_irg(i);
-    ir_entity * ent = get_irg_entity(irg);
-    /* Removing any graph invalidates all interprocedural loop trees. */
-    if (get_irg_loopinfo_state(irg) == loopinfo_ip_consistent ||
-        get_irg_loopinfo_state(irg) == loopinfo_ip_inconsistent) {
-      free_loop_information(irg);
-    }
-    if ((get_entity_visibility(ent) == visibility_local) && (get_entity_link(ent) != MARK)) {
-      remove_irp_irg(irg);
-      set_entity_peculiarity(ent, peculiarity_description);
-
-         DB((dbg, LEVEL_2, "dead method elimination: freeing method %s\n",
-             get_entity_ld_name(ent)));
-    }
-    set_entity_link(ent, NULL);
-  }
+ir_prog_pass_t *gc_irgs_pass(const char *name)
+{
+       return def_prog_pass(name ? name : "cgana", pass_wrapper);
 }