Phi copies are now inserted as part of type inference. More opcodes.
authorDavid Given <dg@cowlark.com>
Mon, 24 Oct 2016 20:14:08 +0000 (22:14 +0200)
committerDavid Given <dg@cowlark.com>
Mon, 24 Oct 2016 20:14:08 +0000 (22:14 +0200)
mach/powerpc/mcg/platform.c
mach/powerpc/mcg/table
mach/proto/mcg/pass_typeinference.c

index 664ed38..725c997 100644 (file)
@@ -184,6 +184,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
                     hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
                     break;
 
+                case burm_long_ATTR:
+                    hop_add_insel(hop, "stw %0H, 4+%S(fp) ! %H", src, dest, dest);
+                    hop_add_insel(hop, "stw %1H, 0+%S(fp) ! %H", src, dest, dest);
+                    break;
+
                 case burm_double_ATTR:
                     hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest);
                     break;
index 79e2f35..39a5305 100644 (file)
@@ -237,7 +237,7 @@ PATTERNS
         cost 16;
 
     out:(long)reg = COPYD.L(in:(double)reg)
-        emit "sfdu %in, -8(sp)"
+        emit "stfdu %in, -8(sp)"
         emit "lwz %out.0, 4(sp)"
         emit "lwz %out.1, 0(sp)"
         emit "addi sp, sp, 8"
@@ -249,10 +249,14 @@ PATTERNS
 
     /* Stores */
 
+       STORE.D(addr:address, value:(double)reg)
+        emit "sfd %value, %addr"
+               cost 4;
+
        STORE.L(addr:address, value:(long)reg)
                emit "stw %value.0, 4+%addr"
                emit "stw %value.1, 0+%addr"
-               cost 4;
+               cost 8;
 
        STORE.I(addr:address, value:(int)reg)
                emit "stw %value, %addr"
@@ -379,6 +383,11 @@ PATTERNS
         emit "bl .fromf2l"
         cost 4;
 
+    out:(long)reg = FROMSI.D(in:(double)reg)
+        with corrupted(volatile)
+        emit "bl .fromsi2d"
+        cost 4;
+
 #if 0
        /* byte conversions */
 
index 90a0ead..c081a4b 100644 (file)
@@ -226,7 +226,37 @@ static struct ir* new_copy(char wanted, char real, struct ir* ir)
        return copy;
 }
 
-static void insert_copies(void)
+static void insert_copy(struct ir* ir, struct ir** child, char returntype, char childtype)
+{
+    if (*child)
+    {
+        char wanted;
+        char real;
+
+        if ((returntype == '?') && (childtype == '?'))
+        {
+            wanted = ir->type;
+            real = (*child)->type;
+        }
+        else
+        {
+            wanted = effective_type(ir, childtype);
+            real = (*child)->type;
+        }
+
+        if (wanted)
+        {
+            if (wanted != real)
+            {
+                struct ir* copy = new_copy(wanted, real, *child);
+                copy->root = ir->root;
+                *child = copy;
+            }
+        }
+    }
+}
+
+static void insert_ir_copies(void)
 {
        int i;
 
@@ -237,32 +267,45 @@ static void insert_copies(void)
                struct ir* ir = irs.item[i];
                const struct ir_data* ird = &ir_data[ir->opcode];
 
-               if (ir->left)
-               {
-                       char wanted = effective_type(ir, ird->lefttype);
-                       char real = ir->left->type;
+        insert_copy(ir, &ir->left, ird->returntype, ird->lefttype);
+        insert_copy(ir, &ir->right, ird->returntype, ird->righttype);
+       }
+}
 
-                       if (wanted && (wanted != real))
-                       {
-                               struct ir* copy = new_copy(wanted, real, ir->left);
-                               copy->root = ir->root;
-                               ir->left = copy;
-                       }
-               }
+static void insert_phi_copies(void)
+{
+    int i, j;
 
-               if (ir->right)
-               {
-                       char wanted = effective_type(ir, ird->righttype);
-                       char real = ir->right->type;
+    /* If the child of a phi isn't the same type as the phi itself, we need to
+     * insert the copy at the end of the block that exported the value. */
 
-                       if (wanted && (wanted != real))
-                       {
-                               struct ir* copy = new_copy(wanted, real, ir->right);
-                               copy->root = ir->root;
-                               ir->right = copy;
-                       }
-               }
-       }
+    for (i=0; i<irs.count; i++)
+    {
+               struct ir* ir = irs.item[i];
+
+        for (j=0; j<ir->u.phivalue.count; j++)
+        {
+            struct ir* childir = ir->u.phivalue.item[j].right;
+            int wanted = ir->type;
+            int real = childir->type;
+            if (wanted != real)
+            {
+                struct basicblock* childbb = ir->u.phivalue.item[j].left;
+                struct ir* copy = new_copy(wanted, real, childir);
+                copy->root = copy;
+
+                /* The copy gets inserted as the second last item of the child
+                 * basic block. That way it'll happen before the final jump
+                 * that exits the block. */
+
+                array_insert(&childbb->irs, copy, childbb->irs.count-1);
+
+                /* And replace the value in the phi with our copy. */
+
+                ir->u.phivalue.item[j].right = copy;
+            }
+        }
+    }
 }
 
 void pass_infer_types(void)
@@ -270,7 +313,8 @@ void pass_infer_types(void)
        collect_irs();
        propagate_types();
        assign_fallback_types();
-       insert_copies();
+       insert_ir_copies();
+    insert_phi_copies();
 }
 
 /* vim: set sw=4 ts=4 expandtab : */