Swaps work (at least for registers). More opcodes. Rearrange the stack layout

so we can always trivially find fp, which lets CHAINFP work.
This commit is contained in:
David Given 2016-10-27 21:50:58 +02:00
parent be3dece5af
commit 81525c0f2c
4 changed files with 61 additions and 28 deletions

View file

@ -4,15 +4,19 @@
* *
* | ...params... * | ...params...
* | --------------- <- ab * | --------------- <- ab
* | saved regs
* | ---------------
* | spills * | spills
* | ---------------
* | saved regs
* | LR
* | FP
* | --------------- <- st, fp (a.k.a. lb) * | --------------- <- st, fp (a.k.a. lb)
* | locals * | locals
* | --------------- <- sp * | --------------- <- sp
* V ...user area... * V ...user area...
* *
* st indexes up; lb indexes down. * st indexes up; lb indexes down.
*
* We ensure that dereferencing fp always produces the caller's fp.
*/ */
static ARRAYOF(struct hreg) saved_regs; 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, "addi sp, sp, %d", -(current_proc->fp_to_ab + current_proc->locals_size));
hop_add_insel(hop, "mfspr r0, lr"); 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 + 0);
hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + current_proc->spills_size + 4); 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); 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++) for (i=0; i<saved_regs.count; i++)
{ {
struct hreg* hreg = saved_regs.item[i]; struct hreg* hreg = saved_regs.item[i];
@ -74,7 +79,8 @@ struct hop* platform_epilogue(void)
int i; int i;
int saved_offset; 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++) for (i=0; i<saved_regs.count; i++)
{ {
struct hreg* hreg = saved_regs.item[i]; struct hreg* hreg = saved_regs.item[i];
@ -85,9 +91,9 @@ struct hop* platform_epilogue(void)
saved_offset += 4; 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, "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, "addi sp, fp, %d", current_proc->fp_to_ab);
hop_add_insel(hop, "mr fp, r0"); hop_add_insel(hop, "mr fp, r0");
hop_add_insel(hop, "bclr 20, 0, 0"); hop_add_insel(hop, "bclr 20, 0, 0");
@ -247,5 +253,42 @@ nomove:
fatal("cannot move %s to %s", src->id, dest->id); 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 : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -210,6 +210,10 @@ PATTERNS
emit "mr %out, fp" emit "mr %out, fp"
cost 4; cost 4;
out:(int)reg = CHAINFP.I(in:(int)reg)
emit "lwz %out, 0(%in)"
cost 4;
out:(int)reg = FPTOARGS.I(GETFP.I) out:(int)reg = FPTOARGS.I(GETFP.I)
emit "addi %out, fp, 8" emit "addi %out, fp, 8"
cost 4; cost 4;
@ -641,8 +645,10 @@ PATTERNS
ALUR(DIVU.I, "divwu") ALUR(DIVU.I, "divwu")
ALUR(ASL.I, "slw") ALUR(ASL.I, "slw")
ALUR(ASR.I, "sraw")
ALUR(LSL.I, "slw") ALUR(LSL.I, "slw")
ALUR(LSR.I, "srw")
out:(int)reg = NEG.I(left:(int)reg) out:(int)reg = NEG.I(left:(int)reg)
emit "neg %out, %left" emit "neg %out, %left"
@ -695,10 +701,6 @@ PATTERNS
emit "lfd %out, %addr" emit "lfd %out, %addr"
cost 4; cost 4;
out:(float)reg = value:CONST.F
emit "lfs %out, address-containing-$value"
cost 8;
FPU4R(ADDF.F, "fadds") FPU4R(ADDF.F, "fadds")
FPU8R(ADDF.D, "fadd") FPU8R(ADDF.D, "fadd")

View file

@ -123,6 +123,7 @@ extern void platform_calculate_offsets(void);
extern struct hop* platform_prologue(void); extern struct hop* platform_prologue(void);
extern struct hop* platform_epilogue(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_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* outputfile;
extern FILE* dominance_dot_file; extern FILE* dominance_dot_file;

View 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 */ /* returns the number of instructions inserted */
static int insert_moves(struct basicblock* bb, int index, static int insert_moves(struct basicblock* bb, int index,
register_assignment_t* srcregs, register_assignment_t* destregs) register_assignment_t* srcregs, register_assignment_t* destregs)
@ -640,12 +627,12 @@ static int insert_moves(struct basicblock* bb, int index,
} }
else 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; src = copies.item[0].left;
dest = pmap_findleft(&copies, src); 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, src, dest);
pmap_remove(&copies, dest, src); pmap_remove(&copies, dest, src);
} }