+ if (!bitset_is_empty(reloads))
+ be_add_spill(env, si->to_spill, si->to_spill);
+}
+
+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;
+
+ BE_TIMER_PUSH(t_ra_spill_apply);
+
+ /* 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_spill_costs(env, si);
+
+ /* determine possibility of rematerialisations */
+ if(be_do_remats) {
+ /* calculate cost savings for each indivial value when it would
+ be rematted instead of reloaded */
+ 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) {
+ /* we don't need the costs for the spill if we can remat
+ all reloaders */
+ all_remat_costs -= si->spill_costs;
+
+ DBG((dbg, LEVEL_2, "\tspill costs %d (rel %f)\n",
+ env->spill_cost, si->spill_costs));
+ }
+
+ 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 */
+ spill_node(env, si);
+
+ /* create a reload, use the first spill for now SSA
+ * reconstruction for memory comes below */
+ assert(si->spills != NULL);
+ copy = be_reload(arch_env, si->reload_cls, rld->reloader, mode,
+ si->spills->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);
+ }
+ /* need to reconstruct SSA form if we had multiple spills */
+ if (si->spills != NULL && si->spills->next != NULL) {
+ spill_t *spill;
+ int spill_count = 0;
+
+ be_ssa_construction_env_t senv;
+
+ be_ssa_construction_init(&senv, env->birg);
+ spill = si->spills;
+ for( ; spill != NULL; spill = spill->next) {
+ /* maybe we rematerialized the value and need no spill */
+ if(spill->spill == NULL)
+ continue;
+ be_ssa_construction_add_copy(&senv, spill->spill);
+ spill_count++;
+ }
+ if(spill_count > 1) {
+ /* all reloads are attached to the first spill, fix them now */
+ be_ssa_construction_fix_users(&senv, si->spills->spill);
+ }
+
+ be_ssa_construction_destroy(&senv);
+ }
+
+ DEL_ARR_F(copies);
+ si->reloaders = NULL;
+ }
+
+ stat_ev_dbl("spill_spills", env->spill_count);
+ stat_ev_dbl("spill_reloads", env->reload_count);
+ stat_ev_dbl("spill_remats", env->remat_count);
+ stat_ev_dbl("spill_spilled_phis", env->spilled_phi_count);
+
+ /* Matze: In theory be_ssa_construction should take care of the liveness...
+ * try to disable this again in the future */
+ be_liveness_invalidate(env->birg->lv);
+
+ be_remove_dead_nodes_from_schedule(env->birg);
+
+ BE_TIMER_POP(t_ra_spill_apply);
+}
+
+void be_init_spill(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.spill");