Swaps work (at least for registers). More opcodes. Rearrange the stack layout
authorDavid Given <dg@cowlark.com>
Thu, 27 Oct 2016 19:50:58 +0000 (21:50 +0200)
committerDavid Given <dg@cowlark.com>
Thu, 27 Oct 2016 19:50:58 +0000 (21:50 +0200)
so we can always trivially find fp, which lets CHAINFP work.

mach/powerpc/mcg/platform.c
mach/powerpc/mcg/table
mach/proto/mcg/mcg.h
mach/proto/mcg/pass_registerallocator.c

index a049de3..7d8499e 100644 (file)
@@ -4,15 +4,19 @@
  *
  * |    ...params...
  * |  --------------- <- ab
- * |     saved regs
+ * |      spills
  * |  ---------------
- * |      spills 
+ * |     saved regs
+ * |         LR
+ * |         FP
  * |  --------------- <- st, fp (a.k.a. lb)
  * |      locals
  * |  --------------- <- sp
  * V  ...user area...
  *
  * st indexes up; lb indexes down.
+ *
+ * We ensure that dereferencing fp always produces the caller's fp.
  */
 
 static ARRAYOF(struct hreg) saved_regs;
@@ -51,11 +55,12 @@ struct hop* platform_prologue(void)
        hop_add_insel(hop, "addi sp, sp, %d", -(current_proc->fp_to_ab + current_proc->locals_size));
        hop_add_insel(hop, "mfspr r0, lr");
 
-       hop_add_insel(hop, "stw r0, %d(sp)", current_proc->locals_size + current_proc->spills_size);
-       hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + current_proc->spills_size + 4);
+       hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + 0);
+       hop_add_insel(hop, "stw r0, %d(sp)", current_proc->locals_size + 4);
        hop_add_insel(hop, "addi fp, sp, %d", current_proc->locals_size);
 
-    saved_offset = current_proc->spills_size + 8;
+    /* Saved reg offsets are negative. */
+    saved_offset = current_proc->saved_size + 8;
     for (i=0; i<saved_regs.count; i++)
     {
         struct hreg* hreg = saved_regs.item[i];
@@ -74,7 +79,8 @@ struct hop* platform_epilogue(void)
     int i;
     int saved_offset;
 
-    saved_offset = current_proc->spills_size + 8;
+    /* Saved reg offsets are negative. */
+    saved_offset = current_proc->saved_size + 8;
     for (i=0; i<saved_regs.count; i++)
     {
         struct hreg* hreg = saved_regs.item[i];
@@ -85,9 +91,9 @@ struct hop* platform_epilogue(void)
         saved_offset += 4;
     }
 
-    hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size);
+    hop_add_insel(hop, "lwz r0, 4(fp)");
     hop_add_insel(hop, "mtspr lr, r0");
-    hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size + 4);
+    hop_add_insel(hop, "lwz r0, 0(fp)"); /* load old fp */
     hop_add_insel(hop, "addi sp, fp, %d", current_proc->fp_to_ab);
     hop_add_insel(hop, "mr fp, r0");
     hop_add_insel(hop, "bclr 20, 0, 0");
@@ -247,5 +253,42 @@ nomove:
     fatal("cannot move %s to %s", src->id, dest->id);
 }
 
+struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
+{
+    struct hop* hop = new_hop(bb, NULL);
+
+    assert(!src->is_stacked);
+    assert(!dest->is_stacked);
+    assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS));
+    
+    switch (src->attrs & TYPE_ATTRS)
+    {
+        case burm_int_ATTR:
+            hop_add_insel(hop, "mr r0, %H", src);
+            hop_add_insel(hop, "mr %H, %H", src, dest);
+            hop_add_insel(hop, "mr %H, r0", dest);
+            break;
+
+        case burm_long_ATTR:
+            hop_add_insel(hop, "mr r0, %0H", src);
+            hop_add_insel(hop, "mr %0H, %0H", src, dest);
+            hop_add_insel(hop, "mr %0H, r0", dest);
+
+            hop_add_insel(hop, "mr r0, %1H", src);
+            hop_add_insel(hop, "mr %1H, %1H", src, dest);
+            hop_add_insel(hop, "mr %1H, r0", dest);
+            break;
+
+        case burm_float_ATTR:
+        case burm_double_ATTR:
+            hop_add_insel(hop, "fmr f0, %H", src);
+            hop_add_insel(hop, "fmr %H, %H", src, dest);
+            hop_add_insel(hop, "fmr %H, f0", dest);
+            break;
+    }
+
+    return hop;
+}
+
 /* vim: set sw=4 ts=4 expandtab : */
 
index 0ffbc40..5b97ae4 100644 (file)
@@ -210,6 +210,10 @@ PATTERNS
         emit "mr %out, fp"
         cost 4;
 
+    out:(int)reg = CHAINFP.I(in:(int)reg)
+        emit "lwz %out, 0(%in)"
+        cost 4;
+
     out:(int)reg = FPTOARGS.I(GETFP.I)
         emit "addi %out, fp, 8"
         cost 4;
@@ -641,8 +645,10 @@ PATTERNS
     ALUR(DIVU.I, "divwu")
 
     ALUR(ASL.I, "slw")
+    ALUR(ASR.I, "sraw")
 
     ALUR(LSL.I, "slw")
+    ALUR(LSR.I, "srw")
 
     out:(int)reg = NEG.I(left:(int)reg)
         emit "neg %out, %left"
@@ -694,10 +700,6 @@ PATTERNS
     out:(double)reg = LOAD.D(addr:address)
         emit "lfd %out, %addr"
         cost 4;
-        
-       out:(float)reg = value:CONST.F
-               emit "lfs %out, address-containing-$value"
-               cost 8;
 
     FPU4R(ADDF.F, "fadds")
     FPU8R(ADDF.D, "fadd")
index c60dee9..13a3d23 100644 (file)
@@ -123,6 +123,7 @@ extern void platform_calculate_offsets(void);
 extern struct hop* platform_prologue(void);
 extern struct hop* platform_epilogue(void);
 extern struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest);
+extern struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest);
 
 extern FILE* outputfile;
 extern FILE* dominance_dot_file;
index fd10b22..0a6eba6 100644 (file)
@@ -578,19 +578,6 @@ static void assign_hregs_to_vregs(void)
     }
 }
 
-static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
-{
-    struct hop* hop = new_hop(bb, NULL);
-
-    hop_add_string_insel(hop, "! swap ");
-    hop_add_hreg_insel(hop, src, 0);
-    hop_add_string_insel(hop, " <-> ");
-    hop_add_hreg_insel(hop, dest, 0);
-    hop_add_eoi_insel(hop);
-
-    return hop;
-}
-
 /* returns the number of instructions inserted */
 static int insert_moves(struct basicblock* bb, int index,
     register_assignment_t* srcregs, register_assignment_t* destregs)
@@ -640,12 +627,12 @@ static int insert_moves(struct basicblock* bb, int index,
         }
         else
         {
-            /* Swap. */
+            /* There's nowhere to copy to --- the copies that are left form a cycle.
+             * So we need to swap instead. */
             
-            assert(false);
             src = copies.item[0].left;
             dest = pmap_findleft(&copies, src);
-            hop = create_swap(bb, src, dest);
+            hop = platform_swap(bb, src, dest);
             pmap_remove(&copies, src, dest);
             pmap_remove(&copies, dest, src);
         }