Keep track of register types as well as attributes --- the type being how we
authorDavid Given <dg@cowlark.com>
Wed, 12 Oct 2016 20:58:46 +0000 (22:58 +0200)
committerDavid Given <dg@cowlark.com>
Wed, 12 Oct 2016 20:58:46 +0000 (22:58 +0200)
find new registers when evicting values. Input constraints work (they were
being ignored before). Various bug fixing so they actually work.

mach/proto/mcg/ir.h
mach/proto/mcg/pass_groupirs.c
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/reg.h
mach/proto/mcg/table
util/mcgg/gram.y
util/mcgg/iburg.c
util/mcgg/iburg.h
util/mcgg/ir.dat
util/mcgg/mcgg.h

index c273709..83dd342 100644 (file)
@@ -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 */
 };
 
index 833809b..ac86ff2 100644 (file)
@@ -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);
                }
     }
 }
index 6ab678a..b87ede3 100644 (file)
@@ -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;
 
index 1c8df2d..42f43ef 100644 (file)
@@ -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(&current_hop->constraints, vreg);
+    return (hreg->attrs & c->attrs) && !array_contains(&current_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(&current_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; i<hregs.count; i++)
     {
         hreg = hregs.item[i];
@@ -103,25 +140,59 @@ static void add_input_register(struct vreg* vreg, struct hreg* hreg)
 
 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,
@@ -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; 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)
@@ -253,16 +335,11 @@ 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;
index fc72f2a..7531090 100644 (file)
@@ -14,6 +14,7 @@ struct phicongruence
 struct hreg
 {
        const char* name;
+    uint32_t type;
        uint32_t attrs;
        bool is_stacked;
        int offset;
index f50f02c..12ad4a3 100644 (file)
@@ -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. */
-
-    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
@@ -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 */
index 74c0c05..f6f39ae 100644 (file)
@@ -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
index 9f2c6b7..bf3a698 100644 (file)
@@ -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(&registerattrs, 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");
index 8a5a71b..34c046e 100644 (file)
@@ -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
index 31574ad..0667ee0 100644 (file)
@@ -58,6 +58,11 @@ S CIU2
 S CIU4
 S CIU8
 
+S CUI1
+S CUI2
+S CUI4
+S CUI8
+
 # Tristate comparisons
 S COMPARES
 S COMPAREU
index 4e86e79..94e5b67 100644 (file)
@@ -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;
 };