ipa-icf-gimple.h 10.0 KB

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