From 1580176436dd0df7f1a0b608aef904d5f6d24e5a Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Fri, 25 Jun 2004 09:03:50 +0000 Subject: [PATCH] Added pattern_dmp to separate the pattern dumper [r3209] --- ir/stat/Makefile.in | 2 +- ir/stat/pattern.c | 185 ++++++++++++++++++++++++++++++++---------- ir/stat/pattern.h | 6 ++ ir/stat/pattern_dmp.c | 183 +++++++++++++++++++++++++++++++++++++++++ ir/stat/pattern_dmp.h | 46 +++++++++++ 5 files changed, 377 insertions(+), 45 deletions(-) create mode 100644 ir/stat/pattern_dmp.c create mode 100644 ir/stat/pattern_dmp.h diff --git a/ir/stat/Makefile.in b/ir/stat/Makefile.in index 7589589d1..e4fff055c 100644 --- a/ir/stat/Makefile.in +++ b/ir/stat/Makefile.in @@ -25,7 +25,7 @@ SOURCES += Makefile.in \ firmstat.c ifeq ($(enable_statistics),yes) -SOURCES += pattern.c pattern.h counter.h +SOURCES += pattern.c pattern.h counter.h pattern_dmp.c pattern_dmp.h endif diff --git a/ir/stat/pattern.c b/ir/stat/pattern.c index f95b025bb..9a27807f1 100644 --- a/ir/stat/pattern.c +++ b/ir/stat/pattern.c @@ -7,9 +7,11 @@ #include "ident.h" #include "irnode_t.h" #include "irgwalk.h" +#include "irprog.h" +#include "set.h" #include "pset.h" #include "counter.h" -#include "irprog.h" +#include "pattern_dmp.h" /* * just be make some things clear :-), the @@ -63,6 +65,7 @@ typedef struct _pattern_entry_t { */ enum options_t { OPT_WITH_MODE = 0x00000001, /**< use modes */ + OPT_ENC_GRAPH = 0x00000002, /**< encode graphs, not terms */ }; @@ -274,11 +277,47 @@ static BYTE next_tag(CODE_BUFFER *buf) return 0; } +/** + * environment for the pattern encoder + */ +typedef struct _codec_enc_t { + CODE_BUFFER *buf; /**< the code buffer */ + set *id_set; /**< the set containing all already seen nodes */ + unsigned curr_id; /**< current node id */ + unsigned options; /**< encoding options */ + pattern_dumper_t *dmp; /**< dumper for the decoder */ +} codec_env_t; + +typedef struct _addr_entry_t { + void *addr; /**< the address */ + unsigned id; /**< associated ID */ +} addr_entry_t; + +/** + * hash value of an address + */ +static INLINE unsigned addr_hash(void *addr) +{ + return ((unsigned)addr) >> 3; +} + +/** + * compare two addresses + */ +static int addr_cmp(const void *p1, const void *p2, size_t size) { + const addr_entry_t *e1 = p1; + const addr_entry_t *e2 = p2; + + return e1->addr != e2->addr; +} + /* * encodes an IR-node, recursive worker */ -static void _encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth) +static void _encode_node(ir_node *node, int max_depth, codec_env_t *env) { + addr_entry_t entry, *r_entry; + set_entry *s_entry; int i, preds; #if 0 @@ -287,31 +326,50 @@ static void _encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth) ir_op *code = get_irn_op(node); #endif - put_code(buf, (unsigned)code); + /* insert the node into our ID map */ + entry.addr = node; + entry.id = env->curr_id; + + s_entry = set_hinsert(env->id_set, &entry, sizeof(entry), addr_hash(node)); + r_entry = (addr_entry_t *)s_entry->dptr; + + if (r_entry->id != env->curr_id) { + /* already in the map, add an REF */ + put_tag(env->buf, VLC_TAG_REF); + put_code(env->buf, r_entry->id); + + return; + } + else { + /* a new entry, proceed */ + ++env->curr_id; + } - if (status->options & OPT_WITH_MODE) { + put_code(env->buf, (unsigned)code); + + if (env->options & OPT_WITH_MODE) { ir_mode *mode = get_irn_mode(node); if (mode) - put_code(buf, (unsigned)mode); + put_code(env->buf, (unsigned)mode); else - put_tag(buf, VLC_TAG_EMPTY); + put_tag(env->buf, VLC_TAG_EMPTY); } --max_depth; if (max_depth <= 0) { - put_code(buf, 0); + put_code(env->buf, 0); return; } preds = get_irn_arity(node); - put_code(buf, preds); + put_code(env->buf, preds); for (i = 0; i < preds; ++i) { ir_node *n = get_irn_n(node, i); - _encode_node(n, buf, max_depth); + _encode_node(n, max_depth, env); } } @@ -320,47 +378,86 @@ static void _encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth) */ static void encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth) { - put_tag(buf, VLC_TAG_OPTION); - put_code(buf, status->options); - _encode_node(node, buf, max_depth); -} + codec_env_t env; + + env.buf = buf; + env.curr_id = 1; /* 0 is used for special purpose */ + env.options = status->options; + env.dmp = NULL; + + if (env.options & OPT_ENC_GRAPH) + env.id_set = new_set(addr_cmp, 32); + else + env.id_set = NULL; + + /* encode options if any */ + if (env.options) { + put_tag(buf, VLC_TAG_OPTION); + put_code(buf, env.options); + } + _encode_node(node, max_depth, &env); + + if (env.options & OPT_ENC_GRAPH) + del_set(env.id_set); +} /** * decode an IR-node, recursive walker */ -static void _decode_node(CODE_BUFFER *buf, unsigned options) +static void _decode_node(unsigned parent, int position, codec_env_t *env) { - unsigned op_code = get_code(buf); - unsigned code = next_tag(buf); - ir_op *op = (ir_op *)op_code; - - /* output the opcode-name */ - printf("%s", get_id_str(op->name)); - - if (options & OPT_WITH_MODE) { - if (next_tag(buf) != VLC_TAG_EMPTY) { - unsigned mode_code = get_code(buf); - ir_mode *mode = (ir_mode *)mode_code; - printf("%s", get_mode_name(mode)); + unsigned code; + unsigned op_code; + unsigned mode_code = 0; + + code = next_tag(env->buf); + if (code == VLC_TAG_REF) { /* it's a REF */ + code = get_code(env->buf); + + /* dump the edge */ + if (parent) + pattern_dump_edge(env->dmp, code, parent, position); + + /* dump the node ref */ + pattern_dump_ref(env->dmp, code); + + return; + } + + /* get the opcode */ + op_code = get_code(env->buf); + + /* get the mode if encoded */ + if (env->options & OPT_WITH_MODE) { + if (next_tag(env->buf) != VLC_TAG_EMPTY) { + mode_code = get_code(env->buf); } } - /* enter it into the ID table */ + /* dump the edge */ + if (parent) + pattern_dump_edge(env->dmp, env->curr_id, parent, position); + + /* dump the node */ + parent = env->curr_id; + pattern_dump_node(env->dmp, parent, op_code, mode_code); + /* ok, we have a new ID */ + ++env->curr_id; + + code = next_tag(env->buf); if (code != VLC_TAG_END) { /* more info, do recursion */ int i, preds; - preds = get_code(buf); + preds = get_code(env->buf); if (preds > 0) { - printf("("); + pattern_start_children(env->dmp, parent); for (i = 0; i < preds; ++i) { - if (i > 0) - printf(", "); - _decode_node(buf, options); + _decode_node(parent, i, env); } - printf(")"); + pattern_finish_children(env->dmp, parent); } } } @@ -370,16 +467,24 @@ static void _decode_node(CODE_BUFFER *buf, unsigned options) */ static void decode_node(BYTE *b, unsigned len) { + codec_env_t env; CODE_BUFFER buf; unsigned code, options = 0; init_buf(&buf, b, len); + env.buf = &buf; + env.curr_id = 1; /* 0 is used for special purpose */ + env.dmp = &stdout_dump; + + /* decode options */ code = next_tag(&buf); if (code == VLC_TAG_OPTION) { options = get_code(&buf); } - _decode_node(&buf, options); + env.options = options; + + _decode_node(0, 0, &env); } /** @@ -389,14 +494,6 @@ typedef struct _pattern_env { int max_depth; /**< maximum depth for pattern generation */ } pattern_env_t; -/** - * calculate a hash value for a pattern - */ -static unsigned pattern_hash(pattern_entry_t *key) -{ - return 9 * key->buf[0] + 31 * key->buf[key->len - 1] + 7 * key->buf[key->len >> 1]; -} - /** * Returns the associates pattern_entry_t for a CODE_BUF */ @@ -412,7 +509,7 @@ static pattern_entry_t *pattern_get_entry(CODE_BUFFER *buf, pset *set) key->len = len; memcpy(key->buf, buf_content(buf), len); - hash = buf_hash(buf); // pattern_hash(key); + hash = buf_hash(buf); elem = pset_find(set, key, hash); if (elem) { @@ -508,7 +605,7 @@ void stat_init_pattern_history(int enable) return; status->bound = 3; - status->options = OPT_WITH_MODE; + status->options = OPT_WITH_MODE | OPT_ENC_GRAPH; obstack_init(&status->obst); diff --git a/ir/stat/pattern.h b/ir/stat/pattern.h index c775e9771..6237606ed 100644 --- a/ir/stat/pattern.h +++ b/ir/stat/pattern.h @@ -11,6 +11,12 @@ #ifndef _PATTERN_H_ #define _PATTERN_H_ +/** + * @file pattern.h + * + * Statistics for libFirm, pattern history. + */ + /** * calculates the pattern history. * diff --git a/ir/stat/pattern_dmp.c b/ir/stat/pattern_dmp.c new file mode 100644 index 000000000..ae6badc43 --- /dev/null +++ b/ir/stat/pattern_dmp.c @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "ident.h" +#include "irop_t.h" +#include "irmode.h" +#include "pattern_dmp.h" + +/** + * starts a new VCG graph + */ +static void vcg_dump_start(pattern_dumper_t *self) +{ + FILE *f; + + 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" + ); +} + +/** + * ends a new VCG graph + */ +static void vcg_dump_end(pattern_dumper_t *self) +{ + fprintf(f, "}\n"); + fclose(f); +} + +static void vcg_dump_node(pattern_dumper_t *self, unsigned id, + unsigned op_code, unsigned mode_code) +{ + 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); +} + +static void vcg_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position) +{ + fprintf(f, " edge: { sourcename: \"n%u\" targetname: \"n78\"}\n", parent, id); +} + +/** + * The VCG dumper. + */ +pattern_dumper_t vcg_dump = { + vcg_dump_node, + NULL, + vcg_dump_edge, + NULL, + NULL, +}; + +/** + * Dumps a node + */ +static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code) +{ + ir_op *op = (ir_op *)op_code; + ir_mode *mode = (ir_mode *)mode_code; + + /* if (env->options & OPT_ENC_GRAPH) */ + printf("%u:", id); + + printf("%s", get_id_str(op->name)); + + if (mode) + printf("%s", get_mode_name(mode)); +} + +/** + * Dump a ref + */ +static void stdout_dump_ref(pattern_dumper_t *self, unsigned id) +{ + printf("REF:%u", id); +} + +/** + * Dump an edge + */ +static void stdout_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position) +{ + if (position > 0) + printf(", "); +} + +/** + * Start children dumper + */ +static void stdout_start_children(pattern_dumper_t *self, unsigned id) +{ + printf("("); +} + +/** + * finishes childred dumper + */ +static void stdout_finish_children(pattern_dumper_t *self, unsigned id) +{ + printf(")"); +} + +/** + * The stdout dumper. + */ +pattern_dumper_t stdout_dump = { + stdout_dump_node, + stdout_dump_ref, + stdout_dump_edge, + stdout_start_children, + stdout_finish_children, +}; + +/* ------------------------------------ API ------------------------------------- */ + +/* + * Dumps a node + */ +void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code) +{ + if (self->dump_node) + self->dump_node(self, id, op_code, mode_code); +} + +/* + * Dump a ref + */ +void pattern_dump_ref(pattern_dumper_t *self, unsigned id) +{ + if (self->dump_ref) + self->dump_ref(self, id); +} + +/* + * Dump an edge + */ +void pattern_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position) +{ + if (self->dump_edge) + self->dump_edge(self, id, parent, position); +} + +/* + * Start children dumper + */ +void pattern_start_children(pattern_dumper_t *self, unsigned id) +{ + if (self->dump_start_children) + self->dump_start_children(self, id); +} + +/* + * finishes childred dumper + */ +void pattern_finish_children(pattern_dumper_t *self, unsigned id) +{ + if (self->dump_finish_children) + self->dump_finish_children(self, id); +} diff --git a/ir/stat/pattern_dmp.h b/ir/stat/pattern_dmp.h new file mode 100644 index 000000000..116128b48 --- /dev/null +++ b/ir/stat/pattern_dmp.h @@ -0,0 +1,46 @@ +#ifndef _PATTERN_DMP_H_ +#define _PATTERN_DMP_H_ + +typedef struct _pattern_dumper_t pattern_dumper_t; +typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code); +typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id); +typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position); +typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id); +typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id); + +struct _pattern_dumper_t { + 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; +}; + +extern pattern_dumper_t vcg_dump, stdout_dump; + +/** + * Dumps a node + */ +void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code); + +/** + * Dump a ref + */ +void pattern_dump_ref(pattern_dumper_t *self, unsigned id); + +/** + * Dump an edge + */ +void pattern_dump_edge(pattern_dumper_t *self, unsigned id, unsigned parent, unsigned position); + +/** + * Start children dumper + */ +void pattern_start_children(pattern_dumper_t *self, unsigned id); + +/** + * finishes childred dumper + */ +void pattern_finish_children(pattern_dumper_t *self, unsigned id); + +#endif /* _PATTERN_DMP_H_ */ -- 2.20.1