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 }