+/**
+ * Spill a node.
+ *
+ * @param senv the spill environment
+ * @param to_spill the node that should be spilled
+ */
+static void spill_node(spill_env_t *env, spill_info_t *spillinfo) {
+ ir_node *to_spill;
+
+ // the node should be tagged for spilling already...
+ if(spillinfo->spill != NULL)
+ return;
+
+ to_spill = spillinfo->spilled_node;
+ if (is_Phi(to_spill) && pset_find_ptr(env->mem_phis, spillinfo->spilled_node)) {
+ spill_phi(env, spillinfo);
+ } else {
+ spill_irn(env, spillinfo);
+ }
+}
+
+/*
+ *
+ * ____ _ _ _ _
+ * | _ \ ___ _ __ ___ __ _| |_ ___ _ __(_) __ _| (_)_______
+ * | |_) / _ \ '_ ` _ \ / _` | __/ _ \ '__| |/ _` | | |_ / _ \
+ * | _ < __/ | | | | | (_| | || __/ | | | (_| | | |/ / __/
+ * |_| \_\___|_| |_| |_|\__,_|\__\___|_| |_|\__,_|_|_/___\___|
+ *
+ */
+
+/**
+ * Tests whether value @p arg is available before node @p reloader
+ * @returns 1 if value is available, 0 otherwise
+ */
+static int is_value_available(spill_env_t *env, ir_node *arg, ir_node *reloader) {
+ if(is_Unknown(arg) || arg == new_NoMem())
+ return 1;
+
+ if(be_is_Spill(arg))
+ return 1;
+
+ if(arg == get_irg_frame(env->chordal_env->irg))
+ return 1;
+
+ /* the following test does not work while spilling,
+ * because the liveness info is not adapted yet to the effects of the
+ * additional spills/reloads.
+ *
+ * So we can only do this test for ignore registers (of our register class)
+ */
+ if(arch_get_irn_reg_class(env->arch_env, arg, -1) == env->chordal_env->cls
+ && arch_irn_is(env->arch_env, arg, ignore)) {
+ int i, arity;
+
+ /* we want to remat before the insn reloader
+ * thus an arguments is alive if
+ * - it interferes with the reloaders result
+ * - or it is (last-) used by reloader itself
+ */
+ if (values_interfere(env->chordal_env->lv, reloader, arg)) {
+ return 1;
+ }
+
+ arity = get_irn_arity(reloader);
+ for (i = 0; i < arity; ++i) {
+ ir_node *rel_arg = get_irn_n(reloader, i);
+ if (rel_arg == arg)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Checks whether the node can principally be rematerialized
+ */
+static int is_remat_node(spill_env_t *env, ir_node *node) {
+ const arch_env_t *arch_env = env->arch_env;
+
+ assert(!be_is_Spill(node));
+
+ if(arch_irn_is(arch_env, node, rematerializable)) {
+ return 1;
+ }
+
+ if(be_is_StackParam(node))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Check if a node is rematerializable. This tests for the following conditions:
+ *
+ * - The node itself is rematerializable
+ * - All arguments of the node are available or also rematerialisable
+ * - The costs for the rematerialisation operation is less or equal a limit
+ *
+ * Returns the costs needed for rematerialisation or something
+ * > REMAT_COST_LIMIT if remat is not possible.
+ */
+static int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled, ir_node *reloader, int parentcosts) {
+ int i, arity;
+ int argremats;
+ int costs = 0;
+
+ if(!is_remat_node(env, spilled))
+ return REMAT_COST_LIMIT;
+
+ if(be_is_Reload(spilled)) {
+ costs += 2;
+ } else {
+ costs += arch_get_op_estimated_cost(env->arch_env, spilled);
+ }
+ if(parentcosts + costs >= REMAT_COST_LIMIT) {
+ return REMAT_COST_LIMIT;
+ }
+
+ argremats = 0;
+ for(i = 0, arity = get_irn_arity(spilled); i < arity; ++i) {
+ ir_node *arg = get_irn_n(spilled, i);
+
+ if(is_value_available(env, arg, reloader))
+ continue;
+
+ // we have to rematerialize the argument as well...
+ if(argremats >= 1) {
+ /* we only support rematerializing 1 argument at the moment,
+ * so that we don't have to care about register pressure
+ */
+ return REMAT_COST_LIMIT;
+ }
+ argremats++;
+
+ costs += check_remat_conditions_costs(env, arg, reloader, parentcosts + costs);
+ if(parentcosts + costs >= REMAT_COST_LIMIT)
+ return REMAT_COST_LIMIT;
+ }
+
+ return costs;
+}
+
+static int check_remat_conditions(spill_env_t *env, ir_node *spilled, ir_node *reloader) {
+ int costs = check_remat_conditions_costs(env, spilled, reloader, 1);
+
+ return costs < REMAT_COST_LIMIT;
+}
+
+/**
+ * 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 *env, ir_node *spilled, ir_node *reloader) {
+ int i, arity;