From: Christoph Mallon Date: Mon, 15 Oct 2007 23:03:18 +0000 (+0000) Subject: Allow loading of stack parameters with a different mode than the parameter mode.... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=5c87c3af579d582a642d29d5f1be31c3421d2c65;p=libfirm Allow loading of stack parameters with a different mode than the parameter mode. This is useful for x86 where loading a char parameter as 32bit results in a shorter opcode. [r16224] --- diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE.c b/ir/be/TEMPLATE/bearch_TEMPLATE.c index aca43b4c2..977dfeb46 100644 --- a/ir/be/TEMPLATE/bearch_TEMPLATE.c +++ b/ir/be/TEMPLATE/bearch_TEMPLATE.c @@ -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 */ diff --git a/ir/be/arm/bearch_arm.c b/ir/be/arm/bearch_arm.c index 832f64a6e..dae0157aa 100644 --- a/ir/be/arm/bearch_arm.c +++ b/ir/be/arm/bearch_arm.c @@ -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 */ diff --git a/ir/be/beabi.c b/ir/be/beabi.c index 8e97d28fb..b6400df39 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -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; } } diff --git a/ir/be/beabi.h b/ir/be/beabi.h index b72005904..cfee12874 100644 --- a/ir/be/beabi.h +++ b/ir/be/beabi.h @@ -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); diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index edd26f187..bb7e0c8bf 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -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); } } diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index 19e529ba9..c790b6929 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -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); } } diff --git a/ir/be/ppc32/bearch_ppc32.c b/ir/be/ppc32/bearch_ppc32.c index ee17302d9..c9d9bda9f 100644 --- a/ir/be/ppc32/bearch_ppc32.c +++ b/ir/be/ppc32/bearch_ppc32.c @@ -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; }