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

Attachment: 0001-Patch-microblaze-Optimized-usage-of-reserved-stack-s.patch
Description: 0001-Patch-microblaze-Optimized-usage-of-reserved-stack-s.patch

Reply via email to