From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 50019 invoked by alias); 20 Dec 2018 22:43:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 49194 invoked by uid 89); 20 Dec 2018 22:43:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.2 spammy=filled, ith X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 20 Dec 2018 22:43:26 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id C6F87AEEC for ; Thu, 20 Dec 2018 22:43:23 +0000 (UTC) From: Martin Jambor To: Jan Hubicka Cc: GCC Patches Subject: [PATCH] Avoid carrying around jump functions with no information User-Agent: Notmuch/0.26 (https://notmuchmail.org) Emacs/26.1 (x86_64-suse-linux-gnu) Date: Thu, 20 Dec 2018 23:14:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes X-SW-Source: 2018-12/txt/msg01515.txt.bz2 Hi Honza, the patch below avoids keeping jump functions that do not hold any interesting value. For all users such dropped jump function vectors will then appear as empty ones, which they should handle gracefully because they already can deal with parameter count mismatches (especially during LTO). It also changes the vector allocation to use vec_safe_reserve_exact, which could save a few bytes here and there too. I have bootstrapped and tested it on x86-64-linux, LTO bootstrap is in progress. If you like it and if it helps with memory use, feel free to commit it to trunk. Martin 2018-12-20 Martin Jambor * ipa-prop.c (determine_locally_known_aggregate_parts): Return true iff any aggregate value has been discovered. (ipa_compute_jump_functions_for_edge): Assert that jump_functions have not been already calculated, use vec_safe_reserve_exact to allocate vectors, only store them if there is a useful value. --- gcc/ipa-prop.c | 98 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 05e666e0588..402f8cbd969 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -1541,9 +1541,10 @@ build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list, in ARG is filled in with constant values. ARG can either be an aggregate expression or a pointer to an aggregate. ARG_TYPE is the type of the aggregate. JFUNC is the jump function into which the constants are - subsequently stored. */ + subsequently stored. Return true if any known aggregate value has been + discovered. */ -static void +static bool determine_locally_known_aggregate_parts (gcall *call, tree arg, tree arg_type, struct ipa_jump_func *jfunc) @@ -1557,7 +1558,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, ao_ref r; if (PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS) == 0) - return; + return false; /* The function operates in three stages. First, we prepare check_ref, r, arg_base and arg_offset based on what is actually passed as an actual @@ -1571,7 +1572,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, tree type_size; if (!tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type))) || !POINTER_TYPE_P (TREE_TYPE (arg))) - return; + return false; check_ref = true; arg_base = arg; arg_offset = 0; @@ -1587,17 +1588,17 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset, &arg_size, &reverse); if (!arg_base) - return; + return false; if (DECL_P (arg_base)) { check_ref = false; ao_ref_init (&r, arg_base); } else - return; + return false; } else - return; + return false; } else { @@ -1610,7 +1611,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset, &arg_size, &reverse); if (!arg_base) - return; + return false; ao_ref_init (&r, arg); } @@ -1697,7 +1698,9 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, { jfunc->agg.by_ref = by_ref; build_agg_jump_func_from_list (list, const_count, arg_offset, jfunc); + return true; } + return false; } /* Return the Ith param type of callee associated with call graph @@ -1827,18 +1830,24 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, struct ipa_edge_args *args = IPA_EDGE_REF (cs); gcall *call = cs->call_stmt; int n, arg_num = gimple_call_num_args (call); + bool useful_value = false; bool useful_context = false; - if (arg_num == 0 || args->jump_functions) + if (arg_num == 0 + || gimple_call_internal_p (call) + || ipa_func_spec_opts_forbid_analysis_p (cs->caller)) return; - vec_safe_grow_cleared (args->jump_functions, arg_num); - if (flag_devirtualize) - vec_safe_grow_cleared (args->polymorphic_call_contexts, arg_num); + gcc_checking_assert (!args->jump_functions + && !args->polymorphic_call_contexts); - if (gimple_call_internal_p (call)) - return; - if (ipa_func_spec_opts_forbid_analysis_p (cs->caller)) - return; + vec_safe_reserve_exact (args->jump_functions, arg_num); + args->jump_functions->quick_grow_cleared (arg_num); + + if (flag_devirtualize) + { + vec_safe_reserve_exact (args->polymorphic_call_contexts, arg_num); + vec_safe_grow_cleared (args->polymorphic_call_contexts, arg_num); + } for (n = 0; n < arg_num; n++) { @@ -1873,6 +1882,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, { tree z = build_int_cst (TREE_TYPE (arg), 0); ipa_set_jfunc_vr (jfunc, VR_ANTI_RANGE, z, z); + useful_value = true; } else gcc_assert (!jfunc->m_vr); @@ -1893,7 +1903,10 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, extract_range_from_unary_expr (&resvr, NOP_EXPR, param_type, &tmpvr, TREE_TYPE (arg)); if (!resvr.undefined_p () && !resvr.varying_p ()) - ipa_set_jfunc_vr (jfunc, &resvr); + { + ipa_set_jfunc_vr (jfunc, &resvr); + useful_value = true; + } else gcc_assert (!jfunc->m_vr); } @@ -1905,11 +1918,20 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, && (TREE_CODE (arg) == SSA_NAME || TREE_CODE (arg) == INTEGER_CST)) { if (TREE_CODE (arg) == SSA_NAME) - ipa_set_jfunc_bits (jfunc, 0, - widest_int::from (get_nonzero_bits (arg), - TYPE_SIGN (TREE_TYPE (arg)))); + { + widest_int nonzero_bits + = widest_int::from (get_nonzero_bits (arg), + TYPE_SIGN (TREE_TYPE (arg))); + ipa_set_jfunc_bits (jfunc, 0, nonzero_bits); + if (SSA_NAME_RANGE_INFO (arg) + && nonzero_bits != -1) + useful_value = true; + } else - ipa_set_jfunc_bits (jfunc, wi::to_widest (arg), 0); + { + ipa_set_jfunc_bits (jfunc, wi::to_widest (arg), 0); + useful_value = true; + } } else if (POINTER_TYPE_P (TREE_TYPE (arg))) { @@ -1917,6 +1939,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, unsigned align; get_pointer_alignment_1 (arg, &align, &bitpos); + if (align != BITS_PER_UNIT) + useful_value = true; widest_int mask = wi::bit_and_not (wi::mask (TYPE_PRECISION (TREE_TYPE (arg)), false), align / BITS_PER_UNIT - 1); @@ -1930,7 +1954,10 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, || (VAR_P (arg) && is_global_var (arg) && TREE_READONLY (arg))) - ipa_set_jf_constant (jfunc, arg, cs); + { + ipa_set_jf_constant (jfunc, arg, cs); + useful_value = true; + } else if (!is_gimple_reg_type (TREE_TYPE (arg)) && TREE_CODE (arg) == PARM_DECL) { @@ -1943,6 +1970,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, if (parm_preserved_before_stmt_p (fbi, index, call, arg)) { ipa_set_jf_simple_pass_through (jfunc, index, false); + useful_value = true; continue; } } @@ -1956,6 +1984,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, bool agg_p; agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg); ipa_set_jf_simple_pass_through (jfunc, index, agg_p); + useful_value = true; } } else @@ -1969,14 +1998,17 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, call, as_a (stmt)); } + if (jfunc->type != IPA_JF_UNKNOWN) + useful_value = true; } - /* If ARG is pointer, we can not use its type to determine the type of aggregate - passed (because type conversions are ignored in gimple). Usually we can - safely get type from function declaration, but in case of K&R prototypes or - variadic functions we can try our luck with type of the pointer passed. - TODO: Since we look for actual initialization of the memory object, we may better - work out the type based on the memory stores we find. */ + /* If ARG is pointer, we can not use its type to determine the type of + aggregate passed (because type conversions are ignored in gimple). + Usually we can safely get type from function declaration, but in case + of K&R prototypes or variadic functions we can try our luck with type + of the pointer passed. + TODO: Since we look for actual initialization of the memory object, we + may better work out the type based on the memory stores we find. */ if (!param_type) param_type = TREE_TYPE (arg); @@ -1986,8 +2018,16 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, || !ipa_get_jf_ancestor_agg_preserved (jfunc)) && (AGGREGATE_TYPE_P (TREE_TYPE (arg)) || POINTER_TYPE_P (param_type))) - determine_locally_known_aggregate_parts (call, arg, param_type, jfunc); + { + if (determine_locally_known_aggregate_parts (call, arg, param_type, + jfunc)) + useful_value = true; + } } + + if (!useful_value) + vec_free (args->jump_functions); + if (!useful_context) vec_free (args->polymorphic_call_contexts); } -- 2.19.2