OSDN Git Service

PR optimization/13424 (hppa), bootstrap/14462, c/14828
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
1 /* Control and data flow functions for trees.
2    Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "toplev.h"
25 #include "tree.h"
26 #include "tree-inline.h"
27 #include "flags.h"
28 #include "langhooks.h"
29 #include "cgraph.h"
30 #include "timevar.h"
31 #include "tm.h"
32 #include "function.h"
33 #include "ggc.h"
34
35
36 /* Called to move the SAVE_EXPRs for parameter declarations in a
37    nested function into the nested function.  DATA is really the
38    nested FUNCTION_DECL.  */
39
40 static tree
41 set_save_expr_context (tree *tp,
42                        int *walk_subtrees,
43                        void *data)
44 {
45   if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
46     SAVE_EXPR_CONTEXT (*tp) = (tree) data;
47   /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
48      circularity.  */
49   else if (DECL_P (*tp))
50     *walk_subtrees = 0;
51
52   return NULL;
53 }
54
55 /* Clear out the DECL_RTL for the non-static local variables in BLOCK and
56    its sub-blocks.  DATA is the decl of the function being processed.  */
57
58 static tree
59 clear_decl_rtl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
60 {
61   bool nonstatic_p, local_p;
62   tree t = *tp;
63
64   switch (TREE_CODE (t))
65     {
66     case VAR_DECL:
67       nonstatic_p = !TREE_STATIC (t) && !DECL_EXTERNAL (t);
68       local_p = decl_function_context (t) == data;
69       break;
70
71     case PARM_DECL:
72     case LABEL_DECL:
73       nonstatic_p = true;
74       local_p = decl_function_context (t) == data;
75       break;
76
77     case RESULT_DECL:
78       nonstatic_p = local_p = true;
79       break;
80
81     default:
82       nonstatic_p = local_p = false;
83       break;
84     }
85
86   if (nonstatic_p && local_p)
87     SET_DECL_RTL (t, NULL);
88
89   return NULL;
90 }
91
92 /* For functions-as-trees languages, this performs all optimization and
93    compilation for FNDECL.  */
94
95 void
96 tree_rest_of_compilation (tree fndecl, bool nested_p)
97 {
98   location_t saved_loc;
99   struct cgraph_node *node, *saved_node = NULL;
100
101   timevar_push (TV_EXPAND);
102
103   if (flag_unit_at_a_time && !cgraph_global_info_ready)
104     abort ();
105
106   /* Initialize the RTL code for the function.  */
107   current_function_decl = fndecl;
108   saved_loc = input_location;
109   input_location = DECL_SOURCE_LOCATION (fndecl);
110   init_function_start (fndecl);
111
112   /* This function is being processed in whole-function mode.  */
113   cfun->x_whole_function_mode_p = 1;
114
115   /* Even though we're inside a function body, we still don't want to
116      call expand_expr to calculate the size of a variable-sized array.
117      We haven't necessarily assigned RTL to all variables yet, so it's
118      not safe to try to expand expressions involving them.  */
119   immediate_size_expand = 0;
120   cfun->x_dont_save_pending_sizes_p = 1;
121
122   node = cgraph_node (fndecl);
123
124   /* We might need the body of this function so that we can expand
125      it inline somewhere else.  This means not lowering some constructs
126      such as exception handling.  */
127   if (cgraph_preserve_function_body_p (fndecl))
128     {
129       if (!flag_unit_at_a_time)
130         {
131           struct cgraph_edge *e;
132
133           saved_node = cgraph_clone_node (node);
134           for (e = saved_node->callees; e; e = e->next_callee)
135             if (!e->inline_failed)
136               cgraph_clone_inlined_nodes (e, true);
137         }
138       cfun->saved_tree = save_body (fndecl, &cfun->saved_args);
139     }
140
141   if (flag_inline_trees)
142     {
143       struct cgraph_edge *e;
144       for (e = node->callees; e; e = e->next_callee)
145         if (!e->inline_failed || warn_inline)
146           break;
147       if (e)
148         {
149           timevar_push (TV_INTEGRATION);
150           optimize_inline_calls (fndecl);
151           timevar_pop (TV_INTEGRATION);
152         }
153     }
154
155   /* If the function has a variably modified type, there may be
156      SAVE_EXPRs in the parameter types.  Their context must be set to
157      refer to this function; they cannot be expanded in the containing
158      function.  */
159   if (decl_function_context (fndecl)
160       && variably_modified_type_p (TREE_TYPE (fndecl)))
161     walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
162                NULL);
163
164   /* Set up parameters and prepare for return, for the function.  */
165   expand_function_start (fndecl, 0);
166
167   /* Allow language dialects to perform special processing.  */
168   lang_hooks.rtl_expand.start ();
169
170   /* If this function is `main', emit a call to `__main'
171      to run global initializers, etc.  */
172   if (DECL_NAME (fndecl)
173       && MAIN_NAME_P (DECL_NAME (fndecl))
174       && DECL_FILE_SCOPE_P (fndecl))
175     expand_main_function ();
176
177   /* Generate the RTL for this function.  */
178   lang_hooks.rtl_expand.stmt (DECL_SAVED_TREE (fndecl));
179
180   /* We hard-wired immediate_size_expand to zero above.
181      expand_function_end will decrement this variable.  So, we set the
182      variable to one here, so that after the decrement it will remain
183      zero.  */
184   immediate_size_expand = 1;
185
186   /* Allow language dialects to perform special processing.  */
187   lang_hooks.rtl_expand.end ();
188
189   /* Generate rtl for function exit.  */
190   expand_function_end ();
191
192   /* If this is a nested function, protect the local variables in the stack
193      above us from being collected while we're compiling this function.  */
194   if (nested_p)
195     ggc_push_context ();
196
197   /* There's no need to defer outputting this function any more; we
198      know we want to output it.  */
199   DECL_DEFER_OUTPUT (fndecl) = 0;
200
201   /* Run the optimizers and output the assembler code for this function.  */
202   rest_of_compilation (fndecl);
203
204
205   /* Undo the GC context switch.  */
206   if (nested_p)
207     ggc_pop_context ();
208
209   /* If requested, warn about function definitions where the function will
210      return a value (usually of some struct or union type) which itself will
211      take up a lot of stack space.  */
212   if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
213     {
214       tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
215
216       if (ret_type && TYPE_SIZE_UNIT (ret_type)
217           && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
218           && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
219                                    larger_than_size))
220         {
221           unsigned int size_as_int
222             = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
223
224           if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
225             warning ("%Jsize of return value of '%D' is %u bytes",
226                      fndecl, fndecl, size_as_int);
227           else
228             warning ("%Jsize of return value of '%D' is larger than %wd bytes",
229                      fndecl, fndecl, larger_than_size);
230         }
231     }
232
233   /* Since we don't need the RTL for this function anymore, stop pointing to
234      it.  That's especially important for LABEL_DECLs, since you can reach all
235      the instructions in the function from the CODE_LABEL stored in the
236      DECL_RTL for the LABEL_DECL.  Walk the BLOCK-tree, clearing DECL_RTL for
237      LABEL_DECLs and non-static local variables.  Note that we must check the
238      context of the variables, otherwise processing a nested function can kill
239      the rtl of a variable from an outer function.  */
240   walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
241                                 clear_decl_rtl,
242                                 fndecl);
243   /* Restore original body if still needed.  */
244   if (cfun->saved_tree)
245     {
246       DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
247       DECL_ARGUMENTS (fndecl) = cfun->saved_args;
248
249       /* When not in unit-at-a-time mode, we must preserve out of line copy
250          representing node before inlining.  Restore original outgoing edges
251          using clone we created earlier.  */
252       if (!flag_unit_at_a_time)
253         {
254           struct cgraph_edge *e;
255           while (node->callees)
256             cgraph_remove_edge (node->callees);
257           node->callees = saved_node->callees;
258           saved_node->callees = NULL;
259           for (e = saved_node->callees; e; e = e->next_callee)
260             e->caller = node;
261           cgraph_remove_node (saved_node);
262         }
263     }
264   else
265     {
266       DECL_SAVED_TREE (fndecl) = NULL;
267       if (cgraph_node (fndecl)->origin)
268         {
269           /* Stop pointing to the local nodes about to be freed.
270              But DECL_INITIAL must remain nonzero so we know this
271              was an actual function definition.
272              For a nested function, this is done in c_pop_function_context.
273              If rest_of_compilation set this to 0, leave it 0.  */
274           if (DECL_INITIAL (fndecl) != 0)
275             DECL_INITIAL (fndecl) = error_mark_node;
276         }
277     }
278   free_after_compilation (cfun);
279   cfun = 0;
280   DECL_STRUCT_FUNCTION (fndecl) = 0;
281
282   input_location = saved_loc;
283
284   timevar_pop (TV_EXPAND);
285 }