Mercurial > hg > CbC > CbC_gcc
annotate gcc/integrate.c @ 88:f214c1d5b862
merge 89
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 20 Dec 2011 18:53:46 +0900 |
parents | f6334be47118 |
children |
rev | line source |
---|---|
0 | 1 /* Procedure integration for GCC. |
2 Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
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 "except.h" | |
40 #include "function.h" | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
41 #include "diagnostic-core.h" |
0 | 42 #include "intl.h" |
43 #include "params.h" | |
44 #include "ggc.h" | |
45 #include "target.h" | |
46 #include "langhooks.h" | |
47 #include "tree-pass.h" | |
48 #include "df.h" | |
49 | |
50 /* Round to the next highest integer that meets the alignment. */ | |
51 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) | |
52 | |
53 | |
54 /* 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
|
55 typedef struct GTY(()) initial_value_pair { |
0 | 56 rtx hard_reg; |
57 rtx pseudo; | |
58 } 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
|
59 typedef struct GTY(()) initial_value_struct { |
0 | 60 int num_entries; |
61 int max_entries; | |
62 initial_value_pair * GTY ((length ("%h.num_entries"))) entries; | |
63 } initial_value_struct; | |
64 | |
65 static void set_block_origin_self (tree); | |
66 static void set_block_abstract_flags (tree, int); | |
67 | |
68 | |
69 /* Return false if the function FNDECL cannot be inlined on account of its | |
70 attributes, true otherwise. */ | |
71 bool | |
72 function_attribute_inlinable_p (const_tree fndecl) | |
73 { | |
74 if (targetm.attribute_table) | |
75 { | |
76 const_tree a; | |
77 | |
78 for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) | |
79 { | |
80 const_tree name = TREE_PURPOSE (a); | |
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)) | |
85 return targetm.function_attribute_inlinable_p (fndecl); | |
86 } | |
87 } | |
88 | |
89 return true; | |
90 } | |
91 | |
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 | |
102 static void | |
103 set_block_origin_self (tree stmt) | |
104 { | |
105 if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) | |
106 { | |
107 BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; | |
108 | |
109 { | |
110 tree local_decl; | |
111 | |
112 for (local_decl = BLOCK_VARS (stmt); | |
113 local_decl != NULL_TREE; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
114 local_decl = DECL_CHAIN (local_decl)) |
0 | 115 set_decl_origin_self (local_decl); /* Potential recursion. */ |
116 } | |
117 | |
118 { | |
119 tree subblock; | |
120 | |
121 for (subblock = BLOCK_SUBBLOCKS (stmt); | |
122 subblock != NULL_TREE; | |
123 subblock = BLOCK_CHAIN (subblock)) | |
124 set_block_origin_self (subblock); /* Recurse. */ | |
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 | |
140 void | |
141 set_decl_origin_self (tree decl) | |
142 { | |
143 if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) | |
144 { | |
145 DECL_ABSTRACT_ORIGIN (decl) = decl; | |
146 if (TREE_CODE (decl) == FUNCTION_DECL) | |
147 { | |
148 tree arg; | |
149 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
150 for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg)) |
0 | 151 DECL_ABSTRACT_ORIGIN (arg) = arg; |
152 if (DECL_INITIAL (decl) != NULL_TREE | |
153 && DECL_INITIAL (decl) != error_mark_node) | |
154 set_block_origin_self (DECL_INITIAL (decl)); | |
155 } | |
156 } | |
157 } | |
158 | |
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 | |
164 static void | |
165 set_block_abstract_flags (tree stmt, int setting) | |
166 { | |
167 tree local_decl; | |
168 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
|
169 unsigned int i; |
0 | 170 |
171 BLOCK_ABSTRACT (stmt) = setting; | |
172 | |
173 for (local_decl = BLOCK_VARS (stmt); | |
174 local_decl != NULL_TREE; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
175 local_decl = DECL_CHAIN (local_decl)) |
0 | 176 set_decl_abstract_flags (local_decl, setting); |
177 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
178 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
|
179 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
180 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
|
181 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
|
182 || 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
|
183 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
|
184 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
185 |
0 | 186 for (subblock = BLOCK_SUBBLOCKS (stmt); |
187 subblock != NULL_TREE; | |
188 subblock = BLOCK_CHAIN (subblock)) | |
189 set_block_abstract_flags (subblock, setting); | |
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 | |
199 set_decl_abstract_flags (tree decl, int setting) | |
200 { | |
201 DECL_ABSTRACT (decl) = setting; | |
202 if (TREE_CODE (decl) == FUNCTION_DECL) | |
203 { | |
204 tree arg; | |
205 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
206 for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg)) |
0 | 207 DECL_ABSTRACT (arg) = setting; |
208 if (DECL_INITIAL (decl) != NULL_TREE | |
209 && DECL_INITIAL (decl) != error_mark_node) | |
210 set_block_abstract_flags (DECL_INITIAL (decl), setting); | |
211 } | |
212 } | |
213 | |
214 /* Functions to keep track of the values hard regs had at the start of | |
215 the function. */ | |
216 | |
217 rtx | |
218 get_hard_reg_initial_reg (rtx reg) | |
219 { | |
220 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
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 | |
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. */ | |
235 | |
236 rtx | |
237 get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) | |
238 { | |
239 struct initial_value_struct *ivs; | |
240 rtx rv; | |
241 | |
242 rv = has_hard_reg_initial_val (mode, regno); | |
243 if (rv) | |
244 return rv; | |
245 | |
246 ivs = crtl->hard_reg_initial_vals; | |
247 if (ivs == 0) | |
248 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
249 ivs = ggc_alloc_initial_value_struct (); |
0 | 250 ivs->num_entries = 0; |
251 ivs->max_entries = 5; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
252 ivs->entries = ggc_alloc_vec_initial_value_pair (5); |
0 | 253 crtl->hard_reg_initial_vals = ivs; |
254 } | |
255 | |
256 if (ivs->num_entries >= ivs->max_entries) | |
257 { | |
258 ivs->max_entries += 5; | |
259 ivs->entries = GGC_RESIZEVEC (initial_value_pair, ivs->entries, | |
260 ivs->max_entries); | |
261 } | |
262 | |
263 ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); | |
264 ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
265 | |
266 return ivs->entries[ivs->num_entries++].pseudo; | |
267 } | |
268 | |
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. */ | |
272 | |
273 rtx | |
274 has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) | |
275 { | |
276 struct initial_value_struct *ivs; | |
277 int i; | |
278 | |
279 ivs = crtl->hard_reg_initial_vals; | |
280 if (ivs != 0) | |
281 for (i = 0; i < ivs->num_entries; i++) | |
282 if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
283 && REGNO (ivs->entries[i].hard_reg) == regno) | |
284 return ivs->entries[i].pseudo; | |
285 | |
286 return NULL_RTX; | |
287 } | |
288 | |
289 unsigned int | |
290 emit_initial_value_sets (void) | |
291 { | |
292 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
293 int i; | |
294 rtx seq; | |
295 | |
296 if (ivs == 0) | |
297 return 0; | |
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 | |
305 emit_insn_at_entry (seq); | |
306 return 0; | |
307 } | |
308 | |
309 struct rtl_opt_pass pass_initial_value_sets = | |
310 { | |
311 { | |
312 RTL_PASS, | |
313 "initvals", /* name */ | |
314 NULL, /* gate */ | |
315 emit_initial_value_sets, /* execute */ | |
316 NULL, /* sub */ | |
317 NULL, /* next */ | |
318 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
|
319 TV_NONE, /* tv_id */ |
0 | 320 0, /* properties_required */ |
321 0, /* properties_provided */ | |
322 0, /* properties_destroyed */ | |
323 0, /* todo_flags_start */ | |
324 TODO_dump_func /* todo_flags_finish */ | |
325 } | |
326 }; | |
327 | |
328 /* If the backend knows where to allocate pseudos for hard | |
329 register initial values, register these allocations now. */ | |
330 void | |
331 allocate_initial_values (rtx *reg_equiv_memory_loc) | |
332 { | |
333 if (targetm.allocate_initial_value) | |
334 { | |
335 struct initial_value_struct *ivs = crtl->hard_reg_initial_vals; | |
336 int i; | |
337 | |
338 if (ivs == 0) | |
339 return; | |
340 | |
341 for (i = 0; i < ivs->num_entries; i++) | |
342 { | |
343 int regno = REGNO (ivs->entries[i].pseudo); | |
344 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
|
345 |
0 | 346 if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) |
347 { | |
348 if (MEM_P (x)) | |
349 reg_equiv_memory_loc[regno] = x; | |
350 else | |
351 { | |
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. */ | |
360 SET_REGNO (ivs->entries[i].pseudo, new_regno); | |
361 /* Update global register liveness information. */ | |
362 FOR_EACH_BB (bb) | |
363 { | |
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); | |
368 } | |
369 } | |
370 } | |
371 } | |
372 } | |
373 } | |
374 | |
375 #include "gt-integrate.h" |