-#include "benode_t.h"
-#include "bechordal_t.h"
-#include "bejavacoal.h"
-#include "benodesets.h"
-#include "bespilloptions.h"
-#include "bestatevent.h"
-
-// only rematerialise when costs are less than REMAT_COST_LIMIT
-// TODO determine a good value here...
-#define REMAT_COST_LIMIT 10
-
-typedef struct _reloader_t reloader_t;
-
-struct _reloader_t {
- reloader_t *next;
- ir_node *reloader;
- ir_node *rematted_node;
-};
-
-typedef struct _spill_info_t {
- /** the value that should get spilled */
- ir_node *spilled_node;
- /** list of places where the value should get reloaded */
- reloader_t *reloaders;
-
- /** the spill node, or a PhiM node */
- ir_node *spill;
- /** if we had the value of a phi spilled before but not the phi itself then
- * this field contains the spill for the phi value */
- ir_node *old_spill;
-
- /** the register class in which the reload should be placed */
- const arch_register_class_t *reload_cls;
-} spill_info_t;
-
-struct _spill_env_t {
- const arch_env_t *arch_env;
- ir_graph *irg;
- struct obstack obst;
- be_irg_t *birg;
- int spill_cost; /**< the cost of a single spill node */
- int reload_cost; /**< the cost of a reload node */
- set *spills; /**< all spill_info_t's, which must be placed */
- pset *mem_phis; /**< set of all special spilled phis. allocated and freed separately */
-
- DEBUG_ONLY(firm_dbg_module_t *dbg;)
-};
-
-/**
- * Compare two spill infos.
- */
-static int cmp_spillinfo(const void *x, const void *y, size_t size) {
- const spill_info_t *xx = x;
- const spill_info_t *yy = y;
- return xx->spilled_node != yy->spilled_node;
-}
-
-/**
- * Returns spill info for a specific value (returns NULL if the info doesn't
- * exist yet)
- */
-static spill_info_t *find_spillinfo(const spill_env_t *env, ir_node *value) {
- spill_info_t info;
- int hash = nodeset_hash(value);
-
- info.spilled_node = value;
-
- return set_find(env->spills, &info, sizeof(info), hash);
-}
-
-/**
- * Returns spill info for a specific value (the value that is to be spilled)
- */
-static spill_info_t *get_spillinfo(const spill_env_t *env, ir_node *value) {
- spill_info_t info, *res;
- int hash = nodeset_hash(value);
-
- info.spilled_node = value;
- res = set_find(env->spills, &info, sizeof(info), hash);
-
- if (res == NULL) {
- info.reloaders = NULL;
- info.spill = NULL;
- info.old_spill = NULL;
- info.reload_cls = NULL;
- res = set_insert(env->spills, &info, sizeof(info), hash);
- }
-
- return res;
-}
-
-DEBUG_ONLY(
-/* Sets the debug module of a spill environment. */
-void be_set_spill_env_dbg_module(spill_env_t *env, firm_dbg_module_t *dbg) {
- env->dbg = dbg;
-}
-)
-
-/* Creates a new spill environment. */
-spill_env_t *be_new_spill_env(be_irg_t *birg) {
- spill_env_t *env = xmalloc(sizeof(env[0]));
- env->spills = new_set(cmp_spillinfo, 1024);
- env->irg = be_get_birg_irg(birg);
- env->birg = birg;
- env->arch_env = birg->main_env->arch_env;
- env->mem_phis = pset_new_ptr_default();
- // TODO, ask backend about costs..., or even ask backend whether we should
- // rematerialize...
- env->spill_cost = 8;
- env->reload_cost = 5;
- obstack_init(&env->obst);
- return env;
-}
-
-/* Deletes a spill environment. */
-void be_delete_spill_env(spill_env_t *env) {
- del_set(env->spills);
- del_pset(env->mem_phis);
- obstack_free(&env->obst, NULL);
- free(env);
-}
-
-/*
- * ____ _ ____ _ _
- * | _ \| | __ _ ___ ___ | _ \ ___| | ___ __ _ __| |___
- * | |_) | |/ _` |/ __/ _ \ | |_) / _ \ |/ _ \ / _` |/ _` / __|
- * | __/| | (_| | (_| __/ | _ < __/ | (_) | (_| | (_| \__ \
- * |_| |_|\__,_|\___\___| |_| \_\___|_|\___/ \__,_|\__,_|___/
- *
- */
-
-void be_add_remat(spill_env_t *env, ir_node *to_spill, ir_node *before, ir_node *rematted_node, const arch_register_class_t *reload_cls) {
- spill_info_t *spill_info;
- reloader_t *reloader;
-
- spill_info = get_spillinfo(env, to_spill);
-
- reloader = obstack_alloc(&env->obst, sizeof(reloader[0]));
- reloader->next = spill_info->reloaders;
- reloader->reloader = before;
- reloader->rematted_node = rematted_node;
-
- spill_info->reloaders = reloader;
- assert(spill_info->reload_cls == NULL || spill_info->reload_cls == reload_cls);
- spill_info->reload_cls = reload_cls;
-}
-
-void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before, const arch_register_class_t *reload_cls) {
- spill_info_t *info;
- reloader_t *rel;
-
- info = get_spillinfo(env, to_spill);
-
- if(is_Phi(to_spill)) {
- int i, arity;
-
- /* create spillinfos for the phi arguments */
- for (i = 0, arity = get_irn_arity(to_spill); i < arity; ++i) {
- ir_node *arg = get_irn_n(to_spill, i);
- get_spillinfo(env, arg);
- }
-
-#if 1
- // hackery... sometimes the morgan algo spilled the value of a phi,
- // the belady algo decides later to spill the whole phi, then sees the
- // spill node and adds a reload for that spill node, problem is the
- // reload gets attach to that same spill (and is totally unnecessary)
- if (info->old_spill != NULL &&
- (before == info->old_spill || value_dominates(before, info->old_spill))) {
- printf("spilledphi hack was needed...\n");
- before = sched_next(info->old_spill);
- }
-#endif
- }