+ del_set(already_visited_phis);
+
+ /* reset the optimizations */
+ set_optimize(save_optimize);
+ set_opt_normalize(save_normalize);
+
+ return res;
+}
+
+#ifdef REMAT
+
+#ifdef BUGGY_REMAT
+
+/**
+ * Check if a spilled node could be rematerialized.
+ *
+ * @param senv the spill environment
+ * @param spill the Spill node
+ * @param spilled the node that was spilled
+ * @param reloader a irn that requires a reload
+ */
+static int check_remat_conditions(spill_env_t *senv, ir_node *spill, ir_node *spilled, ir_node *reloader) {
+ int pos, max;
+
+ /* check for 'normal' spill and general remat condition */
+ if (!be_is_Spill(spill) || !arch_irn_is(senv->chordal_env->birg->main_env->arch_env, spilled, rematerializable))
+ return 0;
+
+ /* check availability of original arguments */
+ if (is_Block(reloader)) {
+
+ /* we want to remat at the end of a block.
+ * thus all arguments must be alive at the end of the block
+ */
+ for (pos=0, max=get_irn_arity(spilled); pos<max; ++pos) {
+ ir_node *arg = get_irn_n(spilled, pos);
+ if (!is_live_end(reloader, arg))
+ return 0;
+ }
+
+ } else {
+
+ /* we want to remat before the insn reloader
+ * thus an arguments is alive if
+ * - it interferes with the reloaders result
+ * or
+ * - or it is (last-) used by reloader itself
+ */
+ for (pos=0, max=get_irn_arity(spilled); pos<max; ++pos) {
+ ir_node *arg = get_irn_n(spilled, pos);
+ int i, m;
+
+ if (values_interfere(reloader, arg))
+ goto is_alive;
+
+ for (i=0, m=get_irn_arity(reloader); i<m; ++i) {
+ ir_node *rel_arg = get_irn_n(reloader, i);
+ if (rel_arg == arg)
+ goto is_alive;
+ }
+
+ /* arg is not alive before reloader */
+ return 0;
+
+is_alive: ;
+
+ }
+
+ }
+
+ return 1;
+}
+
+#else /* BUGGY_REMAT */
+
+/**
+ * A very simple rematerialization checker.
+ *
+ * @param senv the spill environment
+ * @param spill the Spill node
+ * @param spilled the node that was spilled
+ * @param reloader a irn that requires a reload
+ */
+static int check_remat_conditions(spill_env_t *senv, ir_node *spill, ir_node *spilled, ir_node *reloader) {
+ const arch_env_t *aenv = senv->chordal_env->birg->main_env->arch_env;
+
+ return get_irn_arity(spilled) == 0 &&
+ be_is_Spill(spill) &&
+ arch_irn_is(aenv, spilled, rematerializable);
+}
+
+#endif /* BUGGY_REMAT */
+
+#endif /* REMAT */
+
+/**
+ * Re-materialize a node.
+ *
+ * @param senv the spill environment
+ * @param spilled the node that was spilled
+ * @param reloader a irn that requires a reload
+ */
+static ir_node *do_remat(spill_env_t *senv, ir_node *spilled, ir_node *reloader) {
+ ir_node *res;
+ ir_node *bl = (is_Block(reloader)) ? reloader : get_nodes_block(reloader);
+
+ /* recompute the value */
+ res = new_ir_node(get_irn_dbg_info(spilled), senv->chordal_env->irg, bl,
+ get_irn_op(spilled),
+ get_irn_mode(spilled),
+ get_irn_arity(spilled),
+ get_irn_in(spilled) + 1);
+ copy_node_attr(spilled, res);
+
+ DBG((senv->dbg, LEVEL_1, "Insert remat %+F before reloader %+F\n", res, reloader));
+
+ /* insert in schedule */
+ if (is_Block(reloader)) {
+ ir_node *insert = sched_skip(reloader, 0, sched_skip_cf_predicator, (void *) senv->chordal_env->birg->main_env->arch_env);
+ sched_add_after(insert, res);
+ } else {
+ sched_add_before(reloader, res);
+ }
+