]>
Commit | Line | Data |
---|---|---|
f12b58b3 | 1 | /* Procedure integration for GCC. |
a4589b78 | 2 | Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
92468061 | 3 | 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
cfaf579d | 4 | Free Software Foundation, Inc. |
aef5cd70 | 5 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
6 | ||
f12b58b3 | 7 | This file is part of GCC. |
aef5cd70 | 8 | |
f12b58b3 | 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 | |
8c4c00c1 | 11 | Software Foundation; either version 3, or (at your option) any later |
f12b58b3 | 12 | version. |
aef5cd70 | 13 | |
f12b58b3 | 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. | |
aef5cd70 | 18 | |
19 | You should have received a copy of the GNU General Public License | |
8c4c00c1 | 20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
aef5cd70 | 22 | |
aef5cd70 | 23 | #include "config.h" |
405711de | 24 | #include "system.h" |
805e22b2 | 25 | #include "coretypes.h" |
26 | #include "tm.h" | |
3ef9782d | 27 | |
aef5cd70 | 28 | #include "rtl.h" |
29 | #include "tree.h" | |
7953c610 | 30 | #include "tm_p.h" |
39f90fa4 | 31 | #include "regs.h" |
aef5cd70 | 32 | #include "flags.h" |
bc244a4c | 33 | #include "debug.h" |
aef5cd70 | 34 | #include "insn-config.h" |
aef5cd70 | 35 | #include "expr.h" |
36 | #include "output.h" | |
0dbd1c74 | 37 | #include "recog.h" |
aef5cd70 | 38 | #include "integrate.h" |
485aaaaf | 39 | #include "except.h" |
aef5cd70 | 40 | #include "function.h" |
0b205f4c | 41 | #include "diagnostic-core.h" |
be2828ce | 42 | #include "intl.h" |
9a33a2e8 | 43 | #include "params.h" |
fb0c0ea7 | 44 | #include "ggc.h" |
e3c541f0 | 45 | #include "target.h" |
dbc42b78 | 46 | #include "langhooks.h" |
77fce4cd | 47 | #include "tree-pass.h" |
3072d30e | 48 | #include "df.h" |
aef5cd70 | 49 | |
4ee9c684 | 50 | /* Round to the next highest integer that meets the alignment. */ |
aef5cd70 | 51 | #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) |
aef5cd70 | 52 | \f |
fb0c0ea7 | 53 | |
450578f7 | 54 | /* Private type used by {get/has}_hard_reg_initial_val. */ |
fb1e4f4a | 55 | typedef struct GTY(()) initial_value_pair { |
fb0c0ea7 | 56 | rtx hard_reg; |
57 | rtx pseudo; | |
58 | } initial_value_pair; | |
fb1e4f4a | 59 | typedef struct GTY(()) initial_value_struct { |
fb0c0ea7 | 60 | int num_entries; |
61 | int max_entries; | |
1f3233d1 | 62 | initial_value_pair * GTY ((length ("%h.num_entries"))) entries; |
fb0c0ea7 | 63 | } initial_value_struct; |
64 | ||
952f0048 | 65 | static void set_block_origin_self (tree); |
66 | static void set_block_abstract_flags (tree, int); | |
aef5cd70 | 67 | \f |
c3dfa4e8 | 68 | |
e3c541f0 | 69 | /* Return false if the function FNDECL cannot be inlined on account of its |
70 | attributes, true otherwise. */ | |
1431bff6 | 71 | bool |
a9f1838b | 72 | function_attribute_inlinable_p (const_tree fndecl) |
e3c541f0 | 73 | { |
dc600c9e | 74 | if (targetm.attribute_table) |
e3c541f0 | 75 | { |
a9f1838b | 76 | const_tree a; |
e3c541f0 | 77 | |
dc600c9e | 78 | for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) |
e3c541f0 | 79 | { |
a9f1838b | 80 | const_tree name = TREE_PURPOSE (a); |
dc600c9e | 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)) | |
883b2e73 | 85 | return targetm.function_attribute_inlinable_p (fndecl); |
e3c541f0 | 86 | } |
e3c541f0 | 87 | } |
88 | ||
dc600c9e | 89 | return true; |
e3c541f0 | 90 | } |
aef5cd70 | 91 | \f |
234e76ad | 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 | ||
234e76ad | 102 | static void |
952f0048 | 103 | set_block_origin_self (tree stmt) |
234e76ad | 104 | { |
105 | if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) | |
106 | { | |
107 | BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; | |
108 | ||
109 | { | |
19cb6b50 | 110 | tree local_decl; |
234e76ad | 111 | |
ff33f08c | 112 | for (local_decl = BLOCK_VARS (stmt); |
234e76ad | 113 | local_decl != NULL_TREE; |
1767a056 | 114 | local_decl = DECL_CHAIN (local_decl)) |
ff33f08c | 115 | set_decl_origin_self (local_decl); /* Potential recursion. */ |
234e76ad | 116 | } |
117 | ||
118 | { | |
19cb6b50 | 119 | tree subblock; |
234e76ad | 120 | |
ff33f08c | 121 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
234e76ad | 122 | subblock != NULL_TREE; |
123 | subblock = BLOCK_CHAIN (subblock)) | |
ff33f08c | 124 | set_block_origin_self (subblock); /* Recurse. */ |
234e76ad | 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 | ||
0dbc398a | 140 | void |
952f0048 | 141 | set_decl_origin_self (tree decl) |
234e76ad | 142 | { |
143 | if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) | |
144 | { | |
145 | DECL_ABSTRACT_ORIGIN (decl) = decl; | |
146 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
147 | { | |
19cb6b50 | 148 | tree arg; |
234e76ad | 149 | |
1767a056 | 150 | for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg)) |
234e76ad | 151 | DECL_ABSTRACT_ORIGIN (arg) = arg; |
2529d76f | 152 | if (DECL_INITIAL (decl) != NULL_TREE |
153 | && DECL_INITIAL (decl) != error_mark_node) | |
234e76ad | 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 | ||
234e76ad | 164 | static void |
952f0048 | 165 | set_block_abstract_flags (tree stmt, int setting) |
234e76ad | 166 | { |
19cb6b50 | 167 | tree local_decl; |
168 | tree subblock; | |
3b0a08ea | 169 | unsigned int i; |
234e76ad | 170 | |
39f90fa4 | 171 | BLOCK_ABSTRACT (stmt) = setting; |
234e76ad | 172 | |
39f90fa4 | 173 | for (local_decl = BLOCK_VARS (stmt); |
174 | local_decl != NULL_TREE; | |
1767a056 | 175 | local_decl = DECL_CHAIN (local_decl)) |
39f90fa4 | 176 | set_decl_abstract_flags (local_decl, setting); |
234e76ad | 177 | |
3b0a08ea | 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 | ||
39f90fa4 | 186 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
187 | subblock != NULL_TREE; | |
188 | subblock = BLOCK_CHAIN (subblock)) | |
189 | set_block_abstract_flags (subblock, setting); | |
234e76ad | 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 | |
952f0048 | 199 | set_decl_abstract_flags (tree decl, int setting) |
234e76ad | 200 | { |
201 | DECL_ABSTRACT (decl) = setting; | |
202 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
203 | { | |
19cb6b50 | 204 | tree arg; |
234e76ad | 205 | |
1767a056 | 206 | for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg)) |
234e76ad | 207 | DECL_ABSTRACT (arg) = setting; |
2529d76f | 208 | if (DECL_INITIAL (decl) != NULL_TREE |
209 | && DECL_INITIAL (decl) != error_mark_node) | |
234e76ad | 210 | set_block_abstract_flags (DECL_INITIAL (decl), setting); |
211 | } | |
212 | } | |
fb0c0ea7 | 213 | \f |
214 | /* Functions to keep track of the values hard regs had at the start of | |
215 | the function. */ | |
216 | ||
66c6aab2 | 217 | rtx |
abe32cce | 218 | get_hard_reg_initial_reg (rtx reg) |
66c6aab2 | 219 | { |
abe32cce | 220 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
66c6aab2 | 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 | ||
450578f7 | 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. */ | |
fb0c0ea7 | 235 | |
450578f7 | 236 | rtx |
932fa0c9 | 237 | get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
fb0c0ea7 | 238 | { |
450578f7 | 239 | struct initial_value_struct *ivs; |
240 | rtx rv; | |
fb0c0ea7 | 241 | |
450578f7 | 242 | rv = has_hard_reg_initial_val (mode, regno); |
fb0c0ea7 | 243 | if (rv) |
244 | return rv; | |
245 | ||
abe32cce | 246 | ivs = crtl->hard_reg_initial_vals; |
fb0c0ea7 | 247 | if (ivs == 0) |
248 | { | |
ba72912a | 249 | ivs = ggc_alloc_initial_value_struct (); |
fb0c0ea7 | 250 | ivs->num_entries = 0; |
251 | ivs->max_entries = 5; | |
ba72912a | 252 | ivs->entries = ggc_alloc_vec_initial_value_pair (5); |
abe32cce | 253 | crtl->hard_reg_initial_vals = ivs; |
fb0c0ea7 | 254 | } |
255 | ||
256 | if (ivs->num_entries >= ivs->max_entries) | |
257 | { | |
258 | ivs->max_entries += 5; | |
4077bf7a | 259 | ivs->entries = GGC_RESIZEVEC (initial_value_pair, ivs->entries, |
260 | ivs->max_entries); | |
fb0c0ea7 | 261 | } |
262 | ||
450578f7 | 263 | ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); |
264 | ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
fb0c0ea7 | 265 | |
266 | return ivs->entries[ivs->num_entries++].pseudo; | |
267 | } | |
268 | ||
450578f7 | 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. */ | |
fb0c0ea7 | 272 | |
273 | rtx | |
932fa0c9 | 274 | has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) |
fb0c0ea7 | 275 | { |
450578f7 | 276 | struct initial_value_struct *ivs; |
277 | int i; | |
278 | ||
abe32cce | 279 | ivs = crtl->hard_reg_initial_vals; |
450578f7 | 280 | if (ivs != 0) |
281 | for (i = 0; i < ivs->num_entries; i++) | |
282 | if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
932fa0c9 | 283 | && REGNO (ivs->entries[i].hard_reg) == regno) |
450578f7 | 284 | return ivs->entries[i].pseudo; |
285 | ||
286 | return NULL_RTX; | |
fb0c0ea7 | 287 | } |
288 | ||
2a1990e9 | 289 | unsigned int |
952f0048 | 290 | emit_initial_value_sets (void) |
fb0c0ea7 | 291 | { |
abe32cce | 292 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
fb0c0ea7 | 293 | int i; |
294 | rtx seq; | |
295 | ||
296 | if (ivs == 0) | |
2a1990e9 | 297 | return 0; |
fb0c0ea7 | 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 | ||
aa02fa19 | 305 | emit_insn_at_entry (seq); |
2a1990e9 | 306 | return 0; |
fb0c0ea7 | 307 | } |
9fc61494 | 308 | |
20099e35 | 309 | struct rtl_opt_pass pass_initial_value_sets = |
77fce4cd | 310 | { |
20099e35 | 311 | { |
312 | RTL_PASS, | |
228967a9 | 313 | "initvals", /* name */ |
77fce4cd | 314 | NULL, /* gate */ |
315 | emit_initial_value_sets, /* execute */ | |
316 | NULL, /* sub */ | |
317 | NULL, /* next */ | |
318 | 0, /* static_pass_number */ | |
0b1615c1 | 319 | TV_NONE, /* tv_id */ |
77fce4cd | 320 | 0, /* properties_required */ |
321 | 0, /* properties_provided */ | |
322 | 0, /* properties_destroyed */ | |
323 | 0, /* todo_flags_start */ | |
20099e35 | 324 | TODO_dump_func /* todo_flags_finish */ |
325 | } | |
77fce4cd | 326 | }; |
327 | ||
9fc61494 | 328 | /* If the backend knows where to allocate pseudos for hard |
329 | register initial values, register these allocations now. */ | |
330 | void | |
3072d30e | 331 | allocate_initial_values (rtx *reg_equiv_memory_loc) |
9fc61494 | 332 | { |
edf54f2a | 333 | if (targetm.allocate_initial_value) |
9fc61494 | 334 | { |
abe32cce | 335 | struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; |
edf54f2a | 336 | int i; |
9fc61494 | 337 | |
edf54f2a | 338 | if (ivs == 0) |
339 | return; | |
340 | ||
341 | for (i = 0; i < ivs->num_entries; i++) | |
9fc61494 | 342 | { |
edf54f2a | 343 | int regno = REGNO (ivs->entries[i].pseudo); |
344 | rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg); | |
48e1416a | 345 | |
edf54f2a | 346 | if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) |
a53ff4c1 | 347 | { |
edf54f2a | 348 | if (MEM_P (x)) |
349 | reg_equiv_memory_loc[regno] = x; | |
350 | else | |
9732dffb | 351 | { |
edf54f2a | 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. */ | |
3072d30e | 360 | SET_REGNO (ivs->entries[i].pseudo, new_regno); |
edf54f2a | 361 | /* Update global register liveness information. */ |
362 | FOR_EACH_BB (bb) | |
363 | { | |
deb2741b | 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); | |
edf54f2a | 368 | } |
9732dffb | 369 | } |
a53ff4c1 | 370 | } |
9fc61494 | 371 | } |
9fc61494 | 372 | } |
9fc61494 | 373 | } |
1f3233d1 | 374 | |
375 | #include "gt-integrate.h" |