Allow loading of stack parameters with a different mode than the parameter mode....
authorChristoph Mallon <christoph.mallon@gmx.de>
Mon, 15 Oct 2007 23:03:18 +0000 (23:03 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Mon, 15 Oct 2007 23:03:18 +0000 (23:03 +0000)
[r16224]

ir/be/TEMPLATE/bearch_TEMPLATE.c
ir/be/arm/bearch_arm.c
ir/be/beabi.c
ir/be/beabi.h
ir/be/ia32/bearch_ia32.c
ir/be/mips/bearch_mips.c
ir/be/ppc32/bearch_ppc32.c

index aca43b4..977dfeb 100644 (file)
@@ -571,7 +571,9 @@ void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
                /* be_abi_call_param_reg(abi, i, reg); */
 
                /* default: all parameters on stack */
-               be_abi_call_param_stack(abi, i, 4, 0, 0);
+               tp   = get_method_param_type(method_type, i);
+               mode = get_type_mode(tp);
+               be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
        }
 
        /* TODO: set correct return register */
index 832f64a..dae0157 100644 (file)
@@ -1041,11 +1041,13 @@ void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi
        for (i = 0; i < n; i++) {
                /* reg = get reg for param i;          */
                /* be_abi_call_param_reg(abi, i, reg); */
-               if (i < 4)
-
+               if (i < 4) {
                        be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i));
-               else
-                       be_abi_call_param_stack(abi, i, 4, 0, 0);
+               } else {
+                       tp   = get_method_param_type(method_type, i);
+                       mode = get_type_mode(tp);
+                       be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
+               }
        }
 
        /* set return registers */
index 8e97d28..b6400df 100644 (file)
@@ -61,12 +61,13 @@ typedef struct _be_abi_call_arg_t {
        unsigned in_reg   : 1;  /**< 1: this argument is transmitted in registers. */
        unsigned on_stack : 1;  /**< 1: this argument is transmitted on the stack. */
 
-       int pos;
+       int                    pos;
        const arch_register_t *reg;
-       ir_entity *stack_ent;
-       unsigned alignment;     /**< stack alignment */
-       unsigned space_before;  /**< allocate space before */
-       unsigned space_after;   /**< allocate space after */
+       ir_entity             *stack_ent;
+       ir_mode               *load_mode;
+       unsigned               alignment;    /**< stack alignment */
+       unsigned               space_before; /**< allocate space before */
+       unsigned               space_after;  /**< allocate space after */
 } be_abi_call_arg_t;
 
 struct _be_abi_call_t {
@@ -192,10 +193,11 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
 }
 
 
-void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, unsigned alignment, unsigned space_before, unsigned space_after)
+void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after)
 {
        be_abi_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
        arg->on_stack     = 1;
+       arg->load_mode    = load_mode;
        arg->alignment    = alignment;
        arg->space_before = space_before;
        arg->space_after  = space_after;
@@ -1890,25 +1892,25 @@ static void modify_irg(be_abi_irg_t *env)
 
                        if (arg->in_reg) {
                                repl = pmap_get(env->regs, (void *) arg->reg);
-                       }
-
-                       else if(arg->on_stack) {
+                       } else if(arg->on_stack) {
                                ir_node *addr = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);
 
                                /* For atomic parameters which are actually used, we create a Load node. */
                                if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
-                                       ir_mode *mode                    = get_type_mode(param_type);
-                                       ir_node *load = new_rd_Load(NULL, irg, reg_params_bl,
-                                                                   new_NoMem(), addr, mode);
+                                       ir_mode *mode      = get_type_mode(param_type);
+                                       ir_mode *load_mode = arg->load_mode;
+
+                                       ir_node *load = new_r_Load(irg, reg_params_bl, new_NoMem(), addr, load_mode);
                                        set_irn_pinned(load, op_pin_state_floats);
-                                       repl = new_rd_Proj(NULL, irg, reg_params_bl, load,
-                                                          mode, pn_Load_res);
-                               }
+                                       repl = new_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
 
-                               /* The stack parameter is not primitive (it is a struct or array),
-                                  we thus will create a node representing the parameter's address
-                                  on the stack. */
-                               else {
+                                       if (mode != load_mode) {
+                                               repl = new_r_Conv(irg, reg_params_bl, repl, mode);
+                                       }
+                               } else {
+                                       /* The stack parameter is not primitive (it is a struct or array),
+                                        * we thus will create a node representing the parameter's address
+                                        * on the stack. */
                                        repl = addr;
                                }
                        }
index b720059..cfee128 100644 (file)
@@ -131,11 +131,12 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
  *
  * @param call          the abi call object
  * @param pos           the parameter position
+ * @param load_mode     load the parameter with this mode (if the parameter mode is different from this mode a Conv is inserted)
  * @param alignment     stack alignment for the parameter on the current architecture
  * @param space_before  size of allocated additional space before the parameter
  * @param space_after   size of allocated additional space after the parameter
  */
-void be_abi_call_param_stack(be_abi_call_t *call, int pos, unsigned alignment, unsigned space_before, unsigned space_after);
+void be_abi_call_param_stack(be_abi_call_t *call, int pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after);
 void be_abi_call_param_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
 void be_abi_call_res_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
 
index edd26f1..bb7e0c8 100644 (file)
@@ -1808,7 +1808,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
 
        n = get_method_n_params(method_type);
        for (i = regnum = 0; i < n; i++) {
-               const ir_mode         *mode;
+               ir_mode               *mode;
                const arch_register_t *reg = NULL;
 
                tp   = get_method_param_type(method_type, i);
@@ -1820,7 +1820,11 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
                        be_abi_call_param_reg(abi, i, reg);
                        ++regnum;
                } else {
-                       be_abi_call_param_stack(abi, i, 4, 0, 0);
+                       /* Micro optimisation: if the mode is shorter than 4 bytes, load 4 bytes.
+                        * movl has a shorter opcode than mov[sz][bw]l */
+                       ir_mode *load_mode = mode;
+                       if (mode != NULL && get_mode_size_bytes(mode) < 4) load_mode = mode_Iu;
+                       be_abi_call_param_stack(abi, i, load_mode, 4, 0, 0);
                }
        }
 
index 19e529b..c790b69 100644 (file)
@@ -926,7 +926,7 @@ static void mips_get_call_abi(const void *self, ir_type *method_type,
                        be_abi_call_param_reg(abi, i, reg);
                } else {
                        /* default: all parameters on stack */
-                       be_abi_call_param_stack(abi, i, 4, 0, 0);
+                       be_abi_call_param_stack(abi, i, modes[i], 4, 0, 0);
                }
        }
 
index ee17302..c9d9bda 100644 (file)
@@ -792,10 +792,9 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
 
        for (i = 0; i < n; i++) {
                tp   = get_method_param_type(method_type, i);
+               mode = get_type_mode(tp);
                if(is_atomic_type(tp))
                {
-                       mode = get_type_mode(tp);
-
                        if(mode_is_float(mode))
                        {
                                if(fpregi <= REG_F13)
@@ -824,14 +823,14 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
                                be_abi_call_param_reg(abi, i, reg);
                        else
                        {
-                               be_abi_call_param_stack(abi, i, 4, stackoffs-lastoffs, 0);
+                               be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
                                lastoffs = stackoffs+stackparamsize;
                        }
                        stackoffs += stackparamsize;
                }
                else
                {
-                       be_abi_call_param_stack(abi, i, 4, stackoffs-lastoffs, 0);
+                       be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
                        stackoffs += (get_type_size_bytes(tp)+3) & -4;
                        lastoffs = stackoffs;
                }