diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index ccc180540..9a87a341b 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -1,39 +1,92 @@ #include "mcg.h" +static char outbuf[256]; +static struct hop* current_hop; + +static const struct burm_emitter_data emitter_data; + struct hop* new_hop(int insn_no, struct ir* ir) { struct hop* hop = calloc(1, sizeof *hop); hop->insn_no = insn_no; hop->ir = ir; + return hop; } -static void add_reg(struct vreg* vregs[], struct vreg* vreg) +static void append(const char* fmt, ...) { - int i; - - for (i=0; iinvregs, vreg); + struct hop* hop = ir->hop; + if (hop) + { + /* Reference to another hop must be its result register. */ + append("%%%d", hop->resultvreg->id); + } + else + { + /* ...if there is no hop, it's a fragment. */ + const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no]; + insndata->emitter(ir, &emitter_data); + } } -void hop_add_out_reg(struct hop* hop, struct vreg* vreg) +static void emit_string(const char* data) { - add_reg(hop->outvregs, vreg); + append("%s", data); } -void hop_emit(struct hop* hop, const struct burm_emitter_data* ed) +static void emit_value(struct ir* ir) { + append("(val)"); +} + +static void emit_resultreg(void) +{ + append("%%%d", current_hop->resultvreg->id); +} + +static void emit_eoi(void) +{ + append("\n"); +} + +static const struct burm_emitter_data emitter_data = +{ + &emit_string, + &emit_reg, + &emit_value, + &emit_resultreg, + &emit_eoi +}; + +void hop_print(char k, struct hop* hop) +{ + char* s; const struct burm_instruction_data* insndata = &burm_instruction_data[hop->insn_no]; - insndata->emitter(hop->ir, ed); + + current_hop = hop; + outbuf[0] = 0; + if (insndata->emitter) + { + insndata->emitter(hop->ir, &emitter_data); + + s = strtok(outbuf, "\n"); + do + { + tracef(k, "%c: %p: %s\n", k, hop, s); + s = strtok(NULL, "\n"); + } + while (s); + } + else + tracef(k, "%c: %p: (empty)\n", k, hop); } diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index d6cc6e79d..2cb0c9f72 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -1,26 +1,20 @@ #ifndef HOP_H #define HOP_H -struct vreg -{ - int id; - int regclass; -}; - -#define HOP_INOUT_REGS 4 - struct hop { int insn_no; struct ir* ir; - struct vreg* invregs[HOP_INOUT_REGS]; - struct vreg* outvregs[HOP_INOUT_REGS]; + struct vreg* resultvreg; + ARRAYOF(struct vreg) invregs; + ARRAYOF(struct vreg) outvregs; + ARRAYOF(struct vreg) newvregs; + ARRAYOF(struct vreg) deadvregs; }; extern struct hop* new_hop(int insn_no, struct ir* ir); -extern void hop_add_in_reg(struct hop* hop, struct vreg* reg); -extern void hop_add_out_reg(struct hop* hop, struct vreg* reg); +extern void hop_print(char k, struct hop* hop); #endif diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index 79dbfdb8f..f63272a6c 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -20,8 +20,8 @@ struct ir } u; void* state_label; /* used by the iburg instruction selector */ - int insn_no; - int vreg; + int insn_no; /* the table rule number for this instruction */ + struct hop* hop; /* only for IRs that root a hardware op */ bool is_sequence : 1; bool is_generated : 1; diff --git a/mach/proto/mcg/main.c b/mach/proto/mcg/main.c index 83d510107..c17b60bb0 100644 --- a/mach/proto/mcg/main.c +++ b/mach/proto/mcg/main.c @@ -41,7 +41,8 @@ bool tracing(char k) case 'E': return false; case '0': return false; case '1': return false; - case '2': return true; + case '2': return false; + case 'I': return true; default: return true; } } diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 8cf16f952..746f3924c 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -20,6 +20,7 @@ #include "map.h" #include "ir.h" #include "mcgg.h" +#include "vreg.h" #include "hop.h" extern char em_pseu[][4]; diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 9d17c06e3..a2a993c82 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -1,29 +1,6 @@ #include "mcg.h" -static int vregcount; - -#if 0 -static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) { -#ifdef TRACE - int eruleno = burm_rule(STATE_LABEL(p), goalnt); - const short *nts = burm_nts[eruleno]; - NODEPTR_TYPE kids[10]; - int i; - - for (i = 0; i < indent; i++) - fprintf(stderr, " "); - fprintf(stderr, "%s\n", burm_string[eruleno]); - burm_kids(p, eruleno, kids); - for (i = 0; nts[i]; i++) - { - if (kids[i]) - dumpCover(kids[i], nts[i], indent + 1); - else - fprintf(stderr, "failed!\n"); - } -#endif -} -#endif +static struct basicblock* current_bb; void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) { const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno]; @@ -39,72 +16,30 @@ void burm_panic_cannot_match(struct ir* ir) exit(1); } -static const struct burm_emitter_data emitter_data; - -static void emit_string(const char* data) -{ - tracef('I', "I: emit: %s\n", data); -} - -static void emit_reg(struct ir* ir) -{ - const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no]; - if (insndata->is_fragment) - insndata->emitter(ir, &emitter_data); - else - tracef('I', "I: emit reg %d\n", ir->vreg); -} - -static void emit_value(struct ir* ir) -{ - tracef('I', "I: emit value\n"); -} - -static void emit_resultreg(void) -{ - tracef('I', "I: emit resultreg\n"); -} - -static void emit_eoi(void) -{ - tracef('I', "I: emit eoi\n"); -} - -static const struct burm_emitter_data emitter_data = -{ - &emit_string, - &emit_reg, - &emit_value, - &emit_resultreg, - &emit_eoi -}; - -static void walk_instructions(struct ir* ir, int goal) +static void walk_instructions(struct hop* hop, struct ir* ir, int goal) { struct ir* children[10]; int insn_no = burm_rule(ir->state_label, goal); const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no]; const short* nts = burm_nts[insn_no]; int i; - int resultreg = 0; - + ir->insn_no = insn_no; + if (!insndata->is_fragment) + hop = ir->hop = new_hop(insn_no, ir);; if (insndata->allocate) { - resultreg = vregcount++; - tracef('I', "I: new %s %d\n", - burm_register_class_names[insndata->allocate], resultreg); + hop->resultvreg = new_vreg(); + array_append(&hop->newvregs, hop->resultvreg); + array_append(&hop->outvregs, hop->resultvreg); } burm_kids(ir, insn_no, children); for (i=0; nts[i]; i++) - walk_instructions(children[i], nts[i]); + walk_instructions(hop, children[i], nts[i]); - if (ir->vreg) - tracef('I', "I: use %d\n", ir->vreg); - if (resultreg) - ir->vreg = resultreg; + ir->is_generated = true; tracef('I', "I: $%d %s selected %s %d: %s\n", ir->id, @@ -112,30 +47,33 @@ static void walk_instructions(struct ir* ir, int goal) insndata->is_fragment ? "fragment" : "instruction", insn_no, insndata->name); - ir->is_generated = true; - if (!insndata->is_fragment && insndata->emitter) - insndata->emitter(ir, &emitter_data); + if (!insndata->is_fragment) + { + array_append(¤t_bb->hops, hop); + hop_print('I', hop); + } } -static void select_instructions(struct basicblock* bb) +static void select_instructions(void) { int i; - tracef('I', "I: BLOCK: %s\n", bb->name); + tracef('I', "I: BLOCK: %s\n", current_bb->name); - for (i=0; iirs.count; i++) + for (i=0; iirs.count; i++) { int insnno; - struct ir* ir = bb->irs.item[i]; + struct ir* ir = current_bb->irs.item[i]; burm_label(ir); insnno = burm_rule(ir->state_label, 1); if (!insnno) burm_panic_cannot_match(ir); - walk_instructions(ir, 1); + ir_print('I', ir); + walk_instructions(NULL, ir, 1); } } @@ -143,12 +81,10 @@ void pass_instruction_selector(struct procedure* proc) { int i; - vregcount = 1; - for (i=0; iblocks.count; i++) { - struct basicblock* bb = proc->blocks.item[i]; - select_instructions(bb); + current_bb = proc->blocks.item[i]; + select_instructions(); } } diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index d450842aa..f0303a442 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -102,7 +102,7 @@ PATTERNS CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4)) emit "beq $true" - emit "bne $false" + emit "b $false" cost 8; diff --git a/mach/proto/mcg/vreg.c b/mach/proto/mcg/vreg.c new file mode 100644 index 000000000..c841822f8 --- /dev/null +++ b/mach/proto/mcg/vreg.c @@ -0,0 +1,10 @@ +#include "mcg.h" + +static int vreg_count = 0; + +struct vreg* new_vreg(void) +{ + struct vreg* vreg = calloc(1, sizeof *vreg); + vreg->id = vreg_count++; + return vreg; +} diff --git a/mach/proto/mcg/vreg.h b/mach/proto/mcg/vreg.h new file mode 100644 index 000000000..b764d3883 --- /dev/null +++ b/mach/proto/mcg/vreg.h @@ -0,0 +1,13 @@ +#ifndef VREG_H +#define VREG_H + +struct vreg +{ + int id; +}; + +extern struct vreg* new_vreg(void); + +#endif + +