You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
10KB

  1. /* Interprocedural semantic function equality pass
  2. Copyright (C) 2014-2020 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 infrastructure
  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 instance of func_checker and call
  21. a comparison 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. /* Logs a MESSAGE to dump_file if exists and returns false. FUNC is name
  30. of function and LINE is location in the source file. */
  31. static inline bool
  32. return_false_with_message_1 (const char *message, const char *filename,
  33. const char *func, unsigned int line)
  34. {
  35. if (dump_file && (dump_flags & TDF_DETAILS))
  36. fprintf (dump_file, " false returned: '%s' in %s at %s:%u\n", message, func,
  37. filename, line);
  38. return false;
  39. }
  40. /* Logs a MESSAGE to dump_file if exists and returns false. */
  41. #define return_false_with_msg(message) \
  42. return_false_with_message_1 (message, __FILE__, __func__, __LINE__)
  43. /* Return false and log that false value is returned. */
  44. #define return_false() return_false_with_msg ("")
  45. /* Logs return value if RESULT is false. FUNC is name of function and LINE
  46. is location in the source file. */
  47. static inline bool
  48. return_with_result (bool result, const char *filename,
  49. const char *func, unsigned int line)
  50. {
  51. if (!result && dump_file && (dump_flags & TDF_DETAILS))
  52. fprintf (dump_file, " false returned: '' in %s at %s:%u\n", func,
  53. filename, line);
  54. return result;
  55. }
  56. /* Logs return value if RESULT is false. */
  57. #define return_with_debug(result) return_with_result \
  58. (result, __FILE__, __func__, __LINE__)
  59. /* Verbose logging function logging statements S1 and S2 of a CODE.
  60. FUNC is name of function and LINE is location in the source file. */
  61. static inline bool
  62. return_different_stmts_1 (gimple *s1, gimple *s2, const char *code,
  63. const char *func, unsigned int line)
  64. {
  65. if (dump_file && (dump_flags & TDF_DETAILS))
  66. {
  67. fprintf (dump_file, " different statement for code: %s (%s:%u):\n",
  68. code, func, line);
  69. print_gimple_stmt (dump_file, s1, 3, TDF_DETAILS);
  70. print_gimple_stmt (dump_file, s2, 3, TDF_DETAILS);
  71. }
  72. return false;
  73. }
  74. /* Verbose logging function logging statements S1 and S2 of a CODE. */
  75. #define return_different_stmts(s1, s2, code) \
  76. return_different_stmts_1 (s1, s2, code, __func__, __LINE__)
  77. namespace ipa_icf_gimple {
  78. /* Basic block struct for semantic equality pass. */
  79. class sem_bb
  80. {
  81. public:
  82. sem_bb (basic_block bb_, unsigned nondbg_stmt_count_, unsigned edge_count_):
  83. bb (bb_), nondbg_stmt_count (nondbg_stmt_count_), edge_count (edge_count_) {}
  84. /* Basic block the structure belongs to. */
  85. basic_block bb;
  86. /* Number of non-debug statements in the basic block. */
  87. unsigned nondbg_stmt_count;
  88. /* Number of edges connected to the block. */
  89. unsigned edge_count;
  90. };
  91. /* A class aggregating all connections and semantic equivalents
  92. for a given pair of semantic function candidates. */
  93. class func_checker : operand_compare
  94. {
  95. public:
  96. /* Default constructor. */
  97. func_checker ():
  98. m_source_func_decl (NULL_TREE), m_target_func_decl (NULL_TREE),
  99. m_ignored_source_nodes (NULL), m_ignored_target_nodes (NULL),
  100. m_ignore_labels (false)
  101. {
  102. m_source_ssa_names.create (0);
  103. m_target_ssa_names.create (0);
  104. }
  105. /* Initialize internal structures for a given SOURCE_FUNC_DECL and
  106. TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
  107. an option COMPARE_POLYMORPHIC is true. For special cases, one can
  108. set IGNORE_LABELS to skip label comparison.
  109. Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
  110. of declarations that can be skipped. */
  111. func_checker (tree source_func_decl, tree target_func_decl,
  112. bool ignore_labels = false,
  113. hash_set<symtab_node *> *ignored_source_nodes = NULL,
  114. hash_set<symtab_node *> *ignored_target_nodes = NULL);
  115. /* Memory release routine. */
  116. virtual ~func_checker ();
  117. /* Function visits all gimple labels and creates corresponding
  118. mapping between basic blocks and labels. */
  119. void parse_labels (sem_bb *bb);
  120. /* Basic block equivalence comparison function that returns true if
  121. basic blocks BB1 and BB2 correspond. */
  122. bool compare_bb (sem_bb *bb1, sem_bb *bb2);
  123. /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
  124. bool compare_ssa_name (const_tree t1, const_tree t2);
  125. /* Verification function for edges E1 and E2. */
  126. bool compare_edge (edge e1, edge e2);
  127. /* Verifies for given GIMPLEs S1 and S2 that
  128. call statements are semantically equivalent. */
  129. bool compare_gimple_call (gcall *s1, gcall *s2);
  130. /* Verifies for given GIMPLEs S1 and S2 that
  131. assignment statements are semantically equivalent. */
  132. bool compare_gimple_assign (gimple *s1, gimple *s2);
  133. /* Verifies for given GIMPLEs S1 and S2 that
  134. condition statements are semantically equivalent. */
  135. bool compare_gimple_cond (gimple *s1, gimple *s2);
  136. /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
  137. label statements are semantically equivalent. */
  138. bool compare_gimple_label (const glabel *s1, const glabel *s2);
  139. /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
  140. switch statements are semantically equivalent. */
  141. bool compare_gimple_switch (const gswitch *s1, const gswitch *s2);
  142. /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
  143. return statements are semantically equivalent. */
  144. bool compare_gimple_return (const greturn *s1, const greturn *s2);
  145. /* Verifies for given GIMPLEs S1 and S2 that
  146. goto statements are semantically equivalent. */
  147. bool compare_gimple_goto (gimple *s1, gimple *s2);
  148. /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
  149. resx statements are semantically equivalent. */
  150. bool compare_gimple_resx (const gresx *s1, const gresx *s2);
  151. /* Verifies for given GIMPLE_ASM stmts S1 and S2 that ASM statements
  152. are equivalent.
  153. For the beginning, the pass only supports equality for
  154. '__asm__ __volatile__ ("", "", "", "memory")'. */
  155. bool compare_gimple_asm (const gasm *s1, const gasm *s2);
  156. /* Verification function for declaration trees T1 and T2. */
  157. bool compare_decl (const_tree t1, const_tree t2);
  158. /* Function responsible for comparison of various operands T1 and T2.
  159. If these components, from functions FUNC1 and FUNC2, are equal, true
  160. is returned. */
  161. bool compare_operand (tree t1, tree t2);
  162. /* Compares GIMPLE ASM inputs (or outputs) where we iterate tree chain
  163. and compare both TREE_PURPOSEs and TREE_VALUEs. */
  164. bool compare_asm_inputs_outputs (tree t1, tree t2);
  165. /* Verifies that trees T1 and T2, representing function declarations
  166. are equivalent from perspective of ICF. */
  167. bool compare_function_decl (tree t1, tree t2);
  168. /* Verifies that trees T1 and T2 do correspond. */
  169. bool compare_variable_decl (const_tree t1, const_tree t2);
  170. /* Compare loop information for basic blocks BB1 and BB2. */
  171. bool compare_loops (basic_block bb1, basic_block bb2);
  172. /* Return true if types are compatible for polymorphic call analysis.
  173. COMPARE_PTR indicates if polymorphic type comparison should be
  174. done for pointers, too. */
  175. static bool compatible_polymorphic_types_p (tree t1, tree t2,
  176. bool compare_ptr);
  177. /* Return true if types are compatible from perspective of ICF.
  178. FIRST_ARGUMENT indicates if the comparison is called for
  179. first parameter of a function. */
  180. static bool compatible_types_p (tree t1, tree t2);
  181. private:
  182. /* Vector mapping source SSA names to target ones. */
  183. vec <int> m_source_ssa_names;
  184. /* Vector mapping target SSA names to source ones. */
  185. vec <int> m_target_ssa_names;
  186. /* Source TREE function declaration. */
  187. tree m_source_func_decl;
  188. /* Target TREE function declaration. */
  189. tree m_target_func_decl;
  190. /* Source symbol nodes that should be skipped by
  191. declaration comparison. */
  192. hash_set<symtab_node *> *m_ignored_source_nodes;
  193. /* Target symbol nodes that should be skipped by
  194. declaration comparison. */
  195. hash_set<symtab_node *> *m_ignored_target_nodes;
  196. /* Source to target edge map. */
  197. hash_map <edge, edge> m_edge_map;
  198. /* Source to target declaration map. */
  199. hash_map <const_tree, const_tree> m_decl_map;
  200. /* Label to basic block index mapping. */
  201. hash_map <const_tree, int> m_label_bb_map;
  202. /* Flag if ignore labels in comparison. */
  203. bool m_ignore_labels;
  204. public:
  205. /* Return true if two operands are equal. The flags fields can be used
  206. to specify OEP flags described above. */
  207. virtual bool operand_equal_p (const_tree, const_tree, unsigned int flags);
  208. /* Generate a hash value for an expression. This can be used iteratively
  209. by passing a previous result as the HSTATE argument. */
  210. virtual void hash_operand (const_tree, inchash::hash &, unsigned flags);
  211. };
  212. } // ipa_icf_gimple namespace