From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 51226 invoked by alias); 24 Jul 2018 11:37:20 -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 51216 invoked by uid 89); 24 Jul 2018 11:37:20 -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=fake 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; Tue, 24 Jul 2018 11:37:18 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id EB4A0AD53; Tue, 24 Jul 2018 11:37:15 +0000 (UTC) Date: Tue, 24 Jul 2018 11:37:00 -0000 From: Tom de Vries To: Richard Biener Cc: gcc-patches@gcc.gnu.org, Jakub Jelinek , Jim Wilson , aoliva@redhat.com Subject: [RFC 2/3, debug] Add fkeep-vars-live Message-ID: <20180724113732.xo4av4fcbgigi7w2@delia> References:<20180716132909.633uvqxojzgg3wg6@delia> <0e82c00b-a8fc-9f8a-0115-9f7254e1bde1@suse.de> <16bec84d-f6e8-60be-c764-83eb4861b515@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To:<16bec84d-f6e8-60be-c764-83eb4861b515@suse.de> User-Agent: NeoMutt/20170912 (1.9.0) X-IsSubscribed: yes X-SW-Source: 2018-07/txt/msg01369.txt.bz2 On Tue, Jul 24, 2018 at 01:30:30PM +0200, Tom de Vries wrote: > On 07/16/2018 05:10 PM, Tom de Vries wrote: > > On 07/16/2018 03:50 PM, Richard Biener wrote: > >> On Mon, 16 Jul 2018, Tom de Vries wrote: > >>> Any comments? > >> > >> Interesting idea. I wonder if that should be generalized > >> to other places > > > > I kept the option name general, to allow for that. > > > > And indeed, this is a point-fix patch. I've been playing around with a > > more generic patch that adds nops such that each is_stmt .loc is > > associated with a unique insn, but that was embedded in an > > fkeep-vars-live branch, so this patch is minimally addressing the first > > problem I managed to reproduce on trunk. > > > >> and how we can avoid compare-debug failures > >> (var-tracking usually doesn't change code-generation). > >> > > > > I'll post this patch series (the current state of my fkeep-vars-live > branch) in reply to this email: > > 1 [debug] Add fdebug-nops > 2 [debug] Add fkeep-vars-live > 3 [debug] Add fdebug-nops and fkeep-vars-live to Og only > > Bootstrapped and reg-tested on x86_64. ChangeLog entries and function > header comments missing. > > Comments welcome. > This patch adds fake uses of user variables at the point where they go out of scope, to keep user variables inspectable throughout the application. This approach will generate sub-optimal code: in some cases, the executable code will go through efforts to keep a var alive, while var-tracking can easily compute the value of the var from something else. Also, the compiler treats the fake use as any other use, so it may keep an expensive resource like a register occupied (if we could mark the use as a cold use or some such, we could tell optimizers that we need the value, but it's ok if getting the value is expensive, so it could be spilled instead of occupying a register). The current implementation is expected to increase register pressure, and therefore spilling, but we'd still expect less memory accesses then with O0. Another drawback is that the fake uses confuse the unitialized warning analysis, so that is switched off for -fkeep-vars-live. PR debug/78685 [debug] Add fkeep-vars-live --- gcc/cfgexpand.c | 9 +++++++ gcc/common.opt | 4 +++ gcc/function.c | 5 ++-- gcc/gimplify.c | 44 +++++++++++++++++++++++++++----- gcc/testsuite/gcc.dg/guality/pr54200-2.c | 3 +-- gcc/tree-cfg.c | 1 + gcc/tree-sra.c | 7 +++++ gcc/tree-ssa-alias.c | 4 +++ gcc/tree-ssa-structalias.c | 3 ++- gcc/tree-ssa-uninit.c | 2 +- 10 files changed, 70 insertions(+), 12 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index d6e3c382085..eb9e36a8c5b 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -3533,6 +3533,13 @@ expand_clobber (tree lhs) } } +static void +expand_use (tree rhs) +{ + rtx target = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_NORMAL); + emit_use (target); +} + /* A subroutine of expand_gimple_stmt, expanding one gimple statement STMT that doesn't require special handling for outgoing edges. That is no tailcalls and no GIMPLE_COND. */ @@ -3632,6 +3639,8 @@ expand_gimple_stmt_1 (gimple *stmt) /* This is a clobber to mark the going out of scope for this LHS. */ expand_clobber (lhs); + else if (TREE_CLOBBER_P (lhs)) + expand_use (rhs); else expand_assignment (lhs, rhs, gimple_assign_nontemporal_move_p ( diff --git a/gcc/common.opt b/gcc/common.opt index 984b351cd79..a29e320ba45 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1496,6 +1496,10 @@ fdebug-nops Common Report Var(flag_debug_nops) Optimization Insert nops if that might improve debugging of optimized code. +fkeep-vars-live +Common Report Var(flag_keep_vars_live) Optimization +Add artificial uses of local vars at end of scope. + fkeep-gc-roots-live Common Undocumented Report Var(flag_keep_gc_roots_live) Optimization ; Always keep a pointer to a live memory block diff --git a/gcc/function.c b/gcc/function.c index dee303cdbdd..6367d282db3 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1964,11 +1964,12 @@ instantiate_virtual_regs (void) { /* These patterns in the instruction stream can never be recognized. Fortunately, they shouldn't contain virtual registers either. */ - if (GET_CODE (PATTERN (insn)) == USE - || GET_CODE (PATTERN (insn)) == CLOBBER + if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == ASM_INPUT || DEBUG_MARKER_INSN_P (insn)) continue; + else if (GET_CODE (PATTERN (insn)) == USE) + instantiate_virtual_regs_in_rtx (&PATTERN (insn)); else if (DEBUG_BIND_INSN_P (insn)) instantiate_virtual_regs_in_rtx (INSN_VAR_LOCATION_PTR (insn)); else diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 4a109aee27a..1ce6ef648c6 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1264,6 +1264,23 @@ asan_poison_variables (hash_set *variables, bool poison, gimple_seq *seq_p } } +static gimple_seq +gimple_build_uses (tree vars) +{ + gimple_seq seq = NULL; + + for (tree var = vars; var; var = DECL_CHAIN (var)) + { + if (DECL_ARTIFICIAL (var)) + continue; + + gimple *stmt = gimple_build_assign (build_clobber (TREE_TYPE (var)), var); + gimple_seq_add_stmt (&seq, stmt); + } + + return seq; +} + /* Gimplify a BIND_EXPR. Just voidify and recurse. */ static enum gimplify_status @@ -1363,7 +1380,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) gimplify_seq_add_stmt (&cleanup, stack_restore); } - /* Add clobbers for all variables that go out of scope. */ + /* Add clobbers/uses for all variables that go out of scope. */ for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t)) { if (VAR_P (t) @@ -1376,14 +1393,17 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) /* Only care for variables that have to be in memory. Others will be rewritten into SSA names, hence moved to the top-level. */ - && !is_gimple_reg (t) + && (flag_keep_vars_live || !is_gimple_reg (t)) && flag_stack_reuse != SR_NONE) { tree clobber = build_clobber (TREE_TYPE (t)); - gimple *clobber_stmt; - clobber_stmt = gimple_build_assign (t, clobber); - gimple_set_location (clobber_stmt, end_locus); - gimplify_seq_add_stmt (&cleanup, clobber_stmt); + gimple *stmt; + if (is_gimple_reg (t)) + stmt = gimple_build_assign (clobber, t); + else + stmt = gimple_build_assign (t, clobber); + gimple_set_location (stmt, end_locus); + gimplify_seq_add_stmt (&cleanup, stmt); } if (flag_openacc && oacc_declare_returns != NULL) @@ -12763,6 +12783,10 @@ gimplify_body (tree fndecl, bool do_parms) gimple *outer_stmt; gbind *outer_bind; + gimple_seq cleanup = NULL; + if (flag_keep_vars_live) + cleanup = gimple_build_uses (DECL_ARGUMENTS (fndecl)); + timevar_push (TV_TREE_GIMPLIFY); init_tree_ssa (cfun); @@ -12798,6 +12822,14 @@ gimplify_body (tree fndecl, bool do_parms) /* Gimplify the function's body. */ seq = NULL; gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq); + + if (cleanup) + { + gtry *gs = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY); + seq = NULL; + gimplify_seq_add_stmt (&seq, gs); + } + outer_stmt = gimple_seq_first_stmt (seq); if (!outer_stmt) { diff --git a/gcc/testsuite/gcc.dg/guality/pr54200-2.c b/gcc/testsuite/gcc.dg/guality/pr54200-2.c index e30e3c92b94..646790af65a 100644 --- a/gcc/testsuite/gcc.dg/guality/pr54200-2.c +++ b/gcc/testsuite/gcc.dg/guality/pr54200-2.c @@ -1,6 +1,5 @@ /* { dg-do run } */ -/* { dg-skip-if "" { *-*-* } { "*" } { "-Og" "-Os" "-O0" } } */ -/* { dg-options "-g -fdebug-nops -DMAIN" } */ +/* { dg-options "-g -fdebug-nops -fkeep-vars-live -DMAIN" } */ #include "prevent-optimization.h" diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 14d66b7a728..d3a4465fe25 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -4484,6 +4484,7 @@ verify_gimple_assign_single (gassign *stmt) case PARM_DECL: if (!is_gimple_reg (lhs) && !is_gimple_reg (rhs1) + && !TREE_CLOBBER_P (lhs) && is_gimple_reg_type (TREE_TYPE (lhs))) { error ("invalid rhs for gimple memory store"); diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 3e30f6bc3d4..f6488b90378 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -3536,6 +3536,13 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) sra_stats.exprs++; } + if (modify_this_stmt && TREE_CLOBBER_P (gimple_assign_lhs (stmt))) + { + gimple_assign_set_rhs1 (stmt, rhs); + gimple_assign_set_lhs (stmt, build_clobber (TREE_TYPE (rhs))); + return SRA_AM_MODIFIED; + } + if (modify_this_stmt) { if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs))) diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 7b25778307f..007e6f84c2b 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1368,6 +1368,10 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p) poly_int64 max_size1 = -1, max_size2 = -1; bool var1_p, var2_p, ind1_p, ind2_p; + if ((ref1->ref && TREE_CLOBBER_P (ref1->ref)) || + (ref2->ref && TREE_CLOBBER_P (ref2->ref))) + return false; + gcc_checking_assert ((!ref1->ref || TREE_CODE (ref1->ref) == SSA_NAME || DECL_P (ref1->ref) diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index fd24f84fb14..d83579a09c5 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4883,7 +4883,8 @@ find_func_aliases (struct function *fn, gimple *origt) tree lhsop = gimple_assign_lhs (t); tree rhsop = (gimple_num_ops (t) == 2) ? gimple_assign_rhs1 (t) : NULL; - if (rhsop && TREE_CLOBBER_P (rhsop)) + if ((rhsop && TREE_CLOBBER_P (rhsop)) + || (lhsop && TREE_CLOBBER_P (lhsop))) /* Ignore clobbers, they don't actually store anything into the LHS. */ ; diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 8ccbc85970a..77f090bfa80 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -2628,7 +2628,7 @@ warn_uninitialized_phi (gphi *phi, vec *worklist, static bool gate_warn_uninitialized (void) { - return warn_uninitialized || warn_maybe_uninitialized; + return (warn_uninitialized || warn_maybe_uninitialized) && !flag_keep_vars_live; } namespace {