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;
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; i<hregs.count; i++)
+ {
+ struct hreg* hreg = hregs.item[i];
+ struct vreg* candidate = pmap_findleft(current_ins, hreg);
+
+ if (candidate &&
+ (pmap_findleft(current_outs, hreg) == candidate) &&
+ evictable(hreg, vreg))
+ {
+ tracef('R', "R: evicting %%%d from %s\n", candidate->id, 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);
/* 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))
/* Find an unused input register of the right class. */
+ hreg = NULL;
for (i=0; i<hregs.count; i++)
{
hreg = hregs.item[i];
static void add_output_register(struct vreg* vreg)
{
+ struct hreg* hreg;
int i;
/* Find an unused output register of the right class. */
+ hreg = NULL;
for (i=0; i<hregs.count; i++)
{
- struct hreg* hreg = hregs.item[i];
+ hreg = hregs.item[i];
if (allocatable(hreg, vreg) &&
!pmap_findleft(current_outs, hreg))
{
- /* Got one --- use it. */
- pmap_add(current_outs, hreg, vreg);
- return;
+ goto found;
}
}
- /* Evicting an output register is exciting, because the only possible
- * candidates are throughs. */
+ /* If we couldn't find one, evict a register. */
+
+ hreg = evict(vreg);
+
+found:
+ pmap_add(current_outs, hreg, vreg);
+}
+
+static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* src)
+{
+ uint32_t srctype = src->type;
+ 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; i<hregs.count; i++)
+ {
+ hreg = hregs.item[i];
+ if ((hreg->type == 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,
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. */
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; i<evicted.count; i++)
+ {
+ struct vreg* vreg = evicted.item[i].left;
+ struct hreg* src = evicted.item[i].right;
+ find_new_home_for_evicted_register(vreg, src);
+ }
}
static void assign_hregs_to_vregs(void)
register_assignment_t* in = &hop->regsin;
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; k<hop->ins.count; k++)
- tracef('R', " r%%%d", hop->ins.item[k]->id);
- for (k=0; k<hop->throughs.count; k++)
- tracef('R', " =%%%d", hop->throughs.item[k]->id);
- for (k=0; k<hop->outs.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; k<hop->regsin.count; k++)
{
struct hreg* hreg = hop->regsin.item[k].left;
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. */
-
- 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;
-
- 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;
-
- cr0 cr;
+ * 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;
+
+ 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;
+
+ 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!;
DECLARATIONS
cr;
ubyte_to_be;
- address fragment;
+ address fragment;
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)
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)
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 */