From patchwork Wed Dec 14 10:15:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 705637 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tdssw2lrCz9t1P for ; Wed, 14 Dec 2016 21:16:00 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="f/wMbog1"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=G7Cmc/W6iMD3OEvx1 9RccpM0ZNwp5dWkBTaNW4gkbSmHdKd9PlJ/R8t1YTbPjrvbIfP52YjouzdmNVfI5 yVTcX1hKd/oqcWbP7SbYo3+W++q9AxbVfeOHHD9HlJO8D2H05s6MrfqgVhmK7YkV sdzvjiSqHVWI4P/cvvmz2gmvmA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=eLXgghfSx92A5S2CerSy91m 09ao=; b=f/wMbog1el+lbQxR4x/76pX0teRhYtGI53Nxqns41QbOynPxQerW2Ve gXcenIg+KeOytqYkk2+9m43ZFKRwG8V6TLygJYz81RgyrCNdoTvZImL+jTfqc5S4 1AWCbuaRRlnKiN/1Sg9wSCq5yU6SllN+qGauAVIbrVEB3w0oo48w= Received: (qmail 93435 invoked by alias); 14 Dec 2016 10:15:50 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 92776 invoked by uid 89); 14 Dec 2016 10:15:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, SPF_PASS autolearn=ham version=3.3.2 spammy=anticipated, evening, fold_convert X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 14 Dec 2016 10:15:32 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id CB5DBAB49; Wed, 14 Dec 2016 10:15:23 +0000 (UTC) Date: Wed, 14 Dec 2016 11:15:23 +0100 From: Martin Jambor To: Richard Biener Cc: kugan , Jan Hubicka , "gcc-patches@gcc.gnu.org" Subject: Re: [PR78365] ICE in determine_value_range, at tree-ssa-loo p-niter.c:413 Message-ID: <20161214101523.mxvcgfqdwcbdy737@virgil.suse.cz> Mail-Followup-To: Richard Biener , kugan , Jan Hubicka , "gcc-patches@gcc.gnu.org" References: <68396c67-fdcc-33ed-5463-a07502959865@linaro.org> <20161123153317.wjyjxgp6ltg5cp6t@virgil.suse.cz> <4f03c618-081b-e5b8-5ef6-6abdfddd9d9b@linaro.org> <20161207100853.ae3qcpo5ycblqxau@virgil.suse.cz> <20161209105127.mb3xasvrcipt2kqg@virgil.suse.cz> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.2 (2016-07-01) X-IsSubscribed: yes Hi, On Fri, Dec 09, 2016 at 01:18:25PM +0100, Richard Biener wrote: > > The patch looks somewhat backward. It populates the param type from > the callee but the only thing we really know is the _originating_ type > from the callers DECL_ARGUMENTS (if the JF is based on a parameter > which is the only case where we do not know the type of the actual > value statically -- we only know the type we expect). > > So the type would be present only on IPA_JF_PASS_THROUGH JFs > (? does that also cover modified params?). > > At propagation time when applying the jump-function we have to make > sure to first convert the actual parameter value to that expected type > (or drop to BOTTOM if we can't do that conversion due to excess mismatches). > I wanted to have a look at this myself for some time but the omp-low splitting took far more time than I had anticipated and so it took my until yesterday evening to come up with "my fix" which you can find below. It has the added benefit of also fixing PR 78599. The patch removes the LTO WPA attempt to figure out types of actual arguments from TYPE_ARG_TYPES and instead it adds streaming them into node summaries, i.e. they come from the compile time unit with the actual function definition (as opposed to the information we have at call-sites when building jump functions). Because in various corner cases and plain-garbage-code cases the types of the actual and formal arguments can be quite different, especially with LTO, I have reorganized propagate_vr_accross_jump_function so that it uses extract_range_from_unary_expr in all but the IPA_JF_PASS_THROUGH cases, because those rely on fold_convert. In order to have all the information for extract_range_from_unary_expr, I needed to stream also the type of the actual argument, which hitherto we did not have for the cases when the jump function was IPA_JF_UNKNOWN but still had vr_known set (and thus did contain any info for constant propagation but still some info about VR). I am not happy about adding another field to this data structure but at this point see not way around it. Perhaps propagate_vr_accross_jump_function can now be simplified further, running extract_range_from_unary_expr pretty much always (or only when the types are not useless_type_conversion_p). But I think I should post what I have now. The patch passes bootstrap, lto-boostrap (of C, C++ and Fortran) and testing on x86_64-linux. What do you think? Martin 2016-12-13 Martin Jambor PR ipa/78365 * ipa-prop.h (ipa_jump_func): New field pased_type. * ipa-cp.c (ipa_vr_operation_and_type_effects): New function. (propagate_vr_accross_jump_function): Use the above function for all value range computations for pass-through jump functions and type converasion from explicit value range values. (ipcp_propagate_stage): Do not attempt to deduce types of formal parameters from TYPE_ARG_TYPES. * ipa-prop.c (ipa_compute_jump_functions_for_edge): Set jfunc->passed_type whenever setting jfunc->vr_known to true. (ipa_write_jump_function): Remove trailing whitespace, stream passed_type. (ipa_read_jump_function): Stream passed_type. (ipa_write_node_info): Stream type of the actual argument. (ipa_read_node_info): Likewise. Also remove trailing whitespace. testsuite/ * gcc.dg/torture/pr78365.c: New test. --- gcc/ipa-cp.c | 70 +++++++++++++++++----------------- gcc/ipa-prop.c | 22 ++++++++--- gcc/ipa-prop.h | 3 ++ gcc/testsuite/gcc.dg/torture/pr78365.c | 21 ++++++++++ 4 files changed, 75 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr78365.c diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 4ec7cc5..7e6fc9a 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1839,6 +1839,23 @@ propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *j return dest_lattice->set_to_bottom (); } +/* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to + DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if + the result is a range or an anti-range. */ + +static bool +ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, + enum tree_code operation, + tree dst_type, tree src_type) +{ + memset (dst_vr, 0, sizeof (*dst_vr)); + extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); + if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE) + return true; + else + return false; +} + /* Propagate value range across jump function JFUNC that is associated with edge CS with param of callee of PARAM_TYPE and update DEST_PLATS accordingly. */ @@ -1849,7 +1866,6 @@ propagate_vr_accross_jump_function (cgraph_edge *cs, struct ipcp_param_lattices *dest_plats, tree param_type) { - struct ipcp_param_lattices *src_lats; ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; if (dest_lat->bottom_p ()) @@ -1862,31 +1878,23 @@ propagate_vr_accross_jump_function (cgraph_edge *cs, if (jfunc->type == IPA_JF_PASS_THROUGH) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); - int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); - src_lats = ipa_get_parm_lattices (caller_info, src_idx); + enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); - if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) - return dest_lat->meet_with (src_lats->m_value_range); - else if (param_type - && (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) - == tcc_unary)) + if (TREE_CODE_CLASS (operation) == tcc_unary) { - value_range vr; - memset (&vr, 0, sizeof (vr)); + struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); tree operand_type = ipa_get_type (caller_info, src_idx); - enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); + struct ipcp_param_lattices *src_lats + = ipa_get_parm_lattices (caller_info, src_idx); if (src_lats->m_value_range.bottom_p ()) return dest_lat->set_to_bottom (); - - extract_range_from_unary_expr (&vr, - operation, - param_type, - &src_lats->m_value_range.m_vr, - operand_type); - if (vr.type == VR_RANGE - || vr.type == VR_ANTI_RANGE) + value_range vr; + if (ipa_vr_operation_and_type_effects (&vr, + &src_lats->m_value_range.m_vr, + operation, param_type, + operand_type)) return dest_lat->meet_with (&vr); } } @@ -1906,8 +1914,11 @@ propagate_vr_accross_jump_function (cgraph_edge *cs, } } - if (jfunc->vr_known) - return dest_lat->meet_with (&jfunc->m_vr); + value_range vr; + if (jfunc->vr_known + && ipa_vr_operation_and_type_effects (&vr, &jfunc->m_vr, NOP_EXPR, + param_type, jfunc->passed_type)) + return dest_lat->meet_with (&vr); else return dest_lat->set_to_bottom (); } @@ -2247,7 +2258,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) { struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); struct ipcp_param_lattices *dest_plats; - tree param_type = ipa_get_callee_param_type (cs, i); + tree param_type = ipa_get_type (callee_info, i); dest_plats = ipa_get_parm_lattices (callee_info, i); if (availability == AVAIL_INTERPOSABLE) @@ -3234,19 +3245,6 @@ ipcp_propagate_stage (struct ipa_topo_info *topo) { struct ipa_node_params *info = IPA_NODE_REF (node); - /* In LTO we do not have PARM_DECLs but we would still like to be able to - look at types of parameters. */ - if (in_lto_p) - { - tree t = TYPE_ARG_TYPES (TREE_TYPE (node->decl)); - for (int k = 0; k < ipa_get_param_count (info) && t; k++) - { - gcc_assert (t != void_list_node); - info->descriptors[k].decl_or_type = TREE_VALUE (t); - t = t ? TREE_CHAIN (t) : NULL; - } - } - determine_versionability (node, info); if (node->has_gimple_body_p ()) { diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 642111d..123d422 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -1751,6 +1751,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, jfunc->m_vr.min = build_int_cst (TREE_TYPE (arg), 0); jfunc->m_vr.max = build_int_cst (TREE_TYPE (arg), 0); jfunc->m_vr.equiv = NULL; + jfunc->passed_type = TREE_TYPE (arg); } else gcc_assert (!jfunc->vr_known); @@ -1776,7 +1777,10 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, &vr, TREE_TYPE (arg)); if (jfunc->m_vr.type == VR_RANGE || jfunc->m_vr.type == VR_ANTI_RANGE) - jfunc->vr_known = true; + { + jfunc->vr_known = true; + jfunc->passed_type = TREE_TYPE (arg); + } else jfunc->vr_known = false; } @@ -4775,7 +4779,7 @@ ipa_write_jump_function (struct output_block *ob, { streamer_write_widest_int (ob, jump_func->bits.value); streamer_write_widest_int (ob, jump_func->bits.mask); - } + } bp_pack_value (&bp, jump_func->vr_known, 1); streamer_write_bitpack (&bp); if (jump_func->vr_known) @@ -4784,6 +4788,7 @@ ipa_write_jump_function (struct output_block *ob, VR_LAST, jump_func->m_vr.type); stream_write_tree (ob, jump_func->m_vr.min, true); stream_write_tree (ob, jump_func->m_vr.max, true); + stream_write_tree (ob, jump_func->passed_type, true); } } @@ -4877,6 +4882,7 @@ ipa_read_jump_function (struct lto_input_block *ib, VR_LAST); jump_func->m_vr.min = stream_read_tree (ib, data_in); jump_func->m_vr.max = stream_read_tree (ib, data_in); + jump_func->passed_type = stream_read_tree (ib, data_in); } else jump_func->vr_known = false; @@ -4973,7 +4979,10 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) bp_pack_value (&bp, ipa_is_param_used (info, j), 1); streamer_write_bitpack (&bp); for (j = 0; j < ipa_get_param_count (info); j++) - streamer_write_hwi (ob, ipa_get_controlled_uses (info, j)); + { + streamer_write_hwi (ob, ipa_get_controlled_uses (info, j)); + stream_write_tree (ob, ipa_get_type (info, j), true); + } for (e = node->callees; e; e = e->next_callee) { struct ipa_edge_args *args = IPA_EDGE_REF (e); @@ -5020,7 +5029,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, for (k = 0; k < ipa_get_param_count (info); k++) info->descriptors[k].move_cost = streamer_read_uhwi (ib); - + bp = streamer_read_bitpack (ib); if (ipa_get_param_count (info) != 0) info->analysis_done = true; @@ -5028,7 +5037,10 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, for (k = 0; k < ipa_get_param_count (info); k++) ipa_set_param_used (info, k, bp_unpack_value (&bp, 1)); for (k = 0; k < ipa_get_param_count (info); k++) - ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); + { + ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); + info->descriptors[k].decl_or_type = stream_read_tree (ib, data_in); + } for (e = node->callees; e; e = e->next_callee) { struct ipa_edge_args *args = IPA_EDGE_REF (e); diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 0e75cf4..e4de8ed 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -181,6 +181,9 @@ struct GTY (()) ipa_jump_func /* Information about value range. */ bool vr_known; value_range m_vr; + /* If value range is known, this is the type in which we pass the date at the + caller side. */ + tree passed_type; enum jump_func_type type; /* Represents a value of a jump function. pass_through is used only in jump diff --git a/gcc/testsuite/gcc.dg/torture/pr78365.c b/gcc/testsuite/gcc.dg/torture/pr78365.c new file mode 100644 index 0000000..5180a01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr78365.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +int a, b, c; +char d; +static void fn1 (void *, int); +int fn2 (int); + +void fn1 (cc, yh) void *cc; +char yh; +{ + char y; + a = fn2(c - b + 1); + for (; y <= yh; y++) + ; +} + +void fn3() +{ + fn1((void *)fn3, 1); + fn1((void *)fn3, d - 1); +}