Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-nrv.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Language independent return value optimizations | 1 /* Language independent return value optimizations |
2 Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. | 2 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify | 6 GCC is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
42 mandated by the target's ABI. | 42 mandated by the target's ABI. |
43 | 43 |
44 That copy can often be avoided by directly constructing the return value | 44 That copy can often be avoided by directly constructing the return value |
45 into the final destination mandated by the target's ABI. | 45 into the final destination mandated by the target's ABI. |
46 | 46 |
47 This is basically a generic equivalent to the C++ front-end's | 47 This is basically a generic equivalent to the C++ front-end's |
48 Named Return Value optimization. */ | 48 Named Return Value optimization. */ |
49 | 49 |
50 struct nrv_data | 50 struct nrv_data |
51 { | 51 { |
52 /* This is the temporary (a VAR_DECL) which appears in all of | 52 /* This is the temporary (a VAR_DECL) which appears in all of |
54 tree var; | 54 tree var; |
55 | 55 |
56 /* This is the function's RESULT_DECL. We will replace all occurrences | 56 /* This is the function's RESULT_DECL. We will replace all occurrences |
57 of VAR with RESULT_DECL when we apply this optimization. */ | 57 of VAR with RESULT_DECL when we apply this optimization. */ |
58 tree result; | 58 tree result; |
59 int modified; | |
59 }; | 60 }; |
60 | 61 |
61 static tree finalize_nrv_r (tree *, int *, void *); | 62 static tree finalize_nrv_r (tree *, int *, void *); |
62 | 63 |
63 /* Callback for the tree walker. | 64 /* Callback for the tree walker. |
81 if (TYPE_P (*tp)) | 82 if (TYPE_P (*tp)) |
82 *walk_subtrees = 0; | 83 *walk_subtrees = 0; |
83 | 84 |
84 /* Otherwise replace all occurrences of VAR with RESULT. */ | 85 /* Otherwise replace all occurrences of VAR with RESULT. */ |
85 else if (*tp == dp->var) | 86 else if (*tp == dp->var) |
86 *tp = dp->result; | 87 { |
88 *tp = dp->result; | |
89 dp->modified = 1; | |
90 } | |
87 | 91 |
88 /* Keep iterating. */ | 92 /* Keep iterating. */ |
89 return NULL_TREE; | 93 return NULL_TREE; |
90 } | 94 } |
91 | 95 |
98 This is the equivalent of the C++ named return value optimization | 102 This is the equivalent of the C++ named return value optimization |
99 applied to optimized trees in a language independent form. If we | 103 applied to optimized trees in a language independent form. If we |
100 ever encounter languages which prevent this kind of optimization, | 104 ever encounter languages which prevent this kind of optimization, |
101 then we could either have the languages register the optimization or | 105 then we could either have the languages register the optimization or |
102 we could change the gating function to check the current language. */ | 106 we could change the gating function to check the current language. */ |
103 | 107 |
104 static unsigned int | 108 static unsigned int |
105 tree_nrv (void) | 109 tree_nrv (void) |
106 { | 110 { |
107 tree result = DECL_RESULT (current_function_decl); | 111 tree result = DECL_RESULT (current_function_decl); |
108 tree result_type = TREE_TYPE (result); | 112 tree result_type = TREE_TYPE (result); |
121 if (is_gimple_reg_type (result_type)) | 125 if (is_gimple_reg_type (result_type)) |
122 return 0; | 126 return 0; |
123 | 127 |
124 /* If the front end already did something like this, don't do it here. */ | 128 /* If the front end already did something like this, don't do it here. */ |
125 if (DECL_NAME (result)) | 129 if (DECL_NAME (result)) |
130 return 0; | |
131 | |
132 /* If the result has its address taken then it might be modified | |
133 by means not detected in the following loop. Bail out in this | |
134 case. */ | |
135 if (TREE_ADDRESSABLE (result)) | |
126 return 0; | 136 return 0; |
127 | 137 |
128 /* Look through each block for assignments to the RESULT_DECL. */ | 138 /* Look through each block for assignments to the RESULT_DECL. */ |
129 FOR_EACH_BB (bb) | 139 FOR_EACH_BB (bb) |
130 { | 140 { |
172 || DECL_CONTEXT (found) != current_function_decl | 182 || DECL_CONTEXT (found) != current_function_decl |
173 || TREE_STATIC (found) | 183 || TREE_STATIC (found) |
174 || TREE_ADDRESSABLE (found) | 184 || TREE_ADDRESSABLE (found) |
175 || DECL_ALIGN (found) > DECL_ALIGN (result) | 185 || DECL_ALIGN (found) > DECL_ALIGN (result) |
176 || !useless_type_conversion_p (result_type, | 186 || !useless_type_conversion_p (result_type, |
177 TREE_TYPE (found))) | 187 TREE_TYPE (found))) |
178 return 0; | 188 return 0; |
179 } | 189 } |
180 else if (gimple_has_lhs (stmt)) | 190 else if (gimple_has_lhs (stmt)) |
181 { | 191 { |
182 tree addr = get_base_address (gimple_get_lhs (stmt)); | 192 tree addr = get_base_address (gimple_get_lhs (stmt)); |
183 /* If there's any MODIFY of component of RESULT, | 193 /* If there's any MODIFY of component of RESULT, |
184 then bail out. */ | 194 then bail out. */ |
185 if (addr && addr == result) | 195 if (addr && addr == result) |
186 return 0; | 196 return 0; |
187 } | 197 } |
188 } | 198 } |
212 DECL_NAME (result) = DECL_NAME (found); | 222 DECL_NAME (result) = DECL_NAME (found); |
213 DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found); | 223 DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found); |
214 DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found); | 224 DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found); |
215 } | 225 } |
216 | 226 |
217 TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found); | 227 TREE_ADDRESSABLE (result) |= TREE_ADDRESSABLE (found); |
218 | 228 |
219 /* Now walk through the function changing all references to VAR to be | 229 /* Now walk through the function changing all references to VAR to be |
220 RESULT. */ | 230 RESULT. */ |
221 data.var = found; | 231 data.var = found; |
222 data.result = result; | 232 data.result = result; |
227 gimple stmt = gsi_stmt (gsi); | 237 gimple stmt = gsi_stmt (gsi); |
228 /* If this is a copy from VAR to RESULT, remove it. */ | 238 /* If this is a copy from VAR to RESULT, remove it. */ |
229 if (gimple_assign_copy_p (stmt) | 239 if (gimple_assign_copy_p (stmt) |
230 && gimple_assign_lhs (stmt) == result | 240 && gimple_assign_lhs (stmt) == result |
231 && gimple_assign_rhs1 (stmt) == found) | 241 && gimple_assign_rhs1 (stmt) == found) |
232 gsi_remove (&gsi, true); | 242 { |
243 unlink_stmt_vdef (stmt); | |
244 gsi_remove (&gsi, true); | |
245 } | |
233 else | 246 else |
234 { | 247 { |
235 struct walk_stmt_info wi; | 248 struct walk_stmt_info wi; |
236 memset (&wi, 0, sizeof (wi)); | 249 memset (&wi, 0, sizeof (wi)); |
237 wi.info = &data; | 250 wi.info = &data; |
251 data.modified = 0; | |
238 walk_gimple_op (stmt, finalize_nrv_r, &wi); | 252 walk_gimple_op (stmt, finalize_nrv_r, &wi); |
253 if (data.modified) | |
254 update_stmt (stmt); | |
239 gsi_next (&gsi); | 255 gsi_next (&gsi); |
240 } | 256 } |
241 } | 257 } |
242 } | 258 } |
243 | 259 |
250 gate_pass_return_slot (void) | 266 gate_pass_return_slot (void) |
251 { | 267 { |
252 return optimize > 0; | 268 return optimize > 0; |
253 } | 269 } |
254 | 270 |
255 struct gimple_opt_pass pass_nrv = | 271 struct gimple_opt_pass pass_nrv = |
256 { | 272 { |
257 { | 273 { |
258 GIMPLE_PASS, | 274 GIMPLE_PASS, |
259 "nrv", /* name */ | 275 "nrv", /* name */ |
260 gate_pass_return_slot, /* gate */ | 276 gate_pass_return_slot, /* gate */ |
261 tree_nrv, /* execute */ | 277 tree_nrv, /* execute */ |
262 NULL, /* sub */ | 278 NULL, /* sub */ |
263 NULL, /* next */ | 279 NULL, /* next */ |
264 0, /* static_pass_number */ | 280 0, /* static_pass_number */ |
265 TV_TREE_NRV, /* tv_id */ | 281 TV_TREE_NRV, /* tv_id */ |
266 PROP_cfg, /* properties_required */ | 282 PROP_ssa | PROP_cfg, /* properties_required */ |
267 0, /* properties_provided */ | 283 0, /* properties_provided */ |
268 0, /* properties_destroyed */ | 284 0, /* properties_destroyed */ |
269 0, /* todo_flags_start */ | 285 0, /* todo_flags_start */ |
270 TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */ | 286 TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */ |
271 } | 287 } |
337 } | 353 } |
338 } | 354 } |
339 return 0; | 355 return 0; |
340 } | 356 } |
341 | 357 |
342 struct gimple_opt_pass pass_return_slot = | 358 struct gimple_opt_pass pass_return_slot = |
343 { | 359 { |
344 { | 360 { |
345 GIMPLE_PASS, | 361 GIMPLE_PASS, |
346 "retslot", /* name */ | 362 "retslot", /* name */ |
347 NULL, /* gate */ | 363 NULL, /* gate */ |
348 execute_return_slot_opt, /* execute */ | 364 execute_return_slot_opt, /* execute */ |
349 NULL, /* sub */ | 365 NULL, /* sub */ |
350 NULL, /* next */ | 366 NULL, /* next */ |
351 0, /* static_pass_number */ | 367 0, /* static_pass_number */ |
352 0, /* tv_id */ | 368 TV_NONE, /* tv_id */ |
353 PROP_ssa | PROP_alias, /* properties_required */ | 369 PROP_ssa, /* properties_required */ |
354 0, /* properties_provided */ | 370 0, /* properties_provided */ |
355 0, /* properties_destroyed */ | 371 0, /* properties_destroyed */ |
356 0, /* todo_flags_start */ | 372 0, /* todo_flags_start */ |
357 0 /* todo_flags_finish */ | 373 0 /* todo_flags_finish */ |
358 } | 374 } |