Mercurial > hg > CbC > CbC_gcc
annotate gcc/integrate.c @ 56:3c8a44c06a95
Added tag gcc-4.4.5 for changeset 77e2b8dfacca
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:41:23 +0900 |
parents | 77e2b8dfacca |
children | b7f97abdc517 |
rev | line source |
---|---|
0 | 1 /* Procedure integration for GCC. |
2 Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
0 | 4 Free Software Foundation, Inc. |
5 Contributed by Michael Tiemann (tiemann@cygnus.com) | |
6 | |
7 This file is part of GCC. | |
8 | |
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 | |
11 Software Foundation; either version 3, or (at your option) any later | |
12 version. | |
13 | |
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. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with GCC; see the file COPYING3. If not see | |
21 <http://www.gnu.org/licenses/>. */ | |
22 | |
23 #include "config.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "tm.h" | |
27 | |
28 #include "rtl.h" | |
29 #include "tree.h" | |
30 #include "tm_p.h" | |
31 #include "regs.h" | |
32 #include "flags.h" | |
33 #include "debug.h" | |
34 #include "insn-config.h" | |
35 #include "expr.h" | |
36 #include "output.h" | |
37 #include "recog.h" | |
38 #include "integrate.h" | |
39 #include "real.h" | |
40 #include "except.h" | |
41 #include "function.h" | |
42 #include "toplev.h" | |
43 #include "intl.h" | |
44 #include "params.h" | |
45 #include "ggc.h" | |
46 #include "target.h" | |
47 #include "langhooks.h" | |
48 #include "tree-pass.h" | |
49 #include "df.h" | |
50 | |
51 /* Round to the next highest integer that meets the alignment. */ | |
52 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) | |
53 | |
54 | |
55 /* Private type used by {get/has}_hard_reg_initial_val. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
56 typedef struct GTY(()) initial_value_pair { |
0 | 57 rtx hard_reg; |
58 rtx pseudo; | |
59 } initial_value_pair; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
60 typedef struct GTY(()) initial_value_struct { |
0 | 61 int num_entries; |
62 int max_entries; | |
63 initial_value_pair * GTY ((length ("%h.num_entries"))) entries; | |
64 } initial_value_struct; | |
65 | |
66 static void set_block_origin_self (tree); | |
67 static void set_block_abstract_flags (tree, int); | |
68 | |
69 | |
70 /* Return false if the function FNDECL cannot be inlined on account of its | |
71 attributes, true otherwise. */ | |
72 bool | |
73 function_attribute_inlinable_p (const_tree fndecl) | |
74 { | |
75 if (targetm.attribute_table) | |
76 { | |
77 const_tree a; | |
78 | |
79 for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) | |
80 { | |
81 const_tree name = TREE_PURPOSE (a); | |
82 int i; | |
83 | |
84 for (i = 0; targetm.attribute_table[i].name != NULL; i++) | |
85 if (is_attribute_p (targetm.attribute_table[i].name, name)) | |
86 return targetm.function_attribute_inlinable_p (fndecl); | |
87 } | |
88 } | |
89 | |
90 return true; | |
91 } | |
92 | |
93 /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the | |
94 given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so | |
95 that it points to the node itself, thus indicating that the node is its | |
96 own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for | |
97 the given node is NULL, recursively descend the decl/block tree which | |
98 it is the root of, and for each other ..._DECL or BLOCK node contained | |
99 therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also | |
100 still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN | |
101 values to point to themselves. */ | |
102 | |
103 static void | |
104 set_block_origin_self (tree stmt) | |
105 { | |
106 if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) | |
107 { | |
108 BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; | |
109 | |
110 { | |
111 tree local_decl; | |
112 | |
113 for (local_decl = BLOCK_VARS (stmt); | |
114 local_decl != NULL_TREE; | |
115 local_decl = TREE_CHAIN (local_decl)) | |
116 set_decl_origin_self (local_decl); /* Potential recursion. */ | |
117 } | |
118 | |
119 { | |
120 tree subblock; | |
121 | |
122 for (subblock = BLOCK_SUBBLOCKS (stmt); | |
123 subblock != NULL_TREE; | |
124 subblock = BLOCK_CHAIN (subblock)) | |
125 set_block_origin_self (subblock); /* Recurse. */ | |
126 } | |
127 } | |
128 } | |
129 | |
130 /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for | |
131 the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the | |
132 node to so that it points to the node itself, thus indicating that the | |
133 node represents its own (abstract) origin. Additionally, if the | |
134 DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend | |
135 the decl/block tree of which the given node is the root of, and for | |
136 each other ..._DECL or BLOCK node contained therein whose | |
137 DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL, | |
138 set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to | |
139 point to themselves. */ | |
140 | |
141 void | |
142 set_decl_origin_self (tree decl) | |
143 { | |
144 if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) | |
145 { | |
146 DECL_ABSTRACT_ORIGIN (decl) = decl; | |
147 if (TREE_CODE (decl) == FUNCTION_DECL) | |
148 { | |
149 tree arg; | |
150 | |
151 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
152 DECL_ABSTRACT_ORIGIN (arg) = arg; | |
153 if (DECL_INITIAL (decl) != NULL_TREE | |
154 && DECL_INITIAL (decl) != error_mark_node) | |
155 set_block_origin_self (DECL_INITIAL (decl)); | |
156 } | |
157 } | |
158 } | |
159 | |
160 /* Given a pointer to some BLOCK node, and a boolean value to set the | |
161 "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for | |
162 the given block, and for all local decls and all local sub-blocks | |
163 (recursively) which are contained therein. */ | |
164 | |
165 static void | |
166 set_block_abstract_flags (tree stmt, int setting) | |
167 { | |
168 tree local_decl; | |
169 tree subblock; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
170 unsigned int i; |
0 | 171 |
172 BLOCK_ABSTRACT (stmt) = setting; | |
173 | |
174 for (local_decl = BLOCK_VARS (stmt); | |
175 local_decl != NULL_TREE; | |
176 local_decl = TREE_CHAIN (local_decl)) | |
177 set_decl_abstract_flags (local_decl, setting); | |
178 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
179 for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
180 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
181 local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
182 if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
183 || TREE_CODE (local_decl) == PARM_DECL) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
184 set_decl_abstract_flags (local_decl, setting); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
185 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
186 |
0 | 187 for (subblock = BLOCK_SUBBLOCKS (stmt); |
188 subblock != NULL_TREE; | |
189 subblock = BLOCK_CHAIN (subblock)) | |
190 set_block_abstract_flags (subblock, setting); | |
191 } | |
192 | |
193 /* Given a pointer to some ..._DECL node, and a boolean value to set the | |
194 "abstract" flags to, set that value into the DECL_ABSTRACT flag for the | |
195 given decl, and (in the case where the decl is a FUNCTION_DECL) also | |
196 set the abstract flags for all of the parameters, local vars, local | |
197 blocks and sub-blocks (recursively) to the same setting. */ | |
198 | |
199 void | |
200 set_decl_abstract_flags (tree decl, int setting) | |
201 { | |
202 DECL_ABSTRACT (decl) = setting; | |
203 if (TREE_CODE (decl) == FUNCTION_DECL) | |
204 { | |
205 tree arg; | |
206 | |
207 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
208 DECL_ABSTRACT (arg) = setting; | |
209 if (DECL_INITIAL (decl) != NULL_TREE | |
210 && DECL_INITIAL (decl) != error_mark_node) | |
211 set_block_abstract_flags (DECL_INITIAL (decl), setting); | |
212 } | |
213 } | |
214 | |
215 /* Functions to keep track of the values hard regs had at the start of | |
216 the function. */ | |
217 | |
218 rtx | |
219 get_hard_reg_initial_reg (rtx reg) | |
220 { | |
221 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
222 int i; | |
223 | |
224 if (ivs == 0) | |
225 return NULL_RTX; | |
226 | |
227 for (i = 0; i < ivs->num_entries; i++) | |
228 if (rtx_equal_p (ivs->entries[i].pseudo, reg)) | |
229 return ivs->entries[i].hard_reg; | |
230 | |
231 return NULL_RTX; | |
232 } | |
233 | |
234 /* Make sure that there's a pseudo register of mode MODE that stores the | |
235 initial value of hard register REGNO. Return an rtx for such a pseudo. */ | |
236 | |
237 rtx | |
238 get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) | |
239 { | |
240 struct initial_value_struct *ivs; | |
241 rtx rv; | |
242 | |
243 rv = has_hard_reg_initial_val (mode, regno); | |
244 if (rv) | |
245 return rv; | |
246 | |
247 ivs = crtl->hard_reg_initial_vals; | |
248 if (ivs == 0) | |
249 { | |
250 ivs = GGC_NEW (initial_value_struct); | |
251 ivs->num_entries = 0; | |
252 ivs->max_entries = 5; | |
253 ivs->entries = GGC_NEWVEC (initial_value_pair, 5); | |
254 crtl->hard_reg_initial_vals = ivs; | |
255 } | |
256 | |
257 if (ivs->num_entries >= ivs->max_entries) | |
258 { | |
259 ivs->max_entries += 5; | |
260 ivs->entries = GGC_RESIZEVEC (initial_value_pair, ivs->entries, | |
261 ivs->max_entries); | |
262 } | |
263 | |
264 ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); | |
265 ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
266 | |
267 return ivs->entries[ivs->num_entries++].pseudo; | |
268 } | |
269 | |
270 /* See if get_hard_reg_initial_val has been used to create a pseudo | |
271 for the initial value of hard register REGNO in mode MODE. Return | |
272 the associated pseudo if so, otherwise return NULL. */ | |
273 | |
274 rtx | |
275 has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) | |
276 { | |
277 struct initial_value_struct *ivs; | |
278 int i; | |
279 | |
280 ivs = crtl->hard_reg_initial_vals; | |
281 if (ivs != 0) | |
282 for (i = 0; i < ivs->num_entries; i++) | |
283 if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
284 && REGNO (ivs->entries[i].hard_reg) == regno) | |
285 return ivs->entries[i].pseudo; | |
286 | |
287 return NULL_RTX; | |
288 } | |
289 | |
290 unsigned int | |
291 emit_initial_value_sets (void) | |
292 { | |
293 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
294 int i; | |
295 rtx seq; | |
296 | |
297 if (ivs == 0) | |
298 return 0; | |
299 | |
300 start_sequence (); | |
301 for (i = 0; i < ivs->num_entries; i++) | |
302 emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg); | |
303 seq = get_insns (); | |
304 end_sequence (); | |
305 | |
306 emit_insn_at_entry (seq); | |
307 return 0; | |
308 } | |
309 | |
310 struct rtl_opt_pass pass_initial_value_sets = | |
311 { | |
312 { | |
313 RTL_PASS, | |
314 "initvals", /* name */ | |
315 NULL, /* gate */ | |
316 emit_initial_value_sets, /* execute */ | |
317 NULL, /* sub */ | |
318 NULL, /* next */ | |
319 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
320 TV_NONE, /* tv_id */ |
0 | 321 0, /* properties_required */ |
322 0, /* properties_provided */ | |
323 0, /* properties_destroyed */ | |
324 0, /* todo_flags_start */ | |
325 TODO_dump_func /* todo_flags_finish */ | |
326 } | |
327 }; | |
328 | |
329 /* If the backend knows where to allocate pseudos for hard | |
330 register initial values, register these allocations now. */ | |
331 void | |
332 allocate_initial_values (rtx *reg_equiv_memory_loc) | |
333 { | |
334 if (targetm.allocate_initial_value) | |
335 { | |
336 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
337 int i; | |
338 | |
339 if (ivs == 0) | |
340 return; | |
341 | |
342 for (i = 0; i < ivs->num_entries; i++) | |
343 { | |
344 int regno = REGNO (ivs->entries[i].pseudo); | |
345 rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
346 |
0 | 347 if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) |
348 { | |
349 if (MEM_P (x)) | |
350 reg_equiv_memory_loc[regno] = x; | |
351 else | |
352 { | |
353 basic_block bb; | |
354 int new_regno; | |
355 | |
356 gcc_assert (REG_P (x)); | |
357 new_regno = REGNO (x); | |
358 reg_renumber[regno] = new_regno; | |
359 /* Poke the regno right into regno_reg_rtx so that even | |
360 fixed regs are accepted. */ | |
361 SET_REGNO (ivs->entries[i].pseudo, new_regno); | |
362 /* Update global register liveness information. */ | |
363 FOR_EACH_BB (bb) | |
364 { | |
365 if (REGNO_REG_SET_P(df_get_live_in (bb), regno)) | |
366 SET_REGNO_REG_SET (df_get_live_in (bb), new_regno); | |
367 if (REGNO_REG_SET_P(df_get_live_out (bb), regno)) | |
368 SET_REGNO_REG_SET (df_get_live_out (bb), new_regno); | |
369 } | |
370 } | |
371 } | |
372 } | |
373 } | |
374 } | |
375 | |
376 #include "gt-integrate.h" |