]>
Commit | Line | Data |
---|---|---|
1322177d | 1 | /* Procedure integration for GCC. |
8beccec8 | 2 | Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
7072a650 | 3 | 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
66647d44 | 4 | Free Software Foundation, Inc. |
175160e7 MT |
5 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
6 | ||
1322177d | 7 | This file is part of GCC. |
175160e7 | 8 | |
1322177d LB |
9 | GCC is free software; you can redistribute it and/or modify it under |
10 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 11 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 12 | version. |
175160e7 | 13 | |
1322177d LB |
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | for more details. | |
175160e7 MT |
18 | |
19 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
175160e7 | 22 | |
175160e7 | 23 | #include "config.h" |
670ee920 | 24 | #include "system.h" |
4977bab6 ZW |
25 | #include "coretypes.h" |
26 | #include "tm.h" | |
ccd043a9 | 27 | |
175160e7 MT |
28 | #include "rtl.h" |
29 | #include "tree.h" | |
6baf1cc8 | 30 | #include "tm_p.h" |
12307ca2 | 31 | #include "regs.h" |
175160e7 | 32 | #include "flags.h" |
135d50f1 | 33 | #include "debug.h" |
175160e7 | 34 | #include "insn-config.h" |
175160e7 MT |
35 | #include "expr.h" |
36 | #include "output.h" | |
e9a25f70 | 37 | #include "recog.h" |
175160e7 | 38 | #include "integrate.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. */ |
d1b38208 | 55 | typedef struct GTY(()) initial_value_pair { |
c0e7830f DD |
56 | rtx hard_reg; |
57 | rtx pseudo; | |
58 | } initial_value_pair; | |
d1b38208 | 59 | typedef struct GTY(()) initial_value_struct { |
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; | |
e038c37b | 169 | unsigned int i; |
81578142 | 170 | |
12307ca2 | 171 | BLOCK_ABSTRACT (stmt) = setting; |
81578142 | 172 | |
12307ca2 RK |
173 | for (local_decl = BLOCK_VARS (stmt); |
174 | local_decl != NULL_TREE; | |
175 | local_decl = TREE_CHAIN (local_decl)) | |
176 | set_decl_abstract_flags (local_decl, setting); | |
81578142 | 177 | |
e038c37b JJ |
178 | for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) |
179 | { | |
180 | local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i); | |
181 | if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl)) | |
182 | || TREE_CODE (local_decl) == PARM_DECL) | |
183 | set_decl_abstract_flags (local_decl, setting); | |
184 | } | |
185 | ||
12307ca2 RK |
186 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
187 | subblock != NULL_TREE; | |
188 | subblock = BLOCK_CHAIN (subblock)) | |
189 | set_block_abstract_flags (subblock, setting); | |
81578142 RS |
190 | } |
191 | ||
192 | /* Given a pointer to some ..._DECL node, and a boolean value to set the | |
193 | "abstract" flags to, set that value into the DECL_ABSTRACT flag for the | |
194 | given decl, and (in the case where the decl is a FUNCTION_DECL) also | |
195 | set the abstract flags for all of the parameters, local vars, local | |
196 | blocks and sub-blocks (recursively) to the same setting. */ | |
197 | ||
198 | void | |
1d088dee | 199 | set_decl_abstract_flags (tree decl, int setting) |
81578142 RS |
200 | { |
201 | DECL_ABSTRACT (decl) = setting; | |
202 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
203 | { | |
b3694847 | 204 | tree arg; |
81578142 RS |
205 | |
206 | for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
207 | DECL_ABSTRACT (arg) = setting; | |
29d356fb RK |
208 | if (DECL_INITIAL (decl) != NULL_TREE |
209 | && DECL_INITIAL (decl) != error_mark_node) | |
81578142 RS |
210 | set_block_abstract_flags (DECL_INITIAL (decl), setting); |
211 | } | |
212 | } | |
c0e7830f DD |
213 | \f |
214 | /* Functions to keep track of the values hard regs had at the start of | |
215 | the function. */ | |
216 | ||
902197eb | 217 | rtx |
38173d38 | 218 | get_hard_reg_initial_reg (rtx reg) |
902197eb | 219 | { |
38173d38 | 220 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
902197eb DD |
221 | int i; |
222 | ||
223 | if (ivs == 0) | |
224 | return NULL_RTX; | |
225 | ||
226 | for (i = 0; i < ivs->num_entries; i++) | |
227 | if (rtx_equal_p (ivs->entries[i].pseudo, reg)) | |
228 | return ivs->entries[i].hard_reg; | |
229 | ||
230 | return NULL_RTX; | |
231 | } | |
232 | ||
f7239224 RS |
233 | /* Make sure that there's a pseudo register of mode MODE that stores the |
234 | initial value of hard register REGNO. Return an rtx for such a pseudo. */ | |
c0e7830f | 235 | |
f7239224 | 236 | rtx |
6356b546 | 237 | get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
c0e7830f | 238 | { |
f7239224 RS |
239 | struct initial_value_struct *ivs; |
240 | rtx rv; | |
c0e7830f | 241 | |
f7239224 | 242 | rv = has_hard_reg_initial_val (mode, regno); |
c0e7830f DD |
243 | if (rv) |
244 | return rv; | |
245 | ||
38173d38 | 246 | ivs = crtl->hard_reg_initial_vals; |
c0e7830f DD |
247 | if (ivs == 0) |
248 | { | |
a9429e29 | 249 | ivs = ggc_alloc_initial_value_struct (); |
c0e7830f DD |
250 | ivs->num_entries = 0; |
251 | ivs->max_entries = 5; | |
a9429e29 | 252 | ivs->entries = ggc_alloc_vec_initial_value_pair (5); |
38173d38 | 253 | crtl->hard_reg_initial_vals = ivs; |
c0e7830f DD |
254 | } |
255 | ||
256 | if (ivs->num_entries >= ivs->max_entries) | |
257 | { | |
258 | ivs->max_entries += 5; | |
d3bfe4de KG |
259 | ivs->entries = GGC_RESIZEVEC (initial_value_pair, ivs->entries, |
260 | ivs->max_entries); | |
c0e7830f DD |
261 | } |
262 | ||
f7239224 RS |
263 | ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); |
264 | ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
c0e7830f DD |
265 | |
266 | return ivs->entries[ivs->num_entries++].pseudo; | |
267 | } | |
268 | ||
f7239224 RS |
269 | /* See if get_hard_reg_initial_val has been used to create a pseudo |
270 | for the initial value of hard register REGNO in mode MODE. Return | |
271 | the associated pseudo if so, otherwise return NULL. */ | |
c0e7830f DD |
272 | |
273 | rtx | |
6356b546 | 274 | has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
c0e7830f | 275 | { |
f7239224 RS |
276 | struct initial_value_struct *ivs; |
277 | int i; | |
278 | ||
38173d38 | 279 | ivs = crtl->hard_reg_initial_vals; |
f7239224 RS |
280 | if (ivs != 0) |
281 | for (i = 0; i < ivs->num_entries; i++) | |
282 | if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
6356b546 | 283 | && REGNO (ivs->entries[i].hard_reg) == regno) |
f7239224 RS |
284 | return ivs->entries[i].pseudo; |
285 | ||
286 | return NULL_RTX; | |
c0e7830f DD |
287 | } |
288 | ||
c2924966 | 289 | unsigned int |
1d088dee | 290 | emit_initial_value_sets (void) |
c0e7830f | 291 | { |
38173d38 | 292 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
c0e7830f DD |
293 | int i; |
294 | rtx seq; | |
295 | ||
296 | if (ivs == 0) | |
c2924966 | 297 | return 0; |
c0e7830f DD |
298 | |
299 | start_sequence (); | |
300 | for (i = 0; i < ivs->num_entries; i++) | |
301 | emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg); | |
302 | seq = get_insns (); | |
303 | end_sequence (); | |
304 | ||
11b904a1 | 305 | emit_insn_at_entry (seq); |
c2924966 | 306 | return 0; |
c0e7830f | 307 | } |
385b6e2d | 308 | |
8ddbbcae | 309 | struct rtl_opt_pass pass_initial_value_sets = |
ef330312 | 310 | { |
8ddbbcae JH |
311 | { |
312 | RTL_PASS, | |
defb77dc | 313 | "initvals", /* name */ |
ef330312 PB |
314 | NULL, /* gate */ |
315 | emit_initial_value_sets, /* execute */ | |
316 | NULL, /* sub */ | |
317 | NULL, /* next */ | |
318 | 0, /* static_pass_number */ | |
7072a650 | 319 | TV_NONE, /* tv_id */ |
ef330312 PB |
320 | 0, /* properties_required */ |
321 | 0, /* properties_provided */ | |
322 | 0, /* properties_destroyed */ | |
323 | 0, /* todo_flags_start */ | |
8ddbbcae JH |
324 | TODO_dump_func /* todo_flags_finish */ |
325 | } | |
ef330312 PB |
326 | }; |
327 | ||
385b6e2d R |
328 | /* If the backend knows where to allocate pseudos for hard |
329 | register initial values, register these allocations now. */ | |
330 | void | |
6fb5fa3c | 331 | allocate_initial_values (rtx *reg_equiv_memory_loc) |
385b6e2d | 332 | { |
b48f503c | 333 | if (targetm.allocate_initial_value) |
385b6e2d | 334 | { |
38173d38 | 335 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
b48f503c | 336 | int i; |
385b6e2d | 337 | |
b48f503c KK |
338 | if (ivs == 0) |
339 | return; | |
340 | ||
341 | for (i = 0; i < ivs->num_entries; i++) | |
385b6e2d | 342 | { |
b48f503c KK |
343 | int regno = REGNO (ivs->entries[i].pseudo); |
344 | rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg); | |
b8698a0f | 345 | |
b48f503c | 346 | if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) |
41806d92 | 347 | { |
b48f503c KK |
348 | if (MEM_P (x)) |
349 | reg_equiv_memory_loc[regno] = x; | |
350 | else | |
2d6c85d3 | 351 | { |
b48f503c KK |
352 | basic_block bb; |
353 | int new_regno; | |
354 | ||
355 | gcc_assert (REG_P (x)); | |
356 | new_regno = REGNO (x); | |
357 | reg_renumber[regno] = new_regno; | |
358 | /* Poke the regno right into regno_reg_rtx so that even | |
359 | fixed regs are accepted. */ | |
6fb5fa3c | 360 | SET_REGNO (ivs->entries[i].pseudo, new_regno); |
b48f503c KK |
361 | /* Update global register liveness information. */ |
362 | FOR_EACH_BB (bb) | |
363 | { | |
89a95777 KZ |
364 | if (REGNO_REG_SET_P(df_get_live_in (bb), regno)) |
365 | SET_REGNO_REG_SET (df_get_live_in (bb), new_regno); | |
366 | if (REGNO_REG_SET_P(df_get_live_out (bb), regno)) | |
367 | SET_REGNO_REG_SET (df_get_live_out (bb), new_regno); | |
b48f503c | 368 | } |
2d6c85d3 | 369 | } |
41806d92 | 370 | } |
385b6e2d | 371 | } |
385b6e2d | 372 | } |
385b6e2d | 373 | } |
e2500fed GK |
374 | |
375 | #include "gt-integrate.h" |