Annotation of gforth/engine/peephole.c, revision 1.4
1.1 anton 1: /* Peephole optimization routines and tables
2:
3: Copyright (C) 2001 Free Software Foundation, Inc.
4:
5: This file is part of Gforth.
6:
7: Gforth is free software; you can redistribute it and/or
8: modify it under the terms of the GNU General Public License
9: as published by the Free Software Foundation; either version 2
10: of the License, or (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20: */
21:
22: #include "config.h"
23: #include "forth.h"
1.2 anton 24: #include <stdlib.h>
1.4 ! ak042 25: #include <string.h>
! 26: #include <assert.h>
1.1 anton 27:
28: /* the numbers in this struct are primitive indices */
29: typedef struct Combination {
30: int prefix;
31: int lastprim;
32: int combination_prim;
33: } Combination;
34:
35: Combination peephole_table[] = {
36: #include "peephole.i"
37: };
38:
1.3 anton 39: int use_super = 1;
40:
41: typedef Xt Inst;
1.1 anton 42:
1.3 anton 43: typedef struct Peeptable_entry {
44: struct Peeptable_entry *next;
45: Inst prefix;
46: Inst lastprim;
47: Inst combination_prim;
48: } Peeptable_entry;
1.1 anton 49:
1.3 anton 50: #define HASH_SIZE 1024
51: #define hash(_i1,_i2) (((((Cell)(_i1))^((Cell)(_i2)))>>4)&(HASH_SIZE-1))
1.1 anton 52:
1.3 anton 53: Cell peeptable;
1.1 anton 54:
1.3 anton 55: Cell prepare_peephole_table(Inst insts[])
1.1 anton 56: {
57: Cell i;
1.3 anton 58: Peeptable_entry **pt = (Peeptable_entry **)calloc(HASH_SIZE,sizeof(Peeptable_entry *));
1.1 anton 59:
1.3 anton 60: for (i=0; i<sizeof(peephole_table)/sizeof(peephole_table[0]); i++) {
1.1 anton 61: Combination *c = &peephole_table[i];
1.3 anton 62: Peeptable_entry *p = (Peeptable_entry *)malloc(sizeof(Peeptable_entry));
63: Cell h;
64: p->prefix = insts[c->prefix];
65: p->lastprim = insts[c->lastprim];
66: p->combination_prim = insts[c->combination_prim];
67: h = hash(p->prefix,p->lastprim);
68: p->next = pt[h];
69: pt[h] = p;
1.1 anton 70: }
1.3 anton 71: return (Cell)pt;
72: }
73:
74: Inst peephole_opt(Inst inst1, Inst inst2, Cell peeptable)
75: {
76: Peeptable_entry **pt = (Peeptable_entry **)peeptable;
77: Peeptable_entry *p;
78:
79: if (use_super == 0)
80: return 0;
81: for (p = pt[hash(inst1,inst2)]; p != NULL; p = p->next)
82: if (inst1 == p->prefix && inst2 == p->lastprim)
83: return p->combination_prim;
84: return NULL;
1.1 anton 85: }
1.4 ! ak042 86:
! 87:
! 88: /* hashtable stuff (again) */
! 89:
! 90: #undef hash
! 91:
! 92: typedef int (*Pred1) (void* arg1);
! 93: typedef int (*Pred2) (void* arg1, void* arg2);
! 94: typedef void* (*Proc1) (void* arg1);
! 95: typedef void* (*Proc2) (void* arg1, void* arg2);
! 96: typedef void* (*Proc3) (void* arg1, void* arg2, void* arg3);
! 97: typedef int (*Key_Eq) (void* key1, void* key2);
! 98: typedef unsigned (*Key_Hash) (void* key, unsigned modulus);
! 99:
! 100: typedef struct hash_table *Hash_Table;
! 101:
! 102: Hash_Table make_hash_table (unsigned size, Key_Eq eq, Key_Hash hash);
! 103: void* hash_table_ref (Hash_Table table, void* key, void* deflt);
! 104: void hash_table_set (Hash_Table table, void *key, void* value);
! 105: void* hash_table_find_value (Hash_Table table, Pred1 p, void* deflt);
! 106: void* hash_table_with_env_find_value (Hash_Table table,
! 107: Pred2 p, void* env,
! 108: void* deflt);
! 109: void* hash_table_fold (Hash_Table table, Proc3 proc, void *knil);
! 110: void hash_table_print (Hash_Table table);
! 111: int hash_table_addr_eq (void* key1, void* key2);
! 112: unsigned hash_table_addr_hash (void* key, unsigned modulus);
! 113: int hash_table_string_eq (char* k1, char* k2);
! 114: unsigned hash_table_string_hash (char* key, unsigned modulus);
! 115:
! 116: #include <stdlib.h>
! 117: #include <assert.h>
! 118:
! 119: typedef struct hash_bucket {
! 120: void* key;
! 121: void* value;
! 122: struct hash_bucket* next;
! 123: } *Hash_Bucket;
! 124:
! 125: struct hash_table {
! 126: unsigned size;
! 127: Hash_Bucket* buckets;
! 128: Key_Eq eq;
! 129: Key_Hash hash;
! 130: };
! 131:
! 132: Hash_Table make_hash_table (unsigned size, Key_Eq eq, Key_Hash hash) {
! 133: Hash_Table tab = malloc (sizeof *tab);
! 134: Hash_Bucket* buckets = calloc (size, sizeof *buckets);
! 135: assert (tab);
! 136: assert (buckets);
! 137: tab->size = size;
! 138: tab->buckets = buckets;
! 139: tab->eq = eq;
! 140: tab->hash = hash;
! 141: return tab;
! 142: }
! 143:
! 144: static void* hash_bucket_search (Hash_Bucket* next, Pred1 p,
! 145: Proc1 found, Proc1 not_found) {
! 146: for (;;) {
! 147: Hash_Bucket bucket = *next;
! 148: if (bucket == 0) return not_found (next);
! 149: else if (p (bucket->key)) return found (next);
! 150: else { next = &(bucket->next); continue; }
! 151: }
! 152: }
! 153:
! 154: static void* hash_table_search (Hash_Table table, void* key, Key_Eq eq,
! 155: Proc1 found, Proc1 not_found) {
! 156: int pred (void* key2) { return eq (key, key2); }
! 157: unsigned idx= table->hash(key, table->size);
! 158: assert (idx < table->size);
! 159: return hash_bucket_search (table->buckets+idx, pred, found, not_found);
! 160: }
! 161:
! 162: void* hash_table_ref (Hash_Table table, void* key, void* deflt) {
! 163: void* found (Hash_Bucket* next) { return (*next)->value; }
! 164: void* not_found (Hash_Bucket* next) { return deflt; }
! 165: return hash_table_search (table, key, table->eq,
! 166: (Proc1)found, (Proc1)not_found);
! 167: }
! 168:
! 169: void hash_table_set (Hash_Table table, void *key, void* value) {
! 170: void* found (Hash_Bucket* next) {
! 171: Hash_Bucket bucket = *next;
! 172: bucket->key = key;
! 173: bucket->value = value;
! 174: return value;
! 175: }
! 176: void* not_found (Hash_Bucket* next) {
! 177: Hash_Bucket bucket = malloc (sizeof (struct hash_bucket));
! 178: assert (bucket);
! 179: bucket->key = key;
! 180: bucket->value = value;
! 181: bucket->next = *next;
! 182: *next = bucket;
! 183: return value;
! 184: }
! 185: hash_table_search (table, key, table->eq,
! 186: (Proc1)found,(Proc1)not_found);
! 187: }
! 188:
! 189: void* hash_table_find_value (Hash_Table table, Pred1 p, void* deflt) {
! 190: unsigned i = 0;
! 191: for (;;)
! 192: if (i == table->size) return deflt;
! 193: else {
! 194: Hash_Bucket bucket = table->buckets[i];
! 195: for (;;)
! 196: if (bucket == 0) { i++; break; }
! 197: else if (p (bucket->value)) return bucket->value;
! 198: else { bucket = bucket->next; continue; }
! 199: }
! 200: }
! 201:
! 202: void* hash_table_with_env_find_value (Hash_Table table,
! 203: Pred2 p, void* env,
! 204: void* deflt) {
! 205: int pred (void* val) { return p (env, val); }
! 206: return hash_table_find_value (table, pred, deflt);
! 207: }
! 208:
! 209:
! 210: static void* hash_bucket_fold (Hash_Bucket bucket, Proc3 proc, void *init) {
! 211: for (;;)
! 212: if (bucket == 0) return init;
! 213: else {
! 214: init = proc (bucket->key, bucket->value, init);
! 215: bucket = bucket->next; continue;
! 216: }
! 217: }
! 218:
! 219: void* hash_table_fold (Hash_Table table, Proc3 proc, void *init) {
! 220: unsigned i = 0, size = table->size;
! 221: Hash_Bucket* buckets = table->buckets;
! 222: for (;;)
! 223: if (i == size) return init;
! 224: else {
! 225: init = hash_bucket_fold (buckets [i], proc, init);
! 226: i++; continue;
! 227: }
! 228: }
! 229:
! 230: void hash_table_print (Hash_Table table) {
! 231: void* print (void* key, void* value, void* init) {
! 232: printf ("[%p, %p]\n", key, value);
! 233: return init;
! 234: }
! 235: hash_table_fold (table, print, 0);
! 236: }
! 237:
! 238: int hash_table_addr_eq (void* key1, void* key2) {
! 239: return key1 == key2;
! 240: }
! 241:
! 242: unsigned hash_table_addr_hash (void* key, unsigned modulus) {
! 243: return (((unsigned long)key) >> 3) % modulus;
! 244: }
! 245:
! 246: int hash_table_string_eq (char* k1, char* k2) {
! 247: return strcmp (k1, k2) == 0;
! 248: }
! 249:
! 250: unsigned hash_table_string_hash (char* key, unsigned modulus) {
! 251: unsigned sum = 0;
! 252: for (;;)
! 253: if (*key == 0) return (sum >> 3) % modulus;
! 254: else { sum += *key; key++; continue; }
! 255: }
! 256:
! 257: /*
! 258:
! 259: Select super instructions with dynamic programming.
! 260:
! 261: A buffer `dp_table' stores an instruction sequence, i.e. a basic
! 262: block. Instructions can be added with `peephole_dp_append'.
! 263: `peephole_dp_append' takes the Prim_Descriptor of the operator and a
! 264: pointer to a gap where to place the super-instruction, i.e. the
! 265: current `here' pointer.
! 266:
! 267: The actual instructions are copied into the gaps by calling
! 268: `peephole_dp_flush'. This selects an optimal cover for the stored
! 269: sequence, copies the corresponding XTs into the gaps, moves inline
! 270: arguments (this may be required, since some gaps may not be filled
! 271: with instructions), and finally flushes the buffer `dp_table'.
! 272:
! 273: The rest of the system must cooperate, i.e. has to call
! 274: `peephole_dp_flush' in the right places, e.g. before taking labels.
! 275: Non-cooperation will be punished with crashes.
! 276:
! 277: */
! 278:
! 279: /* #define XDP_DEBUG(stm) stm; */
! 280: #define XDP_DEBUG(stm)
! 281:
! 282: #define dprintf(format, args...) XDP_DEBUG(fprintf (stderr, format , ## args))
! 283:
! 284: typedef struct dp_table_entry {
! 285: Prim_Descriptor op; /* NULL marks the end. */
! 286: Cell* mark; /* the gap. */
! 287: struct burm_state* state; /* iburg needs this. */
! 288: /* unsigned state; */
! 289: }* Dp_Table_Entry;
! 290:
! 291: #define DP_TABLE_SIZE 25
! 292: static struct dp_table_entry dp_table[DP_TABLE_SIZE+1];
! 293: static unsigned dp_table_len = 0;
! 294:
! 295: static int dp_table_end_p (Dp_Table_Entry entry) { return entry->op == 0; }
! 296: static void dp_table_clear (void) {
! 297: dp_table_len = 0;
! 298: dp_table[0].op = 0;
! 299: /* dprintf ("dp_table_clear\n"); */
! 300: }
! 301: static void dump_dp_table (void) {
! 302: Dp_Table_Entry e = dp_table;
! 303: for (;;)
! 304: if (dp_table_end_p (e)) return;
! 305: else {
! 306: printf ("[%s, %p]\n", e->op->name, e->mark);
! 307: e++; continue;
! 308: }
! 309: }
! 310:
! 311: Cell* peephole_dp_flush (Cell* mark);
! 312:
! 313: Cell* peephole_dp_append (Prim_Descriptor desc, Cell* mark) {
! 314: if (dp_table_len == DP_TABLE_SIZE) {
! 315: dp_table[dp_table_len].op = 0;
! 316: mark = peephole_dp_flush (mark);
! 317: }
! 318: dp_table[dp_table_len].op = desc;
! 319: assert (dp_table_len == 0 ||
! 320: dp_table[dp_table_len-1].mark < mark);
! 321: dp_table[dp_table_len].mark = mark;
! 322: dp_table_len ++;
! 323: dp_table[dp_table_len].op = 0;
! 324: return mark+1;
! 325: }
! 326:
! 327: /* burg stuff */
! 328:
! 329: #define NIL_TERM_NUM 1
! 330: typedef struct dp_table_entry* NODEPTR_TYPE;
! 331: #define OP_LABEL(p) (((p)->op ? (p)->op->num+2 : NIL_TERM_NUM))
! 332: #define STATE_LABEL(p) ((p)->state)
! 333: #define LEFT_CHILD(p) ((p)+1)
! 334: #define RIGHT_CHILD(p) ((NODEPTR_TYPE)(assert (0), 0L))
! 335: #define PANIC dprintf
! 336:
! 337: #include "prim_burm.i"
! 338:
! 339: static Label* peephole_symbols = 0;
! 340: static Xt desc_to_xt (Prim_Descriptor desc) {
! 341: static Xt* primtab = 0;
! 342: if (primtab == 0) {
! 343: Label* symbols = peephole_symbols;
! 344: unsigned symbols_size = DOESJUMP+1;
! 345: assert (peephole_symbols);
! 346: for (;;)
! 347: if (symbols[symbols_size] == 0) break;
! 348: else { symbols_size ++; continue; }
! 349: primtab = primtable(symbols+DOESJUMP+1,
! 350: symbols_size-DOESJUMP-1);
! 351: }
! 352: return primtab[desc->num];
! 353: }
! 354:
! 355:
! 356: static Prim_Descriptor peephole_descs = 0;
! 357: static Prim_Descriptor external_rule_number_to_desc (int eruleno) {
! 358: assert (peephole_descs);
! 359: return &peephole_descs[eruleno-NIL_TERM_NUM-1];
! 360: }
! 361:
! 362: static void move_args_left (Dp_Table_Entry entry, unsigned n, unsigned offset){
! 363: if (n == 0) return;
! 364: else {
! 365: Cell* from = entry->mark+1;
! 366: size_t size = entry[1].mark - from;
! 367: memmove (from-offset, from, size * sizeof *from);
! 368: move_args_left (entry+1, n-1, offset+1);
! 369: }
! 370: }
! 371:
! 372:
! 373: static unsigned reduce (Dp_Table_Entry entry, int goalnt, unsigned saved) {
! 374: if (dp_table_end_p (entry))
! 375: return saved;
! 376: else {
! 377: int eruleno = burm_rule (STATE_LABEL(entry), goalnt);
! 378: short *nts = burm_nts[eruleno];
! 379: NODEPTR_TYPE kids[2];
! 380: Prim_Descriptor desc = external_rule_number_to_desc (eruleno);
! 381: Label* xt = (Label*)desc_to_xt (desc);;
! 382: dprintf ("burm_string = %s, desc = %s, xt = %p\n",
! 383: burm_string[eruleno], desc->name, xt);
! 384: *(entry->mark-saved) = (Cell)xt;
! 385: move_args_left (entry, desc->len, saved);
! 386: burm_kids (entry, eruleno, kids);
! 387: return reduce (kids[0], nts[0], saved+desc->len-1);
! 388: }
! 389: }
! 390:
! 391:
! 392: static void dump_match (NODEPTR_TYPE p, int goalnt, int indent) {
! 393: int eruleno = burm_rule (STATE_LABEL(p), goalnt);
! 394: short *nts = burm_nts[eruleno];
! 395: NODEPTR_TYPE kids[2];
! 396: int i;
! 397: for (i = 0; i < indent; i++) printf (" ");
! 398: printf ("%s [%d]\n", burm_string[eruleno], eruleno);
! 399: burm_kids(p, eruleno, kids);
! 400: for (i = 0; nts[i]; i++)
! 401: dump_match (kids[i], nts[i], indent+1);
! 402: }
! 403:
! 404: #ifdef PIUMARTA
! 405:
! 406: /* Return the size (in bytes) for the superinstrcution from first to
! 407: (exluding) last. */
! 408: static unsigned
! 409: super_code_size (Dp_Table_Entry first, Dp_Table_Entry last, unsigned length) {
! 410: if (first == last)
! 411: return length;
! 412: else if (first+1 == last)
! 413: return length + (first->op->after_next - first->op->after_trace);
! 414: else
! 415: return super_code_size (first+1,
! 416: last,
! 417: length + (first->op->before_next
! 418: - first->op->after_trace));
! 419: }
! 420:
! 421: static void
! 422: concat_code (Dp_Table_Entry first, Dp_Table_Entry last, char* code) {
! 423: if (first == last)
! 424: return;
! 425: else if (first+1 == last)
! 426: memcpy (code, first->op->after_trace,
! 427: first->op->after_next - first->op->after_trace);
! 428: else {
! 429: unsigned size = first->op->before_next-first->op->after_trace;
! 430: memcpy (code, first->op->after_trace, size);
! 431: concat_code (first+1, last, code+size);
! 432: }
! 433: }
! 434:
! 435: static void apply_icache_magic (char* addr, unsigned size) {
! 436: FLUSH_ICACHE(addr, size);
! 437: }
! 438:
! 439: static void print_from_to (Dp_Table_Entry first, Dp_Table_Entry last) {
! 440: if (first == last) printf ("\n");
! 441: else {
! 442: printf ("[%s]", first->op->name);
! 443: print_from_to (first+1, last);
! 444: }
! 445: }
! 446:
! 447: static Prim_Descriptor search_desc (char *name) {
! 448: Prim_Descriptor d = peephole_descs;
! 449: for (;;)
! 450: if (d->name == 0) assert (0);
! 451: else if (strcmp (d->name, name) == 0) return d;
! 452: else { d++; continue; }
! 453: }
! 454:
! 455: static Xt get_trace_xt (void) {
! 456: static Xt trace_xt = 0;
! 457: if (trace_xt == 0) trace_xt = desc_to_xt (search_desc ("noop"));
! 458: return trace_xt;
! 459: }
! 460:
! 461: static unsigned
! 462: piumarta_gen_simple_inst (Dp_Table_Entry first, unsigned saved) {
! 463: Label* xt = (Label*)desc_to_xt (first->op);;
! 464: *(first->mark-saved) = (Cell)xt;
! 465: move_args_left (first, 1, saved);
! 466: return saved;
! 467: }
! 468:
! 469:
! 470: #if 0
! 471: static void alloc_xt (unsigned size, Xt *xt, char** code) {
! 472: # if defined(DIRECT_THREADED)
! 473: *xt = malloc (size);
! 474: assert (*xt);
! 475: *code = *xt;
! 476: return ;
! 477: # elsif DOUBLY_INDIRECT
! 478: /* this is never reached. blocked in comp.fs. */
! 479: assert (0); return;
! 480: # else
! 481: # warning Assuming indirect threaded
! 482: Xt* xtb = malloc (size + sizeof xt);
! 483: assert (xtb);
! 484: xtb[0] = (Xt)&xtb[1];
! 485: *xt = (Xt)xtb;
! 486: *code = (char*)&xtb[1];
! 487: return;
! 488: # endif
! 489: }
! 490: #else
! 491:
! 492: static Xt make_xt (char* code) {
! 493: # if defined(DIRECT_THREADED)
! 494: return code;
! 495: # elif defined(DOUBLY_INDIRECT)
! 496: /* this is never reached. blocked in comp.fs. */
! 497: assert (0); return 0;
! 498: # else
! 499: # warning Assuming indirect threaded
! 500: Xt xt = malloc (sizeof xt);
! 501: assert (xt);
! 502: *xt = code;
! 503: return xt;
! 504: # endif
! 505: }
! 506: static void alloc_xt (unsigned size, Xt *xt, char** code) {
! 507: *code = malloc (size);
! 508: assert (code);
! 509: *xt = make_xt (*code);
! 510: }
! 511:
! 512: #endif
! 513:
! 514:
! 515:
! 516: int peephole_enable_tracing = 0;
! 517: typedef struct sequence {
! 518: unsigned length;
! 519: Dp_Table_Entry start;
! 520: }* Sequence;
! 521:
! 522: static int sequence_eq (Sequence s1, Sequence s2) {
! 523: Dp_Table_Entry e1=s1->start, e2=s2->start, last=e1+s1->length;
! 524: XDP_DEBUG ({
! 525: print_from_to (e1, last);
! 526: print_from_to (e2, e2+s2->length); });
! 527: if (s1->length != s2->length) return 0;
! 528: for (;;)
! 529: if (e1 == last) return 1;
! 530: else if (e1->op == e2->op) { e1++; e2++; continue; }
! 531: else return 0;
! 532: }
! 533:
! 534: static unsigned sequence_hash (Sequence s, unsigned modulus) {
! 535: unsigned long h=0;
! 536: Dp_Table_Entry e=s->start, last=e+s->length;
! 537: for (;;)
! 538: if (e == last) return (h>>3) % modulus;
! 539: else { h+=(unsigned long)e->op; e++; continue; }
! 540: }
! 541:
! 542: static Hash_Table generated_insts = 0;
! 543: typedef Dp_Table_Entry Entry;
! 544:
! 545: static Xt lookup (Entry first, Entry last) {
! 546: unsigned len = last-first;
! 547: struct sequence seq = { len, first };
! 548: return hash_table_ref (generated_insts, &seq, 0);
! 549: }
! 550:
! 551: static void memoize (Entry first, Entry last, Xt xt) {
! 552: Sequence seq = malloc (sizeof *seq);
! 553: unsigned size = (last-first) * sizeof *first;
! 554: Dp_Table_Entry start = malloc (size);
! 555: assert (seq); assert (start);
! 556: memcpy (start, first, size);
! 557: seq->length = last-first;
! 558: seq->start = start;
! 559: XDP_DEBUG(print_from_to (start, start+(last-first)));
! 560: hash_table_set (generated_insts, seq, xt);
! 561: assert (lookup (first, last) == xt);
! 562: }
! 563:
! 564: static Xt combine_insts (Entry first, Entry last) {
! 565: Xt xt = lookup (first, last);
! 566: if (xt == 0) {
! 567: unsigned size = super_code_size (first, last, 0);
! 568: char* code = 0;
! 569: alloc_xt (size, &xt, &code);
! 570: concat_code (first, last, code);
! 571: apply_icache_magic (code, size);
! 572: memoize (first, last, xt);
! 573: return xt;
! 574: }
! 575: else { dprintf ("reusing combination.\n"); return xt; }
! 576: }
! 577:
! 578: static unsigned
! 579: piumarta_gen_combined_inst (Entry first, Entry last, unsigned saved) {
! 580: Xt xt = combine_insts (first, last);
! 581: unsigned len = last-first;
! 582: unsigned offset = saved-(len-1);
! 583: dprintf ("len = %d, saved = %d\n", len, saved);
! 584: if (!peephole_enable_tracing) {
! 585: move_args_left (first, len, offset);
! 586: *(first->mark-offset) = (Cell)xt;
! 587: return saved;
! 588: } else {
! 589: /** hairy: Move operands for the first op 1 slot to
! 590: right (possible because len>=2). Move operands of
! 591: the remaining ops offset-1 slots to left (and
! 592: eliminate empty slots). */
! 593: Cell* from = first->mark+1;
! 594: Cell* to = from-offset+1;
! 595: size_t size = first[1].mark-from;
! 596: memmove (to, from, size * sizeof *from);
! 597: move_args_left (first+1, len-1, offset);
! 598: *(to-1) = (Cell)xt;
! 599: *(to-2) = (Cell)get_trace_xt ();
! 600: return saved-1;
! 601: }
! 602: }
! 603:
! 604: static unsigned piumarta_gen_inst (Entry first, Entry last, unsigned saved) {
! 605: XDP_DEBUG (print_from_to (first, last));
! 606: switch (last-first) {
! 607: case 0: return saved;
! 608: case 1: return piumarta_gen_simple_inst (first, saved);
! 609: default: return piumarta_gen_combined_inst (first, last, saved);
! 610: }
! 611: }
! 612:
! 613: static unsigned
! 614: piumartaize (Dp_Table_Entry lag, Dp_Table_Entry tail, unsigned saved) {
! 615: assert (tail >= lag);
! 616: if (dp_table_end_p (tail) && tail == lag) return saved;
! 617: else if (dp_table_end_p (tail)) {
! 618: return piumarta_gen_inst (lag, tail, saved);
! 619: }
! 620: else if (tail->op->relocatable)
! 621: return piumartaize (lag, tail+1, saved+((tail==lag)?0:1));
! 622: else {
! 623: saved = piumarta_gen_inst (lag, tail, saved);
! 624: saved = piumarta_gen_inst (tail, tail+1, saved);
! 625: return piumartaize (tail+1, tail+1, saved);
! 626: }
! 627: }
! 628:
! 629: #endif /* PIUMARTA */
! 630:
! 631: Cell* peephole_dp_flush (Cell* mark) {
! 632: assert (dp_table[dp_table_len].op == 0);
! 633: assert (dp_table_len == 0 ||
! 634: dp_table[dp_table_len-1].mark < mark );
! 635: dp_table[dp_table_len].mark = mark;
! 636: XDP_DEBUG(dump_dp_table ());
! 637: #ifndef PIUMARTA
! 638: burm_label (dp_table);
! 639: XDP_DEBUG(dump_match (dp_table, 1, 0));
! 640: {
! 641: unsigned saved = reduce (dp_table, 1, 0);
! 642: dp_table_clear ();
! 643: return mark-saved;
! 644: }
! 645: #else
! 646: {
! 647: unsigned saved = piumartaize (dp_table, dp_table, 0);
! 648: dp_table_clear ();
! 649: return mark-saved;
! 650: }
! 651: #endif
! 652: }
! 653:
! 654:
! 655: static Hash_Table ca_table = 0;
! 656: Prim_Descriptor peephole_code_address_to_desc (void* ca) {
! 657: assert (ca_table);
! 658: return hash_table_ref (ca_table, ca, 0);
! 659: }
! 660:
! 661: static void init_ca_table (Prim_Descriptor descs) {
! 662: unsigned len = 0;
! 663: Prim_Descriptor d = descs;
! 664: for (;;)
! 665: if (d->name == 0) break;
! 666: else { len++; d++; continue; }
! 667: ca_table = make_hash_table (len, hash_table_addr_eq,
! 668: hash_table_addr_hash);
! 669: d=descs;
! 670: for (;;)
! 671: if (d->name == 0) break;
! 672: else { hash_table_set (ca_table, d->start, d); d++; continue; }
! 673: }
! 674:
! 675: void peephole_init (Label* symbols, Prim_Descriptor descs) {
! 676: peephole_symbols = symbols;
! 677: peephole_descs = descs;
! 678: init_ca_table (descs);
! 679: generated_insts = make_hash_table (2000,
! 680: (Key_Eq)sequence_eq,
! 681: (Key_Hash)sequence_hash);
! 682: }
! 683:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>