OSDN Git Service

02c373aa29953d03782abc38ec0abd0970de732f
[pf3gnuchains/gcc-fork.git] / gcc / cgraphbuild.c
1 /* Callgraph construction.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4    Contributed by Jan Hubicka
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "tree-flow.h"
28 #include "langhooks.h"
29 #include "pointer-set.h"
30 #include "cgraph.h"
31 #include "intl.h"
32 #include "gimple.h"
33 #include "tree-pass.h"
34 #include "ipa-utils.h"
35
36 /* Context of record_reference.  */
37 struct record_reference_ctx
38 {
39   bool only_vars;
40 };
41
42 /* Walk tree and record all calls and references to functions/variables.
43    Called via walk_tree: TP is pointer to tree to be examined.
44    When DATA is non-null, record references to callgraph.
45    */
46
47 static tree
48 record_reference (tree *tp, int *walk_subtrees, void *data)
49 {
50   tree t = *tp;
51   tree decl;
52   struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
53
54   switch (TREE_CODE (t))
55     {
56     case VAR_DECL:
57     case FUNCTION_DECL:
58       gcc_unreachable ();
59       break;
60
61     case FDESC_EXPR:
62     case ADDR_EXPR:
63       /* Record dereferences to the functions.  This makes the
64          functions reachable unconditionally.  */
65       decl = get_base_var (*tp);
66       if (TREE_CODE (decl) == FUNCTION_DECL && !ctx->only_vars)
67         cgraph_mark_address_taken_node (cgraph_node (decl));
68
69       if (TREE_CODE (decl) == VAR_DECL)
70         {
71           gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
72           if (lang_hooks.callgraph.analyze_expr)
73             lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
74           varpool_mark_needed_node (varpool_node (decl));
75         }
76       *walk_subtrees = 0;
77       break;
78
79     default:
80       /* Save some cycles by not walking types and declaration as we
81          won't find anything useful there anyway.  */
82       if (IS_TYPE_OR_DECL_P (*tp))
83         {
84           *walk_subtrees = 0;
85           break;
86         }
87
88       if ((unsigned int) TREE_CODE (t) >= LAST_AND_UNUSED_TREE_CODE)
89         return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees);
90       break;
91     }
92
93   return NULL_TREE;
94 }
95
96 /* Reset inlining information of all incoming call edges of NODE.  */
97
98 void
99 reset_inline_failed (struct cgraph_node *node)
100 {
101   struct cgraph_edge *e;
102
103   for (e = node->callers; e; e = e->next_caller)
104     {
105       e->callee->global.inlined_to = NULL;
106       if (!node->analyzed)
107         e->inline_failed = CIF_BODY_NOT_AVAILABLE;
108       else if (node->local.redefined_extern_inline)
109         e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
110       else if (!node->local.inlinable)
111         e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
112       else if (e->call_stmt_cannot_inline_p)
113         e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
114       else
115         e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
116     }
117 }
118
119 /* Computes the frequency of the call statement so that it can be stored in
120    cgraph_edge.  BB is the basic block of the call statement.  */
121 int
122 compute_call_stmt_bb_frequency (tree decl, basic_block bb)
123 {
124   int entry_freq = ENTRY_BLOCK_PTR_FOR_FUNCTION
125                      (DECL_STRUCT_FUNCTION (decl))->frequency;
126   int freq = bb->frequency;
127
128   if (profile_status_for_function (DECL_STRUCT_FUNCTION (decl)) == PROFILE_ABSENT)
129     return CGRAPH_FREQ_BASE;
130
131   if (!entry_freq)
132     entry_freq = 1, freq++;
133
134   freq = freq * CGRAPH_FREQ_BASE / entry_freq;
135   if (freq > CGRAPH_FREQ_MAX)
136     freq = CGRAPH_FREQ_MAX;
137
138   return freq;
139 }
140
141 /* Mark address taken in STMT.  */
142
143 static bool
144 mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
145               void *data ATTRIBUTE_UNUSED)
146 {
147   if (TREE_CODE (addr) == FUNCTION_DECL)
148     {
149       struct cgraph_node *node = cgraph_node (addr);
150       cgraph_mark_address_taken_node (node);
151     }
152   else
153     {
154       addr = get_base_address (addr);
155       if (addr && TREE_CODE (addr) == VAR_DECL
156           && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
157         {
158           struct varpool_node *vnode = varpool_node (addr);
159           int walk_subtrees;
160
161           if (lang_hooks.callgraph.analyze_expr)
162             lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
163           varpool_mark_needed_node (vnode);
164         }
165     }
166
167   return false;
168 }
169
170 /* Mark load of T.  */
171
172 static bool
173 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
174            void *data ATTRIBUTE_UNUSED)
175 {
176   t = get_base_address (t);
177   if (TREE_CODE (t) == VAR_DECL
178       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
179     {
180       struct varpool_node *vnode = varpool_node (t);
181       int walk_subtrees;
182
183       if (lang_hooks.callgraph.analyze_expr)
184         lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
185       varpool_mark_needed_node (vnode);
186     }
187   return false;
188 }
189
190 /* Mark store of T.  */
191
192 static bool
193 mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
194             void *data ATTRIBUTE_UNUSED)
195 {
196   t = get_base_address (t);
197   if (TREE_CODE (t) == VAR_DECL
198       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
199     {
200       struct varpool_node *vnode = varpool_node (t);
201       int walk_subtrees;
202
203       if (lang_hooks.callgraph.analyze_expr)
204         lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
205       varpool_mark_needed_node (vnode);
206      }
207   return false;
208 }
209
210 /* Create cgraph edges for function calls.
211    Also look for functions and variables having addresses taken.  */
212
213 static unsigned int
214 build_cgraph_edges (void)
215 {
216   basic_block bb;
217   struct cgraph_node *node = cgraph_node (current_function_decl);
218   struct pointer_set_t *visited_nodes = pointer_set_create ();
219   gimple_stmt_iterator gsi;
220   tree step;
221
222   /* Create the callgraph edges and record the nodes referenced by the function.
223      body.  */
224   FOR_EACH_BB (bb)
225     {
226       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
227         {
228           gimple stmt = gsi_stmt (gsi);
229           tree decl;
230
231           if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
232             cgraph_create_edge (node, cgraph_node (decl), stmt,
233                                 bb->count,
234                                 compute_call_stmt_bb_frequency
235                                   (current_function_decl, bb),
236                                 bb->loop_depth);
237           walk_stmt_load_store_addr_ops (stmt, node, mark_load,
238                                          mark_store, mark_address);
239           if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
240               && gimple_omp_parallel_child_fn (stmt))
241             {
242               tree fn = gimple_omp_parallel_child_fn (stmt);
243               cgraph_mark_needed_node (cgraph_node (fn));
244             }
245           if (gimple_code (stmt) == GIMPLE_OMP_TASK)
246             {
247               tree fn = gimple_omp_task_child_fn (stmt);
248               if (fn)
249                 cgraph_mark_needed_node (cgraph_node (fn));
250               fn = gimple_omp_task_copy_fn (stmt);
251               if (fn)
252                 cgraph_mark_needed_node (cgraph_node (fn));
253             }
254         }
255       for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
256         walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
257                                        mark_load, mark_store, mark_address);
258    }
259
260   /* Look for initializers of constant variables and private statics.  */
261   for (step = cfun->local_decls;
262        step;
263        step = TREE_CHAIN (step))
264     {
265       tree decl = TREE_VALUE (step);
266       if (TREE_CODE (decl) == VAR_DECL
267           && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
268         varpool_finalize_decl (decl);
269     }
270
271   pointer_set_destroy (visited_nodes);
272   return 0;
273 }
274
275 struct gimple_opt_pass pass_build_cgraph_edges =
276 {
277  {
278   GIMPLE_PASS,
279   "*build_cgraph_edges",                        /* name */
280   NULL,                                 /* gate */
281   build_cgraph_edges,                   /* execute */
282   NULL,                                 /* sub */
283   NULL,                                 /* next */
284   0,                                    /* static_pass_number */
285   TV_NONE,                              /* tv_id */
286   PROP_cfg,                             /* properties_required */
287   0,                                    /* properties_provided */
288   0,                                    /* properties_destroyed */
289   0,                                    /* todo_flags_start */
290   0                                     /* todo_flags_finish */
291  }
292 };
293
294 /* Record references to functions and other variables present in the
295    initial value of DECL, a variable.
296    When ONLY_VARS is true, we mark needed only variables, not functions.  */
297
298 void
299 record_references_in_initializer (tree decl, bool only_vars)
300 {
301   struct pointer_set_t *visited_nodes = pointer_set_create ();
302   struct record_reference_ctx ctx = {false};
303
304   ctx.only_vars = only_vars;
305   walk_tree (&DECL_INITIAL (decl), record_reference,
306              &ctx, visited_nodes);
307   pointer_set_destroy (visited_nodes);
308 }
309
310 /* Rebuild cgraph edges for current function node.  This needs to be run after
311    passes that don't update the cgraph.  */
312
313 unsigned int
314 rebuild_cgraph_edges (void)
315 {
316   basic_block bb;
317   struct cgraph_node *node = cgraph_node (current_function_decl);
318   gimple_stmt_iterator gsi;
319
320   cgraph_node_remove_callees (node);
321
322   node->count = ENTRY_BLOCK_PTR->count;
323
324   FOR_EACH_BB (bb)
325     {
326       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
327         {
328           gimple stmt = gsi_stmt (gsi);
329           tree decl;
330
331           if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
332             cgraph_create_edge (node, cgraph_node (decl), stmt,
333                                 bb->count,
334                                 compute_call_stmt_bb_frequency
335                                   (current_function_decl, bb),
336                                 bb->loop_depth);
337           walk_stmt_load_store_addr_ops (stmt, node, mark_load,
338                                          mark_store, mark_address);
339
340         }
341       for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
342         walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
343                                        mark_load, mark_store, mark_address);
344     }
345   gcc_assert (!node->global.inlined_to);
346
347   return 0;
348 }
349
350 struct gimple_opt_pass pass_rebuild_cgraph_edges =
351 {
352  {
353   GIMPLE_PASS,
354   "*rebuild_cgraph_edges",              /* name */
355   NULL,                                 /* gate */
356   rebuild_cgraph_edges,                 /* execute */
357   NULL,                                 /* sub */
358   NULL,                                 /* next */
359   0,                                    /* static_pass_number */
360   TV_NONE,                              /* tv_id */
361   PROP_cfg,                             /* properties_required */
362   0,                                    /* properties_provided */
363   0,                                    /* properties_destroyed */
364   0,                                    /* todo_flags_start */
365   0,                                    /* todo_flags_finish */
366  }
367 };
368
369
370 static unsigned int
371 remove_cgraph_callee_edges (void)
372 {
373   cgraph_node_remove_callees (cgraph_node (current_function_decl));
374   return 0;
375 }
376
377 struct gimple_opt_pass pass_remove_cgraph_callee_edges =
378 {
379  {
380   GIMPLE_PASS,
381   "*remove_cgraph_callee_edges",                /* name */
382   NULL,                                 /* gate */
383   remove_cgraph_callee_edges,           /* execute */
384   NULL,                                 /* sub */
385   NULL,                                 /* next */
386   0,                                    /* static_pass_number */
387   TV_NONE,                              /* tv_id */
388   0,                                    /* properties_required */
389   0,                                    /* properties_provided */
390   0,                                    /* properties_destroyed */
391   0,                                    /* todo_flags_start */
392   0,                                    /* todo_flags_finish */
393  }
394 };