From patchwork Wed Nov 17 09:33:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 47807 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A1060385840C for ; Wed, 17 Nov 2021 09:33:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A1060385840C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1637141632; bh=i3cyDETu8ulLkaYRl4iHlJUoPO2s9wAReSIhU0wHp1s=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=H6skK8beOnl7H81iFVLE0YFPqSjaZLDTy0LQXSIJ50xP4mcDmcTJ/5Vj7g6tjFqik YU6OWAOhPM0b7YtV41CBHE+Y/H5skId3FchPOrtg0cs+uRQguHb5mmcyOwEHOiP3D5 UfZpzdmwbtJG96Bp+ncQgSWLVKN+8Jzc1Ewr3xd8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from nikam.ms.mff.cuni.cz (nikam.ms.mff.cuni.cz [195.113.20.16]) by sourceware.org (Postfix) with ESMTPS id D6DC13858406 for ; Wed, 17 Nov 2021 09:33:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D6DC13858406 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 7952C280864; Wed, 17 Nov 2021 10:33:19 +0100 (CET) Date: Wed, 17 Nov 2021 10:33:19 +0100 To: gcc-patches@gcc.gnu.org Subject: Finish lto parts of kill analysis Message-ID: <20211117093319.GB87060@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jan Hubicka via Gcc-patches From: Jan Hubicka Reply-To: Jan Hubicka Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, this patch adds the IPA part of modref kill analysis. It just copies of what local code did alrady. I did not manage to push out all patches for modref I planned and I will wait for next stage1. This one however I would like to push since it is quite simple and it makes no sense to leave the ipa bits being collected but unused. Bootstrapped/regtested x86_64-linux. I will commit it tonight if there are no complains. Honza gcc/ChangeLog: 2021-11-17 Jan Hubicka * ipa-modref-tree.c: Include cgraph.h and tree-streamer.h. (modref_access_node::stream_out): New member function. (modref_access_node::stream_in): New member function. * ipa-modref-tree.h (modref_access_node::stream_out, modref_access_node::stream_in): Declare. * ipa-modref.c (modref_summary_lto::useful_p): Free useless kills. (modref_summary_lto::dump): Dump kills. (analyze_store): Record kills for LTO (analyze_stmt): Likewise. (modref_summaries_lto::duplicate): Duplicate kills. (write_modref_records): Use new stream_out member function. (read_modref_records): Likewise. (modref_write): Stream out kills. (read_section): Stream in kills (remap_kills): New function. (update_signature): Use it. diff --git a/gcc/ipa-modref-tree.c b/gcc/ipa-modref-tree.c index bbe23a5a211..ece42ade225 100644 --- a/gcc/ipa-modref-tree.c +++ b/gcc/ipa-modref-tree.c @@ -27,6 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "selftest.h" #include "tree-ssa-alias.h" #include "gimple.h" +#include "cgraph.h" +#include "tree-streamer.h" /* Return true if both accesses are the same. */ bool @@ -458,6 +460,50 @@ modref_access_node::try_merge_with (vec *&accesses, i++; } +/* Stream out to OB. */ + +void +modref_access_node::stream_out (struct output_block *ob) const +{ + streamer_write_hwi (ob, parm_index); + if (parm_index != -1) + { + streamer_write_uhwi (ob, parm_offset_known); + if (parm_offset_known) + { + streamer_write_poly_int64 (ob, parm_offset); + streamer_write_poly_int64 (ob, offset); + streamer_write_poly_int64 (ob, size); + streamer_write_poly_int64 (ob, max_size); + } + } +} + +modref_access_node +modref_access_node::stream_in (struct lto_input_block *ib) +{ + int parm_index = streamer_read_hwi (ib); + bool parm_offset_known = false; + poly_int64 parm_offset = 0; + poly_int64 offset = 0; + poly_int64 size = -1; + poly_int64 max_size = -1; + + if (parm_index != -1) + { + parm_offset_known = streamer_read_uhwi (ib); + if (parm_offset_known) + { + parm_offset = streamer_read_poly_int64 (ib); + offset = streamer_read_poly_int64 (ib); + size = streamer_read_poly_int64 (ib); + max_size = streamer_read_poly_int64 (ib); + } + } + return {offset, size, max_size, parm_offset, parm_index, + parm_offset_known, false}; +} + /* Insert access with OFFSET and SIZE. Collapse tree if it has more than MAX_ACCESSES entries. If RECORD_ADJUSTMENTs is true avoid too many interval extensions. diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h index 1bf2aa8460e..0a097349ebd 100644 --- a/gcc/ipa-modref-tree.h +++ b/gcc/ipa-modref-tree.h @@ -99,6 +99,10 @@ struct GTY(()) modref_access_node tree get_call_arg (const gcall *stmt) const; /* Build ao_ref corresponding to the access and return true if succesful. */ bool get_ao_ref (const gcall *stmt, class ao_ref *ref) const; + /* Stream access to OB. */ + void stream_out (struct output_block *ob) const; + /* Stream access in from IB. */ + static modref_access_node stream_in (struct lto_input_block *ib); /* Insert A into vector ACCESSES. Limit size of vector to MAX_ACCESSES and if RECORD_ADJUSTMENT is true keep track of adjustment counts. Return 0 if nothing changed, 1 is insertion suceeded and -1 if failed. */ diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 90cd1be764c..9ceecdd479f 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -410,6 +410,8 @@ modref_summary_lto::useful_p (int ecf_flags, bool check_flags) && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); if (loads && !loads->every_base) return true; + else + kills.release (); if (ecf_flags & ECF_PURE) return ((!side_effects || !nondeterministic) && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); @@ -634,6 +636,15 @@ modref_summary_lto::dump (FILE *out) dump_lto_records (loads, out); fprintf (out, " stores:\n"); dump_lto_records (stores, out); + if (kills.length ()) + { + fprintf (out, " kills:\n"); + for (auto kill : kills) + { + fprintf (out, " "); + kill.dump (out); + } + } if (writes_errno) fprintf (out, " Writes errno\n"); if (side_effects) @@ -1527,15 +1538,17 @@ analyze_store (gimple *stmt, tree, tree op, void *data) record_access (summary->stores, &r, a); if (summary_lto) record_access_lto (summary_lto->stores, &r, a); - if (summary - && ((summary_ptrs *)data)->always_executed + if (((summary_ptrs *)data)->always_executed && a.useful_for_kill_p () && (!cfun->can_throw_non_call_exceptions || !stmt_could_throw_p (cfun, stmt))) { if (dump_file) fprintf (dump_file, " - Recording kill\n"); - modref_access_node::insert_kill (summary->kills, a, false); + if (summary) + modref_access_node::insert_kill (summary->kills, a, false); + if (summary_lto) + modref_access_node::insert_kill (summary_lto->kills, a, false); } return false; } @@ -1554,8 +1567,7 @@ analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto, Similar logic is in ipa-pure-const.c. */ if ((ipa || cfun->after_inlining) && gimple_clobber_p (stmt)) { - if (summary - && always_executed && record_access_p (gimple_assign_lhs (stmt))) + if (always_executed && record_access_p (gimple_assign_lhs (stmt))) { ao_ref r; ao_ref_init (&r, gimple_assign_lhs (stmt)); @@ -1564,7 +1576,10 @@ analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto, { if (dump_file) fprintf (dump_file, " - Recording kill\n"); - modref_access_node::insert_kill (summary->kills, a, false); + if (summary) + modref_access_node::insert_kill (summary->kills, a, false); + if (summary_lto) + modref_access_node::insert_kill (summary_lto->kills, a, false); } } return true; @@ -3270,6 +3285,8 @@ modref_summaries_lto::duplicate (cgraph_node *, cgraph_node *, src_data->loads->max_refs, src_data->loads->max_accesses); dst_data->loads->copy_from (src_data->loads); + dst_data->kills.reserve_exact (src_data->kills.length ()); + dst_data->kills.splice (src_data->kills); dst_data->writes_errno = src_data->writes_errno; dst_data->side_effects = src_data->side_effects; dst_data->nondeterministic = src_data->nondeterministic; @@ -3324,40 +3341,21 @@ write_modref_records (modref_records_lto *tt, struct output_block *ob) streamer_write_uhwi (ob, tt->every_base); streamer_write_uhwi (ob, vec_safe_length (tt->bases)); - size_t i; - modref_base_node *base_node; - FOR_EACH_VEC_SAFE_ELT (tt->bases, i, base_node) + for (auto base_node : tt->bases) { stream_write_tree (ob, base_node->base, true); streamer_write_uhwi (ob, base_node->every_ref); streamer_write_uhwi (ob, vec_safe_length (base_node->refs)); - size_t j; - modref_ref_node *ref_node; - FOR_EACH_VEC_SAFE_ELT (base_node->refs, j, ref_node) + for (auto ref_node : base_node->refs) { stream_write_tree (ob, ref_node->ref, true); streamer_write_uhwi (ob, ref_node->every_access); streamer_write_uhwi (ob, vec_safe_length (ref_node->accesses)); - size_t k; - modref_access_node *access_node; - FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node) - { - streamer_write_hwi (ob, access_node->parm_index); - if (access_node->parm_index != -1) - { - streamer_write_uhwi (ob, access_node->parm_offset_known); - if (access_node->parm_offset_known) - { - streamer_write_poly_int64 (ob, access_node->parm_offset); - streamer_write_poly_int64 (ob, access_node->offset); - streamer_write_poly_int64 (ob, access_node->size); - streamer_write_poly_int64 (ob, access_node->max_size); - } - } - } + for (auto access_node : ref_node->accesses) + access_node.stream_out (ob); } } } @@ -3469,26 +3467,7 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, for (size_t k = 0; k < naccesses; k++) { - int parm_index = streamer_read_hwi (ib); - bool parm_offset_known = false; - poly_int64 parm_offset = 0; - poly_int64 offset = 0; - poly_int64 size = -1; - poly_int64 max_size = -1; - - if (parm_index != -1) - { - parm_offset_known = streamer_read_uhwi (ib); - if (parm_offset_known) - { - parm_offset = streamer_read_poly_int64 (ib); - offset = streamer_read_poly_int64 (ib); - size = streamer_read_poly_int64 (ib); - max_size = streamer_read_poly_int64 (ib); - } - } - modref_access_node a = {offset, size, max_size, parm_offset, - parm_index, parm_offset_known, false}; + modref_access_node a = modref_access_node::stream_in (ib); if (nolto_ref_node) nolto_ref_node->insert_access (a, max_accesses, false); if (lto_ref_node) @@ -3599,6 +3578,9 @@ modref_write () write_modref_records (r->loads, ob); write_modref_records (r->stores, ob); + streamer_write_uhwi (ob, r->kills.length ()); + for (auto kill : r->kills) + kill.stream_out (ob); struct bitpack_d bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, r->writes_errno, 1); @@ -3723,6 +3705,20 @@ read_section (struct lto_file_decl_data *file_data, const char *data, read_modref_records (&ib, data_in, modref_sum ? &modref_sum->stores : NULL, modref_sum_lto ? &modref_sum_lto->stores : NULL); + int j = streamer_read_uhwi (&ib); + if (j && modref_sum) + modref_sum->kills.reserve_exact (j); + if (j && modref_sum_lto) + modref_sum_lto->kills.reserve_exact (j); + for (int k = 0; k < j; k++) + { + modref_access_node a = modref_access_node::stream_in (&ib); + + if (modref_sum) + modref_sum->kills.quick_push (a); + if (modref_sum_lto) + modref_sum_lto->kills.quick_push (a); + } struct bitpack_d bp = streamer_read_bitpack (&ib); if (bp_unpack_value (&bp, 1)) { @@ -3863,6 +3859,27 @@ remap_arg_flags (auto_vec &arg_flags, clone_info *info) } } +/* Update kills accrdoing to the parm map MAP. */ + +static void +remap_kills (vec &kills, const vec &map) +{ + for (size_t i = 0; i < kills.length ();) + if (kills[i].parm_index >= 0) + { + if (kills[i].parm_index < (int)map.length () + && map[kills[i].parm_index] != MODREF_UNKNOWN_PARM) + { + kills[i].parm_index = map[kills[i].parm_index]; + i++; + } + else + kills.unordered_remove (i); + } + else + i++; +} + /* If signature changed, update the summary. */ static void @@ -3913,8 +3930,7 @@ update_signature (struct cgraph_node *node) { r->loads->remap_params (&map); r->stores->remap_params (&map); - /* TODO: One we do IPA kills analysis, update the table here. */ - r->kills.release (); + remap_kills (r->kills, map); if (r->arg_flags.length ()) remap_arg_flags (r->arg_flags, info); } @@ -3922,8 +3938,7 @@ update_signature (struct cgraph_node *node) { r_lto->loads->remap_params (&map); r_lto->stores->remap_params (&map); - /* TODO: One we do IPA kills analysis, update the table here. */ - r_lto->kills.release (); + remap_kills (r_lto->kills, map); if (r_lto->arg_flags.length ()) remap_arg_flags (r_lto->arg_flags, info); }