gcc/ChangeLog: 2014-11-12 Martin Liska <mli...@suse.cz>
* Makefile.in: New object file is added. * cgraph.h (symbol_table::allocate_cgraph_symbol): Summary UID is filled up. * cgraph_summary.c: New file. * cgraph_summary.h: New file. * gengtype.c (open_base_files): Add cgraph_summary.h. * toplev.c (general_init): Call constructor of symbol_table. --- gcc/Makefile.in | 1 + gcc/cgraph.h | 8 ++ gcc/cgraph_summary.c | 34 ++++++ gcc/cgraph_summary.h | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/gengtype.c | 4 +- gcc/toplev.c | 3 +- 6 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 gcc/cgraph_summary.c create mode 100644 gcc/cgraph_summary.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3d671c2..bf11277 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1175,6 +1175,7 @@ OBJS = \ cfgrtl.o \ symtab.o \ cgraph.o \ + cgraph_summary.o \ cgraphbuild.o \ cgraphunit.o \ cgraphclones.o \ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index e2becb9..588b6d5 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1225,6 +1225,8 @@ public: int count_materialization_scale; /* Unique id of the node. */ int uid; + /* Summary unique id of the node. */ + int summary_uid; /* ID assigned by the profiling. */ unsigned int profile_id; /* Time profiler: first run of function. */ @@ -1786,6 +1788,10 @@ public: friend class cgraph_node; friend class cgraph_edge; + symbol_table (): cgraph_max_summary_uid (1) + { + } + /* Initialize callgraph dump file. */ void initialize (void); @@ -1982,6 +1988,7 @@ public: int cgraph_count; int cgraph_max_uid; + int cgraph_max_summary_uid; int edges_count; int edges_max_uid; @@ -2310,6 +2317,7 @@ symbol_table::allocate_cgraph_symbol (void) node->uid = cgraph_max_uid++; } + node->summary_uid = cgraph_max_summary_uid++; return node; } diff --git a/gcc/cgraph_summary.c b/gcc/cgraph_summary.c new file mode 100644 index 0000000..9af1d7e --- /dev/null +++ b/gcc/cgraph_summary.c @@ -0,0 +1,34 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "predict.h" +#include "vec.h" +#include "hashtab.h" +#include "hash-set.h" +#include "machmode.h" +#include "hard-reg-set.h" +#include "input.h" +#include "function.h" +#include "dominance.h" +#include "cfg.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" +#include "gimple.h" +#include "tree-inline.h" +#include "dumpfile.h" +#include "langhooks.h" +#include "splay-tree.h" +#include "hash-map.h" +#include "plugin-api.h" +#include "ipa-ref.h" +#include "cgraph.h" +#include "ipa-utils.h" +#include "alloc-pool.h" +#include "cgraph_summary.h" +#include "ipa-prop.h" +#include "hash-map.h" diff --git a/gcc/cgraph_summary.h b/gcc/cgraph_summary.h new file mode 100644 index 0000000..dd2b649 --- /dev/null +++ b/gcc/cgraph_summary.h @@ -0,0 +1,301 @@ +/* Callgraph summary data structure. + Copyright (C) 2014 Free Software Foundation, Inc. + Contributed by Martin Liska + +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/>. */ + +#ifndef GCC_CGRAPH_SUMMARY_H +#define GCC_CGRAPH_SUMMARY_H + +#define CGRAPH_SUMMARY_DELETED_VALUE -1 +#define CGRAPH_SUMMARY_EMPTY_VALUE 0 + +template <class T> +class cgraph_summary +{ + private: + cgraph_summary(); +}; + +template <class T> +class GTY((user)) cgraph_summary <T *> +{ +public: + /* Default construction takes SYMTAB as an argument. */ + cgraph_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc), + m_insertion_enabled (true), m_symtab (symtab) + { + cgraph_node *node; + + FOR_EACH_FUNCTION (node) + { + gcc_assert (node->summary_uid > 0); + } + + m_map = new hash_map<int, T*, summary_hashmap_traits>(13, m_ggc); + + m_symtab_insertion_hook = + symtab->add_cgraph_insertion_hook + (cgraph_summary::symtab_insertion, this); + + m_symtab_removal_hook = + symtab->add_cgraph_removal_hook + (cgraph_summary::symtab_removal, this); + m_symtab_duplication_hook = + symtab->add_cgraph_duplication_hook + (cgraph_summary::symtab_duplication, this); + } + + /* Destructor. */ + virtual ~cgraph_summary () + { + destroy (); + } + + /* Destruction method that can be called for GGT purpose. */ + void destroy () + { + if (m_symtab_insertion_hook) + m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook); + + if (m_symtab_removal_hook) + m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook); + + if (m_symtab_duplication_hook) + m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook); + + m_symtab_insertion_hook = NULL; + m_symtab_removal_hook = NULL; + m_symtab_duplication_hook = NULL; + + if (!m_ggc) + m_map->traverse <void *, cgraph_summary::release> (NULL); + } + + /* Traverses all summarys with a function F called with + ARG as argument. */ + template<typename Arg, bool (*f)(const T &, Arg)> + void traverse (Arg a) const + { + m_map->traverse <f> (a); + } + + /* Basic implementation of insertion hook. */ + virtual void insertion_hook (cgraph_node *, T *) {} + + /* Basic implementation of removal hook. */ + virtual void removal_hook (cgraph_node *, T *) {} + + /* Basic implementation of duplication hook. */ + virtual void duplication_hook (cgraph_node *, + cgraph_node *, T *, T *) {} + + /* Allocates new data that are stored within map. */ + inline T* allocate_new () + { + return m_ggc ? new (ggc_alloc <T> ()) T() : new T () ; + } + + /* Getter for summary callgraph ID. */ + inline T* operator[] (int uid) + { + T **v = m_map->get (uid); + if (!v) + { + T *new_value = allocate_new (); + m_map->put (uid, new_value); + + v = &new_value; + } + + return *v; + } + + /* Getter for summary callgraph node pointer. */ + inline T * operator[] (cgraph_node *node) + { + return operator[] (node->summary_uid); + } + + /* Return number of elements handled by data structure. */ + size_t elements () + { + return m_map->elements (); + } + + /* Enable insertin hook invocation. */ + inline void enable_insertion_hook () + { + m_insertion_enabled = true; + } + + /* Enable insertin hook invocation. */ + inline void disable_insertion_hook () + { + m_insertion_enabled = false; + } + + /* Symbol insertion hook that is registered to symbol table. */ + static void symtab_insertion (cgraph_node *node, void *data) + { + cgraph_summary *summary = (cgraph_summary <T *> *) (data); + + if (summary->m_insertion_enabled) + summary->insertion_hook (node, (*summary)[node]); + } + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_node *node, void *data) + { + gcc_assert (node->summary_uid); + cgraph_summary *summary = (cgraph_summary <T *> *) (data); + + int summary_uid = node->summary_uid; + T **v = summary->m_map->get (summary_uid); + + if (v) + { + summary->removal_hook (node, *v); + + if (!summary->m_ggc) + delete (*v); + } + + if (summary->m_map->get (summary_uid)) + summary->m_map->remove (summary_uid); + } + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_node *node, cgraph_node *node2, + void *data) + { + cgraph_summary *summary = (cgraph_summary <T *> *) (data); + T **v = summary->m_map->get (node->summary_uid); + + gcc_assert (node2->summary_uid > 0); + + if (v) + { + T *data = *v; + T *duplicate = summary->allocate_new (); + summary->m_map->put (node2->summary_uid, duplicate); + summary->duplication_hook (node, node2, data, (*summary)[node2]); + } + } + +protected: + /* Indicatation if we use ggc summary. */ + bool m_ggc; + +private: + struct summary_hashmap_traits: default_hashmap_traits + { + static inline + hashval_t hash (const int v) + { + return (hashval_t)v; + } + + template<typename Type> + static inline + bool is_deleted (Type &e) + { + return e.m_key == CGRAPH_SUMMARY_DELETED_VALUE; + } + + template<typename Type> + static inline + bool is_empty (Type &e) + { + return e.m_key == CGRAPH_SUMMARY_EMPTY_VALUE; + } + + template<typename Type> + static inline + void mark_deleted (Type &e) + { + e.m_key = CGRAPH_SUMMARY_DELETED_VALUE; + } + + template<typename Type> + static inline + void mark_empty (Type &e) + { + e.m_key = CGRAPH_SUMMARY_EMPTY_VALUE; + } + }; + + /* Remove summary for summary UID. */ + inline void remove (int uid) + { + T *v = m_map->get (uid); + + if (v) + m_map->erase (uid); + } + + /* Summary class release function called by traverse method. */ + static bool release (int const &, T * const &v, void *) + { + delete (v); + return true; + } + + /* Main summary store, where summary ID is used as key. */ + hash_map <int, T *, summary_hashmap_traits> *m_map; + /* Internal summary insertion hook pointer. */ + cgraph_node_hook_list *m_symtab_insertion_hook; + /* Internal summary removal hook pointer. */ + cgraph_node_hook_list *m_symtab_removal_hook; + /* Internal summary duplication hook pointer. */ + cgraph_2node_hook_list *m_symtab_duplication_hook; + /* Indicates if insertion hook is enabled. */ + bool m_insertion_enabled; + /* Symbol table the summary is registered to. */ + symbol_table *m_symtab; + + template <typename U> friend void gt_ggc_mx (cgraph_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (cgraph_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (cgraph_summary <U *> * const &, + gt_pointer_operator, void *); +}; + +template <typename T> +void +gt_ggc_mx(cgraph_summary<T *>* const &summary) +{ + if (summary->m_ggc) + gt_ggc_mx (summary->m_map); +} + +template <typename T> +void +gt_pch_nx(cgraph_summary<T *>* const &summary) +{ + if (summary->m_ggc) + gt_pch_nx (summary->m_map); +} + +template <typename T> +void +gt_pch_nx(cgraph_summary<T *>* const& summary, gt_pointer_operator op, void *cookie) +{ + if (summary->m_map) + gt_pch_nx (summary->m_map, op, cookie); +} + +#endif /* GCC_CGRAPH_SUMMARY_H */ diff --git a/gcc/gengtype.c b/gcc/gengtype.c index fac83ee..91c5c91 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1842,8 +1842,8 @@ open_base_files (void) "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h", "except.h", "output.h", "cfgloop.h", "target.h", "lto-streamer.h", - "target-globals.h", "ipa-ref.h", "cgraph.h", "ipa-prop.h", - "ipa-inline.h", "dwarf2out.h", NULL + "target-globals.h", "ipa-ref.h", "cgraph.h", "cgraph_summary.h", + "ipa-prop.h", "ipa-inline.h", "dwarf2out.h", NULL }; const char *const *ifp; outf_p gtype_desc_c; diff --git a/gcc/toplev.c b/gcc/toplev.c index aa1653e..e6c5159 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -93,6 +93,7 @@ along with GCC; see the file COPYING3. If not see #include "dwarf2out.h" #include "bitmap.h" #include "ipa-reference.h" +#include "cgraph_summary.h" #include "ipa-prop.h" #include "gcse.h" #include "insn-codes.h" @@ -1209,7 +1210,7 @@ general_init (const char *argv0) /* Create the singleton holder for global state. Doing so also creates the pass manager and with it the passes. */ g = new gcc::context (); - symtab = ggc_cleared_alloc <symbol_table> (); + symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table (); statistics_early_init (); finish_params (); -- 2.1.2