bepeephole: Inline be_peephole_new_node() into its only caller.
[libfirm] / ir / stat / pattern_dmp.c
index cc23cb1..32394b1 100644 (file)
 /*
- * Project:     libFIRM
- * File name:   ir/ir/pattern_dmp.c
- * Purpose:     Statistics for Firm.
- * Author:      Michael Beck
- * Created:
- * CVS-ID:      $Id$
- * Copyright:   (c) 2004 Universität Karlsruhe
- * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * This file is part of libFirm.
+ * Copyright (C) 2012 University of Karlsruhe.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+/**
+ * @file
+ * @brief   Statistics for Firm. Dumping patterns.
+ * @author  Michael Beck
+ */
+#include "config.h"
 
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "ident.h"
 #include "irop_t.h"
 #include "irmode.h"
+#include "firmstat_t.h"
 #include "pattern_dmp.h"
 
-FILE *f;
+/* dumper operations */
+typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
+typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
+typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
+typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
+typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
+typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
+typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
+
+/**
+ * the pattern dumper
+ */
+struct pattern_dumper_t {
+       DUMP_NEW_PATTERN_FUNC      dump_new_pattern;
+       DUMP_FINISH_PATTERN_FUNC   dump_finish_pattern;
+       DUMP_NODE_FUNC             dump_node;
+       DUMP_REF_FUNC              dump_ref;
+       DUMP_EDGE_FUNC             dump_edge;
+       DUMP_START_CHILDREN_FUNC   dump_start_children;
+       DUMP_FINISH_CHILDREN_FUNC  dump_finish_children;
+       DUMP_START_FUNC            dump_start;
+       DUMP_END_FUNC              dump_end;
+       void                       *data;
+};
 
 /**
- * starts a new VCG graph
+ * VCG private data
+ */
+typedef struct vcg_private_t {
+       FILE     *f;          /**< file to dump to */
+       unsigned pattern_id;  /**< ID of the pattern */
+       unsigned max_pattern; /**< maximum number of pattern to be dumped */
+} vcg_private_t;
+
+/**
+ * Starts a new VCG graph.
  */
 static void vcg_dump_start(pattern_dumper_t *self)
 {
-  f = fopen("firmpattern.vcg", "w");
-
-  fprintf(f,
-    "graph: { title: \"Most found pattern\"\n"
-    "  display_edge_labels: no\n"
-    "  layoutalgorithm: mindepth\n"
-    "  manhattan_edges: yes\n"
-    "  port_sharing: no\n"
-    "  orientation: bottom_to_top\n"
-  );
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+
+       fprintf(priv->f,
+               "graph: { title: \"Most found pattern\"\n"
+               "  display_edge_labels: no\n"
+               "  layoutalgorithm: mindepth\n"
+               "  manhattan_edges: yes\n"
+               "  port_sharing: no\n"
+               "  orientation: bottom_to_top\n"
+               );
 }
 
 /**
- * ends a new VCG graph
+ * Ends a new VCG graph.
  */
 static void vcg_dump_end(pattern_dumper_t *self)
 {
-  fprintf(f, "}\n");
-  fclose(f);
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+
+       fprintf(priv->f, "}\n");
+       fclose(priv->f);
 }
 
-/*
- * starts a new pattern
+/**
+ * Starts a new pattern.
  */
 static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
 {
-  fprintf(f,
-    "  graph: { title: \"pattern cnt %u\"\n", cnt->cnt[0]
-  );
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+       static unsigned nr = 0;
+
+       if (priv->pattern_id > priv->max_pattern)
+               return;
+
+       fprintf(priv->f,
+               "  graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
+               priv->pattern_id, priv->pattern_id );
 
+       /* add a pseudo node for the count of this pattern */
+       fprintf(priv->f,
+               "    node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
+               ++nr, cnt_to_uint(cnt)
+       );
 }
 
 /**
- * Finishes current pattern
+ * Finish the current pattern.
  */
 static void vcg_dump_finish_pattern(pattern_dumper_t *self)
 {
-  fprintf(f, "  }\n");
-}
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+
+       if (priv->pattern_id > priv->max_pattern)
+               return;
+
+       fprintf(priv->f, "  }\n");
+
+       if (priv->pattern_id > 0)
+               fprintf(priv->f, "  edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
+                       priv->pattern_id,
+                       priv->pattern_id - 1);
 
+       ++priv->pattern_id;
+}
 
+/**
+ * Dumps a node.
+ */
 static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
-    unsigned op_code, unsigned mode_code)
+    unsigned op_code, unsigned mode_code, void *attr)
 {
-  ir_op *op     = (ir_op *)op_code;
-  ir_mode *mode = (ir_mode *)mode_code;
-
-  fprintf(f, "    node: {title: \"n%u\" label: \"%s%s n%u\" }\n",
-    id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+       ir_op *op           = stat_get_op_from_opcode(op_code);
+       ir_mode *mode       = ir_get_mode(mode_code);
+       long l              = attr ? *(long *)attr : 0;
+
+       if (priv->pattern_id > priv->max_pattern)
+               return;
+
+       if (attr) {
+               fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
+                       priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
+       } else {
+               fprintf(priv->f, "    node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
+                       priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
+       }
 }
 
-static void vcg_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position)
+/**
+ * Dumps an edge.
+ */
+static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
 {
-  fprintf(f, "    edge: { sourcename: \"n%u\" targetname: \"n%u\"}\n", parent, id);
+       vcg_private_t *priv = (vcg_private_t*)self->data;
+       (void) mode_code;
+
+       if (priv->pattern_id > priv->max_pattern)
+               return;
+
+       fprintf(priv->f, "    edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
+               priv->pattern_id, src,
+               priv->pattern_id, tgt,
+               pos
+       );
 }
 
 /**
  * The VCG dumper.
  */
-pattern_dumper_t vcg_dump = {
-  vcg_dump_new_pattern,
-  vcg_dump_finish_pattern,
-  vcg_dump_node,
-  NULL,
-  vcg_dump_edge,
-  NULL,
-  NULL,
+static pattern_dumper_t vcg_dump = {
+       vcg_dump_new_pattern,
+       vcg_dump_finish_pattern,
+       vcg_dump_node,
+       NULL,
+       vcg_dump_edge,
+       NULL,
+       NULL,
+       vcg_dump_start,
+       vcg_dump_end,
+       NULL
 };
 
 /**
- * starts a new pattern
+ * Starts a new pattern.
  */
 static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
 {
-  printf("%8u ", cnt->cnt[0]);
+       FILE *f = (FILE*)self->data;
+
+       fprintf(f, "%8u ", cnt_to_uint(cnt));
 }
 
 
-/*
- * Finishes current pattern
+/**
+ * Finish the current pattern.
  */
 static void stdout_dump_finish_pattern(pattern_dumper_t *self)
 {
-  printf("\n");
+       FILE *f = (FILE*)self->data;
+
+       fprintf(f, "\n");
 }
 
 /**
- * Dumps a node
+ * Dumps a node.
  */
-static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code)
+static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
 {
-  ir_op *op     = (ir_op *)op_code;
-  ir_mode *mode = (ir_mode *)mode_code;
+       FILE *f       = (FILE*)self->data;
+       ir_op *op     = stat_get_op_from_opcode(op_code);
+       ir_mode *mode = ir_get_mode(mode_code);
+       (void) attr;
 
-  /* if (env->options & OPT_ENC_GRAPH) */
-    printf("%u:", id);
+       /* if (env->options & OPT_ENC_GRAPH) */
+       fprintf(f, "%u:", id);
 
-  printf("%s", get_id_str(op->name));
+       fprintf(f, "%s", get_id_str(op->name));
 
-  if (mode)
-    printf("%s", get_mode_name(mode));
+       if (mode)
+               fprintf(f, "%s", get_mode_name(mode));
 }
 
 /**
@@ -135,110 +227,182 @@ static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_co
  */
 static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
 {
-  printf("REF:%u", id);
+       FILE *f = (FILE*)self->data;
+
+       fprintf(f, "REF:%u", id);
 }
 
 /**
- * Dump an edge
+ * Dump an edge.
  */
-static void stdout_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position)
+static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
 {
-  if (position > 0)
-    printf(", ");
+       FILE *f = (FILE*)self->data;
+       (void) tgt;
+       (void) src;
+       (void) pos;
+       (void) mode_code;
+
+       if (pos > 0)
+               fprintf(f, ", ");
 }
 
 /**
- * Start children dumper
+ * Start the children dumper.
  */
 static void stdout_start_children(pattern_dumper_t *self, unsigned id)
 {
-  printf("(");
+       FILE *f = (FILE*)self->data;
+       (void) id;
+
+       fprintf(f, "(");
 }
 
 /**
- * finishes childred  dumper
+ * Finish the children dumper.
  */
 static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
 {
-  printf(")");
+       FILE *f = (FILE*)self->data;
+       (void) id;
+
+       fprintf(f, ")");
 }
 
 /**
  * The stdout dumper.
  */
-pattern_dumper_t stdout_dump = {
-  stdout_dump_new_pattern,
-  stdout_dump_finish_pattern,
-  stdout_dump_node,
-  stdout_dump_ref,
-  stdout_dump_edge,
-  stdout_start_children,
-  stdout_finish_children,
+static const pattern_dumper_t stdout_dump = {
+       stdout_dump_new_pattern,
+       stdout_dump_finish_pattern,
+       stdout_dump_node,
+       stdout_dump_ref,
+       stdout_dump_edge,
+       stdout_start_children,
+       stdout_finish_children,
+       NULL,
+       NULL,
+       NULL
 };
 
 /* ------------------------------------ API ------------------------------------- */
 
 /*
- * starts a new pattern
+ * Starts a new pattern.
  */
 void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
 {
-  if (self->dump_new_pattern)
-    self->dump_new_pattern(self, cnt);
+       if (self->dump_new_pattern)
+               self->dump_new_pattern(self, cnt);
 }
 
 
 /*
- * Finishes current pattern
+ * Finish the current pattern.
  */
 void pattern_dump_finish_pattern(pattern_dumper_t *self)
 {
-  if (self->dump_finish_pattern)
-    self->dump_finish_pattern(self);
+       if (self->dump_finish_pattern)
+               self->dump_finish_pattern(self);
 }
 
 
 /*
- * Dumps a node
+ * Dumps a node.
  */
-void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code)
+void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
 {
-  if (self->dump_node)
-    self->dump_node(self, id, op_code, mode_code);
+       if (self->dump_node)
+               self->dump_node(self, id, op_code, mode_code, attr);
 }
 
 /*
- * Dump a ref
+ * Dump a ref.
  */
 void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
 {
-  if (self->dump_ref)
-    self->dump_ref(self, id);
+       if (self->dump_ref)
+               self->dump_ref(self, id);
 }
 
 /*
- * Dump an edge
+ * Dump an edge.
  */
-void pattern_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position)
+void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
 {
-  if (self->dump_edge)
-    self->dump_edge(self, id, parent, position);
+       if (self->dump_edge)
+               self->dump_edge(self, tgt, src, pos, mode_code);
 }
 
 /*
- * Start children dumper
+ * Start the children dumper.
  */
 void pattern_start_children(pattern_dumper_t *self, unsigned id)
 {
-  if (self->dump_start_children)
-    self->dump_start_children(self, id);
+       if (self->dump_start_children)
+               self->dump_start_children(self, id);
 }
 
 /*
- * finishes childred dumper
+ * Finish the the children dumper.
  */
 void pattern_finish_children(pattern_dumper_t *self, unsigned id)
 {
-  if (self->dump_finish_children)
-    self->dump_finish_children(self, id);
+       if (self->dump_finish_children)
+               self->dump_finish_children(self, id);
+}
+
+/*
+ * Finish the the dumper.
+ */
+void pattern_end(pattern_dumper_t *self)
+{
+       if (self->dump_end)
+               self->dump_end(self);
+
+       free(self);
+}
+
+/**
+ * pattern dumper factory for text dumper
+ */
+pattern_dumper_t *new_text_dumper(void)
+{
+       pattern_dumper_t *res = XMALLOC(pattern_dumper_t);
+
+       *res = stdout_dump;
+       res->data = stdout;
+
+       if (res->dump_start)
+               res->dump_start(res);
+       return res;
+}
+
+/**
+ * pattern dumper factory for vcg dumper
+ */
+pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
+{
+       pattern_dumper_t *res = (pattern_dumper_t*)malloc(sizeof(*res) + sizeof(vcg_private_t));
+       vcg_private_t *priv;
+
+       if (res) {
+               FILE *f;
+
+               memcpy(res, &vcg_dump, sizeof(*res));
+
+               priv = (vcg_private_t *)(res + 1);
+               memset(priv, 0, sizeof(*priv));
+
+               f = fopen(vcg_name, "w");
+               priv->f           = f;
+               priv->pattern_id  = 0;
+               priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
+               res->data         = priv;
+
+               if (res->dump_start)
+                       res->dump_start(res);
+       }
+
+       return res;
 }