no need to pass environment stuff aroudn that can be retireved from irg
[libfirm] / ir / be / ia32 / ia32_transform.c
index dc011d0..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);
 
@@ -3110,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);
@@ -4379,14 +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);
-}
-
 static ir_node *gen_Proj_l_FloattoLL(ir_node *node)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
@@ -4643,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)) {
@@ -4728,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);
@@ -5668,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);
 }
 
 /**
@@ -5778,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
@@ -5970,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 */