Lots more opcodes; better eviction behaviour; better register moves. Lots more
PowerPC stuff (some working).
This commit is contained in:
		
							parent
							
								
									ffb1eabf45
								
							
						
					
					
						commit
						e4fec71f9c
					
				
					 7 changed files with 131 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 : */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(¤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++)
 | 
			
		||||
                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,
 | 
			
		||||
    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(¤t_hop->constraints, 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. */
 | 
			
		||||
    return type_match(hreg, vreg) && !array_contains(¤t_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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue