123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /* Optimization statistics functions.
- Copyright (C) 2008-2015 Free Software Foundation, Inc.
- Contributed by Richard Guenther <rguenther@suse.de>
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tree-pass.h"
- #include "tree-dump.h"
- #include "statistics.h"
- #include "hash-table.h"
- #include "hashtab.h"
- #include "hash-set.h"
- #include "vec.h"
- #include "machmode.h"
- #include "tm.h"
- #include "hard-reg-set.h"
- #include "input.h"
- #include "function.h"
- #include "context.h"
- #include "pass_manager.h"
- static int statistics_dump_nr;
- static int statistics_dump_flags;
- static FILE *statistics_dump_file;
- /* Statistics entry. A integer counter associated to a string ID
- and value. */
- typedef struct statistics_counter_s {
- const char *id;
- int val;
- bool histogram_p;
- unsigned HOST_WIDE_INT count;
- unsigned HOST_WIDE_INT prev_dumped_count;
- } statistics_counter_t;
- /* Hashtable helpers. */
- struct stats_counter_hasher
- {
- typedef statistics_counter_t value_type;
- typedef statistics_counter_t compare_type;
- static inline hashval_t hash (const value_type *);
- static inline bool equal (const value_type *, const compare_type *);
- static inline void remove (value_type *);
- };
- /* Hash a statistic counter by its string ID. */
- inline hashval_t
- stats_counter_hasher::hash (const value_type *c)
- {
- return htab_hash_string (c->id) + c->val;
- }
- /* Compare two statistic counters by their string IDs. */
- inline bool
- stats_counter_hasher::equal (const value_type *c1, const compare_type *c2)
- {
- return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
- }
- /* Free a statistics entry. */
- inline void
- stats_counter_hasher::remove (value_type *v)
- {
- free (CONST_CAST (char *, v->id));
- free (v);
- }
- typedef hash_table<stats_counter_hasher> stats_counter_table_type;
- /* Array of statistic hashes, indexed by pass id. */
- static stats_counter_table_type **statistics_hashes;
- static unsigned nr_statistics_hashes;
- /* Return the current hashtable to be used for recording or printing
- statistics. */
- static stats_counter_table_type *
- curr_statistics_hash (void)
- {
- unsigned idx;
- gcc_assert (current_pass->static_pass_number >= 0);
- idx = current_pass->static_pass_number;
- if (idx < nr_statistics_hashes
- && statistics_hashes[idx])
- return statistics_hashes[idx];
- if (idx >= nr_statistics_hashes)
- {
- statistics_hashes = XRESIZEVEC (stats_counter_table_type *,
- statistics_hashes, idx+1);
- memset (statistics_hashes + nr_statistics_hashes, 0,
- (idx + 1 - nr_statistics_hashes)
- * sizeof (stats_counter_table_type *));
- nr_statistics_hashes = idx + 1;
- }
- statistics_hashes[idx] = new stats_counter_table_type (15);
- return statistics_hashes[idx];
- }
- /* Helper for statistics_fini_pass. Print the counter difference
- since the last dump for the pass dump files. */
- int
- statistics_fini_pass_1 (statistics_counter_t **slot,
- void *data ATTRIBUTE_UNUSED)
- {
- statistics_counter_t *counter = *slot;
- unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
- if (count == 0)
- return 1;
- if (counter->histogram_p)
- fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
- counter->id, counter->val, count);
- else
- fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
- counter->id, count);
- counter->prev_dumped_count = counter->count;
- return 1;
- }
- /* Helper for statistics_fini_pass. Print the counter difference
- since the last dump for the statistics dump. */
- int
- statistics_fini_pass_2 (statistics_counter_t **slot,
- void *data ATTRIBUTE_UNUSED)
- {
- statistics_counter_t *counter = *slot;
- unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
- if (count == 0)
- return 1;
- counter->prev_dumped_count = counter->count;
- if (counter->histogram_p)
- fprintf (statistics_dump_file,
- "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
- current_pass->static_pass_number,
- current_pass->name,
- counter->id, counter->val,
- current_function_name (),
- count);
- else
- fprintf (statistics_dump_file,
- "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
- current_pass->static_pass_number,
- current_pass->name,
- counter->id,
- current_function_name (),
- count);
- counter->prev_dumped_count = counter->count;
- return 1;
- }
- /* Helper for statistics_fini_pass, reset the counters. */
- int
- statistics_fini_pass_3 (statistics_counter_t **slot,
- void *data ATTRIBUTE_UNUSED)
- {
- statistics_counter_t *counter = *slot;
- counter->prev_dumped_count = counter->count;
- return 1;
- }
- /* Dump the current statistics incrementally. */
- void
- statistics_fini_pass (void)
- {
- if (current_pass->static_pass_number == -1)
- return;
- if (dump_file
- && dump_flags & TDF_STATS)
- {
- fprintf (dump_file, "\n");
- fprintf (dump_file, "Pass statistics:\n");
- fprintf (dump_file, "----------------\n");
- curr_statistics_hash ()
- ->traverse_noresize <void *, statistics_fini_pass_1> (NULL);
- fprintf (dump_file, "\n");
- }
- if (statistics_dump_file
- && !(statistics_dump_flags & TDF_STATS
- || statistics_dump_flags & TDF_DETAILS))
- curr_statistics_hash ()
- ->traverse_noresize <void *, statistics_fini_pass_2> (NULL);
- curr_statistics_hash ()
- ->traverse_noresize <void *, statistics_fini_pass_3> (NULL);
- }
- /* Helper for printing summary information. */
- int
- statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
- {
- statistics_counter_t *counter = *slot;
- if (counter->count == 0)
- return 1;
- if (counter->histogram_p)
- fprintf (statistics_dump_file,
- "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
- pass->static_pass_number,
- pass->name,
- counter->id, counter->val,
- counter->count);
- else
- fprintf (statistics_dump_file,
- "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
- pass->static_pass_number,
- pass->name,
- counter->id,
- counter->count);
- return 1;
- }
- /* Finish the statistics and dump summary information. */
- void
- statistics_fini (void)
- {
- gcc::pass_manager *passes = g->get_passes ();
- if (!statistics_dump_file)
- return;
- if (statistics_dump_flags & TDF_STATS)
- {
- unsigned i;
- for (i = 0; i < nr_statistics_hashes; ++i)
- if (statistics_hashes[i]
- && passes->get_pass_for_id (i) != NULL)
- statistics_hashes[i]
- ->traverse_noresize <opt_pass *, statistics_fini_1>
- (passes->get_pass_for_id (i));
- }
- dump_end (statistics_dump_nr, statistics_dump_file);
- }
- /* Register the statistics dump file. */
- void
- statistics_early_init (void)
- {
- gcc::dump_manager *dumps = g->get_dumps ();
- statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
- "statistics", TDF_TREE,
- OPTGROUP_NONE,
- false);
- }
- /* Init the statistics. */
- void
- statistics_init (void)
- {
- gcc::dump_manager *dumps = g->get_dumps ();
- statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
- statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
- }
- /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
- and HISTOGRAM_P. */
- static statistics_counter_t *
- lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
- bool histogram_p)
- {
- statistics_counter_t **counter;
- statistics_counter_t c;
- c.id = id;
- c.val = val;
- counter = hash->find_slot (&c, INSERT);
- if (!*counter)
- {
- *counter = XNEW (struct statistics_counter_s);
- (*counter)->id = xstrdup (id);
- (*counter)->val = val;
- (*counter)->histogram_p = histogram_p;
- (*counter)->prev_dumped_count = 0;
- (*counter)->count = 0;
- }
- return *counter;
- }
- /* Add statistics information about event ID in function FN.
- This will increment the counter associated with ID by INCR.
- It will also dump the event to the global statistics file if requested. */
- void
- statistics_counter_event (struct function *fn, const char *id, int incr)
- {
- statistics_counter_t *counter;
- if ((!(dump_flags & TDF_STATS)
- && !statistics_dump_file)
- || incr == 0)
- return;
- if (current_pass->static_pass_number != -1)
- {
- counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
- gcc_assert (!counter->histogram_p);
- counter->count += incr;
- }
- if (!statistics_dump_file
- || !(statistics_dump_flags & TDF_DETAILS))
- return;
- fprintf (statistics_dump_file,
- "%d %s \"%s\" \"%s\" %d\n",
- current_pass->static_pass_number,
- current_pass->name,
- id,
- function_name (fn),
- incr);
- }
- /* Add statistics information about event ID in function FN with the
- histogram value VAL.
- It will dump the event to the global statistics file if requested. */
- void
- statistics_histogram_event (struct function *fn, const char *id, int val)
- {
- statistics_counter_t *counter;
- if (!(dump_flags & TDF_STATS)
- && !statistics_dump_file)
- return;
- counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
- gcc_assert (counter->histogram_p);
- counter->count += 1;
- if (!statistics_dump_file
- || !(statistics_dump_flags & TDF_DETAILS))
- return;
- fprintf (statistics_dump_file,
- "%d %s \"%s == %d\" \"%s\" 1\n",
- current_pass->static_pass_number,
- current_pass->name,
- id, val,
- function_name (fn));
- }
|