From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 124119 invoked by alias); 25 Feb 2015 09:41:13 -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 124108 invoked by uid 89); 25 Feb 2015 09:41:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 25 Feb 2015 09:41:11 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t1P9f8OI008143 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Wed, 25 Feb 2015 04:41:08 -0500 Received: from freie.home (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t1P9exRw008398 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 25 Feb 2015 04:41:08 -0500 Received: from livre.home (livre.home [172.31.160.2]) by freie.home (8.14.8/8.14.8) with ESMTP id t1P9egd7011807; Wed, 25 Feb 2015 06:40:42 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR58315] reset inlined debug vars at return-to point Date: Wed, 25 Feb 2015 10:06:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2015-02/txt/msg01458.txt.bz2 This patch fixes a problem that has been with us for several years. Variable tracking has no idea about the end of the lifetime of inlined variables, so it keeps on computing locations for them over and over, even though the computed locations make no sense whatsoever because the variable can't even be accessed any more. With this patch, we unbind all inlined variables at the point the inlined function returns to, so that the locations for those variables will not be touched any further. In theory, we could do something similar to non-inlined auto variables, when they go out of scope, but their decls apply to the entire function and I'm told gdb sort-of expects the variables to be accessible throughout the function, so I'm not tackling that in this patch, for I'm happy enough with what this patch gets us: - almost 99% reduction in the output asm for the PR testcase - more than 90% reduction in the peak memory use compiling that testcase - 63% reduction in the compile time for that testcase What's scary is that the testcase is not particularly pathological. Any function that calls a longish sequence of inlined functions, that in turn call other inline functions, and so on, something that's not particularly unusual in C++, will likely observe significant improvement, as we won't see growing sequences of var_location notes after each call or so, as var-tracking computes a new in-stack location for the implicit this argument of each previously-inlined function. Regstrapped on x86_64-linux-gnu and i686-linux-gnu. Ok to install? Reset inlined debug variables at the end of the inlined function From: Alexandre Oliva for gcc/ChangeLog PR debug/58315 * tree-inline.c (reset_debug_binding): New. (reset_debug_bindings): Likewise. (expand_call_inline): Call it. --- gcc/tree-inline.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index d8abe03..5b58d8b 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4345,6 +4345,60 @@ add_local_variables (struct function *callee, struct function *caller, } } +/* Add to BINDINGS a debug stmt resetting SRCVAR if inlining might + have brought in or introduced any debug stmts for SRCVAR. */ + +static inline void +reset_debug_binding (copy_body_data *id, tree srcvar, gimple_seq *bindings) +{ + tree *remappedvarp = id->decl_map->get (srcvar); + + if (!remappedvarp) + return; + + if (TREE_CODE (*remappedvarp) != VAR_DECL) + return; + + if (*remappedvarp == id->retvar || *remappedvarp == id->retbnd) + return; + + tree tvar = target_for_debug_bind (*remappedvarp); + if (!tvar) + return; + + gdebug *stmt = gimple_build_debug_bind (tvar, NULL_TREE, + id->call_stmt); + gimple_seq_add_stmt (bindings, stmt); +} + +/* For each inlined variable for which we may have debug bind stmts, + add before GSI a final debug stmt resetting it, marking the end of + its life, so that var-tracking knows it doesn't have to compute + further locations for it. */ + +static inline void +reset_debug_bindings (copy_body_data *id, gimple_stmt_iterator gsi) +{ + tree var; + unsigned ix; + gimple_seq bindings = NULL; + + if (!gimple_in_ssa_p (id->src_cfun)) + return; + + if (!opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) + return; + + for (var = DECL_ARGUMENTS (id->src_fn); + var; var = DECL_CHAIN (var)) + reset_debug_binding (id, var, &bindings); + + FOR_EACH_LOCAL_DECL (id->src_cfun, ix, var) + reset_debug_binding (id, var, &bindings); + + gsi_insert_seq_before_without_update (&gsi, bindings, GSI_SAME_STMT); +} + /* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */ static bool @@ -4650,6 +4704,8 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) GCOV_COMPUTE_SCALE (cg_edge->frequency, CGRAPH_FREQ_BASE), bb, return_block, NULL); + reset_debug_bindings (id, stmt_gsi); + /* Reset the escaped solution. */ if (cfun->gimple_df) pt_solution_reset (&cfun->gimple_df->escaped); -- Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ You must be the change you wish to see in the world. -- Gandhi Be Free! -- http://FSFLA.org/ FSF Latin America board member Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer