1/* Basic IPA optimizations based on profile.
2   Copyright (C) 2003-2015 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
19
20/* ipa-profile pass implements the following analysis propagating profille
21   inter-procedurally.
22
23   - Count histogram construction.  This is a histogram analyzing how much
24     time is spent executing statements with a given execution count read
25     from profile feedback. This histogram is complete only with LTO,
26     otherwise it contains information only about the current unit.
27
28     Similar histogram is also estimated by coverage runtime.  This histogram
29     is not dependent on LTO, but it suffers from various defects; first
30     gcov runtime is not weighting individual basic block by estimated execution
31     time and second the merging of multiple runs makes assumption that the
32     histogram distribution did not change.  Consequentely histogram constructed
33     here may be more precise.
34
35     The information is used to set hot/cold thresholds.
36   - Next speculative indirect call resolution is performed:  the local
37     profile pass assigns profile-id to each function and provide us with a
38     histogram specifying the most common target.  We look up the callgraph
39     node corresponding to the target and produce a speculative call.
40
41     This call may or may not survive through IPA optimization based on decision
42     of inliner.
43   - Finally we propagate the following flags: unlikely executed, executed
44     once, executed at startup and executed at exit.  These flags are used to
45     control code size/performance threshold and and code placement (by producing
46     .text.unlikely/.text.hot/.text.startup/.text.exit subsections).  */
47#include "config.h"
48#include "system.h"
49#include "coretypes.h"
50#include "tm.h"
51#include "hash-set.h"
52#include "machmode.h"
53#include "vec.h"
54#include "double-int.h"
55#include "input.h"
56#include "alias.h"
57#include "symtab.h"
58#include "wide-int.h"
59#include "inchash.h"
60#include "tree.h"
61#include "fold-const.h"
62#include "predict.h"
63#include "dominance.h"
64#include "cfg.h"
65#include "basic-block.h"
66#include "hash-map.h"
67#include "is-a.h"
68#include "plugin-api.h"
69#include "hard-reg-set.h"
70#include "input.h"
71#include "function.h"
72#include "ipa-ref.h"
73#include "cgraph.h"
74#include "tree-pass.h"
75#include "tree-ssa-alias.h"
76#include "internal-fn.h"
77#include "gimple-expr.h"
78#include "gimple.h"
79#include "gimple-iterator.h"
80#include "flags.h"
81#include "target.h"
82#include "tree-iterator.h"
83#include "ipa-utils.h"
84#include "profile.h"
85#include "params.h"
86#include "value-prof.h"
87#include "alloc-pool.h"
88#include "tree-inline.h"
89#include "lto-streamer.h"
90#include "data-streamer.h"
91#include "symbol-summary.h"
92#include "ipa-prop.h"
93#include "ipa-inline.h"
94
95/* Entry in the histogram.  */
96
97struct histogram_entry
98{
99  gcov_type count;
100  int time;
101  int size;
102};
103
104/* Histogram of profile values.
105   The histogram is represented as an ordered vector of entries allocated via
106   histogram_pool. During construction a separate hashtable is kept to lookup
107   duplicate entries.  */
108
109vec<histogram_entry *> histogram;
110static alloc_pool histogram_pool;
111
112/* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR.  */
113
114struct histogram_hash : typed_noop_remove <histogram_entry>
115{
116  typedef histogram_entry value_type;
117  typedef histogram_entry compare_type;
118  static inline hashval_t hash (const value_type *);
119  static inline int equal (const value_type *, const compare_type *);
120};
121
122inline hashval_t
123histogram_hash::hash (const histogram_entry *val)
124{
125  return val->count;
126}
127
128inline int
129histogram_hash::equal (const histogram_entry *val, const histogram_entry *val2)
130{
131  return val->count == val2->count;
132}
133
134/* Account TIME and SIZE executed COUNT times into HISTOGRAM.
135   HASHTABLE is the on-side hash kept to avoid duplicates.  */
136
137static void
138account_time_size (hash_table<histogram_hash> *hashtable,
139		   vec<histogram_entry *> &histogram,
140		   gcov_type count, int time, int size)
141{
142  histogram_entry key = {count, 0, 0};
143  histogram_entry **val = hashtable->find_slot (&key, INSERT);
144
145  if (!*val)
146    {
147      *val = (histogram_entry *) pool_alloc (histogram_pool);
148      **val = key;
149      histogram.safe_push (*val);
150    }
151  (*val)->time += time;
152  (*val)->size += size;
153}
154
155int
156cmp_counts (const void *v1, const void *v2)
157{
158  const histogram_entry *h1 = *(const histogram_entry * const *)v1;
159  const histogram_entry *h2 = *(const histogram_entry * const *)v2;
160  if (h1->count < h2->count)
161    return 1;
162  if (h1->count > h2->count)
163    return -1;
164  return 0;
165}
166
167/* Dump HISTOGRAM to FILE.  */
168
169static void
170dump_histogram (FILE *file, vec<histogram_entry *> histogram)
171{
172  unsigned int i;
173  gcov_type overall_time = 0, cumulated_time = 0, cumulated_size = 0, overall_size = 0;
174
175  fprintf (dump_file, "Histogram:\n");
176  for (i = 0; i < histogram.length (); i++)
177    {
178      overall_time += histogram[i]->count * histogram[i]->time;
179      overall_size += histogram[i]->size;
180    }
181  if (!overall_time)
182    overall_time = 1;
183  if (!overall_size)
184    overall_size = 1;
185  for (i = 0; i < histogram.length (); i++)
186    {
187      cumulated_time += histogram[i]->count * histogram[i]->time;
188      cumulated_size += histogram[i]->size;
189      fprintf (file, "  %"PRId64": time:%i (%2.2f) size:%i (%2.2f)\n",
190	       (int64_t) histogram[i]->count,
191	       histogram[i]->time,
192	       cumulated_time * 100.0 / overall_time,
193	       histogram[i]->size,
194	       cumulated_size * 100.0 / overall_size);
195   }
196}
197
198/* Collect histogram from CFG profiles.  */
199
200static void
201ipa_profile_generate_summary (void)
202{
203  struct cgraph_node *node;
204  gimple_stmt_iterator gsi;
205  basic_block bb;
206
207  hash_table<histogram_hash> hashtable (10);
208  histogram_pool = create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry),
209				      10);
210
211  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
212    FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
213      {
214	int time = 0;
215	int size = 0;
216        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
217	  {
218	    gimple stmt = gsi_stmt (gsi);
219	    if (gimple_code (stmt) == GIMPLE_CALL
220		&& !gimple_call_fndecl (stmt))
221	      {
222		histogram_value h;
223		h = gimple_histogram_value_of_type
224		      (DECL_STRUCT_FUNCTION (node->decl),
225		       stmt, HIST_TYPE_INDIR_CALL);
226		/* No need to do sanity check: gimple_ic_transform already
227		   takes away bad histograms.  */
228		if (h)
229		  {
230		    /* counter 0 is target, counter 1 is number of execution we called target,
231		       counter 2 is total number of executions.  */
232		    if (h->hvalue.counters[2])
233		      {
234			struct cgraph_edge * e = node->get_edge (stmt);
235			if (e && !e->indirect_unknown_callee)
236			  continue;
237			e->indirect_info->common_target_id
238			  = h->hvalue.counters [0];
239			e->indirect_info->common_target_probability
240			  = GCOV_COMPUTE_SCALE (h->hvalue.counters [1], h->hvalue.counters [2]);
241			if (e->indirect_info->common_target_probability > REG_BR_PROB_BASE)
242			  {
243			    if (dump_file)
244			      fprintf (dump_file, "Probability capped to 1\n");
245			    e->indirect_info->common_target_probability = REG_BR_PROB_BASE;
246			  }
247		      }
248		    gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->decl),
249						    stmt, h);
250		  }
251	      }
252	    time += estimate_num_insns (stmt, &eni_time_weights);
253	    size += estimate_num_insns (stmt, &eni_size_weights);
254	  }
255	account_time_size (&hashtable, histogram, bb->count, time, size);
256      }
257  histogram.qsort (cmp_counts);
258}
259
260/* Serialize the ipa info for lto.  */
261
262static void
263ipa_profile_write_summary (void)
264{
265  struct lto_simple_output_block *ob
266    = lto_create_simple_output_block (LTO_section_ipa_profile);
267  unsigned int i;
268
269  streamer_write_uhwi_stream (ob->main_stream, histogram.length ());
270  for (i = 0; i < histogram.length (); i++)
271    {
272      streamer_write_gcov_count_stream (ob->main_stream, histogram[i]->count);
273      streamer_write_uhwi_stream (ob->main_stream, histogram[i]->time);
274      streamer_write_uhwi_stream (ob->main_stream, histogram[i]->size);
275    }
276  lto_destroy_simple_output_block (ob);
277}
278
279/* Deserialize the ipa info for lto.  */
280
281static void
282ipa_profile_read_summary (void)
283{
284  struct lto_file_decl_data ** file_data_vec
285    = lto_get_file_decl_data ();
286  struct lto_file_decl_data * file_data;
287  int j = 0;
288
289  hash_table<histogram_hash> hashtable (10);
290  histogram_pool = create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry),
291				      10);
292
293  while ((file_data = file_data_vec[j++]))
294    {
295      const char *data;
296      size_t len;
297      struct lto_input_block *ib
298	= lto_create_simple_input_block (file_data,
299					 LTO_section_ipa_profile,
300					 &data, &len);
301      if (ib)
302	{
303          unsigned int num = streamer_read_uhwi (ib);
304	  unsigned int n;
305	  for (n = 0; n < num; n++)
306	    {
307	      gcov_type count = streamer_read_gcov_count (ib);
308	      int time = streamer_read_uhwi (ib);
309	      int size = streamer_read_uhwi (ib);
310	      account_time_size (&hashtable, histogram,
311				 count, time, size);
312	    }
313	  lto_destroy_simple_input_block (file_data,
314					  LTO_section_ipa_profile,
315					  ib, data, len);
316	}
317    }
318  histogram.qsort (cmp_counts);
319}
320
321/* Data used by ipa_propagate_frequency.  */
322
323struct ipa_propagate_frequency_data
324{
325  cgraph_node *function_symbol;
326  bool maybe_unlikely_executed;
327  bool maybe_executed_once;
328  bool only_called_at_startup;
329  bool only_called_at_exit;
330};
331
332/* Worker for ipa_propagate_frequency_1.  */
333
334static bool
335ipa_propagate_frequency_1 (struct cgraph_node *node, void *data)
336{
337  struct ipa_propagate_frequency_data *d;
338  struct cgraph_edge *edge;
339
340  d = (struct ipa_propagate_frequency_data *)data;
341  for (edge = node->callers;
342       edge && (d->maybe_unlikely_executed || d->maybe_executed_once
343	        || d->only_called_at_startup || d->only_called_at_exit);
344       edge = edge->next_caller)
345    {
346      if (edge->caller != d->function_symbol)
347	{
348          d->only_called_at_startup &= edge->caller->only_called_at_startup;
349	  /* It makes sense to put main() together with the static constructors.
350	     It will be executed for sure, but rest of functions called from
351	     main are definitely not at startup only.  */
352	  if (MAIN_NAME_P (DECL_NAME (edge->caller->decl)))
353	    d->only_called_at_startup = 0;
354          d->only_called_at_exit &= edge->caller->only_called_at_exit;
355	}
356
357      /* When profile feedback is available, do not try to propagate too hard;
358	 counts are already good guide on function frequencies and roundoff
359	 errors can make us to push function into unlikely section even when
360	 it is executed by the train run.  Transfer the function only if all
361	 callers are unlikely executed.  */
362      if (profile_info
363	  && opt_for_fn (d->function_symbol->decl, flag_branch_probabilities)
364	  /* Thunks are not profiled.  This is more or less implementation
365	     bug.  */
366	  && !d->function_symbol->thunk.thunk_p
367	  && (edge->caller->frequency != NODE_FREQUENCY_UNLIKELY_EXECUTED
368	      || (edge->caller->global.inlined_to
369		  && edge->caller->global.inlined_to->frequency
370		     != NODE_FREQUENCY_UNLIKELY_EXECUTED)))
371	  d->maybe_unlikely_executed = false;
372      if (!edge->frequency)
373	continue;
374      switch (edge->caller->frequency)
375        {
376	case NODE_FREQUENCY_UNLIKELY_EXECUTED:
377	  break;
378	case NODE_FREQUENCY_EXECUTED_ONCE:
379	  if (dump_file && (dump_flags & TDF_DETAILS))
380	    fprintf (dump_file, "  Called by %s that is executed once\n",
381		     edge->caller->name ());
382	  d->maybe_unlikely_executed = false;
383	  if (inline_edge_summary (edge)->loop_depth)
384	    {
385	      d->maybe_executed_once = false;
386	      if (dump_file && (dump_flags & TDF_DETAILS))
387	        fprintf (dump_file, "  Called in loop\n");
388	    }
389	  break;
390	case NODE_FREQUENCY_HOT:
391	case NODE_FREQUENCY_NORMAL:
392	  if (dump_file && (dump_flags & TDF_DETAILS))
393	    fprintf (dump_file, "  Called by %s that is normal or hot\n",
394		     edge->caller->name ());
395	  d->maybe_unlikely_executed = false;
396	  d->maybe_executed_once = false;
397	  break;
398	}
399    }
400  return edge != NULL;
401}
402
403/* Return ture if NODE contains hot calls.  */
404
405bool
406contains_hot_call_p (struct cgraph_node *node)
407{
408  struct cgraph_edge *e;
409  for (e = node->callees; e; e = e->next_callee)
410    if (e->maybe_hot_p ())
411      return true;
412    else if (!e->inline_failed
413	     && contains_hot_call_p (e->callee))
414      return true;
415  for (e = node->indirect_calls; e; e = e->next_callee)
416    if (e->maybe_hot_p ())
417      return true;
418  return false;
419}
420
421/* See if the frequency of NODE can be updated based on frequencies of its
422   callers.  */
423bool
424ipa_propagate_frequency (struct cgraph_node *node)
425{
426  struct ipa_propagate_frequency_data d = {node, true, true, true, true};
427  bool changed = false;
428
429  /* We can not propagate anything useful about externally visible functions
430     nor about virtuals.  */
431  if (!node->local.local
432      || node->alias
433      || (opt_for_fn (node->decl, flag_devirtualize)
434	  && DECL_VIRTUAL_P (node->decl)))
435    return false;
436  gcc_assert (node->analyzed);
437  if (dump_file && (dump_flags & TDF_DETAILS))
438    fprintf (dump_file, "Processing frequency %s\n", node->name ());
439
440  node->call_for_symbol_and_aliases (ipa_propagate_frequency_1, &d,
441				     true);
442
443  if ((d.only_called_at_startup && !d.only_called_at_exit)
444      && !node->only_called_at_startup)
445    {
446       node->only_called_at_startup = true;
447       if (dump_file)
448         fprintf (dump_file, "Node %s promoted to only called at startup.\n",
449		  node->name ());
450       changed = true;
451    }
452  if ((d.only_called_at_exit && !d.only_called_at_startup)
453      && !node->only_called_at_exit)
454    {
455       node->only_called_at_exit = true;
456       if (dump_file)
457         fprintf (dump_file, "Node %s promoted to only called at exit.\n",
458		  node->name ());
459       changed = true;
460    }
461
462  /* With profile we can decide on hot/normal based on count.  */
463  if (node->count)
464    {
465      bool hot = false;
466      if (node->count >= get_hot_bb_threshold ())
467	hot = true;
468      if (!hot)
469	hot |= contains_hot_call_p (node);
470      if (hot)
471	{
472	  if (node->frequency != NODE_FREQUENCY_HOT)
473	    {
474	      if (dump_file)
475		fprintf (dump_file, "Node %s promoted to hot.\n",
476			 node->name ());
477	      node->frequency = NODE_FREQUENCY_HOT;
478	      return true;
479	    }
480	  return false;
481	}
482      else if (node->frequency == NODE_FREQUENCY_HOT)
483	{
484	  if (dump_file)
485	    fprintf (dump_file, "Node %s reduced to normal.\n",
486		     node->name ());
487	  node->frequency = NODE_FREQUENCY_NORMAL;
488	  changed = true;
489	}
490    }
491  /* These come either from profile or user hints; never update them.  */
492  if (node->frequency == NODE_FREQUENCY_HOT
493      || node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
494    return changed;
495  if (d.maybe_unlikely_executed)
496    {
497      node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
498      if (dump_file)
499	fprintf (dump_file, "Node %s promoted to unlikely executed.\n",
500		 node->name ());
501      changed = true;
502    }
503  else if (d.maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
504    {
505      node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
506      if (dump_file)
507	fprintf (dump_file, "Node %s promoted to executed once.\n",
508		 node->name ());
509      changed = true;
510    }
511  return changed;
512}
513
514/* Simple ipa profile pass propagating frequencies across the callgraph.  */
515
516static unsigned int
517ipa_profile (void)
518{
519  struct cgraph_node **order;
520  struct cgraph_edge *e;
521  int order_pos;
522  bool something_changed = false;
523  int i;
524  gcov_type overall_time = 0, cutoff = 0, cumulated = 0, overall_size = 0;
525  struct cgraph_node *n,*n2;
526  int nindirect = 0, ncommon = 0, nunknown = 0, nuseless = 0, nconverted = 0;
527  bool node_map_initialized = false;
528
529  if (dump_file)
530    dump_histogram (dump_file, histogram);
531  for (i = 0; i < (int)histogram.length (); i++)
532    {
533      overall_time += histogram[i]->count * histogram[i]->time;
534      overall_size += histogram[i]->size;
535    }
536  if (overall_time)
537    {
538      gcov_type threshold;
539
540      gcc_assert (overall_size);
541      if (dump_file)
542	{
543	  gcov_type min, cumulated_time = 0, cumulated_size = 0;
544
545	  fprintf (dump_file, "Overall time: %"PRId64"\n",
546		   (int64_t)overall_time);
547	  min = get_hot_bb_threshold ();
548          for (i = 0; i < (int)histogram.length () && histogram[i]->count >= min;
549	       i++)
550	    {
551	      cumulated_time += histogram[i]->count * histogram[i]->time;
552	      cumulated_size += histogram[i]->size;
553	    }
554	  fprintf (dump_file, "GCOV min count: %"PRId64
555		   " Time:%3.2f%% Size:%3.2f%%\n",
556		   (int64_t)min,
557		   cumulated_time * 100.0 / overall_time,
558		   cumulated_size * 100.0 / overall_size);
559	}
560      cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
561      threshold = 0;
562      for (i = 0; cumulated < cutoff; i++)
563	{
564	  cumulated += histogram[i]->count * histogram[i]->time;
565          threshold = histogram[i]->count;
566	}
567      if (!threshold)
568	threshold = 1;
569      if (dump_file)
570	{
571	  gcov_type cumulated_time = 0, cumulated_size = 0;
572
573          for (i = 0;
574	       i < (int)histogram.length () && histogram[i]->count >= threshold;
575	       i++)
576	    {
577	      cumulated_time += histogram[i]->count * histogram[i]->time;
578	      cumulated_size += histogram[i]->size;
579	    }
580	  fprintf (dump_file, "Determined min count: %"PRId64
581		   " Time:%3.2f%% Size:%3.2f%%\n",
582		   (int64_t)threshold,
583		   cumulated_time * 100.0 / overall_time,
584		   cumulated_size * 100.0 / overall_size);
585	}
586      if (threshold > get_hot_bb_threshold ()
587	  || in_lto_p)
588	{
589	  if (dump_file)
590	    fprintf (dump_file, "Threshold updated.\n");
591          set_hot_bb_threshold (threshold);
592	}
593    }
594  histogram.release ();
595  free_alloc_pool (histogram_pool);
596
597  /* Produce speculative calls: we saved common traget from porfiling into
598     e->common_target_id.  Now, at link time, we can look up corresponding
599     function node and produce speculative call.  */
600
601  FOR_EACH_DEFINED_FUNCTION (n)
602    {
603      bool update = false;
604
605      if (!opt_for_fn (n->decl, flag_ipa_profile))
606	continue;
607
608      for (e = n->indirect_calls; e; e = e->next_callee)
609	{
610	  if (n->count)
611	    nindirect++;
612	  if (e->indirect_info->common_target_id)
613	    {
614	      if (!node_map_initialized)
615	        init_node_map (false);
616	      node_map_initialized = true;
617	      ncommon++;
618	      n2 = find_func_by_profile_id (e->indirect_info->common_target_id);
619	      if (n2)
620		{
621		  if (dump_file)
622		    {
623		      fprintf (dump_file, "Indirect call -> direct call from"
624			       " other module %s/%i => %s/%i, prob %3.2f\n",
625			       xstrdup_for_dump (n->name ()), n->order,
626			       xstrdup_for_dump (n2->name ()), n2->order,
627			       e->indirect_info->common_target_probability
628			       / (float)REG_BR_PROB_BASE);
629		    }
630		  if (e->indirect_info->common_target_probability
631		      < REG_BR_PROB_BASE / 2)
632		    {
633		      nuseless++;
634		      if (dump_file)
635			fprintf (dump_file,
636				 "Not speculating: probability is too low.\n");
637		    }
638		  else if (!e->maybe_hot_p ())
639		    {
640		      nuseless++;
641		      if (dump_file)
642			fprintf (dump_file,
643				 "Not speculating: call is cold.\n");
644		    }
645		  else if (n2->get_availability () <= AVAIL_INTERPOSABLE
646			   && n2->can_be_discarded_p ())
647		    {
648		      nuseless++;
649		      if (dump_file)
650			fprintf (dump_file,
651				 "Not speculating: target is overwritable "
652				 "and can be discarded.\n");
653		    }
654		  else
655		    {
656		      /* Target may be overwritable, but profile says that
657			 control flow goes to this particular implementation
658			 of N2.  Speculate on the local alias to allow inlining.
659		       */
660		      if (!n2->can_be_discarded_p ())
661			{
662			  cgraph_node *alias;
663			  alias = dyn_cast<cgraph_node *> (n2->noninterposable_alias ());
664			  if (alias)
665			    n2 = alias;
666			}
667		      nconverted++;
668		      e->make_speculative
669			(n2,
670			 apply_scale (e->count,
671				      e->indirect_info->common_target_probability),
672			 apply_scale (e->frequency,
673				      e->indirect_info->common_target_probability));
674		      update = true;
675		    }
676		}
677	      else
678		{
679		  if (dump_file)
680		    fprintf (dump_file, "Function with profile-id %i not found.\n",
681			     e->indirect_info->common_target_id);
682		  nunknown++;
683		}
684	    }
685	 }
686       if (update)
687	 inline_update_overall_summary (n);
688     }
689  if (node_map_initialized)
690    del_node_map ();
691  if (dump_file && nindirect)
692    fprintf (dump_file,
693	     "%i indirect calls trained.\n"
694	     "%i (%3.2f%%) have common target.\n"
695	     "%i (%3.2f%%) targets was not found.\n"
696	     "%i (%3.2f%%) speculations seems useless.\n"
697	     "%i (%3.2f%%) speculations produced.\n",
698	     nindirect,
699	     ncommon, ncommon * 100.0 / nindirect,
700	     nunknown, nunknown * 100.0 / nindirect,
701	     nuseless, nuseless * 100.0 / nindirect,
702	     nconverted, nconverted * 100.0 / nindirect);
703
704  order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
705  order_pos = ipa_reverse_postorder (order);
706  for (i = order_pos - 1; i >= 0; i--)
707    {
708      if (order[i]->local.local
709	  && opt_for_fn (order[i]->decl, flag_ipa_profile)
710	  && ipa_propagate_frequency (order[i]))
711	{
712	  for (e = order[i]->callees; e; e = e->next_callee)
713	    if (e->callee->local.local && !e->callee->aux)
714	      {
715	        something_changed = true;
716	        e->callee->aux = (void *)1;
717	      }
718	}
719      order[i]->aux = NULL;
720    }
721
722  while (something_changed)
723    {
724      something_changed = false;
725      for (i = order_pos - 1; i >= 0; i--)
726	{
727	  if (order[i]->aux
728	      && opt_for_fn (order[i]->decl, flag_ipa_profile)
729	      && ipa_propagate_frequency (order[i]))
730	    {
731	      for (e = order[i]->callees; e; e = e->next_callee)
732		if (e->callee->local.local && !e->callee->aux)
733		  {
734		    something_changed = true;
735		    e->callee->aux = (void *)1;
736		  }
737	    }
738	  order[i]->aux = NULL;
739	}
740    }
741  free (order);
742  return 0;
743}
744
745namespace {
746
747const pass_data pass_data_ipa_profile =
748{
749  IPA_PASS, /* type */
750  "profile_estimate", /* name */
751  OPTGROUP_NONE, /* optinfo_flags */
752  TV_IPA_PROFILE, /* tv_id */
753  0, /* properties_required */
754  0, /* properties_provided */
755  0, /* properties_destroyed */
756  0, /* todo_flags_start */
757  0, /* todo_flags_finish */
758};
759
760class pass_ipa_profile : public ipa_opt_pass_d
761{
762public:
763  pass_ipa_profile (gcc::context *ctxt)
764    : ipa_opt_pass_d (pass_data_ipa_profile, ctxt,
765		      ipa_profile_generate_summary, /* generate_summary */
766		      ipa_profile_write_summary, /* write_summary */
767		      ipa_profile_read_summary, /* read_summary */
768		      NULL, /* write_optimization_summary */
769		      NULL, /* read_optimization_summary */
770		      NULL, /* stmt_fixup */
771		      0, /* function_transform_todo_flags_start */
772		      NULL, /* function_transform */
773		      NULL) /* variable_transform */
774  {}
775
776  /* opt_pass methods: */
777  virtual bool gate (function *) { return flag_ipa_profile || in_lto_p; }
778  virtual unsigned int execute (function *) { return ipa_profile (); }
779
780}; // class pass_ipa_profile
781
782} // anon namespace
783
784ipa_opt_pass_d *
785make_pass_ipa_profile (gcc::context *ctxt)
786{
787  return new pass_ipa_profile (ctxt);
788}
789