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