cvsuser 03/02/21 04:26:43
Modified: languages/imcc ChangeLog cfg.c debug.c debug.h imc.c imc.h
imcc.y instructions.c main.c optimizer.c
optimizer.h parser_util.c pbc.c symreg.h
languages/imcc/t/imcpasm opt1.t
Log:
imcc-opt: s. ChangeLog
Revision Changes Path
1.13 +14 -1 parrot/languages/imcc/ChangeLog
Index: ChangeLog
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/ChangeLog,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -w -r1.12 -r1.13
--- ChangeLog 20 Feb 2003 08:04:12 -0000 1.12
+++ ChangeLog 21 Feb 2003 12:26:39 -0000 1.13
@@ -1,4 +1,17 @@
-- 2003-02-20 leo / Juergen Boemmel
+- 2003-02-21 leo
+
+ * version 0.0.9.15
+ * opimized some ugly quadratic timings in cfg building
+ and branch optimizations by:
+ * build bb_list earlier and use basic blocks
+ This improves e.g. -O2 t/op/stacks_33 from >1m to 2s
+
+ * absolute experimental and early stages for using imcc
+ as JIT optimizer (-Oj) this is broken WRT rx_ops, which
+ have an inout INT param and can branch, and WRT NCI/invoke
+ and probably a lot more.
+
+- 2003-02-20 leo / Juergen Boemmels
* version 0.0.9.14
* macro preprocessor - thanks Juergen Boemmels
1.16 +85 -52 parrot/languages/imcc/cfg.c
Index: cfg.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/cfg.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -w -r1.15 -r1.16
--- cfg.c 20 Feb 2003 08:04:13 -0000 1.15
+++ cfg.c 21 Feb 2003 12:26:39 -0000 1.16
@@ -22,18 +22,40 @@
Basic_block *bb;
Instruction *ins, *lab;
int nu = 0;
+ int i;
init_basic_blocks();
+ for(i = 0; i < HASH_SIZE; i++) {
+ SymReg * r = hash[i];
+ if (r && (r->type & VTADDRESS)) {
+ r->first_ins = r->last_ins = NULL;
+ }
+ }
ins = instructions;
+ ins->index = i = 0;
bb = make_basic_block(ins);
+ if ( (ins->type & ITLABEL)) {
+ /* set the labels address (ins) */
+ ins->r[0]->first_ins = ins;
+ }
+ else if (ins->type & ITBRANCH) {
+ SymReg * addr = get_branch_reg(bb->end);
+ if (addr)
+ addr->last_ins = ins;
+ }
for(ins=ins->next; ins; ins = ins->next) {
+ ins->index = ++i;
bb->end = ins;
ins->bbindex = n_basic_blocks - 1;
/* a LABEL starts a new basic block, but not, if we have
* a new one (last was a branch) */
+ if ( (ins->type & ITLABEL)) {
+ /* set the labels address (ins) */
+ ins->r[0]->first_ins = ins;
+ }
if (nu)
nu = 0;
else if ( (ins->type & ITLABEL)) {
@@ -42,7 +64,11 @@
/* a branch is the end of a basic block
* so start a new with the next ins */
if (ins->type & ITBRANCH) {
+ SymReg * addr = get_branch_reg(bb->end);
int found = 1;
+
+ if (addr)
+ addr->last_ins = ins;
/* if we have a bsr, then consider it only as a branch,
* when we have the target here
* and it doesn't saveall - like P6C recursive bsr's
@@ -51,6 +77,7 @@
char *name =
*ins->op == 'b' ? ins->r[0]->name : ins->r[1]->name;
found = 0;
+ /* TODO get_sym */
for (lab = instructions; lab; lab = lab->next) {
if ((lab->type & ITLABEL) &&
!strcmp(lab->r[0]->name, name)) {
@@ -78,17 +105,12 @@
nu = 1;
}
}
- /* XXX instruction type ITADDR is probably address of a
- * CATCH block - we don't optimize them
- * XXX they are marked as branch, to avoid dead code removal
- * when we are sure, how exception will work, we will see.
- */
- if (ins->type & ITADDR)
- dont_optimize = 1;
}
- if (IMCC_DEBUG & DEBUG_CFG)
+ if (IMCC_DEBUG & DEBUG_CFG) {
dump_instructions();
+ dump_labels();
+ }
}
/* Once the basic blocks have been computed, build_cfg computes
@@ -148,6 +170,10 @@
/* find the placement of the label, and link the two nodes */
void bb_findadd_edge(Basic_block *from, SymReg *label) {
+#if 0
+ /* ugly slow quadratic search for a label takes ~35 s for
+ * ../../t/op/stacks_33
+ */
Instruction *ins;
for (ins = instructions; ins; ins = ins->next) {
@@ -160,6 +186,13 @@
}
}
+#else
+ SymReg *r = get_sym(label->name);
+
+ if (r && (r->type & VTADDRESS) && r->first_ins)
+ bb_add_edge(from, bb_list[r->first_ins->bbindex]);
+
+#endif
}
@@ -543,7 +576,6 @@
sort_loops();
if (IMCC_DEBUG & DEBUG_CFG) {
- dump_instructions();
dump_cfg();
dump_loops();
}
@@ -577,7 +609,8 @@
if (i==0)
debug(DEBUG_CFG,"\tdead code\n");
else
- debug(DEBUG_CFG,"\tcan't determine loop entry block (%d found)\n" ,i);
+ debug(DEBUG_CFG,
+ "\tcan't determine loop entry block (%d found)\n" ,i);
}
loop = set_make(n_basic_blocks);
1.11 +18 -0 parrot/languages/imcc/debug.c
Index: debug.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/debug.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -w -r1.10 -r1.11
--- debug.c 8 Feb 2003 14:41:28 -0000 1.10
+++ debug.c 21 Feb 2003 12:26:39 -0000 1.11
@@ -132,6 +132,24 @@
}
}
+void
+dump_labels()
+{
+ int i;
+
+ fprintf(stderr, "Labels\n");
+ fprintf(stderr, "name\tpos\tlast ref\n"
+ "-----------------------\n");
+ for(i = 0; i < HASH_SIZE; i++) {
+ SymReg * r = hash[i];
+ if (r && (r->type & VTADDRESS))
+ fprintf(stderr, "%s\t%d\t%d\n",
+ r->name,
+ r->first_ins ? r->first_ins->index : -1,
+ r->last_ins ? r->last_ins->index : -1);
+ }
+ fprintf(stderr, "\n");
+}
extern int n_comp_units;
void dump_symreg() {
1.7 +1 -0 parrot/languages/imcc/debug.h
Index: debug.h
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/debug.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -w -r1.6 -r1.7
--- debug.h 7 Feb 2003 14:05:51 -0000 1.6
+++ debug.h 21 Feb 2003 12:26:39 -0000 1.7
@@ -22,6 +22,7 @@
void dump_instructions(void);
void dump_cfg(void);
void dump_loops(void);
+void dump_labels(void);
void dump_symreg(void);
void dump_interference_graph(void);
void dump_dominators(void);
1.35 +169 -24 parrot/languages/imcc/imc.c
Index: imc.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/imc.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -w -r1.34 -r1.35
--- imc.c 20 Feb 2003 08:04:13 -0000 1.34
+++ imc.c 21 Feb 2003 12:26:39 -0000 1.35
@@ -1,4 +1,4 @@
-/* Regsster allocator:
+/* Register allocator:
*
* This is a brute force register allocator. It uses a graph-coloring
* algorithm, but the implementation is very kludgy.
@@ -14,27 +14,18 @@
#include <string.h>
#include "imc.h"
#include "optimizer.h"
+#include "parrot/jit.h"
static void make_stat(int *sets, int *cols);
static void imc_stat_init(void);
static void print_stat(void);
+static void allocate_jit(struct Parrot_Interp *interpreter);
extern int pasm_file;
/* Globals: */
static IMCStack nodeStack;
-/* return the index of a PMC class */
-int get_pmc_num(struct Parrot_Interp *interp, char *pmc_type)
-{
- STRING * s = string_make(interp, pmc_type,
- (UINTVAL) strlen(pmc_type), NULL, 0, NULL);
- PMC * key = key_new_string(interp, s);
- PMC * cnames = interp->Parrot_base_classname_hash;
-
- return cnames->vtable->get_integer_keyed(interp, cnames, key);
-}
-
/* allocate is the main loop of the allocation algorithm */
void allocate(struct Parrot_Interp *interpreter) {
int to_spill;
@@ -64,14 +55,14 @@
while (todo) {
info(2, "find_basic_blocks\n");
find_basic_blocks();
+ todo = cfg_optimize(interpreter);
+ }
+ todo = 1;
+ while (todo) {
+ find_basic_blocks();
info(2, "build_cfg\n");
- build_cfg();
- if (!dont_optimize && dead_code_remove()) {
- info(2, "pre_optimize\n");
- pre_optimize(interpreter);
- continue;
- }
+ build_cfg();
info(2, "compute_dominators\n");
compute_dominators();
@@ -82,9 +73,7 @@
build_reglist();
info(2, "life_analysis\n");
life_analysis();
- /* optimize, as long as there is something to do -
- * but not, if we found a set_addr, which means
- * we have probably a CATCH handler */
+ /* optimize, as long as there is something to do */
if (IMCC_DEBUG & DEBUG_IMC)
dump_symreg();
if (dont_optimize)
@@ -116,6 +105,11 @@
}
if (IMCC_DEBUG & DEBUG_IMC)
dump_instructions();
+ if (optimizer_level & OPT_J) {
+ allocate_jit(interpreter);
+ if (IMCC_DEBUG & DEBUG_IMC)
+ dump_instructions();
+ }
if (IMCC_VERBOSE > 1 || (IMCC_DEBUG & DEBUG_IMC))
print_stat();
free_reglist();
@@ -239,7 +233,9 @@
reglist[count++] = r->reg;
else
reglist[count++] = r;
- /* rearange I registers */
+ /* rearange I/N registers
+ * XXX not here, do it, when reading the source
+ * .nciarg, rx_char, ... !!!1 */
if ((optimizer_level & OPT_PASM) && pasm_file &&
(reglist[count-1]->set == 'I' ||
reglist[count-1]->set == 'N'))
@@ -376,8 +372,11 @@
depth = bb_list[ins->bbindex]->loop_depth;
- for (i = 0; ins->r[i] && i < IMCC_MAX_REGS; i++)
+ for (i = 0; ins->r[i] && i < IMCC_MAX_REGS; i++) {
ins->r[i]->score += 1 << (depth * 3);
+ if (ins->flags & ITSPILL)
+ ins->r[i]->score = 50000000;
+ }
}
@@ -447,6 +446,9 @@
* Returns if it has been able to delete at least one node
* and 0 otherwise.
*
+ * XXX: this doesn't look at score, so I think this is bogus
+ * - currently disabled
+ *
*/
int simplify (){
@@ -531,7 +533,7 @@
void restore_interference_graph() {
int i;
for (i=0; i < n_symbols; i++) {
- if (reglist[i]->type & VTPASM)
+ if ((reglist[i]->type & VTPASM) && !(optimizer_level & OPT_PASM))
continue;
reglist[i]->color = -1;
reglist[i]->simplified = 0;
@@ -723,6 +725,149 @@
return cnt;
}
+/* PASM registers are already in most used order, so now:
+ * - consider the top N registers as processor registers
+ * - look at the instruction stream and insert register load/store ins
+ * for e.g. calling out to unJITted functions
+ * This is of course processor dependend
+ *
+ * TODO: rx_ ops may have a inout INT parameter for position/mark.
+ * Do not assign registers, if any such inout branching
+ * instruction is encountered.
+ */
+
+static void
+allocate_jit(struct Parrot_Interp *interpreter)
+{
+ int i, j, f, k;
+/* int to_map[] = { INT_REGISTERS_TO_MAP, 0, 0,
+ * FLOAT_REGISTERS_TO_MAP };
+ * XXX communicate these with jit_emit.h
+ */
+ int to_map[] = { 4, 0, 0, 4 };
+ const char *types = "IPSN";
+ Instruction * ins, *next, *last, *tmp, *prev;
+ SymReg * r, *cpu[4+4], *regs[IMCC_MAX_REGS]; /* XXX */
+ int reads[4+4], writes[4+4], nr, nw;
+ static SymReg *par[4+4]; /* XXX */
+ static int ncpu;
+
+ for (j = 0; j < ncpu; j++)
+ free(par[j]);
+ for(i = ncpu = 0; i < HASH_SIZE; i++) {
+ r = hash[i];
+ /* Add each mapped register to cpu reglist */
+ for(; r; r = r->next) {
+ if ((r->type & VTREGISTER) && r->set != 'K') {
+ if (r->color >= 0 &&
+ r->color < to_map[strchr(types, r->set) - types]) {
+ r->color = -1 - r->color;
+ cpu[ncpu++] = r;
+ }
+ }
+ }
+ }
+ /* generate a list of parrot registers */
+ for (j = 0; j < ncpu; j++) {
+ par[j] = malloc(sizeof(SymReg));
+ memcpy(par[j], cpu[j], sizeof(SymReg));
+ par[j]->color = -1 - cpu[j]->color;
+ }
+ prev = last = NULL;
+ nr = nw = 0;
+ for (ins = instructions; ins; prev = ins, ins = ins->next) {
+ if (ins->opnum >= 0 &&
+ op_jit[ins->opnum].extcall == 1) { /* XXX i386 */
+ for (k = 0; k < ncpu; k++)
+ reads[k] = writes[k] = 999;
+ /* TODO non preserved regs */
+ for (last = next = ins;
+ next && op_jit[next->opnum].extcall == 1;
+ next = next->next) {
+ for (j = 0; j < ncpu; j++) {
+ if (instruction_reads(next, cpu[j]) &&
+ instruction_writes(next, cpu[j])) {
+ /* or set reads[j] - could be faster */
+ for (k = f = 0; k < nr; k++) {
+ if (reads[k] == j) {
+ f = 1;
+ break;
+ }
+ }
+ if (!f)
+ reads[nr++] = j;
+ for (k = f = 0; k < nr; k++) {
+ if (writes[k] == j) {
+ f = 1;
+ break;
+ }
+ }
+ if (!f)
+ writes[nw++] = j;
+ for (k = 0; next->r[k] && k < IMCC_MAX_REGS; k++)
+ if (next->r[k] == cpu[j])
+ next->r[k] = par[j];
+ }
+ else if (instruction_reads(next, cpu[j])) {
+ for (k = f = 0; k < nr; k++) {
+ if (reads[k] == j) {
+ f = 1;
+ break;
+ }
+ }
+ if (!f)
+ reads[nr++] = j;
+ for (k = 0; next->r[k] && k < IMCC_MAX_REGS; k++)
+ if (next->r[k] == cpu[j])
+ next->r[k] = par[j];
+ }
+ else if (instruction_writes(next, cpu[j])) {
+ for (k = 0; next->r[k] && k < IMCC_MAX_REGS; k++)
+ if (next->r[k] == cpu[j])
+ next->r[k] = par[j];
+ for (k = f = 0; k < nr; k++) {
+ if (writes[k] == j) {
+ f = 1;
+ break;
+ }
+ }
+ if (!f)
+ writes[nw++] = j;
+ }
+ }
+ /* remember last extern opcode, all loads are inserted
+ * after this instruction
+ */
+ if (next->type & ITBRANCH) {
+ break;
+ }
+ last = next;
+ }
+ }
+ /* insert load ins after non JIT block */
+ if (last && nw) {
+ for ( ; nw ; nw--) {
+ j = writes[nw-1];
+ regs[0] = cpu[j];
+ regs[1] = par[j];
+ tmp = INS(interpreter, "set", "%s, %s\t# load",
+ regs, 2, 0, 0);
+ insert_ins(last, tmp);
+ }
+ last = NULL;
+ }
+ /* insert save ins before extern op */
+ if (nr) {
+ for ( ; nr ; nr--) {
+ j = reads[nr-1];
+ regs[0] = par[j];
+ regs[1] = cpu[j];
+ tmp = INS(interpreter, "set", "%s, %s\t# save", regs, 2, 0, 0);
+ insert_ins(prev, tmp);
+ }
+ }
+ }
+}
/*
* Utility functions
1.28 +1 -0 parrot/languages/imcc/imc.h
Index: imc.h
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/imc.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -w -r1.27 -r1.28
--- imc.h 20 Feb 2003 08:04:13 -0000 1.27
+++ imc.h 21 Feb 2003 12:26:39 -0000 1.28
@@ -79,6 +79,7 @@
EXTERN int line; /* and line */
EXTERN int optimizer_level;
EXTERN int dont_optimize;
+EXTERN int has_compile;
enum {
OPT_NONE,
1.47 +5 -1 parrot/languages/imcc/imcc.y
Index: imcc.y
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/imcc.y,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -w -r1.46 -r1.47
--- imcc.y 18 Feb 2003 12:39:17 -0000 1.46
+++ imcc.y 21 Feb 2003 12:26:40 -0000 1.47
@@ -365,6 +365,9 @@
/* XXX probably a CATCH block */
ins->type = ITADDR | IF_r1_branch | ITBRANCH;
}
+ else if (!strcmp(name, "compile"))
+ ++has_compile;
+
if (emit)
emitb(ins);
} else {
@@ -439,7 +442,8 @@
emit:
EMIT { open_comp_unit(); }
pasmcode
- EOM { emit_flush(interp); $$=0;}
+ EOM { allocate(interp);
+ emit_flush(interp); $$=0;}
;
1.27 +25 -7 parrot/languages/imcc/instructions.c
Index: instructions.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/instructions.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -w -r1.26 -r1.27
--- instructions.c 20 Feb 2003 08:04:13 -0000 1.26
+++ instructions.c 21 Feb 2003 12:26:40 -0000 1.27
@@ -229,7 +229,16 @@
void insert_ins(Instruction *ins, Instruction * tmp)
{
- Instruction *next = ins->next;
+ Instruction *next;
+ if (!ins) {
+ next = instructions;
+ instructions = tmp;
+ tmp->next = next;
+ next->prev = tmp;
+ tmp->line = next->line;
+ }
+ else {
+ next = ins->next;
ins->next = tmp;
tmp->prev = ins;
tmp->next = next;
@@ -237,6 +246,7 @@
if (!tmp->line)
tmp->line = ins->line;
}
+}
/*
* subst tmp for ins
@@ -316,12 +326,19 @@
sprintf(regb[i], "%c%d", p->set, p->color);
regstr[i] = regb[i];
}
+ else if (p->set != 'K' && p->color < 0 && (p->type & VTREGISTER)) {
+ sprintf(regb[i], "r%c%d", tolower(p->set), -1 - p->color);
+ regstr[i] = regb[i];
+ }
else if (p->type & VTREGKEY) {
SymReg * k = p->nextkey;
for (*regb[i] = '\0'; k; k = k->nextkey) {
if (k->reg && k->reg->color >= 0)
sprintf(regb[i]+strlen(regb[i]), "%c%d",
k->reg->set, k->reg->color); /* XXX */
+ else if (k->reg && k->reg->color < 0)
+ sprintf(regb[i]+strlen(regb[i]), "r%c%d",
+ tolower(k->reg->set), -1 - k->reg->color);
else
strcat(regb[i], k->name); /* XXX */
if (k->nextkey)
@@ -410,6 +427,7 @@
int emit_open(int type, void *param)
{
emitter = type;
+ has_compile = 0;
return (emitters[emitter]).open(param);
return 0;
}
1.18 +2 -2 parrot/languages/imcc/main.c
Index: main.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/main.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -w -r1.17 -r1.18
--- main.c 20 Feb 2003 08:04:13 -0000 1.17
+++ main.c 21 Feb 2003 12:26:40 -0000 1.18
@@ -19,7 +19,7 @@
#include "pbc.h"
#include "parser.h"
-#define IMCC_VERSION "0.0.9.14"
+#define IMCC_VERSION "0.0.9.15"
static int run_pbc, write_pbc;
static char optimizer_opt[20];
@@ -210,7 +210,7 @@
if (strchr(optimizer_opt, '2'))
optimizer_level |= (OPT_CFG | OPT_PRE);
if (strchr(optimizer_opt, 'j'))
- optimizer_level |= OPT_J;
+ optimizer_level |= (OPT_J | OPT_PASM);
if (strchr(optimizer_opt, 'p'))
optimizer_level |= OPT_PASM;
}
1.18 +125 -81 parrot/languages/imcc/optimizer.c
Index: optimizer.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/optimizer.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -w -r1.17 -r1.18
--- optimizer.c 20 Feb 2003 08:04:13 -0000 1.17
+++ optimizer.c 21 Feb 2003 12:26:40 -0000 1.18
@@ -45,8 +45,11 @@
*
*/
static void if_branch(struct Parrot_Interp *);
-static void branch_branch(void);
-static void unused_label(void);
+
+static int branch_branch(void);
+static int unused_label(void);
+static int dead_code_remove(void);
+
static void strength_reduce(struct Parrot_Interp *interp);
static void subst_constants_mix(struct Parrot_Interp *interp);
static void subst_constants_umix(struct Parrot_Interp *interp);
@@ -59,7 +62,7 @@
static int clone_remove(void);
void pre_optimize(struct Parrot_Interp *interp) {
- if (optimizer_level & OPT_PRE) { /* XXX */
+ if (optimizer_level & OPT_PRE) {
subst_constants_mix(interp);
subst_constants_umix(interp);
subst_constants(interp);
@@ -67,10 +70,21 @@
subst_constants_if(interp);
strength_reduce(interp);
if_branch(interp);
- branch_branch();
+ }
+}
+
+int cfg_optimize(struct Parrot_Interp *interp) {
+ UNUSED(interp);
+ if (optimizer_level & OPT_PRE) {
+ if (branch_branch())
+ return 1;
/* XXX cfg / loop detection breaks e.g. in t/compiler/5_3 */
- unused_label();
+ if (unused_label())
+ return 1;
+ if (dead_code_remove())
+ return 1;
}
+ return 0;
}
int optimize(struct Parrot_Interp *interp) {
@@ -127,6 +141,7 @@
last = instructions;
if (!last->next)
return;
+ info(2, "\tif_branch\n");
for (ins = last->next; ins; ) {
if ((last->type & ITBRANCH) && /* if ...L1 */
(ins->type & IF_goto) && /* branch L2*/
@@ -163,81 +178,6 @@
ins = ins->next;
}
}
-
-/*
- * branch L1 => branch L2
- * ...
- * L1:
- * branch L2
- *
- */
-static void branch_branch()
-{
- Instruction *ins1, *ins2, *next;
-
- /* reset statistic globals */
- ostat.branch_branch = 0;
- for (ins1 = 0, ins1 = instructions; ins1; ins1 = ins1->next) {
- if ((ins1->type & IF_goto) && !strcmp(ins1->op, "branch")) {
- for (ins2 = 0, ins2 = instructions; ins2; ins2 = ins2->next) {
- if ((ins2->type & ITLABEL) &&
- !strcmp(ins1->r[0]->name, ins2->r[0]->name)) {
- next = ins2->next;
- if (!next)
- break;
- if ((next->type & IF_goto) &&
- !strcmp(next->op, "branch")) {
- debug(DEBUG_OPT1, "found branch to branch '%s' %s\n",
- ins2->r[0]->name, ins_string(next));
- ostat.branch_branch++;
- ins1->r[0] = next->r[0];
- }
- }
- }
- }
- }
-
-}
-
-static void unused_label()
-{
- Instruction *ins, *ins2, *last;
- SymReg * addr;
- int used;
-
- for (last = 0, ins = instructions; ins; ins = ins->next) {
- if ((ins->type & ITLABEL) && *ins->r[0]->name != '_') {
- SymReg * lab = ins->r[0];
- used = 0;
- for (ins2 = instructions; ins2; ins2 = ins2->next) {
- if ((addr = get_branch_reg(ins2)) != 0) {
- if (addr == lab && addr->type == VTADDRESS) {
- used = 1;
- break;
- }
- }
- /* if we have compile/eval, we don't know, if this
- * label might be used
- */
- else if (!strcmp(ins2->op, "compile")) {
- used = 1;
- break;
- }
- }
- if (!used && last) {
- ostat.deleted_labels++;
- debug(DEBUG_OPT1, "label %s deleted\n", lab->name);
- ostat.deleted_ins++;
- delete_ins(ins, 1);
- last = ins;
- continue;
- }
-
- }
- last = ins;
- }
-}
-
/* these are run after constant simplification, so it is
* guaranteed, that one operand is non constant, if opsize == 4
*/
@@ -248,6 +188,7 @@
int i, found;
SymReg *r;
+ info(2, "\tstrength_reduce\n");
for (ins = instructions; ins; ins = ins->next) {
/*
* add Ix, Ix, Iy => add Ix, Iy
@@ -356,6 +297,7 @@
char b[128];
SymReg *r;
+ info(2, "\tsubst_constants_mix\n");
for (ins = instructions; ins; ins = ins->next) {
for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
/* TODO compare ins->opnum with a list of instructions
@@ -393,6 +335,7 @@
char b[128];
SymReg *r;
+ info(2, "\tsubst_constants_umix\n");
for (ins = instructions; ins; ins = ins->next) {
for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
/* TODO compare ins->opnum with a list of instructions
@@ -494,6 +437,7 @@
int found;
/* save interpreter ctx */
+ info(2, "\tsubst_constants\n");
ctx = mem_sys_allocate(sizeof(struct Parrot_Context));
mem_sys_memcopy(ctx, &interp->ctx, sizeof(struct Parrot_Context));
/* construct a FLOATVAL_FMT with needed precision */
@@ -574,6 +518,7 @@
size_t i;
int res;
+ info(2, "\tsubst_constants_c\n");
for (ins = instructions; ins; ins = ins->next) {
for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
/* TODO s. above */
@@ -711,6 +656,7 @@
int res;
char *s;
+ info(2, "\tsubst_constants_if\n");
for (ins = instructions; ins; ins = ins->next) {
for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
/* TODO s. above */
@@ -761,7 +707,104 @@
/* optimizations with CFG built */
-int dead_code_remove(void)
+
+/*
+ * branch L1 => branch L2
+ * ...
+ * L1:
+ * branch L2
+ *
+ */
+static int branch_branch()
+{
+ Instruction *ins, *next;
+ SymReg * r;
+
+ info(2, "\tbranch_branch\n");
+ /* reset statistic globals */
+ ostat.branch_branch = 0;
+ for (ins = instructions; ins; ins = ins->next) {
+ if ((ins->type & IF_goto) && !strcmp(ins->op, "branch")) {
+ r = get_sym(ins->r[0]->name);
+
+ if (r && (r->type & VTADDRESS) && r->first_ins) {
+ next = r->first_ins->next;
+ if (!next)
+ break;
+ if ((next->type & IF_goto) &&
+ !strcmp(next->op, "branch")) {
+ debug(DEBUG_OPT1, "found branch to branch '%s' %s\n",
+ r->first_ins->r[0]->name, ins_string(next));
+ ostat.branch_branch++;
+ ins->r[0] = next->r[0];
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int unused_label()
+{
+ Instruction *ins;
+ int used;
+ int i;
+
+ info(2, "\tunused_label\n");
+ for (i=1; bb_list[i]; i++) {
+ ins = bb_list[i]->start;
+ if ((ins->type & ITLABEL) && *ins->r[0]->name != '_') {
+ SymReg * lab = ins->r[0];
+ used = 0;
+ if (has_compile)
+ used = 1;
+#if 1
+ else if (lab->last_ins)
+ used = 1;
+#else
+ else {
+ Instruction *ins2;
+ int j;
+ SymReg * addr;
+ for (j=0; bb_list[j]; j++) {
+ /* a branch can be the first ins in a block
+ * (if prev ins was a label)
+ * or the last ins in a block
+ */
+ ins2 = bb_list[j]->start;
+ if ((ins2->type & ITBRANCH) &&
+ (addr = get_branch_reg(ins2)) != 0) {
+ if (addr == lab && addr->type == VTADDRESS) {
+ used = 1;
+ break;
+ }
+ }
+ ins2 = bb_list[j]->end;
+ if ((ins2->type & ITBRANCH) &&
+ (addr = get_branch_reg(ins2)) != 0) {
+ if (addr == lab && addr->type == VTADDRESS) {
+ used = 1;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if (!used) {
+ ostat.deleted_labels++;
+ debug(DEBUG_OPT1, "label %s deleted\n", lab->name);
+ ostat.deleted_ins++;
+ delete_ins(ins, 1);
+ return 1;
+ }
+
+ }
+ }
+ return 0;
+}
+
+static int dead_code_remove(void)
{
Basic_block *bb;
int i;
@@ -771,6 +814,7 @@
/* this could be a separate level, now it's done with -O1 */
if (!(optimizer_level & OPT_PRE))
return 0;
+ info(2, "\tdead_code_remove\n");
for (i=1; bb_list[i]; i++) {
bb = bb_list[i];
if ((bb->start->type & ITLABEL) && *bb->start->r[0]->name == '_')
1.6 +1 -1 parrot/languages/imcc/optimizer.h
Index: optimizer.h
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/optimizer.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -w -r1.5 -r1.6
--- optimizer.h 8 Feb 2003 17:16:16 -0000 1.5
+++ optimizer.h 21 Feb 2003 12:26:40 -0000 1.6
@@ -1,7 +1,7 @@
#ifndef __OPTIMIZER_H
#define __OPTIMIZER_H
void pre_optimize(struct Parrot_Interp *);
-int dead_code_remove(void);
+int cfg_optimize(struct Parrot_Interp *);
int optimize(struct Parrot_Interp *);
void post_optimize(struct Parrot_Interp *);
1.10 +11 -0 parrot/languages/imcc/parser_util.c
Index: parser_util.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/parser_util.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -w -r1.9 -r1.10
--- parser_util.c 17 Feb 2003 13:56:36 -0000 1.9
+++ parser_util.c 21 Feb 2003 12:26:40 -0000 1.10
@@ -195,6 +195,17 @@
string_make(interp, "pIt", 3, NULL,0,NULL));
}
+/* return the index of a PMC class */
+int get_pmc_num(struct Parrot_Interp *interp, char *pmc_type)
+{
+ STRING * s = string_make(interp, pmc_type,
+ (UINTVAL) strlen(pmc_type), NULL, 0, NULL);
+ PMC * key = key_new_string(interp, s);
+ PMC * cnames = interp->Parrot_base_classname_hash;
+
+ return cnames->vtable->get_integer_keyed(interp, cnames, key);
+}
+
/*
* Local variables:
* c-indentation-style: bsd
1.28 +0 -3 parrot/languages/imcc/pbc.c
Index: pbc.c
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/pbc.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -w -r1.27 -r1.28
--- pbc.c 20 Feb 2003 08:04:13 -0000 1.27
+++ pbc.c 21 Feb 2003 12:26:40 -0000 1.28
@@ -229,7 +229,6 @@
Instruction * ins;
int code_size;
opcode_t pc;
- int has_compile = 0;
/* run through instructions,
* 1. pass
@@ -267,8 +266,6 @@
else if (!strcmp(ins->op, "set_addr"))
store_bsr(ins->r[1], pc, 2);
}
- else if (!strcmp(ins->op, "compile"))
- ++has_compile;
pc += ins->opsize;
}
1.14 +2 -1 parrot/languages/imcc/symreg.h
Index: symreg.h
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/symreg.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -w -r1.13 -r1.14
--- symreg.h 21 Jan 2003 10:11:31 -0000 1.13
+++ symreg.h 21 Feb 2003 12:26:40 -0000 1.14
@@ -49,7 +49,7 @@
enum USAGE usage; /* s. USAGE above */
char set; /* Which register set/file it belongs to */
int color; /* Color: parrot register number
- and parrot const table index vof VTCONST*/
+ and parrot const table index of VTCONST*/
int score; /* How costly is to spill this symbol */
int use_count; /* how often is this sym used */
int lhs_use_count; /* how often is this sym written to */
@@ -58,6 +58,7 @@
struct _SymReg * next; /* used in the symbols hash */
struct _Instruction * first_ins; /* first and last instruction */
struct _Instruction * last_ins; /* this symbol is in */
+ /* also used by labels as position of label and last reference */
struct _SymReg * nextkey; /* keys */
struct _SymReg * reg; /* key->register for VTREGKEYs */
} SymReg;
1.6 +12 -12 parrot/languages/imcc/t/imcpasm/opt1.t
Index: opt1.t
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/t/imcpasm/opt1.t,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -w -r1.5 -r1.6
--- opt1.t 17 Feb 2003 15:10:57 -0000 1.5
+++ opt1.t 21 Feb 2003 12:26:43 -0000 1.6
@@ -165,18 +165,6 @@
OUT
##############################
-SKIP: {
-skip("constant concat N/Y", 1);
-output_is(<<'CODE', <<'OUT', "constant concat");
- concat S0, "Parrot ", "rocks"
- end
-CODE
- set S0, "Parrot rocks"
- end
-OUT
-}
-
-##############################
output_is(<<'CODE', <<'OUT', "constant eq taken");
eq 10, 10, L1
set I0, 5
@@ -526,4 +514,16 @@
end
OUT
+
+##############################
+SKIP: {
+skip("constant concat N/Y", 1);
+output_is(<<'CODE', <<'OUT', "constant concat");
+ concat S0, "Parrot ", "rocks"
+ end
+CODE
+ set S0, "Parrot rocks"
+ end
+OUT
+}