- Part1 of backend reorganisation:
authorMatthias Braun <matze@braunis.de>
Thu, 23 Oct 2008 18:02:53 +0000 (18:02 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 23 Oct 2008 18:02:53 +0000 (18:02 +0000)
Node flags and node registers are stored in a generic backend_info struct now
instead of every part of the backend doing custom (and slow) stuff

[r23142]

53 files changed:
ir/be/TEMPLATE/TEMPLATE_new_nodes.c
ir/be/TEMPLATE/bearch_TEMPLATE.c
ir/be/arm/arm_new_nodes.c
ir/be/arm/arm_spec.pl
ir/be/arm/bearch_arm.c
ir/be/beabi.c
ir/be/bearch.c
ir/be/bearch.h
ir/be/bearch_t.h
ir/be/bechordal.c
ir/be/becopyheur2.c
ir/be/becopyheur4.c
ir/be/becopyilp2.c
ir/be/becopyopt.c
ir/be/beifg.c
ir/be/belower.c
ir/be/bemain.c
ir/be/benode.c
ir/be/benode_t.h
ir/be/besched.c
ir/be/besched.h
ir/be/besched_t.h
ir/be/beschednormal.c
ir/be/beschedrss.c
ir/be/beschedtrace.c
ir/be/bespill.c
ir/be/bespillbelady.c
ir/be/bespillbelady2.c
ir/be/bespillremat.c [deleted file]
ir/be/bespillremat.h [deleted file]
ir/be/bessadestr.c
ir/be/bestate.c
ir/be/beverify.c
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_finish.c
ir/be/ia32/ia32_fpu.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_new_nodes.h
ir/be/ia32/ia32_nodes_attr.h
ir/be/ia32/ia32_optimize.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/ia32/ia32_x87.c
ir/be/mips/bearch_mips.c
ir/be/mips/mips_new_nodes.c
ir/be/mips/mips_spec.pl
ir/be/ppc32/bearch_ppc32.c
ir/be/ppc32/ppc32_new_nodes.c
ir/be/ppc32/ppc32_spec.pl
ir/be/scripts/generate_new_opcodes.pl
ir/ir/irnode.c
ir/ir/irtypes.h

index 4333cbd..d3ff9ba 100644 (file)
@@ -205,9 +205,6 @@ static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                if (attr->flags & arch_irn_flags_rematerializable) {
                                        fprintf(F, " remat");
                                }
-                               if (attr->flags & arch_irn_flags_ignore) {
-                                       fprintf(F, " ignore");
-                               }
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
index 367ddaf..9731e29 100644 (file)
@@ -112,49 +112,6 @@ static const arch_register_req_t *TEMPLATE_get_irn_reg_req(const ir_node *node,
        return arch_no_register_req;
 }
 
-static void TEMPLATE_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       int pos = 0;
-
-       if (is_Proj(irn)) {
-               pos = TEMPLATE_translate_proj_pos(irn);
-               irn = skip_Proj(irn);
-       }
-
-       if (is_TEMPLATE_irn(irn)) {
-               const arch_register_t **slots;
-
-               slots      = get_TEMPLATE_slots(irn);
-               slots[pos] = reg;
-       }
-       else {
-               /* here we set the registers for the Phi nodes */
-               TEMPLATE_set_firm_reg(irn, reg, cur_reg_set);
-       }
-}
-
-static const arch_register_t *TEMPLATE_get_irn_reg(const ir_node *irn)
-{
-       int pos = 0;
-       const arch_register_t *reg = NULL;
-
-       if (is_Proj(irn)) {
-               pos = TEMPLATE_translate_proj_pos(irn);
-               irn = skip_Proj_const(irn);
-       }
-
-       if (is_TEMPLATE_irn(irn)) {
-               const arch_register_t * const *slots;
-               slots = get_TEMPLATE_slots_const(irn);
-               reg   = slots[pos];
-       }
-       else {
-               reg = TEMPLATE_get_firm_reg(irn, cur_reg_set);
-       }
-
-       return reg;
-}
-
 static arch_irn_class_t TEMPLATE_classify(const ir_node *irn)
 {
        irn = skip_Proj_const(irn);
@@ -166,20 +123,6 @@ static arch_irn_class_t TEMPLATE_classify(const ir_node *irn)
        return 0;
 }
 
-static arch_irn_flags_t TEMPLATE_get_flags(const ir_node *irn)
-{
-       irn = skip_Proj_const(irn);
-
-       if (is_TEMPLATE_irn(irn)) {
-               return get_TEMPLATE_flags(irn);
-       }
-       else if (is_Unknown(irn)) {
-               return arch_irn_flags_ignore;
-       }
-
-       return 0;
-}
-
 static ir_entity *TEMPLATE_get_frame_entity(const ir_node *node)
 {
        (void) node;
@@ -215,10 +158,7 @@ static int TEMPLATE_get_sp_bias(const ir_node *irn)
 
 static const arch_irn_ops_t TEMPLATE_irn_ops = {
        TEMPLATE_get_irn_reg_req,
-       TEMPLATE_set_irn_reg,
-       TEMPLATE_get_irn_reg,
        TEMPLATE_classify,
-       TEMPLATE_get_flags,
        TEMPLATE_get_frame_entity,
        TEMPLATE_set_frame_entity,
        TEMPLATE_set_frame_offset,
@@ -664,6 +604,7 @@ static int TEMPLATE_is_valid_clobber(const void *self, const char *clobber)
 const arch_isa_if_t TEMPLATE_isa_if = {
        TEMPLATE_init,
        TEMPLATE_done,
+       NULL,                /* handle intrinsics */
        TEMPLATE_get_n_reg_class,
        TEMPLATE_get_reg_class,
        TEMPLATE_get_reg_class_for_mode,
index 8fe748e..5b2a3e1 100644 (file)
@@ -235,9 +235,6 @@ static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                if (attr->flags & arch_irn_flags_rematerializable) {
                                        fprintf(F, " remat");
                                }
-                               if (attr->flags & arch_irn_flags_ignore) {
-                                       fprintf(F, " ignore");
-                               }
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
index 3adff66..8e5a9d4 100644 (file)
@@ -10,99 +10,6 @@ $new_emit_syntax = 1;
 # the number of additional opcodes you want to register
 #$additional_opcodes = 0;
 
-# The node description is done as a perl hash initializer with the
-# following structure:
-#
-# %nodes = (
-#
-# <op-name> => {
-#   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
-#   irn_flags => "R|N|I|S"
-#   arity     => "0|1|2|3 ... |variable|dynamic|any",
-#   state     => "floats|pinned|mem_pinned|exc_pinned",
-#   args      => [
-#                    { type => "type 1", name => "name 1" },
-#                    { type => "type 2", name => "name 2" },
-#                    ...
-#                  ],
-#   comment   => "any comment for constructor",
-#   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
-#   cmp_attr  => "c source code for comparing node attributes",
-#   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
-#   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
-#   mode      => "mode_Iu"          # optional, predefines the mode
-#   emit      => "emit code with templates",
-#   attr      => "attitional attribute arguments for constructor",
-#   init_attr => "emit attribute initialization template",
-#   rd_constructor => "c source code which constructs an ir_node"
-#   hash_func => "name of the hash function for this operation",
-#   latency   => "latency of this operation (can be float)"
-#   attr_type => "name of the attribute struct",
-# },
-#
-# ... # (all nodes you need to describe)
-#
-# ); # close the %nodes initializer
-
-# op_flags: flags for the operation, OPTIONAL (default is "N")
-# the op_flags correspond to the firm irop_flags:
-#   N   irop_flag_none
-#   L   irop_flag_labeled
-#   C   irop_flag_commutative
-#   X   irop_flag_cfopcode
-#   I   irop_flag_ip_cfopcode
-#   F   irop_flag_fragile
-#   Y   irop_flag_forking
-#   H   irop_flag_highlevel
-#   c   irop_flag_constlike
-#   K   irop_flag_keep
-#
-# irn_flags: special node flags, OPTIONAL (default is 0)
-# following irn_flags are supported:
-#   R   rematerializeable
-#   N   not spillable
-#   I   ignore for register allocation
-#   S   modifies stack pointer
-#
-# state: state of the operation, OPTIONAL (default is "floats")
-#
-# arity: arity of the operation, MUST NOT BE OMITTED
-#
-# args:  the OPTIONAL arguments of the node constructor (debug, irg and block
-#        are always the first 3 arguments and are always autmatically
-#        created)
-#        If this key is missing the following arguments will be created:
-#        for i = 1 .. arity: ir_node *op_i
-#        ir_mode *mode
-#
-# outs:  if a node defines more than one output, the names of the projections
-#        nodes having outs having automatically the mode mode_T
-#        One can also annotate some flags for each out, additional to irn_flags.
-#        They are separated from name with a colon ':', and concatenated by pipe '|'
-#        Only I and S are available at the moment (same meaning as in irn_flags).
-#        example: [ "frame:I", "stack:I|S", "M" ]
-#
-# comment: OPTIONAL comment for the node constructor
-#
-# rd_constructor: for every operation there will be a
-#      new_rd_<arch>_<op-name> function with the arguments from above
-#      which creates the ir_node corresponding to the defined operation
-#      you can either put the complete source code of this function here
-#
-#      This key is OPTIONAL. If omitted, the following constructor will
-#      be created:
-#      if (!op_<arch>_<op-name>) assert(0);
-#      for i = 1 to arity
-#         set in[i] = op_i
-#      done
-#      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
-#      return res
-#
-# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
-#
-# latency: the latency of the operation, default is 1
-#
-
 #
 # Modes
 #
@@ -232,8 +139,7 @@ $default_copy_attr = "arm_copy_attr";
 Unknown_GP => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "gp_UKNWN" ] },
+       reg_req   => { out => [ "gp_UKNWN:I" ] },
        emit      => "",
        mode      => $mode_gp,
 },
@@ -241,8 +147,7 @@ Unknown_GP => {
 Unknown_FPA => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "fpa_UKNWN" ] },
+       reg_req   => { out => [ "fpa_UKNWN:I" ] },
        emit      => "",
        mode      => $mode_fpa,
 },
@@ -1029,21 +934,19 @@ fpaDbl2GP => {
 },
 
 AddSP => {
-       irn_flags => "I",
        comment   => "construct Add to stack pointer",
-       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
+       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
        emit      => '. add %D0, %S0, %S1',
-       outs      => [ "stack:I|S", "M" ],
+       outs      => [ "stack", "M" ],
 },
 
 SubSPandCopy => {
-#irn_flags => "I",
        comment   => "construct Sub from stack pointer and copy to Register",
-       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "gp", "none" ] },
+       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
        ins       => [ "stack", "size", "mem" ],
        emit      => ". sub %D0, %S0, %S1\n".
                     ". mov sp, %D1",
-       outs      => [ "stack:I|S", "addr", "M" ],
+       outs      => [ "stack", "addr", "M" ],
 },
 
 LdTls => {
index a02e900..eeb378f 100644 (file)
@@ -130,58 +130,6 @@ static const arch_register_req_t *arm_get_irn_reg_req(const ir_node *node,
        return arch_no_register_req;
 }
 
-static void arm_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       int pos = 0;
-
-       if (get_irn_mode(irn) == mode_X) {
-               return;
-       }
-
-       if (is_Proj(irn)) {
-               pos = get_Proj_proj(irn);
-               irn = skip_Proj(irn);
-       }
-
-       if (is_arm_irn(irn)) {
-               const arch_register_t **slots;
-
-               slots      = get_arm_slots(irn);
-               slots[pos] = reg;
-       }
-       else {
-               /* here we set the registers for the Phi nodes */
-               arm_set_firm_reg(irn, reg, cur_reg_set);
-       }
-}
-
-static const arch_register_t *arm_get_irn_reg(const ir_node *irn)
-{
-       int pos = 0;
-       const arch_register_t *reg = NULL;
-
-       if (is_Proj(irn)) {
-
-               if (get_irn_mode(irn) == mode_X) {
-                       return NULL;
-               }
-
-               pos = get_Proj_proj(irn);
-               irn = skip_Proj_const(irn);
-       }
-
-       if (is_arm_irn(irn)) {
-               const arch_register_t **slots;
-               slots = get_arm_slots(irn);
-               reg   = slots[pos];
-       }
-       else {
-               reg = arm_get_firm_reg(irn, cur_reg_set);
-       }
-
-       return reg;
-}
-
 static arch_irn_class_t arm_classify(const ir_node *irn)
 {
        irn = skip_Proj_const(irn);
@@ -193,29 +141,6 @@ static arch_irn_class_t arm_classify(const ir_node *irn)
        return 0;
 }
 
-static arch_irn_flags_t arm_get_flags(const ir_node *irn)
-{
-       arch_irn_flags_t flags = arch_irn_flags_none;
-
-       if(is_Unknown(irn)) {
-               return arch_irn_flags_ignore;
-       }
-
-       if (is_Proj(irn) && mode_is_datab(get_irn_mode(irn))) {
-               ir_node *pred = get_Proj_pred(irn);
-               if (is_arm_irn(pred)) {
-                       flags = get_arm_out_flags(pred, get_Proj_proj(irn));
-               }
-               irn = pred;
-       }
-
-       if (is_arm_irn(irn)) {
-               flags |= get_arm_flags(irn);
-       }
-
-       return flags;
-}
-
 static ir_entity *arm_get_frame_entity(const ir_node *irn) {
        /* we do NOT transform be_Spill or be_Reload nodes, so we never
           have frame access using ARM nodes. */
@@ -250,10 +175,7 @@ static int arm_get_sp_bias(const ir_node *irn)
 
 static const arch_irn_ops_t arm_irn_ops = {
        arm_get_irn_reg_req,
-       arm_set_irn_reg,
-       arm_get_irn_reg,
        arm_classify,
-       arm_get_flags,
        arm_get_frame_entity,
        arm_set_frame_entity,
        arm_set_stack_bias,
@@ -908,8 +830,7 @@ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *
        block = get_irg_start_block(irg);
 
        ip = be_new_Copy(gp, irg, block, sp);
-       arch_set_irn_register(ip, &arm_gp_regs[REG_R12]);
-       be_set_constr_single_reg(ip, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
+       be_set_constr_single_reg_out(ip, 0, &arm_gp_regs[REG_R12], arch_register_req_type_produces_sp);
 
        store = new_rd_arm_StoreStackM4Inc(NULL, irg, block, sp, fp, ip, lr, pc, *mem);
 
@@ -918,15 +839,13 @@ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *
        *mem = new_r_Proj(irg, block, store, mode_M, pn_arm_StoreStackM4Inc_M);
 
        keep = be_new_CopyKeep_single(gp, irg, block, ip, sp, get_irn_mode(ip));
-       be_node_set_reg_class(keep, 1, gp);
-       arch_set_irn_register(keep, &arm_gp_regs[REG_R12]);
-       be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
+       be_node_set_reg_class_in(keep, 1, gp);
+       be_set_constr_single_reg_out(keep, 0, &arm_gp_regs[REG_R12], arch_register_req_type_produces_sp);
 
        fp = new_rd_arm_Sub_i(NULL, irg, block, keep, get_irn_mode(fp), 4);
        arch_set_irn_register(fp, env->arch_env->bp);
-       fp = be_new_Copy(gp, irg, block, fp); // XXX Gammelfix: only be_ nodes can have the ignore flag set
-       arch_set_irn_register(fp, env->arch_env->bp);
-       be_node_set_flags(fp, BE_OUT_POS(0), arch_irn_flags_ignore);
+       fp = be_new_Copy(gp, irg, block, fp); // XXX Gammelfix: only be_ have custom register requirements
+       be_set_constr_single_reg_out(fp, 0, env->arch_env->bp, 0);
 
        be_abi_reg_map_set(reg_map, env->arch_env->bp, fp);
        be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], keep);
@@ -952,14 +871,10 @@ static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_m
                curr_sp = be_new_IncSP(env->arch_env->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
 
                curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr, curr_sp, get_irn_mode(curr_lr));
-               be_node_set_reg_class(curr_lr, 1, &arm_reg_classes[CLASS_arm_gp]);
-               arch_set_irn_register(curr_lr, &arm_gp_regs[REG_LR]);
-               be_set_constr_single_reg(curr_lr, BE_OUT_POS(0), &arm_gp_regs[REG_LR] );
+               be_set_constr_single_reg_out(curr_lr, 0, &arm_gp_regs[REG_LR], 0);
 
                curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr );
-               arch_set_irn_register(curr_pc, &arm_gp_regs[REG_PC]);
-               be_set_constr_single_reg(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC] );
-               be_node_set_flags(curr_pc, BE_OUT_POS(0), arch_irn_flags_ignore);
+               be_set_constr_single_reg_out(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC], 0);
        } else {
                ir_node *sub12_node;
                ir_node *load_node;
@@ -1243,6 +1158,7 @@ static const lc_opt_table_entry_t arm_options[] = {
 const arch_isa_if_t arm_isa_if = {
        arm_init,
        arm_done,
+       NULL,  /* handle_intrinsics */
        arm_get_n_reg_class,
        arm_get_reg_class,
        arm_get_reg_class_for_mode,
index 5a39c29..8e73d0c 100644 (file)
@@ -665,10 +665,9 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
        /* create new stack pointer */
        curr_sp = new_r_Proj(irg, bl, low_call, get_irn_mode(curr_sp),
                             pn_be_Call_sp);
-       be_set_constr_single_reg(low_call, BE_OUT_POS(pn_be_Call_sp), sp);
+       be_set_constr_single_reg_out(low_call, pn_be_Call_sp, sp,
+                       arch_register_req_type_ignore | arch_register_req_type_produces_sp);
        arch_set_irn_register(curr_sp, sp);
-       be_node_set_flags(low_call, BE_OUT_POS(pn_be_Call_sp),
-                       arch_irn_flags_ignore | arch_irn_flags_modify_sp);
 
        for(i = 0; i < n_res; ++i) {
                int pn;
@@ -704,7 +703,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                Set the register class of the call address to
                the backend provided class (default: stack pointer class)
        */
-       be_node_set_reg_class(low_call, be_pos_Call_ptr, call->cls_addr);
+       be_node_set_reg_class_in(low_call, be_pos_Call_ptr, call->cls_addr);
 
        DBG((env->dbg, LEVEL_3, "\tcreated backend call %+F\n", low_call));
 
@@ -714,7 +713,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                be_abi_call_arg_t *arg = get_call_arg(call, 0, index);
                assert(arg->reg != NULL);
 
-               be_set_constr_single_reg(low_call, be_pos_Call_first_arg + i, arg->reg);
+               be_set_constr_single_reg_in(low_call, be_pos_Call_first_arg + i,
+                                           arg->reg, 0);
        }
 
        /* Set the register constraints of the results. */
@@ -724,7 +724,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                int                      pn   = get_Proj_proj(proj);
 
                assert(arg->in_reg);
-               be_set_constr_single_reg(low_call, BE_OUT_POS(pn), arg->reg);
+               be_set_constr_single_reg_out(low_call, pn, arg->reg, 0);
                arch_set_irn_register(proj, arg->reg);
        }
        obstack_free(obst, in);
@@ -755,15 +755,9 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                                                   curr_res_proj);
 
                        /* memorize the register in the link field. we need afterwards to set the register class of the keep correctly. */
-                       be_set_constr_single_reg(low_call, BE_OUT_POS(curr_res_proj), reg);
+                       be_set_constr_single_reg_out(low_call, curr_res_proj, reg, 0);
                        arch_set_irn_register(proj, reg);
 
-                       /* a call can produce ignore registers, in this case set the flag and register for the Proj */
-                       if (arch_register_type_is(reg, ignore)) {
-                               be_node_set_flags(low_call, BE_OUT_POS(curr_res_proj),
-                                                 arch_irn_flags_ignore);
-                       }
-
                        set_irn_link(proj, (void*) reg);
                        obstack_ptr_grow(obst, proj);
                        curr_res_proj++;
@@ -782,7 +776,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                keep = be_new_Keep(NULL, irg, bl, n, in);
                for (i = 0; i < n; ++i) {
                        const arch_register_t *reg = get_irn_link(in[i]);
-                       be_node_set_reg_class(keep, i, reg->reg_class);
+                       be_node_set_reg_class_in(keep, i, reg->reg_class);
                }
                obstack_free(obst, in);
        }
@@ -1246,50 +1240,6 @@ static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call, ir_type
        return res;
 }
 
-#if 0
-static void create_register_perms(const arch_isa_t *isa, ir_graph *irg, ir_node *bl, pmap *regs)
-{
-       int i, j, n;
-       struct obstack obst;
-
-       obstack_init(&obst);
-
-       /* Create a Perm after the RegParams node to delimit it. */
-       for (i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
-               const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
-               ir_node *perm;
-               ir_node **in;
-               int n_regs;
-
-               for (n_regs = 0, j = 0; j < cls->n_regs; ++j) {
-                       const arch_register_t *reg = &cls->regs[j];
-                       ir_node *irn = pmap_get(regs, (void *) reg);
-
-                       if(irn && !arch_register_type_is(reg, ignore)) {
-                               n_regs++;
-                               obstack_ptr_grow(&obst, irn);
-                               set_irn_link(irn, (void *) reg);
-                       }
-               }
-
-               obstack_ptr_grow(&obst, NULL);
-               in = obstack_finish(&obst);
-               if (n_regs > 0) {
-                       perm = be_new_Perm(cls, irg, bl, n_regs, in);
-                       for (j = 0; j < n_regs; ++j) {
-                               ir_node *arg = in[j];
-                               arch_register_t *reg = get_irn_link(arg);
-                               pmap_insert(regs, reg, arg);
-                               be_set_constr_single_reg(perm, BE_OUT_POS(j), reg);
-                       }
-               }
-               obstack_free(&obst, in);
-       }
-
-       obstack_free(&obst, NULL);
-}
-#endif
-
 typedef struct {
        const arch_register_t *reg;
        ir_node *irn;
@@ -1350,28 +1300,28 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm
        obstack_free(&env->obst, in);
 
        for(n = 0; n < n_regs; ++n) {
-               const arch_register_t *reg = rm[n].reg;
-               int flags                  = 0;
-               int pos                    = BE_OUT_POS(n);
-               ir_node *proj;
+               ir_node                   *pred     = rm[n].irn;
+               const arch_register_t     *reg      = rm[n].reg;
+               arch_register_type_t       add_type = 0;
+               ir_node                   *proj;
+
+               /* stupid workaround for now... as not all nodes report register
+                * requirements. */
+               if (!is_Phi(pred)) {
+                       const arch_register_req_t *ireq = arch_get_register_req_out(pred);
+                       if (ireq->type & arch_register_req_type_ignore)
+                               add_type |= arch_register_req_type_ignore;
+                       if (ireq->type & arch_register_req_type_produces_sp)
+                               add_type |= arch_register_req_type_produces_sp;
+               }
 
-               proj = new_r_Proj(irg, bl, irn, get_irn_mode(rm[n].irn), n);
-               be_node_set_reg_class(irn, n, reg->reg_class);
+               proj = new_r_Proj(irg, bl, irn, get_irn_mode(pred), n);
+               be_node_set_reg_class_in(irn, n, reg->reg_class);
                if (in_req)
-                       be_set_constr_single_reg(irn, n, reg);
-               be_set_constr_single_reg(irn, pos, reg);
-               be_node_set_reg_class(irn, pos, reg->reg_class);
+                       be_set_constr_single_reg_in(irn, n, reg, 0);
+               be_set_constr_single_reg_out(irn, n, reg, add_type);
                arch_set_irn_register(proj, reg);
 
-               /* if the proj projects a ignore register or a node which is set to ignore, propagate this property. */
-               if (arch_register_type_is(reg, ignore) || arch_irn_is(in[n], ignore))
-                       flags |= arch_irn_flags_ignore;
-
-               if (arch_irn_is(in[n], modify_sp))
-                       flags |= arch_irn_flags_modify_sp;
-
-               be_node_set_flags(irn, pos, flags);
-
                pmap_insert(regs, (void *) reg, proj);
        }
 
@@ -1490,9 +1440,12 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
        ret = be_new_Return(dbgi, env->birg->irg, bl, n_res, pop, n, in);
 
        /* Set the register classes of the return's parameter accordingly. */
-       for (i = 0; i < n; ++i)
-               if (regs[i])
-                       be_node_set_reg_class(ret, i, regs[i]->reg_class);
+       for (i = 0; i < n; ++i) {
+               if (regs[i] == NULL)
+                       continue;
+
+               be_node_set_reg_class_in(ret, i, regs[i]->reg_class);
+       }
 
        /* Free the space of the Epilog's in array and the register <-> proj map. */
        obstack_free(&env->obst, in);
@@ -1824,33 +1777,22 @@ static void modify_irg(be_abi_irg_t *env)
 
        rm = reg_map_to_arr(&env->obst, env->regs);
        for (i = 0, n = pmap_count(env->regs); i < n; ++i) {
-               arch_register_t *reg = (void *) rm[i].reg;
-               ir_mode *mode        = reg->reg_class->mode;
-               long nr              = i;
-               int pos              = BE_OUT_POS((int) nr);
-               int flags            = 0;
+               arch_register_t          *reg      = (void *) rm[i].reg;
+               ir_mode                  *mode     = reg->reg_class->mode;
+               long                      nr       = i;
+               arch_register_req_type_t  add_type = 0;
+               ir_node                  *proj;
 
-               ir_node *proj;
+               if (reg == sp)
+                       add_type |= arch_register_req_type_produces_sp | arch_register_req_type_ignore;
 
                assert(nr >= 0);
                bitset_set(used_proj_nr, nr);
                proj = new_r_Proj(irg, reg_params_bl, env->reg_params, mode, nr);
                pmap_insert(env->regs, (void *) reg, proj);
-               be_set_constr_single_reg(env->reg_params, pos, reg);
+               be_set_constr_single_reg_out(env->reg_params, nr, reg, add_type);
                arch_set_irn_register(proj, reg);
 
-               /*
-                * If the register is an ignore register,
-                * The Proj for that register shall also be ignored during register allocation.
-                */
-               if (arch_register_type_is(reg, ignore))
-                       flags |= arch_irn_flags_ignore;
-
-               if (reg == sp)
-                       flags |= arch_irn_flags_modify_sp;
-
-               be_node_set_flags(env->reg_params, pos, flags);
-
                DBG((dbg, LEVEL_2, "\tregister save proj #%d -> reg %s\n", nr, reg->name));
        }
        obstack_free(&env->obst, rm);
@@ -1863,7 +1805,7 @@ static void modify_irg(be_abi_irg_t *env)
        mem = new_mem_proj;
 
        /* Generate the Prologue */
-       fp_reg  = call->cb->prologue(env->cb, &mem, env->regs, &env->frame.initial_bias);
+       fp_reg = call->cb->prologue(env->cb, &mem, env->regs, &env->frame.initial_bias);
 
        /* do the stack allocation BEFORE the barrier, or spill code
           might be added before it */
@@ -2188,6 +2130,9 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
        limited_bitset      = rbitset_obstack_alloc(&env->obst, env->sp_req.cls->n_regs);
        rbitset_set(limited_bitset, arch_register_get_index(env->arch_env->sp));
        env->sp_req.limited = limited_bitset;
+       if (env->arch_env->sp->type & arch_register_type_ignore) {
+               env->sp_req.type |= arch_register_req_type_ignore;
+       }
 
        env->sp_cls_req.type  = arch_register_req_type_normal;
        env->sp_cls_req.cls   = arch_register_get_class(env->arch_env->sp);
@@ -2310,12 +2255,17 @@ typedef struct fix_stack_walker_env_t {
  */
 static void collect_stack_nodes_walker(ir_node *node, void *data)
 {
-       fix_stack_walker_env_t *env = data;
+       fix_stack_walker_env_t    *env = data;
+       const arch_register_req_t *req;
 
-       if (arch_irn_is(node, modify_sp)) {
-               assert(get_irn_mode(node) != mode_M && get_irn_mode(node) != mode_T);
-               ARR_APP1(ir_node*, env->sp_nodes, node);
-       }
+       if (get_irn_mode(node) == mode_T)
+               return;
+
+       req = arch_get_register_req_out(node);
+       if (! (req->type & arch_register_req_type_produces_sp))
+               return;
+
+       ARR_APP1(ir_node*, env->sp_nodes, node);
 }
 
 void be_abi_fix_stack_nodes(be_abi_irg_t *env)
@@ -2345,7 +2295,7 @@ void be_abi_fix_stack_nodes(be_abi_irg_t *env)
        be_ssa_construction_add_copies(&senv, walker_env.sp_nodes,
                                    ARR_LEN(walker_env.sp_nodes));
        be_ssa_construction_fix_users_array(&senv, walker_env.sp_nodes,
-                                     ARR_LEN(walker_env.sp_nodes));
+                                           ARR_LEN(walker_env.sp_nodes));
 
        if(lv != NULL) {
                len = ARR_LEN(walker_env.sp_nodes);
@@ -2361,8 +2311,7 @@ void be_abi_fix_stack_nodes(be_abi_irg_t *env)
        len = ARR_LEN(phis);
        for(i = 0; i < len; ++i) {
                ir_node *phi = phis[i];
-               be_set_phi_reg_req(phi, &env->sp_req);
-               be_set_phi_flags(phi, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
+               be_set_phi_reg_req(phi, &env->sp_req, arch_register_req_type_produces_sp);
                arch_set_irn_register(phi, env->arch_env->sp);
        }
        be_ssa_construction_destroy(&senv);
index bf75984..700115c 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "bearch_t.h"
 #include "benode_t.h"
+#include "beinfo.h"
 #include "ircons_t.h"
 #include "irnode_t.h"
 
@@ -176,28 +177,78 @@ const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
        return req->cls;
 }
 
-const arch_register_t *arch_get_irn_register(const ir_node *irn)
+static inline reg_out_info_t *get_out_info(const ir_node *node)
 {
-       const arch_irn_ops_t *ops = get_irn_ops(irn);
-       return ops->get_irn_reg(irn);
+       int                   pos  = 0;
+       const backend_info_t *info;
+
+       assert(get_irn_mode(node) != mode_T);
+       if (is_Proj(node)) {
+               pos  = get_Proj_proj(node);
+               node = get_Proj_pred(node);
+       }
+
+       info = be_get_info(node);
+       assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
+       return &info->out_infos[pos];
 }
 
-void arch_set_irn_register(ir_node *irn, const arch_register_t *reg)
+
+static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
 {
-       const arch_irn_ops_t *ops = get_irn_ops(irn);
-       ops->set_irn_reg(irn, reg);
+       const backend_info_t *info = be_get_info(node);
+       assert(!is_Proj(node));
+       assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
+       return &info->out_infos[pos];
 }
 
-arch_irn_class_t arch_irn_classify(const ir_node *irn)
+
+const arch_register_t *arch_get_irn_register(const ir_node *node)
 {
-       const arch_irn_ops_t *ops = get_irn_ops(irn);
-       return ops->classify(irn);
+       const reg_out_info_t *out = get_out_info(node);
+       return out->reg;
 }
 
-arch_irn_flags_t arch_irn_get_flags(const ir_node *irn)
+const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
 {
-       const arch_irn_ops_t *ops = get_irn_ops(irn);
-       return ops->get_flags(irn);
+       const reg_out_info_t *out = get_out_info_n(node, pos);
+       return out->reg;
+}
+
+void arch_irn_set_register(ir_node *node, int pos, const arch_register_t *reg)
+{
+       reg_out_info_t *out = get_out_info_n(node, pos);
+       out->reg            = reg;
+}
+
+void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
+{
+       reg_out_info_t *out = get_out_info(node);
+       out->reg = reg;
+}
+
+arch_irn_class_t arch_irn_classify(const ir_node *node)
+{
+       const arch_irn_ops_t *ops = get_irn_ops(node);
+       return ops->classify(node);
+}
+
+arch_irn_flags_t arch_irn_get_flags(const ir_node *node)
+{
+       backend_info_t *info = be_get_info(node);
+       return info->flags;
+}
+
+void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags)
+{
+       backend_info_t *info = be_get_info(node);
+       info->flags = flags;
+}
+
+void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
+{
+       backend_info_t *info = be_get_info(node);
+       info->flags |= flags;
 }
 
 extern char *arch_register_req_format(char *buf, size_t len,
@@ -247,6 +298,13 @@ extern char *arch_register_req_format(char *buf, size_t len,
                }
        }
 
+       if (arch_register_req_is(req, ignore)) {
+               strncat(buf, " ignore", len);
+       }
+       if (arch_register_req_is(req, produces_sp)) {
+               strncat(buf, " produces_sp", len);
+       }
+
        return buf;
 }
 
index db99133..e72e5bf 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef FIRM_BE_BEARCH_H
 #define FIRM_BE_BEARCH_H
 
+#include <stdbool.h>
+
 #include "firm_types.h"
 #include "bitset.h"
 #include "be.h"
@@ -68,11 +70,13 @@ typedef enum arch_register_type_t {
  * Different types of register allocation requirements.
  */
 typedef enum arch_register_req_type_t {
-       arch_register_req_type_none              = 0,  /**< No register requirement. */
-       arch_register_req_type_normal            = 1,  /**< All registers in the class are allowed. */
-       arch_register_req_type_limited           = 2,  /**< Only a real subset of the class is allowed. */
-       arch_register_req_type_should_be_same    = 4,  /**< The register should be equal to another one at the node. */
-       arch_register_req_type_must_be_different = 8,  /**< The register must be unequal from some other at the node. */
+       arch_register_req_type_none              = 0, /**< No register requirement. */
+       arch_register_req_type_normal            = 1U << 0, /**< All registers in the class are allowed. */
+       arch_register_req_type_limited           = 1U << 1, /**< Only a real subset of the class is allowed. */
+       arch_register_req_type_should_be_same    = 1U << 2, /**< The register should be equal to another one at the node. */
+       arch_register_req_type_must_be_different = 1U << 3, /**< The register must be unequal from some other at the node. */
+       arch_register_req_type_ignore            = 1U << 4, /**< ignore while allocating registers */
+       arch_register_req_type_produces_sp       = 1U << 5, /**< the output produces a new value for the stack pointer */
 } arch_register_req_type_t;
 
 extern const arch_register_req_t *arch_no_register_req;
@@ -105,9 +109,7 @@ typedef enum arch_irn_flags_t {
        arch_irn_flags_none             = 0,       /**< Node flags. */
        arch_irn_flags_dont_spill       = 1U << 0, /**< This must not be spilled. */
        arch_irn_flags_rematerializable = 1U << 1, /**< This can be replicated instead of spilled/reloaded. */
-       arch_irn_flags_ignore           = 1U << 2, /**< Ignore node during register allocation. */
-       arch_irn_flags_modify_sp        = 1U << 3, /**< I modify the stack pointer. */
-       arch_irn_flags_modify_flags     = 1U << 4  /**< I modify flags. */
+       arch_irn_flags_modify_flags     = 1U << 2  /**< I modify flags. */
 } arch_irn_flags_t;
 
 void arch_set_frame_offset(ir_node *irn, int bias);
@@ -168,6 +170,7 @@ const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
  * @return    The register allocated for this operand
  */
 const arch_register_t *arch_get_irn_register(const ir_node *irn);
+const arch_register_t *arch_irn_get_register(const ir_node *irn, int pos);
 
 /**
  * Set the register for a certain output operand.
@@ -175,6 +178,7 @@ const arch_register_t *arch_get_irn_register(const ir_node *irn);
  * @param reg The register.
  */
 void arch_set_irn_register(ir_node *irn, const arch_register_t *reg);
+void arch_irn_set_register(ir_node *irn, int pos, const arch_register_t *reg);
 
 /**
  * Classify a node.
@@ -192,10 +196,10 @@ arch_irn_class_t arch_irn_classify(const ir_node *irn);
  */
 arch_irn_flags_t arch_irn_get_flags(const ir_node *irn);
 
-#define arch_irn_is(irn, flag) ((arch_irn_get_flags(irn) & arch_irn_flags_ ## flag) != 0)
+void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags);
+void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags);
 
-#define arch_irn_consider_in_reg_alloc(cls, irn) \
-       (arch_get_irn_reg_class_out(irn) == (cls) && !arch_irn_is(irn, ignore))
+#define arch_irn_is(irn, flag) ((arch_irn_get_flags(irn) & arch_irn_flags_ ## flag) != 0)
 
 /**
  * Get the operations of an irn.
index f1cfc1e..f4bc0fc 100644 (file)
@@ -32,6 +32,7 @@
 #include "beilpsched.h"
 #include "bemachine.h"
 #include "beirg.h"
+#include "beinfo.h"
 #include "beabi.h"
 #include "raw_bitset.h"
 
@@ -184,32 +185,12 @@ struct arch_irn_ops_t {
         * Get the register requirements for a given operand.
         * @param self The self pointer.
         * @param irn The node.
-        * @param pos The operand's position
-        *        (-1 for the result of the node, 0..n for the input operands).
+        * @param pos The operand's position (0..n for the input operands).
         * @return    The register requirements for the selected operand.
         *            The pointer returned is never NULL.
         */
        const arch_register_req_t *(*get_irn_reg_req)(const ir_node *irn, int pos);
 
-       /**
-        * Set the register for an output operand.
-        * @param irn The node.
-        * @param reg The register allocated to that operand.
-        * @note      If the operand is not a register operand,
-        *            the call is ignored.
-        */
-       void (*set_irn_reg)(ir_node *irn, const arch_register_t *reg);
-
-       /**
-        * Get the register allocated for an output operand.
-        * @param irn The node.
-        * @return    The register allocated at that operand. NULL, if
-        *            the operand was no register operand or
-        *            @c arch_register_invalid, if no register has yet been
-        *            allocated for this node.
-        */
-       const arch_register_t *(*get_irn_reg)(const ir_node *irn);
-
        /**
         * Classify the node.
         * @param irn The node.
@@ -217,14 +198,6 @@ struct arch_irn_ops_t {
         */
        arch_irn_class_t (*classify)(const ir_node *irn);
 
-       /**
-        * Get the flags of a node.
-        * @param self The irn ops themselves.
-        * @param irn The node.
-        * @return A set of flags.
-        */
-       arch_irn_flags_t (*get_flags)(const ir_node *irn);
-
        /**
         * Get the entity on the stack frame this node depends on.
         * @param self The this pointer.
@@ -416,6 +389,8 @@ struct arch_isa_if_t {
         */
        void (*done)(void *self);
 
+       void (*handle_intrinsics)(void);
+
        /**
         * Get the the number of register classes in the isa.
         * @return The number of register classes.
@@ -536,6 +511,8 @@ struct arch_isa_if_t {
 };
 
 #define arch_env_done(env)                             ((env)->impl->done(env))
+#define arch_env_handle_intrinsics(env)                \
+       do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0)
 #define arch_env_get_n_reg_class(env)                  ((env)->impl->get_n_reg_class(env))
 #define arch_env_get_reg_class(env,i)                  ((env)->impl->get_reg_class(env, i))
 #define arch_env_get_reg_class_for_mode(env,mode)      ((env)->impl->get_reg_class_for_mode((env), (mode)))
@@ -571,4 +548,25 @@ struct arch_env_t {
 #define arch_env_sp(env)         ((env)->sp)
 #define arch_env_bp(env)         ((env)->bp)
 
-#endif /* FIRM_BE_BEARCH_T_H */
+static inline unsigned arch_irn_get_n_outs(const ir_node *node)
+{
+       backend_info_t *info = be_get_info(node);
+       return ARR_LEN(info->out_infos);
+}
+
+static inline bool arch_irn_consider_in_reg_alloc(
+               const arch_register_class_t *cls, const ir_node *node)
+{
+       const arch_register_req_t *req = arch_get_register_req_out(node);
+       return
+               req->cls == cls &&
+               !(req->type & arch_register_req_type_ignore);
+}
+
+static inline bool arch_irn_is_ignore(const ir_node *irn)
+{
+       const arch_register_req_t *req = arch_get_register_req_out(irn);
+       return !!(req->type & arch_register_req_type_ignore);
+}
+
+#endif
index ade9717..6d32c1c 100644 (file)
@@ -921,7 +921,7 @@ static void assign(ir_node *block, void *env_ptr)
        list_for_each_entry_reverse(border_t, b, head, list) {
                ir_node *irn = b->irn;
                int nr       = get_irn_idx(irn);
-               int ignore   = arch_irn_is(irn, ignore);
+               int ignore   = arch_irn_is_ignore(irn);
 
                /*
                 * Assign a color, if it is a local def. Global defs already have a
index 411646e..8f257c0 100644 (file)
@@ -1173,8 +1173,9 @@ static void ifg_dump_graph_attr(FILE *f, void *self)
 
 static int ifg_is_dump_node(void *self, ir_node *irn)
 {
+       const arch_register_req_t *req = arch_get_register_req_out(irn);
        (void)self;
-       return !arch_irn_is(irn, ignore);
+       return !(req->type & arch_register_req_type_ignore);
 }
 
 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
index bc33dd4..76a1930 100644 (file)
@@ -396,7 +396,7 @@ static void *co_mst_irn_init(ir_phase *ph, const ir_node *irn, void *old) {
                /* build list of interfering neighbours */
                len = 0;
                be_ifg_foreach_neighbour(env->ifg, nodes_it, irn, neigh) {
-                       if (!arch_irn_is(neigh, ignore)) {
+                       if (!arch_irn_is_ignore(neigh)) {
                                obstack_ptr_grow(phase_obst(ph), neigh);
                                ++len;
                        }
@@ -552,10 +552,9 @@ static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
                        if (an != NULL) {
                                neighb_t *neigh;
                                co_gs_foreach_neighb(an, neigh) {
-                                       const ir_node *m    = neigh->irn;
+                                       const ir_node *m = neigh->irn;
 
-                                       /* skip ignore nodes */
-                                       if (arch_irn_is(m, ignore))
+                                       if (arch_irn_is_ignore(m))
                                                continue;
 
                                        w += node_contains(c->n, m) ? neigh->costs : 0;
@@ -585,8 +584,7 @@ static int count_interfering_aff_neighs(co_mst_env_t *env, const affinity_node_t
                const ir_node *n = neigh->irn;
                int           i;
 
-               /* skip ignore nodes */
-               if (arch_irn_is(n, ignore))
+               if (arch_irn_is_ignore(n))
                        continue;
 
                /* check if the affinity neighbour interfere */
@@ -621,8 +619,7 @@ static void build_affinity_chunks(co_mst_env_t *env) {
                co_mst_irn_t    *n1;
                affinity_node_t *an;
 
-               /* skip ignore nodes */
-               if (arch_irn_is(n, ignore))
+               if (arch_irn_is_ignore(n))
                        continue;
 
                n1 = get_co_mst_irn(env, n);
@@ -645,7 +642,7 @@ static void build_affinity_chunks(co_mst_env_t *env) {
                                        aff_edge_t   edge;
 
                                        /* skip ignore nodes */
-                                       if (arch_irn_is(m, ignore))
+                                       if (arch_irn_is_ignore(m))
                                                continue;
 
                                        edge.src = n;
@@ -721,7 +718,7 @@ static __attribute__((unused)) void chunk_order_nodes(co_mst_env_t *env, aff_chu
                int w = 0;
                neighb_t *neigh;
 
-               if (arch_irn_is(irn, ignore))
+               if (arch_irn_is_ignore(irn))
                        continue;
 
                if (an) {
@@ -747,9 +744,9 @@ static __attribute__((unused)) void chunk_order_nodes(co_mst_env_t *env, aff_chu
                while (!pqueue_empty(grow)) {
                        ir_node *irn = pqueue_pop_front(grow);
                        affinity_node_t *an = get_affinity_info(env->co, irn);
-                       neighb_t *neigh;
+                       neighb_t        *neigh;
 
-                       if (arch_irn_is(irn, ignore))
+                       if (arch_irn_is_ignore(irn))
                                continue;
 
                        assert(i <= ARR_LEN(chunk->n));
@@ -802,8 +799,7 @@ static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *v
                                int            m_idx = get_irn_idx(m);
                                co_mst_irn_t *n2;
 
-                               /* skip ignore nodes */
-                               if (arch_irn_is(m, ignore))
+                               if (arch_irn_is_ignore(m))
                                        continue;
 
                                n2 = get_co_mst_irn(env, m);
@@ -1046,8 +1042,7 @@ static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *cost
 
                        neigh = node->int_neighs[j];
 
-                       /* skip ignore nodes */
-                       if (arch_irn_is(neigh, ignore))
+                       if (arch_irn_is_ignore(neigh))
                                continue;
 
                        nn = get_co_mst_irn(env, neigh);
@@ -1444,10 +1439,10 @@ int co_solve_heuristic_mst(copy_opt_t *co) {
 
        /* apply coloring */
        foreach_phase_irn(&mst_env.ph, irn) {
-               co_mst_irn_t *mirn;
+               co_mst_irn_t          *mirn;
                const arch_register_t *reg;
 
-               if (arch_irn_is(irn, ignore))
+               if (arch_irn_is_ignore(irn))
                        continue;
 
                mirn = get_co_mst_irn(&mst_env, irn);
index b0cd699..e3d7963 100644 (file)
@@ -293,7 +293,7 @@ static void build_clique_star_cstr(ilp_env_t *ienv) {
                set *edges;
                int i, o, n_nodes, n_edges;
 
-               if (arch_irn_is(aff->irn, ignore))
+               if (arch_irn_is_ignore(aff->irn))
                        continue;
 
                obstack_init(&ob);
@@ -302,7 +302,7 @@ static void build_clique_star_cstr(ilp_env_t *ienv) {
                /* get all affinity neighbours */
                n_nodes = 0;
                co_gs_foreach_neighb(aff, nbr) {
-                       if (!arch_irn_is(nbr->irn, ignore)) {
+                       if (!arch_irn_is_ignore(nbr->irn)) {
                                obstack_ptr_grow(&ob, nbr->irn);
                                ++n_nodes;
                        }
@@ -406,7 +406,7 @@ static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn) {
        if (pdeq_contains(path, irn))
                return;
 
-       if (arch_irn_is(irn, ignore))
+       if (arch_irn_is_ignore(irn))
                return;
 
        /* insert the new irn */
index 917b2ca..20f7f4b 100644 (file)
@@ -220,9 +220,9 @@ void free_copy_opt(copy_opt_t *co) {
 static int co_is_optimizable_root(ir_node *irn)
 {
        const arch_register_req_t *req;
-       const arch_register_t *reg;
+       const arch_register_t     *reg;
 
-       if (arch_irn_is(irn, ignore))
+       if (arch_irn_is_ignore(irn))
                return 0;
 
        reg = arch_get_irn_register(irn);
@@ -422,26 +422,27 @@ static void co_collect_units(ir_node *irn, void *env)
                        /* Else insert the argument of the phi to the members of this ou */
                        DBG((dbg, LEVEL_1, "\t   Member: %+F\n", arg));
 
-                       if (!arch_irn_is(arg, ignore)) {
-                               /* Check if arg has occurred at a prior position in the arg/list */
-                               arg_pos = 0;
-                               for (o=1; o<unit->node_count; ++o) {
-                                       if (unit->nodes[o] == arg) {
-                                               arg_pos = o;
-                                               break;
-                                       }
-                               }
+                       if (arch_irn_is_ignore(arg))
+                               continue;
 
-                               if (!arg_pos) { /* a new argument */
-                                       /* insert node, set costs */
-                                       unit->nodes[unit->node_count] = arg;
-                                       unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
-                                       unit->node_count++;
-                               } else { /* arg has occurred before in same phi */
-                                       /* increase costs for existing arg */
-                                       unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
+                       /* Check if arg has occurred at a prior position in the arg/list */
+                       arg_pos = 0;
+                       for (o=1; o<unit->node_count; ++o) {
+                               if (unit->nodes[o] == arg) {
+                                       arg_pos = o;
+                                       break;
                                }
                        }
+
+                       if (!arg_pos) { /* a new argument */
+                               /* insert node, set costs */
+                               unit->nodes[unit->node_count] = arg;
+                               unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
+                               unit->node_count++;
+                       } else { /* arg has occurred before in same phi */
+                               /* increase costs for existing arg */
+                               unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
+                       }
                }
                unit->nodes = XREALLOC(unit->nodes, ir_node*, unit->node_count);
                unit->costs = XREALLOC(unit->costs, int,      unit->node_count);
@@ -464,10 +465,11 @@ static void co_collect_units(ir_node *irn, void *env)
                        for (i = 0; (1U << i) <= other; ++i) {
                                if (other & (1U << i)) {
                                        ir_node *o  = get_irn_n(skip_Proj(irn), i);
-                                       if (!arch_irn_is(o, ignore) &&
-                                                       !nodes_interfere(co->cenv, irn, o)) {
-                                               ++count;
-                                       }
+                                       if (arch_irn_is_ignore(o))
+                                               continue;
+                                       if (nodes_interfere(co->cenv, irn, o))
+                                               continue;
+                                       ++count;
                                }
                        }
 
@@ -482,7 +484,7 @@ static void co_collect_units(ir_node *irn, void *env)
                                for (i = 0; 1U << i <= other; ++i) {
                                        if (other & (1U << i)) {
                                                ir_node *o  = get_irn_n(skip_Proj(irn), i);
-                                               if (!arch_irn_is(o, ignore) &&
+                                               if (!arch_irn_is_ignore(o) &&
                                                                !nodes_interfere(co->cenv, irn, o)) {
                                                        unit->nodes[k] = o;
                                                        unit->costs[k] = co->get_costs(co, irn, o, -1);
@@ -777,7 +779,7 @@ static void build_graph_walker(ir_node *irn, void *env) {
        int pos, max;
        const arch_register_t *reg;
 
-       if (req->cls != co->cls || arch_irn_is(irn, ignore))
+       if (req->cls != co->cls || arch_irn_is_ignore(irn))
                return;
 
        reg = arch_get_irn_register(irn);
@@ -800,7 +802,7 @@ static void build_graph_walker(ir_node *irn, void *env) {
                        for (i = 0; 1U << i <= other; ++i) {
                                if (other & (1U << i)) {
                                        ir_node *other = get_irn_n(skip_Proj(irn), i);
-                                       if (!arch_irn_is(other, ignore))
+                                       if (!arch_irn_is_ignore(other))
                                                add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
                                }
                        }
@@ -886,14 +888,15 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
 
        n = n_regs;
        be_ifg_foreach_node(ifg, it, irn) {
-               if (!arch_irn_is(irn, ignore))
-                       node_map[get_irn_idx(irn)] = n++;
+               if (arch_irn_is_ignore(irn))
+                       continue;
+               node_map[get_irn_idx(irn)] = n++;
        }
 
        fprintf(f, "%d %d\n", n, n_regs);
 
        be_ifg_foreach_node(ifg, it, irn) {
-               if (!arch_irn_is(irn, ignore)) {
+               if (!arch_irn_is_ignore(irn)) {
                        int idx                        = node_map[get_irn_idx(irn)];
                        affinity_node_t           *a   = get_affinity_info(co, irn);
                        const arch_register_req_t *req = arch_get_register_req_out(irn);
@@ -907,7 +910,7 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
                        }
 
                        be_ifg_foreach_neighbour(ifg, nit, irn, adj) {
-                               if (!arch_irn_is(adj, ignore) &&
+                               if (!arch_irn_is_ignore(adj) &&
                                                !co_dump_appel_disjoint_constraints(co, irn, adj)) {
                                        int adj_idx = node_map[get_irn_idx(adj)];
                                        if(idx < adj_idx)
@@ -919,7 +922,7 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
                                neighb_t *n;
 
                                co_gs_foreach_neighb(a, n) {
-                                       if (!arch_irn_is(n->irn, ignore)) {
+                                       if (!arch_irn_is_ignore(n->irn)) {
                                                int n_idx = node_map[get_irn_idx(n->irn)];
                                                if(idx < n_idx)
                                                        fprintf(f, "%d %d %d\n", idx, n_idx, (int) n->costs);
@@ -994,7 +997,7 @@ static void ifg_dump_graph_attr(FILE *f, void *self)
 static int ifg_is_dump_node(void *self, ir_node *irn)
 {
        (void)self;
-       return !arch_irn_is(irn, ignore);
+       return !arch_irn_is_ignore(irn);
 }
 
 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
index 666954f..f7f173c 100644 (file)
@@ -642,10 +642,14 @@ static void int_comp_rec(be_ifg_t *ifg, ir_node *n, bitset_t *seen)
        ir_node *m;
 
        be_ifg_foreach_neighbour(ifg, neigh_it, n, m) {
-               if (!bitset_contains_irn(seen, m) && !arch_irn_is(m, ignore)) {
-                       bitset_add_irn(seen, m);
-                       int_comp_rec(ifg, m, seen);
-               }
+               if (bitset_contains_irn(seen, m))
+                       continue;
+
+               if (arch_get_register_req_out(m)->type & arch_register_req_type_ignore)
+                       continue;
+
+               bitset_add_irn(seen, m);
+               int_comp_rec(ifg, m, seen);
        }
 
 }
@@ -659,11 +663,15 @@ static int int_component_stat(be_irg_t *birg, be_ifg_t *ifg)
        ir_node *n;
 
        be_ifg_foreach_node(ifg, nodes_it, n) {
-               if (!bitset_contains_irn(seen, n) && !arch_irn_is(n, ignore)) {
-                       ++n_comp;
-                       bitset_add_irn(seen, n);
-                       int_comp_rec(ifg, n, seen);
-               }
+               if (bitset_contains_irn(seen, n))
+                       continue;
+
+               if (arch_get_register_req_out(n)->type & arch_register_req_type_ignore)
+                       continue;
+
+               ++n_comp;
+               bitset_add_irn(seen, n);
+               int_comp_rec(ifg, n, seen);
        }
 
        free(seen);
index 24bc663..46f6bb3 100644 (file)
@@ -504,7 +504,7 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
        ir_node                     *keep, *cpy;
        op_copy_assoc_t             *entry;
 
-       if (arch_irn_is(other_different, ignore) ||
+       if (arch_irn_is_ignore(other_different) ||
                        !mode_is_datab(get_irn_mode(other_different))) {
                DBG((dbg_constr, LEVEL_1, "ignore constraint for %+F because other_irn is ignore or not a datab node\n", irn));
                return;
@@ -524,7 +524,7 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
        cpy = find_copy(skip_Proj(irn), other_different);
        if (! cpy) {
                cpy = be_new_Copy(cls, irg, block, other_different);
-               be_node_set_flags(cpy, BE_OUT_POS(0), arch_irn_flags_dont_spill);
+               arch_irn_set_flags(cpy, arch_irn_flags_dont_spill);
                DBG((dbg_constr, LEVEL_1, "created non-spillable %+F for value %+F\n", cpy, other_different));
        } else {
                DBG((dbg_constr, LEVEL_1, "using already existing %+F for value %+F\n", cpy, other_different));
@@ -534,7 +534,7 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
        /* of the other_different irn in case of CopyKeep.   */
        if (has_irn_users(other_different)) {
                keep = be_new_CopyKeep_single(cls, irg, block, cpy, irn, get_irn_mode(other_different));
-               be_node_set_reg_class(keep, 1, cls);
+               be_node_set_reg_class_in(keep, 1, cls);
        } else {
                ir_node *in[2];
 
@@ -736,7 +736,7 @@ static void melt_copykeeps(constraint_env_t *cenv) {
 
                                /* set register class for all kept inputs */
                                for (j = 1; j <= n_melt; ++j)
-                                       be_node_set_reg_class(new_ck, j, entry->cls);
+                                       be_node_set_reg_class_in(new_ck, j, entry->cls);
 
                                ir_nodeset_insert(&entry->copies, new_ck);
 
index a44121f..371b4f9 100644 (file)
@@ -473,6 +473,7 @@ static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
        edges_assure(irg);
 
        set_irg_phase_state(irg, phase_backend);
+       be_info_init_irg(irg);
 
        dump(DUMP_INITIAL, irg, "-prepared", dump_ir_block_graph);
 }
@@ -567,11 +568,14 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
        num_birgs = backend_irg_list ? ARR_LEN(backend_irg_list) : get_irp_n_irgs();
        birgs     = ALLOCAN(be_irg_t, num_birgs + 1);
 
+       be_info_init();
+
        /* First: initialize all birgs */
        for(i = 0; i < num_birgs; ++i) {
                ir_graph *irg = backend_irg_list ? backend_irg_list[i] : get_irp_irg(i);
                initialize_birg(&birgs[i], irg, &env);
        }
+       arch_env_handle_intrinsics(arch_env);
        DEL_ARR_F(irg_list);
 
        /*
@@ -604,8 +608,6 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                /* set the current graph (this is important for several firm functions) */
                current_ir_graph = irg;
 
-               be_sched_init_phase(irg);
-
                /* reset the phi handler. */
                be_phi_handler_reset();
 
@@ -859,13 +861,13 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                );
 #undef LC_EMIT
 
-               be_sched_free_phase(irg);
-
                be_free_birg(birg);
                stat_ev_ctx_pop("bemain_irg");
        }
        ir_profile_free();
        be_done_env(&env);
+
+       be_info_free();
 }
 
 /* Main interface to the frontend. */
index 2ec36ce..769e8ce 100644 (file)
 
 #include "beirgmod.h"
 
-#define OUT_POS(x) (-((x) + 1))
-
 #define get_irn_attr(irn) get_irn_generic_attr(irn)
 #define get_irn_attr_const(irn) get_irn_generic_attr_const(irn)
 
 typedef struct {
        arch_register_req_t req;
-       arch_irn_flags_t    flags;
 } be_req_t;
 
 typedef struct {
-       const arch_register_t *reg;
-       be_req_t               req;
-       be_req_t               in_req;
+       be_req_t req;
+       be_req_t in_req;
 } be_reg_data_t;
 
 /** The generic be nodes attribute type. */
@@ -152,8 +148,6 @@ static int be_reqs_equal(const be_req_t *req1, const be_req_t *req2)
 {
        if(!reg_reqs_equal(&req1->req, &req2->req))
                return 0;
-       if(req1->flags != req2->flags)
-               return 0;
 
        return 1;
 }
@@ -171,8 +165,7 @@ static int _node_cmp_attr(const be_node_attr_t *a, const be_node_attr_t *b) {
 
        len = ARR_LEN(a->reg_data);
        for (i = 0; i < len; ++i) {
-               if (a->reg_data[i].reg != b->reg_data[i].reg ||
-                               !be_reqs_equal(&a->reg_data[i].in_req, &b->reg_data[i].in_req) ||
+               if (!be_reqs_equal(&a->reg_data[i].in_req, &b->reg_data[i].in_req) ||
                            !be_reqs_equal(&a->reg_data[i].req,    &b->reg_data[i].req))
                        return 1;
        }
@@ -189,7 +182,10 @@ static int node_cmp_attr(ir_node *a, ir_node *b) {
        const be_node_attr_t *a_attr = get_irn_attr_const(a);
        const be_node_attr_t *b_attr = get_irn_attr_const(b);
 
-       return _node_cmp_attr(a_attr, b_attr);
+       if(_node_cmp_attr(a_attr, b_attr) != 0)
+               return 1;
+
+       return !be_info_equal(a, b);
 }
 
 /**
@@ -296,9 +292,16 @@ static void *init_node_attr(ir_node *node, int max_reg_data)
        memset(a, 0, sizeof(get_op_attr_size(get_irn_op(node))));
 
        if(max_reg_data >= 0) {
+               backend_info_t *info = be_get_info(node);
+               info->out_infos = NEW_ARR_D(reg_out_info_t, obst, max_reg_data);
+               memset(info->out_infos, 0, max_reg_data * sizeof(info->out_infos[0]));
+
                a->reg_data = NEW_ARR_D(be_reg_data_t, obst, max_reg_data);
                memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
        } else {
+               backend_info_t *info = be_get_info(node);
+               info->out_infos = NEW_ARR_F(reg_out_info_t, 0);
+
                a->reg_data = NEW_ARR_F(be_reg_data_t, 0);
        }
 
@@ -307,10 +310,14 @@ static void *init_node_attr(ir_node *node, int max_reg_data)
 
 static void add_register_req(ir_node *node)
 {
-       be_node_attr_t *a = get_irn_attr(node);
-       be_reg_data_t regreq;
+       backend_info_t *info = be_get_info(node);
+       be_node_attr_t *a    = get_irn_attr(node);
+       be_reg_data_t   regreq;
+       reg_out_info_t  out_info;
        memset(&regreq, 0, sizeof(regreq));
+       memset(&out_info, 0, sizeof(out_info));
        ARR_APP1(be_reg_data_t, a->reg_data, regreq);
+       ARR_APP1(reg_out_info_t, info->out_infos, out_info);
 }
 
 /**
@@ -340,30 +347,6 @@ static int redir_proj(const ir_node **node)
        return 0;
 }
 
-static be_reg_data_t *retrieve_reg_data(const ir_node *node)
-{
-       const be_node_attr_t *attr;
-       int pos = 0;
-
-       if(is_Proj(node)) {
-               pos = get_Proj_proj(node);
-               node = get_Proj_pred(node);
-       }
-
-       assert(is_be_node(node));
-       attr = get_irn_attr_const(node);
-       assert(pos >= 0 && pos < ARR_LEN(attr->reg_data) && "illegal proj number");
-
-       return &attr->reg_data[pos];
-}
-
-static void
-be_node_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       be_reg_data_t *r = retrieve_reg_data(irn);
-       r->reg = reg;
-}
-
 ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
        ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill)
 {
@@ -378,25 +361,26 @@ ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_clas
        a->ent    = NULL;
        a->offset = 0;
 
-       be_node_set_reg_class(res, be_pos_Spill_frame, cls_frame);
-       be_node_set_reg_class(res, be_pos_Spill_val, cls);
+       be_node_set_reg_class_in(res, be_pos_Spill_frame, cls_frame);
+       be_node_set_reg_class_in(res, be_pos_Spill_val, cls);
        return res;
 }
 
-ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
-       ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
+ir_node *be_new_Reload(const arch_register_class_t *cls,
+               const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *block,
+               ir_node *frame, ir_node *mem, ir_mode *mode)
 {
        ir_node *in[2];
        ir_node *res;
 
        in[0] = frame;
        in[1] = mem;
-       res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
+       res   = new_ir_node(NULL, irg, block, op_be_Reload, mode, 2, in);
 
        init_node_attr(res, 2);
-       be_node_set_reg_class(res, -1, cls);
-       be_node_set_reg_class(res, be_pos_Reload_frame, cls_frame);
-       be_node_set_flags(res, -1, arch_irn_flags_rematerializable);
+       be_node_set_reg_class_out(res, 0, cls);
+       be_node_set_reg_class_in(res, be_pos_Reload_frame, cls_frame);
+       arch_irn_set_flags(res, arch_irn_flags_rematerializable);
        return res;
 }
 
@@ -424,14 +408,15 @@ ir_node *be_get_Spill_frame(const ir_node *irn)
        return get_irn_n(irn, be_pos_Spill_frame);
 }
 
-ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
+ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg,
+               ir_node *block, int n, ir_node *in[])
 {
        int i;
-       ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
+       ir_node *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
        init_node_attr(irn, n);
        for(i = 0; i < n; ++i) {
-               be_node_set_reg_class(irn, i, cls);
-               be_node_set_reg_class(irn, OUT_POS(i), cls);
+               be_node_set_reg_class_in(irn, i, cls);
+               be_node_set_reg_class_out(irn, i, cls);
        }
 
        return irn;
@@ -439,9 +424,11 @@ ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *b
 
 void be_Perm_reduce(ir_node *perm, int new_size, int *map)
 {
-       int            arity     = get_irn_arity(perm);
-       be_reg_data_t  *old_data = ALLOCAN(be_reg_data_t, arity);
-       be_node_attr_t *attr     = get_irn_attr(perm);
+       int            arity      = get_irn_arity(perm);
+       be_reg_data_t  *old_data  = ALLOCAN(be_reg_data_t, arity);
+       reg_out_info_t *old_infos = ALLOCAN(reg_out_info_t, arity);
+       be_node_attr_t *attr      = get_irn_attr(perm);
+       backend_info_t *info      = be_get_info(perm);
        ir_node        **new_in;
 
        int i;
@@ -449,16 +436,18 @@ void be_Perm_reduce(ir_node *perm, int new_size, int *map)
        assert(be_is_Perm(perm));
        assert(new_size <= arity);
 
-       NEW_ARR_A(ir_node *, new_in, new_size);
+       new_in = alloca(new_size * sizeof(*new_in));
 
        /* save the old register data */
        memcpy(old_data, attr->reg_data, arity * sizeof(old_data[0]));
+       memcpy(old_infos, info->out_infos, arity * sizeof(old_infos[0]));
 
        /* compose the new in array and set the new register data directly in place */
        for (i = 0; i < new_size; ++i) {
                int idx = map[i];
-               new_in[i]         = get_irn_n(perm, idx);
-               attr->reg_data[i] = old_data[idx];
+               new_in[i]          = get_irn_n(perm, idx);
+               attr->reg_data[i]  = old_data[idx];
+               info->out_infos[i] = old_infos[idx];
        }
 
        set_irn_in(perm, new_size, new_in);
@@ -481,10 +470,10 @@ ir_node *be_new_MemPerm(const arch_env_t *arch_env, ir_graph *irg, ir_node *bl,
        irn =  new_ir_node(NULL, irg, bl, op_be_MemPerm, mode_T, n+1, real_in);
 
        init_node_attr(irn, n + 1);
-       be_node_set_reg_class(irn, 0, sp->reg_class);
+       be_node_set_reg_class_in(irn, 0, sp->reg_class);
        for (i = 0; i < n; ++i) {
-               be_node_set_reg_class(irn, i + 1, cls_frame);
-               be_node_set_reg_class(irn, OUT_POS(i), cls_frame);
+               be_node_set_reg_class_in(irn, i + 1, cls_frame);
+               be_node_set_reg_class_out(irn, i, cls_frame);
        }
 
        attr = get_irn_attr(irn);
@@ -507,10 +496,10 @@ ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *b
        in[0] = op;
        res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
        init_node_attr(res, 1);
-       be_node_set_reg_class(res, 0, cls);
-       be_node_set_reg_class(res, OUT_POS(0), cls);
+       be_node_set_reg_class_in(res, 0, cls);
+       be_node_set_reg_class_out(res, 0, cls);
 
-       req = get_req(res, OUT_POS(0));
+       req = get_req(res, BE_OUT_POS(0));
        req->cls = cls;
        req->type = arch_register_req_type_should_be_same;
        req->other_same = 1U << 0;
@@ -537,7 +526,7 @@ ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *b
        for(i = 0; i < n; ++i) {
                add_irn_n(res, in[i]);
                add_register_req(res);
-               be_node_set_reg_class(res, i, cls);
+               be_node_set_reg_class_in(res, i, cls);
        }
        keep_alive(res);
 
@@ -551,7 +540,7 @@ void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls, ir_node *
        assert(be_is_Keep(keep));
        n = add_irn_n(keep, node);
        add_register_req(keep);
-       be_node_set_reg_class(keep, n, cls);
+       be_node_set_reg_class_in(keep, n, cls);
 }
 
 /* creates a be_Call */
@@ -685,12 +674,9 @@ ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl,
        a->offset = offset;
        a->align  = align;
 
-       be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
-
        /* Set output constraint to stack register. */
-       be_node_set_reg_class(irn, 0, sp->reg_class);
-       be_set_constr_single_reg(irn, BE_OUT_POS(0), sp);
-       be_node_set_irn_reg(irn, sp);
+       be_node_set_reg_class_in(irn, 0, sp->reg_class);
+       be_set_constr_single_reg_out(irn, 0, sp, arch_register_req_type_produces_sp);
 
        return irn;
 }
@@ -708,17 +694,12 @@ ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_
        irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
        a   = init_node_attr(irn, be_pos_AddSP_last);
 
-       be_node_set_flags(irn, OUT_POS(pn_be_AddSP_sp),
-                         arch_irn_flags_ignore | arch_irn_flags_modify_sp);
-
        /* Set output constraint to stack register. */
-       be_set_constr_single_reg(irn, be_pos_AddSP_old_sp, sp);
-       be_node_set_reg_class(irn, be_pos_AddSP_size, arch_register_get_class(sp));
-       be_set_constr_single_reg(irn, OUT_POS(pn_be_AddSP_sp), sp);
-       a->reg_data[pn_be_AddSP_sp].reg = sp;
+       be_set_constr_single_reg_in(irn, be_pos_AddSP_old_sp, sp, 0);
+       be_node_set_reg_class_in(irn, be_pos_AddSP_size, arch_register_get_class(sp));
+       be_set_constr_single_reg_out(irn, pn_be_AddSP_sp, sp, arch_register_req_type_produces_sp);
 
        cls = arch_register_get_class(sp);
-       be_node_set_reg_class(irn, OUT_POS(pn_be_AddSP_res), cls);
 
        return irn;
 }
@@ -735,14 +716,10 @@ ir_node *be_new_SubSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_
        irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, be_pos_SubSP_last, in);
        a   = init_node_attr(irn, be_pos_SubSP_last);
 
-       be_node_set_flags(irn, OUT_POS(pn_be_SubSP_sp),
-                         arch_irn_flags_ignore | arch_irn_flags_modify_sp);
-
        /* Set output constraint to stack register. */
-       be_set_constr_single_reg(irn, be_pos_SubSP_old_sp, sp);
-       be_node_set_reg_class(irn, be_pos_SubSP_size, arch_register_get_class(sp));
-       be_set_constr_single_reg(irn, OUT_POS(pn_be_SubSP_sp), sp);
-       a->reg_data[pn_be_SubSP_sp].reg = sp;
+       be_set_constr_single_reg_in(irn, be_pos_SubSP_old_sp, sp, 0);
+       be_node_set_reg_class_in(irn, be_pos_SubSP_size, arch_register_get_class(sp));
+       be_set_constr_single_reg_out(irn, pn_be_SubSP_sp, sp, arch_register_req_type_produces_sp);
 
        return irn;
 }
@@ -771,8 +748,8 @@ ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg,
        a      = init_node_attr(irn, 1);
        a->ent = ent;
        a->offset = 0;
-       be_node_set_reg_class(irn, 0, cls_frame);
-       be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
+       be_node_set_reg_class_in(irn, 0, cls_frame);
+       be_node_set_reg_class_out(irn, 0, cls_frame);
 
        return optimize_node(irn);
 }
@@ -797,8 +774,8 @@ ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_nod
        memcpy(&in[1], in_keep, n * sizeof(in[0]));
        irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
        init_node_attr(irn, n + 1);
-       be_node_set_reg_class(irn, OUT_POS(0), cls);
-       be_node_set_reg_class(irn, 0, cls);
+       be_node_set_reg_class_in(irn, 0, cls);
+       be_node_set_reg_class_out(irn, 0, cls);
 
        return irn;
 }
@@ -935,24 +912,45 @@ int be_get_MemPerm_entity_arity(const ir_node *irn)
        return get_irn_arity(irn) - 1;
 }
 
-void be_set_constr_single_reg(ir_node *node, int pos, const arch_register_t *reg)
+static void set_req_single(struct obstack *obst, arch_register_req_t *req,
+               const arch_register_t *reg, arch_register_req_type_t additional_types)
 {
-       arch_register_req_t *req = get_req(node, pos);
        const arch_register_class_t *cls = arch_register_get_class(reg);
-       ir_graph *irg = get_irn_irg(node);
-       struct obstack *obst = get_irg_obstack(irg);
-       unsigned *limited_bitset;
-
-       assert(req->cls == NULL || req->cls == cls);
-       assert(! (req->type & arch_register_req_type_limited));
-       assert(req->limited == NULL);
+       unsigned                    *limited_bitset;
 
        limited_bitset = rbitset_obstack_alloc(obst, arch_register_class_n_regs(cls));
        rbitset_set(limited_bitset, arch_register_get_index(reg));
 
        req->cls = cls;
-       req->type |= arch_register_req_type_limited;
+       req->type |= arch_register_req_type_limited | additional_types;
        req->limited = limited_bitset;
+
+}
+
+void be_set_constr_single_reg_in(ir_node *node, int pos,
+               const arch_register_t *reg, arch_register_req_type_t additional_types)
+{
+       arch_register_req_t *req = get_req(node, pos);
+       ir_graph *irg = get_irn_irg(node);
+       struct obstack *obst = get_irg_obstack(irg);
+
+       set_req_single(obst, req, reg, additional_types);
+}
+
+void be_set_constr_single_reg_out(ir_node *node, int pos,
+               const arch_register_t *reg, arch_register_req_type_t additional_types)
+{
+       arch_register_req_t *req = get_req(node, BE_OUT_POS(pos));
+       ir_graph *irg = get_irn_irg(node);
+       struct obstack *obst = get_irg_obstack(irg);
+
+       /* if we have an ignore register, add ignore flag and just assign it */
+       if (reg->type & arch_register_type_ignore) {
+               additional_types |= arch_register_req_type_ignore;
+       }
+
+       arch_irn_set_register(node, pos, reg);
+       set_req_single(obst, req, reg, additional_types);
 }
 
 void be_set_constr_limited(ir_node *node, int pos, const arch_register_req_t *req)
@@ -967,21 +965,22 @@ void be_set_constr_limited(ir_node *node, int pos, const arch_register_req_t *re
        r->limited = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
 }
 
-void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
+void be_node_set_reg_class_in(ir_node *irn, int pos, const arch_register_class_t *cls)
 {
-       be_req_t *bereq = get_be_req(irn, pos);
-       bereq->flags = flags;
-}
+       arch_register_req_t *req = get_req(irn, pos);
 
-void be_node_add_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
-{
-       be_req_t *bereq = get_be_req(irn, pos);
-       bereq->flags |= flags;
+       req->cls = cls;
+
+       if (cls == NULL) {
+               req->type = arch_register_req_type_none;
+       } else if (req->type == arch_register_req_type_none) {
+               req->type = arch_register_req_type_normal;
+       }
 }
 
-void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
+void be_node_set_reg_class_out(ir_node *irn, int pos, const arch_register_class_t *cls)
 {
-       arch_register_req_t *req = get_req(irn, pos);
+       arch_register_req_t *req = get_req(irn, BE_OUT_POS(pos));
 
        req->cls = cls;
 
@@ -1125,17 +1124,6 @@ be_node_get_irn_reg_req(const ir_node *irn, int pos)
        return arch_no_register_req;
 }
 
-const arch_register_t *
-be_node_get_irn_reg(const ir_node *irn)
-{
-       be_reg_data_t *r;
-
-       if (get_irn_mode(irn) == mode_T)
-               return NULL;
-       r = retrieve_reg_data(irn);
-       return r->reg;
-}
-
 static arch_irn_class_t be_node_classify(const ir_node *irn)
 {
 restart:
@@ -1160,21 +1148,6 @@ restart:
        }
 }
 
-static arch_irn_flags_t be_node_get_flags(const ir_node *node)
-{
-       be_req_t *bereq;
-       int pos = -1;
-
-       if(is_Proj(node)) {
-               pos = OUT_POS(get_Proj_proj(node));
-               node = skip_Proj_const(node);
-       }
-
-       bereq = get_be_req(node, pos);
-
-       return bereq->flags;
-}
-
 static ir_entity *be_node_get_frame_entity(const ir_node *irn)
 {
        return be_get_frame_entity(irn);
@@ -1219,10 +1192,7 @@ static int be_node_get_sp_bias(const ir_node *irn)
 
 static const arch_irn_ops_t be_node_irn_ops = {
        be_node_get_irn_reg_req,
-       be_node_set_irn_reg,
-       be_node_get_irn_reg,
        be_node_classify,
-       be_node_get_flags,
        be_node_get_frame_entity,
        be_node_set_frame_entity,
        be_node_set_frame_offset,
@@ -1327,7 +1297,7 @@ const arch_register_req_t *phi_get_irn_reg_req(const ir_node *irn, int pos)
                const arch_register_req_t *req;
                req = get_Phi_reg_req_recursive(irn, &visited);
 
-               memcpy(&attr->req, req, sizeof(req[0]));
+               attr->req = *req;
                assert(attr->req.cls != NULL);
                attr->req.type = arch_register_req_type_normal;
 
@@ -1338,14 +1308,16 @@ const arch_register_req_t *phi_get_irn_reg_req(const ir_node *irn, int pos)
        return &attr->req;
 }
 
-void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
+void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req,
+       arch_register_req_type_t additional_types)
 {
        phi_attr_t *attr;
 
        assert(mode_is_datab(get_irn_mode(node)));
 
-       attr = get_Phi_attr(node);
-       memcpy(&attr->req, req, sizeof(req[0]));
+       attr            = get_Phi_attr(node);
+       attr->req       = *req;
+       attr->req.type |= additional_types;
 }
 
 void be_set_phi_flags(ir_node *node, arch_irn_flags_t flags)
@@ -1358,30 +1330,12 @@ void be_set_phi_flags(ir_node *node, arch_irn_flags_t flags)
        attr->flags = flags;
 }
 
-static void phi_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       phi_attr_t *attr = get_Phi_attr(irn);
-       attr->reg = reg;
-}
-
-static const arch_register_t *phi_get_irn_reg(const ir_node *irn)
-{
-       phi_attr_t *attr = get_Phi_attr(irn);
-       return attr->reg;
-}
-
 static arch_irn_class_t phi_classify(const ir_node *irn)
 {
        (void) irn;
        return 0;
 }
 
-static arch_irn_flags_t phi_get_flags(const ir_node *irn)
-{
-       phi_attr_t *attr = get_Phi_attr(irn);
-       return attr->flags;
-}
-
 static ir_entity *phi_get_frame_entity(const ir_node *irn)
 {
        (void) irn;
@@ -1410,10 +1364,7 @@ static int phi_get_sp_bias(const ir_node *irn)
 
 static const arch_irn_ops_t phi_irn_ops = {
        phi_get_irn_reg_req,
-       phi_set_irn_reg,
-       phi_get_irn_reg,
        phi_classify,
-       phi_get_flags,
        phi_get_frame_entity,
        phi_set_frame_entity,
        phi_set_frame_offset,
@@ -1489,9 +1440,8 @@ static void dump_node_reqs(FILE *f, ir_node *node)
 
        fprintf(f, "registers: \n");
        for(i = 0; i < len; ++i) {
-               be_reg_data_t *rd = &a->reg_data[i];
-               if(rd->reg)
-                       fprintf(f, "#%d: %s\n", i, rd->reg->name);
+               const arch_register_t *reg = arch_irn_get_register(node, i);
+               fprintf(f, "#%d: %s\n", i, reg != NULL ? reg->name : "n/a");
        }
 
        fprintf(f, "in requirements:\n");
@@ -1607,6 +1557,8 @@ static void copy_attr(const ir_node *old_node, ir_node *new_node)
        const be_node_attr_t *old_attr = get_irn_attr_const(old_node);
        be_node_attr_t *new_attr = get_irn_attr(new_node);
        struct obstack *obst = get_irg_obstack(get_irn_irg(new_node));
+       backend_info_t *old_info = be_get_info(old_node);
+       backend_info_t *new_info = be_get_info(new_node);
        unsigned i, len;
 
        assert(is_be_node(old_node));
@@ -1623,12 +1575,15 @@ static void copy_attr(const ir_node *old_node, ir_node *new_node)
        if(get_irn_op(old_node)->opar == oparity_dynamic
                        || be_is_RegParams(old_node)) {
                new_attr->reg_data = NEW_ARR_F(be_reg_data_t, len);
+               new_info->out_infos = NEW_ARR_F(reg_out_info_t, len);
        } else {
                new_attr->reg_data = NEW_ARR_D(be_reg_data_t, obst, len);
+               new_info->out_infos = NEW_ARR_D(reg_out_info_t, obst, len);
        }
 
        if(len > 0) {
                memcpy(new_attr->reg_data, old_attr->reg_data, len * sizeof(be_reg_data_t));
+               memcpy(new_info->out_infos, old_info->out_infos, len * sizeof(new_info->out_infos[0]));
                for(i = 0; i < len; ++i) {
                        const be_reg_data_t *rd = &old_attr->reg_data[i];
                        be_reg_data_t *newrd = &new_attr->reg_data[i];
index 3a1104d..2cad672 100644 (file)
@@ -452,10 +452,13 @@ int be_get_MemPerm_entity_arity(const ir_node *irn);
 /**
  * Impose a register constraint on a backend node.
  * @param irn The node.
- * @param pos The position of the argument/result. Results range from -1..-m and arguments form 0..n
+ * @param pos The position of the argument.
  * @param reg The register which is admissible for that node, argument/result and position.
  */
-void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg);
+void be_set_constr_single_reg_in(ir_node *irn, int pos,
+               const arch_register_t *reg, arch_register_req_type_t additional_flags);
+void be_set_constr_single_reg_out(ir_node *irn, int pos,
+               const arch_register_t *reg, arch_register_req_type_t additional_flags);
 
 /**
  * Impose register constraints on a backend node.
@@ -467,23 +470,14 @@ void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
  */
 void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req);
 
-/**
- * Set the flags of a node.
- * @param irn The node itself.
- * @param pos The position (0..n) for arguments, (-1..-m) for results.
- * @param flags The flags to set for that node and position.
- */
-void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags);
-
-void be_node_add_flags(ir_node *irn, int pos, arch_irn_flags_t flags);
-
 /**
  * Set the register class of a node.
  * @param irn The node itself.
- * @param pos The position (0..n) for arguments, (-1..-m) for results.
+ * @param pos The position (0..n) for arguments
  * @param flags The register class to set for that node and position.
  */
-void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls);
+void be_node_set_reg_class_in(ir_node *irn, int pos, const arch_register_class_t *cls);
+void be_node_set_reg_class_out(ir_node *irn, int pos, const arch_register_class_t *cls);
 
 /**
  * Set the register requirement type of a node.
@@ -512,12 +506,8 @@ void be_phi_handler_reset(void);
 /**
  * Set the register requirements for a phi node.
  */
-void be_set_phi_reg_req(ir_node *phi, const arch_register_req_t *req);
-
-/*
- * Set flags for a phi node
- */
-void be_set_phi_flags(ir_node *phi, arch_irn_flags_t flags);
+void be_set_phi_reg_req(ir_node *phi, const arch_register_req_t *req,
+               arch_register_req_type_t additional_types);
 
 /**
  * irn handler for common be nodes and Phi's.
index 5cdb8f4..0a84ac4 100644 (file)
@@ -190,24 +190,3 @@ void be_remove_dead_nodes_from_schedule(be_irg_t *birg)
        // walk schedule and remove non-marked nodes
        irg_block_walk_graph(irg, remove_dead_nodes_walker, NULL, &env);
 }
-
-static void *sched_irn_init(ir_phase *ph, const ir_node *irn, void *old)
-{
-       sched_info_t *info = old ? old : phase_alloc(ph, sizeof(*info));
-
-       info->idx  = get_irn_idx(irn);
-       INIT_LIST_HEAD(&info->list);
-       info->scheduled = 0;
-       info->time_step = 0;
-       return info;
-}
-
-void be_sched_init_phase(ir_graph *irg)
-{
-       init_irg_phase(irg, PHASE_BE_SCHED, 0, sched_irn_init);
-}
-
-void be_sched_free_phase(ir_graph *irg)
-{
-       free_irg_phase(irg, PHASE_BE_SCHED);
-}
index e02d940..5352f5e 100644 (file)
@@ -85,7 +85,4 @@ void    sched_remove(const ir_node *irn);
  */
 void be_remove_dead_nodes_from_schedule(be_irg_t *birg);
 
-void be_sched_init_phase(ir_graph *irg);
-void be_sched_free_phase(ir_graph *irg);
-
-#endif /* FIRM_BE_BESCHED_H */
+#endif
index cf7b7d2..79685aa 100644 (file)
 
 #include "beutil.h"
 #include "besched.h"
-
-typedef unsigned int sched_timestep_t;
-
-extern size_t sched_irn_data_offset;
-
-/**
- * The schedule structure which is present at each ir node.
- *
- * Currently, only basic blocks are scheduled. The list head of
- * every block schedule list is the Block list.
- */
-typedef struct _sched_info_t {
-       struct list_head list;         /**< The list head to list the nodes in a schedule. */
-       unsigned idx;                  /**< The node index of the nodes this schedule info belongs to. */
-       sched_timestep_t time_step;    /**< If a is after b in a schedule, its time step is larger than b's. */
-       unsigned scheduled : 1;        /**< 1, if the node is in the schedule of the block, 0 else. */
-} sched_info_t;
+#include "beinfo.h"
 
 #define _sched_entry(list_head)             (list_entry(list_head, sched_info_t, list))
-#define get_irn_sched_info(irn)             ((sched_info_t *) get_or_set_irn_phase_info(skip_Proj_const(irn), PHASE_BE_SCHED))
+#define get_irn_sched_info(irn)             (&be_get_info(skip_Proj_const(irn))->sched_info)
 #define get_sched_info_irn(irg, sched_info) get_idx_irn((irg), (sched_info)->idx)
 
 /**
@@ -65,7 +49,7 @@ typedef struct _sched_info_t {
  */
 static inline int _have_sched_info(const ir_graph *irg)
 {
-       return get_irg_phase(irg, PHASE_BE_SCHED) != NULL;
+       return be_info_initialized(irg);
 }
 
 /**
index 6b83ee5..cc5ea38 100644 (file)
@@ -108,17 +108,20 @@ typedef struct flag_and_cost {
 static int count_result(const ir_node* irn)
 {
        const ir_mode* mode = get_irn_mode(irn);
-       return
-               mode != mode_M &&
-               mode != mode_X &&
-               !arch_irn_is(irn, ignore);
+
+       if (mode == mode_M || mode == mode_X)
+               return 0;
+
+       if (arch_get_register_req_out(irn)->type & arch_register_req_type_ignore)
+               return 0;
+
+       return 1;
 }
 
 
 /* TODO high cost for store trees
  */
 
-
 static int normal_tree_cost(ir_node* irn)
 {
        flag_and_cost* fc    = get_irn_link(irn);
@@ -159,7 +162,7 @@ static int normal_tree_cost(ir_node* irn)
 
                                cost = normal_tree_cost(pred);
                                if (be_is_Barrier(pred)) cost = 1; // XXX hack: the barrier causes all users to have a reguse of #regs
-                               if (!arch_irn_is(pred, ignore)) {
+                               if (!arch_irn_is_ignore(pred)) {
                                        real_pred = (is_Proj(pred) ? get_Proj_pred(pred) : pred);
                                        pred_fc = get_irn_link(real_pred);
                                        pred_fc->no_root = 1;
@@ -183,7 +186,7 @@ static int normal_tree_cost(ir_node* irn)
                ir_node* op = fc->costs[i].irn;
                if (op == last)                 continue;
                if (get_irn_mode(op) == mode_M) continue;
-               if (arch_irn_is(op, ignore))    continue;
+               if (arch_irn_is_ignore(op))     continue;
                cost = MAX(fc->costs[i].cost + n_op_res, cost);
                last = op;
                ++n_op_res;
index 3659127..c76ebc1 100644 (file)
@@ -632,7 +632,7 @@ static void collect_descendants(rss_t *rss, rss_irn_t *rirn, ir_node *irn, int *
                        ir_node *user = get_edge_src_irn(edge);
 
                        /* skip ignore nodes as they do not really contribute to register pressure */
-                       if (arch_irn_is(user, ignore))
+                       if (arch_irn_is_ignore(user))
                                continue;
 
                        /*
@@ -680,7 +680,7 @@ static void collect_single_consumer(rss_t *rss, rss_irn_t *rss_irn, ir_node *con
        assert(! is_Proj(consumer) && "Cannot handle Projs");
 
        if (! is_Phi(consumer) && ! is_Block(consumer) && get_nodes_block(consumer) == block) {
-               if (!arch_irn_is(consumer, ignore) &&
+               if (!arch_irn_is_ignore(consumer) &&
                                !plist_has_value(rss_irn->consumer_list, consumer)) {
                        plist_insert_back(rss_irn->consumer_list, consumer);
                        DBG((rss->dbg, LEVEL_2, "\t\tconsumer %+F\n", consumer));
@@ -2111,7 +2111,7 @@ static void process_block(ir_node *block, void *env) {
                        if (be_is_Keep(irn))
                                continue;
 
-                       if (!arch_irn_is(irn, ignore) &&
+                       if (!arch_irn_is_ignore(irn) &&
                                        arch_get_irn_reg_class_out(irn) == cls) {
                                plist_insert_back(rss->nodes, skip_Proj(irn));
                        }
index 5bb8d72..4e903ed 100644 (file)
@@ -302,11 +302,16 @@ static int get_reg_difference(trace_env_t *env, ir_node *irn) {
        for (i = get_irn_arity(irn) - 1; i >= 0; i--) {
                ir_node *in = get_irn_n(irn, i);
 
-               if (mode_is_datab(get_irn_mode(in)) &&           /* must be data node */
-                   !arch_irn_is(in, ignore)        &&           /* ignore "ignore" nodes :) */
-                   !be_is_live_end(env->liveness, block, in)) { /* if the value lives outside of block: do not count */
-                       num_in++;
-               }
+               if (!mode_is_datab(get_irn_mode(in)))
+                       continue;
+
+               if (arch_irn_is_ignore(in))
+                       continue;
+
+               if (be_is_live_end(env->liveness, block, in))
+                       continue;
+
+               num_in++;
        }
 
        return num_out - num_in;
index 6df8bc7..2746cb0 100644 (file)
@@ -562,39 +562,19 @@ static int is_value_available(spill_env_t *env, const ir_node *arg,
        if(arg == get_irg_frame(env->irg))
                return 1;
 
+#if 0
        /* hack for now (happens when command should be inserted at end of block) */
-       if(is_Block(reloader)) {
+       if(is_Block(reloader))
                return 0;
-       }
+#else
+       (void)reloader;
+#endif
 
        /*
         * Ignore registers are always available
         */
-       if (arch_irn_is(arg, ignore)) {
+       if (arch_irn_is_ignore(arg))
                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.
-        */
-#if 0
-       /* 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->birg->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;
-       }
-#endif
 
        return 0;
 }
@@ -640,6 +620,10 @@ static int check_remat_conditions_costs(spill_env_t *env,
        if(parentcosts + costs >= env->reload_cost + env->spill_cost) {
                return REMAT_COST_INFINITE;
        }
+       /* never rematerialize a node which modifies the flags.
+        * (would be better to test wether the flags are actually live at point
+        * reloader...)
+        */
        if (arch_irn_is(spilled, modify_flags)) {
                return REMAT_COST_INFINITE;
        }
index 4e4000d..768ece1 100644 (file)
@@ -280,11 +280,10 @@ static inline unsigned get_distance(ir_node *from, unsigned from_step,
                                     const ir_node *def, int skip_from_uses)
 {
        be_next_use_t use;
-       int           flags = arch_irn_get_flags(def);
        unsigned      costs;
        unsigned      time;
 
-       assert(! (flags & arch_irn_flags_ignore));
+       assert(!arch_irn_is_ignore(def));
 
        use  = be_get_next_use(uses, from, from_step, def, skip_from_uses);
        time = use.time;
@@ -292,7 +291,7 @@ static inline unsigned get_distance(ir_node *from, unsigned from_step,
                return USES_INFINITY;
 
        /* We have to keep nonspillable nodes in the workingset */
-       if (flags & arch_irn_flags_dont_spill)
+       if (arch_irn_get_flags(def) & arch_irn_flags_dont_spill)
                return 0;
 
        /* give some bonus to rematerialisable nodes */
index a0aa866..cf2c4db 100644 (file)
@@ -503,7 +503,7 @@ static inline unsigned get_curr_distance(block_info_t *bi, const ir_node *irn, i
        next_use_t *use            = get_current_use(bi, irn);
        int flags                  = arch_irn_get_flags(irn);
 
-       assert(!(flags & arch_irn_flags_ignore));
+       assert(!arch_irn_is_ignore(irn));
 
        /* We have to keep non-spillable nodes in the working set */
        if(flags & arch_irn_flags_dont_spill)
diff --git a/ir/be/bespillremat.c b/ir/be/bespillremat.c
deleted file mode 100644 (file)
index eaf4aa3..0000000
+++ /dev/null
@@ -1,4617 +0,0 @@
-/*
- * Copyright (C) 1995-2008 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       ILP based spilling & rematerialization
- * @author      Adam M. Szalkowski
- * @date        06.04.2006
- * @version     $Id$
- */
-#include "config.h"
-
-#ifdef WITH_ILP
-
-#include <math.h>
-
-#include "array_t.h"
-#include "hashptr.h"
-#include "debug.h"
-#include "obst.h"
-#include "set.h"
-#include "list.h"
-#include "pmap.h"
-
-#include "irprintf.h"
-#include "irgwalk.h"
-#include "irdump_t.h"
-#include "irnode_t.h"
-#include "ircons_t.h"
-#include "irloop_t.h"
-#include "irnodeset.h"
-#include "phiclass.h"
-#include "iredges_t.h"
-#include "execfreq.h"
-#include "irvrfy.h"
-#include "irbackedge_t.h"
-#include "irprofile.h"
-
-#include <lpp/lpp.h>
-#include <lpp/mps.h>
-#include <lpp/lpp_net.h>
-#include <lpp/lpp_cplex.h>
-
-#include "be_t.h"
-#include "beirg_t.h"
-#include "belive_t.h"
-#include "besched_t.h"
-#include "bessaconstr.h"
-#include "bearch_t.h"
-#include "beintlive_t.h"
-#include "beabi.h"
-#include "benode_t.h"
-#include "beutil.h"
-#include "bespillremat.h"
-#include "bespill.h"
-#include "bepressurestat.h"
-#include "bespilloptions.h"
-#include "bechordal_t.h"
-#include "bemodule.h"
-
-#include "lc_opts.h"
-#include "lc_opts_enum.h"
-
-#define DUMP_PROBLEM       1
-#define DUMP_MPS           2
-#define DUMP_SOLUTION      4
-#define DUMP_STATS         8
-#define DUMP_PRESSURE      16
-
-#define KEEPALIVE_REMATS   1
-#define KEEPALIVE_SPILLS   2
-#define KEEPALIVE_RELOADS  4
-
-#define VERIFY_MEMINTERF   1
-#define VERIFY_DOMINANCE   2
-
-#define REMATS_NONE        0
-#define REMATS_BRIGGS      1
-#define REMATS_NOINVERSE   2
-#define REMATS_ALL         3
-
-static unsigned opt_dump_flags = 0;
-static int opt_log = 0;
-static unsigned opt_keep_alive = 0;
-static int opt_goodwin = 1;
-static int opt_memcopies = 1;
-static int opt_memoperands = 1;
-static int opt_verify = VERIFY_MEMINTERF;
-static unsigned opt_remats = REMATS_ALL;
-static int opt_repair_schedule = 0;
-static int opt_no_enlarge_liveness = 0;
-static int opt_remat_while_live = 1;
-static int opt_timeout = 300;
-static double opt_cost_reload = 8.0;
-static double opt_cost_memoperand =  7.0;
-static double opt_cost_spill =  15.0;
-static double opt_cost_remat =  1.0;
-
-
-static const lc_opt_enum_mask_items_t dump_items[] = {
-       { "problem",  DUMP_PROBLEM  },
-       { "mps",      DUMP_MPS      },
-       { "solution", DUMP_SOLUTION },
-       { "stats",    DUMP_STATS },
-       { "pressure", DUMP_PRESSURE },
-       { NULL,       0 }
-};
-
-static lc_opt_enum_mask_var_t dump_var = {
-       &opt_dump_flags, dump_items
-};
-
-static const lc_opt_enum_mask_items_t keepalive_items[] = {
-       { "remats",  KEEPALIVE_REMATS  },
-       { "spills",  KEEPALIVE_SPILLS  },
-       { "reloads", KEEPALIVE_RELOADS },
-       { NULL,      0 }
-};
-
-static lc_opt_enum_mask_var_t keep_alive_var = {
-       &opt_keep_alive, keepalive_items
-};
-
-static const lc_opt_enum_mask_items_t remats_items[] = {
-       { "none",      REMATS_NONE      },
-       { "briggs",    REMATS_BRIGGS    },
-       { "noinverse", REMATS_NOINVERSE },
-       { "all",       REMATS_ALL       },
-       { NULL,        0 }
-};
-
-static lc_opt_enum_mask_var_t remats_var = {
-       &opt_remats, remats_items
-};
-
-static const lc_opt_table_entry_t options[] = {
-       LC_OPT_ENT_ENUM_MASK("keepalive", "keep alive inserted nodes",                              &keep_alive_var),
-
-       LC_OPT_ENT_BOOL     ("goodwin",  "activate goodwin reduction",                              &opt_goodwin),
-       LC_OPT_ENT_BOOL     ("memcopies",  "activate memcopy handling",                             &opt_memcopies),
-       LC_OPT_ENT_BOOL     ("memoperands",  "activate memoperands",                                &opt_memoperands),
-       LC_OPT_ENT_ENUM_INT ("remats",  "type of remats to insert",                                 &remats_var),
-       LC_OPT_ENT_BOOL     ("repair_schedule",  "repair the schedule by rematting once used nodes",&opt_repair_schedule),
-       LC_OPT_ENT_BOOL     ("no_enlage_liveness",  "do not enlarge liveness of operands of remats",&opt_no_enlarge_liveness),
-       LC_OPT_ENT_BOOL     ("remat_while_live",  "only remat where rematted value was live",       &opt_remat_while_live),
-
-       LC_OPT_ENT_ENUM_MASK("dump", "dump problem, solution or statistical data",                  &dump_var),
-       LC_OPT_ENT_BOOL     ("log",  "activate the lpp log",                                        &opt_log),
-       LC_OPT_ENT_INT      ("timeout",  "ILP solver timeout",                                      &opt_timeout),
-
-       LC_OPT_ENT_DBL      ("cost_reload",  "cost of a reload",                                    &opt_cost_reload),
-       LC_OPT_ENT_DBL      ("cost_memoperand",  "cost of a memory operand",                        &opt_cost_memoperand),
-       LC_OPT_ENT_DBL      ("cost_spill",  "cost of a spill instruction",                          &opt_cost_spill),
-       LC_OPT_ENT_DBL      ("cost_remat",  "cost of a rematerialization",                          &opt_cost_remat),
-       LC_OPT_LAST
-};
-
-//#define EXECFREQ_LOOPDEPH   /* compute execution frequency from loop depth only */
-//#define SCHEDULE_PHIM   /* insert phim nodes into schedule */
-
-#define  SOLVE
-//#define  SOLVE_LOCAL
-#define LPP_SERVER "i44pc52"
-#define LPP_SOLVER "cplex"
-
-
-#define MAX_PATHS      INT_MAX
-#define ILP_UNDEF              -1
-
-typedef struct _spill_ilp_t {
-       const arch_register_class_t  *cls;
-       int                           n_regs;
-       be_irg_t                     *birg;
-       be_lv_t                      *lv;
-       lpp_t                        *lpp;
-       struct obstack               *obst;
-       set                          *remat_info;
-       pset                         *all_possible_remats;
-       pset                         *inverse_ops;
-       ir_node                      *keep;
-       set                          *values; /**< for collecting all definitions of values before running ssa-construction */
-       pset                         *spills;
-       set                          *interferences;
-       ir_node                      *m_unknown;
-       set                          *memoperands;
-       phi_classes_t                *pc;
-#ifndef SCHEDULE_PHIM
-       pset                         *phims;
-#endif
-       DEBUG_ONLY(firm_dbg_module_t * dbg);
-} spill_ilp_t;
-
-typedef int ilp_var_t;
-typedef int ilp_cst_t;
-
-typedef struct _spill_bb_t {
-       set      *ilp;
-       set      *reloads;
-} spill_bb_t;
-
-typedef struct _remat_t {
-       const ir_node        *op;      /**< for copy_irn */
-       const ir_node        *value;   /**< the value which is being recomputed by this remat */
-       const ir_node        *proj;    /**< not NULL if the above op produces a tuple */
-       int                   cost;    /**< cost of this remat */
-       int                   inverse; /**< nonzero if this is an inverse remat */
-} remat_t;
-
-/**
- * Data to be attached to each IR node. For remats this contains the ilp_var
- * for this remat and for normal ops this contains the ilp_vars for
- * reloading each operand
- */
-typedef struct _op_t {
-       int             is_remat;
-       union {
-               struct {
-                       ilp_var_t       ilp;
-                       const remat_t  *remat; /** the remat this op belongs to */
-                       int             pre; /** 1, if this is a pressure-increasing remat */
-               } remat;
-               struct {
-                       ilp_var_t       ilp;
-                       ir_node        *op; /** the operation this live range belongs to */
-                       union {
-                               ilp_var_t      *reloads;
-                               ilp_var_t      *copies;
-                       } args;
-               } live_range;
-       } attr;
-} op_t;
-
-typedef struct _defs_t {
-       const ir_node   *value;
-       ir_node         *spills;  /**< points to the first spill for this value (linked by link field) */
-       ir_node         *remats;  /**< points to the first definition for this value (linked by link field) */
-} defs_t;
-
-typedef struct _remat_info_t {
-       const ir_node       *irn; /**< the irn to which these remats belong */
-       pset                *remats; /**< possible remats for this value */
-       pset                *remats_by_operand; /**< remats with this value as operand */
-} remat_info_t;
-
-typedef struct _keyval_t {
-       const void          *key;
-       const void          *val;
-} keyval_t;
-
-typedef struct _spill_t {
-       ir_node            *irn;
-       ilp_var_t           reg_in;
-       ilp_var_t           mem_in;
-       ilp_var_t           reg_out;
-       ilp_var_t           mem_out;
-       ilp_var_t           spill;
-} spill_t;
-
-typedef struct _memoperand_t {
-       ir_node             *irn; /**< the irn */
-       unsigned int         pos; /**< the position of the argument */
-       ilp_var_t            ilp; /**< the ilp var for this memory operand */
-} memoperand_t;
-
-static inline int
-has_reg_class(const spill_ilp_t * si, const ir_node * irn)
-{
-       return arch_irn_consider_in_reg_alloc(si->cls, irn);
-}
-
-#if 0
-static int
-cmp_remat(const void *a, const void *b)
-{
-       const keyval_t *p = a;
-       const keyval_t *q = b;
-       const remat_t  *r = p->val;
-       const remat_t  *s = q->val;
-
-       assert(r && s);
-
-       return !(r == s || r->op == s->op);
-}
-#endif
-static int
-cmp_remat(const void *a, const void *b)
-{
-       const remat_t  *r = a;
-       const remat_t  *s = b;
-
-       return !(r == s || r->op == s->op);
-}
-
-static int
-cmp_spill(const void *a, const void *b, size_t size)
-{
-       const spill_t *p = a;
-       const spill_t *q = b;
-       (void) size;
-
-//     return !(p->irn == q->irn && p->bb == q->bb);
-       return !(p->irn == q->irn);
-}
-
-static int
-cmp_memoperands(const void *a, const void *b, size_t size)
-{
-       const memoperand_t *p = a;
-       const memoperand_t *q = b;
-       (void) size;
-
-       return !(p->irn == q->irn && p->pos == q->pos);
-}
-
-static keyval_t *
-set_find_keyval(set * set, const void * key)
-{
-       keyval_t     query;
-
-       query.key = key;
-       return set_find(set, &query, sizeof(query), HASH_PTR(key));
-}
-
-static keyval_t *
-set_insert_keyval(set * set, void * key, void * val)
-{
-       keyval_t     query;
-
-       query.key = key;
-       query.val = val;
-       return set_insert(set, &query, sizeof(query), HASH_PTR(key));
-}
-
-static defs_t *
-set_find_def(set * set, const ir_node * value)
-{
-       defs_t     query;
-
-       query.value = value;
-       return set_find(set, &query, sizeof(query), HASH_PTR(value));
-}
-
-static defs_t *
-set_insert_def(set * set, const ir_node * value)
-{
-       defs_t     query;
-
-       query.value = value;
-       query.spills = NULL;
-       query.remats = NULL;
-       return set_insert(set, &query, sizeof(query), HASH_PTR(value));
-}
-
-static memoperand_t *
-set_insert_memoperand(set * set, ir_node * irn, unsigned int pos, ilp_var_t ilp)
-{
-       memoperand_t     query;
-
-       query.irn = irn;
-       query.pos = pos;
-       query.ilp = ilp;
-       return set_insert(set, &query, sizeof(query), HASH_PTR(irn)+pos);
-}
-
-static memoperand_t *
-set_find_memoperand(set * set, const ir_node * irn, unsigned int pos)
-{
-       memoperand_t     query;
-
-       query.irn = (ir_node*)irn;
-       query.pos = pos;
-       return set_find(set, &query, sizeof(query), HASH_PTR(irn)+pos);
-}
-
-
-static spill_t *
-set_find_spill(set * set, const ir_node * value)
-{
-       spill_t     query;
-
-       query.irn = (ir_node*)value;
-       return set_find(set, &query, sizeof(query), HASH_PTR(value));
-}
-
-#define pset_foreach(s,i) for((i)=pset_first((s)); (i); (i)=pset_next((s)))
-#define set_foreach(s,i) for((i)=set_first((s)); (i); (i)=set_next((s)))
-#define foreach_post_remat(s,i) for((i)=next_post_remat((s)); (i); (i)=next_post_remat((i)))
-#define foreach_pre_remat(s,i) for((i)=next_pre_remat((s)); (i); (i)=next_pre_remat((i)))
-#define        sched_foreach_op(s,i) for((i)=sched_next_op((s));!sched_is_end((i));(i)=sched_next_op((i)))
-
-static int
-cmp_remat_info(const void *a, const void *b, size_t size)
-{
-       const remat_info_t *p = a;
-       const remat_info_t *q = b;
-       (void) size;
-
-       return !(p->irn == q->irn);
-}
-
-static int
-cmp_defs(const void *a, const void *b, size_t size)
-{
-       const defs_t *p = a;
-       const defs_t *q = b;
-       (void) size;
-
-       return !(p->value == q->value);
-}
-
-static int
-cmp_keyval(const void *a, const void *b, size_t size)
-{
-       const keyval_t *p = a;
-       const keyval_t *q = b;
-       (void) size;
-
-       return !(p->key == q->key);
-}
-
-static double
-execution_frequency(const spill_ilp_t *si, const ir_node * irn)
-{
-#define FUDGE 0.001
-       if(ir_profile_has_data())
-               return ((double)ir_profile_get_block_execcount(get_block_const(irn))) + FUDGE;
-
-#ifndef EXECFREQ_LOOPDEPH
-       return get_block_execfreq(si->birg->exec_freq, get_block_const(irn)) + FUDGE;
-#else
-       if(is_Block(irn))
-               return exp(get_loop_depth(get_irn_loop(irn)) * log(10)) + FUDGE;
-       else
-               return exp(get_loop_depth(get_irn_loop(get_nodes_block(irn))) * log(10)) + FUDGE;
-#endif
-}
-
-static double get_cost(const ir_node *irn)
-{
-       if(be_is_Spill(irn)) {
-               return opt_cost_spill;
-       } else if(be_is_Reload(irn)){
-               return opt_cost_reload;
-       } else {
-               return arch_get_op_estimated_cost(irn);
-       }
-}
-
-/**
- * Checks, whether node and its operands have suitable reg classes
- */
-static inline int
-is_rematerializable(const spill_ilp_t * si, const ir_node * irn)
-{
-       int n;
-       int remat = (arch_irn_get_flags(irn) & arch_irn_flags_rematerializable) != 0;
-
-#if 0
-       if(!remat)
-               ir_fprintf(stderr, "  Node %+F is not rematerializable\n", irn);
-#endif
-
-       for (n = get_irn_arity(irn)-1; n>=0 && remat; --n) {
-               ir_node        *op = get_irn_n(irn, n);
-               remat &= has_reg_class(si, op) || arch_irn_get_flags(op) & arch_irn_flags_ignore || is_NoMem(op);
-
-//             if(!remat)
-//                     ir_fprintf(stderr, "  Argument %d (%+F) of Node %+F has wrong regclass\n", i, op, irn);
-       }
-
-       return remat;
-}
-
-/**
- * Try to create a remat from @p op with destination value @p dest_value
- */
-static inline remat_t *
-get_remat_from_op(spill_ilp_t * si, const ir_node * dest_value, const ir_node * op)
-{
-       remat_t  *remat = NULL;
-
-//     if(!mode_is_datab(get_irn_mode(dest_value)))
-//             return NULL;
-
-       if(dest_value == op) {
-               const ir_node *proj = NULL;
-
-               if(is_Proj(dest_value)) {
-                       op = get_Proj_pred(op);
-                       proj = dest_value;
-               }
-
-               if(!is_rematerializable(si, op))
-                       return NULL;
-
-               remat          = obstack_alloc(si->obst, sizeof(*remat));
-               remat->op      = op;
-               remat->cost    = (int)get_cost(op);
-               remat->value   = dest_value;
-               remat->proj    = proj;
-               remat->inverse = 0;
-       } else {
-               arch_inverse_t     inverse;
-               int                n;
-
-               /* get the index of the operand we want to retrieve by the inverse op */
-               for (n = get_irn_arity(op)-1; n>=0; --n) {
-                       ir_node        *arg = get_irn_n(op, n);
-
-                       if(arg == dest_value) break;
-               }
-               if(n<0) return NULL;
-
-               DBG((si->dbg, LEVEL_5, "\t  requesting inverse op for argument %d of op %+F\n", n, op));
-
-               /* else ask the backend to give an inverse op */
-               if(arch_get_inverse(op, n, &inverse, si->obst)) {
-                       int   i;
-
-                       DBG((si->dbg, LEVEL_4, "\t  backend gave us an inverse op with %d nodes and cost %d\n", inverse.n, inverse.costs));
-
-                       assert(inverse.n > 0 && "inverse op should have at least one node");
-
-                       for(i=inverse.n-1; i>=0; --i) {
-                               pset_insert_ptr(si->inverse_ops, inverse.nodes[i]);
-                       }
-
-                       if(inverse.n <= 2) {
-                               remat = obstack_alloc(si->obst, sizeof(*remat));
-                               remat->op = inverse.nodes[0];
-                               remat->cost = inverse.costs;
-                               remat->value = dest_value;
-                               remat->proj = (inverse.n==2)?inverse.nodes[1]:NULL;
-                               remat->inverse = 1;
-
-                               // Matze: commented this out, this doesn't seem to be true if
-                               // the inverse is a simple operation with only 1 result...
-                               //assert(is_Proj(remat->proj));
-                       } else {
-                               assert(0 && "I can not handle remats with more than 2 nodes");
-                       }
-               }
-       }
-
-       if(remat) {
-               if(remat->proj) {
-                       DBG((si->dbg, LEVEL_3, "\t >Found remat %+F for %+F from %+F with %+F\n", remat->op, dest_value, op, remat->proj));
-               } else {
-                       DBG((si->dbg, LEVEL_3, "\t >Found remat %+F for %+F from %+F\n", remat->op, dest_value, op));
-               }
-       }
-       return remat;
-}
-
-
-static inline void
-add_remat(const spill_ilp_t * si, const remat_t * remat)
-{
-       remat_info_t    *remat_info,
-                     query;
-       int              n;
-
-       assert(remat->op);
-       assert(remat->value);
-
-       query.irn = remat->value;
-       query.remats = NULL;
-       query.remats_by_operand = NULL;
-       remat_info = set_insert(si->remat_info, &query, sizeof(query), HASH_PTR(remat->value));
-
-       if(remat_info->remats == NULL) {
-               remat_info->remats = new_pset(cmp_remat, 4096);
-       }
-       pset_insert(remat_info->remats, remat, HASH_PTR(remat->op));
-
-       /* insert the remat into the remats_be_operand set of each argument of the remat op */
-       for (n = get_irn_arity(remat->op)-1; n>=0; --n) {
-               ir_node        *arg = get_irn_n(remat->op, n);
-
-               query.irn = arg;
-               query.remats = NULL;
-               query.remats_by_operand = NULL;
-               remat_info = set_insert(si->remat_info, &query, sizeof(query), HASH_PTR(arg));
-
-               if(remat_info->remats_by_operand == NULL) {
-                       remat_info->remats_by_operand = new_pset(cmp_remat, 4096);
-               }
-               pset_insert(remat_info->remats_by_operand, remat, HASH_PTR(remat->op));
-       }
-}
-
-static int
-get_irn_n_nonremat_edges(const spill_ilp_t * si, const ir_node * irn)
-{
-       const ir_edge_t   *edge = get_irn_out_edge_first(irn);
-       int                i = 0;
-
-       while(edge) {
-               if(!pset_find_ptr(si->inverse_ops, edge->src)) {
-                       ++i;
-               }
-               edge = get_irn_out_edge_next(irn, edge);
-       }
-
-       return i;
-}
-
-static int
-get_irn_n_nonignore_args(const spill_ilp_t * si, const ir_node * irn)
-{
-       int n;
-       int ret = 0;
-
-       if(is_Proj(irn))
-               irn = get_Proj_pred(irn);
-
-       for(n=get_irn_arity(irn)-1; n>=0; --n) {
-               const ir_node  *arg = get_irn_n(irn, n);
-
-               if(has_reg_class(si, arg)) ++ret;
-       }
-
-       return ret;
-}
-
-static inline void
-get_remats_from_op(spill_ilp_t * si, const ir_node * op)
-{
-       int      n;
-       remat_t *remat;
-
-       if( has_reg_class(si, op)
-       && (opt_repair_schedule || get_irn_n_nonremat_edges(si, op) > 1)
-       && (opt_remats !=  REMATS_BRIGGS || get_irn_n_nonignore_args(si, op) == 0)
-       ) {
-               remat = get_remat_from_op(si, op, op);
-               if(remat) {
-                       add_remat(si, remat);
-               }
-       }
-
-       if(opt_remats == REMATS_ALL) {
-               /* repeat the whole stuff for each remat retrieved by get_remat_from_op(op, arg)
-                  for each arg */
-               for (n = get_irn_arity(op)-1; n>=0; --n) {
-                       ir_node        *arg = get_irn_n(op, n);
-
-                       if(has_reg_class(si, arg)) {
-                               /* try to get an inverse remat */
-                               remat = get_remat_from_op(si, arg, op);
-                               if(remat) {
-                                       add_remat(si, remat);
-                               }
-                       }
-               }
-       }
-}
-
-static inline int
-value_is_defined_before(const spill_ilp_t * si, const ir_node * pos, const ir_node * val)
-{
-       ir_node *block;
-       ir_node *def_block = get_nodes_block(val);
-       int      ret;
-       (void) si;
-
-       if(val == pos)
-               return 0;
-
-       /* if pos is at end of a basic block */
-       if(is_Block(pos)) {
-               ret = (pos == def_block || block_dominates(def_block, pos));
-//             ir_fprintf(stderr, "(def(bb)=%d) ", ret);
-               return ret;
-       }
-
-       /* else if this is a normal operation */
-       block = get_nodes_block(pos);
-       if(block == def_block) {
-               if(!sched_is_scheduled(val)) return 1;
-
-               ret = sched_comes_after(val, pos);
-//             ir_fprintf(stderr, "(def(same block)=%d) ",ret);
-               return ret;
-       }
-
-       ret = block_dominates(def_block, block);
-//     ir_fprintf(stderr, "(def(other block)=%d) ", ret);
-       return ret;
-}
-
-static inline ir_node *sched_block_last_noncf(const ir_node * bb)
-{
-       return sched_skip((ir_node*)bb, 0, sched_skip_cf_predicator, NULL);
-}
-
-/**
- * Returns first non-Phi node of block @p bb
- */
-static inline ir_node *
-sched_block_first_nonphi(const ir_node * bb)
-{
-       return sched_skip((ir_node*)bb, 1, sched_skip_phi_predicator, NULL);
-}
-
-static int
-sched_skip_proj_predicator(const ir_node * irn, void * data)
-{
-       (void) data;
-       return (is_Proj(irn));
-}
-
-static inline ir_node *
-sched_next_nonproj(const ir_node * irn, int forward)
-{
-       return sched_skip((ir_node*)irn, forward, sched_skip_proj_predicator, NULL);
-}
-
-/**
- * Returns next operation node (non-Proj) after @p irn
- * or the basic block of this node
- */
-static inline ir_node *
-sched_next_op(const ir_node * irn)
-{
-       ir_node *next = sched_next(irn);
-
-       if(is_Block(next))
-               return next;
-
-       return sched_next_nonproj(next, 1);
-}
-
-/**
- * Returns previous operation node (non-Proj) before @p irn
- * or the basic block of this node
- */
-static inline ir_node *
-sched_prev_op(const ir_node * irn)
-{
-       ir_node *prev = sched_prev(irn);
-
-       if(is_Block(prev))
-               return prev;
-
-       return sched_next_nonproj(prev, 0);
-}
-
-static void
-sched_put_after(ir_node * insert, ir_node * irn)
-{
-       if(is_Block(insert)) {
-               insert = sched_block_first_nonphi(insert);
-       } else {
-               insert = sched_next_op(insert);
-       }
-       sched_reset(irn);
-       sched_add_before(insert, irn);
-}
-
-static void sched_put_before(ir_node * insert, ir_node * irn)
-{
-  if(is_Block(insert)) {
-         insert = sched_block_last_noncf(insert);
-  } else {
-         insert = sched_next_nonproj(insert, 0);
-         insert = sched_prev(insert);
-  }
-  sched_reset(irn);
-  sched_add_after(insert, irn);
-}
-
-static ir_node *
-next_post_remat(const ir_node * irn)
-{
-       op_t      *op;
-    ir_node   *next;
-
-       if(is_Block(irn)) {
-               next = sched_block_first_nonphi(irn);
-       } else {
-               next = sched_next_op(irn);
-       }
-
-       if(sched_is_end(next))
-               return NULL;
-
-       op = get_irn_link(next);
-       if(op->is_remat && !op->attr.remat.pre) {
-               return next;
-       }
-
-       return NULL;
-}
-
-
-static ir_node *next_pre_remat(const ir_node * irn)
-{
-       op_t      *op;
-       ir_node   *ret;
-
-       if(is_Block(irn)) {
-               ret = sched_block_last_noncf(irn);
-               ret = sched_next(ret);
-               ret = sched_prev_op(ret);
-       } else {
-               ret = sched_prev_op(irn);
-       }
-
-       if(sched_is_end(ret) || is_Phi(ret))
-               return NULL;
-
-       op = (op_t*)get_irn_link(ret);
-       if(op->is_remat && op->attr.remat.pre) {
-               return ret;
-       }
-
-       return NULL;
-}
-
-/**
- * Tells you whether a @p remat can be placed before the irn @p pos
- */
-static inline int
-can_remat_before(const spill_ilp_t * si, const remat_t * remat, const ir_node * pos, const pset * live)
-{
-       const ir_node   *op = remat->op;
-       const ir_node   *prev;
-       int        n,
-                          res = 1;
-
-       if(is_Block(pos)) {
-               prev = sched_block_last_noncf(pos);
-               prev = sched_next_nonproj(prev, 0);
-       } else {
-               prev = sched_prev_op(pos);
-       }
-       /* do not remat if the rematted value is defined immediately before this op */
-       if(prev == remat->op) {
-               return 0;
-       }
-
-#if 0
-       /* this should be just fine, the following OP will be using this value, right? */
-
-       /* only remat AFTER the real definition of a value (?) */
-       if(!value_is_defined_before(si, pos, remat->value)) {
-//             ir_fprintf(stderr, "error(not defined)");
-               return 0;
-       }
-#endif
-
-       for(n=get_irn_arity(op)-1; n>=0 && res; --n) {
-               const ir_node   *arg = get_irn_n(op, n);
-
-               if(opt_no_enlarge_liveness) {
-                       if(has_reg_class(si, arg) && live) {
-                               res &= pset_find_ptr((pset*)live, arg)?1:0;
-                       } else {
-                               res &= value_is_defined_before(si, pos, arg);
-                       }
-               } else {
-                       res &= value_is_defined_before(si, pos, arg);
-               }
-       }
-
-       return res;
-}
-
-/**
- * Tells you whether a @p remat can be placed after the irn @p pos
- */
-static inline int
-can_remat_after(const spill_ilp_t * si, const remat_t * remat, const ir_node * pos, const pset * live)
-{
-       if(is_Block(pos)) {
-               pos = sched_block_first_nonphi(pos);
-       } else {
-               pos = sched_next_op(pos);
-       }
-
-       /* only remat AFTER the real definition of a value (?) */
-       if(!value_is_defined_before(si, pos, remat->value)) {
-               return 0;
-       }
-
-       return can_remat_before(si, remat, pos, live);
-}
-
-/**
- * Collect potetially rematerializable OPs
- */
-static void
-walker_remat_collector(ir_node * irn, void * data)
-{
-       spill_ilp_t    *si = data;
-
-       if(!is_Block(irn) && !is_Phi(irn)) {
-               DBG((si->dbg, LEVEL_4, "\t  Processing %+F\n", irn));
-               get_remats_from_op(si, irn);
-       }
-}
-
-/**
- * Inserts a copy of @p irn before @p pos
- */
-static ir_node *
-insert_copy_before(const spill_ilp_t * si, const ir_node * irn, ir_node * pos)
-{
-       ir_node     *bb;
-       ir_node     *copy;
-
-       bb = is_Block(pos)?pos:get_nodes_block(pos);
-       copy = exact_copy(irn);
-
-       set_phi_class(si->pc, copy, NULL);
-       set_nodes_block(copy, bb);
-       sched_put_before(pos, copy);
-
-       return copy;
-}
-
-/**
- * Inserts a copy of @p irn after @p pos
- */
-static ir_node *
-insert_copy_after(const spill_ilp_t * si, const ir_node * irn, ir_node * pos)
-{
-       ir_node     *bb;
-       ir_node     *copy;
-
-       bb = is_Block(pos)?pos:get_nodes_block(pos);
-       copy = exact_copy(irn);
-
-       set_phi_class(si->pc, copy, NULL);
-       set_nodes_block(copy, bb);
-       sched_put_after(pos, copy);
-
-       return copy;
-}
-
-static ir_node *
-insert_remat_after(spill_ilp_t * si, const remat_t * remat, ir_node * pos, const pset * live)
-{
-       char     buf[256];
-
-       if(can_remat_after(si, remat, pos, live)) {
-               ir_node         *copy,
-                                               *proj_copy;
-               op_t            *op;
-
-               DBG((si->dbg, LEVEL_3, "\t  >inserting remat2 %+F\n", remat->op));
-
-               copy = insert_copy_after(si, remat->op, pos);
-
-               ir_snprintf(buf, sizeof(buf), "remat2_%N_%N", copy, pos);
-               op = obstack_alloc(si->obst, sizeof(*op));
-               op->is_remat = 1;
-               op->attr.remat.remat = remat;
-               op->attr.remat.pre = 0;
-               op->attr.remat.ilp = lpp_add_var_default(si->lpp, buf, lpp_binary, remat->cost*execution_frequency(si, pos), 0.0);
-
-               set_irn_link(copy, op);
-               pset_insert_ptr(si->all_possible_remats, copy);
-               if(remat->proj) {
-                       proj_copy = insert_copy_after(si, remat->proj, copy);
-                       set_irn_n(proj_copy, 0, copy);
-                       set_irn_link(proj_copy, op);
-                       pset_insert_ptr(si->all_possible_remats, proj_copy);
-               } else {
-                       proj_copy = NULL;
-               }
-
-               return copy;
-       }
-
-       return NULL;
-}
-
-static ir_node *
-insert_remat_before(spill_ilp_t * si, const remat_t * remat, ir_node * pos, const pset * live)
-{
-       char     buf[256];
-
-       if(can_remat_before(si, remat, pos, live)) {
-               ir_node         *copy,
-                                               *proj_copy;
-               op_t            *op;
-
-               DBG((si->dbg, LEVEL_3, "\t  >inserting remat %+F\n", remat->op));
-
-               copy = insert_copy_before(si, remat->op, pos);
-
-               ir_snprintf(buf, sizeof(buf), "remat_%N_%N", copy, pos);
-               op = obstack_alloc(si->obst, sizeof(*op));
-               op->is_remat = 1;
-               op->attr.remat.remat = remat;
-               op->attr.remat.pre = 1;
-               op->attr.remat.ilp = lpp_add_var_default(si->lpp, buf, lpp_binary, remat->cost*execution_frequency(si, pos), 0.0);
-
-               set_irn_link(copy, op);
-               pset_insert_ptr(si->all_possible_remats, copy);
-               if(remat->proj) {
-                       proj_copy = insert_copy_after(si, remat->proj, copy);
-                       set_irn_n(proj_copy, 0, copy);
-                       set_irn_link(proj_copy, op);
-                       pset_insert_ptr(si->all_possible_remats, proj_copy);
-               } else {
-                       proj_copy = NULL;
-               }
-
-               return copy;
-       }
-
-       return NULL;
-}
-
-static int
-get_block_n_succs(const ir_node *block) {
-       const ir_edge_t *edge;
-
-       assert(edges_activated(current_ir_graph));
-
-       edge = get_block_succ_first(block);
-       if (! edge)
-               return 0;
-
-       edge = get_block_succ_next(block, edge);
-       return edge ? 2 : 1;
-}
-
-static int
-is_start_block(const ir_node * bb)
-{
-       return get_irg_start_block(get_irn_irg(bb)) == bb;
-}
-
-static int
-is_merge_edge(const ir_node * bb)
-{
-       if(is_start_block(bb))
-               return 0;
-
-       if(opt_goodwin)
-               return get_block_n_succs(bb) == 1;
-       else
-               return 1;
-}
-
-static int
-is_diverge_edge(const ir_node * bb)
-{
-       if(is_start_block(bb))
-               return 0;
-
-       if(opt_goodwin)
-               return get_Block_n_cfgpreds(bb) == 1;
-       else
-               return 1;
-}
-
-static void
-get_live_end(spill_ilp_t * si, ir_node * bb, pset * live)
-{
-       ir_node        *irn;
-       int i;
-
-       be_lv_foreach(si->lv, bb, be_lv_state_end, i) {
-               irn = be_lv_get_irn(si->lv, bb, i);
-
-               if (has_reg_class(si, irn) && !pset_find_ptr(si->all_possible_remats, irn)) {
-                       pset_insert_ptr(live, irn);
-               }
-       }
-
-       irn = sched_last(bb);
-
-       /* all values eaten by control flow operations are also live until the end of the block */
-       sched_foreach_reverse(bb, irn) {
-               int  i;
-
-               if (!sched_skip_cf_predicator(irn, NULL)) break;
-
-               for(i=get_irn_arity(irn)-1; i>=0; --i) {
-                       ir_node *arg = get_irn_n(irn,i);
-
-                       if(has_reg_class(si, arg)) {
-                               pset_insert_ptr(live, arg);
-                       }
-               }
-       }
-       /*
-        * find values that are used by remats at end of block
-        * and insert them into live set
-        */
-       foreach_pre_remat(bb, irn) {
-               int       n;
-
-               for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node        *remat_arg = get_irn_n(irn, n);
-
-                       if(!has_reg_class(si, remat_arg)) continue;
-
-                       /* if value is becoming live through use by remat */
-                       if(!pset_find_ptr(live, remat_arg)) {
-                               DBG((si->dbg, LEVEL_4, "  value %+F becoming live through use by remat at end of block %+F\n", remat_arg, irn));
-
-                               pset_insert_ptr(live, remat_arg);
-                       }
-               }
-       }
-}
-
-static void
-walker_regclass_copy_insertor(ir_node * irn, void * data)
-{
-       spill_ilp_t    *si = data;
-
-       if(is_Phi(irn) && has_reg_class(si, irn)) {
-               int n;
-
-               for(n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node  *phi_arg = get_irn_n(irn, n);
-                       ir_node  *bb = get_Block_cfgpred_block(get_nodes_block(irn), n);
-
-                       if(!has_reg_class(si, phi_arg)) {
-                               ir_node   *copy = be_new_Copy(si->cls, si->birg->irg, bb, phi_arg);
-                               ir_node   *pos = sched_block_last_noncf(bb);
-                               op_t      *op = obstack_alloc(si->obst, sizeof(*op));
-
-                               DBG((si->dbg, LEVEL_2, "\t copy to my regclass for arg %+F of %+F\n", phi_arg, irn));
-                               sched_add_after(pos, copy);
-                               set_irn_n(irn, n, copy);
-
-                               op->is_remat = 0;
-                               op->attr.live_range.args.reloads = NULL;
-                               op->attr.live_range.ilp = ILP_UNDEF;
-                               set_irn_link(copy, op);
-                       }
-               }
-       }
-}
-
-/**
- * Insert (so far unused) remats into the irg to
- * recompute the potential liveness of all values
- */
-static void
-walker_remat_insertor(ir_node * bb, void * data)
-{
-       spill_ilp_t    *si = data;
-       ir_node        *irn;
-       int             n, i;
-       pset           *live;
-       pset           *post_remats;
-       remat_t        *remat;
-
-       /* skip start block, no remats to do there */
-       if(is_start_block(bb)) return;
-
-       DBG((si->dbg, LEVEL_3, "\t Entering %+F\n\n", bb));
-
-       live = pset_new_ptr_default();
-       be_lv_foreach(si->lv, bb, be_lv_state_end, i) {
-               ir_node        *value = be_lv_get_irn(si->lv, bb, i);
-
-               /* add remats at end of block */
-               if (has_reg_class(si, value)) {
-                       pset_insert_ptr(live, value);
-               }
-       }
-
-       irn = sched_last(bb);
-       while(!sched_is_end(irn)) {
-               ir_node   *next;
-               pset      *args;
-               ir_node   *arg;
-               pset      *used;
-
-               next = sched_prev(irn);
-
-               /* delete defined value from live set */
-               if(has_reg_class(si, irn)) {
-                       pset_remove_ptr(live, irn);
-               }
-
-               if(is_Phi(irn) || is_Proj(irn)) {
-                       irn = next;
-                       continue;
-               }
-
-               args = pset_new_ptr_default();
-               used = pset_new_ptr_default();
-
-               /* collect arguments of op and set args of op already live in epilog */
-               for (n = get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node        *arg = get_irn_n(irn, n);
-
-                       pset_insert_ptr(args, arg);
-                       if(has_reg_class(si, arg)) {
-                               pset_insert_ptr(live, arg);
-                               pset_insert_ptr(used, arg);
-                       }
-               }
-
-               /* insert all possible remats before irn */
-               pset_foreach(args, arg) {
-                       remat_info_t   *remat_info,
-                                                   query;
-
-                       /* continue if the operand has the wrong reg class */
-                       if(!has_reg_class(si, arg))
-                               continue;
-
-                       query.irn = arg;
-                       query.remats = NULL;
-                       query.remats_by_operand = NULL;
-                       remat_info = set_find(si->remat_info, &query, sizeof(query), HASH_PTR(arg));
-
-                       if(!remat_info) {
-                               continue;
-                       }
-
-                       if(remat_info->remats) {
-                               pset_foreach(remat_info->remats, remat) {
-                                       ir_node  *remat_irn = NULL;
-
-                                       DBG((si->dbg, LEVEL_4, "\t  considering remat %+F for arg %+F\n", remat->op, arg));
-                                       remat_irn = insert_remat_before(si, remat, irn, live);
-
-                                       if(remat_irn) {
-                                               for(n=get_irn_arity(remat_irn)-1; n>=0; --n) {
-                                                       ir_node  *remat_arg = get_irn_n(remat_irn, n);
-
-                                                       /* collect args of remats which are not args of op */
-                                                       if(has_reg_class(si, remat_arg) && !pset_find_ptr(args, remat_arg)) {
-                                                               pset_insert_ptr(used, remat_arg);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               /* do not place post remats after jumps */
-               if (sched_skip_cf_predicator(irn, si->birg->main_env->arch_env)) {
-                       del_pset(used);
-                       del_pset(args);
-                       break;
-               }
-
-               /* insert all possible remats after irn */
-               post_remats = pset_new_ptr_default();
-               pset_foreach(used, arg) {
-                       remat_info_t   *remat_info,
-                                                   query;
-
-                       /* continue if the operand has the wrong reg class */
-                       if(!has_reg_class(si, arg))
-                               continue;
-
-                       query.irn = arg;
-                       query.remats = NULL;
-                       query.remats_by_operand = NULL;
-                       remat_info = set_find(si->remat_info, &query, sizeof(query), HASH_PTR(arg));
-
-                       if(!remat_info) {
-                               continue;
-                       }
-
-                       if(remat_info->remats_by_operand) {
-                               pset_foreach(remat_info->remats_by_operand, remat) {
-                                       /* do not insert remats producing the same value as one of the operands */
-                                       if(!pset_find_ptr(args, remat->value)) {
-                                               DBG((si->dbg, LEVEL_4, "\t  considering remat %+F with arg %+F\n", remat->op, arg));
-
-                                               /* only remat values that can be used by real ops */
-                                               if(!opt_remat_while_live || pset_find_ptr(live, remat->value)) {
-                                                       pset_insert_ptr(post_remats, remat);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               pset_foreach(post_remats, remat) {
-                       insert_remat_after(si, remat, irn, live);
-               }
-               del_pset(post_remats);
-
-               del_pset(used);
-               del_pset(args);
-               irn = next;
-       }
-
-       /* add remats at end if successor has multiple predecessors */
-       if(is_merge_edge(bb)) {
-               pset     *live_out = pset_new_ptr_default();
-               ir_node  *value;
-
-               get_live_end(si, bb, live_out);
-
-               /* add remats at end of block */
-               pset_foreach(live_out, value) {
-                       remat_info_t   *remat_info,
-                                                  query;
-
-                       query.irn = value;
-                       query.remats = NULL;
-                       query.remats_by_operand = NULL;
-                       remat_info = set_find(si->remat_info, &query, sizeof(query), HASH_PTR(value));
-
-                       if(remat_info && remat_info->remats) {
-                               pset_foreach(remat_info->remats, remat) {
-                                       DBG((si->dbg, LEVEL_4, "\t  considering remat %+F at end of block %+F\n", remat->op, bb));
-
-                                       insert_remat_before(si, remat, bb, live_out);
-                               }
-                       }
-               }
-               del_pset(live_out);
-       }
-
-       if(is_diverge_edge(bb)) {
-               pset     *live_in = pset_new_ptr_default();
-               ir_node  *value;
-
-               be_lv_foreach(si->lv, bb, be_lv_state_in, i) {
-                       value = be_lv_get_irn(si->lv, bb, i);
-
-                       if(has_reg_class(si, value)) {
-                               pset_insert_ptr(live_in, value);
-                       }
-               }
-               /* add phis to live_in */
-               sched_foreach(bb, value) {
-                       if(!is_Phi(value)) break;
-
-                       if(has_reg_class(si, value)) {
-                               pset_insert_ptr(live_in, value);
-                       }
-               }
-
-               /* add remat2s at beginning of block */
-               post_remats = pset_new_ptr_default();
-               pset_foreach(live_in, value) {
-                       remat_info_t   *remat_info,
-                                                  query;
-
-                       query.irn = value;
-                       query.remats = NULL;
-                       query.remats_by_operand = NULL;
-                       remat_info = set_find(si->remat_info, &query, sizeof(query), HASH_PTR(value));
-
-                       if(remat_info && remat_info->remats_by_operand) {
-                               pset_foreach(remat_info->remats_by_operand, remat) {
-                                       DBG((si->dbg, LEVEL_4, "\t  considering remat2 %+F at beginning of block %+F\n", remat->op, bb));
-
-                                       /* put the remat here if all its args are available and result is still live */
-                                       if(!opt_remat_while_live || pset_find_ptr(live_in, remat->value)) {
-                                               pset_insert_ptr(post_remats, remat);
-                                       }
-                               }
-                       }
-               }
-               pset_foreach(post_remats, remat) {
-                       insert_remat_after(si, remat, bb, live_in);
-               }
-               del_pset(post_remats);
-               del_pset(live_in);
-       }
-}
-
-static int
-can_be_copied(const ir_node * bb, const ir_node * irn)
-{
-       const ir_edge_t *edge    = get_block_succ_first(bb);
-       const ir_node   *next_bb = edge->src;
-       int             pos      = edge->pos;
-       const ir_node   *phi;
-
-       assert(is_merge_edge(bb));
-
-       sched_foreach(next_bb, phi) {
-               const ir_node  *phi_arg;
-
-               if(!is_Phi(phi)) break;
-
-               phi_arg = get_irn_n(phi, pos);
-
-               if(phi_arg == irn) {
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/**
- * Initialize additional node info
- */
-static void
-luke_initializer(ir_node * bb, void * data)
-{
-       spill_ilp_t    *si = (spill_ilp_t*)data;
-       spill_bb_t     *spill_bb;
-       ir_node        *irn;
-
-       spill_bb = obstack_alloc(si->obst, sizeof(*spill_bb));
-       set_irn_link(bb, spill_bb);
-
-       sched_foreach(bb, irn) {
-               op_t      *op;
-
-               op = obstack_alloc(si->obst, sizeof(*op));
-               op->is_remat = 0;
-               op->attr.live_range.ilp = ILP_UNDEF;
-               if(is_Phi(irn)) {
-                       if(opt_memcopies) {
-                               op->attr.live_range.args.copies = obstack_alloc(si->obst, sizeof(*op->attr.live_range.args.copies) * get_irn_arity(irn));
-                               memset(op->attr.live_range.args.copies, 0xFF, sizeof(*op->attr.live_range.args.copies) * get_irn_arity(irn));
-                       }
-               } else if(!is_Proj(irn)) {
-                       op->attr.live_range.args.reloads = obstack_alloc(si->obst, sizeof(*op->attr.live_range.args.reloads) * get_irn_arity(irn));
-                       memset(op->attr.live_range.args.reloads, 0xFF, sizeof(*op->attr.live_range.args.reloads) * get_irn_arity(irn));
-               } else {
-                       op->attr.live_range.args.reloads = NULL;
-               }
-               set_irn_link(irn, op);
-       }
-}
-
-
-/**
- * Preparation of blocks' ends for Luke Blockwalker(tm)(R)
- */
-static void
-luke_endwalker(ir_node * bb, void * data)
-{
-       spill_ilp_t    *si = (spill_ilp_t*)data;
-       pset           *live;
-       pset           *use_end;
-       char            buf[256];
-       ilp_cst_t       cst;
-       ir_node        *irn;
-       spill_bb_t     *spill_bb = get_irn_link(bb);
-       int             i;
-
-       live = pset_new_ptr_default();
-       use_end = pset_new_ptr_default();
-
-       be_lv_foreach(si->lv, bb, be_lv_state_end, i) {
-               irn = be_lv_get_irn(si->lv, bb, i);
-               if (has_reg_class(si, irn) && !pset_find_ptr(si->all_possible_remats, irn)) {
-                       pset_insert_ptr(live, irn);
-               }
-       }
-       /*
-        * find values that are used by remats at end of block
-        * and insert them into live set
-        */
-       foreach_pre_remat(bb, irn) {
-               int       n;
-
-               for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node        *remat_arg = get_irn_n(irn, n);
-
-                       if(has_reg_class(si, remat_arg)) {
-                               pset_insert_ptr(live, remat_arg);
-                       }
-               }
-       }
-
-       /* collect values used by cond jumps etc. at bb end (use_end) -> always live */
-       /* their reg_out must always be set */
-       sched_foreach_reverse(bb, irn) {
-               int   n;
-
-               if (!sched_skip_cf_predicator(irn, si->birg->main_env->arch_env)) break;
-
-               for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node        *irn_arg = get_irn_n(irn, n);
-
-                       if(has_reg_class(si, irn_arg)) {
-                               pset_insert_ptr(use_end, irn_arg);
-                       }
-               }
-       }
-
-       ir_snprintf(buf, sizeof(buf), "check_end_%N", bb);
-       //cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs);
-       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs - pset_count(use_end));
-
-       spill_bb->ilp = new_set(cmp_spill, pset_count(live)+pset_count(use_end));
-
-       /* if this is a merge edge we can reload at the end of this block */
-       if(is_merge_edge(bb)) {
-               spill_bb->reloads = new_set(cmp_keyval, pset_count(live)+pset_count(use_end));
-       } else if(pset_count(use_end)){
-               spill_bb->reloads = new_set(cmp_keyval, pset_count(use_end));
-       } else {
-               spill_bb->reloads = NULL;
-       }
-
-       pset_foreach(live,irn) {
-               spill_t     query,
-                                       *spill;
-               double      spill_cost;
-               int         default_spilled;
-
-
-               /* handle values used by control flow nodes later separately */
-               if(pset_find_ptr(use_end, irn)) continue;
-
-               query.irn = irn;
-               spill = set_insert(spill_bb->ilp, &query, sizeof(query), HASH_PTR(irn));
-
-               spill_cost = is_Unknown(irn)?0.0001:opt_cost_spill*execution_frequency(si, bb);
-
-               ir_snprintf(buf, sizeof(buf), "reg_out_%N_%N", irn, bb);
-               spill->reg_out = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-               lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
-
-               ir_snprintf(buf, sizeof(buf), "mem_out_%N_%N", irn, bb);
-               spill->mem_out = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-               ir_snprintf(buf, sizeof(buf), "spill_%N_%N", irn, bb);
-               /* by default spill value right after definition */
-               default_spilled = be_is_live_in(si->lv, bb, irn) || is_Phi(irn);
-               spill->spill    = lpp_add_var_default(si->lpp, buf, lpp_binary, spill_cost, !default_spilled);
-
-               if(is_merge_edge(bb)) {
-                       ilp_var_t   reload;
-                       ilp_cst_t   rel_cst;
-
-                       ir_snprintf(buf, sizeof(buf), "reload_%N_%N", bb, irn);
-                       reload = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_reload*execution_frequency(si, bb), can_be_copied(bb, irn));
-                       set_insert_keyval(spill_bb->reloads, irn, INT_TO_PTR(reload));
-
-                       /* reload <= mem_out */
-                       rel_cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                       lpp_set_factor_fast(si->lpp, rel_cst, reload, 1.0);
-                       lpp_set_factor_fast(si->lpp, rel_cst, spill->mem_out, -1.0);
-               }
-
-               spill->reg_in = ILP_UNDEF;
-               spill->mem_in = ILP_UNDEF;
-       }
-
-       pset_foreach(use_end,irn) {
-               spill_t     query,
-                                       *spill;
-               double      spill_cost;
-               ilp_cst_t   end_use_req,
-                                       rel_cst;
-               ilp_var_t   reload;
-               int         default_spilled;
-
-               query.irn = irn;
-               spill = set_insert(spill_bb->ilp, &query, sizeof(query), HASH_PTR(irn));
-
-               spill_cost = is_Unknown(irn)?0.0001:opt_cost_spill*execution_frequency(si, bb);
-
-               ir_snprintf(buf, sizeof(buf), "reg_out_%N_%N", irn, bb);
-               spill->reg_out = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-               ir_snprintf(buf, sizeof(buf), "mem_out_%N_%N", irn, bb);
-               spill->mem_out = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-               ir_snprintf(buf, sizeof(buf), "spill_%N_%N", irn, bb);
-               default_spilled = be_is_live_in(si->lv, bb, irn) || is_Phi(irn);
-               spill->spill    = lpp_add_var_default(si->lpp, buf, lpp_binary, spill_cost, !default_spilled);
-
-               /* reload for use be control flow op */
-               ir_snprintf(buf, sizeof(buf), "reload_%N_%N", bb, irn);
-               reload = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_reload*execution_frequency(si, bb), 1.0);
-               set_insert_keyval(spill_bb->reloads, irn, INT_TO_PTR(reload));
-
-               /* reload <= mem_out */
-               rel_cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-               lpp_set_factor_fast(si->lpp, rel_cst, reload, 1.0);
-               lpp_set_factor_fast(si->lpp, rel_cst, spill->mem_out, -1.0);
-
-               spill->reg_in = ILP_UNDEF;
-               spill->mem_in = ILP_UNDEF;
-
-               ir_snprintf(buf, sizeof(buf), "req_cf_end_%N_%N", irn, bb);
-               end_use_req = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 1);
-               lpp_set_factor_fast(si->lpp, end_use_req, spill->reg_out, 1.0);
-       }
-
-       del_pset(live);
-       del_pset(use_end);
-}
-
-#ifndef NDEBUG
-/**
- * Find a remat of value @p value in the epilog of @p pos
- */
-static ir_node *
-find_post_remat(const ir_node * value, const ir_node * pos)
-{
-       while((pos = next_post_remat(pos)) != NULL) {
-               op_t   *op;
-
-               op = get_irn_link(pos);
-               assert(op->is_remat && !op->attr.remat.pre);
-
-               if(op->attr.remat.remat->value == value)
-                       return (ir_node*)pos;
-
-#if 0
-       const ir_edge_t *edge;
-               foreach_out_edge(pos, edge) {
-                       ir_node   *proj = get_edge_src_irn(edge);
-                       assert(is_Proj(proj));
-               }
-#endif
-
-       }
-
-       return NULL;
-}
-#endif
-
-static spill_t *
-add_to_spill_bb(spill_ilp_t * si, ir_node * bb, ir_node * irn)
-{
-       spill_bb_t  *spill_bb = get_irn_link(bb);
-       spill_t     *spill,
-                                query;
-       char         buf[256];
-       int          default_spilled;
-
-       query.irn = irn;
-       spill = set_find(spill_bb->ilp, &query, sizeof(query), HASH_PTR(irn));
-       if(!spill) {
-               double   spill_cost = is_Unknown(irn)?0.0001:opt_cost_spill*execution_frequency(si, bb);
-
-               spill = set_insert(spill_bb->ilp, &query, sizeof(query), HASH_PTR(irn));
-
-               spill->reg_out = ILP_UNDEF;
-               spill->reg_in  = ILP_UNDEF;
-               spill->mem_in  = ILP_UNDEF;
-
-               ir_snprintf(buf, sizeof(buf), "mem_out_%N_%N", irn, bb);
-               spill->mem_out = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-               ir_snprintf(buf, sizeof(buf), "spill_%N_%N", irn, bb);
-               default_spilled = be_is_live_in(si->lv, bb, irn) || is_Phi(irn);
-               spill->spill    = lpp_add_var_default(si->lpp, buf, lpp_binary, spill_cost, !default_spilled);
-       }
-
-       return spill;
-}
-
-/**
- *  Inserts ILP-constraints and variables for memory copying before the given position
- */
-static void
-insert_mem_copy_position(spill_ilp_t * si, pset * live, const ir_node * block)
-{
-       const ir_node    *succ;
-       const ir_edge_t  *edge;
-       spill_bb_t       *spill_bb = get_irn_link(block);
-       ir_node          *phi;
-       int               pos;
-       ilp_cst_t         cst;
-       ilp_var_t         copyreg;
-       char              buf[256];
-       ir_node          *tmp;
-
-
-       assert(edges_activated(current_ir_graph));
-
-       edge = get_block_succ_first(block);
-       if(!edge) return;
-
-       succ = edge->src;
-       pos = edge->pos;
-
-       edge = get_block_succ_next(block, edge);
-       /* next block can only contain phis, if this is a merge edge */
-       if(edge) return;
-
-       ir_snprintf(buf, sizeof(buf), "copyreg_%N", block);
-       copyreg = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-       ir_snprintf(buf, sizeof(buf), "check_copyreg_%N", block);
-       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs);
-
-       pset_foreach(live, tmp) {
-               spill_t  *spill;
-#if 0
-               op_t  *op = get_irn_link(irn);
-               lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, 1.0);
-#endif
-               spill = set_find_spill(spill_bb->ilp, tmp);
-               assert(spill);
-
-               lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
-       }
-       lpp_set_factor_fast(si->lpp, cst, copyreg, 1.0);
-
-       sched_foreach(succ, phi) {
-               const ir_node  *to_copy;
-               op_t           *to_copy_op;
-               spill_t        *to_copy_spill;
-               op_t           *phi_op = get_irn_link(phi);
-               ilp_var_t       reload = ILP_UNDEF;
-
-
-               if(!is_Phi(phi)) break;
-               if(!has_reg_class(si, phi)) continue;
-
-               to_copy = get_irn_n(phi, pos);
-               to_copy_op = get_irn_link(to_copy);
-
-               to_copy_spill = set_find_spill(spill_bb->ilp, to_copy);
-               assert(to_copy_spill);
-
-               if(spill_bb->reloads) {
-                       keyval_t *keyval = set_find_keyval(spill_bb->reloads, to_copy);
-
-                       if(keyval) {
-                               reload = PTR_TO_INT(keyval->val);
-                       }
-               }
-
-               ir_snprintf(buf, sizeof(buf), "req_copy_%N_%N_%N", block, phi, to_copy);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-               /* copy - reg_out - reload - remat - live_range <= 0 */
-               lpp_set_factor_fast(si->lpp, cst, phi_op->attr.live_range.args.copies[pos], 1.0);
-               lpp_set_factor_fast(si->lpp, cst, to_copy_spill->reg_out, -1.0);
-               if(reload != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
-               lpp_set_factor_fast(si->lpp, cst, to_copy_op->attr.live_range.ilp, -1.0);
-               foreach_pre_remat(block, tmp) {
-                       op_t     *remat_op = get_irn_link(tmp);
-                       if(remat_op->attr.remat.remat->value == to_copy) {
-                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
-                       }
-               }
-
-               ir_snprintf(buf, sizeof(buf), "copyreg_%N_%N_%N", block, phi, to_copy);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-               /* copy - reg_out - copyreg <= 0 */
-               lpp_set_factor_fast(si->lpp, cst, phi_op->attr.live_range.args.copies[pos], 1.0);
-               lpp_set_factor_fast(si->lpp, cst, to_copy_spill->reg_out, -1.0);
-               lpp_set_factor_fast(si->lpp, cst, copyreg, -1.0);
-       }
-}
-
-
-/**
- * Walk all irg blocks and emit this ILP
- */
-static void
-luke_blockwalker(ir_node * bb, void * data)
-{
-       spill_ilp_t *si = (spill_ilp_t*)data;
-       ir_node     *irn;
-       pset        *live;
-       char         buf[256];
-       ilp_cst_t    cst;
-       spill_bb_t  *spill_bb = get_irn_link(bb);
-       ir_node     *tmp;
-       spill_t     *spill;
-       pset        *defs = pset_new_ptr_default();
-
-       live = pset_new_ptr_default();
-
-       /****************************************
-        *      B A S I C  B L O C K  E N D
-        ***************************************/
-
-
-       /* init live values at end of block */
-       get_live_end(si, bb, live);
-
-       pset_foreach(live, irn) {
-               op_t           *op;
-               ilp_var_t       reload = ILP_UNDEF;
-
-               spill = set_find_spill(spill_bb->ilp, irn);
-               assert(spill);
-
-               if(spill_bb->reloads) {
-                       keyval_t *keyval = set_find_keyval(spill_bb->reloads, irn);
-
-                       if(keyval) {
-                               reload = PTR_TO_INT(keyval->val);
-                       }
-               }
-
-               op = get_irn_link(irn);
-               assert(!op->is_remat);
-
-               ir_snprintf(buf, sizeof(buf), "lr_%N_%N", irn, bb);
-               op->attr.live_range.ilp = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-               op->attr.live_range.op = bb;
-
-               ir_snprintf(buf, sizeof(buf), "reg_out_%N_%N", bb, irn);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-               /* reg_out - reload - remat - live_range <= 0 */
-               lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
-               if(reload != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
-               lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, -1.0);
-               foreach_pre_remat(bb, tmp) {
-                       op_t     *remat_op = get_irn_link(tmp);
-                       if(remat_op->attr.remat.remat->value == irn) {
-                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
-                       }
-               }
-               ir_snprintf(buf, sizeof(buf), "reg_out2_%N_%N", bb, irn);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_greater, 0.0);
-
-               /* value may only die at bb end if it is used for a mem copy */
-               /* reg_out + \sum copy - reload - remat - live_range >= 0 */
-               lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
-               if(reload != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
-               lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, -1.0);
-               foreach_pre_remat(bb, tmp) {
-                       op_t     *remat_op = get_irn_link(tmp);
-                       if(remat_op->attr.remat.remat->value == irn) {
-                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
-                       }
-               }
-               if(is_merge_edge(bb)) {
-                       const ir_edge_t *edge = get_block_succ_first(bb);
-                       const ir_node   *next_bb = edge->src;
-                       int              pos = edge->pos;
-                       const ir_node   *phi;
-
-                       sched_foreach(next_bb, phi) {
-                               const ir_node  *phi_arg;
-
-                               if(!is_Phi(phi)) break;
-
-                               phi_arg = get_irn_n(phi, pos);
-
-                               if(phi_arg == irn) {
-                                       op_t      *phi_op = get_irn_link(phi);
-                                       ilp_var_t  copy = phi_op->attr.live_range.args.copies[pos];
-
-                                       lpp_set_factor_fast(si->lpp, cst, copy, 1.0);
-                               }
-                       }
-               }
-       }
-
-       if(opt_memcopies)
-               insert_mem_copy_position(si, live, bb);
-
-       /*
-        * assure the remat args are available
-        */
-       foreach_pre_remat(bb, tmp) {
-               op_t     *remat_op = get_irn_link(tmp);
-               int       n;
-
-               for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                       ir_node        *remat_arg = get_irn_n(tmp, n);
-                       op_t           *arg_op = get_irn_link(remat_arg);
-
-                       if(!has_reg_class(si, remat_arg)) continue;
-
-                       spill = set_find_spill(spill_bb->ilp, remat_arg);
-                       assert(spill);
-
-                       /* arguments of remats have to be live until the very end of the block
-                        * remat = reg_out(remat_arg) and (reload(remat_arg) or live_range(remat_arg)),
-                        * no remats, they could be in wrong order
-                        */
-
-                       ir_snprintf(buf, sizeof(buf), "req_remat_%N_arg_%N", tmp, remat_arg);
-                       cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
-
-                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 3.0);
-                       lpp_set_factor_fast(si->lpp, cst, spill->reg_out, -2.0);
-                       lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, -1.0);
-
-                       /* use reload placed for this argument */
-                       if(spill_bb->reloads) {
-                               keyval_t *keyval = set_find_keyval(spill_bb->reloads, remat_arg);
-
-                               if(keyval) {
-                                       ilp_var_t       reload = PTR_TO_INT(keyval->val);
-
-                                       lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
-                               }
-                       }
-               }
-       }
-       DBG((si->dbg, LEVEL_4, "\t   %d values live at end of block %+F\n", pset_count(live), bb));
-
-
-
-
-       /**************************************
-        *    B A S I C  B L O C K  B O D Y
-        **************************************/
-
-       sched_foreach_reverse_from(sched_block_last_noncf(bb), irn) {
-               op_t       *op;
-               op_t       *tmp_op;
-               int         n,
-                                       u = 0,
-                                       d = 0;
-               ilp_cst_t       check_pre,
-                                       check_post;
-               set        *args;
-               pset       *used;
-               pset       *remat_defs;
-               keyval_t   *keyval;
-               ilp_cst_t   one_memoperand = -1;
-
-               /* iterate only until first phi */
-               if(is_Phi(irn))
-                       break;
-
-               op = get_irn_link(irn);
-               /* skip remats */
-               if(op->is_remat) continue;
-
-               DBG((si->dbg, LEVEL_4, "\t  at node %+F\n", irn));
-
-               /* collect defined values */
-               if(has_reg_class(si, irn)) {
-                       pset_insert_ptr(defs, irn);
-               }
-
-               /* skip projs */
-               if(is_Proj(irn)) continue;
-
-               /*
-                * init set of irn's arguments
-                * and all possibly used values around this op
-                * and values defined by post remats
-                */
-               args =       new_set(cmp_keyval, get_irn_arity(irn));
-               used =       pset_new_ptr(pset_count(live) + get_irn_arity(irn));
-               remat_defs = pset_new_ptr(pset_count(live));
-
-               if(!is_start_block(bb) || !be_is_Barrier(irn)) {
-                       for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                               ir_node        *irn_arg = get_irn_n(irn, n);
-                               if(has_reg_class(si, irn_arg)) {
-                                       set_insert_keyval(args, irn_arg, (void*)n);
-                                       pset_insert_ptr(used, irn_arg);
-                               }
-                       }
-                       foreach_post_remat(irn, tmp) {
-                               op_t    *remat_op = get_irn_link(tmp);
-
-                               pset_insert_ptr(remat_defs, remat_op->attr.remat.remat->value);
-
-                               for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                                       ir_node        *remat_arg = get_irn_n(tmp, n);
-                                       if(has_reg_class(si, remat_arg)) {
-                                               pset_insert_ptr(used, remat_arg);
-                                       }
-                               }
-                       }
-                       foreach_pre_remat(irn, tmp) {
-                               for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                                       ir_node        *remat_arg = get_irn_n(tmp, n);
-                                       if(has_reg_class(si, remat_arg)) {
-                                               pset_insert_ptr(used, remat_arg);
-                                       }
-                               }
-                       }
-               }
-
-               /**********************************
-                *   I N  E P I L O G  O F  irn
-                **********************************/
-
-               /* ensure each dying value is used by only one post remat */
-               pset_foreach(used, tmp) {
-                       ir_node     *value = tmp;
-                       op_t        *value_op = get_irn_link(value);
-                       ir_node     *remat;
-                       int          n_remats = 0;
-
-                       cst = ILP_UNDEF;
-                       foreach_post_remat(irn, remat) {
-                               op_t  *remat_op = get_irn_link(remat);
-
-                               for(n=get_irn_arity(remat)-1; n>=0; --n) {
-                                       ir_node   *remat_arg = get_irn_n(remat, n);
-
-                                       /* if value is used by this remat add it to constraint */
-                                       if(remat_arg == value) {
-                                               if(n_remats == 0) {
-                                                       /* sum remat2s <= 1 + n_remats*live_range */
-                                                       ir_snprintf(buf, sizeof(buf), "dying_lr_%N_%N", value, irn);
-                                                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-                                               }
-
-                                               n_remats++;
-                                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-                                               break;
-                                       }
-                               }
-                       }
-
-                       if(pset_find_ptr(live, value) && cst != ILP_UNDEF) {
-                               lpp_set_factor_fast(si->lpp, cst, value_op->attr.live_range.ilp, -n_remats);
-                       }
-               }
-
-        /* ensure at least one value dies at post remat */
-        foreach_post_remat(irn, tmp) {
-            op_t     *remat_op = get_irn_link(tmp);
-            pset     *remat_args = pset_new_ptr(get_irn_arity(tmp));
-            ir_node  *remat_arg;
-
-            for(n=get_irn_arity(tmp)-1; n>=0; --n) {
-                remat_arg = get_irn_n(tmp, n);
-
-                if(has_reg_class(si, remat_arg)) {
-
-                    /* does arg always die at this op? */
-                    if(!pset_find_ptr(live, remat_arg))
-                        goto skip_one_must_die;
-
-                    pset_insert_ptr(remat_args, remat_arg);
-                }
-            }
-
-            /* remat + \sum live_range(remat_arg) <= |args| */
-            ir_snprintf(buf, sizeof(buf), "one_must_die_%+F", tmp);
-            cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, pset_count(remat_args));
-            lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-
-            pset_foreach(remat_args, remat_arg) {
-                op_t  *arg_op = get_irn_link(remat_arg);
-
-                lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, 1.0);
-            }
-
-skip_one_must_die:
-            del_pset(remat_args);
-        }
-
-               /* new live ranges for values from L\U defined by post remats */
-               pset_foreach(live, tmp) {
-                       ir_node     *value = tmp;
-                       op_t        *value_op = get_irn_link(value);
-
-                       if(!set_find_keyval(args, value) && !pset_find_ptr(defs, value)) {
-                               ilp_var_t    prev_lr = ILP_UNDEF;
-                               ir_node     *remat;
-
-                               if(pset_find_ptr(remat_defs, value)) {
-
-                                       /* next_live_range <= prev_live_range + sum remat2s */
-                                       ir_snprintf(buf, sizeof(buf), "next_lr_%N_%N", value, irn);
-                                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-                                       ir_snprintf(buf, sizeof(buf), "lr_%N_%N", value, irn);
-                                       prev_lr = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-
-                                       lpp_set_factor_fast(si->lpp, cst, value_op->attr.live_range.ilp, 1.0);
-                                       lpp_set_factor_fast(si->lpp, cst, prev_lr, -1.0);
-
-                                       foreach_post_remat(irn, remat) {
-                                               op_t        *remat_op = get_irn_link(remat);
-
-                                               /* if value is being rematerialized by this remat */
-                                               if(value == remat_op->attr.remat.remat->value) {
-                                                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
-                                               }
-                                       }
-
-                                       value_op->attr.live_range.ilp = prev_lr;
-                                       value_op->attr.live_range.op = irn;
-                               }
-                       }
-               }
-
-               /* requirements for post remats and start live ranges from L/U' for values dying here */
-               foreach_post_remat(irn, tmp) {
-                       op_t        *remat_op = get_irn_link(tmp);
-                       int          n;
-
-                       for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                               ir_node        *remat_arg = get_irn_n(tmp, n);
-                               op_t           *arg_op = get_irn_link(remat_arg);
-
-                               if(!has_reg_class(si, remat_arg)) continue;
-
-                               /* only for values in L\U (TODO and D?), the others are handled with post_use */
-                               if(!pset_find_ptr(used, remat_arg)) {
-                                       /* remat <= live_range(remat_arg) */
-                                       ir_snprintf(buf, sizeof(buf), "req_remat2_%N_arg_%N", tmp, remat_arg);
-                                       cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
-
-                                       /* if value is becoming live through use by remat2 */
-                                       if(!pset_find_ptr(live, remat_arg)) {
-                                               ilp_var_t     lr;
-
-                                               ir_snprintf(buf, sizeof(buf), "lr_%N_%N", remat_arg, irn);
-                                               lr = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-
-                                               arg_op->attr.live_range.ilp = lr;
-                                               arg_op->attr.live_range.op = irn;
-
-                                               DBG((si->dbg, LEVEL_3, "  value %+F becoming live through use by remat2 %+F\n", remat_arg, tmp));
-
-                                               pset_insert_ptr(live, remat_arg);
-                                               add_to_spill_bb(si, bb, remat_arg);
-                                       }
-
-                                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-                                       lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, -1.0);
-                               }
-                       }
-               }
-
-               d = pset_count(defs);
-               DBG((si->dbg, LEVEL_4, "\t   %+F produces %d values in my register class\n", irn, d));
-
-               /* count how many regs irn needs for arguments */
-               u = set_count(args);
-
-
-               /* check the register pressure in the epilog */
-               /* sum_{L\U'} lr + sum_{U'} post_use <= k - |D| */
-               ir_snprintf(buf, sizeof(buf), "check_post_%N", irn);
-               check_post = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs - d);
-
-               /* add L\U' to check_post */
-               pset_foreach(live, tmp) {
-                       if(!pset_find_ptr(used, tmp) && !pset_find_ptr(defs, tmp)) {
-                               /* if a live value is not used by irn */
-                               tmp_op = get_irn_link(tmp);
-                               lpp_set_factor_fast(si->lpp, check_post, tmp_op->attr.live_range.ilp, 1.0);
-                       }
-               }
-
-               /***********************************************************
-                *  I T E R A T I O N  O V E R  U S E S  F O R  E P I L O G
-                **********************************************************/
-
-
-               pset_foreach(used, tmp) {
-                       ilp_var_t       prev_lr;
-                       ilp_var_t       post_use;
-                       int             p = 0;
-                       spill_t        *spill;
-                       ir_node        *arg = tmp;
-                       op_t           *arg_op = get_irn_link(arg);
-                       ir_node        *remat;
-
-                       spill = add_to_spill_bb(si, bb, arg);
-
-                       /* new live range for each used value */
-                       ir_snprintf(buf, sizeof(buf), "lr_%N_%N", arg, irn);
-                       prev_lr = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-
-                       /* the epilog stuff - including post_use, check_post, check_post_remat */
-                       ir_snprintf(buf, sizeof(buf), "post_use_%N_%N", arg, irn);
-                       post_use = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-
-                       lpp_set_factor_fast(si->lpp, check_post, post_use, 1.0);
-
-                       /* arg is live throughout epilog if the next live_range is in a register */
-                       if(pset_find_ptr(live, arg)) {
-                               DBG((si->dbg, LEVEL_3, "\t  arg %+F is possibly live in epilog of %+F\n", arg, irn));
-
-                               /* post_use >= next_lr + remat */
-                               ir_snprintf(buf, sizeof(buf), "post_use_%N_%N-%d", arg, irn, p++);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                               lpp_set_factor_fast(si->lpp, cst, post_use, -1.0);
-                               lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, 1.0);
-                       }
-
-                       /* forall post remat which use arg add a similar cst */
-                       foreach_post_remat(irn, remat) {
-                               int      n;
-
-                               for (n=get_irn_arity(remat)-1; n>=0; --n) {
-                                       ir_node    *remat_arg = get_irn_n(remat, n);
-                                       op_t       *remat_op = get_irn_link(remat);
-
-                                       if(remat_arg == arg) {
-                                               DBG((si->dbg, LEVEL_3, "\t  found remat with arg %+F in epilog of %+F\n", arg, irn));
-
-                                               /* post_use >= remat */
-                                               ir_snprintf(buf, sizeof(buf), "post_use_%N_%N-%d", arg, irn, p++);
-                                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                                               lpp_set_factor_fast(si->lpp, cst, post_use, -1.0);
-                                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-                                       }
-                               }
-                       }
-
-                       /* if value is not an arg of op and not possibly defined by post remat
-                        * then it may only die and not become live
-                        */
-                       if(!set_find_keyval(args, arg)) {
-                               /* post_use <= prev_lr */
-                               ir_snprintf(buf, sizeof(buf), "req_post_use_%N_%N", arg, irn);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                               lpp_set_factor_fast(si->lpp, cst, post_use, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, prev_lr, -1.0);
-
-                               if(!pset_find_ptr(remat_defs, arg) && pset_find_ptr(live, arg)) {
-                                       /* next_lr <= prev_lr */
-                                       ir_snprintf(buf, sizeof(buf), "next_lr_%N_%N", arg, irn);
-                                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                                       lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, 1.0);
-                                       lpp_set_factor_fast(si->lpp, cst, prev_lr, -1.0);
-                               }
-                       }
-
-                       if(opt_memoperands && (!is_start_block(bb) || be_is_Barrier(irn))) {
-                               for(n = get_irn_arity(irn)-1; n>=0; --n) {
-                                       if (get_irn_n(irn, n) == arg &&
-                                                       arch_possible_memory_operand(irn, n)) {
-                                               ilp_var_t       memoperand;
-
-                                               ir_snprintf(buf, sizeof(buf), "memoperand_%N_%d", irn, n);
-                                               memoperand = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_memoperand*execution_frequency(si, bb), 0.0);
-                                               set_insert_memoperand(si->memoperands, irn, n, memoperand);
-
-                                               ir_snprintf(buf, sizeof(buf), "nolivepost_%N_%d", irn, n);
-                                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-
-                                               lpp_set_factor_fast(si->lpp, cst, memoperand, 1.0);
-                                               lpp_set_factor_fast(si->lpp, cst, post_use, 1.0);
-                                       }
-                               }
-                       }
-
-                       /* new live range begins for each used value */
-                       arg_op->attr.live_range.ilp = prev_lr;
-                       arg_op->attr.live_range.op = irn;
-
-                       pset_insert_ptr(live, arg);
-               }
-
-               /* just to be sure */
-               check_post = ILP_UNDEF;
-
-               /* allow original defintions to be removed */
-               if(opt_repair_schedule) {
-                       pset_foreach(defs, tmp) {
-                               op_t      *tmp_op = get_irn_link(tmp);
-                               spill_t   *spill = set_find_spill(spill_bb->ilp, tmp);
-#if 1
-                               ilp_var_t  delete;
-                               assert(spill);
-
-                               ir_snprintf(buf, sizeof(buf), "delete_%N", tmp);
-                               delete = lpp_add_var_default(si->lpp, buf, lpp_binary, -1.0 * get_cost(irn) * execution_frequency(si, bb), 0.0);
-
-                               /* op may not be killed if its first live_range is 1 */
-                               ir_snprintf(buf, sizeof(buf), "killorig-lr_%N", tmp);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, delete, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, tmp_op->attr.live_range.ilp, 1.0);
-
-                               /* op may not be killed if it is spilled after the definition */
-                               ir_snprintf(buf, sizeof(buf), "killorig-spill_%N", tmp);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, delete, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, spill->spill, 1.0);
-#else
-                               ilp_var_t  keep;
-                               assert(spill);
-
-                               ir_snprintf(buf, sizeof(buf), "keep_%N", tmp);
-                               keep = lpp_add_var_default(si->lpp, buf, lpp_binary, get_cost(irn) * execution_frequency(si, bb), 1.0);
-
-                               /* op may not be killed if its first live_range is 1 */
-                               ir_snprintf(buf, sizeof(buf), "killorig-lr_%N", tmp);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_greater, 0.0);
-                               lpp_set_factor_fast(si->lpp, cst, keep, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, tmp_op->attr.live_range.ilp, -1.0);
-
-                               /* op may not be killed if it is spilled after the definition */
-                               ir_snprintf(buf, sizeof(buf), "killorig-spill_%N", tmp);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_greater, 0.0);
-                               lpp_set_factor_fast(si->lpp, cst, keep, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, spill->spill, -1.0);
-#endif
-                       }
-               } else {
-#if 0
-                       pset_foreach(defs, tmp) {
-                               op_t      *tmp_op = get_irn_link(tmp);
-                               spill_t   *spill = set_find_spill(spill_bb->ilp, tmp);
-                               assert(spill);
-
-                               /* live_range or spill should be 1
-                                  TODO: lr should be live until first use */
-                               ir_snprintf(buf, sizeof(buf), "nokillorig_%N", tmp);
-                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_greater, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, tmp_op->attr.live_range.ilp, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, spill->spill, 1.0);
-                       }
-#endif
-               }
-
-
-               /******************
-                *   P R O L O G
-                ******************/
-
-               /* check the register pressure in the prolog */
-               /* sum_{L\U} lr <= k - |U| */
-               ir_snprintf(buf, sizeof(buf), "check_pre_%N", irn);
-               check_pre = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs - u);
-
-               /* for the prolog remove defined values from the live set */
-               pset_foreach(defs, tmp) {
-                       pset_remove_ptr(live, tmp);
-               }
-
-               if(opt_memoperands && (!is_start_block(bb) || be_is_Barrier(irn))) {
-                       ir_snprintf(buf, sizeof(buf), "one_memoperand_%N", irn);
-                       one_memoperand = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-               }
-
-               /***********************************************************
-                *  I T E R A T I O N  O V E R  A R G S  F O R  P R O L O G
-                **********************************************************/
-
-
-               set_foreach(args, keyval) {
-                       spill_t          *spill;
-                       const ir_node    *arg = keyval->key;
-                       int               i = PTR_TO_INT(keyval->val);
-                       op_t             *arg_op = get_irn_link(arg);
-                       ilp_cst_t         requirements;
-                       int               n_memoperands;
-
-                       spill = set_find_spill(spill_bb->ilp, arg);
-                       assert(spill);
-
-                       ir_snprintf(buf, sizeof(buf), "reload_%N_%N", arg, irn);
-                       op->attr.live_range.args.reloads[i] = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_reload*execution_frequency(si, bb), 1.0);
-
-                       /* reload <= mem_out */
-                       ir_snprintf(buf, sizeof(buf), "req_reload_%N_%N", arg, irn);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                       lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.args.reloads[i], 1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spill->mem_out, -1.0);
-
-                       /* requirement: arg must be in register for use */
-                       /* reload + remat + live_range == 1 */
-                       ir_snprintf(buf, sizeof(buf), "req_%N_%N", irn, arg);
-                       requirements = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 1.0);
-
-                       lpp_set_factor_fast(si->lpp, requirements, arg_op->attr.live_range.ilp, 1.0);
-                       lpp_set_factor_fast(si->lpp, requirements, op->attr.live_range.args.reloads[i], 1.0);
-                       foreach_pre_remat(irn, tmp) {
-                               op_t     *remat_op = get_irn_link(tmp);
-                               if(remat_op->attr.remat.remat->value == arg) {
-                                       lpp_set_factor_fast(si->lpp, requirements, remat_op->attr.remat.ilp, 1.0);
-                               }
-                       }
-
-                       if(opt_memoperands && (!is_start_block(bb) || be_is_Barrier(irn))) {
-                               n_memoperands = 0;
-                               for(n = get_irn_arity(irn)-1; n>=0; --n) {
-                                       if(get_irn_n(irn, n) == arg) {
-                                               n_memoperands++;
-                                       }
-                               }
-                               for(n = get_irn_arity(irn)-1; n>=0; --n) {
-                                       if (get_irn_n(irn, n) == arg &&
-                                                       arch_possible_memory_operand(irn, n)) {
-                                               memoperand_t  *memoperand;
-                                               memoperand = set_find_memoperand(si->memoperands, irn, n);
-
-                                               /* memoperand <= mem_out */
-                                               ir_snprintf(buf, sizeof(buf), "req_memoperand_%N_%d", irn, n);
-                                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                                               lpp_set_factor_fast(si->lpp, cst, memoperand->ilp, 1.0);
-                                               lpp_set_factor_fast(si->lpp, cst, spill->mem_out, -1.0);
-
-                                               /* the memoperand is only sufficient if it is used once by the op */
-                                               if(n_memoperands == 1)
-                                                       lpp_set_factor_fast(si->lpp, requirements, memoperand->ilp, 1.0);
-
-                                               lpp_set_factor_fast(si->lpp, one_memoperand, memoperand->ilp, 1.0);
-
-                                               /* we have one more free register if we use a memory operand */
-                                               lpp_set_factor_fast(si->lpp, check_pre, memoperand->ilp, -1.0);
-                                       }
-                               }
-                       }
-               }
-
-               /* iterate over L\U */
-               pset_foreach(live, tmp) {
-                       if(!set_find_keyval(args, tmp)) {
-                               /* if a live value is not used by irn */
-                               tmp_op = get_irn_link(tmp);
-                               lpp_set_factor_fast(si->lpp, check_pre, tmp_op->attr.live_range.ilp, 1.0);
-                       }
-               }
-
-               /* requirements for remats */
-               foreach_pre_remat(irn, tmp) {
-                       op_t        *remat_op = get_irn_link(tmp);
-                       int          n;
-
-                       for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                               ir_node        *remat_arg = get_irn_n(tmp, n);
-                               op_t           *arg_op = get_irn_link(remat_arg);
-
-                               if(!has_reg_class(si, remat_arg)) continue;
-
-                               /* remat <= live_rang(remat_arg) [ + reload(remat_arg) ] */
-                               ir_snprintf(buf, sizeof(buf), "req_remat_%N_arg_%N", tmp, remat_arg);
-                               cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
-
-                               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-                               lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, -1.0);
-
-                               /* if remat arg is also used by current op then we can use reload placed for this argument */
-                               if((keyval = set_find_keyval(args, remat_arg)) != NULL) {
-                                       int    index = (int)keyval->val;
-
-                                       lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.args.reloads[index], -1.0);
-                               }
-                       }
-               }
-
-
-
-
-               /*************************
-                *  D O N E  W I T H  O P
-                *************************/
-
-               DBG((si->dbg, LEVEL_4, "\t   %d values live at %+F\n", pset_count(live), irn));
-
-               pset_foreach(live, tmp) {
-                       assert(has_reg_class(si, tmp));
-               }
-
-#ifndef NDEBUG
-               for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node        *arg = get_irn_n(irn, n);
-
-                       assert(!find_post_remat(arg, irn) && "there should be no post remat for an argument of an op");
-               }
-#endif
-
-               del_pset(remat_defs);
-               del_pset(used);
-               del_set(args);
-               del_pset(defs);
-               defs = pset_new_ptr_default();
-
-               /* skip everything above barrier in start block */
-               if(is_start_block(bb) && be_is_Barrier(irn)) {
-                       assert(pset_count(live) == 0);
-                       break;
-               }
-
-       }
-       del_pset(defs);
-
-
-
-       /***************************************
-        *   B E G I N N I N G  O F  B L O C K
-        ***************************************/
-
-
-       /* we are now at the beginning of the basic block, there are only \Phis in front of us */
-       DBG((si->dbg, LEVEL_3, "\t   %d values live at beginning of block %+F\n", pset_count(live), bb));
-
-       pset_foreach(live, irn) {
-               assert(is_Phi(irn) || get_nodes_block(irn) != bb);
-       }
-
-       /* construct mem_outs for all values */
-       set_foreach(spill_bb->ilp, spill) {
-               ir_snprintf(buf, sizeof(buf), "mem_out_%N_%N", spill->irn, bb);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-               lpp_set_factor_fast(si->lpp, cst, spill->mem_out, 1.0);
-               lpp_set_factor_fast(si->lpp, cst, spill->spill, -1.0);
-
-               if(pset_find_ptr(live, spill->irn)) {
-                       int default_spilled;
-                       DBG((si->dbg, LEVEL_5, "\t     %+F live at beginning of block %+F\n", spill->irn, bb));
-
-                       ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N", spill->irn, bb);
-                       default_spilled = be_is_live_in(si->lv, bb, spill->irn) || is_Phi(spill->irn);
-                       spill->mem_in   = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, default_spilled);
-                       lpp_set_factor_fast(si->lpp, cst, spill->mem_in, -1.0);
-
-                       if(opt_memcopies && is_Phi(spill->irn) && get_nodes_block(spill->irn) == bb) {
-                               int   n;
-                               op_t *op = get_irn_link(spill->irn);
-
-                               for(n=get_irn_arity(spill->irn)-1; n>=0; --n) {
-                                       const ir_node  *arg = get_irn_n(spill->irn, n);
-                                       double          freq=0.0;
-                                       int             m;
-                                       ilp_var_t       var;
-
-
-                                       /* argument already done? */
-                                       if(op->attr.live_range.args.copies[n] != ILP_UNDEF) continue;
-
-                                       /* get sum of execution frequencies of blocks with the same phi argument */
-                                       for(m=n; m>=0; --m) {
-                                               const ir_node  *arg2 = get_irn_n(spill->irn, m);
-
-                                               if(arg==arg2) {
-                                                       freq += execution_frequency(si, get_Block_cfgpred_block(bb, m));
-                                               }
-                                       }
-
-                                       /* copies are not for free */
-                                       ir_snprintf(buf, sizeof(buf), "copy_%N_%N", arg, spill->irn);
-                                       var = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_spill * freq, 1.0);
-
-                                       for(m=n; m>=0; --m) {
-                                               const ir_node  *arg2 = get_irn_n(spill->irn, m);
-
-                                               if(arg==arg2) {
-                                                       op->attr.live_range.args.copies[m] = var;
-                                               }
-                                       }
-
-#if 0
-                                       /* copy <= mem_in */
-                                       ir_snprintf(buf, sizeof(buf), "nocopy_%N_%N", arg, spill->irn);
-                                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                                       lpp_set_factor_fast(si->lpp, cst, var, 1.0);
-                                       lpp_set_factor_fast(si->lpp, cst, spill->mem_in, -1.0);
-#endif
-                               }
-                       }
-               }
-       }
-
-       foreach_post_remat(bb, tmp) {
-               int         n;
-               op_t       *remat_op = get_irn_link(tmp);
-               pset       *remat_args = pset_new_ptr(get_irn_arity(tmp));
-               ir_node    *remat_arg;
-
-               for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                       remat_arg = get_irn_n(tmp, n);
-
-                       if(has_reg_class(si, remat_arg)) {
-                               pset_insert_ptr(remat_args, remat_arg);
-                       }
-               }
-
-               /* remat + \sum live_range(remat_arg) <= |args| */
-               ir_snprintf(buf, sizeof(buf), "one_must_die_%N", tmp);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, pset_count(remat_args));
-               lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-
-               pset_foreach(remat_args, remat_arg) {
-                       if(pset_find_ptr(live, remat_arg)) {
-                               op_t       *remat_arg_op = get_irn_link(remat_arg);
-                               lpp_set_factor_fast(si->lpp, cst, remat_arg_op->attr.live_range.ilp, 1.0);
-                       }
-               }
-               del_pset(remat_args);
-       }
-
-       foreach_post_remat(bb, tmp) {
-               int  n;
-
-               for(n=get_irn_arity(tmp)-1; n>=0; --n) {
-                       ir_node  *remat_arg = get_irn_n(tmp, n);
-
-                       /* if value is becoming live through use by remat2 */
-                       if(has_reg_class(si, remat_arg) && !pset_find_ptr(live, remat_arg)) {
-                               op_t       *remat_arg_op = get_irn_link(remat_arg);
-                               ilp_cst_t   nomem;
-
-                               DBG((si->dbg, LEVEL_3, "  value %+F becoming live through use by remat2 at bb start %+F\n", remat_arg, tmp));
-
-                               pset_insert_ptr(live, remat_arg);
-                               spill = add_to_spill_bb(si, bb, remat_arg);
-                               remat_arg_op->attr.live_range.ilp = ILP_UNDEF;
-
-                               /* we need reg_in and mem_in for this value; they will be referenced later */
-                               ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N", remat_arg, bb);
-                               spill->reg_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-                               ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N", remat_arg, bb);
-                               spill->mem_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-
-                               /* optimization: all memory stuff should be 0, for we do not want to insert reloads for remats */
-                               ir_snprintf(buf, sizeof(buf), "nomem_%N_%N", remat_arg, bb);
-                               nomem = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 0.0);
-                               lpp_set_factor_fast(si->lpp, nomem, spill->spill, 1.0);
-                       }
-               }
-       }
-
-       /* L\U is empty at bb start */
-       /* arg is live throughout epilog if it is reg_in into this block */
-
-       /* check the register pressure at the beginning of the block
-        * including remats
-        */
-       /* reg_in entspricht post_use */
-
-       ir_snprintf(buf, sizeof(buf), "check_start_%N", bb);
-       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs);
-
-       pset_foreach(live, irn) {
-        ilp_cst_t  nospill;
-
-               spill = set_find_spill(spill_bb->ilp, irn);
-               assert(spill);
-
-               ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N", irn, bb);
-               spill->reg_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
-
-               lpp_set_factor_fast(si->lpp, cst, spill->reg_in, 1.0);
-
-               /* spill + mem_in <= 1 */
-               ir_snprintf(buf, sizeof(buf), "nospill_%N_%N", irn, bb);
-               nospill = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1);
-
-               lpp_set_factor_fast(si->lpp, nospill, spill->mem_in, 1.0);
-               lpp_set_factor_fast(si->lpp, nospill, spill->spill, 1.0);
-
-       } /* post_remats are NOT included in register pressure check because
-          they do not increase regpressure */
-
-       /* mem_in/reg_in for live_in values, especially phis and their arguments */
-       pset_foreach(live, irn) {
-               int          p = 0,
-                                        n;
-
-               spill = set_find_spill(spill_bb->ilp, irn);
-               assert(spill && spill->irn == irn);
-
-               if(is_Phi(irn) && get_nodes_block(irn) == bb) {
-                       for (n=get_Phi_n_preds(irn)-1; n>=0; --n) {
-                               ilp_cst_t       mem_in,
-                                                               reg_in;
-                               ir_node        *phi_arg = get_Phi_pred(irn, n);
-                               ir_node        *bb_p = get_Block_cfgpred_block(bb, n);
-                               spill_bb_t     *spill_bb_p = get_irn_link(bb_p);
-                               spill_t        *spill_p;
-                               op_t           *op = get_irn_link(irn);
-
-                               /* although the phi is in the right regclass one or more of
-                                * its arguments can be in a different one or at least to
-                                * ignore
-                                */
-                               if(has_reg_class(si, phi_arg)) {
-                                       /* mem_in < mem_out_arg + copy */
-                                       ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N-%d", irn, bb, p);
-                                       mem_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-                                       /* reg_in < reg_out_arg */
-                                       ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N-%d", irn, bb, p++);
-                                       reg_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-                                       lpp_set_factor_fast(si->lpp, mem_in, spill->mem_in, 1.0);
-                                       lpp_set_factor_fast(si->lpp, reg_in, spill->reg_in, 1.0);
-
-                                       spill_p = set_find_spill(spill_bb_p->ilp, phi_arg);
-                                       assert(spill_p);
-
-                                       lpp_set_factor_fast(si->lpp, mem_in, spill_p->mem_out, -1.0);
-                                       if(opt_memcopies)
-                                               lpp_set_factor_fast(si->lpp, mem_in, op->attr.live_range.args.copies[n], -1.0);
-
-                                       lpp_set_factor_fast(si->lpp, reg_in, spill_p->reg_out, -1.0);
-                               }
-                       }
-               } else {
-                       /* else assure the value arrives on all paths in the same resource */
-
-                       for (n=get_Block_n_cfgpreds(bb)-1; n>=0; --n) {
-                               ilp_cst_t       mem_in,
-                                                               reg_in;
-                               ir_node        *bb_p = get_Block_cfgpred_block(bb, n);
-                               spill_bb_t     *spill_bb_p = get_irn_link(bb_p);
-                               spill_t        *spill_p;
-
-                               ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N-%d", irn, bb, p);
-                               mem_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                               ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N-%d", irn, bb, p++);
-                               reg_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-                               lpp_set_factor_fast(si->lpp, mem_in, spill->mem_in, 1.0);
-                               lpp_set_factor_fast(si->lpp, reg_in, spill->reg_in, 1.0);
-
-                               spill_p = set_find_spill(spill_bb_p->ilp, irn);
-                               assert(spill_p);
-
-                               lpp_set_factor_fast(si->lpp, mem_in, spill_p->mem_out, -1.0);
-                               lpp_set_factor_fast(si->lpp, reg_in, spill_p->reg_out, -1.0);
-                       }
-               }
-       }
-
-       foreach_post_remat(bb, tmp) {
-               int         n;
-
-               for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                       ir_node    *remat_arg = get_irn_n(tmp, n);
-                       op_t       *remat_op = get_irn_link(tmp);
-
-                       if(!has_reg_class(si, remat_arg)) continue;
-
-                       spill = set_find_spill(spill_bb->ilp, remat_arg);
-                       assert(spill);
-
-                       ir_snprintf(buf, sizeof(buf), "req_remat2_%N_%N_arg_%N", tmp, bb, remat_arg);
-                       cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
-                       lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
-                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-               }
-       }
-
-       pset_foreach(live, irn) {
-               const op_t      *op = get_irn_link(irn);
-               const ir_node   *remat;
-               int              n_remats = 0;
-
-               cst = ILP_UNDEF;
-
-               foreach_post_remat(bb, remat) {
-                       int   n;
-
-                       for (n=get_irn_arity(remat)-1; n>=0; --n) {
-                               const ir_node  *arg = get_irn_n(remat, n);
-
-                               if(arg == irn) {
-                                       const op_t   *remat_op = get_irn_link(remat);
-
-                                       if(cst == ILP_UNDEF) {
-                                               /* sum remat2s <= 1 + n_remats*live_range */
-                                               ir_snprintf(buf, sizeof(buf), "dying_lr_%N_%N", irn, bb);
-                                               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
-                                       }
-                                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
-                                       ++n_remats;
-                                       break;
-                               }
-                       }
-               }
-               if(cst != ILP_UNDEF && op->attr.live_range.ilp != ILP_UNDEF) {
-                       lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, -n_remats);
-               }
-       }
-
-       /* first live ranges from reg_ins */
-       pset_foreach(live, irn) {
-               op_t      *op = get_irn_link(irn);
-
-               if(op->attr.live_range.ilp != ILP_UNDEF) {
-
-                       spill = set_find_spill(spill_bb->ilp, irn);
-                       assert(spill && spill->irn == irn);
-
-                       ir_snprintf(buf, sizeof(buf), "first_lr_%N_%N", irn, bb);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-                       lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, 1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
-
-                       foreach_post_remat(bb, tmp) {
-                               op_t     *remat_op = get_irn_link(tmp);
-
-                               if(remat_op->attr.remat.remat->value == irn) {
-                                       lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
-                               }
-                       }
-               }
-       }
-
-       /* walk forward now and compute constraints for placing spills */
-       /* this must only be done for values that are not defined in this block */
-       pset_foreach(live, irn) {
-               /*
-                * if value is defined in this block we can anways place the spill directly after the def
-                *    -> no constraint necessary
-                */
-               if(!is_Phi(irn) && get_nodes_block(irn) == bb) {
-                       assert(0);
-               }
-
-
-               spill = set_find_spill(spill_bb->ilp, irn);
-               assert(spill);
-
-               ir_snprintf(buf, sizeof(buf), "req_spill_%N_%N", irn, bb);
-               cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
-
-               lpp_set_factor_fast(si->lpp, cst, spill->spill, 1.0);
-               if(is_diverge_edge(bb)) lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
-
-               if(!is_Phi(irn)) {
-                       sched_foreach_op(bb, tmp) {
-                               op_t   *op = get_irn_link(tmp);
-
-                               if(is_Phi(tmp)) continue;
-                               assert(!is_Proj(tmp));
-
-                               if(op->is_remat) {
-                                       const ir_node   *value = op->attr.remat.remat->value;
-
-                                       if(value == irn) {
-                                               /* only collect remats up to the first real use of a value */
-                                               lpp_set_factor_fast(si->lpp, cst, op->attr.remat.ilp, -1.0);
-                                       }
-                               } else {
-                                       int   n;
-
-                                       for (n=get_irn_arity(tmp)-1; n>=0; --n) {
-                                               ir_node    *arg = get_irn_n(tmp, n);
-
-                                               if(arg == irn) {
-                                                       /* if a value is used stop collecting remats */
-                            goto next_live;
-                                               }
-                                       }
-                               }
-                       }
-               }
-next_live: ;
-       }
-
-       del_pset(live);
-}
-
-typedef struct _irnlist_t {
-       struct list_head   list;
-       ir_node           *irn;
-} irnlist_t;
-
-typedef struct _interference_t {
-       struct list_head    blocklist;
-       ir_node            *a;
-       ir_node            *b;
-} interference_t;
-
-static int
-cmp_interference(const void *a, const void *b, size_t size)
-{
-       const interference_t *p = a;
-       const interference_t *q = b;
-       (void) size;
-
-       return !(p->a == q->a && p->b == q->b);
-}
-
-static interference_t *
-set_find_interference(set * set, ir_node * a, ir_node * b)
-{
-       interference_t     query;
-
-       query.a = (a>b)?a:b;
-       query.b = (a>b)?b:a;
-
-       return set_find(set, &query, sizeof(query), HASH_PTR(PTR_TO_INT(a) ^ PTR_TO_INT(b)));
-}
-
-static interference_t *
-set_insert_interference(spill_ilp_t * si, set * set, ir_node * a, ir_node * b, ir_node * bb)
-{
-       interference_t     query,
-                                         *result;
-       irnlist_t         *list = obstack_alloc(si->obst, sizeof(*list));
-
-       list->irn = bb;
-
-       result = set_find_interference(set, a, b);
-       if(result) {
-
-               list_add(&list->list, &result->blocklist);
-               return result;
-       }
-
-       query.a = (a>b)?a:b;
-       query.b = (a>b)?b:a;
-
-       result = set_insert(set, &query, sizeof(query), HASH_PTR(PTR_TO_INT(a) ^ PTR_TO_INT(b)));
-
-       INIT_LIST_HEAD(&result->blocklist);
-       list_add(&list->list, &result->blocklist);
-
-       return result;
-}
-
-static
-int values_interfere_in_block(const spill_ilp_t *si, const ir_node *bb, const ir_node *a, const ir_node *b)
-{
-       const ir_edge_t *edge;
-
-       if (get_nodes_block(a) != bb && get_nodes_block(b) != bb) {
-               /* both values are live in, so they interfere */
-               return 1;
-       }
-
-       /* ensure a dominates b */
-       if (value_dominates(b, a)) {
-               const ir_node *t;
-               t = b;
-               b = a;
-               a = t;
-       }
-       assert(get_nodes_block(b) == bb && "at least b should be defined here in this block");
-
-
-       /* the following code is stolen from bera.c */
-       if (be_is_live_end(si->lv, bb, a))
-               return 1;
-
-       foreach_out_edge(a, edge) {
-               const ir_node *user = edge->src;
-               if (get_nodes_block(user) == bb
-                               && ! is_Phi(user)
-                               && b != user
-                               && ! pset_find_ptr(si->inverse_ops, user)
-                               && value_dominates(b, user))
-                       return 1;
-       }
-
-       return 0;
-}
-
-/**
- * Walk all irg blocks and collect interfering values inside of phi classes
- */
-static void
-luke_interferencewalker(ir_node * bb, void * data)
-{
-       spill_ilp_t    *si = (spill_ilp_t*)data;
-       int             l1, l2;
-
-       be_lv_foreach(si->lv, bb, be_lv_state_end | be_lv_state_out | be_lv_state_in, l1) {
-               ir_node        *a = be_lv_get_irn(si->lv, bb, l1);
-               op_t           *a_op = get_irn_link(a);
-
-
-               /* a is only interesting if it is in my register class and if it is inside a phi class */
-               if (has_reg_class(si, a) && get_phi_class(si->pc, a)) {
-                       if (a_op->is_remat || pset_find_ptr(si->inverse_ops, a))
-                               continue;
-
-                       for (l2 = _be_lv_next_irn(si->lv, bb, 0xff, l1 + 1); l2 >= 0; l2 = _be_lv_next_irn(si->lv, bb, 0xff, l2 + 1)) {
-                               ir_node *b    = be_lv_get_irn(si->lv, bb, l2);
-                               op_t    *b_op = get_irn_link(b);
-
-                               /* a and b are only interesting if they are in the same phi class */
-                               if (has_reg_class(si, b) && get_phi_class(si->pc, a) == get_phi_class(si->pc, b)) {
-                                       if (b_op->is_remat || pset_find_ptr(si->inverse_ops, b))
-                                               continue;
-
-                                       if (values_interfere_in_block(si, bb, a, b)) {
-                                               DBG((si->dbg, LEVEL_4, "\tvalues interfere in %+F: %+F, %+F\n", bb, a, b));
-                                               set_insert_interference(si, si->interferences, a, b, bb);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-static unsigned int copy_path_id = 0;
-
-static void
-write_copy_path_cst(spill_ilp_t *si, pset * copies, ilp_var_t any_interfere)
-{
-       ilp_cst_t  cst;
-       ilp_var_t  copy;
-       char       buf[256];
-       void      *ptr;
-
-       ir_snprintf(buf, sizeof(buf), "copy_path-%d", copy_path_id++);
-       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0);
-
-       lpp_set_factor_fast(si->lpp, cst, any_interfere, 1.0);
-
-       pset_foreach(copies, ptr) {
-               copy = PTR_TO_INT(ptr);
-               lpp_set_factor_fast(si->lpp, cst, copy, -1.0);
-       }
-}
-
-/**
- * @parameter copies   contains a path of copies which lead us to irn
- * @parameter visited  contains a set of nodes already visited on this path
- */
-static int
-find_copy_path(spill_ilp_t * si, const ir_node * irn, const ir_node * target, ilp_var_t any_interfere, pset * copies, pset * visited)
-{
-       const ir_edge_t *edge;
-       op_t            *op = get_irn_link(irn);
-    pset            *visited_users = pset_new_ptr_default();
-       int              paths = 0;
-
-       if(op->is_remat) return 0;
-
-       pset_insert_ptr(visited, irn);
-
-       if(is_Phi(irn)) {
-               int    n;
-        pset  *visited_operands = pset_new_ptr(get_irn_arity(irn));
-
-               /* visit all operands */
-               for(n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node  *arg = get_irn_n(irn, n);
-                       ilp_var_t  copy = op->attr.live_range.args.copies[n];
-
-                       if(!has_reg_class(si, arg)) continue;
-            if(pset_find_ptr(visited_operands, arg)) continue;
-            pset_insert_ptr(visited_operands, arg);
-
-                       if(arg == target) {
-                               if(++paths > MAX_PATHS && pset_count(copies) != 0) {
-                                       del_pset(visited_operands);
-                                       del_pset(visited_users);
-                                       pset_remove_ptr(visited, irn);
-                                       return paths;
-                               }
-                               pset_insert(copies, INT_TO_PTR(copy), copy);
-                               write_copy_path_cst(si, copies, any_interfere);
-                               pset_remove(copies, INT_TO_PTR(copy), copy);
-                       } else if(!pset_find_ptr(visited, arg)) {
-                               pset_insert(copies, INT_TO_PTR(copy), copy);
-                               paths += find_copy_path(si, arg, target, any_interfere, copies, visited);
-                               pset_remove(copies, INT_TO_PTR(copy), copy);
-
-                if(paths > MAX_PATHS) {
-                    if(pset_count(copies) == 0) {
-                        ilp_cst_t  cst;
-                        char       buf[256];
-
-                        ir_snprintf(buf, sizeof(buf), "always_copy-%d-%d", any_interfere, copy);
-                        cst = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 0);
-                        lpp_set_factor_fast(si->lpp, cst, any_interfere, -1.0);
-                        lpp_set_factor_fast(si->lpp, cst, copy, 1.0);
-                        DBG((si->dbg, LEVEL_1, "ALWAYS COPYING %d FOR INTERFERENCE %d\n", copy, any_interfere));
-
-                        paths = 0;
-                    } else {
-                        del_pset(visited_operands);
-                        del_pset(visited_users);
-                        pset_remove_ptr(visited, irn);
-                        return paths;
-                    }
-                } else if(pset_count(copies) == 0) {
-                                       paths = 0;
-                               }
-                       }
-               }
-
-        del_pset(visited_operands);
-       }
-
-       /* visit all uses which are phis */
-       foreach_out_edge(irn, edge) {
-               ir_node  *user = edge->src;
-               int       pos  = edge->pos;
-               op_t     *op = get_irn_link(user);
-               ilp_var_t copy;
-
-               if(!is_Phi(user)) continue;
-               if(!has_reg_class(si, user)) continue;
-        if(pset_find_ptr(visited_users, user)) continue;
-        pset_insert_ptr(visited_users, user);
-
-               copy = op->attr.live_range.args.copies[pos];
-
-               if(user == target) {
-                       if(++paths > MAX_PATHS && pset_count(copies) != 0) {
-                               del_pset(visited_users);
-                               pset_remove_ptr(visited, irn);
-                               return paths;
-                       }
-                       pset_insert(copies, INT_TO_PTR(copy), copy);
-                       write_copy_path_cst(si, copies, any_interfere);
-                       pset_remove(copies, INT_TO_PTR(copy), copy);
-               } else if(!pset_find_ptr(visited, user)) {
-                       pset_insert(copies, INT_TO_PTR(copy), copy);
-                       paths += find_copy_path(si, user, target, any_interfere, copies, visited);
-                       pset_remove(copies, INT_TO_PTR(copy), copy);
-
-            if(paths > MAX_PATHS) {
-                if(pset_count(copies) == 0) {
-                    ilp_cst_t  cst;
-                    char       buf[256];
-
-                    ir_snprintf(buf, sizeof(buf), "always_copy-%d-%d", any_interfere, copy);
-                    cst = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 0);
-                    lpp_set_factor_fast(si->lpp, cst, any_interfere, -1.0);
-                    lpp_set_factor_fast(si->lpp, cst, copy, 1.0);
-                    DBG((si->dbg, LEVEL_1, "ALWAYS COPYING %d FOR INTERFERENCE %d\n", copy, any_interfere));
-
-                    paths = 0;
-                } else {
-                    del_pset(visited_users);
-                    pset_remove_ptr(visited, irn);
-                    return paths;
-                }
-            } else if(pset_count(copies) == 0) {
-                               paths = 0;
-                       }
-               }
-       }
-
-    del_pset(visited_users);
-       pset_remove_ptr(visited, irn);
-       return paths;
-}
-
-static void
-gen_copy_constraints(spill_ilp_t * si, const ir_node * a, const ir_node * b, ilp_var_t any_interfere)
-{
-       pset * copies = pset_new_ptr_default();
-       pset * visited = pset_new_ptr_default();
-
-       find_copy_path(si, a, b, any_interfere, copies, visited);
-
-       del_pset(visited);
-       del_pset(copies);
-}
-
-
-static void
-memcopyhandler(spill_ilp_t * si)
-{
-       interference_t   *interference;
-       char              buf[256];
-       /* teste Speicherwerte auf Interferenz */
-
-       DBG((si->dbg, LEVEL_2, "\t calling interferencewalker\n"));
-       irg_block_walk_graph(si->birg->irg, luke_interferencewalker, NULL, si);
-
-       /* now lets emit the ILP unequations for the crap */
-       set_foreach(si->interferences, interference) {
-               irnlist_t      *irnlist;
-               ilp_var_t      interfere, any_interfere;
-               ilp_cst_t      any_interfere_cst, cst;
-               const ir_node  *a  = interference->a;
-               const ir_node  *b  = interference->b;
-
-               /* any_interf <= \sum interf */
-               ir_snprintf(buf, sizeof(buf), "interfere_%N_%N", a, b);
-               any_interfere_cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0);
-               any_interfere     = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-               lpp_set_factor_fast(si->lpp, any_interfere_cst, any_interfere, 1.0);
-
-               list_for_each_entry(irnlist_t, irnlist, &interference->blocklist, list) {
-                       const ir_node  *bb = irnlist->irn;
-                       spill_bb_t     *spill_bb = get_irn_link(bb);
-                       spill_t        *spilla,
-                                                  *spillb;
-                       char           buf[256];
-
-                       spilla = set_find_spill(spill_bb->ilp, a);
-                       assert(spilla);
-
-                       spillb = set_find_spill(spill_bb->ilp, b);
-                       assert(spillb);
-
-                       /* interfere <-> (mem_in_a or spill_a) and (mem_in_b or spill_b): */
-                       /* 1:   mem_in_a + mem_in_b + spill_a + spill_b - interfere <= 1 */
-                       /* 2: - mem_in_a - spill_a + interfere <= 0 */
-                       /* 3: - mem_in_b - spill_b + interfere <= 0 */
-                       ir_snprintf(buf, sizeof(buf), "interfere_%N_%N_%N", bb, a, b);
-                       interfere = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
-
-                       ir_snprintf(buf, sizeof(buf), "interfere_%N_%N_%N-1", bb, a, b);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1);
-
-                       lpp_set_factor_fast(si->lpp, cst, interfere, -1.0);
-                       if(spilla->mem_in != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, spilla->mem_in, 1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spilla->spill, 1.0);
-                       if(spillb->mem_in != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, spillb->mem_in, 1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spillb->spill, 1.0);
-
-                       ir_snprintf(buf, sizeof(buf), "interfere_%N_%N_%N-2", bb, a, b);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0);
-
-                       lpp_set_factor_fast(si->lpp, cst, interfere, 1.0);
-                       if(spilla->mem_in != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, spilla->mem_in, -1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spilla->spill, -1.0);
-
-                       ir_snprintf(buf, sizeof(buf), "interfere_%N_%N_%N-3", bb, a, b);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0);
-
-                       lpp_set_factor_fast(si->lpp, cst, interfere, 1.0);
-                       if(spillb->mem_in != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, spillb->mem_in, -1.0);
-                       lpp_set_factor_fast(si->lpp, cst, spillb->spill, -1.0);
-
-
-                       lpp_set_factor_fast(si->lpp, any_interfere_cst, interfere, -1.0);
-
-                       /* any_interfere >= interf */
-                       ir_snprintf(buf, sizeof(buf), "interfere_%N_%N-%N", a, b, bb);
-                       cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0);
-
-                       lpp_set_factor_fast(si->lpp, cst, interfere, 1.0);
-                       lpp_set_factor_fast(si->lpp, cst, any_interfere, -1.0);
-               }
-
-               /* now that we know whether the two values interfere in memory we can drop constraints to enforce copies */
-               gen_copy_constraints(si,a,b,any_interfere);
-       }
-}
-
-
-static inline int
-is_zero(double x)
-{
-       return fabs(x) < 0.00001;
-}
-
-/**
- * node attribute hook for changing colors
- */
-static int mark_remat_nodes_hook(FILE *F, ir_node *n, ir_node *l)
-{
-       spill_ilp_t *si = get_irg_link(current_ir_graph);
-       (void) l;
-
-       if(pset_find_ptr(si->all_possible_remats, n)) {
-               op_t   *op = (op_t*)get_irn_link(n);
-               assert(op && op->is_remat);
-
-               if(!op->attr.remat.remat->inverse) {
-                       if(op->attr.remat.pre) {
-                               ir_fprintf(F, "color:red info3:\"remat value: %+F\"", op->attr.remat.remat->value);
-                       } else {
-                               ir_fprintf(F, "color:orange info3:\"remat2 value: %+F\"", op->attr.remat.remat->value);
-                       }
-
-                       return 1;
-               } else {
-                       op_t   *op = (op_t*)get_irn_link(n);
-                       assert(op && op->is_remat);
-
-                       if(op->attr.remat.pre) {
-                               ir_fprintf(F, "color:cyan info3:\"remat inverse value: %+F\"", op->attr.remat.remat->value);
-                       } else {
-                               ir_fprintf(F, "color:lightcyan info3:\"remat2 inverse value: %+F\"", op->attr.remat.remat->value);
-                       }
-
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-static void
-dump_graph_with_remats(ir_graph * irg, const char * suffix)
-{
-       set_dump_node_vcgattr_hook(mark_remat_nodes_hook);
-       be_dump(irg, suffix, dump_ir_block_graph_sched);
-       set_dump_node_vcgattr_hook(NULL);
-}
-
-/**
- * Edge hook to dump the schedule edges with annotated register pressure.
- */
-static int
-sched_pressure_edge_hook(FILE *F, ir_node *irn)
-{
-       if(sched_is_scheduled(irn) && sched_has_prev(irn)) {
-               ir_node *prev = sched_prev(irn);
-               fprintf(F, "edge:{sourcename:\"");
-               PRINT_NODEID(irn);
-               fprintf(F, "\" targetname:\"");
-               PRINT_NODEID(prev);
-               fprintf(F, "\" label:\"%d", (int)get_irn_link(irn));
-               fprintf(F, "\" color:magenta}\n");
-       }
-       return 1;
-}
-
-static void
-dump_ir_block_graph_sched_pressure(ir_graph *irg, const char *suffix)
-{
-       DUMP_NODE_EDGE_FUNC old_edge_hook = get_dump_node_edge_hook();
-
-       dump_consts_local(0);
-       set_dump_node_edge_hook(sched_pressure_edge_hook);
-       dump_ir_block_graph(irg, suffix);
-       set_dump_node_edge_hook(old_edge_hook);
-}
-
-static void
-walker_pressure_annotator(ir_node * bb, void * data)
-{
-       spill_ilp_t  *si = data;
-       ir_node      *irn;
-       int           n, i;
-       pset         *live = pset_new_ptr_default();
-       int           projs = 0;
-
-       be_lv_foreach(si->lv, bb, be_lv_state_end, i) {
-               irn = be_lv_get_irn(si->lv, bb, i);
-
-               if (has_reg_class(si, irn)) {
-                       pset_insert_ptr(live, irn);
-               }
-       }
-
-       set_irn_link(bb, INT_TO_PTR(pset_count(live)));
-
-       sched_foreach_reverse(bb, irn) {
-               if(is_Phi(irn)) {
-                       set_irn_link(irn, INT_TO_PTR(pset_count(live)));
-                       continue;
-               }
-
-               if(has_reg_class(si, irn)) {
-                       pset_remove_ptr(live, irn);
-                       if(is_Proj(irn)) ++projs;
-               }
-
-               if(!is_Proj(irn)) projs = 0;
-
-               for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                       ir_node    *arg = get_irn_n(irn, n);
-
-                       if(has_reg_class(si, arg)) pset_insert_ptr(live, arg);
-               }
-               set_irn_link(irn, INT_TO_PTR(pset_count(live)+projs));
-       }
-
-       del_pset(live);
-}
-
-static void
-dump_pressure_graph(spill_ilp_t * si, const char *suffix)
-{
-       be_dump(si->birg->irg, suffix, dump_ir_block_graph_sched_pressure);
-}
-
-static void
-connect_all_remats_with_keep(spill_ilp_t * si)
-{
-       ir_node   *irn;
-       ir_node  **ins,
-                        **pos;
-       int        n_remats;
-
-
-       n_remats = pset_count(si->all_possible_remats);
-       if(n_remats) {
-               ins = obstack_alloc(si->obst, n_remats * sizeof(*ins));
-
-               pos = ins;
-               pset_foreach(si->all_possible_remats, irn) {
-                       *pos = irn;
-                       ++pos;
-               }
-
-               si->keep = be_new_Keep(si->cls, si->birg->irg, get_irg_end_block(si->birg->irg), n_remats, ins);
-
-               obstack_free(si->obst, ins);
-       }
-}
-
-static void
-connect_all_spills_with_keep(spill_ilp_t * si)
-{
-       ir_node   *irn;
-       ir_node  **ins,
-                        **pos;
-       int        n_spills;
-       ir_node   *keep;
-
-
-       n_spills = pset_count(si->spills);
-       if(n_spills) {
-               ins = obstack_alloc(si->obst, n_spills * sizeof(*ins));
-
-               pos = ins;
-               pset_foreach(si->spills, irn) {
-                       *pos = irn;
-                       ++pos;
-               }
-
-               keep = be_new_Keep(si->cls, si->birg->irg, get_irg_end_block(si->birg->irg), n_spills, ins);
-
-               obstack_free(si->obst, ins);
-       }
-}
-
-/** insert a spill at an arbitrary position */
-static ir_node *be_spill2(ir_node *irn, ir_node *insert)
-{
-       ir_node  *bl    = is_Block(insert) ? insert : get_nodes_block(insert);
-       ir_graph *irg   = get_irn_irg(bl);
-       ir_node  *frame = get_irg_frame(irg);
-       ir_node  *spill;
-       ir_node  *next;
-       const arch_register_class_t *cls       = arch_get_irn_reg_class_out(irn);
-       const arch_register_class_t *cls_frame = arch_get_irn_reg_class_out(frame);
-
-       spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
-
-       /*
-        * search the right insertion point. a spill of a phi cannot be put
-        * directly after the phi, if there are some phis behind the one which
-        * is spilled. Also, a spill of a Proj must be after all Projs of the
-        * same tuple node.
-        *
-        * Here's one special case:
-        * If the spill is in the start block, the spill must be after the frame
-        * pointer is set up. This is done by setting insert to the end of the block
-        * which is its default initialization (see above).
-        */
-
-       if (bl == get_irg_start_block(irg) && sched_get_time_step(frame) >= sched_get_time_step(insert))
-               insert = frame;
-
-       for (next = sched_next(insert); is_Phi(next) || is_Proj(next); next = sched_next(insert))
-               insert = next;
-
-       sched_add_after(insert, spill);
-       return spill;
-}
-
-static void
-delete_remat(spill_ilp_t * si, ir_node * remat) {
-       int       n;
-       ir_node  *bad = get_irg_bad(si->birg->irg);
-
-       sched_remove(remat);
-
-       /* kill links to operands */
-       for (n=get_irn_arity(remat)-1; n>=-1; --n) {
-               set_irn_n(remat, n, bad);
-       }
-}
-
-static void
-clean_remat_info(spill_ilp_t * si)
-{
-       int            n;
-       remat_t       *remat;
-       remat_info_t  *remat_info;
-       ir_node       *bad = get_irg_bad(si->birg->irg);
-
-       set_foreach(si->remat_info, remat_info) {
-               if(!remat_info->remats) continue;
-
-               pset_foreach(remat_info->remats, remat)
-               {
-                       if(remat->proj && get_irn_n_edges(remat->proj) == 0) {
-                               if(sched_is_scheduled(remat->proj)) {
-                                       sched_remove((ir_node*)remat->proj);
-                               }
-                               set_irn_n((ir_node*)remat->proj, -1, bad);
-                               set_irn_n((ir_node*)remat->proj, 0, bad);
-                       }
-
-                       if(get_irn_n_edges(remat->op) == 0) {
-                               if(sched_is_scheduled(remat->op)) {
-                                       sched_remove((ir_node*)remat->op);
-                               }
-                               for (n=get_irn_arity(remat->op)-1; n>=-1; --n) {
-                                       set_irn_n((ir_node*)remat->op, n, bad);
-                               }
-                       }
-               }
-
-               if(remat_info->remats) del_pset(remat_info->remats);
-               if(remat_info->remats_by_operand) del_pset(remat_info->remats_by_operand);
-       }
-}
-
-static void
-delete_unnecessary_remats(spill_ilp_t * si)
-{
-       if(opt_keep_alive & KEEPALIVE_REMATS) {
-               int       n;
-               ir_node  *bad = get_irg_bad(si->birg->irg);
-
-               if(si->keep) {
-                       for (n=get_irn_arity(si->keep)-1; n>=0; --n) {
-                               ir_node        *keep_arg = get_irn_n(si->keep, n);
-                               op_t           *arg_op = get_irn_link(keep_arg);
-                               lpp_name_t     *name;
-
-                               assert(arg_op->is_remat);
-
-                               name = si->lpp->vars[arg_op->attr.remat.ilp];
-
-                               if(is_zero(name->value)) {
-                                       DBG((si->dbg, LEVEL_3, "\t  deleting remat %+F\n", keep_arg));
-                                       /* TODO check whether reload is preferred over remat (could be bug) */
-                                       delete_remat(si, keep_arg);
-                               } else {
-                                       if(!arg_op->attr.remat.remat->inverse) {
-                                               if(arg_op->attr.remat.pre) {
-                                                       DBG((si->dbg, LEVEL_2, "\t**remat kept: %+F\n", keep_arg));
-                                               } else {
-                                                       DBG((si->dbg, LEVEL_2, "\t%%%%remat2 kept: %+F\n", keep_arg));
-                                               }
-                                       } else {
-                                               if(arg_op->attr.remat.pre) {
-                                                       DBG((si->dbg, LEVEL_2, "\t**INVERSE remat kept: %+F\n", keep_arg));
-                                               } else {
-                                                       DBG((si->dbg, LEVEL_2, "\t%%%%INVERSE remat2 kept: %+F\n", keep_arg));
-                                               }
-                                       }
-                               }
-
-                               set_irn_n(si->keep, n, bad);
-                       }
-               } else {
-                       DBG((si->dbg, LEVEL_2, "\t  no remats to delete (none have been inserted)\n"));
-               }
-       } else {
-               ir_node  *remat;
-
-               pset_foreach(si->all_possible_remats, remat) {
-                       op_t           *remat_op = get_irn_link(remat);
-                       lpp_name_t     *name = si->lpp->vars[remat_op->attr.remat.ilp];
-
-                       if(is_zero(name->value)) {
-                               DBG((si->dbg, LEVEL_3, "\t  deleting remat %+F\n", remat));
-                               /* TODO check whether reload is preferred over remat (could be bug) */
-                               delete_remat(si, remat);
-                       } else {
-                               if(!remat_op->attr.remat.remat->inverse) {
-                                       if(remat_op->attr.remat.pre) {
-                                               DBG((si->dbg, LEVEL_2, "\t**remat kept: %+F\n", remat));
-                                       } else {
-                                               DBG((si->dbg, LEVEL_2, "\t%%%%remat2 kept: %+F\n", remat));
-                                       }
-                               } else {
-                                       if(remat_op->attr.remat.pre) {
-                                               DBG((si->dbg, LEVEL_2, "\t**INVERSE remat kept: %+F\n", remat));
-                                       } else {
-                                               DBG((si->dbg, LEVEL_2, "\t%%%%INVERSE remat2 kept: %+F\n", remat));
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-static pset *
-get_spills_for_value(spill_ilp_t * si, const ir_node * value)
-{
-       pset     *spills = pset_new_ptr_default();
-
-       const ir_node  *next;
-       defs_t         *defs;
-
-       defs = set_find_def(si->values, value);
-
-       if(defs && defs->spills) {
-               for(next = defs->spills; next; next = get_irn_link(next)) {
-                       pset_insert_ptr(spills, next);
-               }
-       }
-
-       return spills;
-}
-
-static ir_node *
-new_r_PhiM_nokeep(ir_graph * irg, ir_node *block, int arity, ir_node **in)
-{
-       ir_node  *res;
-
-       assert( get_irn_arity(block) == arity );
-
-       res = new_ir_node(NULL, irg, block, op_Phi, mode_M, arity, in);
-       res->attr.phi.u.backedge = new_backedge_arr(irg->obst, arity);
-
-       return res;
-}
-
-/**
- * @param before   The node after which the spill will be placed in the schedule
- */
-static ir_node *
-insert_spill(spill_ilp_t * si, ir_node * irn, const ir_node * value, ir_node * before)
-{
-       defs_t   *defs;
-       ir_node  *spill;
-
-       DBG((si->dbg, LEVEL_3, "\t  inserting spill for value %+F after %+F\n", irn, before));
-
-       spill = be_spill2(irn, before);
-
-       defs = set_insert_def(si->values, value);
-       assert(defs);
-
-       /* enter into the linked list */
-       set_irn_link(spill, defs->spills);
-       defs->spills = spill;
-
-       if(opt_keep_alive & KEEPALIVE_SPILLS)
-               pset_insert_ptr(si->spills, spill);
-
-       return spill;
-}
-
-/**
- * @param before   The Phi node which has to be spilled
- */
-static ir_node *
-insert_mem_phi(spill_ilp_t * si, ir_node * phi)
-{
-       ir_node   *mem_phi;
-       ir_node  **ins;
-       defs_t    *defs;
-       int        n;
-
-       NEW_ARR_A(ir_node*, ins, get_irn_arity(phi));
-
-       for(n=get_irn_arity(phi)-1; n>=0; --n) {
-               ins[n] = si->m_unknown;
-       }
-
-       mem_phi =  new_r_PhiM_nokeep(si->birg->irg, get_nodes_block(phi), get_irn_arity(phi), ins);
-
-       defs = set_insert_def(si->values, phi);
-       assert(defs);
-
-       /* enter into the linked list */
-       set_irn_link(mem_phi, defs->spills);
-       defs->spills = mem_phi;
-
-#ifdef SCHEDULE_PHIM
-       sched_add_after(phi, mem_phi);
-#else
-       pset_insert_ptr(si->phims, mem_phi);
-#endif
-
-       if(opt_keep_alive & KEEPALIVE_SPILLS)
-               pset_insert_ptr(si->spills, mem_phi);
-
-
-       return mem_phi;
-}
-
-/**
- * Add remat to list of defs, destroys link field!
- */
-static void
-insert_remat(spill_ilp_t * si, ir_node * remat)
-{
-       defs_t   *defs;
-       op_t     *remat_op = get_irn_link(remat);
-
-       assert(remat_op->is_remat);
-
-       defs = set_insert_def(si->values, remat_op->attr.remat.remat->value);
-       assert(defs);
-
-       /* enter into the linked list */
-       set_irn_link(remat, defs->remats);
-       defs->remats = remat;
-}
-
-
-/**
- * Add reload before operation and add to list of defs
- */
-static ir_node *
-insert_reload(spill_ilp_t * si, const ir_node * value, ir_node * after)
-{
-       defs_t   *defs;
-       ir_node  *reload,
-                        *spill;
-
-       DBG((si->dbg, LEVEL_3, "\t  inserting reload for value %+F before %+F\n", value, after));
-
-       defs = set_find_def(si->values, value);
-
-       spill = defs->spills;
-       assert(spill && "no spill placed before reload");
-
-       reload = be_reload(si->cls, after, get_irn_mode(value), spill);
-
-       /* enter into the linked list */
-       set_irn_link(reload, defs->remats);
-       defs->remats = reload;
-
-       return reload;
-}
-
-void perform_memory_operand(spill_ilp_t * si, memoperand_t * memoperand)
-{
-       defs_t  *defs;
-       ir_node *value = get_irn_n(memoperand->irn, memoperand->pos);
-       ir_node *spill;
-
-       DBG((si->dbg, LEVEL_2, "\t  inserting memory operand for value %+F at %+F\n", value, memoperand->irn));
-
-       defs = set_find_def(si->values, value);
-
-       spill = defs->spills;
-       assert(spill && "no spill placed before reload");
-
-       arch_perform_memory_operand(memoperand->irn, spill, memoperand->pos);
-}
-
-void insert_memoperands(spill_ilp_t * si)
-{
-       memoperand_t   *memoperand;
-       lpp_name_t     *name;
-
-       set_foreach(si->memoperands, memoperand) {
-               name = si->lpp->vars[memoperand->ilp];
-               if(!is_zero(name->value)) {
-                       perform_memory_operand(si, memoperand);
-               }
-       }
-}
-
-static void
-walker_spill_placer(ir_node * bb, void * data) {
-       spill_ilp_t   *si = (spill_ilp_t*)data;
-       ir_node       *irn;
-       spill_bb_t    *spill_bb = get_irn_link(bb);
-       pset          *spills_to_do = pset_new_ptr_default();
-       spill_t       *spill;
-
-       set_foreach(spill_bb->ilp, spill) {
-               lpp_name_t    *name;
-
-               if(is_Phi(spill->irn) && get_nodes_block(spill->irn) == bb) {
-                       name = si->lpp->vars[spill->mem_in];
-                       if(!is_zero(name->value)) {
-                               ir_node   *mem_phi;
-
-                               mem_phi = insert_mem_phi(si, spill->irn);
-
-                               DBG((si->dbg, LEVEL_2, "\t >>spilled Phi %+F -> %+F\n", spill->irn, mem_phi));
-                       }
-               }
-
-               name = si->lpp->vars[spill->spill];
-               if(!is_zero(name->value)) {
-                       /* place spill directly after definition */
-                       if(get_nodes_block(spill->irn) == bb) {
-                               insert_spill(si, spill->irn, spill->irn, spill->irn);
-                               continue;
-                       }
-
-                       /* place spill at bb start */
-                       if(spill->reg_in > 0) {
-                               name = si->lpp->vars[spill->reg_in];
-                               if(!is_zero(name->value)) {
-                                       insert_spill(si, spill->irn, spill->irn, bb);
-                                       continue;
-                               }
-                       }
-                       /* place spill after a remat */
-                       pset_insert_ptr(spills_to_do, spill->irn);
-               }
-       }
-       DBG((si->dbg, LEVEL_3, "\t  %d spills to do in block %+F\n", pset_count(spills_to_do), bb));
-
-
-       for(irn = sched_block_first_nonphi(bb); !sched_is_end(irn); irn = sched_next(irn)) {
-               op_t     *op = get_irn_link(irn);
-
-               if(be_is_Spill(irn)) continue;
-
-               if(op->is_remat) {
-                       /* TODO fix this if we want to support remats with more than two nodes */
-                       if(get_irn_mode(irn) != mode_T && pset_find_ptr(spills_to_do, op->attr.remat.remat->value)) {
-                               pset_remove_ptr(spills_to_do, op->attr.remat.remat->value);
-
-                               insert_spill(si, irn, op->attr.remat.remat->value, irn);
-                       }
-               } else {
-                       if(pset_find_ptr(spills_to_do, irn)) {
-                               pset_remove_ptr(spills_to_do, irn);
-
-                               insert_spill(si, irn, irn, irn);
-                       }
-               }
-
-       }
-
-       assert(pset_count(spills_to_do) == 0);
-
-       /* afterwards free data in block */
-       del_pset(spills_to_do);
-}
-
-static ir_node *
-insert_mem_copy(spill_ilp_t * si, ir_node * bb, ir_node * value)
-{
-       ir_node          *insert_pos = bb;
-       ir_node          *spill;
-
-       /* find last definition of arg value in block */
-       ir_node  *next;
-       defs_t   *defs;
-       int       last = 0;
-
-       defs = set_find_def(si->values, value);
-
-       if(defs && defs->remats) {
-               for(next = defs->remats; next; next = get_irn_link(next)) {
-                       if(get_nodes_block(next) == bb && sched_get_time_step(next) > last) {
-                               last = sched_get_time_step(next);
-                               insert_pos = next;
-                       }
-               }
-       }
-
-       if(get_nodes_block(value) == bb && sched_get_time_step(value) > last) {
-               last = sched_get_time_step(value);
-               insert_pos = value;
-       }
-
-       DBG((si->dbg, LEVEL_2, "\t  inserting mem copy for value %+F after %+F\n", value, insert_pos));
-
-       spill = be_spill2(is_Block(insert_pos)?value:insert_pos, insert_pos);
-
-       return spill;
-}
-
-static void
-phim_fixer(spill_ilp_t *si) {
-       defs_t  *defs;
-
-       set_foreach(si->values, defs) {
-               const ir_node  *phi = defs->value;
-               op_t           *op = get_irn_link(phi);
-               ir_node        *phi_m = NULL;
-               ir_node        *next = defs->spills;
-               int             n;
-
-               if(!is_Phi(phi)) continue;
-
-               while(next) {
-                       if(is_Phi(next) && get_irn_mode(next) == mode_M) {
-                               phi_m = next;
-                               break;
-                       } else {
-                               next = get_irn_link(next);
-                       }
-               }
-               if(!phi_m) continue;
-
-               for(n=get_irn_arity(phi)-1; n>=0; --n) {
-                       ir_node        *value = get_irn_n(phi, n);
-                       defs_t         *val_defs = set_find_def(si->values, value);
-
-                       /* a spill of this value */
-                       ir_node      *spill;
-
-
-                       if(opt_memcopies) {
-                               ir_node    *pred = get_Block_cfgpred_block(get_nodes_block(phi), n);
-                               lpp_name_t *name = si->lpp->vars[op->attr.live_range.args.copies[n]];
-
-                               if(!is_zero(name->value)) {
-                                       spill = insert_mem_copy(si, pred, value);
-                               } else {
-                                       spill = val_defs->spills;
-                               }
-                       } else {
-                               spill = val_defs->spills;
-                       }
-
-                       assert(spill && "no spill placed before PhiM");
-                       set_irn_n(phi_m, n, spill);
-               }
-       }
-}
-
-static void
-walker_reload_placer(ir_node * bb, void * data) {
-       spill_ilp_t   *si = (spill_ilp_t*)data;
-       ir_node       *irn;
-       spill_bb_t    *spill_bb = get_irn_link(bb);
-
-       /* reloads at end of block */
-       if(spill_bb->reloads) {
-               keyval_t    *keyval;
-
-               set_foreach(spill_bb->reloads, keyval) {
-                       ir_node        *irn = (ir_node*)keyval->key;
-                       ilp_var_t       reload = PTR_TO_INT(keyval->val);
-                       lpp_name_t     *name;
-
-                       name = si->lpp->vars[reload];
-                       if(!is_zero(name->value)) {
-                               ir_node    *reload;
-                               ir_node    *insert_pos = bb;
-                               ir_node    *prev = sched_block_last_noncf(bb);
-                               op_t       *prev_op = get_irn_link(prev);
-
-                               while(be_is_Spill(prev)) {
-                                       prev = sched_prev(prev);
-                               }
-
-                               prev_op = get_irn_link(prev);
-
-                               /* insert reload before pre-remats */
-                               while(!sched_is_end(prev) && !be_is_Reload(prev) && !is_Phi(prev)
-                                               && prev_op->is_remat && prev_op->attr.remat.pre) {
-                                       insert_pos = prev;
-
-                                       do {
-                                               prev = sched_prev(prev);
-                                       } while(be_is_Spill(prev));
-
-                                       prev_op = get_irn_link(prev);
-
-                               }
-
-                               reload = insert_reload(si, irn, insert_pos);
-
-                               if(opt_keep_alive & KEEPALIVE_RELOADS)
-                                       pset_insert_ptr(si->spills, reload);
-                       }
-               }
-       }
-
-       /* walk and insert more reloads and collect remats */
-       sched_foreach_reverse(bb, irn) {
-               op_t     *op = get_irn_link(irn);
-
-               if(be_is_Reload(irn) || be_is_Spill(irn)) continue;
-               if(is_Phi(irn)) break;
-
-               if(op->is_remat) {
-                       if(get_irn_mode(irn) != mode_T) {
-                               insert_remat(si, irn);
-                       }
-               } else {
-                       int    n;
-
-                       for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                               ir_node    *arg = get_irn_n(irn, n);
-
-                               if(op->attr.live_range.args.reloads && op->attr.live_range.args.reloads[n] != ILP_UNDEF) {
-                                       lpp_name_t    *name;
-
-                                       name = si->lpp->vars[op->attr.live_range.args.reloads[n]];
-                                       if(!is_zero(name->value)) {
-                                               ir_node    *reload;
-                                               ir_node    *insert_pos = irn;
-                                               ir_node    *prev = sched_prev(insert_pos);
-                                               op_t       *prev_op;
-
-                                               while(be_is_Spill(prev)) {
-                                                       prev = sched_prev(prev);
-                                               }
-
-                                               prev_op = get_irn_link(prev);
-
-                                               /* insert reload before pre-remats */
-                                               while(!sched_is_end(prev) && !be_is_Reload(prev) && !is_Phi(prev)
-                                                               && prev_op->is_remat && prev_op->attr.remat.pre) {
-                                                       insert_pos = prev;
-
-                                                       do {
-                                                               prev = sched_prev(prev);
-                                                       } while(be_is_Spill(prev));
-
-                                                       prev_op = get_irn_link(prev);
-
-                                               }
-
-                                               reload = insert_reload(si, arg, insert_pos);
-
-                                               assert(reload && "no reload returned");
-                                               set_irn_n(irn, n, reload);
-
-                                               if(opt_keep_alive & KEEPALIVE_RELOADS)
-                                                       pset_insert_ptr(si->spills, reload);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       del_set(spill_bb->ilp);
-       if(spill_bb->reloads) del_set(spill_bb->reloads);
-}
-
-static void
-walker_collect_used(ir_node * irn, void * data)
-{
-       bitset_t   *used = data;
-
-       bitset_set(used, get_irn_idx(irn));
-}
-
-struct kill_helper {
-       bitset_t  *used;
-       spill_ilp_t  *si;
-};
-
-static void
-walker_kill_unused(ir_node * bb, void * data)
-{
-       struct kill_helper *kh = data;
-       ir_node            *bad = get_irg_bad(get_irn_irg(bb));
-       ir_node            *irn;
-
-
-       for(irn=sched_first(bb); !sched_is_end(irn);) {
-               ir_node     *next = sched_next(irn);
-               int          n;
-
-               if(!bitset_is_set(kh->used, get_irn_idx(irn))) {
-                       if(be_is_Spill(irn) || be_is_Reload(irn)) {
-                               DBG((kh->si->dbg, LEVEL_1, "\t SUBOPTIMAL! %+F IS UNUSED (cost: %g)\n", irn, get_cost(irn) * execution_frequency(kh->si, bb)));
-#if 0
-                               assert(lpp_get_sol_state(kh->si->lpp) != lpp_optimal && "optimal solution is suboptimal?");
-#endif
-                       }
-
-                       sched_remove(irn);
-
-                       set_nodes_block(irn, bad);
-                       for (n=get_irn_arity(irn)-1; n>=0; --n) {
-                               set_irn_n(irn, n, bad);
-                       }
-               }
-               irn = next;
-       }
-}
-
-#ifndef SCHEDULE_PHIM
-static void
-kill_unused_phims(spill_ilp_t * si, struct kill_helper * kh)
-{
-       ir_node  *phi;
-       ir_node  *bad = get_irg_bad(si->birg->irg);
-       int       n;
-
-       pset_foreach(si->phims, phi) {
-               if(!bitset_is_set(kh->used, get_irn_idx(phi))) {
-
-                       set_nodes_block(phi, bad);
-                       for (n=get_irn_arity(phi)-1; n>=0; --n) {
-                               set_irn_n(phi, n, bad);
-                       }
-               }
-       }
-}
-#endif
-
-static void
-kill_all_unused_values_in_schedule(spill_ilp_t * si)
-{
-       struct kill_helper  kh;
-
-       kh.used = bitset_malloc(get_irg_last_idx(si->birg->irg));
-       kh.si = si;
-
-       irg_walk_graph(si->birg->irg, walker_collect_used, NULL, kh.used);
-#ifndef SCHEDULE_PHIM
-       kill_unused_phims(si, &kh);
-#endif
-       irg_block_walk_graph(si->birg->irg, walker_kill_unused, NULL, &kh);
-
-       bitset_free(kh.used);
-}
-
-void
-print_irn_pset(pset * p)
-{
-       ir_node   *irn;
-
-       pset_foreach(p, irn) {
-               ir_printf("%+F\n", irn);
-       }
-}
-
-void
-dump_phi_class(spill_ilp_t *si, ir_node **phiclass, const char * file)
-{
-    FILE           *f = fopen(file, "w");
-    ir_node        *irn;
-    interference_t *interference;
-    int            i;
-
-    set_break(si->interferences);
-
-    ir_fprintf(f, "digraph phiclass {\n");
-
-    for (i = ARR_LEN(phiclass) - 1; i >= 0; --i) {
-        irn = phiclass[i];
-        if (is_Phi(irn))
-            ir_fprintf(f, "  %F%N [shape=box]\n", irn, irn);
-    }
-
-    for (i = ARR_LEN(phiclass) - 1; i >= 0; --i) {
-        int n;
-
-        irn = phiclass[i];
-        if (! is_Phi(irn))
-            continue;
-
-        for (n = get_irn_arity(irn) - 1; n >= 0; --n) {
-            ir_node  *arg = get_irn_n(irn, n);
-
-            ir_fprintf(f, "  %F%N -> %F%N\n", irn, irn, arg, arg);
-        }
-    }
-
-    set_foreach(si->interferences, interference) {
-        const ir_node *a = interference->a;
-        const ir_node *b = interference->b;
-        if (get_phi_class(si->pc, (ir_node *)a) == phiclass) {
-            ir_fprintf(f, "  %F%N -> %F%N [color=red,dir=none,style=bold]\n", a, a, b, b);
-        }
-    }
-
-    ir_fprintf(f, "}");
-    fclose(f);
-}
-
-static void
-rewire_uses(spill_ilp_t * si)
-{
-       defs_t               *defs;
-       ir_nodeset_t         ignore;
-
-       ir_nodeset_init(&ignore);
-       ir_nodeset_insert(&ignore, get_irg_end(si->birg->irg));
-
-       /* then fix uses of spills */
-       set_foreach(si->values, defs) {
-               pset           *reloads;
-               pset           *spills;
-               const ir_node  *next = defs->remats;
-               int remats = 0;
-
-               reloads = pset_new_ptr_default();
-
-               while(next) {
-                       if(be_is_Reload(next)) {
-                               pset_insert_ptr(reloads, next);
-                       } else {
-                               ++remats;
-                       }
-                       next = get_irn_link(next);
-               }
-
-               spills = get_spills_for_value(si, defs->value);
-               DBG((si->dbg, LEVEL_2, "\t  %d remats, %d reloads, and %d spills for value %+F\n", remats, pset_count(reloads), pset_count(spills), defs->value));
-               if(pset_count(spills) > 1) {
-                       be_ssa_construction_env_t senv;
-                       ir_node *node;
-                       //assert(pset_count(reloads) > 0);
-                       //                              print_irn_pset(spills);
-                       //                              print_irn_pset(reloads);
-
-                       be_ssa_construction_init(&senv, si->birg);
-                       be_ssa_construction_set_ignore_uses(&senv, &ignore);
-                       pset_foreach(spills, node) {
-                               be_ssa_construction_add_copy(&senv, node);
-                       }
-                       pset_foreach(spills, node) {
-                               be_ssa_construction_fix_users(&senv, node);
-                       }
-                       be_ssa_construction_update_liveness_phis(&senv, si->lv);
-                       pset_foreach(spills, node) {
-                               be_liveness_update(si->lv, node);
-                       }
-                       be_ssa_construction_destroy(&senv);
-               }
-
-               del_pset(reloads);
-               del_pset(spills);
-       }
-
-       /* first fix uses of remats and reloads */
-       set_foreach(si->values, defs) {
-               const ir_node  *next = defs->remats;
-               int             orig_kept = 0;
-
-               if(next) {
-                       be_ssa_construction_env_t senv;
-
-                       be_ssa_construction_init(&senv, si->birg);
-
-                       if(sched_is_scheduled(defs->value)) {
-                               be_ssa_construction_add_copy(&senv, (ir_node*) defs->value);
-                               orig_kept = 1;
-                       }
-
-                       next = defs->remats;
-                       while(next) {
-                               be_ssa_construction_add_copy(&senv, (ir_node*) next);
-                               next = get_irn_link(next);
-                       }
-
-                       if(sched_is_scheduled(defs->value)) {
-                               be_ssa_construction_fix_users(&senv, (ir_node*) defs->value);
-                       }
-
-                       next = defs->remats;
-                       while(next) {
-                               be_ssa_construction_fix_users(&senv, (ir_node*) next);
-                               next = get_irn_link(next);
-                       }
-
-                       be_ssa_construction_update_liveness_phis(&senv, si->lv);
-                       if(sched_is_scheduled(defs->value)) {
-                               be_liveness_update(si->lv, (ir_node*) defs->value);
-                       }
-
-                       next = defs->remats;
-                       while(next) {
-                               be_liveness_update(si->lv, (ir_node*) next);
-                               next = get_irn_link(next);
-                       }
-
-                       be_ssa_construction_destroy(&senv);
-               }
-       }
-
-       ir_nodeset_destroy(&ignore);
-//     remove_unused_defs(si);
-}
-
-
-static void
-writeback_results(spill_ilp_t * si)
-{
-       /* walk through the graph and collect all spills, reloads and remats for a value */
-
-       si->values = new_set(cmp_defs, 4096);
-
-       DBG((si->dbg, LEVEL_1, "Applying results\n"));
-       delete_unnecessary_remats(si);
-       si->m_unknown = new_r_Unknown(si->birg->irg, mode_M);
-       irg_block_walk_graph(si->birg->irg, walker_spill_placer, NULL, si);
-       irg_block_walk_graph(si->birg->irg, walker_reload_placer, NULL, si);
-       if(opt_memoperands)
-               insert_memoperands(si);
-       phim_fixer(si);
-
-       /* clean the remat info! there are still back-edges leading there! */
-       clean_remat_info(si);
-
-       rewire_uses(si);
-
-       connect_all_spills_with_keep(si);
-
-       del_set(si->values);
-}
-
-static int
-get_n_regs(spill_ilp_t * si)
-{
-       int       arch_n_regs = arch_register_class_n_regs(si->cls);
-
-       bitset_t *arch_regs = bitset_malloc(arch_n_regs);
-       bitset_t *abi_regs = bitset_malloc(arch_n_regs);
-
-       arch_put_non_ignore_regs(si->cls, arch_regs);
-       be_abi_put_ignore_regs(si->birg->abi, si->cls, abi_regs);
-
-       bitset_andnot(arch_regs, abi_regs);
-       arch_n_regs = bitset_popcnt(arch_regs);
-
-       bitset_free(arch_regs);
-       bitset_free(abi_regs);
-
-       DBG((si->dbg, LEVEL_1, "\tArchitecture has %d free registers in class %s\n", arch_n_regs, si->cls->name));
-       return arch_n_regs;
-}
-
-static void
-walker_reload_mover(ir_node * bb, void * data)
-{
-       spill_ilp_t   *si = data;
-       ir_node           *tmp;
-
-       sched_foreach(bb, tmp) {
-               if(be_is_Reload(tmp) && has_reg_class(si, tmp)) {
-                       ir_node       *reload = tmp;
-                       ir_node       *irn = tmp;
-
-                       /* move reload upwards */
-
-                       int pressure = (int)get_irn_link(reload);
-                       if(pressure < si->n_regs) {
-                               irn = sched_prev(reload);
-                               DBG((si->dbg, LEVEL_5, "regpressure before %+F: %d\n", reload, pressure));
-                               sched_remove(reload);
-                               pressure = (int)get_irn_link(irn);
-
-                               while(pressure < si->n_regs) {
-                                       if( sched_is_end(irn) ||
-                                          (be_is_Reload(irn) && has_reg_class(si, irn)) ||
-                                          /* do not move reload before its spill */
-                                          (irn == be_get_Reload_mem(reload)) ||
-                                          /* do not move before phi */
-                                          is_Phi(irn)) break;
-
-                                       set_irn_link(irn, INT_TO_PTR(pressure+1));
-                                       DBG((si->dbg, LEVEL_5, "new regpressure before %+F: %d\n", irn, pressure+1));
-                                       irn = sched_prev(irn);
-
-                                       pressure = (int)get_irn_link(irn);
-                               }
-
-                               DBG((si->dbg, LEVEL_3, "putting reload %+F after %+F\n", reload, irn));
-                               sched_put_after(irn, reload);
-                       }
-               }
-       }
-}
-
-static void
-move_reloads_upward(spill_ilp_t * si)
-{
-       irg_block_walk_graph(si->birg->irg, walker_reload_mover, NULL, si);
-}
-
-
-/**
- * Walk all irg blocks and check for interfering spills inside of phi classes
- */
-static void
-luke_meminterferencechecker(ir_node * bb, void * data)
-{
-       spill_ilp_t *si = (spill_ilp_t*)data;
-       int         l1, l2;
-
-       be_lv_foreach(si->lv, bb, be_lv_state_end | be_lv_state_out | be_lv_state_in, l1) {
-               ir_node        *a = be_lv_get_irn(si->lv, bb, l1);
-
-               if (! be_is_Spill(a) && (!is_Phi(a) || get_irn_mode(a) != mode_T))
-                       continue;
-
-               /* a is only interesting if it is in my register class and if it is inside a phi class */
-               if (has_reg_class(si, a) && get_phi_class(si->pc, a)) {
-                       for (l2 = _be_lv_next_irn(si->lv, bb, 0xff, l1 + 1); l2 >= 0; l2 = _be_lv_next_irn(si->lv, bb, 0xff, l2 + 1)) {
-                               ir_node *b = be_lv_get_irn(si->lv, bb, l2);
-
-                               if (! be_is_Spill(b) && (! is_Phi(b) || get_irn_mode(b) != mode_T))
-                                       continue;
-
-                               /* a and b are only interesting if they are in the same phi class */
-                               if (has_reg_class(si, b) && get_phi_class(si->pc, a) == get_phi_class(si->pc, b)) {
-                                       if (values_interfere_in_block(si, bb, a, b)) {
-                                               ir_fprintf(stderr, "$$ Spills interfere in %+F: %+F, %+F \t$$\n", bb, a, b);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-static void
-verify_phiclasses(spill_ilp_t * si)
-{
-       /* analyze phi classes */
-       phi_class_free(si->pc);
-       si->pc = phi_class_new_from_irg(si->birg->irg, 0);
-
-       DBG((si->dbg, LEVEL_2, "\t calling memory interference checker\n"));
-       irg_block_walk_graph(si->birg->irg, luke_meminterferencechecker, NULL, si);
-}
-
-void
-be_spill_remat(be_irg_t *birg, const arch_register_class_t *cls)
-{
-       char            buf[256];
-       char            problem_name[256];
-       char            dump_suffix[256];
-       char            dump_suffix2[256];
-       struct obstack  obst;
-       spill_ilp_t     si;
-       ir_graph       *irg = be_get_birg_irg(birg);
-
-       ir_snprintf(problem_name, sizeof(problem_name), "%F_%s", irg, cls->name);
-       ir_snprintf(dump_suffix, sizeof(dump_suffix), "-%s-remats", cls->name);
-       ir_snprintf(dump_suffix2, sizeof(dump_suffix2), "-%s-pressure", cls->name);
-
-       FIRM_DBG_REGISTER(si.dbg, "firm.be.ra.spillremat");
-       DBG((si.dbg, LEVEL_1, "\n\n\t\t===== Processing %s =====\n\n", problem_name));
-
-       if(opt_verify & VERIFY_DOMINANCE)
-               be_check_dominance(irg);
-
-       be_assure_liveness(birg);
-
-       obstack_init(&obst);
-       si.obst                = &obst;
-       si.birg                = birg;
-       si.cls                 = cls;
-       si.lpp                 = new_lpp(problem_name, lpp_minimize);
-       si.remat_info          = new_set(cmp_remat_info, 4096);
-       si.interferences       = new_set(cmp_interference, 32);
-       si.memoperands         = new_set(cmp_memoperands, 128);
-       si.all_possible_remats = pset_new_ptr_default();
-       si.spills              = pset_new_ptr_default();
-       si.inverse_ops         = pset_new_ptr_default();
-       si.lv                  = birg->lv;
-       si.keep                = NULL;
-       si.n_regs              = get_n_regs(&si);
-
-       set_irg_link(irg, &si);
-       compute_doms(irg);
-
-       /* compute phi classes */
-       // phi_class_compute(irg);
-
-       if(opt_dump_flags & DUMP_STATS)
-               be_analyze_regpressure(birg, cls, "-pre");
-
-       DBG((si.dbg, LEVEL_2, "\t initializing\n"));
-       irg_block_walk_graph(irg, luke_initializer, NULL, &si);
-
-       if(opt_remats) {
-               /* collect remats */
-               DBG((si.dbg, LEVEL_1, "Collecting remats\n"));
-               irg_walk_graph(irg, walker_remat_collector, NULL, &si);
-       }
-
-       /* insert possible remats */
-       DBG((si.dbg, LEVEL_1, "Inserting possible remats\n"));
-       irg_block_walk_graph(irg, walker_remat_insertor, NULL, &si);
-       DBG((si.dbg, LEVEL_2, " -> inserted %d possible remats\n", pset_count(si.all_possible_remats)));
-
-       if(opt_keep_alive & KEEPALIVE_REMATS) {
-               DBG((si.dbg, LEVEL_1, "Connecting remats with keep and dumping\n"));
-               connect_all_remats_with_keep(&si);
-               /* dump graph with inserted remats */
-               dump_graph_with_remats(irg, dump_suffix);
-       }
-
-       /* insert copies for phi arguments not in my regclass */
-       irg_walk_graph(irg, walker_regclass_copy_insertor, NULL, &si);
-
-       /* recompute liveness */
-       DBG((si.dbg, LEVEL_1, "Recomputing liveness\n"));
-       be_liveness_recompute(si.lv);
-
-       /* build the ILP */
-       DBG((si.dbg, LEVEL_1, "\tBuilding ILP\n"));
-       DBG((si.dbg, LEVEL_2, "\t endwalker\n"));
-       irg_block_walk_graph(irg, luke_endwalker, NULL, &si);
-
-       DBG((si.dbg, LEVEL_2, "\t blockwalker\n"));
-       irg_block_walk_graph(irg, luke_blockwalker, NULL, &si);
-
-       si.pc = phi_class_new_from_irg(birg->irg, 0);
-       if (opt_memcopies) {
-               DBG((si.dbg, LEVEL_2, "\t memcopyhandler\n"));
-               memcopyhandler(&si);
-       }
-
-       if (opt_dump_flags & DUMP_PROBLEM) {
-               FILE           *f;
-               ir_snprintf(buf, sizeof(buf), "%s-spillremat.ilp", problem_name);
-               if ((f = fopen(buf, "wt")) != NULL) {
-                       lpp_dump_plain(si.lpp, f);
-                       fclose(f);
-               }
-       }
-
-       if (opt_dump_flags & DUMP_MPS) {
-               FILE *f;
-
-               ir_snprintf(buf, sizeof(buf), "%s-spillremat.mps", problem_name);
-               if ((f = fopen(buf, "wt")) != NULL) {
-                       mps_write_mps(si.lpp, s_mps_fixed, f);
-                       fclose(f);
-               }
-
-               ir_snprintf(buf, sizeof(buf), "%s-spillremat.mst", problem_name);
-               if ((f = fopen(buf, "wt")) != NULL) {
-                       mps_write_mst(si.lpp, s_mps_fixed, f);
-                       fclose(f);
-               }
-       }
-
-       lpp_check_startvals(si.lpp);
-
-#ifdef SOLVE
-       DBG((si.dbg, LEVEL_1, "\tSolving %s (%d variables, %d constraints)\n", problem_name, si.lpp->var_next, si.lpp->cst_next));
-       lpp_set_time_limit(si.lpp, opt_timeout);
-
-       if(opt_log)
-               lpp_set_log(si.lpp, stdout);
-
-#ifdef SOLVE_LOCAL
-       lpp_solve_cplex(si.lpp);
-#else
-       lpp_solve_net(si.lpp, LPP_SERVER, LPP_SOLVER);
-#endif
-       assert(lpp_is_sol_valid(si.lpp)
-              && "solution of ILP must be valid");
-
-       DBG((si.dbg, LEVEL_1, "\t%s: iterations: %d, solution time: %g, objective function: %g, best bound: %g\n", problem_name, si.lpp->iterations, si.lpp->sol_time, is_zero(si.lpp->objval)?0.0:si.lpp->objval, is_zero(si.lpp->best_bound)?0.0:si.lpp->best_bound));
-
-       if(opt_dump_flags & DUMP_SOLUTION) {
-               FILE           *f;
-               char            buf[256];
-
-               ir_snprintf(buf, sizeof(buf), "%s-spillremat.sol", problem_name);
-               if ((f = fopen(buf, "wt")) != NULL) {
-                       int             i;
-                       for (i = 0; i < si.lpp->var_next; ++i) {
-                               lpp_name_t     *name = si.lpp->vars[i];
-                               fprintf(f, "%20s %4d %10f\n", name->name, name->nr, name->value);
-                       }
-                       fclose(f);
-               }
-       }
-
-#ifndef SCHEDULE_PHIM
-       si.phims = pset_new_ptr_default();
-#endif
-       writeback_results(&si);
-
-
-#endif                         /* SOLVE */
-
-       kill_all_unused_values_in_schedule(&si);
-
-#if !defined(SCHEDULE_PHIM) && defined(SOLVE)
-       del_pset(si.phims);
-#endif
-
-       if(opt_keep_alive & (KEEPALIVE_SPILLS | KEEPALIVE_RELOADS))
-               be_dump(irg, "-spills-placed", dump_ir_block_graph);
-
-       // move reloads upwards
-       be_liveness_recompute(si.lv);
-       irg_block_walk_graph(irg, walker_pressure_annotator, NULL, &si);
-       move_reloads_upward(&si);
-
-       if(opt_memcopies) {
-               verify_phiclasses(&si);
-       }
-
-       irg_block_walk_graph(irg, walker_pressure_annotator, NULL, &si);
-
-       if(opt_dump_flags & DUMP_PRESSURE)
-               dump_pressure_graph(&si, dump_suffix2);
-
-       if(opt_dump_flags & DUMP_STATS)
-               be_analyze_regpressure(birg, cls, "-post");
-
-       if(opt_verify & VERIFY_DOMINANCE)
-               be_check_dominance(irg);
-
-       free_dom(irg);
-       del_set(si.interferences);
-       del_pset(si.inverse_ops);
-       del_pset(si.all_possible_remats);
-       del_set(si.memoperands);
-       del_pset(si.spills);
-       free_lpp(si.lpp);
-       phi_class_free(si.pc);
-       obstack_free(&obst, NULL);
-       DBG((si.dbg, LEVEL_1, "\tdone.\n"));
-}
-
-void be_init_spillremat(void)
-{
-       static be_spiller_t remat_spiller = {
-               be_spill_remat
-       };
-       lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
-       lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
-       lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
-       lc_opt_entry_t *remat_grp = lc_opt_get_grp(chordal_grp, "remat");
-
-       be_register_spiller("remat", &remat_spiller);
-       lc_opt_add_table(remat_grp, options);
-}
-
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillremat);
-
-#else                          /* WITH_ILP */
-
-static __attribute__((unused))
-void only_that_you_can_compile_without_WITH_ILP_defined(void)
-{
-}
-
-#endif                         /* WITH_ILP */
diff --git a/ir/be/bespillremat.h b/ir/be/bespillremat.h
deleted file mode 100644 (file)
index 1d3d53a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 1995-2008 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       ILP based spilling & rematerialization
- * @author      Adam M. Szalkowski
- * @date        06.04.2006
- * @version     $Id$
- */
-#ifndef FIRM_BE_BESPILLREMAT_H
-#define FIRM_BE_BESPILLREMAT_H
-
-#include "bearch.h"
-#include "beirg.h"
-
-void be_spill_remat(be_irg_t *birg, const arch_register_class_t *cls);
-
-#endif /* FIRM_BE_BESPILLREMAT_H */
index d1b4bd2..db7ddc7 100644 (file)
@@ -131,13 +131,15 @@ static void insert_all_perms_walker(ir_node *bl, void *data) {
                 * register class by construction.
                 */
                for(phi = get_irn_link(bl); phi; phi = get_irn_link(phi)) {
-                       ir_node     *arg  = get_irn_n(phi, i);
-                       unsigned     hash = hash_irn(arg);
-                       perm_proj_t  templ;
+                       ir_node                   *arg = get_irn_n(phi, i);
+                       const arch_register_req_t *req = arch_get_register_req_out(arg);
+                       unsigned                   hash;
+                       perm_proj_t                templ;
 
-                       if (arch_irn_is(arg, ignore))
+                       if (req->type & arch_register_req_type_ignore)
                                continue;
 
+                       hash = hash_irn(arg);
                        templ.arg  = arg;
                        pp         = set_find(arg_set, &templ, sizeof(templ), hash);
 
@@ -242,13 +244,17 @@ static void       set_regs_or_place_dupls_walker(ir_node *bl, void *data) {
 
                /* process all arguments of the phi */
                for (i = 0, max = get_irn_arity(phi); i < max; ++i) {
-                       ir_node               *arg       = get_irn_n(phi, i);
-                       ir_node               *arg_block = get_Block_cfgpred_block(phi_block, i);
-                       const arch_register_t *arg_reg   = get_reg(arg);
+                       ir_node                   *arg = get_irn_n(phi, i);
+                       const arch_register_req_t *req = arch_get_register_req_out(arg);
+                       const arch_register_t     *arg_reg;
+                       ir_node                   *arg_block;
 
-                       if (arch_irn_is(arg, ignore))
+                       if (req->type & arch_register_req_type_ignore)
                                continue;
 
+                       arg_block = get_Block_cfgpred_block(phi_block, i);
+                       arg_reg   = get_reg(arg);
+
                        assert(arg_reg && "Register must be set while placing perms");
 
                        DBG((dbg, LEVEL_1, "  for %+F(%s) -- %+F(%s)\n", phi, phi_reg->name, arg, arg_reg->name));
@@ -420,9 +426,10 @@ static void ssa_destruction_check_walker(ir_node *bl, void *data) {
                phi_reg = get_reg(phi);
                /* iterate over all args of phi */
                for (i = 0, max = get_irn_arity(phi); i < max; ++i) {
-                       ir_node *arg = get_irn_n(phi, i);
+                       ir_node                   *arg = get_irn_n(phi, i);
+                       const arch_register_req_t *req = arch_get_register_req_out(arg);
 
-                       if (arch_irn_is(arg, ignore))
+                       if (req->type & arch_register_req_type_ignore)
                                continue;
 
                        arg_reg = get_reg(arg);
index 7adc54b..28e336e 100644 (file)
@@ -597,7 +597,6 @@ void be_assure_state(be_irg_t *birg, const arch_register_t *reg, void *func_env,
                len = ARR_LEN(phis);
                for(i = 0; i < len; ++i) {
                        ir_node *phi = phis[i];
-                       be_set_phi_flags(phi, arch_irn_flags_ignore);
                        arch_set_irn_register(phi, env.reg);
                }
                be_ssa_construction_destroy(&senv);
index 7e18c11..c49be92 100644 (file)
@@ -284,31 +284,28 @@ static void verify_schedule_walker(ir_node *block, void *data) {
 
 static int should_be_scheduled(ir_node *node)
 {
-       if(is_Block(node))
-               return -1;
-
-       if(is_Proj(node))
-               return 0;
-
-       if(get_irn_mode(node) == mode_M) {
-               if(is_Phi(node) || is_Sync(node) || is_Pin(node))
-                       return 0;
-       }
-       if(be_is_Keep(node) && get_irn_opcode(get_nodes_block(node)) == iro_Bad)
-               return 0;
-
        switch(get_irn_opcode(node)) {
+       case iro_Bad:
+       case iro_Block:
        case iro_End:
        case iro_NoMem:
-       case iro_Bad:
+       case iro_Pin:
+       case iro_Proj:
+       case iro_Sync:
        case iro_Unknown:
                return 0;
+       case iro_Phi:
+               if (get_irn_mode(node) == mode_M)
+                       return 0;
+               break;
        default:
                break;
        }
 
-       if (arch_irn_get_flags(node) & arch_irn_flags_ignore)
-               return -1;
+       if (get_irn_mode(node) != mode_T) {
+               if (arch_irn_is_ignore(node))
+                       return -1;
+       }
 
        return 1;
 }
@@ -771,7 +768,7 @@ static void value_used(ir_node *node) {
                return;
 
        reg = arch_get_irn_register(node);
-       if (reg->type & arch_register_type_virtual)
+       if (reg == NULL || reg->type & arch_register_type_virtual)
                return;
 
        reg_node = registers[reg->index];
@@ -794,7 +791,7 @@ static void value_def(ir_node *node)
                return;
 
        reg = arch_get_irn_register(node);
-       if (reg->type & arch_register_type_virtual)
+       if (reg == NULL || reg->type & arch_register_type_virtual)
                return;
 
        reg_node = registers[reg->index];
index 9e65fdb..e7ad570 100644 (file)
@@ -249,55 +249,9 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const ir_node *node,
        }
 
        /* unknowns should be transformed already */
-       assert(!is_Unknown(node));
        return arch_no_register_req;
 }
 
-static void ia32_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       int    pos = 0;
-
-       if (get_irn_mode(irn) == mode_X) {
-               return;
-       }
-
-       if (is_Proj(irn)) {
-               pos = get_Proj_proj(irn);
-               irn = skip_Proj(irn);
-       }
-
-       if (is_ia32_irn(irn)) {
-               const arch_register_t **slots;
-
-               slots      = get_ia32_slots(irn);
-               slots[pos] = reg;
-       } else {
-               ia32_set_firm_reg(irn, reg, cur_reg_set);
-       }
-}
-
-static const arch_register_t *ia32_get_irn_reg(const ir_node *irn)
-{
-       int pos = 0;
-
-       if (is_Proj(irn)) {
-               if (get_irn_mode(irn) == mode_X) {
-                       return NULL;
-               }
-
-               pos = get_Proj_proj(irn);
-               irn = skip_Proj_const(irn);
-       }
-
-       if (is_ia32_irn(irn)) {
-               const arch_register_t **slots = get_ia32_slots(irn);
-               assert(pos < get_ia32_n_res(irn));
-               return slots[pos];
-       } else {
-               return ia32_get_firm_reg(irn, cur_reg_set);
-       }
-}
-
 static arch_irn_class_t ia32_classify(const ir_node *irn) {
        arch_irn_class_t classification = 0;
 
@@ -321,29 +275,6 @@ static arch_irn_class_t ia32_classify(const ir_node *irn) {
        return classification;
 }
 
-static arch_irn_flags_t ia32_get_flags(const ir_node *irn) {
-       arch_irn_flags_t flags = arch_irn_flags_none;
-
-       if (is_Unknown(irn))
-               return arch_irn_flags_ignore;
-
-       if(is_Proj(irn) && mode_is_datab(get_irn_mode(irn))) {
-               ir_node *pred = get_Proj_pred(irn);
-
-               if(is_ia32_irn(pred)) {
-                       flags = get_ia32_out_flags(pred, get_Proj_proj(irn));
-               }
-
-               irn = pred;
-       }
-
-       if (is_ia32_irn(irn)) {
-               flags |= get_ia32_flags(irn);
-       }
-
-       return flags;
-}
-
 /**
  * The IA32 ABI callback object.
  */
@@ -412,15 +343,16 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap
        const arch_env_t *arch_env = env->aenv;
 
        if (! env->flags.try_omit_fp) {
-               ir_graph *irg     =env->irg;
+               ir_graph *irg     = env->irg;
                ir_node  *bl      = get_irg_start_block(irg);
                ir_node  *curr_sp = be_abi_reg_map_get(reg_map, arch_env->sp);
                ir_node  *curr_bp = be_abi_reg_map_get(reg_map, arch_env->bp);
-               ir_node  *noreg = ia32_new_NoReg_gp(cg);
+               ir_node  *noreg   = ia32_new_NoReg_gp(cg);
                ir_node  *push;
 
-               /* ALL nodes representing bp must be set to ignore. */
-               be_node_set_flags(get_Proj_pred(curr_bp), BE_OUT_POS(get_Proj_proj(curr_bp)), arch_irn_flags_ignore);
+               /* mark bp register as ignore */
+               be_set_constr_single_reg_out(get_Proj_pred(curr_bp),
+                               get_Proj_proj(curr_bp), arch_env->bp, arch_register_req_type_ignore);
 
                /* push ebp */
                push    = new_rd_ia32_Push(NULL, irg, bl, noreg, noreg, *mem, curr_bp, curr_sp);
@@ -429,22 +361,19 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap
 
                /* the push must have SP out register */
                arch_set_irn_register(curr_sp, arch_env->sp);
-               set_ia32_flags(push, arch_irn_flags_ignore);
 
                /* this modifies the stack bias, because we pushed 32bit */
                *stack_bias -= 4;
 
                /* move esp to ebp */
-               curr_bp  = be_new_Copy(arch_env->bp->reg_class, irg, bl, curr_sp);
-               be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), arch_env->bp);
-               arch_set_irn_register(curr_bp, arch_env->bp);
-               be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
+               curr_bp = be_new_Copy(arch_env->bp->reg_class, irg, bl, curr_sp);
+               be_set_constr_single_reg_out(curr_bp, 0, arch_env->bp,
+                                            arch_register_req_type_ignore);
 
                /* beware: the copy must be done before any other sp use */
                curr_sp = be_new_CopyKeep_single(arch_env->sp->reg_class, irg, bl, curr_sp, curr_bp, get_irn_mode(curr_sp));
-               be_set_constr_single_reg(curr_sp, BE_OUT_POS(0), arch_env->sp);
-               arch_set_irn_register(curr_sp, arch_env->sp);
-               be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);
+               be_set_constr_single_reg_out(curr_sp, 0, arch_env->sp,
+                                                    arch_register_req_type_produces_sp);
 
                be_abi_reg_map_set(reg_map, arch_env->sp, curr_sp);
                be_abi_reg_map_set(reg_map, arch_env->bp, curr_bp);
@@ -484,7 +413,6 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
 
                        /* leave */
                        leave   = new_rd_ia32_Leave(NULL, irg, bl, curr_bp);
-                       set_ia32_flags(leave, arch_irn_flags_ignore);
                        curr_bp = new_r_Proj(irg, bl, leave, mode_bp, pn_ia32_Leave_frame);
                        curr_sp = new_r_Proj(irg, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack);
                } else {
@@ -497,11 +425,11 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
                        /* copy ebp to esp */
                        curr_sp = be_new_Copy(&ia32_reg_classes[CLASS_ia32_gp], irg, bl, curr_bp);
                        arch_set_irn_register(curr_sp, arch_env->sp);
-                       be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);
+                       be_set_constr_single_reg_out(curr_sp, 0, arch_env->sp,
+                                                        arch_register_req_type_ignore);
 
                        /* pop ebp */
-                       pop     = new_rd_ia32_Pop(NULL, env->irg, bl, *mem, curr_sp);
-                       set_ia32_flags(pop, arch_irn_flags_ignore);
+                       pop     = new_rd_ia32_PopEbp(NULL, env->irg, bl, *mem, curr_sp);
                        curr_bp = new_r_Proj(irg, bl, pop, mode_bp, pn_ia32_Pop_res);
                        curr_sp = new_r_Proj(irg, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack);
 
@@ -893,10 +821,7 @@ static const be_abi_callbacks_t ia32_abi_callbacks = {
 
 static const arch_irn_ops_t ia32_irn_ops = {
        ia32_get_irn_reg_req,
-       ia32_set_irn_reg,
-       ia32_get_irn_reg,
        ia32_classify,
-       ia32_get_flags,
        ia32_get_frame_entity,
        ia32_set_frame_entity,
        ia32_set_frame_offset,
@@ -1164,7 +1089,7 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
 
        /* copy the register from the old node to the new Load */
        reg = arch_get_irn_register(node);
-       arch_set_irn_register(new_op, reg);
+       arch_set_irn_register(proj, reg);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
 
@@ -1769,7 +1694,6 @@ static arch_env_t *ia32_init(FILE *file_handle) {
 
        /* enter the ISA object into the intrinsic environment */
        intrinsic_env.isa = isa;
-       ia32_handle_intrinsics();
 
        /* emit asm includes */
        n = get_irp_n_asms();
@@ -2355,6 +2279,7 @@ static const lc_opt_table_entry_t ia32_options[] = {
 const arch_isa_if_t ia32_isa_if = {
        ia32_init,
        ia32_done,
+       ia32_handle_intrinsics,
        ia32_get_n_reg_class,
        ia32_get_reg_class,
        ia32_get_reg_class_for_mode,
index 34c75bb..5132474 100644 (file)
@@ -167,7 +167,7 @@ static const arch_register_t *get_out_reg(const ir_node *irn, int pos)
                assert(pos == 0);
                reg = arch_get_irn_register(irn);
        } else if (is_ia32_irn(irn)) {
-               reg = get_ia32_out_reg(irn, pos);
+               reg = arch_irn_get_register(irn, pos);
        } else {
                const ir_edge_t *edge;
 
index 6bbbc64..fbb1e6c 100644 (file)
@@ -73,7 +73,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg)
        in2      = get_irn_n(irn, n_ia32_binary_right);
        in1_reg  = arch_get_irn_register(in1);
        in2_reg  = arch_get_irn_register(in2);
-       out_reg  = get_ia32_out_reg(irn, 0);
+       out_reg  = arch_irn_get_register(irn, 0);
 
        irg     = cg->irg;
        block   = get_nodes_block(irn);
@@ -258,7 +258,7 @@ static void assure_should_be_same_requirements(ia32_code_gen_t *cg,
        ir_node                    *in_node, *block;
 
        reqs  = get_ia32_out_req_all(node);
-       n_res = get_ia32_n_res(node);
+       n_res = arch_irn_get_n_outs(node);
        block = get_nodes_block(node);
 
        /* check all OUT requirements, if there is a should_be_same */
@@ -280,7 +280,7 @@ static void assure_should_be_same_requirements(ia32_code_gen_t *cg,
                same_pos = get_first_same(req);
 
                /* get in and out register */
-               out_reg  = get_ia32_out_reg(node, i);
+               out_reg  = arch_irn_get_register(node, i);
                in_node  = get_irn_n(node, same_pos);
                in_reg   = arch_get_irn_register(in_node);
 
@@ -406,7 +406,7 @@ static void fix_am_source(ir_node *irn)
                return;
 
        reqs  = get_ia32_out_req_all(irn);
-       n_res = get_ia32_n_res(irn);
+       n_res = arch_irn_get_n_outs(irn);
 
        for (i = 0; i < n_res; i++) {
                const arch_register_t *out_reg;
@@ -419,7 +419,7 @@ static void fix_am_source(ir_node *irn)
                        continue;
 
                /* get in and out register */
-               out_reg   = get_ia32_out_reg(irn, i);
+               out_reg   = arch_irn_get_register(irn, i);
                same_pos  = get_first_same(reqs[i]);
                same_node = get_irn_n(irn, same_pos);
                same_reg  = arch_get_irn_register(same_node);
index 3c7fcbd..40ca7b5 100644 (file)
@@ -288,7 +288,6 @@ void rewire_fpu_mode_nodes(be_irg_t *birg)
        len = ARR_LEN(phis);
        for(i = 0; i < len; ++i) {
                ir_node *phi = phis[i];
-               be_set_phi_flags(phi, arch_irn_flags_ignore);
                arch_set_irn_register(phi, reg);
        }
        be_ssa_construction_destroy(&senv);
index e3ddcf6..4b3012a 100644 (file)
@@ -46,6 +46,7 @@
 #include "xmalloc.h"
 
 #include "../bearch_t.h"
+#include "../beinfo.h"
 
 #include "bearch_ia32_t.h"
 #include "ia32_nodes_attr.h"
@@ -70,7 +71,7 @@
 static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
                          int inout) {
        char *dir = inout ? "out" : "in";
-       int   max = inout ? get_ia32_n_res(n) : get_irn_arity(n);
+       int   max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
        char  buf[1024];
        int   i;
 
@@ -139,7 +140,6 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
        int          bad  = 0;
        int          i, n_res, flags;
        const arch_register_req_t **reqs;
-       const arch_register_t     **slots;
 
        switch (reason) {
                case dump_node_opcode_txt:
@@ -205,7 +205,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        break;
 
                case dump_node_info_txt:
-                       n_res = get_ia32_n_res(n);
+                       n_res = arch_irn_get_n_outs(n);
                        fprintf(F, "=== IA32 attr begin ===\n");
 
                        /* dump IN requirements */
@@ -221,12 +221,9 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        }
 
                        /* dump assigned registers */
-                       slots = get_ia32_slots(n);
-                       if (slots && n_res > 0) {
+                       if (n_res > 0) {
                                for (i = 0; i < n_res; i++) {
-                                       const arch_register_t *reg;
-
-                                       reg = slots[i];
+                                       const arch_register_t *reg = arch_irn_get_register(n, i);
 
                                        fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
                                }
@@ -292,7 +289,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                fprintf(F, "size = %u\n", get_ia32_copyb_size(n));
                        }
 
-                       fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
+                       fprintf(F, "n_res = %d\n", arch_irn_get_n_outs(n));
                        fprintf(F, "use_frame = %d\n", is_ia32_use_frame(n));
                        fprintf(F, "commutative = %d\n", is_ia32_commutative(n));
                        fprintf(F, "need stackent = %d\n", is_ia32_need_stackent(n));
@@ -301,7 +298,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
 
                        /* dump flags */
                        fprintf(F, "flags =");
-                       flags = get_ia32_flags(n);
+                       flags = arch_irn_get_flags(n);
                        if (flags == arch_irn_flags_none) {
                                fprintf(F, " none");
                        }
@@ -312,12 +309,6 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                if (flags & arch_irn_flags_rematerializable) {
                                        fprintf(F, " remat");
                                }
-                               if (flags & arch_irn_flags_ignore) {
-                                       fprintf(F, " ignore");
-                               }
-                               if (flags & arch_irn_flags_modify_sp) {
-                                       fprintf(F, " modify_sp");
-                               }
                                if (flags & arch_irn_flags_modify_flags) {
                                        fprintf(F, " modify_flags");
                                }
@@ -796,43 +787,6 @@ void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
        attr->in_req[pos] = req;
 }
 
-/**
- * Returns the register flag of an ia32 node.
- */
-arch_irn_flags_t get_ia32_flags(const ir_node *node) {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-       return attr->data.flags;
-}
-
-/**
- * Sets the register flag of an ia32 node.
- */
-void set_ia32_flags(ir_node *node, arch_irn_flags_t flags) {
-       ia32_attr_t *attr = get_ia32_attr(node);
-       attr->data.flags  = flags;
-}
-
-void add_ia32_flags(ir_node *node, arch_irn_flags_t flags) {
-       ia32_attr_t *attr  = get_ia32_attr(node);
-       attr->data.flags  |= flags;
-}
-
-/**
- * Returns the result register slots of an ia32 node.
- */
-const arch_register_t **get_ia32_slots(const ir_node *node) {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-       return attr->slots;
-}
-
-/**
- * Returns the number of results.
- */
-int get_ia32_n_res(const ir_node *node) {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-       return ARR_LEN(attr->slots);
-}
-
 /**
  * Returns the condition code of a node.
  */
@@ -860,24 +814,6 @@ unsigned get_ia32_copyb_size(const ir_node *node)
        return attr->size;
 }
 
-/**
- * Sets the flags for the n'th out.
- */
-void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) {
-       ia32_attr_t *attr = get_ia32_attr(node);
-       assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
-       attr->out_flags[pos] = flags;
-}
-
-/**
- * Gets the flags for the n'th out.
- */
-arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos) {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-       assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
-       return attr->out_flags[pos];
-}
-
 /**
  * Get the list of available execution units.
  */
@@ -981,18 +917,6 @@ void ia32_swap_left_right(ir_node *node)
        set_irn_n(node, n_ia32_binary_right, left);
 }
 
-/**
- * Returns the OUT register at position pos.
- */
-const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-
-       assert(pos < ARR_LEN(attr->slots) && "Invalid OUT position.");
-       assert(attr->slots[pos]  && "No register assigned");
-
-       return attr->slots[pos];
-}
-
 /**
  * Initializes the nodes attributes.
  */
@@ -1005,8 +929,9 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
        ir_graph        *irg  = get_irn_irg(node);
        struct obstack  *obst = get_irg_obstack(irg);
        ia32_attr_t     *attr = get_ia32_attr(node);
+       backend_info_t  *info;
 
-       set_ia32_flags(node, flags);
+       arch_irn_set_flags(node, flags);
        set_ia32_in_req_all(node, in_reqs);
        set_ia32_out_req_all(node, out_reqs);
 
@@ -1015,12 +940,9 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
        attr->attr_type  |= IA32_ATTR_ia32_attr_t;
 #endif
 
-       attr->out_flags = NEW_ARR_D(int, obst, n_res);
-       memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0]));
-
-       attr->slots = NEW_ARR_D(const arch_register_t*, obst, n_res);
-       /* void* cast to suppress an incorrect warning on MSVC */
-       memset((void*)attr->slots, 0, n_res * sizeof(attr->slots[0]));
+       info            = be_get_info(node);
+       info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
+       memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
 }
 
 void
@@ -1264,16 +1186,17 @@ static void ia32_copy_attr(const ir_node *old_node, ir_node *new_node)
        struct obstack    *obst     = get_irg_obstack(irg);
        const ia32_attr_t *attr_old = get_ia32_attr_const(old_node);
        ia32_attr_t       *attr_new = get_ia32_attr(new_node);
+       backend_info_t    *old_info = be_get_info(old_node);
+       backend_info_t    *new_info;
+
+       new_info = be_get_info(new_node);
 
        /* copy the attributes */
        memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
 
        /* copy out flags */
-       attr_new->out_flags =
-               DUP_ARR_D(int, obst, attr_old->out_flags);
-       /* copy register assignments */
-       attr_new->slots =
-               DUP_ARR_D(arch_register_t*, obst, attr_old->slots);
+       new_info->out_infos =
+               DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
 }
 
 /* Include the generated constructor functions */
index ce7d968..e3c99f2 100644 (file)
@@ -283,33 +283,6 @@ void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos);
  */
 void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos);
 
-/**
- * Returns the register flag of an ia32 node.
- */
-arch_irn_flags_t get_ia32_flags(const ir_node *node);
-
-/**
- * Sets the register flag of an ia32 node.
- */
-void set_ia32_flags(ir_node *node, arch_irn_flags_t flags);
-
-void add_ia32_flags(ir_node *node, arch_irn_flags_t flags);
-
-/**
- * Returns the result register slots of an ia32 node.
- */
-const arch_register_t **get_ia32_slots(const ir_node *node);
-
-/**
- * Returns the OUT register at position pos.
- */
-const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos);
-
-/**
- * Returns the number of results.
- */
-int get_ia32_n_res(const ir_node *node);
-
 /**
  * Returns the condition code of a node.
  */
index 065cb49..c2de549 100644 (file)
@@ -92,7 +92,6 @@ typedef struct ia32_attr_t ia32_attr_t;
 struct ia32_attr_t {
        except_attr  exc;               /**< the exception attribute. MUST be the first one. */
        struct ia32_attr_data_bitfield {
-               unsigned flags:5;               /**< Indicating if spillable, rematerializeable, stack modifying and/or ignore. */
                unsigned tp:3;                  /**< ia32 node type. */
                unsigned am_arity:2;            /**< Indicates the address mode type supported by this node. */
                unsigned am_scale:2;            /**< The address mode scale for index register. */
@@ -114,8 +113,6 @@ struct ia32_attr_t {
                unsigned is_remat : 1;
        } data;
 
-       int       *out_flags;     /**< flags for each produced value */
-
        int        am_offs;       /**< offsets for AddrMode */
        ir_entity *am_sc;         /**< SymConst for AddrMode */
 
@@ -129,8 +126,6 @@ struct ia32_attr_t {
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
        const arch_register_req_t **out_req; /**< register requirements for results */
 
-       const arch_register_t **slots;     /**< register slots for assigned registers */
-
        ir_label_t        exc_label;       /**< the exception label iff this instruction can throw an exception */
 
 #ifndef NDEBUG
index 1d5647b..059ce49 100644 (file)
@@ -224,8 +224,8 @@ static void peephole_ia32_Cmp(ir_node *const node)
        }
        set_ia32_ls_mode(test, get_ia32_ls_mode(node));
 
-       reg = arch_get_irn_register(node);
-       arch_set_irn_register(test, reg);
+       reg = arch_irn_get_register(node, pn_ia32_Cmp_eflags);
+       arch_irn_set_register(test, pn_ia32_Test_eflags, reg);
 
        foreach_out_edge_safe(node, edge, tmp) {
                ir_node *const user = get_edge_src_irn(edge);
@@ -558,10 +558,12 @@ static void peephole_store_incsp(ir_node *store)
        dbg_info *dbgi;
        ir_node  *node;
        ir_node  *block;
-       ir_node  *noref;
+       ir_node  *noreg;
        ir_node  *mem;
        ir_node  *push;
        ir_node  *val;
+       ir_node  *base;
+       ir_node  *index;
        ir_node  *am_base = get_irn_n(store, n_ia32_Store_base);
        if (!be_is_IncSP(am_base)
                        || get_nodes_block(am_base) != get_nodes_block(store))
@@ -610,7 +612,7 @@ static void peephole_store_incsp(ir_node *store)
                                         || get_ia32_op_type(node) == ia32_AddrModeD)) {
                                int      node_offset  = get_ia32_am_offs_int(node);
                                ir_mode *node_ls_mode = get_ia32_ls_mode(node);
-                               int      node_size    = get_mode_size_bytes(node);
+                               int      node_size    = get_mode_size_bytes(node_ls_mode);
                                /* overlapping with our position? abort */
                                if (node_offset < my_offset + my_store_size
                                                && node_offset + node_size >= my_offset)
@@ -628,7 +630,7 @@ static void peephole_store_incsp(ir_node *store)
        dbgi  = get_irn_dbg_info(store);
        block = get_nodes_block(store);
        noreg = ia32_new_NoReg_gp(cg);
-       val   = get_ia32_
+       val   = get_irn_n(store, n_ia32_Store_val);
 
        push  = new_rd_ia32_Push(dbgi, irg, block, noreg, noreg, mem,
 
@@ -740,7 +742,7 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn)
                if (loads[loadslot] != NULL)
                        break;
 
-               dreg = arch_get_irn_register(node);
+               dreg = arch_irn_get_register(node, pn_ia32_Load_res);
                if (regmask & (1 << dreg->index)) {
                        /* this register is already used */
                        break;
@@ -782,10 +784,10 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn)
                const arch_register_t *reg;
 
                mem = get_irn_n(load, n_ia32_mem);
-               reg = arch_get_irn_register(load);
+               reg = arch_irn_get_register(load, pn_ia32_Load_res);
 
                pop = new_rd_ia32_Pop(get_irn_dbg_info(load), irg, block, mem, pred_sp);
-               arch_set_irn_register(pop, reg);
+               arch_irn_set_register(pop, pn_ia32_Load_res, reg);
 
                copy_mark(load, pop);
 
index 4bbb018..61b6b40 100644 (file)
@@ -17,7 +17,7 @@ $arch = "ia32";
 #
 # <op-name> => {
 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
-#   irn_flags => "R|N|I|S"
+#   irn_flags => "R|N"
 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
 #   state     => "floats|pinned|mem_pinned|exc_pinned",
 #   args      => [
@@ -63,8 +63,6 @@ $arch = "ia32";
 # following irn_flags are supported:
 #   R   rematerializeable
 #   N   not spillable
-#   I   ignore for register allocation
-#   S   modifies stack pointer
 #
 # state: state of the operation, OPTIONAL (default is "floats")
 #
@@ -79,10 +77,7 @@ $arch = "ia32";
 #
 # outs:  if a node defines more than one output, the names of the projections
 #        nodes having outs having automatically the mode mode_T
-#        One can also annotate some flags for each out, additional to irn_flags.
-#        They are separated from name with a colon ':', and concatenated by pipe '|'
-#        Only I and S are available at the moment (same meaning as in irn_flags).
-#        example: [ "frame:I", "stack:I|S", "M" ]
+#        example: [ "frame", "stack", "M" ]
 #
 # comment: OPTIONAL comment for the node constructor
 #
@@ -248,7 +243,7 @@ sub ia32_custom_init_attr {
        my $res = "";
 
        if(defined($node->{modified_flags})) {
-               $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
+               $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
        }
        if(defined($node->{am})) {
                my $am = $node->{am};
@@ -323,8 +318,7 @@ $fpcw_flags         = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
 Immediate => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "gp_NOREG" ] },
+       reg_req   => { out => [ "gp_NOREG:I" ] },
        attr      => "ir_entity *symconst, int symconst_sign, long offset",
        attr_type => "ia32_immediate_attr_t",
        hash_func => "ia32_hash_Immediate",
@@ -1191,8 +1185,7 @@ GetEIP => {
 Unknown_GP => {
        state     => "pinned",
        op_flags  => "c|NB",
-       irn_flags => "I",
-       reg_req   => { out => [ "gp_UKNWN" ] },
+       reg_req   => { out => [ "gp_UKNWN:I" ] },
        units     => [],
        emit      => "",
        latency   => 0,
@@ -1202,8 +1195,7 @@ Unknown_GP => {
 Unknown_VFP => {
        state     => "pinned",
        op_flags  => "c|NB",
-       irn_flags => "I",
-       reg_req   => { out => [ "vfp_UKNWN" ] },
+       reg_req   => { out => [ "vfp_UKNWN:I" ] },
        units     => [],
        emit      => "",
        mode      => "mode_E",
@@ -1214,8 +1206,7 @@ Unknown_VFP => {
 Unknown_XMM => {
        state     => "pinned",
        op_flags  => "c|NB",
-       irn_flags => "I",
-       reg_req   => { out => [ "xmm_UKNWN" ] },
+       reg_req   => { out => [ "xmm_UKNWN:I" ] },
        units     => [],
        emit      => "",
        latency   => 0,
@@ -1225,8 +1216,7 @@ Unknown_XMM => {
 NoReg_GP => {
        state     => "pinned",
        op_flags  => "c|NB|NI",
-       irn_flags => "I",
-       reg_req   => { out => [ "gp_NOREG" ] },
+       reg_req   => { out => [ "gp_NOREG:I" ] },
        units     => [],
        emit      => "",
        latency   => 0,
@@ -1236,8 +1226,7 @@ NoReg_GP => {
 NoReg_VFP => {
        state     => "pinned",
        op_flags  => "c|NB|NI",
-       irn_flags => "I",
-       reg_req   => { out => [ "vfp_NOREG" ] },
+       reg_req   => { out => [ "vfp_NOREG:I" ] },
        units     => [],
        emit      => "",
        mode      => "mode_E",
@@ -1248,8 +1237,7 @@ NoReg_VFP => {
 NoReg_XMM => {
        state     => "pinned",
        op_flags  => "c|NB|NI",
-       irn_flags => "I",
-       reg_req   => { out => [ "xmm_NOREG" ] },
+       reg_req   => { out => [ "xmm_NOREG:I" ] },
        units     => [],
        emit      => "",
        latency   => 0,
@@ -1259,8 +1247,7 @@ NoReg_XMM => {
 ChangeCW => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "fp_cw" ] },
+       reg_req   => { out => [ "fpcw:I" ] },
        mode      => $mode_fpcw,
        latency   => 3,
        units     => [ "GP" ],
@@ -1270,7 +1257,7 @@ ChangeCW => {
 FldCW => {
        op_flags  => "L|F",
        state     => "pinned",
-       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
        ins       => [ "base", "index", "mem" ],
        latency   => 5,
        emit      => ". fldcw %AM",
@@ -1365,10 +1352,10 @@ Lea => {
 
 Push => {
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
        ins       => [ "base", "index", "mem", "val", "stack" ],
        emit      => '. push%M %unop3',
-       outs      => [ "stack:I|S", "M" ],
+       outs      => [ "stack", "M" ],
        am        => "source,unary",
        latency   => 2,
        units     => [ "GP" ],
@@ -1376,9 +1363,19 @@ Push => {
 
 Pop => {
        state     => "exc_pinned",
-       reg_req   => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp" ] },
+       reg_req   => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
        ins       => [ "mem", "stack" ],
-       outs      => [ "res", "M", "unused", "stack:I|S" ],
+       outs      => [ "res", "M", "unused", "stack" ],
+       emit      => '. pop%M %D0',
+       latency   => 3, # Pop is more expensive than Push on Athlon
+       units     => [ "GP" ],
+},
+
+PopEbp => {
+       state     => "exc_pinned",
+       reg_req   => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
+       ins       => [ "mem", "stack" ],
+       outs      => [ "res", "M", "unused", "stack" ],
        emit      => '. pop%M %D0',
        latency   => 3, # Pop is more expensive than Push on Athlon
        units     => [ "GP" ],
@@ -1386,53 +1383,51 @@ Pop => {
 
 PopMem => {
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
        ins       => [ "base", "index", "mem", "stack" ],
-       outs      => [ "unused0", "M", "unused1", "stack:I|S" ],
+       outs      => [ "unused0", "M", "unused1", "stack" ],
        emit      => '. pop%M %AM',
        latency   => 3, # Pop is more expensive than Push on Athlon
        units     => [ "GP" ],
 },
 
 Enter => {
-       reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
+       reg_req   => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
        emit      => '. enter',
-       outs      => [ "frame:I", "stack:I|S", "M" ],
+       outs      => [ "frame", "stack", "M" ],
        latency   => 15,
        units     => [ "GP" ],
 },
 
 Leave => {
-       reg_req   => { in => [ "ebp" ], out => [ "ebp", "esp" ] },
+       reg_req   => { in => [ "ebp" ], out => [ "ebp", "esp:I|S" ] },
        emit      => '. leave',
-       outs      => [ "frame:I", "stack:I|S" ],
+       outs      => [ "frame", "stack" ],
        latency   => 3,
        units     => [ "GP" ],
 },
 
 AddSP => {
-       irn_flags => "I",
        state     => "pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
        ins       => [ "base", "index", "mem", "stack", "size" ],
        am        => "source,binary",
        emit      => '. addl %binop',
        latency   => 1,
-       outs      => [ "stack:I|S", "M" ],
+       outs      => [ "stack", "M" ],
        units     => [ "GP" ],
        modified_flags => $status_flags
 },
 
 SubSP => {
-#irn_flags => "I",
        state     => "pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
        ins       => [ "base", "index", "mem", "stack", "size" ],
        am        => "source,binary",
        emit      => ". subl %binop\n".
                     ". movl %%esp, %D1",
        latency   => 2,
-       outs      => [ "stack:I|S", "addr", "M" ],
+       outs      => [ "stack", "addr", "M" ],
        units     => [ "GP" ],
        modified_flags => $status_flags
 },
@@ -1468,10 +1463,10 @@ Call => {
        state     => "exc_pinned",
        reg_req   => {
                in  => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
-               out => [ "esp", "fpcw", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ]
+               out => [ "esp:I|S", "fpcw:I", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ]
        },
        ins       => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
-       outs      => [ "stack:I|S", "fpcw:I", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ],
+       outs      => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ],
        attr_type => "ia32_call_attr_t",
        attr      => "unsigned pop, ir_type *call_tp",
        am        => "source,unary",
@@ -2022,6 +2017,7 @@ vfisttp => {
 vfldz => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2031,6 +2027,7 @@ vfldz => {
 vfld1 => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2040,6 +2037,7 @@ vfld1 => {
 vfldpi => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2049,6 +2047,7 @@ vfldpi => {
 vfldln2 => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2058,6 +2057,7 @@ vfldln2 => {
 vfldlg2 => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2067,6 +2067,7 @@ vfldlg2 => {
 vfldl2t => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -2076,6 +2077,7 @@ vfldl2t => {
 vfldl2e => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
+       outs      => [ "res" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
index 6fe28ab..00007f8 100644 (file)
@@ -268,7 +268,7 @@ static ir_node *gen_Const(ir_node *node)
                                                             mode);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_sc(load, floatent);
-                               set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
+                               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
                                res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
                        }
                } else {
@@ -286,7 +286,7 @@ static ir_node *gen_Const(ir_node *node)
                                load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_sc(load, floatent);
-                               set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
+                               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
                                res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
                                /* take the mode from the entity */
                                set_ia32_ls_mode(load, get_type_mode(get_entity_type(floatent)));
@@ -1312,6 +1312,9 @@ static ir_node *transform_AM_mem(ir_graph *const irg, ir_node *const block,
 
                NEW_ARR_A(ir_node*, ins, arity + 1);
 
+               /* NOTE: This sometimes produces dead-code because the old sync in
+                * src_mem might not be used anymore, we should detect this case
+                * and kill the sync... */
                for (i = arity - 1; i >= 0; --i) {
                        ir_node *const pred = get_Sync_pred(src_mem, i);
 
@@ -1905,7 +1908,10 @@ static ir_node *gen_Load(ir_node *node)
        set_address(new_node, &addr);
 
        if (get_irn_pinned(node) == op_pin_state_floats) {
-               add_ia32_flags(new_node, arch_irn_flags_rematerializable);
+               assert(pn_ia32_xLoad_res == pn_ia32_vfld_res
+                               && pn_ia32_vfld_res == pn_ia32_Load_res
+                               && pn_ia32_Load_res == pn_ia32_res);
+               arch_irn_add_flags(new_node, arch_irn_flags_rematerializable);
        }
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
@@ -2307,6 +2313,7 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns)
                set_address(new_node, &addr);
                SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
+               assert(i < 4);
                ins[i++] = new_node;
 
                size        -= 4;
@@ -2314,7 +2321,11 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns)
                addr.offset += 4;
        } while (size != 0);
 
-       return i == 1 ? ins[0] : new_rd_Sync(dbgi, irg, new_block, i, ins);
+       if (i > 1) {
+               return new_rd_Sync(dbgi, irg, new_block, i, ins);
+       } else {
+               return ins[0];
+       }
 }
 
 /**
@@ -4286,7 +4297,7 @@ static ir_node *gen_be_Call(ir_node *node)
 static ir_node *gen_be_IncSP(ir_node *node)
 {
        ir_node *res = be_duplicate_node(node);
-       be_node_add_flags(res, -1, arch_irn_flags_modify_flags);
+       arch_irn_add_flags(res, arch_irn_flags_modify_flags);
 
        return res;
 }
@@ -4381,17 +4392,17 @@ static ir_node *gen_Proj_be_Call(ir_node *node)
                proj = pn_ia32_Call_M;
        } else {
                arch_register_req_t const *const req    = arch_get_register_req_out(node);
-               int                        const n_outs = get_ia32_n_res(new_call);
+               int                        const n_outs = arch_irn_get_n_outs(new_call);
                int                              i;
 
                assert(proj      >= pn_be_Call_first_res);
-               assert(req->type == arch_register_req_type_limited);
+               assert(req->type & arch_register_req_type_limited);
 
                for (i = 0; i < n_outs; ++i) {
                        arch_register_req_t const *const new_req = get_ia32_out_req(new_call, i);
 
-                       if (new_req->type     != arch_register_req_type_limited ||
-                           new_req->cls      != req->cls                       ||
+                       if (!(new_req->type & arch_register_req_type_limited) ||
+                           new_req->cls      != req->cls                     ||
                            *new_req->limited != *req->limited)
                                continue;
 
@@ -4466,7 +4477,7 @@ static ir_node *gen_Proj_ASM(ir_node *node)
        new_pred = be_transform_node(pred);
        block    = get_nodes_block(new_pred);
        return new_r_Proj(current_ir_graph, block, new_pred, mode_M,
-                       get_ia32_n_res(new_pred) + 1);
+                       arch_irn_get_n_outs(new_pred) + 1);
 }
 
 /**
@@ -4682,7 +4693,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
        if (!is_ia32_irn(node))
                return;
 
-       n_outs = get_ia32_n_res(node);
+       n_outs = arch_irn_get_n_outs(node);
        if (n_outs <= 0)
                return;
        if (is_ia32_SwitchJmp(node))
index 17c1fa4..22ffaa8 100644 (file)
@@ -450,6 +450,15 @@ static inline const arch_register_t *x87_get_irn_register(const ir_node *irn)
        return res;
 }  /* x87_get_irn_register */
 
+static inline const arch_register_t *x87_irn_get_register(const ir_node *irn,
+                                                          int pos)
+{
+       const arch_register_t *res = arch_irn_get_register(irn, pos);
+
+       assert(res->reg_class->regs == ia32_vfp_regs);
+       return res;
+}
+
 /* -------------- x87 perm --------------- */
 
 /**
@@ -926,7 +935,7 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
        ir_node               *op2     = get_irn_n(n, n_ia32_binary_right);
        const arch_register_t *op1_reg = x87_get_irn_register(op1);
        const arch_register_t *op2_reg = x87_get_irn_register(op2);
-       const arch_register_t *out     = x87_get_irn_register(n);
+       const arch_register_t *out     = x87_irn_get_register(n, pn_ia32_res);
        int reg_index_1                = arch_register_get_index(op1_reg);
        int reg_index_2                = arch_register_get_index(op2_reg);
        vfp_liveness           live    = vfp_live_args_after(sim, n, REGMASK(out));
@@ -1144,14 +1153,14 @@ static int sim_unop(x87_state *state, ir_node *n, ir_op *op)
  *
  * @return NO_NODE_ADDED
  */
-static int sim_load(x87_state *state, ir_node *n, ir_op *op)
+static int sim_load(x87_state *state, ir_node *n, ir_op *op, int res_pos)
 {
-       const arch_register_t *out = x87_get_irn_register(n);
+       const arch_register_t *out = x87_irn_get_register(n, res_pos);
        ia32_x87_attr_t *attr;
 
        DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, arch_register_get_name(out)));
        x87_push(state, arch_register_get_index(out), x87_patch_insn(n, op));
-       assert(out == x87_get_irn_register(n));
+       assert(out == x87_irn_get_register(n, res_pos));
        attr = get_ia32_x87_attr(n);
        attr->x87[2] = out = &ia32_st_regs[0];
        DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
@@ -1320,13 +1329,11 @@ static int sim_##op(x87_state *state, ir_node *n) { \
 #define GEN_BINOP(op)   _GEN_BINOP(op, op)
 #define GEN_BINOPR(op) _GEN_BINOP(op, op##r)
 
-#define GEN_LOAD2(op, nop) \
-static int sim_##op(x87_state *state, ir_node *n) { \
-       return sim_load(state, n, op_ia32_##nop); \
+#define GEN_LOAD(op)                                              \
+static int sim_##op(x87_state *state, ir_node *n) {               \
+       return sim_load(state, n, op_ia32_##op, pn_ia32_v##op##_res); \
 }
 
-#define GEN_LOAD(op)   GEN_LOAD2(op, op)
-
 #define GEN_UNOP(op) \
 static int sim_##op(x87_state *state, ir_node *n) { \
        return sim_unop(state, n, op_ia32_##op); \
@@ -2001,7 +2008,7 @@ end_call:
  */
 static int sim_Spill(x87_state *state, ir_node *n)
 {
-       assert(0 && "Spill not lowered");
+       panic("Spill not lowered");
        return sim_fst(state, n);
 }  /* sim_Spill */
 
@@ -2015,7 +2022,7 @@ static int sim_Spill(x87_state *state, ir_node *n)
  */
 static int sim_Reload(x87_state *state, ir_node *n)
 {
-       assert(0 && "Reload not lowered");
+       panic("Reload not lowered");
        return sim_fld(state, n);
 }  /* sim_Reload */
 
index d5d9ef8..06f289b 100644 (file)
@@ -157,33 +157,6 @@ static void mips_set_irn_reg(ir_node *irn, const arch_register_t *reg)
        }
 }
 
-static const arch_register_t *mips_get_irn_reg(const ir_node *irn)
-{
-       int pos = 0;
-       const arch_register_t *reg = NULL;
-
-       if (is_Proj(irn)) {
-
-               if (get_irn_mode(irn) == mode_X) {
-                       return NULL;
-               }
-
-               pos = mips_translate_proj_pos(irn);
-               irn = skip_Proj_const(irn);
-       }
-
-       if (is_mips_irn(irn)) {
-               const arch_register_t **slots;
-               slots = get_mips_slots(irn);
-               reg   = slots[pos];
-       }
-       else {
-               reg = mips_get_firm_reg(irn, cur_reg_set);
-       }
-
-       return reg;
-}
-
 static arch_irn_class_t mips_classify(const ir_node *irn)
 {
        irn = skip_Proj_const(irn);
@@ -195,16 +168,6 @@ static arch_irn_class_t mips_classify(const ir_node *irn)
        return 0;
 }
 
-static arch_irn_flags_t mips_get_flags(const ir_node *irn)
-{
-       irn = skip_Proj_const(irn);
-
-       if (!is_mips_irn(irn))
-               return 0;
-
-       return get_mips_flags(irn);
-}
-
 int mips_is_Load(const ir_node *node)
 {
        return is_mips_lw(node) || is_mips_lh(node) || is_mips_lhu(node) ||
@@ -277,10 +240,7 @@ static int mips_get_sp_bias(const ir_node *irn)
 
 static const arch_irn_ops_t mips_irn_ops = {
        mips_get_irn_reg_req,
-       mips_set_irn_reg,
-       mips_get_irn_reg,
        mips_classify,
-       mips_get_flags,
        mips_get_frame_entity,
        mips_set_frame_entity,
        mips_set_frame_offset,
@@ -558,7 +518,7 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                sp = new_rd_mips_addu(NULL, irg, block, sp,
                                      mips_create_Immediate(initialstackframesize));
                mips_set_irn_reg(sp, &mips_gp_regs[REG_SP]);
-               set_mips_flags(sp, arch_irn_flags_ignore);
+               panic("FIXME Use IncSP or set register requirement with ignore");
 
                /* TODO: where to get an edge with a0-a3
                int i;
@@ -596,7 +556,7 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                sp = new_rd_mips_addu(NULL, irg, block, sp,
                                      mips_create_Immediate(-initialstackframesize));
                mips_set_irn_reg(sp, &mips_gp_regs[REG_SP]);
-               set_mips_flags(sp, arch_irn_flags_ignore);
+               panic("FIXME Use IncSP or set register requirement with ignore");
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
                store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 0);
@@ -608,7 +568,7 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
        fp = new_rd_mips_addu(NULL, irg, block, sp,
                              mips_create_Immediate(-initialstackframesize));
        mips_set_irn_reg(fp, &mips_gp_regs[REG_FP]);
-       set_mips_flags(fp, arch_irn_flags_ignore);
+       panic("FIXME Use IncSP or set register requirement with ignore");
 
        be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_FP], fp);
        be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_SP], sp);
@@ -630,12 +590,12 @@ static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *r
        // copy fp to sp
        sp = new_rd_mips_or(NULL, irg, block, fp, mips_create_zero());
        mips_set_irn_reg(sp, &mips_gp_regs[REG_SP]);
-       set_mips_flags(sp, arch_irn_flags_ignore);
+       panic("FIXME Use be_Copy or set register requirement with ignore");
 
        // 1. restore fp
        load = new_rd_mips_lw(NULL, irg, block, sp, *mem, NULL,
                              fp_save_offset - initial_frame_size);
-       set_mips_flags(load, arch_irn_flags_ignore);
+       panic("FIXME register requirement with ignore");
 
        fp = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_res);
        *mem = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_M);
@@ -847,6 +807,7 @@ static int mips_is_valid_clobber(const void *self, const char *clobber)
 const arch_isa_if_t mips_isa_if = {
        mips_init,
        mips_done,
+       NULL,               /* handle intrinsics */
        mips_get_n_reg_class,
        mips_get_reg_class,
        mips_get_reg_class_for_mode,
index e88434e..6c37667 100644 (file)
@@ -222,9 +222,6 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                if (attr->flags & arch_irn_flags_rematerializable) {
                                        fprintf(F, " remat");
                                }
-                               if (attr->flags & arch_irn_flags_ignore) {
-                                       fprintf(F, " ignore");
-                               }
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
index 2cc8789..c1dfb2d 100644 (file)
@@ -7,88 +7,6 @@
 $arch = "mips";
 $new_emit_syntax = 1;
 
-# The node description is done as a perl hash initializer with the
-# following structure:
-#
-# %nodes = (
-#
-# <op-name> => {
-#   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
-#   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
-#   "state"     => "floats|pinned|mem_pinned|exc_pinned",
-#   "args"      => [
-#                    { "type" => "type 1", "name" => "name 1" },
-#                    { "type" => "type 2", "name" => "name 2" },
-#                    ...
-#                  ],
-#   comment   => "any comment for constructor",
-#   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
-#   cmp_attr  => "c source code for comparing node attributes",
-#   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
-#   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
-#   mode      => "mode_Iu"          # optional, predefines the mode
-#   emit      => "emit code with templates",
-#   attr      => "attitional attribute arguments for constructor",
-#   init_attr => "emit attribute initialization template",
-#   rd_constructor => "c source code which constructs an ir_node",
-#   hash_func => "name of the hash function for this operation",
-#   latency   => "latency of this operation (can be float)"
-#   attr_type => "name of the attribute struct",
-# },
-#
-# ... # (all nodes you need to describe)
-#
-# ); # close the %nodes initializer
-
-# op_flags: flags for the operation, OPTIONAL (default is "N")
-# the op_flags correspond to the firm irop_flags:
-#   N   irop_flag_none
-#   L   irop_flag_labeled
-#   C   irop_flag_commutative
-#   X   irop_flag_cfopcode
-#   I   irop_flag_ip_cfopcode
-#   F   irop_flag_fragile
-#   Y   irop_flag_forking
-#   H   irop_flag_highlevel
-#   c   irop_flag_constlike
-#   K   irop_flag_keep
-#
-#   R   rematerializeable
-#   N   not spillable
-#   I   ignore for register allocation
-#
-# state: state of the operation, OPTIONAL (default is "floats")
-#
-# arity: arity of the operation, MUST NOT BE OMITTED
-#
-# args:  the OPTIONAL arguments of the node constructor (debug, irg and block
-#        are always the first 3 arguments and are always autmatically
-#        created)
-#        If this key is missing the following arguments will be created:
-#        for i = 1 .. arity: ir_node *op_i
-#        ir_mode *mode
-#
-# outs:  if a node defines more than one output, the names of the projections
-#        nodes having outs having automatically the mode mode_T
-#
-# comment: OPTIONAL comment for the node constructor
-#
-# rd_constructor: for every operation there will be a
-#      new_rd_<arch>_<op-name> function with the arguments from above
-#      which creates the ir_node corresponding to the defined operation
-#      you can either put the complete source code of this function here
-#
-#      This key is OPTIONAL. If omitted, the following constructor will
-#      be created:
-#      if (!op_<arch>_<op-name>) assert(0);
-#      for i = 1 to arity
-#         set in[i] = op_i
-#      done
-#      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
-#      return res
-#
-# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
-
 # register types:
 #   0 - no special type
 #   1 - caller save (register must be saved by the caller of a function)
@@ -187,8 +105,7 @@ $mode_gp = "mode_Iu";
 Immediate => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "gp_NOREG" ] },
+       reg_req   => { out => [ "gp_NOREG:I" ] },
        attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
        attr_type => "mips_immediate_attr_t",
        mode      => $mode_gp,
@@ -353,8 +270,7 @@ mfhi => {
 zero => {
        state     => "pinned",
        op_flags  => "c",
-       irn_flags => "I",
-       reg_req   => { out => [ "zero" ] },
+       reg_req   => { out => [ "zero:I" ] },
        emit      => '',
        mode      => $mode_gp
 },
index 707c038..1a5daee 100644 (file)
@@ -137,59 +137,6 @@ static const arch_register_req_t *ppc32_get_irn_reg_req(const ir_node *irn,
        return arch_no_register_req;
 }
 
-static void ppc32_set_irn_reg(ir_node *irn, const arch_register_t *reg)
-{
-       int pos = 0;
-
-       if (is_Proj(irn)) {
-
-               if (get_irn_mode(irn) == mode_X) {
-                       return;
-               }
-
-               pos = ppc32_translate_proj_pos(irn);
-               irn = skip_Proj(irn);
-       }
-
-       if (is_ppc32_irn(irn)) {
-               const arch_register_t **slots;
-
-               slots      = get_ppc32_slots(irn);
-               slots[pos] = reg;
-       }
-       else {
-               /* here we set the registers for the Phi nodes */
-               ppc32_set_firm_reg(irn, reg, cur_reg_set);
-       }
-}
-
-static const arch_register_t *ppc32_get_irn_reg(const ir_node *irn)
-{
-       int pos = 0;
-       const arch_register_t *reg = NULL;
-
-       if (is_Proj(irn)) {
-
-               if (get_irn_mode(irn) == mode_X) {
-                       return NULL;
-               }
-
-               pos = ppc32_translate_proj_pos(irn);
-               irn = skip_Proj_const(irn);
-       }
-
-       if (is_ppc32_irn(irn)) {
-               const arch_register_t **slots;
-               slots = get_ppc32_slots(irn);
-               reg   = slots[pos];
-       }
-       else {
-               reg = ppc32_get_firm_reg(irn, cur_reg_set);
-       }
-
-       return reg;
-}
-
 static arch_irn_class_t ppc32_classify(const ir_node *irn)
 {
        irn = skip_Proj_const(irn);
@@ -201,20 +148,6 @@ static arch_irn_class_t ppc32_classify(const ir_node *irn)
        return 0;
 }
 
-static arch_irn_flags_t ppc32_get_flags(const ir_node *irn)
-{
-       irn = skip_Proj_const(irn);
-
-       if (is_ppc32_irn(irn)) {
-               return get_ppc32_flags(irn);
-       }
-       else if (is_Unknown(irn)) {
-               return arch_irn_flags_ignore;
-       }
-
-       return 0;
-}
-
 static ir_entity *ppc32_get_frame_entity(const ir_node *irn)
 {
        if(!is_ppc32_irn(irn)) return NULL;
@@ -359,10 +292,7 @@ static const be_abi_callbacks_t ppc32_abi_callbacks = {
 
 static const arch_irn_ops_t ppc32_irn_ops = {
        ppc32_get_irn_reg_req,
-       ppc32_set_irn_reg,
-       ppc32_get_irn_reg,
        ppc32_classify,
-       ppc32_get_flags,
        ppc32_get_frame_entity,
        ppc32_set_frame_entity,
        ppc32_set_stack_bias,
@@ -921,6 +851,7 @@ static int ppc32_is_valid_clobber(const void *self, const char *clobber)
 const arch_isa_if_t ppc32_isa_if = {
        ppc32_init,
        ppc32_done,
+       NULL,             /* handle intrinsics */
        ppc32_get_n_reg_class,
        ppc32_get_reg_class,
        ppc32_get_reg_class_for_mode,
index aeb2d1f..4ae904b 100644 (file)
@@ -205,9 +205,6 @@ static int ppc32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                if (attr->flags & arch_irn_flags_rematerializable) {
                                        fprintf(F, " remat");
                                }
-                               if (attr->flags & arch_irn_flags_ignore) {
-                                       fprintf(F, " ignore");
-                               }
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
index a492fc0..ec2d5c4 100644 (file)
@@ -7,91 +7,6 @@
 $arch = "ppc32";
 $new_emit_syntax = 1;
 
-# The node description is done as a perl hash initializer with the
-# following structure:
-#
-# %nodes = (
-#
-# <op-name> => {
-#   "op_flags"  => "N|L|C|X|I|F|Y|H|c|K",
-#   "irn_flags" => "R|N|I"
-#   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
-#   "state"     => "floats|pinned|mem_pinned|exc_pinned",
-#   "args"      => [
-#                    { "type" => "type 1", "name" => "name 1" },
-#                    { "type" => "type 2", "name" => "name 2" },
-#                    ...
-#                  ],
-#   comment   => "any comment for constructor",
-#   reg_req   => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
-#   cmp_attr  => "c source code for comparing node attributes",
-#   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
-#   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
-#   mode      => "mode_Iu"          # optional, predefines the mode
-#   emit      => "emit code with templates",
-#   attr      => "attitional attribute arguments for constructor",
-#   init_attr => "emit attribute initialization template",
-#   rd_constructor => "c source code which constructs an ir_node",
-#   hash_func => "name of the hash function for this operation",
-#   latency   => "latency of this operation (can be float)"
-#   attr_type => "name of the attribute struct",
-# },
-#
-# ... # (all nodes you need to describe)
-#
-# ); # close the %nodes initializer
-
-# op_flags: flags for the operation, OPTIONAL (default is "N")
-# the op_flags correspond to the firm irop_flags:
-#   N   irop_flag_none
-#   L   irop_flag_labeled
-#   C   irop_flag_commutative
-#   X   irop_flag_cfopcode
-#   I   irop_flag_ip_cfopcode
-#   F   irop_flag_fragile
-#   Y   irop_flag_forking
-#   H   irop_flag_highlevel
-#   c   irop_flag_constlike
-#   K   irop_flag_keep
-#
-# irn_flags: special node flags, OPTIONAL (default is 0)
-# following irn_flags are supported:
-#   R   rematerializeable
-#   N   not spillable
-#   I   ignore for register allocation
-#
-# state: state of the operation, OPTIONAL (default is "floats")
-#
-# arity: arity of the operation, MUST NOT BE OMITTED
-#
-# args:  the OPTIONAL arguments of the node constructor (debug, irg and block
-#        are always the first 3 arguments and are always autmatically
-#        created)
-#        If this key is missing the following arguments will be created:
-#        for i = 1 .. arity: ir_node *op_i
-#        ir_mode *mode
-#
-# outs:  if a node defines more than one output, the names of the projections
-#        nodes having outs having automatically the mode mode_T
-#
-# comment: OPTIONAL comment for the node constructor
-#
-# rd_constructor: for every operation there will be a
-#      new_rd_<arch>_<op-name> function with the arguments from above
-#      which creates the ir_node corresponding to the defined operation
-#      you can either put the complete source code of this function here
-#
-#      This key is OPTIONAL. If omitted, the following constructor will
-#      be created:
-#      if (!op_<arch>_<op-name>) assert(0);
-#      for i = 1 to arity
-#         set in[i] = op_i
-#      done
-#      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
-#      return res
-#
-# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
-
 # register types:
 #   0 - no special type
 #   1 - caller save (register must be saved by the caller of a function)
index 1a634a6..2597c80 100755 (executable)
@@ -487,10 +487,8 @@ foreach my $op (keys(%nodes)) {
                                                $temp .= "\tflags |= arch_irn_flags_rematerializable;\n";
                                        } elsif ($flag eq "N") {
                                                $temp .= "\tflags |= arch_irn_flags_dont_spill;\n";
-                                       } elsif ($flag eq "I") {
-                                               $temp .= "\tflags |= arch_irn_flags_ignore;\n";
-                                       } elsif ($flag eq "S") {
-                                               $temp .= "\tflags |= arch_irn_flags_modify_sp;\n";
+                                       } else {
+                                               die "Fatal error: unknown flag $flag for ${op}\n";
                                        }
                                }
                                $temp .= "\n";
@@ -513,33 +511,6 @@ foreach my $op (keys(%nodes)) {
                        }
                        $temp .= "\n";
 
-                       # set flags for outs
-                       if (exists($n{"outs"})) {
-                               undef my @outs;
-                               @outs     = @{ $n{"outs"} };
-
-                               for (my $idx = 0; $idx <= $#outs; $idx++) {
-                                       # check, if we have additional flags annotated to out
-                                       if ($outs[$idx] =~ /:((S|I)(\|(S|I))*)/) {
-                                               my $flag_string = $1;
-                                               my $prefix = "";
-                                               my $flags  = "";
-
-                                               foreach my $flag (split(/\|/, $flag_string)) {
-                                                       if ($flag eq "I") {
-                                                               $flags .= $prefix."arch_irn_flags_ignore";
-                                                               $prefix = " | ";
-                                                       } elsif ($flag eq "S") {
-                                                               $flags .= $prefix."arch_irn_flags_modify_sp";
-                                                               $prefix = " | ";
-                                                       }
-                                               }
-
-                                               $temp .= "\tset_$arch\_out_flags(res, $flags, $idx);\n";
-                                       }
-                               }
-                       }
-
                        if (exists($n{"init_attr"})) {
                                $temp .= "\tattr = get_irn_generic_attr(res);\n";
                                $temp .= "\t".$n{"init_attr"}."\n";
@@ -899,6 +870,7 @@ TP_SEARCH:  foreach my $cur_type (keys(%cpu)) {
 sub mangle_requirements {
        my $reqs  = shift;
        my $class = shift;
+       my $flags = shift;
 
        my @alternatives = split(/ /, $reqs);
        for(my $idx = 0; $idx < scalar(@alternatives); $idx++) {
@@ -908,6 +880,10 @@ sub mangle_requirements {
        @alternatives = sort @alternatives;
 
        my $name = $class."_".join('_', @alternatives);
+       if (defined($flags)) {
+               $flags =~ s/\|/_/g;
+               $name .= "_$flags";
+       }
 
        return $name;
 }
@@ -961,13 +937,14 @@ sub build_inout_idx_class {
 
                for (my $idx = 0; $idx <= $#reqs; $idx++) {
                        my $class = undef;
+                       my ($req,) = split(/:/, $reqs[$idx]);
 
-                       if ($reqs[$idx] eq "none") {
+                       if ($req eq "none") {
                                $class = "none";
-                       } elsif (is_reg_class($reqs[$idx])) {
-                               $class = $reqs[$idx];
+                       } elsif (is_reg_class($req)) {
+                               $class = $req;
                        } else {
-                               my @regs = split(/ /, $reqs[$idx]);
+                               my @regs = split(/ /, $req);
 GET_CLASS:             foreach my $reg (@regs) {
                                        if ($reg =~ /!?(in|out)\_r\d+/ || $reg =~ /!in/) {
                                                $class = "UNKNOWN_CLASS";
@@ -1015,6 +992,7 @@ sub build_subset_class_func {
        my $idx   = shift;
        my $is_in = shift;
        my @regs  = split(/ /, shift);
+       my $flags = shift;
 
        my @idx_class = build_inout_idx_class($node, $op, !$is_in);
 
@@ -1165,7 +1143,7 @@ CHECK_REQS: foreach (@regs) {
 # Generate register requirements structure
 ###
 sub generate_requirements {
-       my $reqs  = shift;
+       my ($reqs, $flags) = split(/:/, shift);
        my $node  = shift;
        my $op    = shift;
        my $idx   = shift;
@@ -1173,6 +1151,17 @@ sub generate_requirements {
        my $class = "";
        my $result;
 
+       my @req_type_mask;
+       if (defined($flags)) {
+               foreach my $f (split(/|/, $flags)) {
+                       if ($f eq "I") {
+                               push(@req_type_mask, "arch_register_req_type_ignore");
+                       } elsif ($f eq "S") {
+                               push(@req_type_mask, "arch_register_req_type_produces_sp");
+                       }
+               }
+       }
+
        if ($reqs eq "none") {
 
                $result = <<EOF;
@@ -1186,10 +1175,12 @@ sub generate_requirements {
 
 EOF
        } elsif (is_reg_class($reqs)) {
+               push(@req_type_mask, "arch_register_req_type_normal");
+               my $reqtype = join(" | ", @req_type_mask);
                $class  = $reqs;
                $result = <<EOF;
 {
-       arch_register_req_type_normal,
+       ${reqtype},
        & ${arch}_reg_classes[CLASS_${arch}_${class}],
        NULL,        /* limit bitset */
        0,           /* same pos */
@@ -1199,9 +1190,8 @@ EOF
 EOF
 
        } else {
-               my @req_type_mask;
                my ($regclass, $limit_bitset, $same_pos, $different_pos)
-                       = build_subset_class_func($node, $op, $idx, $is_in, $reqs);
+                       = build_subset_class_func($node, $op, $idx, $is_in, $reqs, $flags);
 
                if (!defined($regclass)) {
                        die("Fatal error: Could not build subset for requirements '$reqs' of '$op' pos $idx ... exiting.\n");
@@ -1216,7 +1206,7 @@ EOF
                if ($different_pos != 0) {
                        push(@req_type_mask, "arch_register_req_type_must_be_different");
                }
-               my $reqtype      = join(" | ", @req_type_mask);
+               my $reqtype = join(" | ", @req_type_mask);
 
                if(!defined($limit_bitset)) {
                        $limit_bitset = "NULL";
@@ -1235,7 +1225,7 @@ EOF
 EOF
        }
 
-       my $name = "${arch}_requirements_".mangle_requirements($reqs, $class);
+       my $name = "${arch}_requirements_".mangle_requirements($reqs, $class, $flags);
        if(defined($requirements{$name})) {
                return $name;
        }
index 182fc99..ec5d4d9 100644 (file)
@@ -44,6 +44,8 @@
 #include "irhooks.h"
 #include "irtools.h"
 
+#include "beinfo.h"
+
 /* some constants fixing the positions of nodes predecessors
    in the in array */
 #define CALL_PARAM_OFFSET     2
@@ -179,6 +181,9 @@ new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mod
                edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
 
        hook_new_node(irg, res);
+       if (get_irg_phase_state(irg) == phase_backend) {
+               be_info_new_node(res);
+       }
 
        return res;
 }
index 79a2719..4dbae00 100644 (file)
@@ -370,6 +370,7 @@ struct ir_node {
        /* ------- For analyses -------- */
        ir_loop *loop;           /**< the loop the node is in. Access routines in irloop.h */
        struct ir_node **deps;   /**< Additional dependencies induced by state. */
+       void            *backend_info;
        irn_edges_info_t edge_info;  /**< Everlasting out edges. */
        /* ------- Opcode depending fields -------- */
        attr attr;               /**< The set of attributes of this node. Depends on opcode.