fix Cltd register pressure, fix some SSE (ABI with x87) call things...
authorMatthias Braun <matze@braunis.de>
Tue, 17 Jul 2007 14:27:41 +0000 (14:27 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 17 Jul 2007 14:27:41 +0000 (14:27 +0000)
[r15189]

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/ia32/ia32_x87.c

index b83bffe..d7d312b 100644 (file)
@@ -1269,17 +1269,12 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
                        const ir_mode *mode = ia32_reg_classes[CLASS_ia32_fp_cw].mode;
                        int align = 4;
                        be_node_needs_frame_entity(env, node, mode, align);
-               } else if (is_ia32_SetST0(node)) {
-                       const ir_mode *mode = get_ia32_ls_mode(node);
-                       int align = 4;
-                       be_node_needs_frame_entity(env, node, mode, align);
                } else {
 #ifndef NDEBUG
                        assert(is_ia32_St(node) ||
                                   is_ia32_xStoreSimple(node) ||
                                   is_ia32_vfst(node) ||
                                   is_ia32_vfist(node) ||
-                              is_ia32_GetST0(node) ||
                               is_ia32_FnstCW(node));
 #endif
                }
index e97d78b..6f7caac 100644 (file)
@@ -336,6 +336,7 @@ Immediate => {
        reg_req   => { out => [ "gp_NOREG" ] },
        attr      => "ir_entity *symconst, int symconst_sign, long offset",
        attr_type => "ia32_immediate_attr_t",
+       latency   => 0,
        mode      => $mode_gp,
 },
 
@@ -344,6 +345,17 @@ Asm => {
        arity     => "variable",
        out_arity => "variable",
        attr_type => "ia32_asm_attr_t",
+       latency   => 100,
+},
+
+ProduceVal => {
+       op_flags  => "c",
+       irn_flags => "R",
+       reg_req   => { out => [ "gp" ] },
+       emit      => "",
+       units     => [ ],
+       latency   => 0,
+       mode      => $mode_gp,
 },
 
 #-----------------------------------------------------------------#
@@ -908,8 +920,8 @@ FnstCW => {
 Cltd => {
        # we should not rematrialize this node. It produces 2 results and has
        # very strict constrains
-       reg_req   => { in => [ "eax" ], out => [ "edx" ] },
-       ins       => [ "val" ],
+       reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
+       ins       => [ "val", "globbered" ],
        emit      => '. cltd',
        mode      => $mode_gp,
        units     => [ "GP" ],
@@ -1248,29 +1260,6 @@ l_SSEtoX87 => {
        arity    => 3,
 },
 
-GetST0 => {
-       op_flags => "L|F",
-       irn_flags => "I",
-       state    => "pinned",
-       reg_req  => { in => [ "gp", "gp", "none" ] },
-       emit     => '. fstp%XM %AM',
-       latency  => 4,
-       units    => [ "SSE" ],
-       mode     => "mode_M",
-},
-
-SetST0 => {
-       op_flags => "L|F",
-       irn_flags => "I",
-       state    => "pinned",
-       reg_req  => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] },
-       ins      => [ "base", "index", "mem" ],
-       emit     => '. fld%XM %AM',
-       outs     => [ "res", "M" ],
-       latency  => 2,
-       units     => [ "SSE" ],
-},
-
 # CopyB
 
 CopyB => {
index af57736..4a4a2ee 100644 (file)
@@ -1078,7 +1078,9 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
 
        if (mode_is_signed(mode)) {
                /* in signed mode, we need to sign extend the dividend */
-               sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend);
+               ir_node *produceval = new_rd_ia32_ProduceVal(dbgi, irg, block);
+               sign_extension      = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend,
+                                                      produceval);
        } else {
                sign_extension = new_rd_ia32_Const(dbgi, irg, block);
                set_ia32_Immop_tarval(sign_extension, get_tarval_null(mode_Iu));
@@ -1216,8 +1218,9 @@ static ir_node *gen_Shrs(ir_node *node) {
                        ir_node  *block  = be_transform_node(get_nodes_block(node));
                        ir_node  *op     = left;
                        ir_node  *new_op = be_transform_node(op);
+                       ir_node  *pval   = new_rd_ia32_ProduceVal(dbgi, irg, block);
 
-                       return new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+                       return new_rd_ia32_Cltd(dbgi, irg, block, new_op, pval);
                }
        }
 
@@ -1422,7 +1425,9 @@ static ir_node *gen_Abs(ir_node *node) {
                }
        } else {
                ir_node *xor;
-               ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+               ir_node *pval           = new_rd_ia32_ProduceVal(dbgi, irg, block);
+               ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op,
+                                                          pval);
                SET_IA32_ORIG_NODE(sign_extension,
                                   ia32_get_old_node_name(env_cg, node));
 
@@ -2971,22 +2976,21 @@ static ir_node *gen_be_Return(ir_node *node) {
        noreg = ia32_new_NoReg_gp(env_cg);
 
        /* store xmm0 onto stack */
-       sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg, new_ret_val, new_ret_mem);
+       sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg,
+                                            new_ret_val, new_ret_mem);
        set_ia32_ls_mode(sse_store, mode);
        set_ia32_op_type(sse_store, ia32_AddrModeD);
        set_ia32_use_frame(sse_store);
        set_ia32_am_flavour(sse_store, ia32_am_B);
 
-       /* load into st0 */
-       fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, noreg, sse_store);
-       set_ia32_ls_mode(fld, mode);
+       /* load into x87 register */
+       fld = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, sse_store, mode);
        set_ia32_op_type(fld, ia32_AddrModeS);
        set_ia32_use_frame(fld);
        set_ia32_am_flavour(fld, ia32_am_B);
 
-       mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
-       fld   = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res);
-       arch_set_irn_register(env_cg->arch_env, fld, &ia32_vfp_regs[REG_VF0]);
+       mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_vfld_M);
+       fld   = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_vfld_res);
 
        /* create a new barrier */
        arity = get_irn_arity(barrier);
@@ -3819,26 +3823,32 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                }
 
                if (call_res_pred == NULL || be_is_Call(call_res_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+                       return new_rd_Proj(dbgi, irg, block, new_call, mode_M,
+                                          pn_be_Call_M_regular);
                } else {
                        assert(is_ia32_xLoad(call_res_pred));
-                       return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M, pn_ia32_xLoad_M);
+                       return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M,
+                                          pn_ia32_xLoad_M);
                }
        }
        if (proj == pn_be_Call_first_res && mode_is_float(mode) && USE_SSE2(env_cg)) {
                ir_node *fstp;
                ir_node *frame = get_irg_frame(irg);
                ir_node *noreg = ia32_new_NoReg_gp(env_cg);
-               ir_node *p;
+               //ir_node *p;
                ir_node *call_mem = be_get_Proj_for_pn(call, pn_be_Call_M_regular);
+               ir_node *call_res;
 
-               /* in case there is no memory output: create one to serialize the copy FPU -> SSE */
-               call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+               /* in case there is no memory output: create one to serialize the copy
+                  FPU -> SSE */
+               call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M,
+                                      pn_be_Call_M_regular);
+               call_res = new_rd_Proj(dbgi, irg, block, new_call, mode,
+                                      pn_be_Call_first_res);
 
                /* store st(0) onto stack */
-               fstp = new_rd_ia32_GetST0(dbgi, irg, block, frame, noreg, call_mem);
-
-               set_ia32_ls_mode(fstp, mode);
+               fstp = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, call_mem,
+                                       call_res, mode);
                set_ia32_op_type(fstp, ia32_AddrModeD);
                set_ia32_use_frame(fstp);
                set_ia32_am_flavour(fstp, ia32_am_B);
@@ -3850,8 +3860,10 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                set_ia32_use_frame(sse_load);
                set_ia32_am_flavour(sse_load, ia32_am_B);
 
-               sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, pn_ia32_xLoad_res);
+               sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm,
+                                      pn_ia32_xLoad_res);
 
+#if 0
                /* now: create new Keep whith all former ins and one additional in - the result Proj */
 
                /* get a Proj representing a caller save register */
@@ -3861,6 +3873,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                /* user of the the proj is the Keep */
                p = get_edge_src_irn(get_irn_out_edge_first(p));
                assert(be_is_Keep(p) && "Keep expected.");
+#endif
 
                return sse_load;
        }
index c291176..eaef610 100644 (file)
@@ -1659,24 +1659,23 @@ static ir_node *create_Copy(x87_state *state, ir_node *n) {
  * @return NO_NODE_ADDED
  */
 static int sim_Copy(x87_state *state, ir_node *n) {
-       x87_simulator         *sim;
-       ir_node               *pred;
-       const arch_register_t *out;
-       const arch_register_t *op1;
-       ir_node               *node, *next;
-       ia32_x87_attr_t       *attr;
-       int                   op1_idx, out_idx;
-       unsigned              live;
-
-       ir_mode *mode = get_irn_mode(n);
-
-       if (!mode_is_float(mode))
+       x87_simulator               *sim = state->sim;
+       ir_node                     *pred;
+       const arch_register_t       *out;
+       const arch_register_t       *op1;
+       const arch_register_class_t *class;
+       ir_node                     *node, *next;
+       ia32_x87_attr_t             *attr;
+       int                         op1_idx, out_idx;
+       unsigned                    live;
+
+       class = arch_get_irn_reg_class(sim->arch_env, n, -1);
+       if (class->regs != ia32_vfp_regs)
                return 0;
 
-       sim = state->sim;
        pred = get_irn_n(n, 0);
-       out = x87_get_irn_register(sim, n);
-       op1 = x87_get_irn_register(sim, pred);
+       out  = x87_get_irn_register(sim, n);
+       op1  = x87_get_irn_register(sim, pred);
        live = vfp_live_args_after(sim, n, REGMASK(out));
 
        DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n,
@@ -1772,11 +1771,10 @@ static int sim_Copy(x87_state *state, ir_node *n) {
 }  /* sim_Copy */
 
 /**
- * Returns the result proj of the call, or NULL if the result is not used
+ * Returns the result proj of the call
  */
 static ir_node *get_call_result_proj(ir_node *call) {
        const ir_edge_t *edge;
-       ir_node *resproj = NULL;
 
        /* search the result proj */
        foreach_out_edge(call, edge) {
@@ -1784,23 +1782,10 @@ static ir_node *get_call_result_proj(ir_node *call) {
                long pn = get_Proj_proj(proj);
 
                if (pn == pn_be_Call_first_res) {
-                       resproj = proj;
-                       break;
-               }
-       }
-       if (resproj == NULL) {
-               return NULL;
-       }
-
-       /* the result proj is connected to a Keep and maybe other nodes */
-       foreach_out_edge(resproj, edge) {
-               ir_node *pred = get_edge_src_irn(edge);
-               if (!be_is_Keep(pred)) {
-                       return resproj;
+                       return proj;
                }
        }
 
-       /* only be_Keep found, so result is not used */
        return NULL;
 }  /* get_call_result_proj */
 
@@ -1822,11 +1807,13 @@ static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *arch_env)
        const arch_register_t *reg;
        (void) arch_env;
 
+       DB((dbg, LEVEL_1, ">>> %+F\n", n));
+
        /* at the begin of a call the x87 state should be empty */
        assert(state->depth == 0 && "stack not empty before call");
 
        if (get_method_n_ress(call_tp) <= 0)
-               return NO_NODE_ADDED;
+               goto end_call;
 
        /*
         * If the called function returns a float, it is returned in st(0).
@@ -1837,15 +1824,18 @@ static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *arch_env)
        mode     = get_type_mode(res_type);
 
        if (mode == NULL || !mode_is_float(mode))
-               return NO_NODE_ADDED;
+               goto end_call;
 
        resproj = get_call_result_proj(n);
-       if (resproj == NULL)
-               return NO_NODE_ADDED;
+       assert(resproj != NULL);
 
        reg = x87_get_irn_register(state->sim, resproj);
        x87_push(state, arch_register_get_index(reg), resproj);
 
+end_call:
+       DB((dbg, LEVEL_1, "Stack after: "));
+       DEBUG_ONLY(x87_dump_stack(state));
+
        return NO_NODE_ADDED;
 }  /* sim_Call */