+void be_add_remat(spill_env_t *env, ir_node *to_spill, ir_node *before, ir_node *rematted_node) {
+ spill_info_t *spill_info;
+ reloader_t *reloader;
+
+ spill_info = get_spillinfo(env, to_spill);
+
+ /* add the remat information */
+ reloader = obstack_alloc(&env->obst, sizeof(reloader[0]));
+ reloader->next = spill_info->reloaders;
+ reloader->reloader = before;
+ reloader->rematted_node = rematted_node;
+ reloader->allow_remat = 1;
+
+ spill_info->reloaders = reloader;
+}
+
+void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before,
+ const arch_register_class_t *reload_cls, int allow_remat)
+{
+ 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
+ }
+
+ /* put reload into list */
+ rel = obstack_alloc(&env->obst, sizeof(rel[0]));
+ rel->next = info->reloaders;
+ rel->reloader = before;
+ rel->rematted_node = NULL;
+ rel->allow_remat = allow_remat;
+
+ info->reloaders = rel;
+ assert(info->reload_cls == NULL || info->reload_cls == reload_cls);
+ info->reload_cls = reload_cls;
+}
+
+static ir_node *get_reload_insertion_point(ir_node *block, int pos) {
+ ir_node *predblock, *last;
+
+ /* simply add the reload to the beginning of the block if we only have 1 predecessor
+ * (we don't need to check for phis as there can't be any in a block with only 1 pred)
+ */
+ if(get_Block_n_cfgpreds(block) == 1) {
+ assert(!is_Phi(sched_first(block)));
+ return sched_first(block);
+ }
+
+ /* We have to reload the value in pred-block */
+ predblock = get_Block_cfgpred_block(block, pos);
+ last = sched_last(predblock);
+
+ /* we might have projs and keepanys behind the jump... */
+ while(is_Proj(last) || be_is_Keep(last)) {
+ last = sched_prev(last);
+ assert(!sched_is_end(last));
+ }
+
+ if(!is_cfop(last)) {
+ ir_graph *irg = get_irn_irg(block);
+ ir_node *startblock = get_irg_start_block(irg);
+
+ last = sched_next(last);
+ // last node must be a cfop, only exception is the start block
+ assert(last == startblock);
+ }
+
+ // add the reload before the (cond-)jump
+ return last;
+}
+
+void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, int pos,
+ const arch_register_class_t *reload_cls, int allow_remat)
+{
+ ir_node *before = get_reload_insertion_point(block, pos);
+ be_add_reload(env, to_spill, before, reload_cls, allow_remat);
+}
+
+void be_spill_phi(spill_env_t *env, ir_node *node) {
+ spill_info_t* spill;
+ int i, arity;
+
+ assert(is_Phi(node));
+
+ pset_insert_ptr(env->mem_phis, node);
+
+ // create spillinfos for the phi arguments
+ spill = get_spillinfo(env, node);
+ for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
+ ir_node *arg = get_irn_n(node, i);
+ get_spillinfo(env, arg);
+ }
+
+ // if we had a spill for the phi value before, then remove this spill from
+ // schedule, as we will remove it in the insert spill/reload phase
+ if(spill->spill != NULL && !is_Phi(spill->spill)) {
+ assert(spill->old_spill == NULL);
+ spill->old_spill = spill->spill;
+ spill->spill = NULL;
+ }
+}
+
+/*
+ * ____ _ ____ _ _ _
+ * / ___|_ __ ___ __ _| |_ ___ / ___| _ __ (_) | |___
+ * | | | '__/ _ \/ _` | __/ _ \ \___ \| '_ \| | | / __|
+ * | |___| | | __/ (_| | || __/ ___) | |_) | | | \__ \
+ * \____|_| \___|\__,_|\__\___| |____/| .__/|_|_|_|___/
+ * |_|
+ */
+
+/**
+ * Schedules a node after an instruction. (That is the place after all projs and phis
+ * that are scheduled after the instruction)
+ * This function also skips phi nodes at the beginning of a block
+ */
+static void sched_add_after_insn(ir_node *sched_after, ir_node *node) {
+ ir_node *next = sched_next(sched_after);
+ while(is_Proj(next) || is_Phi(next)) {
+ next = sched_next(next);
+ }
+ assert(next != NULL);