-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 */
- offset = get_type_size_bits(frame) / 8;
- offset = round_up2(offset, ALIGN_SPILL_AREA);
- set_type_size_bytes(frame, -1);
-
- /* create entities and assign offsets according to size and alignment*/
- for (i = 0; i < n_slots; ++i) {
- char buf[64];
- ident *name;
- entity *spill_ent;
- ir_node *irn;
-
- /* build entity */
- snprintf(buf, sizeof(buf), "spill_slot_%d", i);
- name = new_id_from_str(buf);
-
- 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 += round_up2(ss[i]->size, ss[i]->align);
-
- pset_foreach(ss[i]->members, irn)
- be_set_Spill_entity(irn, spill_ent);
+
+void be_insert_spills_reloads(spill_env_t *env)
+{
+ const arch_env_t *arch_env = env->arch_env;
+ const ir_exec_freq *exec_freq = env->exec_freq;
+ spill_info_t *si;
+ ir_nodeset_iterator_t iter;
+ ir_node *node;
+
+ /* create all phi-ms first, this is needed so, that phis, hanging on
+ spilled phis work correctly */
+ foreach_ir_nodeset(&env->mem_phis, node, iter) {
+ spill_info_t *info = get_spillinfo(env, node);
+ spill_node(env, info);
+ }
+
+ /* process each spilled node */
+ for (si = set_first(env->spills); si; si = set_next(env->spills)) {
+ reloader_t *rld;
+ ir_node *to_spill = si->to_spill;
+ ir_mode *mode = get_irn_mode(to_spill);
+ ir_node **copies = NEW_ARR_F(ir_node*, 0);
+ double all_remat_costs = 0; /** costs when we would remat all nodes */
+ int force_remat = 0;
+
+ DBG((dbg, LEVEL_1, "\nhandling all reloaders of %+F:\n", to_spill));
+
+ /* determine possibility of rematerialisations */
+ if(be_do_remats) {
+ for (rld = si->reloaders; rld != NULL; rld = rld->next) {
+ double freq;
+ int remat_cost;
+ int remat_cost_delta;
+ ir_node *block;
+ ir_node *reloader = rld->reloader;
+
+ if(rld->rematted_node != NULL) {
+ DBG((dbg, LEVEL_2, "\tforced remat %+F before %+F\n",
+ rld->rematted_node, reloader));
+ continue;
+ }
+ if(rld->remat_cost_delta >= REMAT_COST_INFINITE) {
+ DBG((dbg, LEVEL_2, "\treload before %+F is forbidden\n",
+ reloader));
+ all_remat_costs = REMAT_COST_INFINITE;
+ continue;
+ }
+
+ remat_cost = check_remat_conditions_costs(env, to_spill,
+ reloader, 0);
+ if(remat_cost >= REMAT_COST_INFINITE) {
+ DBG((dbg, LEVEL_2, "\tremat before %+F not possible\n",
+ reloader));
+ rld->remat_cost_delta = REMAT_COST_INFINITE;
+ all_remat_costs = REMAT_COST_INFINITE;
+ continue;
+ }
+
+ remat_cost_delta = remat_cost - env->reload_cost;
+ rld->remat_cost_delta = remat_cost_delta;
+ block = is_Block(reloader) ? reloader : get_nodes_block(reloader);
+ freq = get_block_execfreq(exec_freq, block);
+ all_remat_costs += remat_cost_delta * freq;
+ DBG((dbg, LEVEL_2, "\tremat costs delta before %+F: "
+ "%d (rel %f)\n", reloader, remat_cost_delta,
+ remat_cost_delta * freq));
+ }
+ if(all_remat_costs < REMAT_COST_INFINITE) {
+ ir_node *block = get_nodes_block(to_spill);
+ double freq = get_block_execfreq(exec_freq, block);
+ /* we don't need the costs for the spill if we can remat
+ all reloaders */
+ all_remat_costs -= env->spill_cost * freq;
+
+ DBG((dbg, LEVEL_2, "\tspill costs %d (rel %f)\n",
+ env->spill_cost, env->spill_cost * freq));
+ }
+
+ if(all_remat_costs < 0) {
+ DBG((dbg, LEVEL_1, "\nforcing remats of all reloaders (%f)\n",
+ all_remat_costs));
+ force_remat = 1;
+ }
+ }
+
+ /* go through all reloads for this spill */
+ for (rld = si->reloaders; rld != NULL; rld = rld->next) {
+ ir_node *copy; /* a reload is a "copy" of the original value */
+
+ if (rld->rematted_node != NULL) {
+ copy = rld->rematted_node;
+ sched_add_before(rld->reloader, copy);
+ } else if (be_do_remats &&
+ (force_remat || rld->remat_cost_delta < 0)) {
+ copy = do_remat(env, to_spill, rld->reloader);
+ } else {
+ /* make sure we have a spill */
+ if (si->spill == NULL) {
+ spill_node(env, si);
+ }
+
+ /* create a reload */
+ copy = be_reload(arch_env, si->reload_cls, rld->reloader, mode,
+ si->spill);
+#ifdef FIRM_STATISTICS
+ env->reload_count++;
+#endif
+ }
+
+ DBG((dbg, LEVEL_1, " %+F of %+F before %+F\n",
+ copy, to_spill, rld->reloader));
+ ARR_APP1(ir_node*, copies, copy);
+ }
+
+ /* if we had any reloads or remats, then we need to reconstruct the
+ * SSA form for the spilled value */
+ if (ARR_LEN(copies) > 0) {
+ be_ssa_construction_env_t senv;
+ /* be_lv_t *lv = be_get_birg_liveness(env->birg); */
+
+ be_ssa_construction_init(&senv, env->birg);
+ be_ssa_construction_add_copy(&senv, to_spill);
+ be_ssa_construction_add_copies(&senv, copies, ARR_LEN(copies));
+ be_ssa_construction_fix_users(&senv, to_spill);
+
+#if 0
+ /* no need to enable this as long as we invalidate liveness
+ after this function... */
+ be_ssa_construction_update_liveness_phis(&senv);
+ be_liveness_update(to_spill);
+ len = ARR_LEN(copies);
+ for(i = 0; i < len; ++i) {
+ be_liveness_update(lv, copies[i]);
+ }
+#endif
+ be_ssa_construction_destroy(&senv);
+ }
+
+ DEL_ARR_F(copies);
+ si->reloaders = NULL;