added register pressure statistics
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 7 Apr 2006 14:03:11 +0000 (14:03 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 7 Apr 2006 14:03:11 +0000 (14:03 +0000)
[r7601]

ir/stat/firmstat.c
ir/stat/firmstat_t.h
ir/stat/stat_dmp.c

index 9d1781f..aa3a594 100644 (file)
@@ -129,6 +129,17 @@ static int block_cmp(const void *elt, const void *key)
   return e1->block_nr != e2->block_nr;
 }
 
+/**
+ * compare two elements of the block/extbb hash
+ */
+static int reg_pressure_cmp(const void *elt, const void *key)
+{
+  const reg_pressure_entry_t *e1 = elt;
+  const reg_pressure_entry_t *e2 = key;
+
+  return e1->id_name != e2->id_name;
+}
+
 /**
  * compare two elements of the ir_op hash
  */
@@ -267,6 +278,9 @@ static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap)
   elem->address_mark = new_set(address_mark_cmp, 5);
   elem->irg          = irg;
 
+  /* create hash map for reg pressure */
+  elem->rp_block_hash = new_pset(block_cmp, 5);
+
   /* these hash tables are created on demand */
   elem->block_hash = NULL;
   elem->extbb_hash = NULL;
@@ -323,6 +337,7 @@ static void block_clear_entry(block_entry_t *elem)
   cnt_clr(&elem->cnt_in_edges);
   cnt_clr(&elem->cnt_out_edges);
   cnt_clr(&elem->cnt_phi_data);
+  elem->reg_pressure = new_pset(reg_pressure_cmp, 2);
 }
 
 /**
@@ -1482,6 +1497,42 @@ static void stat_arch_dep_replace_division_by_const(void *ctx, ir_node *node)
   STAT_LEAVE;
 }
 
+/**
+ * Update the register pressure of a block
+ *
+ * @param ctx        the hook context
+ * @param block      the block for which the reg pressure should be set
+ * @param irg        the irg containing the block
+ * @param pressure   the pressure
+ * @param class_name the ident name of the register class
+ */
+static void stat_be_block_regpressure(void *ctx, ir_node *block, ir_graph *irg, int pressure, ident *class_name)
+{
+  if (! status->stat_options)
+    return;
+
+  STAT_ENTER;
+  {
+    graph_entry_t        *graph = graph_get_entry(irg, status->irg_hash);
+    block_entry_t        *block_ent;
+    reg_pressure_entry_t *rp_ent;
+
+    /* create new block counter */
+    if (! graph->rp_block_hash)
+      graph->rp_block_hash = new_pset(block_cmp, 5);
+
+    block_ent = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(block), graph->rp_block_hash);
+       rp_ent    = obstack_alloc(&status->cnts, sizeof(*rp_ent));
+       memset(rp_ent, 0, sizeof(*rp_ent));
+
+       rp_ent->id_name  = class_name;
+    rp_ent->pressure = pressure;
+
+    pset_insert(block_ent->reg_pressure, rp_ent, HASH_PTR(class_name));
+  }
+  STAT_LEAVE;
+}
+
 /* Dumps a statistics snapshot */
 void stat_dump_snapshot(const char *name, const char *phase)
 {
@@ -1645,6 +1696,7 @@ void firm_init_stat(unsigned enable_options)
   HOOK(hook_func_call,                          stat_func_call);
   HOOK(hook_arch_dep_replace_mul_with_shifts,   stat_arch_dep_replace_mul_with_shifts);
   HOOK(hook_arch_dep_replace_division_by_const, stat_arch_dep_replace_division_by_const);
+  HOOK(hook_be_block_regpressure,               stat_be_block_regpressure);
 
   obstack_init(&status->cnts);
 
index 831b5dd..66553c0 100644 (file)
@@ -25,6 +25,7 @@
 #include "irgwalk.h"
 #include "counter.h"
 #include "irhooks.h"
+#include "ident.h"
 
 /* some useful macro. */
 #define ARR_SIZE(a)   (sizeof(a)/sizeof((a)[0]))
@@ -39,6 +40,7 @@ typedef pset hmap_node_entry_t;
 typedef pset hmap_graph_entry_t;
 typedef pset hmap_opt_entry_t;
 typedef pset hmap_block_entry_t;
+typedef pset hmap_reg_pressure_entry_t;
 typedef pset hmap_ir_op;
 typedef pset hmap_distrib_entry_t;
 
@@ -83,7 +85,8 @@ typedef struct _graph_entry_t {
   HASH_MAP(node_entry_t)  *opcode_hash;                 /**< hash map containing the opcode counter */
   HASH_MAP(block_entry_t) *block_hash;                  /**< hash map containing the block counter */
   HASH_MAP(block_entry_t) *extbb_hash;                  /**< hash map containing the extended block counter */
-  counter_t               cnt_walked;                    /**< walker walked over the graph */
+  HASH_MAP(block_entry_t) *rp_block_hash;               /**< hash map containing the block reg pressure information */
+  counter_t               cnt_walked;                  /**< walker walked over the graph */
   counter_t               cnt_walked_blocks;            /**< walker walked over the graph blocks */
   counter_t               cnt_was_inlined;              /**< number of times other graph were inlined */
   counter_t               cnt_got_inlined;              /**< number of times this graph was inlined */
@@ -115,16 +118,26 @@ typedef struct _opt_entry_t {
   const ir_op *op;      /**< the op for this entry */
 } opt_entry_t;
 
+/**
+ * An entry for register pressure.
+ */
+typedef struct _reg_pressure_entry_t {
+  ident *id_name;    /**< name of the register class */
+  int    pressure;   /**< the register pressure for this class */
+} reg_pressure_entry_t;
+
 /**
  * An entry for a block or extended block in a ir-graph
  */
 typedef struct _block_entry_t {
-  counter_t  cnt_nodes;     /**< the counter of nodes in this block */
-  counter_t  cnt_edges;     /**< the counter of edges in this block */
-  counter_t  cnt_in_edges;  /**< the counter of edges incoming from other blocks to this block */
-  counter_t  cnt_out_edges; /**< the counter of edges outgoing from this block to other blocks */
-  counter_t  cnt_phi_data;  /**< the counter of data Phi nodes in this block */
-  long       block_nr;      /**< block nr */
+  counter_t       cnt_nodes;     /**< the counter of nodes in this block */
+  counter_t       cnt_edges;     /**< the counter of edges in this block */
+  counter_t       cnt_in_edges;  /**< the counter of edges incoming from other blocks to this block */
+  counter_t       cnt_out_edges; /**< the counter of edges outgoing from this block to other blocks */
+  counter_t       cnt_phi_data;  /**< the counter of data Phi nodes in this block */
+  long            block_nr;      /**< block nr */
+  /**< the highest register pressures for this block for each register class */
+  HASH_MAP(reg_pressure_entry_t) *reg_pressure;
 } block_entry_t;
 
 /** An entry for an extended block in a ir-graph */
@@ -232,8 +245,8 @@ ir_op *stat_get_op_from_opcode(opcode code);
  * An entry in a distribution table
  */
 typedef struct _distrib_entry_t {
-  counter_t    cnt;            /**< the current count */
-  const void   *object;        /**< the object which is counted */
+  counter_t     cnt;       /**< the current count */
+  const void *object;   /**< the object which is counted */
 } distrib_entry_t;
 
 /** The type of the hash function for objects in distribution tables. */
@@ -243,10 +256,10 @@ typedef unsigned (*distrib_hash_fun)(const void *object);
  * The distribution table.
  */
 typedef struct _distrib_tbl_t {
-  struct obstack               cnts;           /**< obstack containing the distrib_entry_t entries */
-  HASH_MAP(distrib_entry_t)    *hash_map;      /**< the hash map containing the distribution */
-  distrib_hash_fun          hash_func; /**< the hash function for object in this distribution */
-  unsigned                     int_dist;       /**< non-zero, if it's a integer distribution */
+  struct obstack               cnts;       /**< obstack containing the distrib_entry_t entries */
+  HASH_MAP(distrib_entry_t)    *hash_map;  /**< the hash map containing the distribution */
+  distrib_hash_fun          hash_func;  /**< the hash function for object in this distribution */
+  unsigned                  int_dist;   /**< non-zero, if it's a integer distribution */
 } distrib_tbl_t;
 
 /* API for distribution tables */
index d33184c..caf4b30 100644 (file)
@@ -148,6 +148,44 @@ static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
   }
 }
 
+/**
+ * dumps the register pressure for each block and for each register class
+ */
+static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry) {
+  block_entry_t *b_entry = pset_first(entry->rp_block_hash);
+  reg_pressure_entry_t *rp_entry;
+
+  /* return if no reg pressure information available */
+  if (! b_entry)
+         return;
+
+  /* print table head (register classes) */
+  fprintf(dmp->f, "\nREG PRESSURE:\n");
+  fprintf(dmp->f, "%12s", "Block Nr");
+  for (rp_entry = pset_first(b_entry->reg_pressure);
+       rp_entry;
+          rp_entry = pset_next(b_entry->reg_pressure))
+  {
+    fprintf(dmp->f, "%15s", get_id_str(rp_entry->id_name));
+  }
+  fprintf(dmp->f, "\n");
+
+  /* print the reg pressure for all blocks and register classes */
+  for (/* b_entry is already initialized */ ;
+       b_entry;
+          b_entry = pset_next(entry->rp_block_hash))
+  {
+       fprintf(dmp->f, "BLK   %6ld", b_entry->block_nr);
+       for (rp_entry = pset_first(b_entry->reg_pressure);
+            rp_entry;
+                rp_entry = pset_next(b_entry->reg_pressure))
+       {
+      fprintf(dmp->f, "%15d", rp_entry->pressure);
+       }
+    fprintf(dmp->f, "\n");
+  }
+}
+
 /**
  * dumps the number of real_function_call optimization
  */
@@ -277,6 +315,9 @@ static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
       );
     }
 
+    /* dump block reg pressure */
+       simple_dump_be_block_reg_pressure(dmp, entry);
+
     if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB) {
       /* dump extended block info */
       fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");