Much better handling of fragments (no run-time code needed to distinguish them
authorDavid Given <dg@cowlark.com>
Thu, 29 Sep 2016 20:06:04 +0000 (22:06 +0200)
committerDavid Given <dg@cowlark.com>
Thu, 29 Sep 2016 20:06:04 +0000 (22:06 +0200)
from registers) and better handling of individual hops within a paragraph ---
no more ghastly hacks to try and distinguish the input from the output.

mach/proto/mcg/hop.c
mach/proto/mcg/hop.h
mach/proto/mcg/ir.c
mach/proto/mcg/ir.h
mach/proto/mcg/mcgg_generated_header.h
mach/proto/mcg/pass_convertstackops.c
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/table
mach/proto/mcg/treebuilder.c
util/mcgg/iburg.c
util/mcgg/mcgg.h

index 510190c..35bed38 100644 (file)
@@ -28,10 +28,11 @@ void hop_add_string_insel(struct hop* hop, const char* string)
        array_append(&hop->insels, insel);
 }
 
-void hop_add_reg_insel(struct hop* hop, struct hop* reg)
+void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no)
 {
        struct insel* insel = new_insel(INSEL_REG);
-       insel->u.reg = reg;
+       insel->u.reg.ir = ir;
+       insel->u.reg.insn_no = insn_no;
        array_append(&hop->insels, insel);
 }
 
@@ -72,7 +73,7 @@ void hop_print(char k, struct hop* hop)
                                break;
 
                        case INSEL_REG:
-                               tracef(k, "%%%d", insel->u.reg->id);
+                               tracef(k, "$%d.%d", insel->u.reg.ir->id, insel->u.reg.insn_no);
                                break;
 
                        case INSEL_STRING:
index 8f92d89..e6cc8f8 100644 (file)
@@ -15,7 +15,12 @@ struct insel
        union
        {
                const char* string;
-               struct hop* reg;
+               struct
+               {
+                       struct ir* ir;
+                       int insn_no;
+               }
+               reg;
                struct ir* value;
        }
        u;
@@ -26,15 +31,13 @@ struct hop
        int id;
        int insn_no;
        struct ir* ir;
-       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_reg_insel(struct hop* hop, struct ir* ir, int insn_no);
 extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
 extern void hop_add_eoi_insel(struct hop* hop);
 
@@ -42,4 +45,3 @@ extern void hop_print(char k, struct hop* hop);
 
 #endif
 
-
index 4d61bdd..c4755b2 100644 (file)
@@ -71,14 +71,14 @@ struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
     if (cb(ir, user))
         return ir;
 
-    if (ir->left && !ir->left->is_sequence)
+    if (ir->left && !ir->left->is_root)
     {
         struct ir* irr = ir_walk(ir->left, cb, user);
         if (irr)
             return irr;
     }
 
-    if (ir->right && !ir->right->is_sequence)
+    if (ir->right && !ir->right->is_root)
     {
         struct ir* irr = ir_walk(ir->right, cb, user);
         if (irr)
@@ -126,7 +126,7 @@ static void print_expr(char k, const struct ir* ir)
                default:
             if (ir->left)
             {
-                if (ir->left->is_sequence)
+                if (ir->left->is_root)
                     tracef(k, "$%d", ir->left->id);
                 else
                     print_expr(k, ir->left);
@@ -134,7 +134,7 @@ static void print_expr(char k, const struct ir* ir)
             if (ir->right)
             {
                 tracef(k, ", ");
-                if (ir->right->is_sequence)
+                if (ir->right->is_root)
                     tracef(k, "$%d", ir->right->id);
                 else
                     print_expr(k, ir->right);
index d38ecf1..069a76b 100644 (file)
@@ -20,9 +20,9 @@ struct ir
 
        void* state_label; /* used by the iburg instruction selector */
        int insn_no;       /* the table rule number for this instruction */
-       struct hop* hop;   /* only for IRs that root a hardware op */
+       ARRAYOF(struct hop) hops; /* only for root IRs */
 
-       bool is_sequence : 1;
+       bool is_root : 1;
        bool is_generated : 1;
 };
 
index fbe0603..a3e79af 100644 (file)
@@ -6,9 +6,8 @@
 
 static int OP_LABEL(struct ir* ir)
 {
-       if (ir->is_generated)
+       if (ir->is_root && ir->is_generated)
        {
-               assert(ir->is_sequence);
                return ir_to_esn(IR_REG, ir->size);
        }
        return ir_to_esn(ir->opcode, ir->size);
index adbe250..6f62fe7 100644 (file)
@@ -112,9 +112,9 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
         for (i=0; i<pushes.count; i++)
         {
             struct ir* ir = pushes.item[i];
-            assert(ir->is_sequence);
+            assert(ir->is_root);
             *ir = *ir->left;
-            ir->is_sequence = true;
+            ir->is_root = true;
         }
 
         for (i=0; i<pops.count; i++)
@@ -126,7 +126,7 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
             for (j=1; j<pushes.count; j++)
                 phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
 
-            phi->is_sequence = ir->is_sequence;
+            phi->is_root = ir->is_root;
             *ir = *phi;
         }
     }
index 13d3d89..2b0bb96 100644 (file)
@@ -19,16 +19,9 @@ void burm_panic_cannot_match(struct ir* ir)
        exit(1);
 }
 
-static void emit_reg(struct ir* ir)
+static void emit_reg(struct ir* ir, int goal)
 {
-    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);
-    }
+    hop_add_reg_insel(current_hop, ir, goal);
 }
 
 static void emit_string(const char* data)
@@ -36,6 +29,14 @@ static void emit_string(const char* data)
        hop_add_string_insel(current_hop, data);
 }
 
+static void emit_fragment(struct ir* ir, int goal)
+{
+    int insn_no = burm_rule(ir->state_label, goal);
+    const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
+    if (insndata->emitter)
+        insndata->emitter(ir, &emitter_data);
+}
+
 static void emit_value(struct ir* ir)
 {
        hop_add_value_insel(current_hop, ir);
@@ -43,7 +44,6 @@ static void emit_value(struct ir* ir)
 
 static void emit_resultreg(void)
 {
-       hop_add_reg_insel(current_hop, current_hop);
 }
 
 static void emit_eoi(void)
@@ -54,6 +54,7 @@ static void emit_eoi(void)
 static const struct burm_emitter_data emitter_data =
 {
     &emit_string,
+    &emit_fragment,
     &emit_reg,
     &emit_value,
     &emit_resultreg,
@@ -70,11 +71,10 @@ static void walk_instructions(struct ir* ir, int goal)
     struct hop* parent_hop = NULL;
     int i;
     
-    ir->insn_no = insn_no;
     if (!insndata->is_fragment)
     {
         parent_hop = current_hop;
-        current_hop = ir->hop = new_hop(insn_no, ir);
+        current_hop = new_hop(insn_no, ir);
     }
 
     burm_kids(ir, insn_no, children);
@@ -82,10 +82,11 @@ static void walk_instructions(struct ir* ir, int goal)
         walk_instructions(children[i], nts[i]);
 
     ir->is_generated = true;
+    ir->insn_no = insn_no;
 
     tracef('I', "I: $%d %s selected %s %d: %s\n",
         ir->id,
-        ir->is_sequence ? "S" : " ",
+        ir->is_root ? "S" : " ",
         insndata->is_fragment ? "fragment" : "instruction",
         insn_no,
         insndata->name);
@@ -96,12 +97,11 @@ static void walk_instructions(struct ir* ir, int goal)
             insndata->emitter(ir, &emitter_data);
 
         hop_print('I', current_hop);
-        array_append(&current_bb->hops, current_hop);
+        array_append(&ir->hops, current_hop);
         current_hop = parent_hop;
     }
 }
 
-
 static void select_instructions(void)
 {
        int i;
index 9bd39d4..4126b2f 100644 (file)
@@ -1,27 +1,38 @@
 REGISTERS
 
-       r0  GPR RET0;
-       r1  GPR RET1;
-       r2  GPR;
-       r3  GPR;
-       r4  GPR;
-       r5  GPR;
-       r6  GPR;
-       r7  GPR;
-       r8  GPR;
-       r9  GPR;
-       r10 GPR;
-       r11 GPR;
-
-       cc  CC;
+       r0  reg4 int ret0;
+       r1  reg4 int ret1;
+       r2  reg4 int;
+       r3  reg4 int;
+       r4  reg4 int;
+       r5  reg4 int;
+       r6  reg4 int;
+       r7  reg4 int;
+       r8  reg4 int;
+       r9  reg4 int;
+       r10 reg4 int;
+       r11 reg4 int;
+
+       s0  reg4 float;
+       s1  reg4 float;
+       s2  reg4 float;
+       s3  reg4 float;
+       s4  reg4 float;
+       s5  reg4 float;
+       s6  reg4 float;
+       s7  reg4 float;
+       s8  reg4 float;
+       s9  reg4 float;
+
+       cc  conditioncode;
 
 DECLARATIONS
 
        address   fragment;
        aluparam  fragment;
-       reg       allocates(GPR);
-       tristate  allocates(CC);
-       bistate   allocates(CC);
+       reg       allocates(reg4);
+       tristate  allocates(conditioncode);
+       bistate   allocates(conditioncode);
 
 PATTERNS
 
@@ -158,7 +169,8 @@ PATTERNS
        aluparam = value:CONST4
                emit "#$value";
 
-       aluparam = reg;
+       aluparam = value:reg
+               emit "%value";
 
        reg = value:aluparam
                emit "mov %reg, %value"
@@ -175,3 +187,10 @@ PATTERNS
        reg = value:CONST4
                emit "ldr %reg, #$value"
                cost 8;
+
+/* FPU operations */
+
+       reg = ADDF4(left:reg, right:reg)
+               emit "fadds %reg, %left, %right"
+               cost 4;
+
index a0ebe0e..58f19bd 100644 (file)
@@ -76,7 +76,7 @@ static struct ir* appendir(struct ir* ir)
     int i;
 
     assert(current_bb != NULL);
-    ir->is_sequence = true;
+    ir->is_root = true;
     array_append(&current_bb->irs, ir);
 
     ir_print('0', ir);
@@ -479,7 +479,7 @@ static void insn_ivalue(int opcode, arith value)
         case op_dup:
         {
             struct ir* v = pop(value);
-            if (!v->is_sequence)
+            if (!v->is_root)
                 appendir(v);
             push(v);
             push(v);
index f29c859..0e8cad4 100644 (file)
@@ -295,7 +295,7 @@ struct regclass* getregclass(const char* id)
 {
        struct regclass* p = lookup(id);
        if (!p || (p->kind != REGCLASS))
-               yyerror("'%p' is not the name of a register class");
+               yyerror("'%s' is not the name of a register class", id);
        return p;
 }
 
@@ -917,18 +917,22 @@ static void print_path(uint32_t path)
 
 static const uint32_t PATH_MISSING = 0xffffffff;
 
-static uint32_t find_label(Tree root, const char* name, uint32_t path)
+static uint32_t find_label(Tree root, const char* name, uint32_t path, Tree* found)
 {
        uint32_t p;
 
        if (root->label && (strcmp(root->label, name) == 0))
+       {
+               if (found)
+                       *found = root;
                return path;
+       }
 
        p = PATH_MISSING;
        if (root->left && (p == PATH_MISSING))
-               p = find_label(root->left, name, path*3 + 1);
+               p = find_label(root->left, name, path*3 + 1, found);
        if (root->right && (p == PATH_MISSING))
-               p = find_label(root->right, name, path*3 + 2);
+               p = find_label(root->right, name, path*3 + 2, found);
        return p;
 }
 
@@ -963,15 +967,23 @@ static void emitinsndata(Rule rules)
                                                const char* label = f->data + 1;
 
                                                if (strcmp(label, r->lhs->name) == 0)
-                                                       print("%1data->emit_resultreg();\n");
+                                                       print("%1data->emit_reg(node, %P%s_NT);\n", label);
                                                else
                                                {
-                                                       uint32_t path = find_label(r->pattern, label, 0);
-                                                       print("%1data->emit_reg(");
+                                                       Tree node;
+                                                       uint32_t path = find_label(r->pattern, label, 0, &node);
+                                                       Nonterm nt = node->op;
+
                                                        if (path == PATH_MISSING)
                                                                label_not_found(r, label);
+
+                                                       if (nt->is_fragment)
+                                                               print("%1data->emit_fragment(");
+                                                       else
+                                                               print("%1data->emit_reg(");
+
                                                        print_path(path);
-                                                       print(");\n");
+                                                       print(", %P%s_NT);\n", ((Nonterm)node->op)->name);
                                                }
                                                break;
                                        }
@@ -979,7 +991,7 @@ static void emitinsndata(Rule rules)
                                        case '$':
                                        {
                                                const char* label = f->data + 1;
-                                               uint32_t path = find_label(r->pattern, label, 0);
+                                               uint32_t path = find_label(r->pattern, label, 0, NULL);
                                                print("%1data->emit_value(");
                                                if (path == PATH_MISSING)
                                                        label_not_found(r, label);
index 004146b..0bbe4ae 100644 (file)
@@ -27,7 +27,8 @@ extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
 struct burm_emitter_data
 {
     void (*emit_string)(const char* data);
-    void (*emit_reg)(struct ir* ir);
+    void (*emit_fragment)(struct ir* ir, int goal);
+    void (*emit_reg)(struct ir* ir, int goal);
     void (*emit_value)(struct ir* ir);
     void (*emit_resultreg)(void);
     void (*emit_eoi)(void);