]>
Commit | Line | Data |
---|---|---|
1322177d | 1 | /* Procedure integration for GCC. |
8beccec8 | 2 | Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
6fb5fa3c | 3 | 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. |
175160e7 MT |
4 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
5 | ||
1322177d | 6 | This file is part of GCC. |
175160e7 | 7 | |
1322177d LB |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 10 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 11 | version. |
175160e7 | 12 | |
1322177d LB |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
175160e7 MT |
17 | |
18 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
175160e7 | 21 | |
175160e7 | 22 | #include "config.h" |
670ee920 | 23 | #include "system.h" |
4977bab6 ZW |
24 | #include "coretypes.h" |
25 | #include "tm.h" | |
ccd043a9 | 26 | |
175160e7 MT |
27 | #include "rtl.h" |
28 | #include "tree.h" | |
6baf1cc8 | 29 | #include "tm_p.h" |
12307ca2 | 30 | #include "regs.h" |
175160e7 | 31 | #include "flags.h" |
135d50f1 | 32 | #include "debug.h" |
175160e7 | 33 | #include "insn-config.h" |
175160e7 MT |
34 | #include "expr.h" |
35 | #include "output.h" | |
e9a25f70 | 36 | #include "recog.h" |
175160e7 MT |
37 | #include "integrate.h" |
38 | #include "real.h" | |
6adb4e3a | 39 | #include "except.h" |
175160e7 | 40 | #include "function.h" |
d6f4ec51 | 41 | #include "toplev.h" |
ab87f8c8 | 42 | #include "intl.h" |
c6d9a88c | 43 | #include "params.h" |
c0e7830f | 44 | #include "ggc.h" |
91d231cb | 45 | #include "target.h" |
63e1b1c4 | 46 | #include "langhooks.h" |
ef330312 | 47 | #include "tree-pass.h" |
6fb5fa3c | 48 | #include "df.h" |
175160e7 | 49 | |
6de9cd9a | 50 | /* Round to the next highest integer that meets the alignment. */ |
175160e7 | 51 | #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) |
175160e7 | 52 | \f |
c0e7830f | 53 | |
f7239224 | 54 | /* Private type used by {get/has}_hard_reg_initial_val. */ |
e2500fed | 55 | typedef struct initial_value_pair GTY(()) { |
c0e7830f DD |
56 | rtx hard_reg; |
57 | rtx pseudo; | |
58 | } initial_value_pair; | |
e2500fed | 59 | typedef struct initial_value_struct GTY(()) { |
c0e7830f DD |
60 | int num_entries; |
61 | int max_entries; | |
e2500fed | 62 | initial_value_pair * GTY ((length ("%h.num_entries"))) entries; |
c0e7830f DD |
63 | } initial_value_struct; |
64 | ||
1d088dee AJ |
65 | static void set_block_origin_self (tree); |
66 | static void set_block_abstract_flags (tree, int); | |
175160e7 | 67 | \f |
1f3d3a31 | 68 | |
91d231cb JM |
69 | /* Return false if the function FNDECL cannot be inlined on account of its |
70 | attributes, true otherwise. */ | |
588d3ade | 71 | bool |
3101faab | 72 | function_attribute_inlinable_p (const_tree fndecl) |
91d231cb | 73 | { |
b9a26d09 | 74 | if (targetm.attribute_table) |
91d231cb | 75 | { |
3101faab | 76 | const_tree a; |
91d231cb | 77 | |
b9a26d09 | 78 | for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) |
91d231cb | 79 | { |
3101faab | 80 | const_tree name = TREE_PURPOSE (a); |
b9a26d09 NB |
81 | int i; |
82 | ||
83 | for (i = 0; targetm.attribute_table[i].name != NULL; i++) | |
84 | if (is_attribute_p (targetm.attribute_table[i].name, name)) | |
5fd9b178 | 85 | return targetm.function_attribute_inlinable_p (fndecl); |
91d231cb | 86 | } |
91d231cb JM |
87 | } |
88 | ||
b9a26d09 | 89 | return true; |
91d231cb | 90 | } |
175160e7 | 91 | \f |
81578142 RS |
92 | /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the |
93 | given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so | |
94 | that it points to the node itself, thus indicating that the node is its | |
95 | own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for | |
96 | the given node is NULL, recursively descend the decl/block tree which | |
97 | it is the root of, and for each other ..._DECL or BLOCK node contained | |
98 | therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also | |
99 | still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN | |
100 | values to point to themselves. */ | |
101 | ||
81578142 | 102 | static void |
1d088dee | 103 | set_block_origin_self (tree stmt) |
81578142 RS |
104 | { |
105 | if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) | |
106 | { | |
107 | BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; | |
108 | ||
109 | { | |
b3694847 | 110 | tree local_decl; |
81578142 | 111 | |
00174bdf | 112 | for (local_decl = BLOCK_VARS (stmt); |
81578142 RS |
113 | local_decl != NULL_TREE; |
114 | local_decl = TREE_CHAIN (local_decl)) | |
00174bdf | 115 | set_decl_origin_self (local_decl); /* Potential recursion. */ |
81578142 RS |
116 | } |
117 | ||
118 | { | |
b3694847 | 119 | tree subblock; |
81578142 | 120 | |
00174bdf | 121 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
81578142 RS |
122 | subblock != NULL_TREE; |
123 | subblock = BLOCK_CHAIN (subblock)) | |
00174bdf | 124 | set_block_origin_self (subblock); /* Recurse. */ |
81578142 RS |
125 | } |
126 | } | |
127 | } | |
128 | ||
129 | /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for | |
130 | the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the | |
131 | node to so that it points to the node itself, thus indicating that the | |
132 | node represents its own (abstract) origin. Additionally, if the | |
133 | DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend | |
134 | the decl/block tree of which the given node is the root of, and for | |
135 | each other ..._DECL or BLOCK node contained therein whose | |
136 | DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL, | |
137 | set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to | |
138 | point to themselves. */ | |
139 | ||
1cfdcc15 | 140 | void |
1d088dee | 141 | set_decl_origin_self (tree decl) |
81578142 RS |
142 | { |
143 | if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) | |
144 | { | |
145 | DECL_ABSTRACT_ORIGIN (decl) = decl; | |
146 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
147 | { | |
b3694847 | 148 | tree arg; |
81578142 RS |
149 | |
150 | for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
151 | DECL_ABSTRACT_ORIGIN (arg) = arg; | |
29d356fb RK |
152 | if (DECL_INITIAL (decl) != NULL_TREE |
153 | && DECL_INITIAL (decl) != error_mark_node) | |
81578142 RS |
154 | set_block_origin_self (DECL_INITIAL (decl)); |
155 | } | |
156 | } | |
157 | } | |
158 | \f | |
159 | /* Given a pointer to some BLOCK node, and a boolean value to set the | |
160 | "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for | |
161 | the given block, and for all local decls and all local sub-blocks | |
162 | (recursively) which are contained therein. */ | |
163 | ||
81578142 | 164 | static void |
1d088dee | 165 | set_block_abstract_flags (tree stmt, int setting) |
81578142 | 166 | { |
b3694847 SS |
167 | tree local_decl; |
168 | tree subblock; | |
81578142 | 169 | |
12307ca2 | 170 | BLOCK_ABSTRACT (stmt) = setting; |
81578142 | 171 | |
12307ca2 RK |
172 | for (local_decl = BLOCK_VARS (stmt); |
173 | local_decl != NULL_TREE; | |
174 | local_decl = TREE_CHAIN (local_decl)) | |
175 | set_decl_abstract_flags (local_decl, setting); | |
81578142 | 176 | |
12307ca2 RK |
177 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
178 | subblock != NULL_TREE; | |
179 | subblock = BLOCK_CHAIN (subblock)) | |
180 | set_block_abstract_flags (subblock, setting); | |
81578142 RS |
181 | } |
182 | ||
183 | /* Given a pointer to some ..._DECL node, and a boolean value to set the | |
184 | "abstract" flags to, set that value into the DECL_ABSTRACT flag for the | |
185 | given decl, and (in the case where the decl is a FUNCTION_DECL) also | |
186 | set the abstract flags for all of the parameters, local vars, local | |
187 | blocks and sub-blocks (recursively) to the same setting. */ | |
188 | ||
189 | void | |
1d088dee | 190 | set_decl_abstract_flags (tree decl, int setting) |
81578142 RS |
191 | { |
192 | DECL_ABSTRACT (decl) = setting; | |
193 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
194 | { | |
b3694847 | 195 | tree arg; |
81578142 RS |
196 | |
197 | for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
198 | DECL_ABSTRACT (arg) = setting; | |
29d356fb RK |
199 | if (DECL_INITIAL (decl) != NULL_TREE |
200 | && DECL_INITIAL (decl) != error_mark_node) | |
81578142 RS |
201 | set_block_abstract_flags (DECL_INITIAL (decl), setting); |
202 | } | |
203 | } | |
c0e7830f DD |
204 | \f |
205 | /* Functions to keep track of the values hard regs had at the start of | |
206 | the function. */ | |
207 | ||
902197eb | 208 | rtx |
1d088dee | 209 | get_hard_reg_initial_reg (struct function *fun, rtx reg) |
902197eb DD |
210 | { |
211 | struct initial_value_struct *ivs = fun->hard_reg_initial_vals; | |
212 | int i; | |
213 | ||
214 | if (ivs == 0) | |
215 | return NULL_RTX; | |
216 | ||
217 | for (i = 0; i < ivs->num_entries; i++) | |
218 | if (rtx_equal_p (ivs->entries[i].pseudo, reg)) | |
219 | return ivs->entries[i].hard_reg; | |
220 | ||
221 | return NULL_RTX; | |
222 | } | |
223 | ||
f7239224 RS |
224 | /* Make sure that there's a pseudo register of mode MODE that stores the |
225 | initial value of hard register REGNO. Return an rtx for such a pseudo. */ | |
c0e7830f | 226 | |
f7239224 | 227 | rtx |
6356b546 | 228 | get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
c0e7830f | 229 | { |
f7239224 RS |
230 | struct initial_value_struct *ivs; |
231 | rtx rv; | |
c0e7830f | 232 | |
f7239224 | 233 | rv = has_hard_reg_initial_val (mode, regno); |
c0e7830f DD |
234 | if (rv) |
235 | return rv; | |
236 | ||
f7239224 | 237 | ivs = cfun->hard_reg_initial_vals; |
c0e7830f DD |
238 | if (ivs == 0) |
239 | { | |
f7239224 | 240 | ivs = ggc_alloc (sizeof (initial_value_struct)); |
c0e7830f DD |
241 | ivs->num_entries = 0; |
242 | ivs->max_entries = 5; | |
703ad42b | 243 | ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair)); |
f7239224 | 244 | cfun->hard_reg_initial_vals = ivs; |
c0e7830f DD |
245 | } |
246 | ||
247 | if (ivs->num_entries >= ivs->max_entries) | |
248 | { | |
249 | ivs->max_entries += 5; | |
703ad42b KG |
250 | ivs->entries = ggc_realloc (ivs->entries, |
251 | ivs->max_entries | |
252 | * sizeof (initial_value_pair)); | |
c0e7830f DD |
253 | } |
254 | ||
f7239224 RS |
255 | ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); |
256 | ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
c0e7830f DD |
257 | |
258 | return ivs->entries[ivs->num_entries++].pseudo; | |
259 | } | |
260 | ||
f7239224 RS |
261 | /* See if get_hard_reg_initial_val has been used to create a pseudo |
262 | for the initial value of hard register REGNO in mode MODE. Return | |
263 | the associated pseudo if so, otherwise return NULL. */ | |
c0e7830f DD |
264 | |
265 | rtx | |
6356b546 | 266 | has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
c0e7830f | 267 | { |
f7239224 RS |
268 | struct initial_value_struct *ivs; |
269 | int i; | |
270 | ||
271 | ivs = cfun->hard_reg_initial_vals; | |
272 | if (ivs != 0) | |
273 | for (i = 0; i < ivs->num_entries; i++) | |
274 | if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
6356b546 | 275 | && REGNO (ivs->entries[i].hard_reg) == regno) |
f7239224 RS |
276 | return ivs->entries[i].pseudo; |
277 | ||
278 | return NULL_RTX; | |
c0e7830f DD |
279 | } |
280 | ||
c2924966 | 281 | unsigned int |
1d088dee | 282 | emit_initial_value_sets (void) |
c0e7830f DD |
283 | { |
284 | struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; | |
285 | int i; | |
286 | rtx seq; | |
287 | ||
288 | if (ivs == 0) | |
c2924966 | 289 | return 0; |
c0e7830f DD |
290 | |
291 | start_sequence (); | |
292 | for (i = 0; i < ivs->num_entries; i++) | |
293 | emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg); | |
294 | seq = get_insns (); | |
295 | end_sequence (); | |
296 | ||
11b904a1 | 297 | emit_insn_at_entry (seq); |
c2924966 | 298 | return 0; |
c0e7830f | 299 | } |
385b6e2d | 300 | |
ef330312 PB |
301 | struct tree_opt_pass pass_initial_value_sets = |
302 | { | |
defb77dc | 303 | "initvals", /* name */ |
ef330312 PB |
304 | NULL, /* gate */ |
305 | emit_initial_value_sets, /* execute */ | |
306 | NULL, /* sub */ | |
307 | NULL, /* next */ | |
308 | 0, /* static_pass_number */ | |
309 | 0, /* tv_id */ | |
310 | 0, /* properties_required */ | |
311 | 0, /* properties_provided */ | |
312 | 0, /* properties_destroyed */ | |
313 | 0, /* todo_flags_start */ | |
defb77dc | 314 | TODO_dump_func, /* todo_flags_finish */ |
ef330312 PB |
315 | 0 /* letter */ |
316 | }; | |
317 | ||
385b6e2d R |
318 | /* If the backend knows where to allocate pseudos for hard |
319 | register initial values, register these allocations now. */ | |
320 | void | |
6fb5fa3c | 321 | allocate_initial_values (rtx *reg_equiv_memory_loc) |
385b6e2d | 322 | { |
b48f503c | 323 | if (targetm.allocate_initial_value) |
385b6e2d | 324 | { |
b48f503c KK |
325 | struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; |
326 | int i; | |
385b6e2d | 327 | |
b48f503c KK |
328 | if (ivs == 0) |
329 | return; | |
330 | ||
331 | for (i = 0; i < ivs->num_entries; i++) | |
385b6e2d | 332 | { |
b48f503c KK |
333 | int regno = REGNO (ivs->entries[i].pseudo); |
334 | rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg); | |
335 | ||
336 | if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) | |
41806d92 | 337 | { |
b48f503c KK |
338 | if (MEM_P (x)) |
339 | reg_equiv_memory_loc[regno] = x; | |
340 | else | |
2d6c85d3 | 341 | { |
b48f503c KK |
342 | basic_block bb; |
343 | int new_regno; | |
344 | ||
345 | gcc_assert (REG_P (x)); | |
346 | new_regno = REGNO (x); | |
347 | reg_renumber[regno] = new_regno; | |
348 | /* Poke the regno right into regno_reg_rtx so that even | |
349 | fixed regs are accepted. */ | |
6fb5fa3c | 350 | SET_REGNO (ivs->entries[i].pseudo, new_regno); |
b48f503c KK |
351 | /* Update global register liveness information. */ |
352 | FOR_EACH_BB (bb) | |
353 | { | |
89a95777 KZ |
354 | if (REGNO_REG_SET_P(df_get_live_in (bb), regno)) |
355 | SET_REGNO_REG_SET (df_get_live_in (bb), new_regno); | |
356 | if (REGNO_REG_SET_P(df_get_live_out (bb), regno)) | |
357 | SET_REGNO_REG_SET (df_get_live_out (bb), new_regno); | |
b48f503c | 358 | } |
2d6c85d3 | 359 | } |
41806d92 | 360 | } |
385b6e2d | 361 | } |
385b6e2d | 362 | } |
385b6e2d | 363 | } |
e2500fed GK |
364 | |
365 | #include "gt-integrate.h" |