#include "beutil.h"
#include "bearch_t.h"
-#include "bespillbelady.h"
#include "beuses.h"
#include "besched_t.h"
#include "beirgmod.h"
#include "bespilloptions.h"
#include "beloopana.h"
#include "beirg_t.h"
+#include "bespill.h"
#include "bemodule.h"
#define DBG_SPILL 1
#define DBG_WORKSET 128
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+/* factor to weight the different costs of reloading/rematerializing a node
+ (see bespill.h be_get_reload_costs_no_weight) */
+#define RELOAD_COST_FACTOR 10
+
typedef enum {
value_not_reloaded, /* the value has not been reloaded */
value_partially_reloaded, /* the value has been reloaded on some paths */
{
be_next_use_t use;
int flags = arch_irn_get_flags(arch_env, def);
+ unsigned costs;
unsigned time;
assert(! (flags & arch_irn_flags_ignore));
if(flags & arch_irn_flags_dont_spill)
return 0;
- time = use.time;
- time += be_get_reload_costs_no_weight(senv, def, use.before) * 10;
+ costs = be_get_reload_costs_no_weight(senv, def, use.before);
+ assert(costs * RELOAD_COST_FACTOR < 1000);
+ time = use.time + 1000 - (costs * RELOAD_COST_FACTOR);
- return use.time;
+ return time;
}
/**
*/
static void displace(workset_t *new_vals, int is_usage)
{
- ir_node *val;
- int i, len, max_allowed, demand, iter;
-
- ir_node **to_insert = alloca(n_regs * sizeof(to_insert[0]));
-
- /*
- 1. Identify the number of needed slots and the values to reload
- */
+ ir_node **to_insert = alloca(n_regs * sizeof(to_insert[0]));
+ ir_node *val;
+ int i;
+ int len;
+ int spills_needed;
+ int demand;
+ int iter;
+
+ /* 1. Identify the number of needed slots and the values to reload */
demand = 0;
workset_foreach(new_vals, val, iter) {
/* mark value as used */
if (! workset_contains(ws, val)) {
DBG((dbg, DBG_DECIDE, " insert %+F\n", val));
- to_insert[demand++] = val;
if (is_usage) {
DBG((dbg, DBG_SPILL, "Reload %+F before %+F\n", val, instr));
be_add_reload(senv, val, instr, cls, 1);
} else {
DBG((dbg, DBG_DECIDE, " %+F already in workset\n", val));
assert(is_usage);
+ /* remove the value from the current workset so it is not accidently
+ * spilled */
+ workset_remove(ws, val);
}
+ to_insert[demand++] = val;
}
- /*
- 2. Make room for at least 'demand' slots
- */
- len = workset_get_length(ws);
- max_allowed = n_regs - demand;
+ /* 2. Make room for at least 'demand' slots */
+ len = workset_get_length(ws);
+ spills_needed = len + demand - n_regs;
+ assert(spills_needed <= len);
/* Only make more free room if we do not have enough */
- if (len > max_allowed) {
- DBG((dbg, DBG_DECIDE, " disposing %d values\n",
- ws->len - max_allowed));
+ if (spills_needed > 0) {
+ ir_node *curr_bb = get_nodes_block(instr);
+ workset_t *ws_start = get_block_info(curr_bb)->start_workset;
+
+ DBG((dbg, DBG_DECIDE, " disposing %d values\n", spills_needed));
- /* get current next-use distance */
- for (i = 0; i < ws->len; ++i) {
+ /* calculate current next-use distance for live values */
+ for (i = 0; i < len; ++i) {
ir_node *val = workset_get_val(ws, i);
unsigned dist = get_distance(instr, instr_nr, val, !is_usage);
workset_set_time(ws, i, dist);
/* sort entries by increasing nextuse-distance*/
workset_sort(ws);
- /*
- Logic for not needed live-ins: If a value is disposed
- before its first usage, remove it from start workset
- We don't do this for phis though
- */
- for (i = max_allowed; i < ws->len; ++i) {
- ir_node *node = ws->vals[i].node;
+ /* Logic for not needed live-ins: If a value is disposed
+ * before its first usage, remove it from start workset
+ * We don't do this for phis though */
+ for (i = len - spills_needed; i < len; ++i) {
+ ir_node *val = ws->vals[i].node;
- DBG((dbg, DBG_DECIDE, " disposing node %+F (%u)\n", node,
+ DBG((dbg, DBG_DECIDE, " disposing node %+F (%u)\n", val,
workset_get_time(ws, i)));
if(!USES_IS_INFINITE(ws->vals[i].time)
&& !ws->vals[i].reloaded) {
- //be_add_spill(senv, node, instr);
+ //be_add_spill(senv, val, instr);
}
- if (is_Phi(node))
- continue;
-
- if (! ir_nodeset_contains(&used, node)) {
- ir_node *curr_bb = get_nodes_block(instr);
- workset_t *ws_start = get_block_info(curr_bb)->start_workset;
- workset_remove(ws_start, node);
-
- DBG((dbg, DBG_DECIDE, " (and removing %+F from start workset)\n", node));
+ if (! ir_nodeset_contains(&used, val)) {
+ workset_remove(ws_start, val);
+ DBG((dbg, DBG_DECIDE, " (and removing %+F from start workset)\n", val));
}
}
/* kill the last 'demand' entries in the array */
- workset_set_length(ws, max_allowed);
+ workset_set_length(ws, len - spills_needed);
}
- /*
- 3. Insert the new values into the workset
- */
- for (i = 0; i < demand; ++i)
- workset_insert(ws, to_insert[i], 1);
+ /* 3. Insert the new values into the workset */
+ for (i = 0; i < demand; ++i) {
+ ir_node *val = to_insert[i];
+
+ workset_insert(ws, val, 1);
+ }
}
/** Decides whether a specific node should be in the start workset or not
+++ /dev/null
-/*
- * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief Beladys spillalgorithm.
- * @author Daniel Grund, Matthias Braun
- * @date 20.09.2005
- * @version $Id$
- */
-#ifndef FIRM_BE_BESPILLBELADY_H
-#define FIRM_BE_BESPILLBELADY_H
-
-#include "beirg.h"
-#include "bearch.h"
-#include "bespill.h"
-
-/**
- * Same as be_spill_belady but reuses an existing spill environment.
- * This is usefull for "pre-spillers" that create some spills+reloads
- * but can't ensure that regpressure never exceeds the number of registers
- */
-void be_spill_belady_spill_env(be_irg_t *birg, const arch_register_class_t *cls,
- spill_env_t *spill_env);
-
-#endif /* FIRM_BE_BESPILLBELADY_H */