diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index c273709f2..83dd34246 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -20,6 +20,8 @@ struct ir PMAPOF(struct basicblock, struct ir) phivalue; } u; + ARRAYOF(struct ir) uses; /* all places this IR is used */ + struct vreg* result; /* vreg containing IR result */ }; diff --git a/mach/proto/mcg/pass_groupirs.c b/mach/proto/mcg/pass_groupirs.c index 833809b1d..ac86ff230 100644 --- a/mach/proto/mcg/pass_groupirs.c +++ b/mach/proto/mcg/pass_groupirs.c @@ -28,7 +28,7 @@ static void collect_irs(struct procedure* proc) { struct ir* ir = bb->irs.item[j]; addall(ir); - array_appendu(&rootirs, ir); + array_append(&rootirs, ir); } } } diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 6ab678ac9..b87ede3aa 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -177,7 +177,10 @@ static struct insn* walk_instructions(struct burm_node* node, int goal) switch (node->label) { - case ir_to_esn(IR_REG, 0): + case ir_to_esn(IR_REG, 1): + case ir_to_esn(IR_REG, 2): + case ir_to_esn(IR_REG, 4): + case ir_to_esn(IR_REG, 8): vreg = node->ir->result; break; diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index 1c8df2d16..42f43ef33 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -8,7 +8,7 @@ struct assignment static ARRAYOF(struct hreg) hregs; -static ARRAYOF(struct vreg) evicted; +static PMAPOF(struct vreg, struct hreg) evicted; static struct hop* current_hop; static register_assignment_t* current_ins; static register_assignment_t* current_outs; @@ -63,6 +63,42 @@ static struct hreg* allocate_phi_hreg(register_assignment_t* regs, assert(false); } +static bool evictable(struct hreg* hreg, struct vreg* vreg) +{ + struct constraint* c = pmap_findleft(¤t_hop->constraints, vreg); + return (hreg->attrs & c->attrs) && !array_contains(¤t_hop->ins, vreg); + /* Find an unused output register of the right class which is not also being used as an input register. */ +} + +static struct hreg* evict(struct vreg* vreg) +{ + int i; + + /* Look for a through register which matches our requirements. We should be + * doing some calculation here to figure out the cheapest register to + * evict, but for now we're picking the first one. FIXME. */ + + for (i=0; iid, hreg->name); + pmap_put(&evicted, candidate, hreg); + pmap_remove(current_ins, hreg, candidate); + pmap_remove(current_outs, hreg, candidate); + return hreg; + } + } + + /* Couldn't find anything to evict */ + assert(false); +} + static bool allocatable(struct hreg* hreg, struct vreg* vreg) { struct constraint* c = pmap_findleft(¤t_hop->constraints, vreg); @@ -75,7 +111,7 @@ static void add_input_register(struct vreg* vreg, struct hreg* hreg) /* Register hint for an input? */ - if (hreg) + if (hreg && allocatable(hreg, vreg)) { /* If it's already assigned, it's most likely a through. */ if (!pmap_findleft(current_ins, hreg)) @@ -85,6 +121,7 @@ static void add_input_register(struct vreg* vreg, struct hreg* hreg) /* Find an unused input register of the right class. */ + hreg = NULL; for (i=0; itype; + struct hreg* hreg; + int i; + + /* Find an unused output register of the right class which is not also + * being used as an input register. */ + + hreg = NULL; + for (i=0; itype == src->type) && + !pmap_findleft(current_ins, hreg) && + !pmap_findleft(current_outs, hreg)) + { + goto found; + } + } + + /* No more registers --- allocate a stack slot. */ + assert(false); + +found: + tracef('R', "R: evicted %%%d moving to %s\n", vreg->id, hreg->name); + pmap_add(current_ins, hreg, vreg); + pmap_add(current_outs, hreg, vreg); } static void select_registers(struct hop* hop, @@ -132,6 +203,7 @@ static void select_registers(struct hop* hop, current_hop = hop; current_ins = in; current_outs = out; + evicted.count = 0; /* First, any vregs passing through the instruction stay in the same * registers they are currently in. */ @@ -164,6 +236,16 @@ static void select_registers(struct hop* hop, struct vreg* vreg = hop->outs.item[i]; add_output_register(vreg); } + + /* Any evicted registers now need to go somewhere (potentially, the stack). + * */ + + for (i=0; iregsin; register_assignment_t* out = &hop->regsout;; + hop_print('R', hop); + select_registers(hop, old, in, out); - tracef('R', "R: %d from $%d:", hop->id, hop->ir->id); - for (k=0; kins.count; k++) - tracef('R', " r%%%d", hop->ins.item[k]->id); - for (k=0; kthroughs.count; k++) - tracef('R', " =%%%d", hop->throughs.item[k]->id); - for (k=0; kouts.count; k++) - tracef('R', " w%%%d", hop->outs.item[k]->id); - tracef('R', " ["); + tracef('R', "R: %d from $%d: [", hop->id, hop->ir->id); for (k=0; kregsin.count; k++) { struct hreg* hreg = hop->regsin.item[k].left; diff --git a/mach/proto/mcg/reg.h b/mach/proto/mcg/reg.h index fc72f2ae0..753109063 100644 --- a/mach/proto/mcg/reg.h +++ b/mach/proto/mcg/reg.h @@ -14,6 +14,7 @@ struct phicongruence struct hreg { const char* name; + uint32_t type; uint32_t attrs; bool is_stacked; int offset; diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index f50f02c11..12ad4a35d 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -1,73 +1,77 @@ REGISTERS /* Registers are allocated top down; the order here is odd in order to make - * sure that non-volatile registers get allocated from r31 (or f31) down. */ + * sure that non-volatile registers get allocated from r31 (or f31) down. + * + * Attributes ending in an exclamation mark must match exactly when copying + * a register into another register (e.g. for eviction). + */ - r12 bytes4 int volatile; - r11 bytes4 int volatile; - r10 bytes4 int volatile; - r9 bytes4 int volatile; - r8 bytes4 int volatile; - r7 bytes4 int volatile; - r6 bytes4 int volatile; - r5 bytes4 int volatile; - r4 bytes4 int volatile; - r3 bytes4 int ret volatile; + r12 bytes4! int! volatile; + r11 bytes4! int! volatile; + r10 bytes4! int! volatile; + r9 bytes4! int! volatile; + r8 bytes4! int! volatile; + r7 bytes4! int! volatile; + r6 bytes4! int! volatile; + r5 bytes4! int! volatile; + r4 bytes4! int! volatile; + r3 bytes4! int! ret volatile; - r31 bytes4 int; - r30 bytes4 int; - r29 bytes4 int; - r28 bytes4 int; - r27 bytes4 int; - r26 bytes4 int; - r25 bytes4 int; - r24 bytes4 int; - r23 bytes4 int; - r22 bytes4 int; - r21 bytes4 int; - r20 bytes4 int; - r19 bytes4 int; - r18 bytes4 int; - r17 bytes4 int; - r16 bytes4 int; - r15 bytes4 int; - r14 bytes4 int; + r31 bytes4! int!; + r30 bytes4! int!; + r29 bytes4! int!; + r28 bytes4! int!; + r27 bytes4! int!; + r26 bytes4! int!; + r25 bytes4! int!; + r24 bytes4! int!; + r23 bytes4! int!; + r22 bytes4! int!; + r21 bytes4! int!; + r20 bytes4! int!; + r19 bytes4! int!; + r18 bytes4! int!; + r17 bytes4! int!; + r16 bytes4! int!; + r15 bytes4! int!; + r14 bytes4! int!; - f14 bytes4 float volatile; - f13 bytes4 float volatile; - f12 bytes4 float volatile; - f11 bytes4 float volatile; - f10 bytes4 float volatile; - f9 bytes4 float volatile; - f8 bytes4 float volatile; - f7 bytes4 float volatile; - f6 bytes4 float volatile; - f5 bytes4 float volatile; - f4 bytes4 float volatile; - f3 bytes4 float volatile; - f2 bytes4 float volatile; - f1 bytes4 float volatile; - f0 bytes4 float volatile; + f14 bytes4! float! volatile; + f13 bytes4! float! volatile; + f12 bytes4! float! volatile; + f11 bytes4! float! volatile; + f10 bytes4! float! volatile; + f9 bytes4! float! volatile; + f8 bytes4! float! volatile; + f7 bytes4! float! volatile; + f6 bytes4! float! volatile; + f5 bytes4! float! volatile; + f4 bytes4! float! volatile; + f3 bytes4! float! volatile; + f2 bytes4! float! volatile; + f1 bytes4! float! volatile; + f0 bytes4! float! volatile; - f31 bytes4 float; - f30 bytes4 float; - f29 bytes4 float; - f28 bytes4 float; - f27 bytes4 float; - f26 bytes4 float; - f25 bytes4 float; - f24 bytes4 float; - f23 bytes4 float; - f22 bytes4 float; - f21 bytes4 float; - f20 bytes4 float; - f19 bytes4 float; - f18 bytes4 float; - f17 bytes4 float; - f16 bytes4 float; - f15 bytes4 float; + f31 bytes4! float!; + f30 bytes4! float!; + f29 bytes4! float!; + f28 bytes4! float!; + f27 bytes4! float!; + f26 bytes4! float!; + f25 bytes4! float!; + f24 bytes4! float!; + f23 bytes4! float!; + f22 bytes4! float!; + f21 bytes4! float!; + f20 bytes4! float!; + f19 bytes4! float!; + f18 bytes4! float!; + f17 bytes4! float!; + f16 bytes4! float!; + f15 bytes4! float!; - cr0 cr; + cr0 cr!; DECLARATIONS @@ -75,7 +79,7 @@ DECLARATIONS cr; ubyte_to_be; - address fragment; + address fragment; PATTERNS @@ -107,10 +111,11 @@ PATTERNS cost 4; SETRET4(in:(ret)reg) - emit "mr r3, %in" + emit "! setret4" cost 4; (ret)reg = GETRET4 + emit "! getret4" cost 1; STACKADJUST4(delta:CONST4) @@ -139,12 +144,15 @@ PATTERNS cost 4; out:(int)ubyte_to_be = in:(int)reg + emit "! reg -> ubyte" cost 1; out:(int)ubyte_to_be = CIU41(value:(int)reg) + emit "! CIU41(reg) -> ubyte" cost 1; out:(int)ubyte_to_be = CIU41(CII14(CIU41(value:(int)reg))) + emit "! CIU41(CII14(CIU41(reg))) -> ubyte" cost 1; out:(int)reg = LOAD4(addr:address) @@ -284,9 +292,12 @@ PATTERNS cost 4; out:(int)reg = CIU44(in:(int)reg) - emit "mr %out, %in" + emit "mr %out, %in ! ciu44" cost 4; + out:(int)reg = CUI44(in:(int)reg) + emit "mr %out, %in ! cui44" + cost 4; /* ALU operations */ diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 74c0c0502..f6f39ae0f 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -71,7 +71,8 @@ registers register : ID { $$ = makereg($1); } - | register ID { $$ = $1; addregattr($1, $2); } + | register ID { $$ = $1; addregattr($1, $2, false); } + | register ID '!' { $$ = $1; addregattr($1, $2, true); } ; declarations diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 9f2c6b729..bf3a698d1 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -283,7 +283,7 @@ struct regattr* makeregattr(const char* id) return p; } -void addregattr(struct reg* reg, const char* id) +void addregattr(struct reg* reg, const char* id, bool exact) { struct regattr* p = smap_get(®isterattrs, id); @@ -291,6 +291,8 @@ void addregattr(struct reg* reg, const char* id) p = makeregattr(id); reg->attrs |= 1<<(p->number); + if (exact) + reg->type |= 1<<(p->number); } struct regattr* getregattr(const char* id) @@ -589,7 +591,7 @@ static void emitregisters(void) struct reg* r = registers.item[i].right; assert(r->number == i); - print("%1{ \"%s\", 0x%x },\n", r->name, r->attrs); + print("%1{ \"%s\", 0x%x, 0x%x },\n", r->name, r->type, r->attrs); } print("%1{ NULL }\n"); print("};\n\n"); diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 8a5a71b32..34c046e13 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -62,6 +62,7 @@ struct reg const char* name; /* register name */ int number; /* identifying number */ uint32_t attrs; /* bitfield of register attributes */ + uint32_t type; /* register type */ }; struct regattr @@ -71,7 +72,7 @@ struct regattr }; extern struct reg* makereg(const char* name); -extern void addregattr(struct reg* reg, const char* regattr); +extern void addregattr(struct reg* reg, const char* regattr, bool exact); extern struct regattr* getregattr(const char* name); struct term diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 31574adbb..0667ee04d 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -58,6 +58,11 @@ S CIU2 S CIU4 S CIU8 +S CUI1 +S CUI2 +S CUI4 +S CUI8 + # Tristate comparisons S COMPARES S COMPAREU diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index 4e86e79e0..94e5b67bf 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -62,6 +62,7 @@ extern const struct burm_instruction_data burm_instruction_data[]; struct burm_register_data { const char* name; + uint32_t type; uint32_t attrs; };