]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-nrv.c
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / tree-nrv.c
CommitLineData
4ee9c684 1/* Language independent return value optimizations
71e45bc2 2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
ce084dfc 3 Free Software Foundation, Inc.
4ee9c684 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
8c4c00c1 9the Free Software Foundation; either version 3, or (at your option)
4ee9c684 10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
8c4c00c1 18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
4ee9c684 20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "tree.h"
4ee9c684 26#include "function.h"
27#include "basic-block.h"
ce084dfc 28#include "tree-pretty-print.h"
4ee9c684 29#include "tree-flow.h"
4ee9c684 30#include "tree-pass.h"
31#include "langhooks.h"
a7a46268 32#include "flags.h" /* For "optimize" in gate_pass_return_slot.
33 FIXME: That should be up to the pass manager,
34 but pass_nrv is not in pass_all_optimizations. */
4ee9c684 35
36/* This file implements return value optimizations for functions which
37 return aggregate types.
38
39 Basically this pass searches the function for return statements which
40 return a local aggregate. When converted to RTL such statements will
41 generate a copy from the local aggregate to final return value destination
42 mandated by the target's ABI.
43
44 That copy can often be avoided by directly constructing the return value
45 into the final destination mandated by the target's ABI.
46
48e1416a 47 This is basically a generic equivalent to the C++ front-end's
4ee9c684 48 Named Return Value optimization. */
49
50struct nrv_data
51{
52 /* This is the temporary (a VAR_DECL) which appears in all of
53 this function's RETURN_EXPR statements. */
54 tree var;
55
365db11e 56 /* This is the function's RESULT_DECL. We will replace all occurrences
4ee9c684 57 of VAR with RESULT_DECL when we apply this optimization. */
58 tree result;
a8dd994c 59 int modified;
4ee9c684 60};
61
62static tree finalize_nrv_r (tree *, int *, void *);
63
64/* Callback for the tree walker.
65
66 If TP refers to a RETURN_EXPR, then set the expression being returned
67 to nrv_data->result.
68
69 If TP refers to nrv_data->var, then replace nrv_data->var with
70 nrv_data->result.
71
72 If we reach a node where we know all the subtrees are uninteresting,
73 then set *WALK_SUBTREES to zero. */
74
75static tree
76finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
77{
75a70cf9 78 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
79 struct nrv_data *dp = (struct nrv_data *) wi->info;
4ee9c684 80
81 /* No need to walk into types. */
82 if (TYPE_P (*tp))
83 *walk_subtrees = 0;
15a9f039 84
2c763ed4 85 /* Otherwise replace all occurrences of VAR with RESULT. */
4ee9c684 86 else if (*tp == dp->var)
a8dd994c 87 {
88 *tp = dp->result;
89 dp->modified = 1;
90 }
4ee9c684 91
92 /* Keep iterating. */
93 return NULL_TREE;
94}
95
96/* Main entry point for return value optimizations.
97
98 If this function always returns the same local variable, and that
99 local variable is an aggregate type, then replace the variable with
100 the function's DECL_RESULT.
101
102 This is the equivalent of the C++ named return value optimization
103 applied to optimized trees in a language independent form. If we
104 ever encounter languages which prevent this kind of optimization,
105 then we could either have the languages register the optimization or
106 we could change the gating function to check the current language. */
48e1416a 107
2a1990e9 108static unsigned int
4ee9c684 109tree_nrv (void)
110{
111 tree result = DECL_RESULT (current_function_decl);
112 tree result_type = TREE_TYPE (result);
113 tree found = NULL;
114 basic_block bb;
75a70cf9 115 gimple_stmt_iterator gsi;
4ee9c684 116 struct nrv_data data;
117
118 /* If this function does not return an aggregate type in memory, then
119 there is nothing to do. */
120 if (!aggregate_value_p (result, current_function_decl))
2a1990e9 121 return 0;
4ee9c684 122
e264d515 123 /* If a GIMPLE type is returned in memory, finalize_nrv_r might create
124 non-GIMPLE. */
125 if (is_gimple_reg_type (result_type))
126 return 0;
127
93ef9154 128 /* If the front end already did something like this, don't do it here. */
129 if (DECL_NAME (result))
130 return 0;
131
a97b4ced 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))
136 return 0;
137
84ef41be 138 /* Look through each block for assignments to the RESULT_DECL. */
4ee9c684 139 FOR_EACH_BB (bb)
140 {
75a70cf9 141 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4ee9c684 142 {
75a70cf9 143 gimple stmt = gsi_stmt (gsi);
144 tree ret_val;
84ef41be 145
75a70cf9 146 if (gimple_code (stmt) == GIMPLE_RETURN)
4ee9c684 147 {
84ef41be 148 /* In a function with an aggregate return value, the
149 gimplifier has changed all non-empty RETURN_EXPRs to
150 return the RESULT_DECL. */
75a70cf9 151 ret_val = gimple_return_retval (stmt);
152 if (ret_val)
153 gcc_assert (ret_val == result);
84ef41be 154 }
93ef9154 155 else if (gimple_has_lhs (stmt)
156 && gimple_get_lhs (stmt) == result)
84ef41be 157 {
75a70cf9 158 tree rhs;
159
160 if (!gimple_assign_copy_p (stmt))
161 return 0;
162
163 rhs = gimple_assign_rhs1 (stmt);
84ef41be 164
165 /* Now verify that this return statement uses the same value
166 as any previously encountered return statement. */
167 if (found != NULL)
168 {
169 /* If we found a return statement using a different variable
170 than previous return statements, then we can not perform
171 NRV optimizations. */
75a70cf9 172 if (found != rhs)
2a1990e9 173 return 0;
84ef41be 174 }
175 else
75a70cf9 176 found = rhs;
84ef41be 177
178 /* The returned value must be a local automatic variable of the
179 same type and alignment as the function's result. */
180 if (TREE_CODE (found) != VAR_DECL
181 || TREE_THIS_VOLATILE (found)
182 || DECL_CONTEXT (found) != current_function_decl
183 || TREE_STATIC (found)
184 || TREE_ADDRESSABLE (found)
185 || DECL_ALIGN (found) > DECL_ALIGN (result)
c8ca3ee7 186 || !useless_type_conversion_p (result_type,
a97b4ced 187 TREE_TYPE (found)))
2a1990e9 188 return 0;
4ee9c684 189 }
93ef9154 190 else if (gimple_has_lhs (stmt))
fdf6266d 191 {
93ef9154 192 tree addr = get_base_address (gimple_get_lhs (stmt));
48e1416a 193 /* If there's any MODIFY of component of RESULT,
fdf6266d 194 then bail out. */
195 if (addr && addr == result)
196 return 0;
197 }
4ee9c684 198 }
199 }
200
201 if (!found)
2a1990e9 202 return 0;
4ee9c684 203
204 /* If dumping details, then note once and only the NRV replacement. */
205 if (dump_file && (dump_flags & TDF_DETAILS))
206 {
207 fprintf (dump_file, "NRV Replaced: ");
208 print_generic_expr (dump_file, found, dump_flags);
209 fprintf (dump_file, " with: ");
210 print_generic_expr (dump_file, result, dump_flags);
211 fprintf (dump_file, "\n");
212 }
213
214 /* At this point we know that all the return statements return the
215 same local which has suitable attributes for NRV. Copy debugging
93ef9154 216 information from FOUND to RESULT if it will be useful. But don't set
217 DECL_ABSTRACT_ORIGIN to point at another function. */
218 if (!DECL_IGNORED_P (found)
219 && !(DECL_ABSTRACT_ORIGIN (found)
220 && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (found)) != current_function_decl))
221 {
222 DECL_NAME (result) = DECL_NAME (found);
223 DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found);
224 DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found);
225 }
226
a97b4ced 227 TREE_ADDRESSABLE (result) |= TREE_ADDRESSABLE (found);
4ee9c684 228
229 /* Now walk through the function changing all references to VAR to be
230 RESULT. */
231 data.var = found;
232 data.result = result;
233 FOR_EACH_BB (bb)
234 {
75a70cf9 235 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
84ef41be 236 {
75a70cf9 237 gimple stmt = gsi_stmt (gsi);
84ef41be 238 /* If this is a copy from VAR to RESULT, remove it. */
75a70cf9 239 if (gimple_assign_copy_p (stmt)
240 && gimple_assign_lhs (stmt) == result
241 && gimple_assign_rhs1 (stmt) == found)
a8dd994c 242 {
243 unlink_stmt_vdef (stmt);
244 gsi_remove (&gsi, true);
bc8a8451 245 release_defs (stmt);
a8dd994c 246 }
84ef41be 247 else
248 {
75a70cf9 249 struct walk_stmt_info wi;
250 memset (&wi, 0, sizeof (wi));
251 wi.info = &data;
a8dd994c 252 data.modified = 0;
75a70cf9 253 walk_gimple_op (stmt, finalize_nrv_r, &wi);
a8dd994c 254 if (data.modified)
255 update_stmt (stmt);
75a70cf9 256 gsi_next (&gsi);
84ef41be 257 }
258 }
4ee9c684 259 }
260
e641a23b 261 SET_DECL_VALUE_EXPR (found, result);
262 DECL_HAS_VALUE_EXPR_P (found) = 1;
263
2a1990e9 264 return 0;
4ee9c684 265}
266
bff4202c 267static bool
268gate_pass_return_slot (void)
269{
270 return optimize > 0;
271}
272
48e1416a 273struct gimple_opt_pass pass_nrv =
4ee9c684 274{
20099e35 275 {
276 GIMPLE_PASS,
4ee9c684 277 "nrv", /* name */
c7875731 278 OPTGROUP_NONE, /* optinfo_flags */
bff4202c 279 gate_pass_return_slot, /* gate */
4ee9c684 280 tree_nrv, /* execute */
281 NULL, /* sub */
282 NULL, /* next */
283 0, /* static_pass_number */
284 TV_TREE_NRV, /* tv_id */
a8dd994c 285 PROP_ssa | PROP_cfg, /* properties_required */
4ee9c684 286 0, /* properties_provided */
287 0, /* properties_destroyed */
288 0, /* todo_flags_start */
771e2890 289 TODO_ggc_collect /* todo_flags_finish */
20099e35 290 }
4ee9c684 291};
ea523851 292
166cf564 293/* Determine (pessimistically) whether DEST is available for NRV
294 optimization, where DEST is expected to be the LHS of a modify
295 expression where the RHS is a function returning an aggregate.
296
095a3ce9 297 DEST is available if it is not clobbered or used by the call. */
166cf564 298
299static bool
4debfcfc 300dest_safe_for_nrv_p (gimple call)
166cf564 301{
4debfcfc 302 tree dest = gimple_call_lhs (call);
fbb5d9ac 303
4debfcfc 304 dest = get_base_address (dest);
305 if (! dest)
fbb5d9ac 306 return false;
307
308 if (TREE_CODE (dest) == SSA_NAME)
4debfcfc 309 return true;
fbb5d9ac 310
095a3ce9 311 if (call_may_clobber_ref_p (call, dest)
312 || ref_maybe_used_by_stmt_p (call, dest))
fbb5d9ac 313 return false;
fb0ac376 314
fbb5d9ac 315 return true;
166cf564 316}
317
75a70cf9 318/* Walk through the function looking for GIMPLE_ASSIGNs with calls that
ea523851 319 return in memory on the RHS. For each of these, determine whether it is
320 safe to pass the address of the LHS as the return slot, and mark the
321 call appropriately if so.
322
323 The NRV shares the return slot with a local variable in the callee; this
324 optimization shares the return slot with the target of the call within
325 the caller. If the NRV is performed (which we can't know in general),
326 this optimization is safe if the address of the target has not
327 escaped prior to the call. If it has, modifications to the local
328 variable will produce visible changes elsewhere, as in PR c++/19317. */
329
2a1990e9 330static unsigned int
ea523851 331execute_return_slot_opt (void)
332{
333 basic_block bb;
334
335 FOR_EACH_BB (bb)
336 {
75a70cf9 337 gimple_stmt_iterator gsi;
338 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
ea523851 339 {
75a70cf9 340 gimple stmt = gsi_stmt (gsi);
341 bool slot_opt_p;
342
343 if (is_gimple_call (stmt)
344 && gimple_call_lhs (stmt)
345 && !gimple_call_return_slot_opt_p (stmt)
346 && aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
095a3ce9 347 gimple_call_fndecl (stmt)))
75a70cf9 348 {
349 /* Check if the location being assigned to is
4debfcfc 350 clobbered by the call. */
351 slot_opt_p = dest_safe_for_nrv_p (stmt);
75a70cf9 352 gimple_call_set_return_slot_opt (stmt, slot_opt_p);
353 }
ea523851 354 }
355 }
2a1990e9 356 return 0;
ea523851 357}
358
48e1416a 359struct gimple_opt_pass pass_return_slot =
ea523851 360{
20099e35 361 {
362 GIMPLE_PASS,
ea523851 363 "retslot", /* name */
c7875731 364 OPTGROUP_NONE, /* optinfo_flags */
ea523851 365 NULL, /* gate */
366 execute_return_slot_opt, /* execute */
367 NULL, /* sub */
368 NULL, /* next */
369 0, /* static_pass_number */
0b1615c1 370 TV_NONE, /* tv_id */
2f8eb909 371 PROP_ssa, /* properties_required */
ea523851 372 0, /* properties_provided */
373 0, /* properties_destroyed */
374 0, /* todo_flags_start */
20099e35 375 0 /* todo_flags_finish */
376 }
ea523851 377};