This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 2/4] New parameter manipulation infrastructure
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Martin Jambor <mjambor at suse dot cz>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jan Hubicka <jh at suse dot cz>
- Date: Fri, 13 Sep 2019 19:40:13 +0200
- Subject: Re: [PATCH 2/4] New parameter manipulation infrastructure
- References: <cover.1566408586.git.mjambor@suse.cz> <089afda4b307a6222a4c747ccece5ae49601235e.1566408586.git.mjambor@suse.cz>
> 2019-08-20 Martin Jambor <mjambor@suse.cz>
>
> * Makefile.in (GTFILES): Added ipa-param-manipulation.h.
> * cgraph.h (ipa_replace_map): Removed fields old_tree, replace_p
> and ref_p, added fields param_adjustments and performed_splits.
> (struct cgraph_clone_info): Remove ags_to_skip and
> combined_args_to_skip, new field param_adjustments.
> (cgraph_node::create_clone): Changed parameters to use
> ipa_param_adjustments.
> (cgraph_node::create_virtual_clone): Likewise.
> (cgraph_node::create_virtual_clone_with_body): Likewise.
> (tree_function_versioning): Likewise.
> (cgraph_build_function_type_skip_args): Removed.
> * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Convert to
> using ipa_param_adjustments.
> (clone_of_p): Likewise.
> * cgraphclones.c (cgraph_build_function_type_skip_args): Removed.
> (build_function_decl_skip_args): Likewise.
> (duplicate_thunk_for_node): Adjust parameters using
> ipa_param_body_adjustments, copy param_adjustments instead of
> args_to_skip.
> (cgraph_node::create_clone): Convert to using ipa_param_adjustments.
> (cgraph_node::create_virtual_clone): Likewise.
> (cgraph_node::create_version_clone_with_body): Likewise.
> (cgraph_materialize_clone): Likewise.
> (symbol_table::materialize_all_clones): Likewise.
> * coretypes.h (cgraph_edge): Declare.
> * ipa-cp.c (get_replacement_map): Do not initialize removed fields.
> (initialize_node_lattices): Make aware that some parameters might have
> already been removed.
> (want_remove_some_param_p): New function.
> (create_specialized_node): Convert to using ipa_param_adjustments and
> deal with possibly pre-existing adjustments.
> * ipa-fnsummary.c (ipa_fn_summary_t::duplicate): Simplify
> ipa_replace_map check.
> * ipa-inline-transform.c (save_inline_function_body): Update to
> refelct new tree_function_versioning signature.
> * ipa-param-manipulation.c: Rewrite.
> * ipa-param-manipulation.h: Likewise.
> * ipa-prop.c (adjust_agg_replacement_values): Use a helper from
> ipa_param_adjustments to get current parameter indices.
> (ipcp_modif_dom_walker::before_dom_children): Likewise.
> (ipcp_update_bits): Likewise.
> (ipcp_update_vr): Likewise.
> * ipa-split.c (split_function): Convert to using ipa_param_adjustments.
> * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise.
> (output_node_opt_summary): Do not stream removed fields. Stream
> parameter adjustments instead of argumetns to skip.
> (input_node_opt_summary): Likewise.
> (input_node_opt_summary): Likewise.
> * multiple_target.c (create_target_clone): Update to reflet new type
> of create_version_clone_with_body.
> * omp-simd-clone.c (simd_clone_vector_of_formal_parm_types): Adjust
> for the new interface.
> (simd_clone_clauses_extract): Likewise, make args an auto_vec.
> (simd_clone_compute_base_data_type): Likewise.
> (simd_clone_init_simd_arrays): Adjust for the new interface.
> (simd_clone_adjust_argument_types): Likewise.
> (struct modify_stmt_info): Likewise.
> (ipa_simd_modify_stmt_ops): Likewise.
> (ipa_simd_modify_function_body): Likewise.
> (simd_clone_adjust): Likewise.
> * trans-mem.c (ipa_tm_create_version): Update to reflect new type of
> tree_function_versioning.
> * tree-inline.h (copy_body_data): New fields killed_new_ssa_names and
> param_body_adjs.
> (copy_decl_to_var): Declare.
> * tree-inline.c (update_clone_info): Do not remap old_tree.
> (remap_gimple_stmt): Use ipa_param_body_adjustments to modify gimple
> statements, walk all extra generated statements and remap their
> operands.
> (redirect_all_calls): Add killed SSA names to a hash set.
> (remap_ssa_name): Do not remap killed SSA names.
> (copy_arguments_for_versioning): Renames to copy_arguments_nochange,
> half of functionality moved to ipa_param_body_adjustments.
> (copy_decl_to_var): Make exported.
> (copy_body): Destroy killed_new_ssa_names hash set.
> (expand_call_inline): Remap performed splits.
> (update_clone_info): Likewise.
> (tree_function_versioning): Simplify tree_map processing. Updated to
> accept ipa_param_adjustments and use ipa_param_body_adjustments.
OK
> +/* Modify actual arguments of a function call in statement STMT, assuming it
> + calls CALLEE_DECL. CALLER_ADJ must be the description of parameter
> + adjustments of the caller or NULL if there are none. Return the new
> + statement that replaced the old one. When invoked, cfun and
> + current_function_decl have to be set to the caller. */
> +
> +gcall *
> +ipa_param_adjustments::modify_call (gcall *stmt,
> + vec<ipa_param_performed_split,
> + va_gc> *performed_splits,
> + tree callee_decl, bool update_references)
> +{
> + unsigned len = vec_safe_length (m_adj_params);
> + auto_vec<tree, 16> vargs (len);
> + tree old_decl = gimple_call_fndecl (stmt);
> + unsigned old_nargs = gimple_call_num_args (stmt);
> + auto_vec<bool, 16> kept (old_nargs);
> + kept.quick_grow_cleared (old_nargs);
> +
> + auto_vec <unsigned, 16> index_map;
> + auto_vec <transitive_split_map> trans_map;
> + bool transitive_remapping = false;
vertical space here and move the quick_grow_cleared here too I guess.
It seems that you omit vertical space after declaration at many places.
> diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h
> index 71fc4a201aa..b9da00bb5c9 100644
> --- a/gcc/ipa-param-manipulation.h
> +++ b/gcc/ipa-param-manipulation.h
> @@ -16,101 +16,394 @@ for more details.
>
> You should have received a copy of the GNU General Public License
> along with GCC; see the file COPYING3. If not see
> -<http://www.gnu.org/licenses/>. */
> +<http://www.gnu.org/licenses/>.
> +
> +
> +
> +This file defines classes and other data structures that are used to manipulate
> +the prototype of a function, especially to create, remove or split its formal
> +parameters, but also to remove its return value, and also its call statements
> +correspondingly.
> +
> +The most basic one is a vector of structures ipa_adjusted_param. It is simply
> +a description how the new parameters should look like after the transformation
> +in what way they relate to the previous ones (if in any). Such relation to an
> +old parameter can be an outright copy or an IPA-SRA replacement. If an old
> +parameter is not listed or otherwise mentioned, it is removed as unused or at
> +least unnecessary. Note that this most basic structure does not work for
> +modifying calls of functions with variable number of arguments.
> +
> +Class ipa_param_adjustments is only a little more than a thin encapsulation of
> +a vector of ipa_param_adjustments. Along with this vector it contains an index
> +of the first potential vararg argument and a boolean flag whether the return
> +value should be removed or not. Moreover, the class contains method
> +modify_call which can transform a call statement so that it correctly calls a
> +modified function. These two data structures were designed to have a small
> +memory footprint because they are allocated for each clone of a call graph node
> +that has its prototype changed and live until the end of IPA clone
> +materialization and call redirection phase.
> +
> +On the other hand, class ipa_param_body_adjustments can afford to allocate more
> +data because its life span is much smaller, it is allocated and destroyed in
> +the course of materialization of each single clone that needs it or only when a
> +particular pass needs to change a function it is operating on. This class has
> +various methods required to change function declaration and the body of the
> +function according to instructions given either by class ipa_param_adjustments
> +or only a vector of ipa_adjusted_params.
> +
> +When these classes are used in the context of call graph clone materialization
> +and subsequent call statement redirection - which is the point at which we
> +modify arguments in call statements - they need to cooperate with each other in
> +order to handle what we refer to as transitive (IPA-SRA) splits. These are
> +situations when a formal parameter of one function is split into several
> +smaller ones and some of them are then passed on in a call to another function
> +because the formal parameter of this callee has also been split.
> +
> +Consider a simple example:
> +
> +struct S {int a, b, c;};
> +struct Z {int x; S s;};
> +
> +foo (S s)
> +{
> + use (s.b);
> +}
> +
> +bar (Z z)
> +{
> + use (z.s.a);
> + foo (z.s);
> +}
> +
> +baz ()
> +{
> + bar (*global);
> +}
> +
> +Both bar and foo would have their parameter split. Foo would receive one
> +replacement representing s.b. Function bar would see its parameter split into
> +one replacement representing z.s.a and another representing z.s.b which would
> +be passed on to foo. It would be a so called transitive split IPA-SRA
> +replacement, one which is passed in a call as an actual argument to another
> +IPA-SRA replacement in another function.
> +
> +Note that the call chain the example can be arbitrarily long and recursive and
> +that any function in it can be cloned by another IPA pass and any number of
> +adjacent functions in the call chain can be inlined into each other. Call
> +redirection takes place only after bodies of the function have been modified by
> +all of the above.
> +
> +Call redirection has to be able to find the right decl or SSA_NAME that
> +corresponds to the transitive split in the caller. The SSA names are assigned
> +right after clone materialization/ modification and cannot be "added"
> +afterwards. Moreover, if the caller has been inlined the SSA_NAMEs in question
> +no longer belong to PARM_DECLs but to VAR_DECLs, indistinguishable from any
> +others.
> +
> +Therefore, when clone materialization finds a call statement which it knows is
> +a part of a transitive split, it will modify it into:
> +
> + foo (DUMMY_Z_VAR.s, repl_for_a, repl_for_b, <rest of original arguments>);
> +
> +It will also store {DUMMY_S_VAR, 32} and {DUMMY_S_VAR, 64} representing offsets
> +of z.s.a and z.s.b (assuming a 32-bit int) into foo's cgraph node
> +clone->performed_splits vector (which is storing structures of type
> +ipa_param_performed_split also defined in this header file).
> +
> +Call redirection will identify that expression DUMMY_Z_VAR.s is based on a
> +variable stored in performed_splits vector and learn that the following
> +arguments, already in SSA form, represent offsets 32 and 64 in a split original
> +parameter. It subtracts offset of DUMMY_Z_VAR.s from 32 and 64 and arrives at
> +offsets 0 and 32 within callee's original parameter. At this point it also
> +knows from the call graph that only the bit with offset 32 is needed and so
> +changes the call statement into final:
> +
> +bar (repl_for_b, <rest of original arguments>); */
I would probably also include one line comments for public member
functions for new classes you introduce so one has most of essential
info at one place.
Honza