OSDN Git Service

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