Lots more opcodes; better eviction behaviour; better register moves. Lots more
PowerPC stuff (some working).
This commit is contained in:
parent
ffb1eabf45
commit
e4fec71f9c
|
@ -99,14 +99,47 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
||||||
{
|
{
|
||||||
struct hop* hop = new_hop(bb, NULL);
|
struct hop* hop = new_hop(bb, NULL);
|
||||||
|
|
||||||
if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
|
if (!src->is_stacked && dest->is_stacked)
|
||||||
{
|
{
|
||||||
if (src->is_stacked)
|
if (src->type & burm_int_ATTR)
|
||||||
hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
|
|
||||||
else if (dest->is_stacked)
|
|
||||||
hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
|
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);
|
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
|
else
|
||||||
fatal("cannot generate move from %s to %s", src->name, dest->name);
|
fatal("cannot generate move from %s to %s", src->name, dest->name);
|
||||||
|
|
|
@ -16,7 +16,7 @@ REGISTERS
|
||||||
r6 "r6" bytes4! int! volatile;
|
r6 "r6" bytes4! int! volatile;
|
||||||
r5 "r5" bytes4! int! volatile;
|
r5 "r5" bytes4! int! volatile;
|
||||||
r4 "r4" bytes4! int! volatile;
|
r4 "r4" bytes4! int! volatile;
|
||||||
r3 "r3" bytes4! int! ret volatile;
|
r3 "r3" bytes4! int! volatile ret;
|
||||||
|
|
||||||
r31 "r31" bytes4! int!;
|
r31 "r31" bytes4! int!;
|
||||||
r30 "r30" bytes4! int!;
|
r30 "r30" bytes4! int!;
|
||||||
|
@ -48,7 +48,7 @@ REGISTERS
|
||||||
f6 "f6" bytes4! float! volatile;
|
f6 "f6" bytes4! float! volatile;
|
||||||
f5 "f5" bytes4! float! volatile;
|
f5 "f5" bytes4! float! volatile;
|
||||||
f4 "f4" bytes4! float! volatile;
|
f4 "f4" bytes4! float! volatile;
|
||||||
f3 "f3" bytes4! float! volatile;
|
f3 "f3" bytes4! float! volatile fret;
|
||||||
f2 "f2" bytes4! float! volatile;
|
f2 "f2" bytes4! float! volatile;
|
||||||
f1 "f1" bytes4! float! volatile;
|
f1 "f1" bytes4! float! volatile;
|
||||||
f0 "f0" bytes4! float! volatile;
|
f0 "f0" bytes4! float! volatile;
|
||||||
|
@ -476,6 +476,10 @@ PATTERNS
|
||||||
|
|
||||||
/* FPU operations */
|
/* FPU operations */
|
||||||
|
|
||||||
|
out:(float)reg = LOADF4(addr:address)
|
||||||
|
emit "lfs %out, %addr"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
out:(float)reg = value:CONSTF4
|
out:(float)reg = value:CONSTF4
|
||||||
emit "lfs %out, address-containing-$value"
|
emit "lfs %out, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
@ -488,6 +492,32 @@ PATTERNS
|
||||||
emit "fsubs %out, %left, %right"
|
emit "fsubs %out, %left, %right"
|
||||||
cost 4;
|
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 : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
||||||
|
|
|
@ -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)
|
void burm_panic_cannot_match(struct burm_node* node)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not find any patterns to match:\n");
|
fprintf(stderr, "could not find any patterns to match:\n");
|
||||||
ir_print(0, node->ir);
|
ir_print('!', node->ir);
|
||||||
fprintf(stderr, "aborting!\n");
|
fprintf(stderr, "aborting!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,18 @@ void pass_add_prologue_epilogue(void)
|
||||||
struct hop* hop = bb->hops.item[j];
|
struct hop* hop = bb->hops.item[j];
|
||||||
|
|
||||||
for (k=0; k<hop->regsin.count; k++)
|
for (k=0; k<hop->regsin.count; k++)
|
||||||
array_appendu(¤t_proc->usedregs, hop->regsin.item[k].left);
|
{
|
||||||
|
struct hreg* hreg = hop->regsin.item[k].left;
|
||||||
|
if (!hreg->is_stacked)
|
||||||
|
array_appendu(¤t_proc->usedregs, hreg);
|
||||||
|
}
|
||||||
|
|
||||||
for (k=0; k<hop->regsout.count; k++)
|
for (k=0; k<hop->regsout.count; k++)
|
||||||
array_appendu(¤t_proc->usedregs, hop->regsout.item[k].left);
|
{
|
||||||
|
struct hreg* hreg = hop->regsout.item[k].left;
|
||||||
|
if (!hreg->is_stacked)
|
||||||
|
array_appendu(¤t_proc->usedregs, hreg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ static register_assignment_t* current_outs;
|
||||||
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);
|
||||||
|
|
||||||
|
static bool type_match(struct hreg* hreg, struct vreg* vreg);
|
||||||
|
|
||||||
static void populate_hregs(void)
|
static void populate_hregs(void)
|
||||||
{
|
{
|
||||||
const struct burm_register_data* brd = burm_register_data;
|
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)
|
static bool evictable(struct hreg* hreg, struct vreg* vreg)
|
||||||
{
|
{
|
||||||
struct constraint* c = pmap_findleft(¤t_hop->constraints, vreg);
|
return type_match(hreg, vreg) && !array_contains(¤t_hop->ins, vreg);
|
||||||
return (hreg->attrs & c->attrs) && !array_contains(¤t_hop->ins, vreg);
|
|
||||||
/* Find an unused output register of the right class which is not also being used as an input register. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hreg* evict(struct vreg* 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++)
|
for (i=0; i<hregs.count; i++)
|
||||||
{
|
{
|
||||||
struct hreg* hreg = hregs.item[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 &&
|
if (evictable(hreg, vreg))
|
||||||
(pmap_findleft(current_outs, hreg) == candidate) &&
|
|
||||||
evictable(hreg, vreg))
|
|
||||||
{
|
{
|
||||||
tracef('R', "R: evicting %%%d from %s\n", candidate->id, hreg->name);
|
if (!candidatein && !candidateout)
|
||||||
pmap_put(&evicted, candidate, hreg);
|
{
|
||||||
pmap_remove(current_ins, hreg, candidate);
|
/* This hreg is unused, so we don't need to evict anything.
|
||||||
pmap_remove(current_outs, hreg, candidate);
|
* Shouldn't really happen in real life. */
|
||||||
return hreg;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,8 @@ static void insn_simple(int opcode)
|
||||||
case op_cii: simple_convert(IR_CII1); break;
|
case op_cii: simple_convert(IR_CII1); break;
|
||||||
case op_ciu: simple_convert(IR_CIU1); break;
|
case op_ciu: simple_convert(IR_CIU1); break;
|
||||||
case op_cui: simple_convert(IR_CUI1); 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:
|
case op_cmp:
|
||||||
push(
|
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_dvf: simple_alu2(opcode, value, IR_DIVF); break;
|
||||||
case op_ngf: simple_alu1(opcode, value, IR_NEGF); 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:
|
case op_lol:
|
||||||
push(
|
push(
|
||||||
new_ir1(
|
new_ir1(
|
||||||
|
@ -469,6 +476,15 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_ldl:
|
||||||
|
push(
|
||||||
|
new_ir1(
|
||||||
|
IR_LOAD, EM_wordsize*2,
|
||||||
|
new_localir(value)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case op_stl:
|
case op_stl:
|
||||||
appendir(
|
appendir(
|
||||||
new_ir2(
|
new_ir2(
|
||||||
|
@ -634,19 +650,6 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
break;
|
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:
|
case op_ads:
|
||||||
{
|
{
|
||||||
struct ir* off = pop(value);
|
struct ir* off = pop(value);
|
||||||
|
@ -953,6 +956,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
|
||||||
{
|
{
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
case op_lpi:
|
||||||
case op_lae:
|
case op_lae:
|
||||||
push(
|
push(
|
||||||
address_of_external(label, offset)
|
address_of_external(label, offset)
|
||||||
|
|
|
@ -63,9 +63,20 @@ S CUI2
|
||||||
S CUI4
|
S CUI4
|
||||||
S CUI8
|
S CUI8
|
||||||
|
|
||||||
|
S CFI1
|
||||||
|
S CFI2
|
||||||
|
S CFI4
|
||||||
|
S CFI8
|
||||||
|
|
||||||
|
S CIF1
|
||||||
|
S CIF2
|
||||||
|
S CIF4
|
||||||
|
S CIF8
|
||||||
|
|
||||||
# Tristate comparisons
|
# Tristate comparisons
|
||||||
S COMPARES
|
S COMPARES
|
||||||
S COMPAREU
|
S COMPAREU
|
||||||
|
S COMPAREF
|
||||||
|
|
||||||
# Boolean comparisons
|
# Boolean comparisons
|
||||||
S IFEQ
|
S IFEQ
|
||||||
|
|
Loading…
Reference in a new issue