15 * just be make some things clear :-), the
18 #define HASH_MAP(type) pset_##type
20 typedef pset pset_pattern_entry_t;
22 typedef unsigned char BYTE;
28 typedef struct _code_buf_t {
29 BYTE *next; /**< next byte to be written */
30 BYTE *end; /**< end of the buffer */
31 BYTE *start; /**< start of the buffer */
32 unsigned hash; /**< calculates the hash value */
39 VLC_7BIT = 0x00, /**< 8 bit code, carrying 7 bits payload */
40 VLC_14BIT = 0x80, /**< 16 bit code, carrying 14 bits payload */
41 VLC_21BIT = 0xC0, /**< 24 bit code, carrying 21 bits payload */
42 VLC_28BIT = 0xE0, /**< 32 bit code, carrying 28 bits payload */
43 VLC_32BIT = 0xF0, /**< 40 bit code, carrying 32 bits payload */
45 VLC_TAG_FIRST = 0xF1, /**< first possible tag value */
46 VLC_TAG_EMPTY = 0xFC, /**< encodes an empty entity */
47 VLC_TAG_OPTION = 0xFD, /**< options exists */
48 VLC_TAG_REF = 0xFE, /**< special tag, next code is an ID */
49 VLC_TAG_END = 0xFF, /**< end tag */
53 * An entry for patterns
55 typedef struct _pattern_entry_t {
56 counter_t count; /**< amount of pattern occurance */
57 unsigned len; /**< lenght of the VLC encoded buffer */
58 BYTE buf[1]; /**< buffer contains the VLC encoded pattern */
65 OPT_WITH_MODE = 0x00000001, /**< use modes */
72 typedef struct _pattern_info_t {
73 int enable; /**< if non-zero, this module is enabled */
74 struct obstack obst; /**< obstack containing the counters */
75 HASH_MAP(pattern_entry_t) *pattern_hash; /**< hash map containing the counter for pattern */
76 unsigned bound; /**< lowest value for output */
77 unsigned options; /**< option mask */
83 static pattern_info_t _status, *status = &_status;
86 * compare two elemnts for counter
88 static int pattern_count_cmp(const void *elt, const void *key)
92 pattern_entry_t **e1 = (pattern_entry_t **)elt;
93 pattern_entry_t **e2 = (pattern_entry_t **)key;
95 cmp = cnt_cmp(&(*e1)->count, &(*e2)->count);
97 /* we want it sorted in descending order */
102 * compare two elements of the pattern hash
104 static int pattern_cmp(const void *elt, const void *key)
106 const pattern_entry_t *e1 = elt;
107 const pattern_entry_t *e2 = key;
108 int diff = e1->len - e2->len;
113 return memcmp(e1->buf, e2->buf, e1->len);
117 * initialise a code buffer
119 static void init_buf(CODE_BUFFER *buf, BYTE *data, unsigned len)
121 buf->start = buf->next = data;
122 buf->end = data + len;
127 * put a byte into the buffer
129 static INLINE void put_byte(CODE_BUFFER *buf, BYTE byte)
131 if (buf->next < buf->end) {
132 unsigned hash = buf->hash;
134 hash = (hash * 9) ^ byte;
141 * returns the current lenght of a buffer
143 static unsigned buf_lenght(const CODE_BUFFER *buf)
145 return buf->next - buf->start;
149 * returns the current lenght of a buffer
151 static const BYTE *buf_content(const CODE_BUFFER *buf)
157 * returns the hash value of a buffer
159 static unsigned buf_hash(const CODE_BUFFER *buf)
165 * returns the next byte from the buffer WITHOUT dropping
167 static INLINE BYTE look_byte(CODE_BUFFER *buf)
169 if (buf->next < buf->end)
175 * returns the next byte from the buffer WITH dropping
177 static INLINE BYTE get_byte(CODE_BUFFER *buf)
179 if (buf->next < buf->end)
184 #define BITS(n) (1 << (n))
187 * put a 32bit value into the buffer
189 static void put_code(CODE_BUFFER *buf, unsigned code)
191 if (code < BITS(7)) {
192 put_byte(buf, VLC_7BIT | code);
194 else if (code < BITS(6 + 8)) {
195 put_byte(buf, VLC_14BIT | (code >> 8));
198 else if (code < BITS(5 + 8 + 8)) {
199 put_byte(buf, VLC_21BIT | (code >> 16));
200 put_byte(buf, code >> 8);
203 else if (code < BITS(4 + 8 + 8 + 8)) {
204 put_byte(buf, VLC_28BIT | (code >> 24));
205 put_byte(buf, code >> 16);
206 put_byte(buf, code >> 8);
210 put_byte(buf, VLC_32BIT);
211 put_byte(buf, code >> 24);
212 put_byte(buf, code >> 16);
213 put_byte(buf, code >> 8);
218 #define BIT_MASK(n) ((1 << (n)) - 1)
221 * get 32 bit from the buffer
223 static unsigned get_code(CODE_BUFFER *buf)
225 unsigned code = get_byte(buf);
227 if (code < VLC_14BIT)
229 if (code < VLC_21BIT)
230 return ((code & BIT_MASK(6)) << 8) | get_byte(buf);
231 if (code < VLC_28BIT) {
232 code = ((code & BIT_MASK(5)) << 16) | (get_byte(buf) << 8);
233 code |= get_byte(buf);
236 if (code < VLC_32BIT) {
237 code = ((code & BIT_MASK(4)) << 24) | (get_byte(buf) << 16);
238 code |= get_byte(buf) << 8;
239 code |= get_byte(buf);
242 if (code == VLC_32BIT) {
243 code = get_byte(buf) << 24;
244 code |= get_byte(buf) << 16;
245 code |= get_byte(buf) << 8;
246 code |= get_byte(buf);
249 /* should not happen */
250 assert(0 && "Wrong code in buffer");
256 * put a tag into the buffer
258 static void put_tag(CODE_BUFFER *buf, BYTE tag)
260 assert(tag >= VLC_TAG_FIRST && "invalid tag");
266 * returns the next tag or zero if the next code isn't a tag
268 static BYTE next_tag(CODE_BUFFER *buf)
270 BYTE b = look_byte(buf);
272 if (b >= VLC_TAG_FIRST)
273 return get_byte(buf);
278 * encodes an IR-node, recursive worker
280 static void _encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth)
285 opcode code = get_irn_opcode(node);
287 ir_op *code = get_irn_op(node);
290 put_code(buf, (unsigned)code);
292 if (status->options & OPT_WITH_MODE) {
293 ir_mode *mode = get_irn_mode(node);
296 put_code(buf, (unsigned)mode);
298 put_tag(buf, VLC_TAG_EMPTY);
303 if (max_depth <= 0) {
308 preds = get_irn_arity(node);
309 put_code(buf, preds);
311 for (i = 0; i < preds; ++i) {
312 ir_node *n = get_irn_n(node, i);
314 _encode_node(n, buf, max_depth);
321 static void encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth)
323 put_tag(buf, VLC_TAG_OPTION);
324 put_code(buf, status->options);
325 _encode_node(node, buf, max_depth);
330 * decode an IR-node, recursive walker
332 static void _decode_node(CODE_BUFFER *buf, unsigned options)
334 unsigned op_code = get_code(buf);
335 unsigned code = next_tag(buf);
336 ir_op *op = (ir_op *)op_code;
338 /* output the opcode-name */
339 printf("%s", get_id_str(op->name));
341 if (options & OPT_WITH_MODE) {
342 if (next_tag(buf) != VLC_TAG_EMPTY) {
343 unsigned mode_code = get_code(buf);
344 ir_mode *mode = (ir_mode *)mode_code;
345 printf("%s", get_mode_name(mode));
349 /* enter it into the ID table */
351 if (code != VLC_TAG_END) {
352 /* more info, do recursion */
355 preds = get_code(buf);
358 for (i = 0; i < preds; ++i) {
361 _decode_node(buf, options);
371 static void decode_node(BYTE *b, unsigned len)
374 unsigned code, options = 0;
376 init_buf(&buf, b, len);
378 code = next_tag(&buf);
379 if (code == VLC_TAG_OPTION) {
380 options = get_code(&buf);
382 _decode_node(&buf, options);
386 * the environment for the pattern calculation
388 typedef struct _pattern_env {
389 int max_depth; /**< maximum depth for pattern generation */
393 * calculate a hash value for a pattern
395 static unsigned pattern_hash(pattern_entry_t *key)
397 return 9 * key->buf[0] + 31 * key->buf[key->len - 1] + 7 * key->buf[key->len >> 1];
401 * Returns the associates pattern_entry_t for a CODE_BUF
403 static pattern_entry_t *pattern_get_entry(CODE_BUFFER *buf, pset *set)
405 pattern_entry_t *key, *elem;
406 unsigned len = buf_lenght(buf);
409 key = obstack_alloc(&status->obst, sizeof(*key) + len - 1);
413 memcpy(key->buf, buf_content(buf), len);
415 hash = buf_hash(buf); // pattern_hash(key);
417 elem = pset_find(set, key, hash);
419 obstack_free(&status->obst, key);
423 cnt_clr(&key->count);
424 assert(key != (void *)4);
425 return pset_insert(set, key, hash);
429 * walker for nodes pattern calculation
431 static void calc_nodes_pattern(ir_node *node, void *ctx)
434 pattern_env_t *env = ctx;
436 pattern_entry_t *entry;
438 init_buf(&buf, buffer, sizeof(buffer));
439 encode_node(node, &buf, env->max_depth);
441 entry = pattern_get_entry(&buf, status->pattern_hash);
444 cnt_inc(&entry->count);
449 static void pattern_output(void)
451 pattern_entry_t *entry;
452 pattern_entry_t **pattern_arr;
453 int i, count = pset_count(status->pattern_hash);
455 printf("\n%d pattern detected\n", count);
460 pattern_arr = xmalloc(sizeof(*pattern_arr) * count);
461 for (i = 0, entry = pset_first(status->pattern_hash);
463 entry = pset_next(status->pattern_hash), ++i) {
464 pattern_arr[i] = entry;
470 qsort(pattern_arr, count, sizeof(*pattern_arr), pattern_count_cmp);
472 for (i = 0; i < count; ++i) {
473 entry = pattern_arr[i];
474 if (entry->count.cnt[0] < status->bound)
477 printf("%8d\t", entry->count.cnt[0]);
478 decode_node(entry->buf, entry->len);
484 * calculates the pattern history
486 void stat_calc_pattern_history(ir_graph *irg)
490 if (! status->enable)
493 /* do NOT count the const code IRG */
494 if (irg == get_const_code_irg())
498 irg_walk_graph(irg, calc_nodes_pattern, NULL, &env);
502 * initialises the pattern history
504 void stat_init_pattern_history(int enable)
506 status->enable = enable;
511 status->options = OPT_WITH_MODE;
513 obstack_init(&status->obst);
515 /* create the hash-table */
516 status->pattern_hash = new_pset(pattern_cmp, 8);
520 * finishes the pattern history
522 void stat_finish_pattern_history(void)
524 if (! status->enable)
529 del_pset(status->pattern_hash);
530 obstack_free(&status->obst, NULL);