sparc: Improve handling of MemPerm nodes.
[libfirm] / ir / be / ia32 / ia32_transform.c
index efee8b5..a06ccd3 100644 (file)
@@ -292,7 +292,7 @@ static ir_node *gen_Const(ir_node *node)
                                                             mode);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_sc(load, floatent);
-                               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
+                               arch_add_irn_flags(load, arch_irn_flags_rematerializable);
                                res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res);
                        }
                } else {
@@ -317,7 +317,7 @@ static ir_node *gen_Const(ir_node *node)
                                                            ls_mode);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_sc(load, floatent);
-                               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
+                               arch_add_irn_flags(load, arch_irn_flags_rematerializable);
                                res = new_r_Proj(load, mode_vfp, pn_ia32_vfld_res);
                        }
                }
@@ -1111,15 +1111,19 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
 {
        dbg_info *dbgi;
        ir_node  *block, *new_block, *new_op1, *new_op2, *new_node;
+       ir_mode  *mode = get_irn_mode(node);
 
-       assert(! mode_is_float(get_irn_mode(node)));
+       assert(! mode_is_float(mode));
        assert(flags & match_immediate);
        assert((flags & ~(match_mode_neutral | match_immediate)) == 0);
 
+       if (get_mode_modulo_shift(mode) != 32)
+               panic("modulo shift!=32 not supported by ia32 backend");
+
        if (flags & match_mode_neutral) {
                op1     = ia32_skip_downconv(op1);
                new_op1 = be_transform_node(op1);
-       } else if (get_mode_size_bits(get_irn_mode(node)) != 32) {
+       } else if (get_mode_size_bits(mode) != 32) {
                new_op1 = create_upconv(op1, node);
        } else {
                new_op1 = be_transform_node(op1);
@@ -2094,17 +2098,6 @@ static ia32_condition_code_t relation_to_condition_code(ir_relation relation,
        }
 }
 
-static ir_node *get_flags_mode_b(ir_node *node, ia32_condition_code_t *cc_out)
-{
-       /* a mode_b value, we have to compare it against 0 */
-       dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *new_block = be_transform_node(get_nodes_block(node));
-       ir_node  *new_op    = be_transform_node(node);
-       ir_node  *flags     = new_bd_ia32_Test(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_op, new_op, false);
-       *cc_out  = ia32_cc_not_equal;
-       return flags;
-}
-
 static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out)
 {
        /* must have a Cmp as input */
@@ -2166,10 +2159,8 @@ static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out)
  */
 static ir_node *get_flags_node(ir_node *node, ia32_condition_code_t *cc_out)
 {
-       if (is_Cmp(node))
-               return get_flags_node_cmp(node, cc_out);
-       assert(get_irn_mode(node) == mode_b);
-       return get_flags_mode_b(node, cc_out);
+       assert(is_Cmp(node));
+       return get_flags_node_cmp(node, cc_out);
 }
 
 /**
@@ -2240,7 +2231,7 @@ static ir_node *gen_Load(ir_node *node)
                assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res
                                && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res
                                && (int)pn_ia32_Load_res == (int)pn_ia32_res);
-               arch_irn_add_flags(new_node, arch_irn_flags_rematerializable);
+               arch_add_irn_flags(new_node, arch_irn_flags_rematerializable);
        }
 
        SET_IA32_ORIG_NODE(new_node, node);
@@ -2837,6 +2828,8 @@ static ir_node *create_Switch(ir_node *node)
        set_ia32_op_type(new_node, ia32_AddrModeS);
        set_ia32_ls_mode(new_node, mode_Iu);
        SET_IA32_ORIG_NODE(new_node, node);
+       // FIXME This seems wrong. GCC uses PIC for switch on OS X.
+       get_ia32_attr(new_node)->data.am_sc_no_pic_adjust = true;
 
        return new_node;
 }
@@ -3015,7 +3008,8 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
                                return shifted == 0 || shifted == -1;
                        } else {
                                unsigned long shifted = (unsigned long)attr->offset;
-                               shifted >>= get_mode_size_bits(mode);
+                               shifted >>= get_mode_size_bits(mode)-1;
+                               shifted >>= 1;
                                return shifted == 0;
                        }
                }
@@ -3648,6 +3642,18 @@ static ir_node *gen_Mux(ir_node *node)
        }
 }
 
+static ir_node *gen_ia32_l_Setcc(ir_node *node)
+{
+       ia32_condition_code_t cc;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
+       ir_node  *cond      = get_irn_n(node, n_ia32_l_Setcc_cond);
+       ir_node  *flags     = get_flags_node(cond, &cc);
+       ir_node  *new_node  = new_bd_ia32_Setcc(dbgi, new_block, flags, cc);
+       SET_IA32_ORIG_NODE(new_node, node);
+       return new_node;
+}
 
 /**
  * Create a conversion from x87 state register to general purpose.
@@ -3923,7 +3929,7 @@ static ir_node *gen_Conv(ir_node *node)
                        }
                } else {
                        /* this should be optimized already, but who knows... */
-                       DEBUG_ONLY(ir_fprintf(stderr, "Debug warning: conv %+F is pointless\n", node));
+                       DEBUG_ONLY(ir_fprintf(stderr, "Debug warning: conv %+F is pointless\n", node);)
                        DB((dbg, LEVEL_1, "killed Conv(mode, mode) ..."));
                        return be_transform_node(op);
                }
@@ -4135,8 +4141,8 @@ static ir_node *gen_be_AddSP(ir_node *node)
        ir_node *new_node = gen_binop(node, sp, sz, new_bd_ia32_SubSP,
                                      match_am | match_immediate);
        assert(is_ia32_SubSP(new_node));
-       arch_irn_set_register(new_node, pn_ia32_SubSP_stack,
-                             &ia32_registers[REG_ESP]);
+       arch_set_irn_register_out(new_node, pn_ia32_SubSP_stack,
+                                 &ia32_registers[REG_ESP]);
        return new_node;
 }
 
@@ -4151,8 +4157,8 @@ static ir_node *gen_be_SubSP(ir_node *node)
        ir_node *new_node = gen_binop(node, sp, sz, new_bd_ia32_AddSP,
                                      match_am | match_immediate);
        assert(is_ia32_AddSP(new_node));
-       arch_irn_set_register(new_node, pn_ia32_AddSP_stack,
-                             &ia32_registers[REG_ESP]);
+       arch_set_irn_register_out(new_node, pn_ia32_AddSP_stack,
+                                 &ia32_registers[REG_ESP]);
        return new_node;
 }
 
@@ -4193,7 +4199,7 @@ static ir_node *gen_Phi(ir_node *node)
        copy_node_attr(irg, node, phi);
        be_duplicate_deps(node, phi);
 
-       arch_set_out_register_req(phi, 0, req);
+       arch_set_irn_register_req_out(phi, 0, req);
 
        be_enqueue_preds(node);
 
@@ -4835,7 +4841,8 @@ static ir_node *gen_be_Call(ir_node *node)
        i    = get_irn_arity(node) - 1;
        fpcw = be_transform_node(get_irn_n(node, i--));
        for (; i >= n_be_Call_first_arg; --i) {
-               arch_register_req_t const *const req = arch_get_register_req(node, i);
+               arch_register_req_t const *const req
+                       = arch_get_irn_register_req_in(node, i);
                ir_node *const reg_parm = be_transform_node(get_irn_n(node, i));
 
                assert(req->type == arch_register_req_type_limited);
@@ -4931,7 +4938,7 @@ static ir_node *gen_return_address(ir_node *node)
                assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res
                                && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res
                                && (int)pn_ia32_Load_res == (int)pn_ia32_res);
-               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
+               arch_add_irn_flags(load, arch_irn_flags_rematerializable);
        }
 
        SET_IA32_ORIG_NODE(load, node);
@@ -4982,7 +4989,7 @@ static ir_node *gen_frame_address(ir_node *node)
                assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res
                                && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res
                                && (int)pn_ia32_Load_res == (int)pn_ia32_res);
-               arch_irn_add_flags(load, arch_irn_flags_rematerializable);
+               arch_add_irn_flags(load, arch_irn_flags_rematerializable);
        }
 
        SET_IA32_ORIG_NODE(load, node);
@@ -5567,7 +5574,7 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
 static ir_node *gen_be_IncSP(ir_node *node)
 {
        ir_node *res = be_duplicate_node(node);
-       arch_irn_add_flags(res, arch_irn_flags_modify_flags);
+       arch_add_irn_flags(res, arch_irn_flags_modify_flags);
 
        return res;
 }
@@ -5589,7 +5596,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node)
        }
        /* transform call modes */
        if (mode_is_data(mode)) {
-               const arch_register_class_t *cls = arch_get_irn_reg_class_out(node);
+               const arch_register_class_t *cls = arch_get_irn_reg_class(node);
                mode = cls->mode;
        }
 
@@ -5603,8 +5610,8 @@ static ir_node *gen_Proj_be_Call(ir_node *node)
        } else if (proj == pn_be_Call_X_regular) {
                proj = pn_ia32_Call_X_regular;
        } else {
-               arch_register_req_t const *const req    = arch_get_register_req_out(node);
-               int                        const n_outs = arch_irn_get_n_outs(new_call);
+               arch_register_req_t const *const req    = arch_get_irn_register_req(node);
+               int                        const n_outs = arch_get_irn_n_outs(new_call);
                int                              i;
 
                assert(proj      >= pn_be_Call_first_res);
@@ -5612,7 +5619,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node)
 
                for (i = 0; i < n_outs; ++i) {
                        arch_register_req_t const *const new_req
-                               = arch_get_out_register_req(new_call, i);
+                               = arch_get_irn_register_req_out(new_call, i);
 
                        if (!(new_req->type & arch_register_req_type_limited) ||
                            new_req->cls      != req->cls                     ||
@@ -5659,7 +5666,7 @@ static ir_node *gen_Proj_ASM(ir_node *node)
        long     pos      = get_Proj_proj(node);
 
        if (mode == mode_M) {
-               pos = arch_irn_get_n_outs(new_pred)-1;
+               pos = arch_get_irn_n_outs(new_pred)-1;
        } else if (mode_is_int(mode) || mode_is_reference(mode)) {
                mode = mode_Iu;
        } else if (mode_is_float(mode)) {
@@ -5772,6 +5779,7 @@ static void register_transformers(void)
        be_set_transform_function(op_ia32_l_LLtoFloat, gen_ia32_l_LLtoFloat);
        be_set_transform_function(op_ia32_l_Mul,       gen_ia32_l_Mul);
        be_set_transform_function(op_ia32_l_Sbb,       gen_ia32_l_Sbb);
+       be_set_transform_function(op_ia32_l_Setcc,     gen_ia32_l_Setcc);
        be_set_transform_function(op_ia32_l_Sub,       gen_ia32_l_Sub);
        be_set_transform_function(op_ia32_GetEIP,      be_duplicate_node);
        be_set_transform_function(op_ia32_Minus64Bit,  be_duplicate_node);
@@ -5885,7 +5893,11 @@ static void postprocess_fp_call_results(void)
                                        assert((long)pn_ia32_xStore_X_except == (long)pn_ia32_vfst_X_except);
 
                                        exchange(succ, st);
-                               } else if (new_res == NULL) {
+
+                                       continue;
+                               }
+
+                               if (new_res == NULL) {
                                        dbg_info *db       = get_irn_dbg_info(call);
                                        ir_node  *block    = get_nodes_block(call);
                                        ir_node  *frame    = get_irg_frame(current_ir_graph);