blob: ead929ab6869a41faa195b67fe4c2a4ffee6f5f7 [file] [log] [blame]
Brad Bishop286d45c2018-10-02 15:21:57 -04001From f5416ee7ddc6e4853e57ed15fb2bf630de2c3b12 Mon Sep 17 00:00:00 2001
2From: Mahesh Bodapati <mbodapat@xilinx.com>
3Date: Sat, 26 Aug 2017 19:21:37 -0700
4Subject: [PATCH] Reducing Stack space for arguments Currently in Microblaze
5 target stack space
6
7Reducing Stack space for arguments Currently in Microblaze target stack
8space for arguments in register is being allocated even if there are no
9arguments in the function. This patch will optimize the extra 24 bytes
10that are being allocated.
11
12ChangeLog:
132015-04-17 Nagaraju Mekala <nagaraju.mekala@xilinx.com>
14 Ajit Agarwal <ajitkum@xilinx.com>
15
16 * microblaze.c (microblaze_parm_needs_stack, microblaze_function_parms_need_stack): New
17 * microblaze.c (REG_PARM_STACK_SPACE): Modify
18
19Signed-off-by: Nagaraju Mekala <nagaraju.mekala@xilinx.com>
20Signed-off-by: Ajit Agarwal <ajitkum@xilinx.com>
21Signed-off-by: Mahesh Bodapati <mbodapat@xilinx.com>
22Signed-off-by: Manjukumar Matha <manjukumar.harthikote-matha@xilinx.com>
23Upstream-Status: Pending
24---
25 gcc/config/microblaze/microblaze-protos.h | 1 +
26 gcc/config/microblaze/microblaze.c | 134 +++++++++++++++++++++++++++++-
27 gcc/config/microblaze/microblaze.h | 4 +-
28 3 files changed, 136 insertions(+), 3 deletions(-)
29
30diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
31index b56e052ae4..a1408629cc 100644
32--- a/gcc/config/microblaze/microblaze-protos.h
33+++ b/gcc/config/microblaze/microblaze-protos.h
34@@ -57,6 +57,7 @@ extern int symbol_mentioned_p (rtx);
35 extern int label_mentioned_p (rtx);
36 extern bool microblaze_cannot_force_const_mem (machine_mode, rtx);
37 extern void microblaze_eh_return (rtx op0);
38+int microblaze_reg_parm_stack_space(tree fun);
39 #endif /* RTX_CODE */
40
41 /* Declare functions in microblaze-c.c. */
42diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
43index c1b0172bcf..f46dffff0d 100644
44--- a/gcc/config/microblaze/microblaze.c
45+++ b/gcc/config/microblaze/microblaze.c
46@@ -1965,6 +1965,138 @@ microblaze_must_save_register (int regno)
47 return 0;
48 }
49
50+static bool
51+microblaze_parm_needs_stack (cumulative_args_t args_so_far, tree type)
52+{
53+ enum machine_mode mode;
54+ int unsignedp;
55+ rtx entry_parm;
56+
57+ /* Catch errors. */
58+ if (type == NULL || type == error_mark_node)
59+ return true;
60+
61+ if (TREE_CODE (type) == POINTER_TYPE)
62+ return true;
63+
64+ /* Handle types with no storage requirement. */
65+ if (TYPE_MODE (type) == VOIDmode)
66+ return false;
67+
68+ /* Handle complex types. */
69+ if (TREE_CODE (type) == COMPLEX_TYPE)
70+ return (microblaze_parm_needs_stack (args_so_far, TREE_TYPE (type))
71+ || microblaze_parm_needs_stack (args_so_far, TREE_TYPE (type)));
72+
73+ /* Handle transparent aggregates. */
74+ if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE)
75+ && TYPE_TRANSPARENT_AGGR (type))
76+ type = TREE_TYPE (first_field (type));
77+
78+ /* See if this arg was passed by invisible reference. */
79+ if (pass_by_reference (get_cumulative_args (args_so_far),
80+ TYPE_MODE (type), type, true))
81+ type = build_pointer_type (type);
82+
83+ /* Find mode as it is passed by the ABI. */
84+ unsignedp = TYPE_UNSIGNED (type);
85+ mode = promote_mode (type, TYPE_MODE (type), &unsignedp);
86+
87+/* If there is no incoming register, we need a stack. */
88+ entry_parm = microblaze_function_arg (args_so_far, mode, type, true);
89+ if (entry_parm == NULL)
90+ return true;
91+
92+ /* Likewise if we need to pass both in registers and on the stack. */
93+ if (GET_CODE (entry_parm) == PARALLEL
94+ && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
95+ return true;
96+
97+ /* Also true if we're partially in registers and partially not. */
98+ if (function_arg_partial_bytes (args_so_far, mode, type, true) != 0)
99+ return true;
100+
101+ /* Update info on where next arg arrives in registers. */
102+ microblaze_function_arg_advance (args_so_far, mode, type, true);
103+ return false;
104+ }
105+
106+static bool
107+microblaze_function_parms_need_stack (tree fun, bool incoming)
108+{
109+ tree fntype, result;
110+ CUMULATIVE_ARGS args_so_far_v;
111+ cumulative_args_t args_so_far;
112+ int num_of_args = 0;
113+
114+ /* Must be a libcall, all of which only use reg parms. */
115+ if (!fun)
116+ return true;
117+
118+ fntype = fun;
119+ if (!TYPE_P (fun))
120+ fntype = TREE_TYPE (fun);
121+
122+ /* Varargs functions need the parameter save area. */
123+ if ((!incoming && !prototype_p (fntype)) || stdarg_p (fntype))
124+ return true;
125+
126+ INIT_CUMULATIVE_ARGS(args_so_far_v, fntype, NULL_RTX,0,0);
127+ args_so_far = pack_cumulative_args (&args_so_far_v);
128+
129+ /* When incoming, we will have been passed the function decl.
130+ * It is necessary to use the decl to handle K&R style functions,
131+ * where TYPE_ARG_TYPES may not be available. */
132+ if (incoming)
133+ {
134+ gcc_assert (DECL_P (fun));
135+ result = DECL_RESULT (fun);
136+ }
137+ else
138+ result = TREE_TYPE (fntype);
139+
140+ if (result && aggregate_value_p (result, fntype))
141+ {
142+ if (!TYPE_P (result))
143+ result = build_pointer_type (result);
144+ microblaze_parm_needs_stack (args_so_far, result);
145+ }
146+
147+ if (incoming)
148+ {
149+ tree parm;
150+ for (parm = DECL_ARGUMENTS (fun);
151+ parm && parm != void_list_node;
152+ parm = TREE_CHAIN (parm))
153+ if (microblaze_parm_needs_stack (args_so_far, TREE_TYPE (parm)))
154+ return true;
155+ }
156+ else
157+ {
158+ function_args_iterator args_iter;
159+ tree arg_type;
160+
161+ FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
162+ {
163+ num_of_args++;
164+ if (microblaze_parm_needs_stack (args_so_far, arg_type))
165+ return true;
166+ }
167+ }
168+
169+ if (num_of_args > 3) return true;
170+
171+ return false;
172+}
173+
174+int microblaze_reg_parm_stack_space(tree fun)
175+{
176+ if (microblaze_function_parms_need_stack (fun,false))
177+ return MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD;
178+ else
179+ return 0;
180+}
181+
182 /* Return the bytes needed to compute the frame pointer from the current
183 stack pointer.
184
185@@ -3275,7 +3407,7 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
186 emit_insn (gen_indirect_jump (temp2));
187
188 /* Run just enough of rest_of_compilation. This sequence was
189- "borrowed" from rs6000.c. */
190+ "borrowed" from microblaze.c. */
191 insn = get_insns ();
192 shorten_branches (insn);
193 final_start_function (insn, file, 1);
194diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
195index 0dd8b853e2..82e7e890be 100644
196--- a/gcc/config/microblaze/microblaze.h
197+++ b/gcc/config/microblaze/microblaze.h
198@@ -467,9 +467,9 @@ extern struct microblaze_frame_info current_frame_info;
199
200 #define ARG_POINTER_CFA_OFFSET(FNDECL) 0
201
202-#define REG_PARM_STACK_SPACE(FNDECL) (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD)
203+#define REG_PARM_STACK_SPACE(FNDECL) microblaze_reg_parm_stack_space(FNDECL)
204
205-#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
206+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
207
208 #define STACK_BOUNDARY 32
209
210--
2112.14.2
212