version 1.124, 2003/10/09 14:15:20
|
version 1.125, 2003/10/16 18:48:03
|
Line 154 static int no_dynamic=NO_DYNAMIC_DEFAULT
|
Line 154 static int no_dynamic=NO_DYNAMIC_DEFAULT
|
dynamically */ |
dynamically */ |
static int print_metrics=0; /* if true, print metrics on exit */ |
static int print_metrics=0; /* if true, print metrics on exit */ |
static int static_super_number = 10000000; /* number of ss used if available */ |
static int static_super_number = 10000000; /* number of ss used if available */ |
|
#define MAX_STATE 4 /* maximum number of states */ |
|
static int maxstates = MAX_STATE; /* number of states for stack caching */ |
static int ss_greedy = 0; /* if true: use greedy, not optimal ss selection */ |
static int ss_greedy = 0; /* if true: use greedy, not optimal ss selection */ |
|
|
#ifdef HAS_DEBUG |
#ifdef HAS_DEBUG |
Line 169 Label *vm_prims;
|
Line 171 Label *vm_prims;
|
Label *xts; /* same content as vm_prims, but should only be used for xts */ |
Label *xts; /* same content as vm_prims, but should only be used for xts */ |
#endif |
#endif |
|
|
|
#ifndef NO_DYNAMIC |
|
#define MAX_IMMARGS 2 |
|
|
|
typedef struct { |
|
Label start; /* NULL if not relocatable */ |
|
Cell length; /* only includes the jump iff superend is true*/ |
|
Cell restlength; /* length of the rest (i.e., the jump or (on superend) 0) */ |
|
char superend; /* true if primitive ends superinstruction, i.e., |
|
unconditional branch, execute, etc. */ |
|
Cell nimmargs; |
|
struct immarg { |
|
Cell offset; /* offset of immarg within prim */ |
|
char rel; /* true if immarg is relative */ |
|
} immargs[MAX_IMMARGS]; |
|
} PrimInfo; |
|
|
|
PrimInfo *priminfos; |
|
PrimInfo **decomp_prims; |
|
|
|
static int is_relocatable(int p) |
|
{ |
|
return !no_dynamic && priminfos[p].start != NULL; |
|
} |
|
#else /* defined(NO_DYNAMIC) */ |
|
static int is_relocatable(int p) |
|
{ |
|
return 0; |
|
} |
|
#endif /* defined(NO_DYNAMIC) */ |
|
|
#ifdef MEMCMP_AS_SUBROUTINE |
#ifdef MEMCMP_AS_SUBROUTINE |
int gforth_memcmp(const char * s1, const char * s2, size_t n) |
int gforth_memcmp(const char * s1, const char * s2, size_t n) |
{ |
{ |
Line 176 int gforth_memcmp(const char * s1, const
|
Line 208 int gforth_memcmp(const char * s1, const
|
} |
} |
#endif |
#endif |
|
|
|
static Cell max(Cell a, Cell b) |
|
{ |
|
return a>b?a:b; |
|
} |
|
|
|
static Cell min(Cell a, Cell b) |
|
{ |
|
return a<b?a:b; |
|
} |
|
|
/* image file format: |
/* image file format: |
* "#! binary-path -i\n" (e.g., "#! /usr/local/bin/gforth-0.4.0 -i\n") |
* "#! binary-path -i\n" (e.g., "#! /usr/local/bin/gforth-0.4.0 -i\n") |
* padding to a multiple of 8 |
* padding to a multiple of 8 |
Line 221 Cell groups[32] = {
|
Line 263 Cell groups[32] = {
|
#define GROUPADD(n) |
#define GROUPADD(n) |
}; |
}; |
|
|
|
unsigned char *branch_targets(Cell *image, const unsigned char *bitstring, |
|
int size, Cell base) |
|
/* produce a bitmask marking all the branch targets */ |
|
{ |
|
int i=0, j, k, steps=(size/sizeof(Cell))/RELINFOBITS; |
|
Cell token; |
|
unsigned char bits; |
|
unsigned char *result=malloc(steps+1); |
|
|
|
memset(result, 0, steps+1); |
|
for(k=0; k<=steps; k++) { |
|
for(j=0, bits=bitstring[k]; j<RELINFOBITS; j++, i++, bits<<=1) { |
|
if((i < size) && (bits & (1U << (RELINFOBITS-1)))) { |
|
token=image[i]; |
|
if (token>=base) { /* relocatable address */ |
|
UCell bitnum=(token-base)/sizeof(Cell); |
|
result[bitnum/RELINFOBITS] |= 1U << ((~bitnum)&(RELINFOBITS-1)); |
|
} |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
void relocate(Cell *image, const unsigned char *bitstring, |
void relocate(Cell *image, const unsigned char *bitstring, |
int size, Cell base, Label symbols[]) |
int size, Cell base, Label symbols[]) |
{ |
{ |
Line 233 void relocate(Cell *image, const unsigne
|
Line 299 void relocate(Cell *image, const unsigne
|
* the one in the image |
* the one in the image |
*/ |
*/ |
Cell *start = (Cell * ) (((void *) image) - ((void *) base)); |
Cell *start = (Cell * ) (((void *) image) - ((void *) base)); |
|
unsigned char *targets = branch_targets(image, bitstring, size, base); |
|
|
/* group index into table */ |
/* group index into table */ |
if(groups[31]==0) { |
if(groups[31]==0) { |
Line 281 void relocate(Cell *image, const unsigne
|
Line 348 void relocate(Cell *image, const unsigne
|
if (CF((token | 0x4000))<max_symbols) { |
if (CF((token | 0x4000))<max_symbols) { |
image[i]=(Cell)CFA(CF(token)); |
image[i]=(Cell)CFA(CF(token)); |
#ifdef DIRECT_THREADED |
#ifdef DIRECT_THREADED |
if ((token & 0x4000) == 0) /* threade code, no CFA */ |
if ((token & 0x4000) == 0) { /* threade code, no CFA */ |
|
if (targets[k] & (1U<<(RELINFOBITS-1-j))) |
|
compile_prim1(0); |
compile_prim1(&image[i]); |
compile_prim1(&image[i]); |
|
} |
#endif |
#endif |
} else |
} else |
fprintf(stderr,"Primitive %ld used in this image at $%lx (offset $%x) is not implemented by this\n engine (%s); executing this code will crash.\n",(long)CF(token),(long)&image[i], i, PACKAGE_VERSION); |
fprintf(stderr,"Primitive %ld used in this image at $%lx (offset $%x) is not implemented by this\n engine (%s); executing this code will crash.\n",(long)CF(token),(long)&image[i], i, PACKAGE_VERSION); |
Line 296 void relocate(Cell *image, const unsigne
|
Line 366 void relocate(Cell *image, const unsigne
|
image[i]=(Cell)CFA((groups[group]+tok)); |
image[i]=(Cell)CFA((groups[group]+tok)); |
#endif |
#endif |
#ifdef DIRECT_THREADED |
#ifdef DIRECT_THREADED |
if ((token & 0x4000) == 0) /* threade code, no CFA */ |
if ((token & 0x4000) == 0) { /* threade code, no CFA */ |
|
if (targets[k] & (1U<<(RELINFOBITS-1-j))) |
|
compile_prim1(0); |
compile_prim1(&image[i]); |
compile_prim1(&image[i]); |
|
} |
#endif |
#endif |
} else |
} else |
fprintf(stderr,"Primitive %lx, %d of group %d used in this image at $%lx (offset $%x) is not implemented by this\n engine (%s); executing this code will crash.\n", (long)-token, tok, group, (long)&image[i],i,PACKAGE_VERSION); |
fprintf(stderr,"Primitive %lx, %d of group %d used in this image at $%lx (offset $%x) is not implemented by this\n engine (%s); executing this code will crash.\n", (long)-token, tok, group, (long)&image[i],i,PACKAGE_VERSION); |
Line 311 void relocate(Cell *image, const unsigne
|
Line 384 void relocate(Cell *image, const unsigne
|
} |
} |
} |
} |
} |
} |
|
free(targets); |
finish_code(); |
finish_code(); |
((ImageHeader*)(image))->base = (Address) image; |
((ImageHeader*)(image))->base = (Address) image; |
} |
} |
Line 560 struct cost {
|
Line 634 struct cost {
|
char stores; /* number of stack stores */ |
char stores; /* number of stack stores */ |
char updates; /* number of stack pointer updates */ |
char updates; /* number of stack pointer updates */ |
char branch; /* is it a branch (SET_IP) */ |
char branch; /* is it a branch (SET_IP) */ |
char state_in; /* state on entry */ |
unsigned char state_in; /* state on entry */ |
char state_out; /* state on exit */ |
unsigned char state_out; /* state on exit */ |
short offset; /* offset into super2 table */ |
short offset; /* offset into super2 table */ |
char length; /* number of components */ |
unsigned char length; /* number of components */ |
}; |
}; |
|
|
PrimNum super2[] = { |
PrimNum super2[] = { |
Line 574 struct cost super_costs[] = {
|
Line 648 struct cost super_costs[] = {
|
#include "costs.i" |
#include "costs.i" |
}; |
}; |
|
|
|
struct super_state { |
|
struct super_state *next; |
|
PrimNum super; |
|
}; |
|
|
#define HASH_SIZE 256 |
#define HASH_SIZE 256 |
|
|
struct super_table_entry { |
struct super_table_entry { |
struct super_table_entry *next; |
struct super_table_entry *next; |
PrimNum *start; |
PrimNum *start; |
short length; |
short length; |
PrimNum super; |
struct super_state *ss_list; /* list of supers */ |
} *super_table[HASH_SIZE]; |
} *super_table[HASH_SIZE]; |
int max_super=2; |
int max_super=2; |
|
|
|
struct super_state *state_transitions=NULL; |
|
|
int hash_super(PrimNum *start, int length) |
int hash_super(PrimNum *start, int length) |
{ |
{ |
int i, r; |
int i, r; |
Line 595 int hash_super(PrimNum *start, int lengt
|
Line 676 int hash_super(PrimNum *start, int lengt
|
return r & (HASH_SIZE-1); |
return r & (HASH_SIZE-1); |
} |
} |
|
|
int lookup_super(PrimNum *start, int length) |
struct super_state **lookup_super(PrimNum *start, int length) |
{ |
{ |
int hash=hash_super(start,length); |
int hash=hash_super(start,length); |
struct super_table_entry *p = super_table[hash]; |
struct super_table_entry *p = super_table[hash]; |
|
|
assert(length >= 2); |
/* assert(length >= 2); */ |
for (; p!=NULL; p = p->next) { |
for (; p!=NULL; p = p->next) { |
if (length == p->length && |
if (length == p->length && |
memcmp((char *)p->start, (char *)start, length*sizeof(PrimNum))==0) |
memcmp((char *)p->start, (char *)start, length*sizeof(PrimNum))==0) |
return p->super; |
return &(p->ss_list); |
} |
} |
return -1; |
return NULL; |
} |
} |
|
|
void prepare_super_table() |
void prepare_super_table() |
Line 616 void prepare_super_table()
|
Line 697 void prepare_super_table()
|
|
|
for (i=0; i<sizeof(super_costs)/sizeof(super_costs[0]); i++) { |
for (i=0; i<sizeof(super_costs)/sizeof(super_costs[0]); i++) { |
struct cost *c = &super_costs[i]; |
struct cost *c = &super_costs[i]; |
if (c->length > 1 && nsupers < static_super_number) { |
if ((c->length < 2 || nsupers < static_super_number) && |
int hash = hash_super(super2+c->offset, c->length); |
c->state_in < maxstates && c->state_out < maxstates) { |
struct super_table_entry **p = &super_table[hash]; |
struct super_state **ss_listp= lookup_super(super2+c->offset, c->length); |
struct super_table_entry *e = malloc(sizeof(struct super_table_entry)); |
struct super_state *ss = malloc(sizeof(struct super_state)); |
e->next = *p; |
ss->super= i; |
e->start = super2 + c->offset; |
if (c->offset==N_noop && i != N_noop) { |
e->length = c->length; |
if (is_relocatable(i)) { |
e->super = i; |
ss->next = state_transitions; |
*p = e; |
state_transitions = ss; |
|
} |
|
} else if (ss_listp != NULL) { |
|
ss->next = *ss_listp; |
|
*ss_listp = ss; |
|
} else { |
|
int hash = hash_super(super2+c->offset, c->length); |
|
struct super_table_entry **p = &super_table[hash]; |
|
struct super_table_entry *e = malloc(sizeof(struct super_table_entry)); |
|
ss->next = NULL; |
|
e->next = *p; |
|
e->start = super2 + c->offset; |
|
e->length = c->length; |
|
e->ss_list = ss; |
|
*p = e; |
|
} |
if (c->length > max_super) |
if (c->length > max_super) |
max_super = c->length; |
max_super = c->length; |
nsupers++; |
if (c->length >= 2) |
|
nsupers++; |
} |
} |
} |
} |
if (debug) |
if (debug) |
Line 636 void prepare_super_table()
|
Line 733 void prepare_super_table()
|
|
|
/* dynamic replication/superinstruction stuff */ |
/* dynamic replication/superinstruction stuff */ |
|
|
#define MAX_IMMARGS 2 |
|
|
|
#ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
typedef struct { |
|
Label start; |
|
Cell length; /* only includes the jump iff superend is true*/ |
|
Cell restlength; /* length of the rest (i.e., the jump or (on superend) 0) */ |
|
char superend; /* true if primitive ends superinstruction, i.e., |
|
unconditional branch, execute, etc. */ |
|
Cell nimmargs; |
|
struct immarg { |
|
Cell offset; /* offset of immarg within prim */ |
|
char rel; /* true if immarg is relative */ |
|
} immargs[MAX_IMMARGS]; |
|
} PrimInfo; |
|
|
|
PrimInfo *priminfos; |
|
PrimInfo **decomp_prims; |
|
|
|
int compare_priminfo_length(const void *_a, const void *_b) |
int compare_priminfo_length(const void *_a, const void *_b) |
{ |
{ |
PrimInfo **a = (PrimInfo **)_a; |
PrimInfo **a = (PrimInfo **)_a; |
Line 669 int compare_priminfo_length(const void *
|
Line 748 int compare_priminfo_length(const void *
|
} |
} |
#endif /* !defined(NO_DYNAMIC) */ |
#endif /* !defined(NO_DYNAMIC) */ |
|
|
static char superend[]={ |
static char MAYBE_UNUSED superend[]={ |
#include "prim_superend.i" |
#include "prim_superend.i" |
}; |
}; |
|
|
Line 1050 void compile_prim_dyn(Cell *start)
|
Line 1129 void compile_prim_dyn(Cell *start)
|
dei->branchinfo = nbranchinfos; |
dei->branchinfo = nbranchinfos; |
dei->xt = (Cell *)(last_start[1]); |
dei->xt = (Cell *)(last_start[1]); |
next_code_target = compile_call2(NULL); |
next_code_target = compile_call2(NULL); |
} else if (pi->start == NULL) { /* non-reloc */ |
} else if (!is_relocatable(i)) { |
next_code_target = compile_prim1arg(N_set_next_code); |
next_code_target = compile_prim1arg(N_set_next_code); |
set_rel_target(compile_prim1arg(N_abranch),*(Xt)last_prim); |
set_rel_target(compile_prim1arg(N_abranch),*(Xt)last_prim); |
} else { |
} else { |
Line 1086 void compile_prim_dyn(Cell *start)
|
Line 1165 void compile_prim_dyn(Cell *start)
|
*start = (Cell)prim; |
*start = (Cell)prim; |
return; |
return; |
} |
} |
if (i>=npriminfos || priminfos[i].start == 0) { /* not a relocatable prim */ |
if (i>=npriminfos || !is_relocatable(i)) { |
append_jump(); |
append_jump(); |
*start = (Cell)prim; |
*start = (Cell)prim; |
return; |
return; |
} |
} |
assert(priminfos[i].start = prim); |
|
#ifdef ALIGN_CODE |
#ifdef ALIGN_CODE |
/* ALIGN_CODE;*/ |
/* ALIGN_CODE;*/ |
#endif |
#endif |
Line 1121 Cell compile_prim_dyn(unsigned p)
|
Line 1199 Cell compile_prim_dyn(unsigned p)
|
|
|
if (no_dynamic) |
if (no_dynamic) |
return static_prim; |
return static_prim; |
if (p>=npriminfos || priminfos[p].start == 0) { /* not a relocatable prim */ |
if (p>=npriminfos || !is_relocatable(p)) { |
append_jump(); |
append_jump(); |
return static_prim; |
return static_prim; |
} |
} |
Line 1179 struct {
|
Line 1257 struct {
|
}; |
}; |
|
|
#define MAX_BB 128 /* maximum number of instructions in BB */ |
#define MAX_BB 128 /* maximum number of instructions in BB */ |
|
#define INF_COST 1000000 /* infinite cost */ |
|
#define CANONICAL_STATE 0 |
|
|
/* use dynamic programming to find the shortest paths within the basic |
struct waypoint { |
block origs[0..ninsts-1]; optimals[i] contains the superinstruction |
int cost; /* the cost from here to the end */ |
on the shortest path to the end of the BB */ |
PrimNum inst; /* the inst used from here to the next waypoint */ |
void optimize_bb(PrimNum origs[], PrimNum optimals[], int ninsts) |
char relocatable; /* the last non-transition was relocatable */ |
|
char no_transition; /* don't use the next transition (relocatability) |
|
* or this transition (does not change state) */ |
|
}; |
|
|
|
void init_waypoints(struct waypoint ws[]) |
{ |
{ |
int i,j, mincost; |
int k; |
static int costs[MAX_BB+1]; |
|
|
|
assert(ninsts<MAX_BB); |
for (k=0; k<maxstates; k++) |
costs[ninsts]=0; |
ws[k].cost=INF_COST; |
|
} |
|
|
|
void transitions(struct waypoint inst[], struct waypoint trans[]) |
|
{ |
|
int k; |
|
struct super_state *l; |
|
|
|
for (k=0; k<maxstates; k++) { |
|
trans[k] = inst[k]; |
|
trans[k].no_transition = 1; |
|
} |
|
for (l = state_transitions; l != NULL; l = l->next) { |
|
PrimNum s = l->super; |
|
int jcost; |
|
struct cost *c=super_costs+s; |
|
struct waypoint *wi=&(trans[c->state_in]); |
|
struct waypoint *wo=&(inst[c->state_out]); |
|
if (wo->cost == INF_COST) |
|
continue; |
|
jcost = wo->cost + ss_cost(s); |
|
if (jcost <= wi->cost) { |
|
wi->cost = jcost; |
|
wi->inst = s; |
|
wi->relocatable = wo->relocatable; |
|
wi->no_transition = 0; |
|
/* if (ss_greedy) wi->cost = wo->cost ? */ |
|
} |
|
} |
|
} |
|
|
|
/* use dynamic programming to find the shortest paths within the basic |
|
block origs[0..ninsts-1] and rewrite the instructions pointed to by |
|
instps to use it */ |
|
void optimize_rewrite(Cell *instps[], PrimNum origs[], int ninsts) |
|
{ |
|
int i,j; |
|
static struct waypoint inst[MAX_BB+1][MAX_STATE]; /* before instruction*/ |
|
static struct waypoint trans[MAX_BB+1][MAX_STATE]; /* before transition */ |
|
int nextdyn, nextstate, no_transition; |
|
|
|
init_waypoints(inst[ninsts]); |
|
inst[ninsts][CANONICAL_STATE].cost=0; |
|
transitions(inst[ninsts],trans[ninsts]); |
for (i=ninsts-1; i>=0; i--) { |
for (i=ninsts-1; i>=0; i--) { |
optimals[i] = origs[i]; |
init_waypoints(inst[i]); |
costs[i] = mincost = costs[i+1] + ss_cost(optimals[i]); |
for (j=1; j<=max_super && i+j<=ninsts; j++) { |
for (j=2; j<=max_super && i+j<=ninsts ; j++) { |
struct super_state **superp = lookup_super(origs+i, j); |
int super, jcost; |
if (superp!=NULL) { |
|
struct super_state *supers = *superp; |
super = lookup_super(origs+i,j); |
for (; supers!=NULL; supers = supers->next) { |
if (super >= 0) { |
PrimNum s = supers->super; |
jcost = costs[i+j] + ss_cost(super); |
int jcost; |
if (jcost <= mincost) { |
struct cost *c=super_costs+s; |
optimals[i] = super; |
struct waypoint *wi=&(inst[i][c->state_in]); |
mincost = jcost; |
struct waypoint *wo=&(trans[i+j][c->state_out]); |
if (!ss_greedy) |
int no_transition = wo->no_transition; |
costs[i] = jcost; |
if (!(is_relocatable(s)) && !wo->relocatable) { |
|
wo=&(inst[i+j][c->state_out]); |
|
no_transition=1; |
|
} |
|
if (wo->cost == INF_COST) |
|
continue; |
|
jcost = wo->cost + ss_cost(s); |
|
if (jcost <= wi->cost) { |
|
wi->cost = jcost; |
|
wi->inst = s; |
|
wi->relocatable = is_relocatable(s); |
|
wi->no_transition = no_transition; |
|
/* if (ss_greedy) wi->cost = wo->cost ? */ |
|
} |
} |
} |
} |
} |
} |
} |
|
transitions(inst[i],trans[i]); |
|
} |
|
/* now rewrite the instructions */ |
|
nextdyn=0; |
|
nextstate=CANONICAL_STATE; |
|
no_transition = ((!trans[0][nextstate].relocatable) |
|
||trans[0][nextstate].no_transition); |
|
for (i=0; i<ninsts; i++) { |
|
Cell tc=0, tc2; |
|
if (i==nextdyn) { |
|
if (!no_transition) { |
|
/* process trans */ |
|
PrimNum p = trans[i][nextstate].inst; |
|
struct cost *c = super_costs+p; |
|
assert(trans[i][nextstate].cost != INF_COST); |
|
assert(c->state_in==nextstate); |
|
tc = compile_prim_dyn(p); |
|
nextstate = c->state_out; |
|
} |
|
{ |
|
/* process inst */ |
|
PrimNum p = inst[i][nextstate].inst; |
|
struct cost *c=super_costs+p; |
|
assert(c->state_in==nextstate); |
|
assert(inst[i][nextstate].cost != INF_COST); |
|
#if defined(GFORTH_DEBUGGING) |
|
assert(p == origs[i]); |
|
#endif |
|
tc2 = compile_prim_dyn(p); |
|
if (no_transition || !is_relocatable(p)) |
|
/* !! actually what we care about is if and where |
|
* compile_prim_dyn() puts NEXTs */ |
|
tc=tc2; |
|
no_transition = inst[i][nextstate].no_transition; |
|
nextstate = c->state_out; |
|
nextdyn += c->length; |
|
} |
|
} else { |
|
#if defined(GFORTH_DEBUGGING) |
|
assert(0); |
|
#endif |
|
tc=0; |
|
/* tc= (Cell)vm_prims[inst[i][CANONICAL_STATE].inst]; */ |
|
} |
|
*(instps[i]) = tc; |
|
} |
|
if (!no_transition) { |
|
PrimNum p = trans[i][nextstate].inst; |
|
struct cost *c = super_costs+p; |
|
assert(c->state_in==nextstate); |
|
assert(trans[i][nextstate].cost != INF_COST); |
|
assert(i==nextdyn); |
|
(void)compile_prim_dyn(p); |
|
nextstate = c->state_out; |
} |
} |
|
assert(nextstate==CANONICAL_STATE); |
} |
} |
|
|
/* rewrite the instructions pointed to by instps to use the |
/* rewrite the instructions pointed to by instps to use the |
superinstructions in optimals */ |
superinstructions in optimals */ |
void rewrite_bb(Cell *instps[], PrimNum *optimals, int ninsts) |
static void rewrite_bb(Cell *instps[], PrimNum *optimals, int ninsts) |
{ |
{ |
int i,j, nextdyn; |
int i,j, nextdyn; |
Cell inst; |
Cell inst; |
Line 1235 void rewrite_bb(Cell *instps[], PrimNum
|
Line 1430 void rewrite_bb(Cell *instps[], PrimNum
|
void compile_prim1(Cell *start) |
void compile_prim1(Cell *start) |
{ |
{ |
#if defined(DOUBLY_INDIRECT) |
#if defined(DOUBLY_INDIRECT) |
Label prim=(Label)*start; |
Label prim; |
|
|
|
if (start==NULL) |
|
return; |
|
prim = (Label)*start; |
if (prim<((Label)(xts+DOESJUMP)) || prim>((Label)(xts+npriminfos))) { |
if (prim<((Label)(xts+DOESJUMP)) || prim>((Label)(xts+npriminfos))) { |
fprintf(stderr,"compile_prim encountered xt %p\n", prim); |
fprintf(stderr,"compile_prim encountered xt %p\n", prim); |
*start=(Cell)prim; |
*start=(Cell)prim; |
Line 1249 void compile_prim1(Cell *start)
|
Line 1448 void compile_prim1(Cell *start)
|
#else /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
#else /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
static Cell *instps[MAX_BB]; |
static Cell *instps[MAX_BB]; |
static PrimNum origs[MAX_BB]; |
static PrimNum origs[MAX_BB]; |
static PrimNum optimals[MAX_BB]; |
|
static int ninsts=0; |
static int ninsts=0; |
PrimNum prim_num; |
PrimNum prim_num; |
|
|
Line 1264 void compile_prim1(Cell *start)
|
Line 1462 void compile_prim1(Cell *start)
|
ninsts++; |
ninsts++; |
if (ninsts >= MAX_BB || superend[prim_num]) { |
if (ninsts >= MAX_BB || superend[prim_num]) { |
end_bb: |
end_bb: |
optimize_bb(origs,optimals,ninsts); |
optimize_rewrite(instps,origs,ninsts); |
rewrite_bb(instps,optimals,ninsts); |
|
ninsts=0; |
ninsts=0; |
} |
} |
#endif /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
#endif /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
Line 1491 UCell convsize(char *s, UCell elemsize)
|
Line 1688 UCell convsize(char *s, UCell elemsize)
|
|
|
enum { |
enum { |
ss_number = 256, |
ss_number = 256, |
|
ss_states, |
ss_min_codesize, |
ss_min_codesize, |
ss_min_ls, |
ss_min_ls, |
ss_min_lsu, |
ss_min_lsu, |
Line 1526 void gforth_args(int argc, char ** argv,
|
Line 1724 void gforth_args(int argc, char ** argv,
|
{"dynamic", no_argument, &no_dynamic, 0}, |
{"dynamic", no_argument, &no_dynamic, 0}, |
{"print-metrics", no_argument, &print_metrics, 1}, |
{"print-metrics", no_argument, &print_metrics, 1}, |
{"ss-number", required_argument, NULL, ss_number}, |
{"ss-number", required_argument, NULL, ss_number}, |
|
{"ss-states", required_argument, NULL, ss_states}, |
#ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
{"ss-min-codesize", no_argument, NULL, ss_min_codesize}, |
{"ss-min-codesize", no_argument, NULL, ss_min_codesize}, |
#endif |
#endif |
Line 1557 void gforth_args(int argc, char ** argv,
|
Line 1756 void gforth_args(int argc, char ** argv,
|
case 'x': debug = 1; break; |
case 'x': debug = 1; break; |
case 'v': fputs(PACKAGE_STRING"\n", stderr); exit(0); |
case 'v': fputs(PACKAGE_STRING"\n", stderr); exit(0); |
case ss_number: static_super_number = atoi(optarg); break; |
case ss_number: static_super_number = atoi(optarg); break; |
|
case ss_states: maxstates = max(min(atoi(optarg),MAX_STATE),1); break; |
#ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
case ss_min_codesize: ss_cost = cost_codesize; break; |
case ss_min_codesize: ss_cost = cost_codesize; break; |
#endif |
#endif |
Line 1590 Engine Options:\n\
|
Line 1790 Engine Options:\n\
|
--ss-min-lsu minimize loads, stores, and pointer updates\n\ |
--ss-min-lsu minimize loads, stores, and pointer updates\n\ |
--ss-min-nexts minimize the number of static superinsts\n\ |
--ss-min-nexts minimize the number of static superinsts\n\ |
--ss-number=N use N static superinsts (default max)\n\ |
--ss-number=N use N static superinsts (default max)\n\ |
|
--ss-states=N N states for stack caching (default max)\n\ |
-v, --version Print engine version and exit\n\ |
-v, --version Print engine version and exit\n\ |
SIZE arguments consist of an integer followed by a unit. The unit can be\n\ |
SIZE arguments consist of an integer followed by a unit. The unit can be\n\ |
`b' (byte), `e' (element; default), `k' (KB), `M' (MB), `G' (GB) or `T' (TB).\n", |
`b' (byte), `e' (element; default), `k' (KB), `M' (MB), `G' (GB) or `T' (TB).\n", |