All: The below patch optimized the usage of the reserved stack space for function arguments. The stack space is reserved if the function is a libcall, variable number of arguments, aggregate data types, and some parameter are reserved in registers and some parameters is reserved in the stack. Along with the above conditions the stack space is not reserved if no arguments are passed. No regressions is seen in Deja GNU tests for microblaze.
[Patch,microblaze]: Optimized usage of reserved stack space for function arguments. The changes are made in the patch for optimized usage of reserved stack space for arguments. The stack space is reserved if the function is a libcall, variable number of arguments, aggregate data types, and some parameter are reserved in registers and some parameters is reserved in the stack. Along with the above conditions the stack space is not reserved if no arguments are passed. ChangeLog: 2015-07-06 Ajit Agarwal <ajit...@xilinx.com> * config/microblaze/microblaze.c (microblaze_parm_needs_stack): New. (microblaze_function_parms_need_stack): New. (microblaze_reg_parm_stack_space): New. * config/microblaze/microblaze.h (REG_PARM_STACK_SPACE): Modify the macro. * config/microblaze/microblaze-protos.h (microblaze_reg_parm_stack_space): Declare. Signed-off-by:Ajit Agarwal ajit...@xilinx.com --- gcc/config/microblaze/microblaze-protos.h | 1 + gcc/config/microblaze/microblaze.c | 140 +++++++++++++++++++++++++++++ gcc/config/microblaze/microblaze.h | 2 +- 3 files changed, 142 insertions(+), 1 deletions(-) diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h index 57879b1..d27d3e1 100644 --- a/gcc/config/microblaze/microblaze-protos.h +++ b/gcc/config/microblaze/microblaze-protos.h @@ -56,6 +56,7 @@ extern bool microblaze_tls_referenced_p (rtx); extern int symbol_mentioned_p (rtx); extern int label_mentioned_p (rtx); extern bool microblaze_cannot_force_const_mem (machine_mode, rtx); +extern int microblaze_reg_parm_stack_space(tree fun); #endif /* RTX_CODE */ /* Declare functions in microblaze-c.c. */ diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 566b78c..0eae4cd 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -3592,7 +3592,147 @@ microblaze_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) return true; } +/* Heuristics and criteria for having param needs stack. */ +static bool +microblaze_parm_needs_stack (cumulative_args_t args_so_far, tree type) +{ + enum machine_mode mode; + int unsignedp; + rtx entry_parm; + + /* Catch errors. */ + if (type == NULL || type == error_mark_node) + return true; + + /* Handle types with no storage requirement. */ + if (TYPE_MODE (type) == VOIDmode) + return false; + + /* Handle complex types. */ + if (TREE_CODE (type) == COMPLEX_TYPE) + return (microblaze_parm_needs_stack (args_so_far, TREE_TYPE (type)) + || microblaze_parm_needs_stack (args_so_far, TREE_TYPE (type))); + + /* Handle transparent aggregates. */ + if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (type)) + type = TREE_TYPE (first_field (type)); + + /* See if this arg was passed by invisible reference. */ + if (pass_by_reference (get_cumulative_args (args_so_far), + TYPE_MODE (type), type, true)) + type = build_pointer_type (type); + + /* Find mode as it is passed by the ABI. */ + unsignedp = TYPE_UNSIGNED (type); + mode = promote_mode (type, TYPE_MODE (type), &unsignedp); + + /* If there is no incoming register, we need a stack. */ + entry_parm = microblaze_function_arg (args_so_far, mode, type, true); + + if (entry_parm == NULL) + return true; + + /* Likewise if we need to pass both in registers and on the stack. */ + if (GET_CODE (entry_parm) == PARALLEL + && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX) + return true; + + /* Also true if we're partially in registers and partially not. */ + if (function_arg_partial_bytes (args_so_far, mode, type, true) != 0) + return true; + + /* Update info on where next arg arrives in registers. */ + microblaze_function_arg_advance (args_so_far, mode, type, true); + + return false; +} + +/* Function need stack for param if + 1. The function is a libcall. + 2. Variable number of arguments. + 3. If the param is aggregate data types. + 4. If partially some param in registers and some in the stack. */ + +static bool +microblaze_function_parms_need_stack (tree fun, bool incoming) +{ + tree fntype, result; + CUMULATIVE_ARGS args_so_far_v; + cumulative_args_t args_so_far; + int num_of_args = 0; + + /* Must be a libcall, all of which only use reg parms. */ + if (!fun) + return true; + + fntype = fun; + if (!TYPE_P (fun)) + fntype = TREE_TYPE (fun); + + /* Varargs functions need the parameter save area. */ + if ((!incoming && !prototype_p (fntype)) || stdarg_p (fntype)) + return true; + + INIT_CUMULATIVE_ARGS(args_so_far_v, fntype, NULL_RTX,0,0); + args_so_far = pack_cumulative_args (&args_so_far_v); + + if (incoming) + { + gcc_assert (DECL_P (fun)); + result = DECL_RESULT (fun); + } + else + result = TREE_TYPE (fntype); + + if (result && aggregate_value_p (result, fntype)) + { + if (!TYPE_P (result)) + result = build_pointer_type (result); + microblaze_parm_needs_stack (args_so_far, result); + } + + if (incoming) + { + tree parm; + for (parm = DECL_ARGUMENTS (fun); + parm && parm != void_list_node; + parm = TREE_CHAIN (parm)) + if (microblaze_parm_needs_stack (args_so_far, TREE_TYPE (parm))) + return true; + } + else + { + function_args_iterator args_iter; + tree arg_type; + + FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) + { + num_of_args++; + if (microblaze_parm_needs_stack (args_so_far, arg_type)) + return true; + } + } + + if (num_of_args > 1) + return true; + + return false; +} + +/* This function defines REG_PARM_STACK_SPACE macro.If + the Param needs stack returns the number of words to + be reserved. Otherwise return 0. */ + +int +microblaze_reg_parm_stack_space(tree fun) +{ + if (microblaze_function_parms_need_stack (fun, false)) + return MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD; + else + return 0; +} #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO microblaze_encode_section_info diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h index faeb780..69fbd89 100644 --- a/gcc/config/microblaze/microblaze.h +++ b/gcc/config/microblaze/microblaze.h @@ -451,7 +451,7 @@ extern struct microblaze_frame_info current_frame_info; #define ARG_POINTER_CFA_OFFSET(FNDECL) 0 -#define REG_PARM_STACK_SPACE(FNDECL) (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD) +#define REG_PARM_STACK_SPACE(FNDECL) microblaze_reg_parm_stack_space (FNDECL) #define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 -- 1.7.1
0001-Patch-microblaze-Optimized-usage-of-reserved-stack-s.patch
Description: 0001-Patch-microblaze-Optimized-usage-of-reserved-stack-s.patch