From patchwork Sun Nov 3 13:51:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 1188556 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-512274-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ucw.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="A6ekQJ2V"; dkim-atps=neutral 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 475cm05rkFz9sP4 for ; Mon, 4 Nov 2019 00:51:26 +1100 (AEDT) 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:subject:message-id:mime-version:content-type; q=dns; s= default; b=tFaaoyDvMs5mCfKT1+HcQlYjVeeoMWlXEfFpuTFVXoDDgxyhVsjGy rR94dRi+JrtUiiihLdtjGRVVTctja+GZS/1tGxbdxN6+QkDcBSSu/HuRTu8zYGvZ pK7J7nr2wOiApq/YMUwZEx2so7RjPnELjE5WSa24tH8yTxEQz8Jpzo= 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:subject:message-id:mime-version:content-type; s= default; bh=bRi0KlL3xeJOGgLnZiXlGLqzcls=; b=A6ekQJ2VxQPWgZjcRMsG oe8dNe+DwrgYehieyQeuKdQMqz46L12ISMucQRh1VzcsJSNUCCrHEKVMzEL+V1Xp 3OMYgM7MDusZi0qJ35kaXJdc4PEBLGlsNEaTuadqDMJ84CwpYc1Vj7b/zkdhI6V5 riYb5BCBivAIENuHjIv4r9U= Received: (qmail 18798 invoked by alias); 3 Nov 2019 13:51:17 -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 18789 invoked by uid 89); 3 Nov 2019 13:51:16 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS autolearn=ham version=3.3.1 spammy=owned, calculated, nonNULL, non-null X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 03 Nov 2019 13:51:11 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id D067B282BE5; Sun, 3 Nov 2019 14:51:08 +0100 (CET) Date: Sun, 3 Nov 2019 14:51:08 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Introduce ipa_inline_call_context class Message-ID: <20191103135108.nuptw2xv3fhxphsk@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20170113 (1.7.2) Hi, this patch refactors estimate_node_size_and_time so we can store the context call size/time estimates was calculated for. The goal is to prevent recalculation of these properties for calls from different call sites but with same context and instead cache the results. Honza Bootstrapped/regtested x86_64-linux, will commit it shortly. * ipa-fnsummary.c (ipa_call_context): New constructor. (estimate_node_size_and_time): Turn to ... (ipa_call_context::estimate_size_and_time): ... this one. (ipa_call_context::release): New. * ipa-fnsummary.h (ipa_call_context): New class. (estimate_node_size_and_time): Remove. (do_estimate_edge_time, do_estimate_edge_size, do_estimate_edge_hints): Update. =================================================================== --- ipa-fnsummary.c (revision 277753) +++ ipa-fnsummary.c (working copy) @@ -2940,31 +2940,54 @@ estimate_calls_size_and_time (struct cgr } } +/* Default constructor for ipa call context. + Memory alloction of known_vals, known_contexts + and known_aggs vectors is owned by the caller, but can + be release by ipa_call_context::release. + + inline_param_summary is owned by the caller. */ +ipa_call_context::ipa_call_context (cgraph_node *node, + clause_t possible_truths, + clause_t nonspec_possible_truths, + vec known_vals, + vec + known_contexts, + vec known_aggs, + vec + inline_param_summary) +: m_node (node), m_possible_truths (possible_truths), + m_nonspec_possible_truths (nonspec_possible_truths), + m_inline_param_summary (inline_param_summary), + m_known_vals (known_vals), + m_known_contexts (known_contexts), + m_known_aggs (known_aggs) +{ +} + +/* Release memory used by known_vals/contexts/aggs vectors. */ + +void +ipa_call_context::release () +{ + m_known_vals.release (); + m_known_contexts.release (); + m_known_aggs.release (); +} -/* Estimate size and time needed to execute NODE assuming - POSSIBLE_TRUTHS clause, and KNOWN_VALS, KNOWN_AGGS and KNOWN_CONTEXTS - information about NODE's arguments. If non-NULL use also probability - information present in INLINE_PARAM_SUMMARY vector. +/* Estimate size and time needed to execute call in the given context. Additionally detemine hints determined by the context. Finally compute minimal size needed for the call that is independent on the call context and can be used for fast estimates. Return the values in RET_SIZE, RET_MIN_SIZE, RET_TIME and RET_HINTS. */ void -estimate_node_size_and_time (struct cgraph_node *node, - clause_t possible_truths, - clause_t nonspec_possible_truths, - vec known_vals, - vec known_contexts, - vec known_aggs, - int *ret_size, int *ret_min_size, - sreal *ret_time, - sreal *ret_nonspecialized_time, - ipa_hints *ret_hints, - vec - inline_param_summary) +ipa_call_context::estimate_size_and_time (int *ret_size, + int *ret_min_size, + sreal *ret_time, + sreal *ret_nonspecialized_time, + ipa_hints *ret_hints) { - class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); + class ipa_fn_summary *info = ipa_fn_summaries->get_create (m_node); size_time_entry *e; int size = 0; sreal time = 0; @@ -2976,13 +2999,13 @@ estimate_node_size_and_time (struct cgra { bool found = false; fprintf (dump_file, " Estimating body: %s/%i\n" - " Known to be false: ", node->name (), - node->order); + " Known to be false: ", m_node->name (), + m_node->order); for (i = predicate::not_inlined_condition; i < (predicate::first_dynamic_condition + (int) vec_safe_length (info->conds)); i++) - if (!(possible_truths & (1 << i))) + if (!(m_possible_truths & (1 << i))) { if (found) fprintf (dump_file, ", "); @@ -2991,19 +3014,19 @@ estimate_node_size_and_time (struct cgra } } - estimate_calls_size_and_time (node, &size, &min_size, &time, &hints, possible_truths, - known_vals, known_contexts, known_aggs); + estimate_calls_size_and_time (m_node, &size, &min_size, &time, &hints, m_possible_truths, + m_known_vals, m_known_contexts, m_known_aggs); sreal nonspecialized_time = time; for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++) { - bool exec = e->exec_predicate.evaluate (nonspec_possible_truths); + bool exec = e->exec_predicate.evaluate (m_nonspec_possible_truths); /* Because predicates are conservative, it can happen that nonconst is 1 but exec is 0. */ if (exec) { - bool nonconst = e->nonconst_predicate.evaluate (possible_truths); + bool nonconst = e->nonconst_predicate.evaluate (m_possible_truths); gcc_checking_assert (e->time >= 0); gcc_checking_assert (time >= 0); @@ -3019,7 +3042,7 @@ estimate_node_size_and_time (struct cgra nonspecialized_time += e->time; if (!nonconst) ; - else if (!inline_param_summary.exists ()) + else if (!m_inline_param_summary.exists ()) { if (nonconst) time += e->time; @@ -3027,8 +3050,8 @@ estimate_node_size_and_time (struct cgra else { int prob = e->nonconst_predicate.probability - (info->conds, possible_truths, - inline_param_summary); + (info->conds, m_possible_truths, + m_inline_param_summary); gcc_checking_assert (prob >= 0); gcc_checking_assert (prob <= REG_BR_PROB_BASE); time += e->time * prob / REG_BR_PROB_BASE; @@ -3052,14 +3075,14 @@ estimate_node_size_and_time (struct cgra time = nonspecialized_time; if (info->loop_iterations - && !info->loop_iterations->evaluate (possible_truths)) + && !info->loop_iterations->evaluate (m_possible_truths)) hints |= INLINE_HINT_loop_iterations; if (info->loop_stride - && !info->loop_stride->evaluate (possible_truths)) + && !info->loop_stride->evaluate (m_possible_truths)) hints |= INLINE_HINT_loop_stride; if (info->scc_no) hints |= INLINE_HINT_in_scc; - if (DECL_DECLARED_INLINE_P (node->decl)) + if (DECL_DECLARED_INLINE_P (m_node->decl)) hints |= INLINE_HINT_declared_inline; size = RDIV (size, ipa_fn_summary::size_scale); @@ -3101,10 +3124,11 @@ estimate_ipcp_clone_size_and_time (struc evaluate_conditions_for_known_args (node, false, known_vals, known_aggs, &clause, &nonspec_clause); - estimate_node_size_and_time (node, clause, nonspec_clause, - known_vals, known_contexts, - known_aggs, ret_size, NULL, ret_time, - ret_nonspec_time, hints, vNULL); + ipa_call_context ctx (node, clause, nonspec_clause, + known_vals, known_contexts, + known_aggs, vNULL); + ctx.estimate_size_and_time (ret_size, NULL, ret_time, + ret_nonspec_time, hints); } /* Return stack frame offset where frame of NODE is supposed to start inside Index: ipa-fnsummary.h =================================================================== --- ipa-fnsummary.h (revision 277753) +++ ipa-fnsummary.h (working copy) @@ -281,6 +281,47 @@ public: ipa_call_summary *dst_data); }; +/* This object describe a context of call. That is a summary of known + information about its parameters. Main purpose of this context is + to give more realistic esitmations of function runtime, size and + inline hints. */ +class ipa_call_context +{ +public: + ipa_call_context (cgraph_node *node, + clause_t possible_truths, + clause_t nonspec_possible_truths, + vec known_vals, + vec known_contexts, + vec known_aggs, + vec m_inline_param_summary); + void estimate_size_and_time (int *ret_size, int *ret_min_size, + sreal *ret_time, + sreal *ret_nonspecialized_time, + ipa_hints *ret_hints); + void release (); +private: + /* Called function. */ + cgraph_node *m_node; + /* Clause describing what predicate conditionals can be satisfied + in this context if function is inlined/specialised. */ + clause_t m_possible_truths; + /* Clause describing what predicate conditionals can be satisfied + in this context if function is kept offline. */ + clause_t m_nonspec_possible_truths; + /* Inline summary maintains info about change probabilities. */ + vec m_inline_param_summary; + + /* The following is used only to resolve indirect calls. */ + + /* Vector describing known values of parameters. */ + vec m_known_vals; + /* Vector describing known polymorphic call contexts. */ + vec m_known_contexts; + /* Vector describing known aggregate values. */ + vec m_known_aggs; +}; + extern fast_call_summary *ipa_call_summaries; /* In ipa-fnsummary.c */ @@ -302,25 +343,14 @@ void ipa_update_overall_fn_summary (stru void compute_fn_summary (struct cgraph_node *, bool); -void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, +void evaluate_properties_for_edge (struct cgraph_edge *e, + bool inline_p, clause_t *clause_ptr, clause_t *nonspec_clause_ptr, vec *known_vals_ptr, vec *known_contexts_ptr, vec *); -void estimate_node_size_and_time (struct cgraph_node *node, - clause_t possible_truths, - clause_t nonspec_possible_truths, - vec known_vals, - vec, - vec known_aggs, - int *ret_size, int *ret_min_size, - sreal *ret_time, - sreal *ret_nonspecialized_time, - ipa_hints *ret_hints, - vec - inline_param_summary); void ipa_fnsummary_c_finalize (void); HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node); Index: ipa-inline-analysis.c =================================================================== --- ipa-inline-analysis.c (revision 277753) +++ ipa-inline-analysis.c (working copy) @@ -137,9 +137,10 @@ do_estimate_edge_time (struct cgraph_edg evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause, &known_vals, &known_contexts, &known_aggs); - estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, - known_contexts, known_aggs, &size, &min_size, - &time, &nonspec_time, &hints, es->param); + ipa_call_context ctx (callee, clause, nonspec_clause, known_vals, + known_contexts, known_aggs, es->param); + ctx.estimate_size_and_time (&size, &min_size, + &time, &nonspec_time, &hints); /* When we have profile feedback, we can quite safely identify hot edges and for those we disable size limits. Don't do that when @@ -152,9 +153,7 @@ do_estimate_edge_time (struct cgraph_edg : edge->caller->count.ipa ()))) hints |= INLINE_HINT_known_hot; - known_vals.release (); - known_contexts.release (); - known_aggs.release (); + ctx.release (); gcc_checking_assert (size >= 0); gcc_checking_assert (time >= 0); @@ -207,12 +206,10 @@ do_estimate_edge_size (struct cgraph_edg &clause, &nonspec_clause, &known_vals, &known_contexts, &known_aggs); - estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, - known_contexts, known_aggs, &size, NULL, NULL, - NULL, NULL, vNULL); - known_vals.release (); - known_contexts.release (); - known_aggs.release (); + ipa_call_context ctx (callee, clause, nonspec_clause, known_vals, + known_contexts, known_aggs, vNULL); + ctx.estimate_size_and_time (&size, NULL, NULL, NULL, NULL); + ctx.release (); return size; } @@ -248,12 +245,10 @@ do_estimate_edge_hints (struct cgraph_ed &clause, &nonspec_clause, &known_vals, &known_contexts, &known_aggs); - estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, - known_contexts, known_aggs, NULL, NULL, - NULL, NULL, &hints, vNULL); - known_vals.release (); - known_contexts.release (); - known_aggs.release (); + ipa_call_context ctx (callee, clause, nonspec_clause, known_vals, + known_contexts, known_aggs, vNULL); + ctx.estimate_size_and_time (NULL, NULL, NULL, NULL, &hints); + ctx.release (); hints |= simple_edge_hints (edge); return hints; }