Lots more opcodes; better eviction behaviour; better register moves. Lots more
authorDavid Given <dg@cowlark.com>
Wed, 19 Oct 2016 21:29:05 +0000 (23:29 +0200)
committerDavid Given <dg@cowlark.com>
Wed, 19 Oct 2016 21:29:05 +0000 (23:29 +0200)
PowerPC stuff (some working).

mach/powerpc/mcg/platform.c
mach/powerpc/mcg/table
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/pass_prologueepilogue.c
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/treebuilder.c
util/mcgg/ir.dat

index 2e59833..0feaf0d 100644 (file)
@@ -99,14 +99,47 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
 {
     struct hop* hop = new_hop(bb, NULL);
 
-       if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
-       {
-               if (src->is_stacked)
-                       hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
-               else if (dest->is_stacked)
+    if (!src->is_stacked && dest->is_stacked)
+    {
+        if (src->type & burm_int_ATTR)
                        hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
-               else
+        else if (src->type & burm_float_ATTR)
+            hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
+        else
+            assert(false);
+    }
+    else if (src->is_stacked && !dest->is_stacked)
+    {
+        if (src->type & burm_int_ATTR)
+                       hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
+        else if (src->type & burm_float_ATTR)
+            hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src);
+        else
+            assert(false);
+    }
+    else if (!src->is_stacked && !dest->is_stacked)
+    {
+        if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
                        hop_add_insel(hop, "mr %H, %H", dest, src);
+        else if ((src->type & burm_float_ATTR) && (dest->type & burm_float_ATTR))
+            hop_add_insel(hop, "fmr %H, %H", dest, src);
+        else
+        {
+            if (src->type & burm_int_ATTR)
+                hop_add_insel(hop, "stwu %H, -4(sp)", src);
+            else if (src->type & burm_float_ATTR)
+                hop_add_insel(hop, "stfsu %H, -4(sp)", src);
+            else
+                assert(false);
+
+            if (dest->type & burm_int_ATTR)
+                hop_add_insel(hop, "lwz %H, 0(sp)", dest);
+            else if (dest->type & burm_float_ATTR)
+                hop_add_insel(hop, "lfs %H, 0(sp)", dest);
+            else
+                assert(false);
+            hop_add_insel(hop, "addi sp, sp, 4");
+        }
        }
        else
                fatal("cannot generate move from %s to %s", src->name, dest->name);
index 93bdb19..3a1da6f 100644 (file)
@@ -16,7 +16,7 @@ REGISTERS
     r6  "r6"  bytes4! int! volatile;
     r5  "r5"  bytes4! int! volatile;
     r4  "r4"  bytes4! int! volatile;
-    r3  "r3"  bytes4! int! ret volatile;
+    r3  "r3"  bytes4! int! volatile ret;
 
     r31 "r31" bytes4! int!; 
     r30 "r30" bytes4! int!; 
@@ -48,7 +48,7 @@ REGISTERS
     f6  "f6"  bytes4! float! volatile;
     f5  "f5"  bytes4! float! volatile;
     f4  "f4"  bytes4! float! volatile;
-    f3  "f3"  bytes4! float! volatile;
+    f3  "f3"  bytes4! float! volatile fret;
     f2  "f2"  bytes4! float! volatile;
     f1  "f1"  bytes4! float! volatile;
     f0  "f0"  bytes4! float! volatile;
@@ -476,6 +476,10 @@ PATTERNS
 
 /* FPU operations */
 
+    out:(float)reg = LOADF4(addr:address)
+        emit "lfs %out, %addr"
+        cost 4;
+        
        out:(float)reg = value:CONSTF4
                emit "lfs %out, address-containing-$value"
                cost 8;
@@ -488,6 +492,32 @@ PATTERNS
                emit "fsubs %out, %left, %right"
                cost 4;
 
+    out:(float)reg = MULF4(left:(float)reg, right:(float)reg)
+        emit "fmuls %out, %left, %right"
+        cost 4;
+
+    out:(float)reg = NEGF4(left:(float)reg)
+        emit "fneg %out, %left"
+        cost 4;
+
+       cr:(cr)cr = COMPAREF4(left:(float)reg, right:(float)reg)
+        emit "fcmpu %cr, %left, %right"
+               cost 4;
+
+    cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4)
+        when specific_constant(%result, 0)
+        emit "fcmpu %cr, %left, %right"
+        cost 4;
+
+    out:(ret)reg = CFI44(val:(fret)reg)
+        with corrupted(volatile)
+        emit "bl .cfi4"
+        cost 4;
+
+    out:(fret)reg = CIF44(val:(ret)reg)
+        with corrupted(volatile)
+        emit "bl .cif4"
+        cost 4;
 
 /* vim: set sw=4 ts=4 expandtab : */
 
index 82d7f98..fcfb551 100644 (file)
@@ -27,7 +27,7 @@ void burm_trace(struct burm_node* p, int ruleno, int cost, int bestcost) {
 void burm_panic_cannot_match(struct burm_node* node)
 {
        fprintf(stderr, "could not find any patterns to match:\n");
-       ir_print(0, node->ir);
+       ir_print('!', node->ir);
        fprintf(stderr, "aborting!\n");
        exit(1);
 }
index 9a5762e..3b0c517 100644 (file)
@@ -14,10 +14,18 @@ void pass_add_prologue_epilogue(void)
             struct hop* hop = bb->hops.item[j];
 
             for (k=0; k<hop->regsin.count; k++)
-                array_appendu(&current_proc->usedregs, hop->regsin.item[k].left);
+            {
+                struct hreg* hreg = hop->regsin.item[k].left;
+                if (!hreg->is_stacked)
+                    array_appendu(&current_proc->usedregs, hreg);
+            }
 
             for (k=0; k<hop->regsout.count; k++)
-                array_appendu(&current_proc->usedregs, hop->regsout.item[k].left);
+            {
+                struct hreg* hreg = hop->regsout.item[k].left;
+                if (!hreg->is_stacked)
+                    array_appendu(&current_proc->usedregs, hreg);
+            }
         }
     }
 
index 393395e..93a9b1d 100644 (file)
@@ -16,6 +16,8 @@ static register_assignment_t* current_outs;
 static int insert_moves(struct basicblock* bb, int index,
     register_assignment_t* srcregs, register_assignment_t* destregs);
 
+static bool type_match(struct hreg* hreg, struct vreg* vreg);
+
 static void populate_hregs(void)
 {
     const struct burm_register_data* brd = burm_register_data;
@@ -65,9 +67,7 @@ static struct hreg* allocate_phi_hreg(register_assignment_t* regs,
 
 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. */
+    return type_match(hreg, vreg) && !array_contains(&current_hop->ins, vreg);
 }
 
 static struct hreg* evict(struct vreg* vreg)
@@ -81,17 +81,26 @@ static struct hreg* evict(struct vreg* vreg)
     for (i=0; i<hregs.count; i++)
     {
         struct hreg* hreg = hregs.item[i];
-        struct vreg* candidate = pmap_findleft(current_ins, hreg);
+        struct vreg* candidatein = pmap_findleft(current_ins, hreg);
+        struct vreg* candidateout = pmap_findleft(current_outs, hreg);
 
-        if (candidate &&
-            (pmap_findleft(current_outs, hreg) == candidate) &&
-            evictable(hreg, vreg))
+        if (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;
+            if (!candidatein && !candidateout)
+            {
+                /* This hreg is unused, so we don't need to evict anything.
+                 * Shouldn't really happen in real life. */
+                return hreg;
+            }
+            if (candidatein == candidateout)
+            {
+                /* This is a through register. */
+                tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->name);
+                pmap_put(&evicted, candidatein, hreg);
+                pmap_remove(current_ins, hreg, candidatein);
+                pmap_remove(current_outs, hreg, candidatein);
+                return hreg;
+            }
         }
     }
 
index 9fbae16..8684f1f 100644 (file)
@@ -197,6 +197,8 @@ static void insn_simple(int opcode)
         case op_cii: simple_convert(IR_CII1); break;
         case op_ciu: simple_convert(IR_CIU1); break;
         case op_cui: simple_convert(IR_CUI1); break;
+        case op_cfi: simple_convert(IR_CFI1); break;
+        case op_cif: simple_convert(IR_CIF1); break;
 
         case op_cmp:
             push(
@@ -460,6 +462,11 @@ static void insn_ivalue(int opcode, arith value)
         case op_dvf: simple_alu2(opcode, value, IR_DIVF); break;
         case op_ngf: simple_alu1(opcode, value, IR_NEGF); break;
 
+        case op_cmu: /* fall through */
+        case op_cms: push(tristate_compare(value, IR_COMPAREU)); break;
+        case op_cmi: push(tristate_compare(value, IR_COMPARES)); break;
+        case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break;
+
         case op_lol:
             push(
                 new_ir1(
@@ -469,6 +476,15 @@ static void insn_ivalue(int opcode, arith value)
             );
             break;
 
+        case op_ldl:
+            push(
+                new_ir1(
+                    IR_LOAD, EM_wordsize*2,
+                    new_localir(value)
+                )
+            );
+            break;
+
         case op_stl:
             appendir(
                 new_ir2(
@@ -634,19 +650,6 @@ static void insn_ivalue(int opcode, arith value)
             break;
         }
 
-        case op_cmi:
-            push(
-                tristate_compare(value, IR_COMPARES)
-            );
-            break;
-
-        case op_cmu:
-        case op_cms:
-            push(
-                tristate_compare(value, IR_COMPAREU)
-            );
-            break;
-
         case op_ads:
         {
             struct ir* off = pop(value);
@@ -953,6 +956,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
 {
     switch (opcode)
     {
+        case op_lpi:
         case op_lae:
             push(
                 address_of_external(label, offset)
index 44e28e9..6f40ae3 100644 (file)
@@ -63,9 +63,20 @@ S CUI2
 S CUI4
 S CUI8
 
+S CFI1
+S CFI2
+S CFI4
+S CFI8
+
+S CIF1
+S CIF2
+S CIF4
+S CIF8
+
 # Tristate comparisons
 S COMPARES
 S COMPAREU
+S COMPAREF
 
 # Boolean comparisons
 S IFEQ