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