no need to pass environment stuff aroudn that can be retireved from irg
[libfirm] / ir / be / ia32 / ia32_transform.c
index 973e788..f580cc9 100644 (file)
 #define DFP_INTMAX "9223372036854775807"
 #define ULL_BIAS   "18446744073709551616"
 
-#define ENT_SFP_SIGN ".LC_ia32_sfp_sign"
-#define ENT_DFP_SIGN ".LC_ia32_dfp_sign"
-#define ENT_SFP_ABS  ".LC_ia32_sfp_abs"
-#define ENT_DFP_ABS  ".LC_ia32_dfp_abs"
-#define ENT_ULL_BIAS ".LC_ia32_ull_bias"
+#define ENT_SFP_SIGN "C_ia32_sfp_sign"
+#define ENT_DFP_SIGN "C_ia32_dfp_sign"
+#define ENT_SFP_ABS  "C_ia32_sfp_abs"
+#define ENT_DFP_ABS  "C_ia32_dfp_abs"
+#define ENT_ULL_BIAS "C_ia32_ull_bias"
 
 #define mode_vfp       (ia32_reg_classes[CLASS_ia32_vfp].mode)
 #define mode_xmm    (ia32_reg_classes[CLASS_ia32_xmm].mode)
@@ -201,7 +201,7 @@ static bool is_simple_sse_Const(ir_node *node)
  */
 static ir_node *get_symconst_base(void)
 {
-       if (env_cg->birg->main_env->options->pic) {
+       if (be_get_irg_options(env_cg->irg)->pic) {
                return arch_code_generator_get_pic_base(env_cg);
        }
 
@@ -520,7 +520,7 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct)
 
                set_entity_ld_ident(ent, get_entity_ident(ent));
                add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
-               set_entity_visibility(ent, ir_visibility_local);
+               set_entity_visibility(ent, ir_visibility_private);
 
                if (kct == ia32_ULLBIAS) {
                        ir_initializer_t *initializer = create_initializer_compound(2);
@@ -709,8 +709,8 @@ static int is_downconv(const ir_node *node)
                return 0;
 
        /* we only want to skip the conv when we're the only user
-        * (not optimal but for now...)
-        */
+        * (because this test is used in the context of address-mode selection
+        *  and we don't want to use address mode for multiple users) */
        if (get_irn_n_edges(node) > 1)
                return 0;
 
@@ -722,7 +722,7 @@ static int is_downconv(const ir_node *node)
                get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
 }
 
-/* Skip all Down-Conv's on a given node and return the resulting node. */
+/** Skip all Down-Conv's on a given node and return the resulting node. */
 ir_node *ia32_skip_downconv(ir_node *node)
 {
        while (is_downconv(node))
@@ -731,6 +731,37 @@ ir_node *ia32_skip_downconv(ir_node *node)
        return node;
 }
 
+static bool is_sameconv(ir_node *node)
+{
+       ir_mode *src_mode;
+       ir_mode *dest_mode;
+
+       if (!is_Conv(node))
+               return 0;
+
+       /* we only want to skip the conv when we're the only user
+        * (because this test is used in the context of address-mode selection
+        *  and we don't want to use address mode for multiple users) */
+       if (get_irn_n_edges(node) > 1)
+               return 0;
+
+       src_mode  = get_irn_mode(get_Conv_op(node));
+       dest_mode = get_irn_mode(node);
+       return
+               ia32_mode_needs_gp_reg(src_mode)  &&
+               ia32_mode_needs_gp_reg(dest_mode) &&
+               get_mode_size_bits(dest_mode) == get_mode_size_bits(src_mode);
+}
+
+/** Skip all signedness convs */
+static ir_node *ia32_skip_sameconv(ir_node *node)
+{
+       while (is_sameconv(node))
+               node = get_Conv_op(node);
+
+       return node;
+}
+
 static ir_node *create_upconv(ir_node *node, ir_node *orig_node)
 {
        ir_mode  *mode = get_irn_mode(node);
@@ -798,6 +829,11 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                if (op1 != NULL) {
                        op1 = ia32_skip_downconv(op1);
                }
+       } else {
+               op2 = ia32_skip_sameconv(op2);
+               if (op1 != NULL) {
+                       op1 = ia32_skip_sameconv(op1);
+               }
        }
 
        /* match immediates. firm nodes are normalized: constants are always on the
@@ -1000,7 +1036,7 @@ static ir_node *get_fpcw(void)
        if (initial_fpcw != NULL)
                return initial_fpcw;
 
-       fpcw         = be_abi_get_ignore_irn(env_cg->birg->abi,
+       fpcw         = be_abi_get_ignore_irn(be_get_irg_abi(env_cg->irg),
                                             &ia32_fp_cw_regs[REG_FPCW]);
        initial_fpcw = be_transform_node(fpcw);
 
@@ -2004,7 +2040,6 @@ static ir_node *gen_Load(ir_node *node)
        ir_node  *index;
        dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_mode  *mode    = get_Load_mode(node);
-       ir_mode  *res_mode;
        ir_node  *new_node;
        ia32_address_t addr;
 
@@ -2030,11 +2065,9 @@ static ir_node *gen_Load(ir_node *node)
                if (ia32_cg_config.use_sse2) {
                        new_node = new_bd_ia32_xLoad(dbgi, block, base, index, new_mem,
                                                     mode);
-                       res_mode = mode_xmm;
                } else {
                        new_node = new_bd_ia32_vfld(dbgi, block, base, index, new_mem,
                                                    mode);
-                       res_mode = mode_vfp;
                }
        } else {
                assert(mode != mode_b);
@@ -2046,7 +2079,6 @@ static ir_node *gen_Load(ir_node *node)
                } else {
                        new_node = new_bd_ia32_Load(dbgi, block, base, index, new_mem);
                }
-               res_mode = mode_Iu;
        }
 
        set_irn_pinned(new_node, get_irn_pinned(node));
@@ -2210,7 +2242,6 @@ static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
        ir_node        *mux_true  = get_Mux_true(node);
        ir_node        *mux_false = get_Mux_false(node);
        ir_node        *cond;
-       ir_node        *new_mem;
        dbg_info       *dbgi;
        ir_node        *block;
        ir_node        *new_block;
@@ -2244,7 +2275,6 @@ static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
        dbgi      = get_irn_dbg_info(node);
        block     = get_nodes_block(node);
        new_block = be_transform_node(block);
-       new_mem   = be_transform_node(mem);
        new_node  = new_bd_ia32_SetccMem(dbgi, new_block, addr.base,
                                         addr.index, addr.mem, flags, pnc);
        set_address(new_node, &addr);
@@ -3116,10 +3146,10 @@ static ir_entity *ia32_create_const_array(ir_node *c0, ir_node *c1, ir_mode **ne
        tp = ia32_create_float_type(mode, 4);
        tp = ia32_create_float_array(tp);
 
-       ent = new_entity(get_glob_type(), ia32_unique_id(".LC%u"), tp);
+       ent = new_entity(get_glob_type(), id_unique("C%u"), tp);
 
        set_entity_ld_ident(ent, get_entity_ident(ent));
-       set_entity_visibility(ent, ir_visibility_local);
+       set_entity_visibility(ent, ir_visibility_private);
        add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
 
        initializer = create_initializer_compound(2);
@@ -3442,13 +3472,6 @@ static ir_node *gen_Mux(ir_node *node)
                        setcc_transform_t res;
                        int step;
 
-                       /* check if flags is a cmp node and we are the only user,
-                          i.e no other user yet */
-                       int permutate_allowed = 0;
-                       if (is_ia32_Cmp(flags) && get_irn_n_edges(flags) == 0) {
-                               /* yes, we can permutate its inputs */
-                               permutate_allowed = 1;
-                       }
                        find_const_transform(pnc, tv_true, tv_false, &res);
                        new_node = node;
                        if (res.permutate_cmp_ins) {
@@ -4392,15 +4415,6 @@ static ir_node *gen_ia32_l_FloattoLL(ir_node *node)
        return mem;
 }
 
-/**
- * the BAD transformer.
- */
-static ir_node *bad_transform(ir_node *node)
-{
-       panic("No transform function for %+F available.", node);
-       return NULL;
-}
-
 static ir_node *gen_Proj_l_FloattoLL(ir_node *node)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
@@ -4657,7 +4671,7 @@ static ir_node *gen_Proj_CopyB(ir_node *node)
        long     proj      = get_Proj_proj(node);
 
        switch (proj) {
-       case pn_CopyB_M_regular:
+       case pn_CopyB_M:
                if (is_ia32_CopyB_i(new_pred)) {
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_i_M);
                } else if (is_ia32_CopyB(new_pred)) {
@@ -4742,7 +4756,7 @@ static ir_node *gen_be_Call(ir_node *node)
 
        /* special case for PIC trampoline calls */
        old_no_pic_adjust = no_pic_adjust;
-       no_pic_adjust     = env_cg->birg->main_env->options->pic;
+       no_pic_adjust     = be_get_irg_options(env_cg->irg)->pic;
 
        match_arguments(&am, src_block, NULL, src_ptr, src_mem,
                        match_am | match_immediate);
@@ -5558,7 +5572,7 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
  */
 static ir_node *gen_Proj_Bound(ir_node *node)
 {
-       ir_node *new_node, *block;
+       ir_node *new_node;
        ir_node *pred = get_Proj_pred(node);
 
        switch (get_Proj_proj(node)) {
@@ -5566,11 +5580,9 @@ static ir_node *gen_Proj_Bound(ir_node *node)
                return be_transform_node(get_Bound_mem(pred));
        case pn_Bound_X_regular:
                new_node = be_transform_node(pred);
-               block    = get_nodes_block(new_node);
                return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_true);
        case pn_Bound_X_except:
                new_node = be_transform_node(pred);
-               block    = get_nodes_block(new_node);
                return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_false);
        case pn_Bound_res:
                return be_transform_node(get_Bound_index(pred));
@@ -5684,97 +5696,70 @@ static ir_node *gen_Proj(ir_node *node)
 static void register_transformers(void)
 {
        /* first clear the generic function pointer for all ops */
-       clear_irp_opcodes_generic_func();
-
-#define GEN(a)   { be_transform_func *func = gen_##a; op_##a->ops.generic = (op_func) func; }
-#define BAD(a)   op_##a->ops.generic = (op_func)bad_transform
-
-       GEN(Add);
-       GEN(Sub);
-       GEN(Mul);
-       GEN(Mulh);
-       GEN(And);
-       GEN(Or);
-       GEN(Eor);
-
-       GEN(Shl);
-       GEN(Shr);
-       GEN(Shrs);
-       GEN(Rotl);
-
-       GEN(Quot);
-
-       GEN(Div);
-       GEN(Mod);
-       GEN(DivMod);
-
-       GEN(Minus);
-       GEN(Conv);
-       GEN(Abs);
-       GEN(Not);
-
-       GEN(Load);
-       GEN(Store);
-       GEN(Cond);
-
-       GEN(Cmp);
-       GEN(ASM);
-       GEN(CopyB);
-       GEN(Mux);
-       GEN(Proj);
-       GEN(Phi);
-       GEN(Jmp);
-       GEN(IJmp);
-       GEN(Bound);
-
-       /* transform ops from intrinsic lowering */
-       GEN(ia32_l_Add);
-       GEN(ia32_l_Adc);
-       GEN(ia32_l_Mul);
-       GEN(ia32_l_IMul);
-       GEN(ia32_l_ShlDep);
-       GEN(ia32_l_ShrDep);
-       GEN(ia32_l_SarDep);
-       GEN(ia32_l_ShlD);
-       GEN(ia32_l_ShrD);
-       GEN(ia32_l_Sub);
-       GEN(ia32_l_Sbb);
-       GEN(ia32_l_LLtoFloat);
-       GEN(ia32_l_FloattoLL);
-
-       GEN(Const);
-       GEN(SymConst);
-       GEN(Unknown);
-
-       /* we should never see these nodes */
-       BAD(Raise);
-       BAD(Sel);
-       BAD(InstOf);
-       BAD(Cast);
-       BAD(Free);
-       BAD(Tuple);
-       BAD(Id);
-       //BAD(Bad);
-       BAD(Confirm);
-       BAD(Filter);
-       BAD(CallBegin);
-       BAD(EndReg);
-       BAD(EndExcept);
-
-       /* handle builtins */
-       GEN(Builtin);
-
-       /* handle generic backend nodes */
-       GEN(be_FrameAddr);
-       GEN(be_Call);
-       GEN(be_IncSP);
-       GEN(be_Return);
-       GEN(be_AddSP);
-       GEN(be_SubSP);
-       GEN(be_Copy);
-
-#undef GEN
-#undef BAD
+       be_start_transform_setup();
+
+       be_set_transform_function(op_Abs,              gen_Abs);
+       be_set_transform_function(op_Add,              gen_Add);
+       be_set_transform_function(op_And,              gen_And);
+       be_set_transform_function(op_ASM,              gen_ASM);
+       be_set_transform_function(op_be_AddSP,         gen_be_AddSP);
+       be_set_transform_function(op_be_Call,          gen_be_Call);
+       be_set_transform_function(op_be_Copy,          gen_be_Copy);
+       be_set_transform_function(op_be_FrameAddr,     gen_be_FrameAddr);
+       be_set_transform_function(op_be_IncSP,         gen_be_IncSP);
+       be_set_transform_function(op_be_Return,        gen_be_Return);
+       be_set_transform_function(op_be_SubSP,         gen_be_SubSP);
+       be_set_transform_function(op_Bound,            gen_Bound);
+       be_set_transform_function(op_Builtin,          gen_Builtin);
+       be_set_transform_function(op_Cmp,              gen_Cmp);
+       be_set_transform_function(op_Cond,             gen_Cond);
+       be_set_transform_function(op_Const,            gen_Const);
+       be_set_transform_function(op_Conv,             gen_Conv);
+       be_set_transform_function(op_CopyB,            gen_CopyB);
+       be_set_transform_function(op_Div,              gen_Div);
+       be_set_transform_function(op_DivMod,           gen_DivMod);
+       be_set_transform_function(op_Eor,              gen_Eor);
+       be_set_transform_function(op_ia32_l_Adc,       gen_ia32_l_Adc);
+       be_set_transform_function(op_ia32_l_Add,       gen_ia32_l_Add);
+       be_set_transform_function(op_ia32_Leave,       be_duplicate_node);
+       be_set_transform_function(op_ia32_l_FloattoLL, gen_ia32_l_FloattoLL);
+       be_set_transform_function(op_ia32_l_IMul,      gen_ia32_l_IMul);
+       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_SarDep,    gen_ia32_l_SarDep);
+       be_set_transform_function(op_ia32_l_Sbb,       gen_ia32_l_Sbb);
+       be_set_transform_function(op_ia32_l_ShlDep,    gen_ia32_l_ShlDep);
+       be_set_transform_function(op_ia32_l_ShlD,      gen_ia32_l_ShlD);
+       be_set_transform_function(op_ia32_l_ShrDep,    gen_ia32_l_ShrDep);
+       be_set_transform_function(op_ia32_l_ShrD,      gen_ia32_l_ShrD);
+       be_set_transform_function(op_ia32_l_Sub,       gen_ia32_l_Sub);
+       be_set_transform_function(op_ia32_Minus64Bit,  be_duplicate_node);
+       be_set_transform_function(op_ia32_NoReg_GP,    be_duplicate_node);
+       be_set_transform_function(op_ia32_NoReg_VFP,   be_duplicate_node);
+       be_set_transform_function(op_ia32_NoReg_XMM,   be_duplicate_node);
+       be_set_transform_function(op_ia32_PopEbp,      be_duplicate_node);
+       be_set_transform_function(op_ia32_Push,        be_duplicate_node);
+       be_set_transform_function(op_IJmp,             gen_IJmp);
+       be_set_transform_function(op_Jmp,              gen_Jmp);
+       be_set_transform_function(op_Load,             gen_Load);
+       be_set_transform_function(op_Minus,            gen_Minus);
+       be_set_transform_function(op_Mod,              gen_Mod);
+       be_set_transform_function(op_Mul,              gen_Mul);
+       be_set_transform_function(op_Mulh,             gen_Mulh);
+       be_set_transform_function(op_Mux,              gen_Mux);
+       be_set_transform_function(op_Not,              gen_Not);
+       be_set_transform_function(op_Or,               gen_Or);
+       be_set_transform_function(op_Phi,              gen_Phi);
+       be_set_transform_function(op_Proj,             gen_Proj);
+       be_set_transform_function(op_Quot,             gen_Quot);
+       be_set_transform_function(op_Rotl,             gen_Rotl);
+       be_set_transform_function(op_Shl,              gen_Shl);
+       be_set_transform_function(op_Shr,              gen_Shr);
+       be_set_transform_function(op_Shrs,             gen_Shrs);
+       be_set_transform_function(op_Store,            gen_Store);
+       be_set_transform_function(op_Sub,              gen_Sub);
+       be_set_transform_function(op_SymConst,         gen_SymConst);
+       be_set_transform_function(op_Unknown,          gen_Unknown);
 }
 
 /**
@@ -5784,9 +5769,6 @@ static void ia32_pretransform_node(void)
 {
        ia32_code_gen_t *cg = env_cg;
 
-       cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
-       cg->unknown_vfp = be_pre_transform_node(cg->unknown_vfp);
-       cg->unknown_xmm = be_pre_transform_node(cg->unknown_xmm);
        cg->noreg_gp    = be_pre_transform_node(cg->noreg_gp);
        cg->noreg_vfp   = be_pre_transform_node(cg->noreg_vfp);
        cg->noreg_xmm   = be_pre_transform_node(cg->noreg_xmm);
@@ -5797,91 +5779,6 @@ static void ia32_pretransform_node(void)
        get_fpcw();
 }
 
-/**
- * Walker, checks if all ia32 nodes producing more than one result have their
- * Projs, otherwise creates new Projs and keeps them using a be_Keep node.
- */
-static void add_missing_keep_walker(ir_node *node, void *data)
-{
-       int              n_outs, i;
-       unsigned         found_projs = 0;
-       const ir_edge_t *edge;
-       ir_mode         *mode = get_irn_mode(node);
-       ir_node         *last_keep;
-       (void) data;
-       if (mode != mode_T)
-               return;
-       if (!is_ia32_irn(node))
-               return;
-
-       n_outs = arch_irn_get_n_outs(node);
-       if (n_outs <= 0)
-               return;
-       if (is_ia32_SwitchJmp(node))
-               return;
-
-       assert(n_outs < (int) sizeof(unsigned) * 8);
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               int      pn;
-
-               /* The node could be kept */
-               if (is_End(proj))
-                       continue;
-
-               if (get_irn_mode(proj) == mode_M)
-                       continue;
-
-               pn = get_Proj_proj(proj);
-               assert(pn < n_outs);
-               found_projs |= 1 << pn;
-       }
-
-
-       /* are keeps missing? */
-       last_keep = NULL;
-       for (i = 0; i < n_outs; ++i) {
-               ir_node                     *block;
-               ir_node                     *in[1];
-               const arch_register_req_t   *req;
-               const arch_register_class_t *cls;
-
-               if (found_projs & (1 << i)) {
-                       continue;
-               }
-
-               req = arch_get_out_register_req(node, i);
-               cls = req->cls;
-               if (cls == NULL) {
-                       continue;
-               }
-               if (cls == &ia32_reg_classes[CLASS_ia32_flags]) {
-                       continue;
-               }
-
-               block = get_nodes_block(node);
-               in[0] = new_r_Proj(node, arch_register_class_mode(cls), i);
-               if (last_keep != NULL) {
-                       be_Keep_add_node(last_keep, cls, in[0]);
-               } else {
-                       last_keep = be_new_Keep(block, 1, in);
-                       if (sched_is_scheduled(node)) {
-                               sched_add_after(node, last_keep);
-                       }
-               }
-       }
-}
-
-/**
- * Adds missing keeps to nodes. Adds missing Proj nodes for unused outputs
- * and keeps them.
- */
-void ia32_add_missing_keeps(ia32_code_gen_t *cg)
-{
-       ir_graph *irg = be_get_birg_irg(cg->birg);
-       irg_walk_graph(irg, add_missing_keep_walker, NULL, NULL);
-}
-
 /**
  * Post-process all calls if we are in SSE mode.
  * The ABI requires that the results are in st0, copy them
@@ -5989,7 +5886,7 @@ void ia32_transform_graph(ia32_code_gen_t *cg)
        be_timer_push(T_HEIGHTS);
        heights      = heights_new(cg->irg);
        be_timer_pop(T_HEIGHTS);
-       ia32_calculate_non_address_mode_nodes(cg->birg);
+       ia32_calculate_non_address_mode_nodes(cg->irg);
 
        /* the transform phase is not safe for CSE (yet) because several nodes get
         * attributes set after their creation */
@@ -5998,7 +5895,7 @@ void ia32_transform_graph(ia32_code_gen_t *cg)
 
        call_list  = NEW_ARR_F(ir_node *, 0);
        call_types = NEW_ARR_F(ir_type *, 0);
-       be_transform_graph(cg->birg, ia32_pretransform_node);
+       be_transform_graph(cg->irg, ia32_pretransform_node);
 
        if (ia32_cg_config.use_sse2)
                postprocess_fp_call_results();