Output register equality constraints work.
authorDavid Given <dg@cowlark.com>
Fri, 14 Oct 2016 20:17:02 +0000 (22:17 +0200)
committerDavid Given <dg@cowlark.com>
Fri, 14 Oct 2016 20:17:02 +0000 (22:17 +0200)
mach/proto/mcg/hop.h
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/table
util/mcgg/gram.y
util/mcgg/iburg.c
util/mcgg/iburg.h
util/mcgg/mcgg.h

index 7dcbfd8..ab2b39d 100644 (file)
@@ -26,6 +26,7 @@ struct insel
 struct constraint
 {
     uint32_t attrs;
+    struct vreg* equals_to;
 };
 
 struct hop
index b87ede3..7e38efe 100644 (file)
@@ -113,6 +113,13 @@ static void constrain_output_reg(uint32_t attr)
     get_constraint(vreg)->attrs = attr;
 }
 
+static void constrain_output_reg_equal_to(int child)
+{
+    struct vreg* vreg = find_vreg_of_child(child);
+
+    get_constraint(current_hop->output)->equals_to = vreg;
+}
+
 static const struct burm_emitter_data emitter_data =
 {
     &emit_string,
@@ -122,7 +129,8 @@ static const struct burm_emitter_data emitter_data =
     &emit_value,
     &emit_eoi,
     &constrain_input_reg,
-    &constrain_output_reg
+    &constrain_output_reg,
+    &constrain_output_reg_equal_to,
 };
 
 static void emit(struct insn* insn)
index 42f43ef..6f2cff2 100644 (file)
@@ -142,26 +142,74 @@ static void add_output_register(struct vreg* vreg)
 {
     struct hreg* hreg;
     int i;
+    struct constraint* c;
 
-    /* Find an unused output register of the right class. */
+    /* Is this register supposed to be the same as one of the input registers?
+     * */
 
-    hreg = NULL;
-    for (i=0; i<hregs.count; i++)
+    c = pmap_findleft(&current_hop->constraints, vreg);
+    if (c->equals_to)
     {
-        hreg = hregs.item[i];
-        if (allocatable(hreg, vreg) &&
-            !pmap_findleft(current_outs, hreg))
+        /* This output register is constrained to be in the same hreg as an
+         * input register (most likely for a 2op instruction). */
+
+        hreg = pmap_findright(current_ins, c->equals_to);
+
+        /* If this register is current unused as an output, use it. */
+
+        if (!pmap_findleft(current_outs, hreg))
         {
-            goto found;
+            pmap_add(current_outs, hreg, vreg);
+            return;
+        }
+
+        /* Okay, something's in it. Most likely it's a through being used as an
+         * input register.  Trying to evict it would be pointless as that would
+         * also evict the input. So, we're going to have to do this the hard
+         * way: we try to allocate a matched set of input and output registers.
+         * */
+
+        hreg = NULL;
+        for (i=0; i<hregs.count; i++)
+        {
+            hreg = hregs.item[i];
+            if (allocatable(hreg, vreg) &&
+                !pmap_findleft(current_ins, hreg) &&
+                !pmap_findleft(current_outs, hreg))
+            {
+                goto found1;
+            }
         }
+
+        /* If we couldn't find one, evict a register. */
+
+        hreg = evict(vreg);
+    found1:
+        pmap_add(current_outs, hreg, vreg);
+        pmap_add(current_ins, hreg, c->equals_to);
     }
+    else
+    {
+        /* This is an ordinary new register. */
+
+        hreg = NULL;
+        for (i=0; i<hregs.count; i++)
+        {
+            hreg = hregs.item[i];
+            if (allocatable(hreg, vreg) &&
+                !pmap_findleft(current_outs, hreg))
+            {
+                goto found2;
+            }
+        }
 
-    /* If we couldn't find one, evict a register. */
+        /* If we couldn't find one, evict a register. */
 
-    hreg = evict(vreg);
+        hreg = evict(vreg);
 
-found:
-    pmap_add(current_outs, hreg, vreg);
+    found2:
+        pmap_add(current_outs, hreg, vreg);
+    }
 }
 
 static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* src)
index 3cea3ef..88fc591 100644 (file)
@@ -167,33 +167,40 @@ PATTERNS
     /* Conversions to ubyte and ushort */
 
     out:(int)ubyte = in:(int)reg
-        emit "mr %out, %in ! reg -> ubyte"
+        with %out == %in
+        emit "! reg -> ubyte"
         cost 1;
 
     out:(int)ubyte = CIU41(value:(int)reg)
-        emit "mr %out, %value ! CIU41(reg) -> ubyte"
+        with %out == %value
+        emit "! CIU41(reg) -> ubyte"
         cost 1;
 
     out:(int)ubyte = CIU41(CII14(CIU41(value:(int)reg)))
-        emit "mr %out, %value ! CIU41(CII14(CIU41(reg))) -> ubyte"
+        with %out == %value
+        emit "! CIU41(CII14(CIU41(reg))) -> ubyte"
         cost 1;
 
     out:(int)ushort = in:(int)reg
-        emit "mr %out, %in ! reg -> ushort"
+        with %out == %in
+        emit "! reg -> ushort"
         cost 1;
 
     out:(int)ushort = CIU42(value:(int)reg)
-        emit "mr %out, %value ! CIU42(reg) -> ushort"
+        with %out == %value
+        emit "! CIU42(reg) -> ushort"
         cost 1;
 
     out:(int)ushort = CIU42(CII24(CIU42(value:(int)reg)))
-        emit "mr %out, %value ! CIU42(CII24(CIU42(reg))) -> ushort"
+        with %out == %value
+        emit "! CIU42(CII24(CIU42(reg))) -> ushort"
         cost 1;
 
     /* Conversions from ubyte and ushort */
 
     out:(int)reg = CIU14(in:(int)ubyte)
-        emit "mr %out, %in ! CIU14"
+        with %out == %in
+        emit "! CIU14"
         cost 4;
 
        
index f6f39ae..3fe5f9c 100644 (file)
@@ -143,12 +143,8 @@ constraints
 
 constraint
     : '(' constraint ')'                { $$ = $2; }
-    | ID ID                             { $$ = calloc(1, sizeof(*$$));
-                                          $$->type = CONSTRAINT_ATTR; $$->left = $1; $$->right = $2; }
-    | ID EQUALS ID                      { $$ = calloc(1, sizeof(*$$));
-                                          $$->type = CONSTRAINT_EQUALS; $$->left = $1; $$->right = $3; }
-    | ID NOTEQUALS ID                   { $$ = calloc(1, sizeof(*$$));
-                                          $$->type = CONSTRAINT_NOTEQUALS; $$->left = $1; $$->right = $3; }
+    | '%' ID EQUALS '%' ID              { $$ = calloc(1, sizeof(*$$));
+                                          $$->type = CONSTRAINT_EQUALS; $$->left = $2; $$->right = $5; }
     ;
 
 qfragments
index bf3a698..a3d9568 100644 (file)
@@ -1096,6 +1096,36 @@ static void emit_input_regs(Tree node, int* index)
                emit_input_regs(node->right, index);
 }
 
+static void emit_output_constraints(Rule r)
+{
+       int i;
+       struct constraint* outputc = NULL;
+
+       for (i=0; i<r->constraints.count; i++)
+       {
+               struct constraint* c = r->constraints.item[i];
+
+               if (c->type == CONSTRAINT_EQUALS)
+               {
+                       if (strcmp(c->left, r->label) != 0)
+                               yyerror("equality register constraints must have an output register on the left hand side");
+                       if (outputc != NULL)
+                               yyerror("you can't specify more than one output register constraint");
+                       outputc = c;
+               }
+       }
+
+       if (outputc)
+       {
+               int index = 0;
+
+               if (!find_child_index(r->pattern, outputc->right, &index, NULL))
+                       label_not_found(r, outputc->right);
+
+               print("%1data->constrain_output_reg_equal_to(%d);\n", index);
+       }
+}
+
 /* emitinsndata - emit the code generation data */
 static void emitinsndata(Rule rules)
 {
@@ -1129,7 +1159,9 @@ static void emitinsndata(Rule rules)
                        int index = 0;
                        emit_input_regs(r->pattern, &index);
                }
-
+               
+               emit_output_constraints(r);
+               
                while (f)
                {
                        switch (f->data[0])
index 34c046e..ebd22fb 100644 (file)
@@ -19,9 +19,7 @@ typedef struct term* Term;
 
 enum
 {
-       CONSTRAINT_ATTR,
        CONSTRAINT_EQUALS,
-       CONSTRAINT_NOTEQUALS
 };
 
 struct constraint
index 94e5b67..c0c9d87 100644 (file)
@@ -46,6 +46,7 @@ struct burm_emitter_data
     void (*emit_eoi)(void);
     void (*constrain_input_reg)(int child, uint32_t attr);
     void (*constrain_output_reg)(uint32_t attr);
+    void (*constrain_output_reg_equal_to)(int child);
 };
 
 typedef void burm_emitter_t(const struct burm_emitter_data* data);