+/**
+ * @author Daniel Grund
+ * @date 09.12.2004
+ */
+
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "config.h"
#include "irop.h"
#include "irprog.h"
#include "irmode_t.h"
-#include "bephicongr_t.h"
-
-
-#define SUMMARY_FILE_NAME "all.phi"
-
-#define ARG_CNT_MAX 10
-#define PHI_CLS_MAX 10
-
-#define I_PHI_CNT 0
-#define I_BLK_CNT (I_PHI_CNT+1)
-#define I_SPACE3 (I_BLK_CNT+1)
-#define I_ARG_CNT_S (I_SPACE3+1)
-#define I_ARG_CNT_E (I_ARG_CNT_S+ARG_CNT_MAX)
-#define I_SPACE1 (I_ARG_CNT_E+1)
-#define I_PHI_CLS_S (I_SPACE1+1)
-#define I_PHI_CLS_E (I_PHI_CLS_S+PHI_CLS_MAX)
-#define I_SPACE2 (I_PHI_CLS_E+1)
-#define I_INTERFP (I_SPACE2+1) /* number of interfering pairs */
-#define I_INTERFV (I_INTERFP+1) /* number of interfering values */
-#define I_PHICLSCNT (I_INTERFV+1) /* number of phi classes */
-#define I_INTERFPHI (I_PHICLSCNT+1) /* number of phi classes which have interfering vals */
-#define I_CONST (I_INTERFPHI+1)
-#define I_PRED (I_CONST+1)
-#define I_GLOB (I_PRED+1)
-
-#define ASIZE (I_GLOB+1)
+
+#include "bechordal.h"
+#include "phistat.h"
+
+#define MAX_ARITY 10
+#define MAX_CLS_SIZE 10
+
+/**
+ * For an explanation of these values see phi_stat_dump_pretty
+ */
+enum vals_t {
+ I_ARG = 0,
+ I_CONST,
+ I_PRED,
+ I_GLOB,
+
+ I_SPACE1,
+ I_BLOCKS,
+ I_PHIS,
+ I_PHICLS,
+ I_PHICLSI,
+ I_PAIRS,
+ I_PAIRSI,
+ I_VALUES,
+ I_VALUESI,
+
+ I_SPACE2,
+ I_ARITY_S,
+ I_ARITY_E = I_ARITY_S+MAX_ARITY,
+
+ I_SPACE3,
+ I_CLS_SIZE_S,
+ I_CLS_SIZE_E = I_CLS_SIZE_S+MAX_CLS_SIZE,
+ I_ALL_NODES,
+ ASIZE
+};
+
+/**
+ * Holds current values. Values are added till next
+ * phi_stat_reset
+ */
static int curr_vals[ASIZE];
-static void phi_stat_walker(ir_node *node, void *env) {
- int count, i, size;
+/**
+ * Resets the array holding the data
+ */
+void phi_stat_reset(void) {
+ int i;
+
+ for (i = 0; i < ASIZE; ++i)
+ curr_vals[i] = 0;
+ curr_vals[I_SPACE1] = -1;
+ curr_vals[I_SPACE2] = -1;
+ curr_vals[I_SPACE3] = -1;
+}
+
+
+/**
+ * Collect general data
+ */
+static void stat_walker(ir_node *node, void *env) {
+ /* count all nodes */
+ curr_vals[I_ALL_NODES]++;
/* count all block nodes */
if (is_Block(node))
- curr_vals[I_BLK_CNT]++;
+ curr_vals[I_BLOCKS]++;
+}
- if (!(is_Phi(node) && mode_is_datab(get_irn_mode(node)))) return;
+
+/**
+ * Collect phi node data
+ */
+static void phi_node_stat(ir_node *node) {
+ int arity, i;
/* count all phi nodes */
- curr_vals[I_PHI_CNT]++;
+ curr_vals[I_PHIS]++;
/* argument count */
- count = get_irn_arity(node);
- if (count > ARG_CNT_MAX)
- curr_vals[I_ARG_CNT_E]++;
+ arity = get_irn_arity(node);
+ curr_vals[I_ARG] += arity;
+ if (arity > MAX_ARITY)
+ curr_vals[I_ARITY_E]++;
else
- curr_vals[I_ARG_CNT_S + count]++;
+ curr_vals[I_ARITY_S + arity]++;
- /* type of argument */
- for (i = 0; i < count; i++) {
+ /* type of argument {const, pred, glob} */
+ for (i = 0; i < arity; i++) {
ir_node *block_of_arg, *block_ith_pred;
ir_node *arg = get_irn_n(node, i);
curr_vals[I_GLOB]++;
}
+}
- size = get_phi_class_size(node);
+/**
+ * Collect phi class data
+ */
+static void phi_class_stat(pset *pc) {
+ int i, o, size, doit, sth_interfered;
+ ir_node **members, *p;
+
/* phi class count */
- if (size > 0)
- curr_vals[I_PHICLSCNT]++;
+ curr_vals[I_PHICLS]++;
/* phi class size */
- if (size > PHI_CLS_MAX)
- curr_vals[I_PHI_CLS_E]++;
+ size = pset_count(pc);
+ if (size > MAX_CLS_SIZE)
+ curr_vals[I_CLS_SIZE_E]++;
else
- curr_vals[I_PHI_CLS_S + size]++;
+ curr_vals[I_CLS_SIZE_S + size]++;
+
+ /* get an array of all members for double iterating */
+ members = (ir_node **) malloc(size * sizeof(ir_node*));
+ for (i=0, p = (ir_node *)pset_first(pc); p; p = (ir_node *)pset_next(pc))
+ members[i++] = p;
+ assert(i == size);
+
+ /* determine interference of phi class members */
+ curr_vals[I_VALUES] += size;
+ sth_interfered = 0;
+ for (i = 0; i < size-1; ++i) {
+ doit = 1;
+ for (o = i+1; o < size; ++o) {
+ curr_vals[I_PAIRS]++;
+ if (phi_ops_interfere(members[i], members[o])) {
+ sth_interfered = 1;
+ curr_vals[I_PAIRSI]++;
+ if (doit) {
+ curr_vals[I_VALUESI]++;
+ doit = 0;
+ }
+ }
+ }
+ }
+
+ /* Does this phi class have an inner interference? */
+ curr_vals[I_PHICLSI] += sth_interfered;
- /* count of interfering pairs / values */
- curr_vals[I_INTERFP] += get_irn_phi_info(node)->interf_pairs;
- curr_vals[I_INTERFV] += get_irn_phi_info(node)->interf_vals;
- if (get_irn_phi_info(node)->interf_vals > 0)
- curr_vals[I_INTERFPHI]++;
+ free(members);
}
/**
- * Dump values and some annotations for current irp
+ * Collect all stat data
*/
-static void dump_files(void) {
- int i, sum1, sum2, sum3, next;
- FILE *out;
- char buf[200];
+void phi_stat_collect(ir_graph *irg, pset *all_phi_nodes, pset *all_phi_classes) {
+ ir_node *n;
+ pset *pc;
- sum1 = curr_vals[I_CONST] + curr_vals[I_PRED] + curr_vals[I_GLOB];
- sum2 = 0;
- for (i = I_ARG_CNT_S; i<=I_ARG_CNT_E; i++)
- sum2 += curr_vals[i];
- sum3 = 0;
- for (i = I_PHI_CLS_S; i<=I_PHI_CLS_E; i++)
- sum3 += curr_vals[i];
+ irg_walk_graph(irg, stat_walker, NULL, NULL);
+ curr_vals[I_BLOCKS] -= 2;
- next = sprintf(buf, get_irp_prog_name());
- sprintf(buf+next, ".phi.stat");
- out = fopen(buf, "wt");
+ for (n = (ir_node *)pset_first(all_phi_nodes); n; n = (ir_node *)pset_next(all_phi_nodes))
+ phi_node_stat(n);
- fprintf(out, "Phis %i\n", curr_vals[I_PHI_CNT]);
- fprintf(out, "Blks %i\n", curr_vals[I_BLK_CNT]);
+ for (pc = (pset *)pset_first(all_phi_classes); pc; pc = (pset *)pset_next(all_phi_classes))
+ phi_class_stat(pc);
+}
- fprintf(out, "\nArgument counts\n");
- for (i = I_ARG_CNT_S; i<=I_ARG_CNT_E; i++)
- fprintf(out, "%2i %2.4f\n", i-I_ARG_CNT_S, (double) curr_vals[i] / sum2);
- fprintf(out, "\nPhi class sizes\n");
- for (i = I_PHI_CLS_S; i<=I_PHI_CLS_E; i++)
- fprintf(out, "%2i %2.4f\n", i-I_PHI_CLS_S, (double) curr_vals[i] / sum3);
-
- fprintf(out, "\n");
- fprintf(out, "Interf Pairs %d\n", curr_vals[I_INTERFP]);
- fprintf(out, "Interf Values %d\n", curr_vals[I_INTERFV]);
- fprintf(out, "PhiCls Count %d\n", curr_vals[I_PHICLSCNT]);
- fprintf(out, "Interf PhisCl %d\n", curr_vals[I_INTERFPHI]);
- fprintf(out, "Const %2.2f\n", (double) curr_vals[I_CONST] / sum1);
- fprintf(out, "Pred %2.2f\n", (double) curr_vals[I_PRED] / sum1);
- fprintf(out, "Glob %2.2f\n", (double) curr_vals[I_GLOB] / sum1);
+/**
+ * Dump statistic values in raw format
+ */
+static void dump_file(char *filename, int stat[ASIZE]) {
+ FILE *file;
+ int i;
- fclose(out);
+ if (! (file = fopen(filename, "wt"))) {
+ fprintf(stderr, "Cannot open file for writing: %s\n", filename);
+ return;
+ }
+
+ for (i = 0; i < ASIZE; i++) {
+ if (i >= I_ARITY_S && i <= I_ARITY_E)
+ fprintf(file, "%i %i\n", stat[i], stat[I_PHIS]);
+ else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
+ fprintf(file, "%i %i\n", stat[i], stat[I_PHICLS]);
+ else
+ fprintf(file, "%i\n", stat[i]);
+ }
+
+ fclose(file);
}
/**
- * Updates the summary file with cumulated values
+ * Updates a cumulative file with the current values.
*/
-static void update_all_file(void) {
+void phi_stat_update(char *filename) {
int i;
FILE *all;
int vals[ASIZE];
+ if (!filename)
+ return;
+
/* read in */
- all = fopen(SUMMARY_FILE_NAME, "rt");
+ all = fopen(filename, "rt");
+
if (all) {
- for (i = 0; i<ASIZE; i++)
- fscanf(all, "%i\n", &vals[i]);
+ for (i = 0; i < ASIZE; i++) {
+ if (i >= I_ARITY_S && i <= I_ARITY_E)
+ fscanf(all, "%i %i\n", &vals[i], &vals[I_PHIS]);
+ else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
+ fscanf(all, "%i %i\n", &vals[i], &vals[I_PHICLS]);
+ else
+ fscanf(all, "%i\n", &vals[i]);
+ }
fclose(all);
} else {
- for (i = 0; i<ASIZE; i++)
+ for (i = 0; i < ASIZE; i++)
vals[i] = 0;
}
+ /* add current values */
+ for (i = 0; i < ASIZE; i++)
+ vals[i] += curr_vals[i];
+
/* write out */
- all = fopen(SUMMARY_FILE_NAME, "wt");
- for (i = 0; i<ASIZE; i++)
- fprintf(all, "%i\n", vals[i]+curr_vals[i]);
- fclose(all);
+ dump_file(filename, vals);
}
-void do_phi_statistics(void) {
- int i, n;
- curr_vals[I_SPACE1] = -1;
- curr_vals[I_SPACE2] = -1;
- curr_vals[I_SPACE3] = -1;
- for (i = 0, n = get_irp_n_irgs(); i < n; i++) {
- ir_graph *irg = get_irp_irg(i);
- irg_walk_graph(irg, phi_stat_walker, NULL, NULL);
- curr_vals[I_BLK_CNT] -= 2;
+/**
+ * Dumps the current contents of the values array to a file.
+ * Updates a cumulative file.
+ */
+void phi_stat_dump(char *filename) {
+ if (filename)
+ dump_file(filename, curr_vals);
+}
+
+
+/**
+ * Dumps the current contents of the values array
+ * and annotations to a file.
+ */
+void phi_stat_dump_pretty(char *filename) {
+ int i;
+ FILE *out;
+
+ if (! (out = fopen(filename, "wt"))) {
+ fprintf(stderr, "Cannot open file for writing: %s\n", filename);
+ return;
}
- dump_files();
- update_all_file();
+ fprintf(out, "\nPhi argument types\n");
+ fprintf(out, "Total %4d\n", curr_vals[I_ARG]);
+ fprintf(out, "Constants %4d\n", curr_vals[I_CONST]);
+ fprintf(out, "CF-Pred %4d\n", curr_vals[I_PRED]);
+ fprintf(out, "Others %4d\n", curr_vals[I_GLOB]);
+
+ fprintf(out, "\nPhi class interference\n");
+ fprintf(out, "Blocks %4d\n", curr_vals[I_BLOCKS]);
+ fprintf(out, "Phis %4d\n", curr_vals[I_PHIS]);
+ fprintf(out, "Interf classes %4d of %4d\n", curr_vals[I_PHICLSI], curr_vals[I_PHICLS]);
+ fprintf(out, "Interf pairs %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_PAIRS]);
+ fprintf(out, "Interf values %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_VALUES]);
+
+ fprintf(out, "\nPhi arity\n");
+ for (i = I_ARITY_S; i<=I_ARITY_E; i++)
+ fprintf(out, "%2i %4d\n", i-I_ARITY_S, curr_vals[i]);
+
+ fprintf(out, "\nPhi class sizes\n");
+ for (i = I_CLS_SIZE_S; i<=I_CLS_SIZE_E; i++)
+ fprintf(out, "%2i %4d\n", i-I_CLS_SIZE_S, curr_vals[i]);
+
+ fprintf(out, "\n\nTotal nodes: %4d\n", curr_vals[I_ALL_NODES]);
+
+ fclose(out);
}