Get rid of be_SetSP.
[libfirm] / ir / be / ia32 / ia32_finish.c
index 99340cc..03d3802 100644 (file)
@@ -74,8 +74,8 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
        noreg   = ia32_new_NoReg_gp(cg);
        noreg_fp = ia32_new_NoReg_fp(cg);
        nomem   = new_rd_NoMem(cg->irg);
-       in1     = get_irn_n(irn, 2);
-       in2     = get_irn_n(irn, 3);
+       in1     = get_irn_n(irn, n_ia32_binary_left);
+       in2     = get_irn_n(irn, n_ia32_binary_right);
        in1_reg = arch_get_irn_register(cg->arch_env, in1);
        in2_reg = arch_get_irn_register(cg->arch_env, in2);
        out_reg = get_ia32_out_reg(irn, 0);
@@ -93,13 +93,14 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
        if(mode_is_float(mode)) {
                int size;
                ir_entity *entity;
+               ir_mode *op_mode = get_ia32_ls_mode(irn);
 
-               res = new_rd_ia32_xXor(dbg, irg, block, noreg, noreg, in2, noreg_fp, nomem);
-               size = get_mode_size_bits(mode);
+               res = new_rd_ia32_xXor(dbg, irg, block, noreg, noreg, nomem, in2, noreg_fp);
+               size = get_mode_size_bits(op_mode);
                entity = ia32_gen_fp_known_const(size == 32 ? ia32_SSIGN : ia32_DSIGN);
                set_ia32_am_sc(res, entity);
                set_ia32_op_type(res, ia32_AddrModeS);
-               set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
+               set_ia32_ls_mode(res, op_mode);
        } else {
                res = new_rd_ia32_Neg(dbg, irg, block, in2);
        }
@@ -110,11 +111,11 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
 
        /* generate the add */
        if (mode_is_float(mode)) {
-               res = new_rd_ia32_xAdd(dbg, irg, block, noreg, noreg, res, in1, nomem);
+               res = new_rd_ia32_xAdd(dbg, irg, block, noreg, noreg, nomem, res, in1);
                set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
                set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
        } else {
-               res = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, res, in1, nomem);
+               res = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, nomem, res, in1);
                set_ia32_am_support(res, ia32_am_Full, ia32_am_binary);
                set_ia32_commutative(res);
        }
@@ -171,6 +172,22 @@ static ir_node *create_immediate_from_am(ia32_code_gen_t *cg,
        return res;
 }
 
+static int is_am_one(const ir_node *node)
+{
+       int        offset  = get_ia32_am_offs_int(node);
+       ir_entity *entity  = get_ia32_am_sc(node);
+
+       return offset == 1 && entity == NULL;
+}
+
+static int is_am_minus_one(const ir_node *node)
+{
+       int        offset  = get_ia32_am_offs_int(node);
+       ir_entity *entity  = get_ia32_am_sc(node);
+
+       return offset == -1 && entity == NULL;
+}
+
 /**
  * Transforms a LEA into an Add or SHL if possible.
  * THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
@@ -243,8 +260,7 @@ static void ia32_transform_lea_to_add_or_shl(ir_node *node, ia32_code_gen_t *cg)
                        }
 #endif
                        op1 = base;
-                       op2 = create_immediate_from_am(cg, node);
-                       goto make_add;
+                       goto make_add_immediate;
                }
                if(scale == 0 && !has_immediates) {
                        op1 = base;
@@ -255,20 +271,19 @@ static void ia32_transform_lea_to_add_or_shl(ir_node *node, ia32_code_gen_t *cg)
                return;
        } else if(out_reg == index_reg) {
                if(base == NULL) {
-                  if(has_immediates && scale == 0) {
-                          op1 = index;
-                          op2 = create_immediate_from_am(cg, node);
-                          goto make_add;
-                  } else if(!has_immediates && scale > 0) {
-                          op1 = index;
-                          op2 = create_immediate_from_int(cg, scale);
-                          goto make_shl;
-                  } else if(!has_immediates) {
+                       if(has_immediates && scale == 0) {
+                               op1 = index;
+                               goto make_add_immediate;
+                       } else if(!has_immediates && scale > 0) {
+                               op1 = index;
+                               op2 = create_immediate_from_int(cg, scale);
+                               goto make_shl;
+                       } else if(!has_immediates) {
 #ifdef DEBUG_libfirm
                                ir_fprintf(stderr, "Optimisation warning: found lea which is "
                                           "just a copy\n");
 #endif
-                  }
+                       }
                } else if(scale == 0 && !has_immediates) {
                        op1 = index;
                        op2 = base;
@@ -281,14 +296,32 @@ static void ia32_transform_lea_to_add_or_shl(ir_node *node, ia32_code_gen_t *cg)
                return;
        }
 
+make_add_immediate:
+       if(cg->isa->opt & IA32_OPT_INCDEC) {
+               if(is_am_one(node)) {
+                       dbgi  = get_irn_dbg_info(node);
+                       block = get_nodes_block(node);
+                       res   = new_rd_ia32_Inc(dbgi, irg, block, op1);
+                       arch_set_irn_register(arch_env, res, out_reg);
+                       goto exchange;
+               }
+               if(is_am_minus_one(node)) {
+                       dbgi  = get_irn_dbg_info(node);
+                       block = get_nodes_block(node);
+                       res   = new_rd_ia32_Dec(dbgi, irg, block, op1);
+                       arch_set_irn_register(arch_env, res, out_reg);
+                       goto exchange;
+               }
+       }
+       op2 = create_immediate_from_am(cg, node);
+
 make_add:
        dbgi  = get_irn_dbg_info(node);
        block = get_nodes_block(node);
        noreg = ia32_new_NoReg_gp(cg);
        nomem = new_NoMem();
-       res   = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, op1, op2, nomem);
+       res   = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, nomem, op1, op2);
        arch_set_irn_register(arch_env, res, out_reg);
-       set_ia32_op_type(res, ia32_Normal);
        set_ia32_commutative(res);
        goto exchange;
 
@@ -299,7 +332,6 @@ make_shl:
        nomem = new_NoMem();
        res   = new_rd_ia32_Shl(dbgi, irg, block, op1, op2);
        arch_set_irn_register(arch_env, res, out_reg);
-       set_ia32_op_type(res, ia32_Normal);
        goto exchange;
 
 exchange:
@@ -429,7 +461,7 @@ static void assure_should_be_same_requirements(ia32_code_gen_t *cg,
                }
 
                /* for commutative nodes we can simply swap the left/right */
-               if(is_ia32_commutative(node) && uses_out_reg_pos == 3) {
+               if(is_ia32_commutative(node) && uses_out_reg_pos == n_ia32_binary_right) {
                        ia32_swap_left_right(node);
                        DBG((dbg, LEVEL_1, "swapped left/right input of %+F to resolve "
                             "should be same constraint\n", node));
@@ -478,7 +510,8 @@ static void assure_should_be_same_requirements(ia32_code_gen_t *cg,
 
                if (pnc & pn_Cmp_Uo) {
                        ir_node *tmp;
-                       int idx1 = 2, idx2 = 3;
+                       int idx1 = n_ia32_binary_left;
+                       int idx2 = n_ia32_binary_right;
 
                        if (is_ia32_xCmpCMov(node)) {
                                idx1 = 0;
@@ -549,6 +582,7 @@ static void fix_am_source(ir_node *irn, void *env) {
                        ir_mode               *proj_mode;
                        ir_node               *load;
                        ir_node               *load_res;
+                       ir_node               *mem;
                        int                    pnres;
 
                        /* should_be same constraint is fullfilled, nothing to do */
@@ -562,17 +596,15 @@ static void fix_am_source(ir_node *irn, void *env) {
 
                        /* turn back address mode */
                        same_cls = arch_register_get_class(same_reg);
+                       mem = get_irn_n(irn, n_ia32_mem);
+                       assert(get_irn_mode(mem) == mode_M);
                        if (same_cls == &ia32_reg_classes[CLASS_ia32_gp]) {
-                               load  = new_rd_ia32_Load(dbgi, irg, block, base, index,
-                                                        get_irn_n(irn, 4));
-                               assert(get_irn_mode(get_irn_n(irn,4)) == mode_M);
+                               load      = new_rd_ia32_Load(dbgi, irg, block, base, index, mem);
                                pnres     = pn_ia32_Load_res;
                                proj_mode = mode_Iu;
                        } else if (same_cls == &ia32_reg_classes[CLASS_ia32_xmm]) {
-                               load  = new_rd_ia32_xLoad(dbgi, irg, block, base, index,
-                                                         get_irn_n(irn, 4),
-                                                         get_ia32_ls_mode(irn));
-                               assert(get_irn_mode(get_irn_n(irn,4)) == mode_M);
+                               load      = new_rd_ia32_xLoad(dbgi, irg, block, base, index, mem,
+                                                             get_ia32_ls_mode(irn));
                                pnres     = pn_ia32_xLoad_res;
                                proj_mode = mode_E;
                        } else {
@@ -580,16 +612,8 @@ static void fix_am_source(ir_node *irn, void *env) {
                        }
 
                        /* copy address mode information to load */
-                       set_ia32_ls_mode(load, get_ia32_ls_mode(irn));
                        set_ia32_op_type(load, ia32_AddrModeS);
-                       set_ia32_am_scale(load, get_ia32_am_scale(irn));
-                       set_ia32_am_sc(load, get_ia32_am_sc(irn));
-                       if(is_ia32_am_sc_sign(irn))
-                               set_ia32_am_sc_sign(load);
-                       add_ia32_am_offs_int(load, get_ia32_am_offs_int(irn));
-                       set_ia32_frame_ent(load, get_ia32_frame_ent(irn));
-                       if (is_ia32_use_frame(irn))
-                               set_ia32_use_frame(load);
+                       ia32_copy_am_attrs(load, irn);
 
                        /* insert the load into schedule */
                        sched_add_before(irn, load);
@@ -600,7 +624,7 @@ static void fix_am_source(ir_node *irn, void *env) {
                        arch_set_irn_register(cg->arch_env, load_res, out_reg);
 
                        /* set the new input operand */
-                       set_irn_n(irn, 3, load_res);
+                       set_irn_n(irn, n_ia32_binary_right, load_res);
                        if(get_irn_mode(irn) == mode_T) {
                                const ir_edge_t *edge, *next;
                                foreach_out_edge_safe(irn, edge, next) {
@@ -617,8 +641,8 @@ static void fix_am_source(ir_node *irn, void *env) {
                        }
 
                        /* this is a normal node now */
-                       set_irn_n(irn, 0, noreg);
-                       set_irn_n(irn, 1, noreg);
+                       set_irn_n(irn, n_ia32_base,  noreg);
+                       set_irn_n(irn, n_ia32_index, noreg);
                        set_ia32_op_type(irn, ia32_Normal);
                        break;
                }