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
*/
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;
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);
}
/**
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)
{
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);
#include "irgwalk.h"
#include "counter.h"
#include "irhooks.h"
+#include "ident.h"
/* some useful macro. */
#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
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;
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 */
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 */
* 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. */
* 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 */
}
}
+/**
+ * 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
*/
);
}
+ /* 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");