]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ipa-icf-gimple.h
generalized IPA predicate on parameter
[thirdparty/gcc.git] / gcc / ipa-icf-gimple.h
1 /* Interprocedural semantic function equality pass
2 Copyright (C) 2014-2019 Free Software Foundation, Inc.
3
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
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 /* Gimple identical code folding (class func_checker) is an infastructure
23 capable of comparing two given functions. The class compares every
24 gimple statement and uses many dictionaries to map source and target
25 SSA_NAMEs, declarations and other components.
26
27 To use the infrastructure, create an instanse of func_checker and call
28 a comparsion function based on type of gimple statement. */
29
30 /* Prints string STRING to a FILE with a given number of SPACE_COUNT. */
31 #define FPUTS_SPACES(file, space_count, string) \
32 fprintf (file, "%*s" string, space_count, " ");
33
34 /* fprintf function wrapper that transforms given FORMAT to follow given
35 number for SPACE_COUNT and call fprintf for a FILE. */
36 #define FPRINTF_SPACES(file, space_count, format, ...) \
37 fprintf (file, "%*s" format, space_count, " ", ##__VA_ARGS__);
38
39 /* Logs a MESSAGE to dump_file if exists and returns false. FUNC is name
40 of function and LINE is location in the source file. */
41
42 static inline bool
43 return_false_with_message_1 (const char *message, const char *filename,
44 const char *func, unsigned int line)
45 {
46 if (dump_file && (dump_flags & TDF_DETAILS))
47 fprintf (dump_file, " false returned: '%s' in %s at %s:%u\n", message, func,
48 filename, line);
49 return false;
50 }
51
52 /* Logs a MESSAGE to dump_file if exists and returns false. */
53 #define return_false_with_msg(message) \
54 return_false_with_message_1 (message, __FILE__, __func__, __LINE__)
55
56 /* Return false and log that false value is returned. */
57 #define return_false() return_false_with_msg ("")
58
59 /* Logs return value if RESULT is false. FUNC is name of function and LINE
60 is location in the source file. */
61
62 static inline bool
63 return_with_result (bool result, const char *filename,
64 const char *func, unsigned int line)
65 {
66 if (!result && dump_file && (dump_flags & TDF_DETAILS))
67 fprintf (dump_file, " false returned: '' in %s at %s:%u\n", func,
68 filename, line);
69
70 return result;
71 }
72
73 /* Logs return value if RESULT is false. */
74 #define return_with_debug(result) return_with_result \
75 (result, __FILE__, __func__, __LINE__)
76
77 /* Verbose logging function logging statements S1 and S2 of a CODE.
78 FUNC is name of function and LINE is location in the source file. */
79
80 static inline bool
81 return_different_stmts_1 (gimple *s1, gimple *s2, const char *code,
82 const char *func, unsigned int line)
83 {
84 if (dump_file && (dump_flags & TDF_DETAILS))
85 {
86 fprintf (dump_file, " different statement for code: %s (%s:%u):\n",
87 code, func, line);
88
89 print_gimple_stmt (dump_file, s1, 3, TDF_DETAILS);
90 print_gimple_stmt (dump_file, s2, 3, TDF_DETAILS);
91 }
92
93 return false;
94 }
95
96 /* Verbose logging function logging statements S1 and S2 of a CODE. */
97 #define return_different_stmts(s1, s2, code) \
98 return_different_stmts_1 (s1, s2, code, __func__, __LINE__)
99
100 namespace ipa_icf_gimple {
101
102 /* Basic block struct for semantic equality pass. */
103 class sem_bb
104 {
105 public:
106 sem_bb (basic_block bb_, unsigned nondbg_stmt_count_, unsigned edge_count_):
107 bb (bb_), nondbg_stmt_count (nondbg_stmt_count_), edge_count (edge_count_) {}
108
109 /* Basic block the structure belongs to. */
110 basic_block bb;
111
112 /* Number of non-debug statements in the basic block. */
113 unsigned nondbg_stmt_count;
114
115 /* Number of edges connected to the block. */
116 unsigned edge_count;
117 };
118
119 /* A class aggregating all connections and semantic equivalents
120 for a given pair of semantic function candidates. */
121 class func_checker
122 {
123 public:
124 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
125 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
126 an option COMPARE_POLYMORPHIC is true. For special cases, one can
127 set IGNORE_LABELS to skip label comparison.
128 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
129 of declarations that can be skipped. */
130 func_checker (tree source_func_decl, tree target_func_decl,
131 bool compare_polymorphic,
132 bool ignore_labels = false,
133 hash_set<symtab_node *> *ignored_source_nodes = NULL,
134 hash_set<symtab_node *> *ignored_target_nodes = NULL);
135
136 /* Memory release routine. */
137 ~func_checker();
138
139 /* Function visits all gimple labels and creates corresponding
140 mapping between basic blocks and labels. */
141 void parse_labels (sem_bb *bb);
142
143 /* Basic block equivalence comparison function that returns true if
144 basic blocks BB1 and BB2 correspond. */
145 bool compare_bb (sem_bb *bb1, sem_bb *bb2);
146
147 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
148 bool compare_ssa_name (tree t1, tree t2);
149
150 /* Verification function for edges E1 and E2. */
151 bool compare_edge (edge e1, edge e2);
152
153 /* Verifies for given GIMPLEs S1 and S2 that
154 call statements are semantically equivalent. */
155 bool compare_gimple_call (gcall *s1, gcall *s2);
156
157 /* Verifies for given GIMPLEs S1 and S2 that
158 assignment statements are semantically equivalent. */
159 bool compare_gimple_assign (gimple *s1, gimple *s2);
160
161 /* Verifies for given GIMPLEs S1 and S2 that
162 condition statements are semantically equivalent. */
163 bool compare_gimple_cond (gimple *s1, gimple *s2);
164
165 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
166 label statements are semantically equivalent. */
167 bool compare_gimple_label (const glabel *s1, const glabel *s2);
168
169 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
170 switch statements are semantically equivalent. */
171 bool compare_gimple_switch (const gswitch *s1, const gswitch *s2);
172
173 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
174 return statements are semantically equivalent. */
175 bool compare_gimple_return (const greturn *s1, const greturn *s2);
176
177 /* Verifies for given GIMPLEs S1 and S2 that
178 goto statements are semantically equivalent. */
179 bool compare_gimple_goto (gimple *s1, gimple *s2);
180
181 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
182 resx statements are semantically equivalent. */
183 bool compare_gimple_resx (const gresx *s1, const gresx *s2);
184
185 /* Verifies for given GIMPLE_ASM stmts S1 and S2 that ASM statements
186 are equivalent.
187 For the beginning, the pass only supports equality for
188 '__asm__ __volatile__ ("", "", "", "memory")'. */
189 bool compare_gimple_asm (const gasm *s1, const gasm *s2);
190
191 /* Verification function for declaration trees T1 and T2. */
192 bool compare_decl (tree t1, tree t2);
193
194 /* Verifies that tree labels T1 and T2 correspond. */
195 bool compare_tree_ssa_label (tree t1, tree t2);
196
197 /* Function compare for equality given memory operands T1 and T2. */
198 bool compare_memory_operand (tree t1, tree t2);
199
200 /* Function compare for equality given trees T1 and T2 which
201 can be either a constant or a declaration type. */
202 bool compare_cst_or_decl (tree t1, tree t2);
203
204 /* Function responsible for comparison of various operands T1 and T2.
205 If these components, from functions FUNC1 and FUNC2, are equal, true
206 is returned. */
207 bool compare_operand (tree t1, tree t2);
208
209 /* Compares GIMPLE ASM inputs (or outputs) where we iterate tree chain
210 and compare both TREE_PURPOSEs and TREE_VALUEs. */
211 bool compare_asm_inputs_outputs (tree t1, tree t2);
212
213 /* Verifies that trees T1 and T2, representing function declarations
214 are equivalent from perspective of ICF. */
215 bool compare_function_decl (tree t1, tree t2);
216
217 /* Verifies that trees T1 and T2 do correspond. */
218 bool compare_variable_decl (tree t1, tree t2);
219
220 /* Compare loop information for basic blocks BB1 and BB2. */
221 bool compare_loops (basic_block bb1, basic_block bb2);
222
223 /* Return true if types are compatible for polymorphic call analysis.
224 COMPARE_PTR indicates if polymorphic type comparsion should be
225 done for pointers, too. */
226 static bool compatible_polymorphic_types_p (tree t1, tree t2,
227 bool compare_ptr);
228
229 /* Return true if types are compatible from perspective of ICF.
230 FIRST_ARGUMENT indicates if the comparison is called for
231 first parameter of a function. */
232 static bool compatible_types_p (tree t1, tree t2);
233
234
235 private:
236 /* Vector mapping source SSA names to target ones. */
237 vec <int> m_source_ssa_names;
238
239 /* Vector mapping target SSA names to source ones. */
240 vec <int> m_target_ssa_names;
241
242 /* Source TREE function declaration. */
243 tree m_source_func_decl;
244
245 /* Target TREE function declaration. */
246 tree m_target_func_decl;
247
248 /* Source symbol nodes that should be skipped by
249 declaration comparison. */
250 hash_set<symtab_node *> *m_ignored_source_nodes;
251
252 /* Target symbol nodes that should be skipped by
253 declaration comparison. */
254 hash_set<symtab_node *> *m_ignored_target_nodes;
255
256 /* Source to target edge map. */
257 hash_map <edge, edge> m_edge_map;
258
259 /* Source to target declaration map. */
260 hash_map <tree, tree> m_decl_map;
261
262 /* Label to basic block index mapping. */
263 hash_map <tree, int> m_label_bb_map;
264
265 /* Flag if polymorphic comparison should be executed. */
266 bool m_compare_polymorphic;
267
268 /* Flag if ignore labels in comparison. */
269 bool m_ignore_labels;
270 };
271
272 } // ipa_icf_gimple namespace