2003-08-30 Richard Earnshaw <rearnsha@arm.com>
[official-gcc.git] / gcc / tree-optimize.c
blobe5bea3ea5bc9da0c80b1ad71e7f8bd2fc7d5e45f
1 /* Control and data flow functions for trees.
2 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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. */
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"
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. */
40 static tree
41 set_save_expr_context (tree *tp,
42 int *walk_subtrees,
43 void *data)
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;
52 return NULL;
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. */
58 static tree
59 clear_decl_rtl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
61 bool nonstatic_p, local_p;
62 tree t = *tp;
64 switch (TREE_CODE (t))
66 case VAR_DECL:
67 nonstatic_p = !TREE_STATIC (t) && !DECL_EXTERNAL (t);
68 local_p = DECL_CONTEXT (t) == data;
69 break;
71 case PARM_DECL:
72 case LABEL_DECL:
73 nonstatic_p = true;
74 local_p = DECL_CONTEXT (t) == data;
75 break;
77 case RESULT_DECL:
78 nonstatic_p = local_p = true;
79 break;
81 default:
82 nonstatic_p = local_p = false;
83 break;
86 if (nonstatic_p && local_p)
87 SET_DECL_RTL (t, NULL);
89 return NULL;
92 /* For functions-as-trees languages, this performs all optimization and
93 compilation for FNDECL. */
95 void
96 tree_rest_of_compilation (tree fndecl)
98 static int nesting = -1;
100 timevar_push (TV_EXPAND);
102 ++nesting;
104 if (flag_unit_at_a_time && !cgraph_global_info_ready)
105 abort ();
107 if (nesting > 0)
108 /* Squirrel away our current state. */
109 push_function_context ();
111 /* Initialize the RTL code for the function. */
112 current_function_decl = fndecl;
113 input_location = DECL_SOURCE_LOCATION (fndecl);
114 init_function_start (fndecl);
116 /* This function is being processed in whole-function mode. */
117 cfun->x_whole_function_mode_p = 1;
119 /* Even though we're inside a function body, we still don't want to
120 call expand_expr to calculate the size of a variable-sized array.
121 We haven't necessarily assigned RTL to all variables yet, so it's
122 not safe to try to expand expressions involving them. */
123 immediate_size_expand = 0;
124 cfun->x_dont_save_pending_sizes_p = 1;
126 /* If the function has a variably modified type, there may be
127 SAVE_EXPRs in the parameter types. Their context must be set to
128 refer to this function; they cannot be expanded in the containing
129 function. */
130 if (decl_function_context (fndecl)
131 && variably_modified_type_p (TREE_TYPE (fndecl)))
132 walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
133 NULL);
135 /* Set up parameters and prepare for return, for the function. */
136 expand_function_start (fndecl, 0);
138 /* Allow language dialects to perform special processing. */
139 (*lang_hooks.rtl_expand.start) ();
141 /* If this function is `main', emit a call to `__main'
142 to run global initializers, etc. */
143 if (DECL_NAME (fndecl)
144 && MAIN_NAME_P (DECL_NAME (fndecl))
145 && DECL_FILE_SCOPE_P (fndecl))
146 expand_main_function ();
148 /* Generate the RTL for this function. */
149 (*lang_hooks.rtl_expand.stmt) (DECL_SAVED_TREE (fndecl));
151 /* We hard-wired immediate_size_expand to zero above.
152 expand_function_end will decrement this variable. So, we set the
153 variable to one here, so that after the decrement it will remain
154 zero. */
155 immediate_size_expand = 1;
157 /* Allow language dialects to perform special processing. */
158 (*lang_hooks.rtl_expand.end) ();
160 /* Generate rtl for function exit. */
161 expand_function_end ();
163 /* If this is a nested function, protect the local variables in the stack
164 above us from being collected while we're compiling this function. */
165 if (nesting > 0)
166 ggc_push_context ();
168 /* There's no need to defer outputting this function any more; we
169 know we want to output it. */
170 DECL_DEFER_OUTPUT (fndecl) = 0;
172 /* Run the optimizers and output the assembler code for this function. */
173 rest_of_compilation (fndecl);
175 /* Undo the GC context switch. */
176 if (nesting > 0)
177 ggc_pop_context ();
179 /* If requested, warn about function definitions where the function will
180 return a value (usually of some struct or union type) which itself will
181 take up a lot of stack space. */
182 if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
184 tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
186 if (ret_type && TYPE_SIZE_UNIT (ret_type)
187 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
188 && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
189 larger_than_size))
191 const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
192 unsigned int size_as_int
193 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
195 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
196 warning ("%Hsize of return value of '%D' is %u bytes",
197 locus, fndecl, size_as_int);
198 else
199 warning ("%Hsize of return value of '%D' is larger than %wd bytes",
200 locus, fndecl, larger_than_size);
204 /* ??? Looks like some of this could be combined. */
206 /* If possible, obliterate the body of the function so that it can
207 be garbage collected. */
208 if (dump_enabled_p (TDI_all))
209 /* Keep the body; we're going to dump it. */
211 else if (DECL_INLINE (fndecl) && flag_inline_trees)
212 /* We might need the body of this function so that we can expand
213 it inline somewhere else. */
215 else
216 /* We don't need the body; blow it away. */
217 DECL_SAVED_TREE (fndecl) = NULL;
219 /* Since we don't need the RTL for this function anymore, stop pointing to
220 it. That's especially important for LABEL_DECLs, since you can reach all
221 the instructions in the function from the CODE_LABEL stored in the
222 DECL_RTL for the LABEL_DECL. Walk the BLOCK-tree, clearing DECL_RTL for
223 LABEL_DECLs and non-static local variables. Note that we must check the
224 context of the variables, otherwise processing a nested function can kill
225 the rtl of a variable from an outer function. */
226 walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
227 clear_decl_rtl,
228 fndecl);
230 if (DECL_SAVED_INSNS (fndecl) == 0 && ! nesting && ! flag_inline_trees)
232 /* Stop pointing to the local nodes about to be freed.
233 But DECL_INITIAL must remain nonzero so we know this
234 was an actual function definition.
235 For a nested function, this is done in c_pop_function_context.
236 If rest_of_compilation set this to 0, leave it 0. */
237 if (DECL_INITIAL (fndecl) != 0)
238 DECL_INITIAL (fndecl) = error_mark_node;
240 DECL_ARGUMENTS (fndecl) = 0;
243 if (nesting > 0)
244 /* Return to the enclosing function. */
245 pop_function_context ();
247 --nesting;
249 timevar_pop (TV_EXPAND);