X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbespill.c;h=8d98792052b2c665ca46afe3ee612b0359053987;hb=3a0fdee861ad2cfc195fad0a34ee9f9981d28486;hp=4d691c93ec6c5232b5224afa3113ccfb2d3d8a06;hpb=9eed62458866b141e1a392c3ec71a657aded9684;p=libfirm diff --git a/ir/be/bespill.c b/ir/be/bespill.c index 4d691c93e..8d9879205 100644 --- a/ir/be/bespill.c +++ b/ir/be/bespill.c @@ -51,15 +51,15 @@ typedef struct _spill_ctx_t { } spill_ctx_t; struct _spill_env_t { - firm_dbg_module_t *dbg; const arch_register_class_t *cls; const be_chordal_env_t *chordal_env; struct obstack obst; set *spill_ctxs; set *spills; /**< all spill_info_t's, which must be placed */ - pset *mem_phis; /**< set of all special spilled phis. allocated and freed seperately */ + pset *mem_phis; /**< set of all special spilled phis. allocated and freed separately */ decide_irn_t is_mem_phi; /**< callback func to decide if a phi needs special spilling */ void *data; /**< data passed to all callbacks */ + DEBUG_ONLY(firm_dbg_module_t *dbg;) }; static int cmp_spillctx(const void *a, const void *b, size_t n) { @@ -74,15 +74,17 @@ static int cmp_spillinfo(const void *x, const void *y, size_t size) { return ! (xx->spilled_node == yy->spilled_node); } -spill_env_t *be_new_spill_env(firm_dbg_module_t *dbg, - const be_chordal_env_t *chordal_env, - decide_irn_t is_mem_phi, void *data) { +DEBUG_ONLY( +void be_set_spill_env_dbg_module(spill_env_t *env, firm_dbg_module_t *dbg) { + env->dbg = dbg; +} +); +spill_env_t *be_new_spill_env(const be_chordal_env_t *chordal_env, decide_irn_t is_mem_phi, void *data) { spill_env_t *env = xmalloc(sizeof(env[0])); env->spill_ctxs = new_set(cmp_spillctx, 1024); env->spills = new_set(cmp_spillinfo, 1024); env->cls = chordal_env->cls; - env->dbg = dbg; env->is_mem_phi = is_mem_phi; env->data = data; env->chordal_env = chordal_env; @@ -386,14 +388,16 @@ typedef struct _spill_slot_t { } spill_slot_t; typedef struct _ss_env_t { - firm_dbg_module_t *dbg; struct obstack ob; be_chordal_env_t *cenv; pmap *slots; /* maps spill_contexts to spill_slots */ - pmap *types; /* maps modes to types */ + pmap *types; /* maps modes to types */ + DEBUG_ONLY(firm_dbg_module_t *dbg;) } ss_env_t; - +/** + * Walker: compute the spill slots + */ static void compute_spill_slots_walker(ir_node *spill, void *env) { ss_env_t *ssenv = env; ir_node *ctx; @@ -408,12 +412,18 @@ static void compute_spill_slots_walker(ir_node *spill, void *env) { entry = pmap_find(ssenv->slots, ctx); if (!entry) { + struct _arch_env_t *arch_env = ssenv->cenv->birg->main_env->arch_env; + ir_node *spilled = get_irn_n(spill, be_pos_Spill_val); + const arch_register_t *reg = arch_get_irn_register(arch_env, spilled); + const arch_register_class_t *cls = arch_register_get_class(reg); + ir_mode *largest_mode = arch_register_class_mode(cls); + /* this is a new spill context */ ss = obstack_alloc(&ssenv->ob, sizeof(*ss)); - ss->members = pset_new_ptr(8); - ss->largest_mode = get_irn_mode(get_irn_n(spill, be_pos_Spill_val)); - ss->size = get_mode_size_bytes(ss->largest_mode); - ss->align = ss->size; /* TODO Assumed for now */ + ss->members = pset_new_ptr(8); + ss->largest_mode = largest_mode; + ss->size = get_mode_size_bytes(ss->largest_mode); + ss->align = arch_isa_get_reg_class_alignment(arch_env->isa, cls); pmap_insert(ssenv->slots, ctx, ss); } else { ir_node *irn; @@ -430,6 +440,9 @@ static void compute_spill_slots_walker(ir_node *spill, void *env) { pset_insert_ptr(ss->members, spill); } +/** + * qsort compare function, sort spill slots by size. + */ static int ss_sorter(const void *v1, const void *v2) { const spill_slot_t *ss1 = v1; const spill_slot_t *ss2 = v2; @@ -520,24 +533,41 @@ interf_detected: /*nothing*/ ; /** * Returns a spill type for a mode. Keep them in a map to reduce * the number of types. + * + * @param types a map containing all created types + * @param ss the spill slot + * + * Note that type types should are identical for every mode. + * This rule might break if two different register classes return the same + * mode but different alignments. */ -static ir_type *get_spill_type(pmap *types, ir_mode *mode) { - pmap_entry *e = pmap_find(types, mode); +static ir_type *get_spill_type(pmap *types, spill_slot_t *ss) { + pmap_entry *e = pmap_find(types, ss->largest_mode); ir_type *res; if (! e) { char buf[64]; - snprintf(buf, sizeof(buf), "spill_slot_type_%s", get_mode_name(mode)); - res = new_type_primitive(new_id_from_str(buf), mode); - pmap_insert(types, mode, res); + snprintf(buf, sizeof(buf), "spill_slot_type_%s", get_mode_name(ss->largest_mode)); + res = new_type_primitive(new_id_from_str(buf), ss->largest_mode); + set_type_alignment_bytes(res, ss->align); + pmap_insert(types, ss->largest_mode, res); } - else + else { res = e->value; + assert(get_type_alignment_bytes(res) == (int)ss->align); + } return res; } -static void assign_entities(ss_env_t *ssenv, int n, spill_slot_t **ss) { - int i, offset; +/** + * Create spill slot entities on the frame type. + * + * @param ssenv the spill environment + * @param n number of spill slots + * @param ss array of spill slots + */ +static void assign_entities(ss_env_t *ssenv, int n_slots, spill_slot_t *ss[]) { + int i, offset, frame_align; ir_type *frame = get_irg_frame_type(ssenv->cenv->irg); /* aligning by increasing frame size */ @@ -546,7 +576,7 @@ static void assign_entities(ss_env_t *ssenv, int n, spill_slot_t **ss) { set_type_size_bytes(frame, -1); /* create entities and assign offsets according to size and alignment*/ - for (i=0; itypes, ss[i]->largest_mode)); + spill_ent = new_entity(frame, name, get_spill_type(ssenv->types, ss[i])); /* align */ offset = round_up2(offset, ss[i]->align); /* set */ set_entity_offset_bytes(spill_ent, offset); /* next possible offset */ - offset += ss[i]->size; + offset += round_up2(ss[i]->size, ss[i]->align); pset_foreach(ss[i]->members, irn) be_set_Spill_entity(irn, spill_ent); } /* set final size of stack frame */ - set_type_size_bytes(frame, offset); + frame_align = get_type_alignment_bytes(frame); + set_type_size_bytes(frame, round_up2(offset, frame_align)); } void be_compute_spill_offsets(be_chordal_env_t *cenv) { @@ -583,7 +614,7 @@ void be_compute_spill_offsets(be_chordal_env_t *cenv) { ssenv.cenv = cenv; ssenv.slots = pmap_create(); ssenv.types = pmap_create(); - ssenv.dbg = firm_dbg_register("ir.be.spillslots"); + FIRM_DBG_REGISTER(ssenv.dbg, "ir.be.spillslots"); /* Get initial spill slots */ irg_walk_graph(cenv->irg, NULL, compute_spill_slots_walker, &ssenv);