From 4572f1b774478332d3c38c71315637dd01f4b8bf Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 27 Sep 2016 23:38:47 +0200 Subject: [PATCH] Actually, I don't need vregs: hops work just as well. Particularly if I restructure things so that I don't need to walk the blasted ir / burg tree every time I look at an instruction. --- mach/proto/mcg/build.lua | 1 - mach/proto/mcg/hop.c | 118 ++++++++++++--------- mach/proto/mcg/hop.h | 34 +++++- mach/proto/mcg/mcg.h | 1 - mach/proto/mcg/pass_instructionselection.c | 68 ++++++++++-- mach/proto/mcg/table | 15 +++ mach/proto/mcg/vreg.c | 10 -- mach/proto/mcg/vreg.h | 13 --- 8 files changed, 166 insertions(+), 94 deletions(-) delete mode 100644 mach/proto/mcg/vreg.c delete mode 100644 mach/proto/mcg/vreg.h diff --git a/mach/proto/mcg/build.lua b/mach/proto/mcg/build.lua index dc3504294..0626c4a3c 100644 --- a/mach/proto/mcg/build.lua +++ b/mach/proto/mcg/build.lua @@ -28,7 +28,6 @@ cprogram { vars = { ["+cflags"] = { "-Werror-implicit-function-declaration", - "-Wint-conversion" } } } diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 9a87a341b..510190c70 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -1,6 +1,6 @@ #include "mcg.h" -static char outbuf[256]; +static int hop_count = 1; static struct hop* current_hop; static const struct burm_emitter_data emitter_data; @@ -8,85 +8,97 @@ 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->id = hop_count++; hop->insn_no = insn_no; hop->ir = ir; return hop; } -static void append(const char* fmt, ...) +static struct insel* new_insel(enum insel_type type) { - va_list ap; - - va_start(ap, fmt); - vsprintf(outbuf + strlen(outbuf), fmt, ap); - va_end(ap); + struct insel* insel = calloc(1, sizeof(*insel)); + insel->type = type; + return insel; } -static void emit_reg(struct ir* ir) +void hop_add_string_insel(struct hop* hop, const char* string) { - 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); - } + struct insel* insel = new_insel(INSEL_STRING); + insel->u.string = string; + array_append(&hop->insels, insel); } -static void emit_string(const char* data) +void hop_add_reg_insel(struct hop* hop, struct hop* reg) { - append("%s", data); + struct insel* insel = new_insel(INSEL_REG); + insel->u.reg = reg; + array_append(&hop->insels, insel); } -static void emit_value(struct ir* ir) +void hop_add_value_insel(struct hop* hop, struct ir* ir) { - append("(val)"); + struct insel* insel = new_insel(INSEL_VALUE); + insel->u.value = ir; + array_append(&hop->insels, insel); } -static void emit_resultreg(void) +void hop_add_eoi_insel(struct hop* hop) { - append("%%%d", current_hop->resultvreg->id); + struct insel* insel = new_insel(INSEL_EOI); + array_append(&hop->insels, insel); } -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]; + int i; + bool soi = true; - current_hop = hop; - outbuf[0] = 0; - if (insndata->emitter) + i = 0; + for (i=0; iinsels.count; i++) { - insndata->emitter(hop->ir, &emitter_data); + struct insel* insel = hop->insels.item[i]; - s = strtok(outbuf, "\n"); - do + if (soi) { - tracef(k, "%c: %p: %s\n", k, hop, s); - s = strtok(NULL, "\n"); + tracef(k, "%c: %d: ", k, hop->id); + soi = false; + } + + switch (insel->type) + { + case INSEL_EOI: + tracef(k, "\n"); + soi = true; + break; + + case INSEL_REG: + tracef(k, "%%%d", insel->u.reg->id); + break; + + case INSEL_STRING: + tracef(k, "%s", insel->u.string); + break; + + case INSEL_VALUE: + { + struct ir* ir = insel->u.value; + switch (ir->opcode) + { + case IR_BLOCK: + tracef(k, "%s", ir->u.bvalue->name); + break; + + case IR_LOCAL: + case IR_CONST: + tracef(k, "0x%d", ir->u.ivalue); + break; + } + break; + } } - while (s); } - else - tracef(k, "%c: %p: (empty)\n", k, hop); + + if (!soi) + tracef(k, "\n", k); } diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index 2cb0c9f72..8f92d898e 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -1,19 +1,43 @@ #ifndef HOP_H #define HOP_H +enum insel_type +{ + INSEL_STRING, + INSEL_REG, + INSEL_VALUE, + INSEL_EOI +}; + +struct insel +{ + enum insel_type type; + union + { + const char* string; + struct hop* reg; + struct ir* value; + } + u; +}; + struct hop { + int id; int insn_no; struct ir* ir; - struct vreg* resultvreg; - ARRAYOF(struct vreg) invregs; - ARRAYOF(struct vreg) outvregs; - ARRAYOF(struct vreg) newvregs; - ARRAYOF(struct vreg) deadvregs; + struct hop* result; + ARRAYOF(struct hop) params; + ARRAYOF(struct insel) insels; }; extern struct hop* new_hop(int insn_no, struct ir* ir); +extern void hop_add_string_insel(struct hop* hop, const char* string); +extern void hop_add_reg_insel(struct hop* hop, struct hop* reg); +extern void hop_add_value_insel(struct hop* hop, struct ir* ir); +extern void hop_add_eoi_insel(struct hop* hop); + extern void hop_print(char k, struct hop* hop); #endif diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 746f3924c..8cf16f952 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -20,7 +20,6 @@ #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 a2a993c82..13d3d892a 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -1,6 +1,9 @@ #include "mcg.h" static struct basicblock* current_bb; +static struct hop* current_hop; + +static const struct burm_emitter_data emitter_data; void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) { const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno]; @@ -16,28 +19,67 @@ void burm_panic_cannot_match(struct ir* ir) exit(1); } -static void walk_instructions(struct hop* hop, struct ir* ir, int goal) +static void emit_reg(struct ir* ir) +{ + if (ir->hop) + hop_add_reg_insel(current_hop, ir->hop); + else + { + const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no]; + if (insndata->emitter) + insndata->emitter(ir, &emitter_data); + } +} + +static void emit_string(const char* data) +{ + hop_add_string_insel(current_hop, data); +} + +static void emit_value(struct ir* ir) +{ + hop_add_value_insel(current_hop, ir); +} + +static void emit_resultreg(void) +{ + hop_add_reg_insel(current_hop, current_hop); +} + +static void emit_eoi(void) +{ + hop_add_eoi_insel(current_hop); +} + +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) { 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]; + struct hop* parent_hop = NULL; int i; ir->insn_no = insn_no; if (!insndata->is_fragment) - hop = ir->hop = new_hop(insn_no, ir);; - - if (insndata->allocate) { - hop->resultvreg = new_vreg(); - array_append(&hop->newvregs, hop->resultvreg); - array_append(&hop->outvregs, hop->resultvreg); + parent_hop = current_hop; + current_hop = ir->hop = new_hop(insn_no, ir); } burm_kids(ir, insn_no, children); for (i=0; nts[i]; i++) - walk_instructions(hop, children[i], nts[i]); + walk_instructions(children[i], nts[i]); ir->is_generated = true; @@ -50,8 +92,12 @@ static void walk_instructions(struct hop* hop, struct ir* ir, int goal) if (!insndata->is_fragment) { - array_append(¤t_bb->hops, hop); - hop_print('I', hop); + if (insndata->emitter) + insndata->emitter(ir, &emitter_data); + + hop_print('I', current_hop); + array_append(¤t_bb->hops, current_hop); + current_hop = parent_hop; } } @@ -73,7 +119,7 @@ static void select_instructions(void) burm_panic_cannot_match(ir); ir_print('I', ir); - walk_instructions(NULL, ir, 1); + walk_instructions(ir, 1); } } diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index f0303a442..3348787c3 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -21,6 +21,7 @@ DECLARATIONS aluparam fragment; reg allocates(GPR); tristate allocates(CC); + bistate allocates(CC); PATTERNS @@ -105,6 +106,11 @@ PATTERNS emit "b $false" cost 8; + CJUMPEQ(value:bistate, PAIR(true:BLOCK4, false:BLOCK4)) + emit "beq $true" + emit "b $false" + cost 8; + /* Comparisons */ @@ -112,12 +118,21 @@ PATTERNS emit "cmp %left, %right" cost 4; + bistate = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4) + emit "cmp %left, %right" + cost 4; + reg = tristate emit "mov %reg, #0" emit "movlt %reg, #-1" emit "movgt %reg, #1" cost 12; + reg = bistate + emit "moveq %reg, #1" + emit "movne %reg, #0" + cost 8; + /* Conversions */ diff --git a/mach/proto/mcg/vreg.c b/mach/proto/mcg/vreg.c deleted file mode 100644 index c841822f8..000000000 --- a/mach/proto/mcg/vreg.c +++ /dev/null @@ -1,10 +0,0 @@ -#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 deleted file mode 100644 index b764d3883..000000000 --- a/mach/proto/mcg/vreg.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef VREG_H -#define VREG_H - -struct vreg -{ - int id; -}; - -extern struct vreg* new_vreg(void); - -#endif - - -- 2.34.1