ipa-param-manipulation.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /* Manipulation of formal and actual parameters of functions and function
  2. calls.
  3. Copyright (C) 2017-2020 Free Software Foundation, Inc.
  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. This file defines classes and other data structures that are used to manipulate
  17. the prototype of a function, especially to create, remove or split its formal
  18. parameters, but also to remove its return value, and also its call statements
  19. correspondingly.
  20. The most basic one is a vector of structures ipa_adjusted_param. It is simply
  21. a description how the new parameters should look like after the transformation
  22. in what way they relate to the previous ones (if in any). Such relation to an
  23. old parameter can be an outright copy or an IPA-SRA replacement. If an old
  24. parameter is not listed or otherwise mentioned, it is removed as unused or at
  25. least unnecessary. Note that this most basic structure does not work for
  26. modifying calls of functions with variable number of arguments.
  27. Class ipa_param_adjustments is only a little more than a thin encapsulation of
  28. a vector of ipa_param_adjustments. Along with this vector it contains an index
  29. of the first potential vararg argument and a boolean flag whether the return
  30. value should be removed or not. Moreover, the class contains method
  31. modify_call which can transform a call statement so that it correctly calls a
  32. modified function. These two data structures were designed to have a small
  33. memory footprint because they are allocated for each clone of a call graph node
  34. that has its prototype changed and live until the end of IPA clone
  35. materialization and call redirection phase.
  36. On the other hand, class ipa_param_body_adjustments can afford to allocate more
  37. data because its life span is much smaller, it is allocated and destroyed in
  38. the course of materialization of each single clone that needs it or only when a
  39. particular pass needs to change a function it is operating on. This class has
  40. various methods required to change function declaration and the body of the
  41. function according to instructions given either by class ipa_param_adjustments
  42. or only a vector of ipa_adjusted_params.
  43. When these classes are used in the context of call graph clone materialization
  44. and subsequent call statement redirection - which is the point at which we
  45. modify arguments in call statements - they need to cooperate with each other in
  46. order to handle what we refer to as transitive (IPA-SRA) splits. These are
  47. situations when a formal parameter of one function is split into several
  48. smaller ones and some of them are then passed on in a call to another function
  49. because the formal parameter of this callee has also been split.
  50. Consider a simple example:
  51. struct S {int a, b, c;};
  52. struct Z {int x; S s;};
  53. foo (S s)
  54. {
  55. use (s.b);
  56. }
  57. bar (Z z)
  58. {
  59. use (z.s.a);
  60. foo (z.s);
  61. }
  62. baz ()
  63. {
  64. bar (*global);
  65. }
  66. Both bar and foo would have their parameter split. Foo would receive one
  67. replacement representing s.b. Function bar would see its parameter split into
  68. one replacement representing z.s.a and another representing z.s.b which would
  69. be passed on to foo. It would be a so called transitive split IPA-SRA
  70. replacement, one which is passed in a call as an actual argument to another
  71. IPA-SRA replacement in another function.
  72. Note that the call chain the example can be arbitrarily long and recursive and
  73. that any function in it can be cloned by another IPA pass and any number of
  74. adjacent functions in the call chain can be inlined into each other. Call
  75. redirection takes place only after bodies of the function have been modified by
  76. all of the above.
  77. Call redirection has to be able to find the right decl or SSA_NAME that
  78. corresponds to the transitive split in the caller. The SSA names are assigned
  79. right after clone materialization/ modification and cannot be "added"
  80. afterwards. Moreover, if the caller has been inlined the SSA_NAMEs in question
  81. no longer belong to PARM_DECLs but to VAR_DECLs, indistinguishable from any
  82. others.
  83. Therefore, when clone materialization finds a call statement which it knows is
  84. a part of a transitive split, it will modify it into:
  85. foo (DUMMY_Z_VAR.s, repl_for_a, repl_for_b, <rest of original arguments>);
  86. It will also store {DUMMY_S_VAR, 32} and {DUMMY_S_VAR, 64} representing offsets
  87. of z.s.a and z.s.b (assuming a 32-bit int) into foo's cgraph node
  88. clone->performed_splits vector (which is storing structures of type
  89. ipa_param_performed_split also defined in this header file).
  90. Call redirection will identify that expression DUMMY_Z_VAR.s is based on a
  91. variable stored in performed_splits vector and learn that the following
  92. arguments, already in SSA form, represent offsets 32 and 64 in a split original
  93. parameter. It subtracts offset of DUMMY_Z_VAR.s from 32 and 64 and arrives at
  94. offsets 0 and 32 within callee's original parameter. At this point it also
  95. knows from the call graph that only the bit with offset 32 is needed and so
  96. changes the call statement into final:
  97. bar (repl_for_b, <rest of original arguments>); */
  98. #ifndef IPA_PARAM_MANIPULATION_H
  99. #define IPA_PARAM_MANIPULATION_H
  100. /* Indices into ipa_param_prefixes to identify a human-readable prefix for newly
  101. synthesized parameters. Keep in sync with the array. */
  102. enum ipa_param_name_prefix_indices
  103. {
  104. IPA_PARAM_PREFIX_SYNTH,
  105. IPA_PARAM_PREFIX_ISRA,
  106. IPA_PARAM_PREFIX_SIMD,
  107. IPA_PARAM_PREFIX_MASK,
  108. IPA_PARAM_PREFIX_COUNT
  109. };
  110. /* We do not support manipulating functions with more than
  111. 1<<IPA_PARAM_MAX_INDEX_BITS parameters. */
  112. #define IPA_PARAM_MAX_INDEX_BITS 16
  113. /* Operation to be performed for the parameter in ipa_parm_adjustment
  114. below. */
  115. enum ipa_parm_op
  116. {
  117. /* Do not use or you will trigger an assert. */
  118. IPA_PARAM_OP_UNDEFINED,
  119. /* This new parameter is an unmodified parameter at index base_index. */
  120. IPA_PARAM_OP_COPY,
  121. /* This describes a brand new parameter. If it somehow relates to any
  122. original parameters, the user needs to manage the transition itself. */
  123. IPA_PARAM_OP_NEW,
  124. /* Split parameter as indicated by fields base_index, offset and type. */
  125. IPA_PARAM_OP_SPLIT
  126. };
  127. /* Structure that describes one parameter of a function after transformation.
  128. Omitted parameters will be removed. */
  129. struct GTY(()) ipa_adjusted_param
  130. {
  131. /* Type of the new parameter. Required for all operations except
  132. IPA_PARM_OP_COPY when the original type will be preserved. */
  133. tree type;
  134. /* Alias reference type to be used in MEM_REFs when adjusting caller
  135. arguments. Required for IPA_PARM_OP_SPLIT operation. */
  136. tree alias_ptr_type;
  137. /* Offset into the original parameter (for the cases when the new parameter
  138. is a component of an original one). Required for IPA_PARM_OP_SPLIT
  139. operation. */
  140. unsigned unit_offset;
  141. /* Zero based index of the original parameter this one is based on. Required
  142. for IPA_PARAM_OP_COPY and IPA_PARAM_OP_SPLIT, users of IPA_PARAM_OP_NEW
  143. only need to specify it if they use replacement lookup provided by
  144. ipa_param_body_adjustments. */
  145. unsigned base_index : IPA_PARAM_MAX_INDEX_BITS;
  146. /* Zero based index of the parameter this one is based on in the previous
  147. clone. If there is no previous clone, it must be equal to base_index. */
  148. unsigned prev_clone_index : IPA_PARAM_MAX_INDEX_BITS;
  149. /* Specify the operation, if any, to be performed on the parameter. */
  150. enum ipa_parm_op op : 2;
  151. /* If set, this structure describes a parameter copied over from a previous
  152. IPA clone, any transformations are thus not to be re-done. */
  153. unsigned prev_clone_adjustment : 1;
  154. /* Index into ipa_param_prefixes specifying a prefix to be used with
  155. DECL_NAMEs of newly synthesized parameters. */
  156. unsigned param_prefix_index : 2;
  157. /* Storage order of the original parameter (for the cases when the new
  158. parameter is a component of an original one). */
  159. unsigned reverse : 1;
  160. /* A bit free for the user. */
  161. unsigned user_flag : 1;
  162. };
  163. void ipa_dump_adjusted_parameters (FILE *f,
  164. vec<ipa_adjusted_param, va_gc> *adj_params);
  165. /* Structure to remember the split performed on a node so that edge redirection
  166. (i.e. splitting arguments of call statements) know how split formal
  167. parameters of the caller are represented. */
  168. struct GTY(()) ipa_param_performed_split
  169. {
  170. /* The dummy VAR_DECL that was created instead of the split parameter that
  171. sits in the call in the meantime between clone materialization and call
  172. redirection. All entries in a vector of performed splits that correspond
  173. to the same dumy decl must be grouped together. */
  174. tree dummy_decl;
  175. /* Offset into the original parameter. */
  176. unsigned unit_offset;
  177. };
  178. /* Class used to record planned modifications to parameters of a function and
  179. also to perform necessary modifications at the caller side at the gimple
  180. level. Used to describe all cgraph node clones that have their parameters
  181. changed, therefore the class should only have a small memory footprint. */
  182. class GTY(()) ipa_param_adjustments
  183. {
  184. public:
  185. /* Constructor from NEW_PARAMS showing how new parameters should look like
  186. plus copying any pre-existing actual arguments starting from argument
  187. with index ALWAYS_COPY_START (if non-negative, negative means do not copy
  188. anything beyond what is described in NEW_PARAMS), and SKIP_RETURN, which
  189. indicates that the function should return void after transformation. */
  190. ipa_param_adjustments (vec<ipa_adjusted_param, va_gc> *new_params,
  191. int always_copy_start, bool skip_return)
  192. : m_adj_params (new_params), m_always_copy_start (always_copy_start),
  193. m_skip_return (skip_return)
  194. {}
  195. /* Modify a call statement arguments (and possibly remove the return value)
  196. as described in the data fields of this class. */
  197. gcall *modify_call (gcall *stmt,
  198. vec<ipa_param_performed_split, va_gc> *performed_splits,
  199. tree callee_decl, bool update_references);
  200. /* Return if the first parameter is left intact. */
  201. bool first_param_intact_p ();
  202. /* Build a function type corresponding to the modified call. */
  203. tree build_new_function_type (tree old_type, bool type_is_original_p);
  204. /* Build a declaration corresponding to the target of the modified call. */
  205. tree adjust_decl (tree orig_decl);
  206. /* Fill a vector marking which parameters are intact by the described
  207. modifications. */
  208. void get_surviving_params (vec<bool> *surviving_params);
  209. /* Fill a vector with new indices of surviving original parameters. */
  210. void get_updated_indices (vec<int> *new_indices);
  211. /* Return the original index for the given new parameter index. Return a
  212. negative number if not available. */
  213. int get_original_index (int newidx);
  214. void dump (FILE *f);
  215. void debug ();
  216. /* How the known part of arguments should look like. */
  217. vec<ipa_adjusted_param, va_gc> *m_adj_params;
  218. /* If non-negative, copy any arguments starting at this offset without any
  219. modifications so that functions with variable number of arguments can be
  220. modified. This number should be equal to the number of original forma
  221. parameters. */
  222. int m_always_copy_start;
  223. /* If true, make the function not return any value. */
  224. bool m_skip_return;
  225. private:
  226. ipa_param_adjustments () {}
  227. void init (vec<tree> *cur_params);
  228. int get_max_base_index ();
  229. bool method2func_p (tree orig_type);
  230. };
  231. /* Structure used to map expressions accessing split or replaced parameters to
  232. new PARM_DECLs. */
  233. struct ipa_param_body_replacement
  234. {
  235. /* The old decl of the original parameter. */
  236. tree base;
  237. /* The new decl it should be replaced with. */
  238. tree repl;
  239. /* When modifying clones during IPA clone materialization, this is a dummy
  240. decl used to mark calls in which we need to apply transitive splitting,
  241. these dummy delcls are inserted as arguments to such calls and then
  242. followed by all the replacements with offset info stored in
  243. ipa_param_performed_split.
  244. Users of ipa_param_body_adjustments that modify standalone functions
  245. outside of IPA clone materialization can use this field for their internal
  246. purposes. */
  247. tree dummy;
  248. /* The offset within BASE that REPL represents. */
  249. unsigned unit_offset;
  250. };
  251. struct ipa_replace_map;
  252. /* Class used when actually performing adjustments to formal parameters of a
  253. function to map accesses that need to be replaced to replacements. The
  254. class attempts to work in two very different sets of circumstances: as a
  255. part of tree-inine.c's tree_function_versioning machinery to clone functions
  256. (when M_ID is not NULL) and in s standalone fashion, modifying an existing
  257. function in place (when M_ID is NULL). While a lot of stuff handled in a
  258. unified way in both modes, there are many aspects of the processs that
  259. requires distinct paths. */
  260. class ipa_param_body_adjustments
  261. {
  262. public:
  263. /* Constructor to use from within tree-inline. */
  264. ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
  265. tree fndecl, tree old_fndecl,
  266. struct copy_body_data *id, tree *vars,
  267. vec<ipa_replace_map *, va_gc> *tree_map);
  268. /* Constructor to use for modifying a function outside of tree-inline from an
  269. instance of ipa_param_adjustments. */
  270. ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
  271. tree fndecl);
  272. /* Constructor to use for modifying a function outside of tree-inline from a
  273. simple vector of desired parameter modification. */
  274. ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
  275. tree fndecl);
  276. /* The do-it-all function for modifying a function outside of
  277. tree-inline. */
  278. bool perform_cfun_body_modifications ();
  279. /* Change the PARM_DECLs. */
  280. void modify_formal_parameters ();
  281. /* Register a replacement decl for the transformation done in APM. */
  282. void register_replacement (ipa_adjusted_param *apm, tree replacement,
  283. tree dummy = NULL_TREE);
  284. /* Lookup a replacement for a given offset within a given parameter. */
  285. tree lookup_replacement (tree base, unsigned unit_offset);
  286. /* Lookup a replacement for an expression, if there is one. */
  287. ipa_param_body_replacement *get_expr_replacement (tree expr,
  288. bool ignore_default_def);
  289. /* Lookup the new base for surviving names previously belonging to a
  290. parameter. */
  291. tree get_replacement_ssa_base (tree old_decl);
  292. /* Modify a statement. */
  293. bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts);
  294. /* Return the new chain of parameters. */
  295. tree get_new_param_chain ();
  296. /* Pointers to data structures defining how the function should be
  297. modified. */
  298. vec<ipa_adjusted_param, va_gc> *m_adj_params;
  299. ipa_param_adjustments *m_adjustments;
  300. /* Vector of old parameter declarations that must have their debug bind
  301. statements re-mapped and debug decls created. */
  302. auto_vec<tree, 16> m_reset_debug_decls;
  303. /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored
  304. adjustments. */
  305. bool m_split_modifications_p;
  306. private:
  307. void common_initialization (tree old_fndecl, tree *vars,
  308. vec<ipa_replace_map *, va_gc> *tree_map);
  309. tree carry_over_param (tree t);
  310. unsigned get_base_index (ipa_adjusted_param *apm);
  311. ipa_param_body_replacement *lookup_replacement_1 (tree base,
  312. unsigned unit_offset);
  313. tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
  314. bool modify_expression (tree *expr_p, bool convert);
  315. bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
  316. bool modify_call_stmt (gcall **stmt_p);
  317. bool modify_cfun_body ();
  318. void reset_debug_stmts ();
  319. /* Declaration of the function that is being transformed. */
  320. tree m_fndecl;
  321. /* If non-NULL, the tree-inline master data structure guiding materialization
  322. of the current clone. */
  323. struct copy_body_data *m_id;
  324. /* Vector of old parameter declarations (before changing them). */
  325. auto_vec<tree, 16> m_oparms;
  326. /* Vector of parameter declarations the function will have after
  327. transformation. */
  328. auto_vec<tree, 16> m_new_decls;
  329. /* If the function type has non-NULL TYPE_ARG_TYPES, this is the vector of
  330. these types after transformation, otherwise an empty one. */
  331. auto_vec<tree, 16> m_new_types;
  332. /* Vector of structures telling how to replace old parameters in the
  333. function body. TODO: Even though there usually be only few, but should we
  334. use a hash? */
  335. auto_vec<ipa_param_body_replacement, 16> m_replacements;
  336. /* Vector for remapping SSA_BASES from old parameter declarations that are
  337. being removed as a part of the transformation. Before a new VAR_DECL is
  338. created, it holds the old PARM_DECL, once the variable is built it is
  339. stored here. */
  340. auto_vec<tree> m_removed_decls;
  341. /* Hash to quickly lookup the item in m_removed_decls given the old decl. */
  342. hash_map<tree, unsigned> m_removed_map;
  343. /* True iff the transformed function is a class method that is about to loose
  344. its this pointer and must be converted to a normal function. */
  345. bool m_method2func;
  346. };
  347. void push_function_arg_decls (vec<tree> *args, tree fndecl);
  348. void push_function_arg_types (vec<tree> *types, tree fntype);
  349. #endif /* IPA_PARAM_MANIPULATION_H */