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