-/**
- * This function should optimize the spill slots.
- * - Coalescing of multiple slots
- * - Ordering the slots
- *
- * Input slots are in @p ssenv->slots
- * @p size The count of initial spill slots in @p ssenv->slots
- * This also is the size of the preallocated array @p ass
- *
- * @return An array of spill slots @p ass in specific order
- **/
-static void optimize_slots(ss_env_t *ssenv, int size, spill_slot_t **ass) {
- int i, o, used_slots;
- pmap_entry *entr;
-
- i=0;
- pmap_foreach(ssenv->slots, entr)
- ass[i++] = entr->value;
-
- /* Sort the array to minimize fragmentation and cache footprint.
- Large slots come first */
- qsort(ass, size, sizeof(ass[0]), ss_sorter);
-
- /* For each spill slot:
- - assign a new offset to this slot
- - xor find another slot to coalesce with */
- used_slots = 0;
- for (i=0; i<size; ++i) { /* for each spill slot */
- ir_node *n1;
- int tgt_slot = -1;
-
- DBG((ssenv->dbg, LEVEL_1, "Spill slot %d members:\n", i));
- for(n1 = pset_first(ass[i]->members); n1; n1 = pset_next(ass[i]->members))
- DBG((ssenv->dbg, LEVEL_1, " %+F\n", n1));
-
-
- for (o=0; o < used_slots && tgt_slot == -1; ++o) { /* for each offset-assigned spill slot */
- /* check inter-slot-pairs for interference */
- ir_node *n2;
- for(n1 = pset_first(ass[i]->members); n1; n1 = pset_next(ass[i]->members))
- for(n2 = pset_first(ass[o]->members); n2; n2 = pset_next(ass[o]->members))
- if(values_interfere(n1, n2)) {
- pset_break(ass[i]->members);
- pset_break(ass[o]->members);
- DBG((ssenv->dbg, LEVEL_1, " Interf %+F -- %+F\n", n1, n2));
- goto interf_detected;
- }
-
- /* if we are here, there is no interference between ass[i] and ass[o] */
- tgt_slot = o;
-
-interf_detected: /*nothing*/ ;
+ /* 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;
+ }