summaryrefslogtreecommitdiff
path: root/meta-xilinx/meta-microblaze/recipes-devtools/gcc/gcc-10/0018-Patch-microblaze-Reducing-Stack-space-for-arguments.patch
blob: 1f8decc77a3802fb50ac2d90a772a716eb3e2a9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
From 59273a71f1f180456d87eb4a1a5f95fcc6d17003 Mon Sep 17 00:00:00 2001
From: Mahesh Bodapati <mbodapat@xilinx.com>
Date: Tue, 17 Jan 2017 16:42:44 +0530
Subject: [PATCH 18/58] [Patch, microblaze]: Reducing Stack space for arguments

Currently in Microblaze target stack space for arguments in register is being
allocated even if there are no arguments in the function.
This patch will optimize the extra 24 bytes that are being allocated.

Signed-off-by :Nagaraju Mekala <nmekala@xilix.com>
              :Ajit Agarwal  <ajitkum@xilinx.com>

ChangeLog:
2015-04-17 Nagaraju Mekala <nmekala@xilix.com>
           Ajit Agarwal  <ajitkum@xilinx.com>

    *microblaze.c (microblaze_parm_needs_stack, microblaze_function_parms_need_stack): New
    *microblaze.c (REG_PARM_STACK_SPACE): Modify
---
 gcc/config/microblaze/microblaze-protos.h |   1 +
 gcc/config/microblaze/microblaze.c        | 132 +++++++++++++++++++++-
 gcc/config/microblaze/microblaze.h        |   4 +-
 3 files changed, 134 insertions(+), 3 deletions(-)

diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index 982b2abd2d4..96f7bb67f6c 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -59,6 +59,7 @@ extern int symbol_mentioned_p (rtx);
 extern int label_mentioned_p (rtx);
 extern bool microblaze_cannot_force_const_mem (machine_mode, rtx);
 extern void microblaze_eh_return (rtx op0);
+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 9eae5515c60..a4bdf66f045 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2057,6 +2057,136 @@ microblaze_must_save_register (int regno)
   return 0;
 }
 
+static bool
+microblaze_parm_needs_stack (cumulative_args_t args_so_far, tree type)
+{
+  int unsignedp;
+  rtx entry_parm;
+
+  /* Catch errors.  */
+  if (type == NULL || type == error_mark_node)
+    return true;
+
+  if (TREE_CODE (type) == POINTER_TYPE)
+    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.  */
+  function_arg_info arg (type, /*named=*/true);
+  apply_pass_by_reference_rules (get_cumulative_args (args_so_far), arg);
+
+  /* Find mode as it is passed by the ABI.  */
+  unsignedp = TYPE_UNSIGNED (type);
+  arg.mode = promote_mode (arg.type, arg.mode, &unsignedp);
+
+  /* If there is no incoming register, we need a stack.  */
+  entry_parm = microblaze_function_arg (args_so_far, arg);
+  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, arg) != 0)
+     return true;
+
+  /* Update info on where next arg arrives in registers.  */
+  microblaze_function_arg_advance (args_so_far, arg);
+  return false;
+}
+
+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);
+
+  /* When incoming, we will have been passed the function decl.
+   *      It is necessary to use the decl to handle K&R style functions,
+   *      where TYPE_ARG_TYPES may not be available.  */
+  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 > 3) return true;
+
+  return false;
+}
+
+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;
+}
+
 /* Return the bytes needed to compute the frame pointer from the current
    stack pointer.
 
@@ -3403,7 +3533,7 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   emit_insn (gen_indirect_jump (temp2));
 
   /* Run just enough of rest_of_compilation.  This sequence was
-     "borrowed" from rs6000.c.  */
+     "borrowed" from microblaze.c.  */
   insn = get_insns ();
   shorten_branches (insn);
   assemble_start_function (thunk_fndecl, fnname);
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 8aa3f155790..1e155e4041c 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -434,9 +434,9 @@ 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
+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE)  1
 
 #define STACK_BOUNDARY				32
 
-- 
2.17.1