Line data Source code
1 : /* Classes for purging state at function_points.
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_ANALYZER_STATE_PURGE_H
22 : #define GCC_ANALYZER_STATE_PURGE_H
23 :
24 : namespace ana {
25 :
26 : /* The result of analyzing which decls and SSA names can be purged from state at
27 : different points in the program, so that we can simplify program_state
28 : objects, in the hope of reducing state-blowup. */
29 :
30 : class state_purge_map : public log_user
31 : {
32 : public:
33 : typedef ordered_hash_map<tree, state_purge_per_ssa_name *> ssa_map_t;
34 : typedef ssa_map_t::iterator ssa_iterator;
35 :
36 : typedef ordered_hash_map<tree, state_purge_per_decl *> decl_map_t;
37 : typedef decl_map_t::iterator decl_iterator;
38 :
39 : state_purge_map (const supergraph &sg,
40 : region_model_manager *mgr,
41 : logger *logger);
42 : ~state_purge_map ();
43 :
44 1456987 : const state_purge_per_ssa_name &get_data_for_ssa_name (tree name) const
45 : {
46 1456987 : gcc_assert (TREE_CODE (name) == SSA_NAME);
47 1456987 : if (tree var = SSA_NAME_VAR (name))
48 1133713 : if (TREE_CODE (var) == VAR_DECL)
49 1040139 : gcc_assert (!VAR_DECL_IS_VIRTUAL_OPERAND (var));
50 :
51 1456987 : state_purge_per_ssa_name **slot
52 1456987 : = const_cast <ssa_map_t&> (m_ssa_map).get (name);
53 1456987 : return **slot;
54 : }
55 :
56 284408 : const state_purge_per_decl *get_any_data_for_decl (tree decl) const
57 : {
58 284408 : gcc_assert (TREE_CODE (decl) == VAR_DECL
59 : || TREE_CODE (decl) == PARM_DECL
60 : || TREE_CODE (decl) == RESULT_DECL);
61 568816 : if (state_purge_per_decl **slot
62 284408 : = const_cast <decl_map_t&> (m_decl_map).get (decl))
63 262901 : return *slot;
64 : else
65 : return nullptr;
66 : }
67 :
68 : state_purge_per_decl &
69 : get_or_create_data_for_decl (const function &fun, tree decl);
70 :
71 93504 : const supergraph &get_sg () const { return m_sg; }
72 :
73 191 : ssa_iterator begin_ssas () const { return m_ssa_map.begin (); }
74 9764 : ssa_iterator end_ssas () const { return m_ssa_map.end (); }
75 :
76 3560 : decl_iterator begin_decls () const { return m_decl_map.begin (); }
77 10930 : decl_iterator end_decls () const { return m_decl_map.end (); }
78 :
79 : void
80 : on_duplicated_node (const supernode &old_snode,
81 : const supernode &new_snode);
82 :
83 : private:
84 : DISABLE_COPY_AND_ASSIGN (state_purge_map);
85 :
86 : const supergraph &m_sg;
87 : ssa_map_t m_ssa_map;
88 : decl_map_t m_decl_map;
89 : };
90 :
91 : /* Base class for state_purge_per_ssa_name and state_purge_per_decl. */
92 :
93 : class state_purge_per_tree
94 : {
95 : public:
96 415841 : const function &get_function () const { return m_fun; }
97 2 : tree get_fndecl () const { return m_fun.decl; }
98 :
99 : protected:
100 : typedef hash_set<const supernode *> point_set_t;
101 :
102 74679 : state_purge_per_tree (const function &fun)
103 74679 : : m_fun (fun)
104 : {
105 : }
106 :
107 : private:
108 : const function &m_fun;
109 : };
110 :
111 : /* The part of a state_purge_map relating to a specific SSA name.
112 :
113 : The result of analyzing a given SSA name, recording which
114 : function_points need to retain state information about it to handle
115 : their successor states, so that we can simplify program_state objects,
116 : in the hope of reducing state-blowup. */
117 :
118 71542 : class state_purge_per_ssa_name : public state_purge_per_tree
119 : {
120 : public:
121 : state_purge_per_ssa_name (const state_purge_map &map,
122 : tree name,
123 : const function &fun);
124 :
125 : bool needed_at_supernode_p (const supernode *snode) const;
126 :
127 : void
128 : on_duplicated_node (const supernode &old_snode,
129 : const supernode &new_snode);
130 :
131 : private:
132 : void add_to_worklist (const supernode &node,
133 : auto_vec<const supernode *> *worklist,
134 : logger *logger);
135 :
136 : void process_supernode (const supernode &node,
137 : auto_vec<const supernode *> *worklist,
138 : const state_purge_map &map);
139 :
140 : point_set_t m_snodes_needing_name;
141 : tree m_name;
142 : };
143 :
144 : /* The part of a state_purge_map relating to a specific decl.
145 :
146 : Analogous to state_purge_per_ssa_name, but for local decls.
147 :
148 : This is more involved than the SSA name case, because we also need
149 : to handle pointers and components. */
150 :
151 3137 : class state_purge_per_decl : public state_purge_per_tree
152 : {
153 : public:
154 : state_purge_per_decl (const state_purge_map &map,
155 : tree decl,
156 : const function &fun);
157 :
158 : bool needed_at_supernode_p (const supernode *snode) const;
159 :
160 : void add_needed_at (const supernode &snode);
161 : void add_pointed_to_at (const supernode &snode);
162 : void process_worklists (const state_purge_map &map,
163 : region_model_manager *mgr);
164 :
165 : void
166 : on_duplicated_node (const supernode &old_snode,
167 : const supernode &new_snode);
168 :
169 : private:
170 : static const supernode * before_use_stmt (const state_purge_map &map,
171 : const gimple *use_stmt);
172 :
173 : void add_to_worklist (const supernode &node,
174 : auto_vec<const supernode *> *worklist,
175 : point_set_t *seen,
176 : logger *logger);
177 :
178 : void process_supernode_backwards (const supernode &snode,
179 : auto_vec<const supernode *> *worklist,
180 : point_set_t *seen,
181 : const state_purge_map &map,
182 : const region_model &model);
183 : void process_supernode_forwards (const supernode &snode,
184 : auto_vec<const supernode *> *worklist,
185 : point_set_t *seen,
186 : const state_purge_map &map);
187 :
188 : point_set_t m_snodes_needing_decl;
189 : point_set_t m_snodes_taking_address;
190 : tree m_decl;
191 : };
192 :
193 : /* Subclass of dot_annotator for use by -fdump-analyzer-state-purge.
194 : Annotate the .dot output with state-purge information. */
195 :
196 4 : class state_purge_annotator : public dot_annotator
197 : {
198 : public:
199 4 : state_purge_annotator (const state_purge_map *map) : m_map (map) {}
200 :
201 : void
202 : add_node_annotations (graphviz_out *gv,
203 : const supernode &n) const final override;
204 :
205 : private:
206 : const state_purge_map *m_map;
207 : };
208 :
209 : } // namespace ana
210 :
211 : #endif /* GCC_ANALYZER_STATE_PURGE_H */
|