Message ID | 20220202144248.8F84513E6F@imap2.suse-dmz.suse.de |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DA9C53858039 for <patchwork@sourceware.org>; Wed, 2 Feb 2022 14:43:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA9C53858039 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1643812998; bh=XEXE8F6awfzV7e1VDYBe3kdF0V3IlliCL7bmf2fslKI=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=d6AALTHJwRImE4sRisJIskIuZHlQvsQ7SZ8mk/TgrziWJHcOQQqWvpNOoZrpFapET 6Mzbu0/S0kr205qAaLgR0O+q8GmyEuFiRvf++gvtMF9KKzWtbfa6AJfPl09+kvp8ma buWT72yL5TlU7uY1Slv0at6sd+lb8vpLK+W/PXTw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id BA14F385840F for <gcc-patches@gcc.gnu.org>; Wed, 2 Feb 2022 14:42:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org BA14F385840F Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id A8B3B1F3A9; Wed, 2 Feb 2022 14:42:48 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 8F84513E6F; Wed, 2 Feb 2022 14:42:48 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id uZbjIWiY+mHrdAAAMHmgww (envelope-from <rguenther@suse.de>); Wed, 02 Feb 2022 14:42:48 +0000 Date: Wed, 2 Feb 2022 15:42:48 +0100 (CET) To: gcc-patches@gcc.gnu.org Subject: [PATCH] Add CLOBBER_MARKS_EOL to mark storage end-of-life clobbers MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Message-Id: <20220202144248.8F84513E6F@imap2.suse-dmz.suse.de> X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Richard Biener via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Richard Biener <rguenther@suse.de> Cc: richard.sandiford@arm.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
Add CLOBBER_MARKS_EOL to mark storage end-of-life clobbers
|
|
Commit Message
Richard Biener
Feb. 2, 2022, 2:42 p.m. UTC
This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this marks the end-of-life of storage as opposed to just ending the lifetime of the object that occupied it. The dangling pointer diagnostics uses CLOBBERs but is confused by those emitted by the C++ frontend for example which emits them for the second purpose at the start of CTORs. The issue is also appearant for aarch64 in PR104092. Distinguishing the two cases is also necessary for the PR90348 fix. Bootstrapped and tested on x86_64-unknown-linux-gnu. I verified the bogus diagnostic in PR104092 is gone with a cross. OK for trunk? Thanks, Richard. 2022-02-02 Richard Biener <rguenther@suse.de> PR middle-end/90348 PR middle-end/104092 * tree-core.h: Document protected_flag use on CONSTRUCTOR nodes. * tree.h (CLOBBER_MARKS_EOL): Add. * tree-pretty-print.cc (dump_generic_node): Mark EOL CLOBBERs. * gimplify.c (gimplify_bind_expr): Mark storage end-of-life clobbers with CLOBBER_MARKS_EOL. (gimplify_target_expr): Likewise. * tree-inline.cc (expand_call_inline): Likewise. * tree-ssa-ccp.cc (insert_clobber_before_stack_restore): Likewise. * gimple-ssa-warn-access.cc (pass_waccess::check_stmt): Only treat CLOBBER_MARKS_EOL clobbers as ending lifetime of storage. * gcc.dg/pr87052.c: Adjust. --- gcc/gimple-ssa-warn-access.cc | 4 +++- gcc/gimplify.cc | 2 ++ gcc/testsuite/gcc.dg/pr87052.c | 2 +- gcc/tree-core.h | 3 +++ gcc/tree-inline.cc | 2 ++ gcc/tree-pretty-print.cc | 6 +++++- gcc/tree-ssa-ccp.cc | 1 + gcc/tree.h | 3 +++ 8 files changed, 20 insertions(+), 3 deletions(-)
Comments
On Wed, Feb 02, 2022 at 03:42:48PM +0100, Richard Biener via Gcc-patches wrote: > This adds a flag to CONSTRUCTOR nodes indicating that for > clobbers this marks the end-of-life of storage as opposed to > just ending the lifetime of the object that occupied it. > The dangling pointer diagnostics uses CLOBBERs but is confused > by those emitted by the C++ frontend for example which emits > them for the second purpose at the start of CTORs. The issue > is also appearant for aarch64 in PR104092. I think many further build_clobber calls actually should build those EOL clobbers, I think we'd need to go through them one by one and see what kind of clobber it is. E.g. I think all of omp-low.cc build_clobber calls are like that. C++ FE indeed emits some clobbers at the start of ctors with -flifetime-dse=2, but others e.g. at the end of dtors, dunno about those, though maybe the object doesn't go out of scope at that point yet. What about expansion and tree-ssa-live.cc, should those keep doing what it does and not ignore clobbers that aren't CLOBBER_MARKS_EOL? Jakub
On Wed, 2 Feb 2022, Jakub Jelinek wrote: > On Wed, Feb 02, 2022 at 03:42:48PM +0100, Richard Biener via Gcc-patches wrote: > > This adds a flag to CONSTRUCTOR nodes indicating that for > > clobbers this marks the end-of-life of storage as opposed to > > just ending the lifetime of the object that occupied it. > > The dangling pointer diagnostics uses CLOBBERs but is confused > > by those emitted by the C++ frontend for example which emits > > them for the second purpose at the start of CTORs. The issue > > is also appearant for aarch64 in PR104092. > > I think many further build_clobber calls actually should build > those EOL clobbers, I think we'd need to go through them one by one and see > what kind of clobber it is. > E.g. I think all of omp-low.cc build_clobber calls are like that. Yeah, there may be others that also end lifetime of the storage. It should be pretty safe since the only consumer after this patch is the access warning. > C++ FE indeed emits some clobbers at the start of ctors with > -flifetime-dse=2, but others e.g. at the end of dtors, dunno about those, > though maybe the object doesn't go out of scope at that point yet. > What about expansion and tree-ssa-live.cc, should those keep doing > what it does and not ignore clobbers that aren't CLOBBER_MARKS_EOL? Yes. Basically EOL clobbers act as regular clobbers _plus_ they also note the end of life of the underlying storage, so treating those like regular clobbers is safe, likewise it's not a regression to not ignore !CLOBBER_MARKS_EOL clobbers elsewhere and I'd rather have testcases showing the current behavior is wrong for those than changing other places. The inliner and CCP cases I ran into when fixing PR90348, I did not run into any others sofar. Richard.
Hello, On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > marks the end-of-life of storage as opposed to just ending the lifetime > of the object that occupied it. The dangling pointer diagnostics uses > CLOBBERs but is confused by those emitted by the C++ frontend for > example which emits them for the second purpose at the start of CTORs. > The issue is also appearant for aarch64 in PR104092. > > Distinguishing the two cases is also necessary for the PR90348 fix. (Just FWIW: I agree with the plan to have different types of CLOBBERs, in particular those for marking births) A style nit: > tree clobber = build_clobber (TREE_TYPE (t)); > + CLOBBER_MARKS_EOL (clobber) = 1; I think it really were better if build_clobber() gained an additional argument (non-optional!) that sets the type of it. Ciao, Michael.
On 2/2/2022 7:42 AM, Richard Biener via Gcc-patches wrote: > This adds a flag to CONSTRUCTOR nodes indicating that for > clobbers this marks the end-of-life of storage as opposed to > just ending the lifetime of the object that occupied it. > The dangling pointer diagnostics uses CLOBBERs but is confused > by those emitted by the C++ frontend for example which emits > them for the second purpose at the start of CTORs. The issue > is also appearant for aarch64 in PR104092. > > Distinguishing the two cases is also necessary for the PR90348 fix. > > Bootstrapped and tested on x86_64-unknown-linux-gnu. I verified > the bogus diagnostic in PR104092 is gone with a cross. > > OK for trunk? > > Thanks, > Richard. > > 2022-02-02 Richard Biener <rguenther@suse.de> > > PR middle-end/90348 > PR middle-end/104092 > * tree-core.h: Document protected_flag use on CONSTRUCTOR nodes. > * tree.h (CLOBBER_MARKS_EOL): Add. > * tree-pretty-print.cc (dump_generic_node): Mark EOL CLOBBERs. > * gimplify.c (gimplify_bind_expr): Mark storage end-of-life clobbers > with CLOBBER_MARKS_EOL. > (gimplify_target_expr): Likewise. > * tree-inline.cc (expand_call_inline): Likewise. > * tree-ssa-ccp.cc (insert_clobber_before_stack_restore): Likewise. > * gimple-ssa-warn-access.cc (pass_waccess::check_stmt): Only treat > CLOBBER_MARKS_EOL clobbers as ending lifetime of storage. > > * gcc.dg/pr87052.c: Adjust. OK. Note that I think something similar may be needed to mark EOL for the pointer passed to realloc to fix a related set of false positives for code like this bool something = p != q; whatever = realloc (p, newsize) if (something) We forward propagate the p != q test generating something like this; whatever - realloc (p, newsize); if (p != q) Which triggers a warning even though the original source was reasonable. I think a well placed clobber of p should expose the dataflow necessary to prevent the propagation and ultimately avoid the false positive. IIRC something like this came up in glibc and/or gnulib. I realize it's not exactly the same, but they're reasonably closely related. jeff
On Wed, Feb 02, 2022 at 01:23:44PM -0700, Jeff Law via Gcc-patches wrote: > Note that I think something similar may be needed to mark EOL for the > pointer passed to realloc to fix a related set of false positives for code > like this > > bool something = p != q; > whatever = realloc (p, newsize) > if (something) > > We forward propagate the p != q test generating something like this; > > whatever - realloc (p, newsize); > if (p != q) IMNSHO we shouldn't warn for pointer passed to realloc being used in equality comparisons at all, it is just unnecessarily pedantic, it works just fine and a lot of programs use it to find out if the memory was actually reallocated or was just extended or shrunk in place; in the former case they often need some extra work, such as adjust something in the memory block. Yes, one can probably do uintptr_t pint = (uintptr_t) p; whatever = realloc (p, newsize); if ((uintptr_t) whatever != pint) but I think most people don't bother. Jakub
On Wed, 2 Feb 2022, Michael Matz wrote: > Hello, > > On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: > > > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > > marks the end-of-life of storage as opposed to just ending the lifetime > > of the object that occupied it. The dangling pointer diagnostics uses > > CLOBBERs but is confused by those emitted by the C++ frontend for > > example which emits them for the second purpose at the start of CTORs. > > The issue is also appearant for aarch64 in PR104092. > > > > Distinguishing the two cases is also necessary for the PR90348 fix. > > (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > particular those for marking births) > > A style nit: > > > tree clobber = build_clobber (TREE_TYPE (t)); > > + CLOBBER_MARKS_EOL (clobber) = 1; > > I think it really were better if build_clobber() gained an additional > argument (non-optional!) that sets the type of it. It indeed did occur to me as well, so as we're two now I tried to see how it looks like. It does like the following (didn't bother to replace all build_clobber calls but defaulted the parameter - there are too many). With CLOBBER_BIRTH added for the fix for PR90348 the enum would be constructed like #define CLOBBER_KIND(NODE) \ ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1 | CONSTRUCTOR_CHECK (NODE)->base.protected_flag)) or so (maybe different dependent on bitfield endianess to make extracting the two adjacent bits cheap). That would leave us space for a fourth state. So do you think that makes it nicer? What do others think? Thanks, Richard.
Richard Biener <rguenther@suse.de> writes: > On Wed, 2 Feb 2022, Michael Matz wrote: > >> Hello, >> >> On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: >> >> > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this >> > marks the end-of-life of storage as opposed to just ending the lifetime >> > of the object that occupied it. The dangling pointer diagnostics uses >> > CLOBBERs but is confused by those emitted by the C++ frontend for >> > example which emits them for the second purpose at the start of CTORs. >> > The issue is also appearant for aarch64 in PR104092. >> > >> > Distinguishing the two cases is also necessary for the PR90348 fix. >> >> (Just FWIW: I agree with the plan to have different types of CLOBBERs, in >> particular those for marking births) >> >> A style nit: >> >> > tree clobber = build_clobber (TREE_TYPE (t)); >> > + CLOBBER_MARKS_EOL (clobber) = 1; >> >> I think it really were better if build_clobber() gained an additional >> argument (non-optional!) that sets the type of it. > > It indeed did occur to me as well, so as we're two now I tried to see > how it looks like. It does like the following (didn't bother to > replace all build_clobber calls but defaulted the parameter - there > are too many). With CLOBBER_BIRTH added for the fix for PR90348 > the enum would be constructed like > > #define CLOBBER_KIND(NODE) \ > ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1 > | CONSTRUCTOR_CHECK (NODE)->base.protected_flag)) > > or so (maybe different dependent on bitfield endianess to make > extracting the two adjacent bits cheap). That would leave us space > for a fourth state. > > So do you think that makes it nicer? What do others think? This way looks cleaner to me FWIW. Which arm of tree_base::u do constructors use? If we need a 2-bit enum then maybe we can carve one out from there. Thanks, Richard
On Thu, 3 Feb 2022, Richard Sandiford wrote: > Richard Biener <rguenther@suse.de> writes: > > On Wed, 2 Feb 2022, Michael Matz wrote: > > > >> Hello, > >> > >> On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: > >> > >> > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > >> > marks the end-of-life of storage as opposed to just ending the lifetime > >> > of the object that occupied it. The dangling pointer diagnostics uses > >> > CLOBBERs but is confused by those emitted by the C++ frontend for > >> > example which emits them for the second purpose at the start of CTORs. > >> > The issue is also appearant for aarch64 in PR104092. > >> > > >> > Distinguishing the two cases is also necessary for the PR90348 fix. > >> > >> (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > >> particular those for marking births) > >> > >> A style nit: > >> > >> > tree clobber = build_clobber (TREE_TYPE (t)); > >> > + CLOBBER_MARKS_EOL (clobber) = 1; > >> > >> I think it really were better if build_clobber() gained an additional > >> argument (non-optional!) that sets the type of it. > > > > It indeed did occur to me as well, so as we're two now I tried to see > > how it looks like. It does like the following (didn't bother to > > replace all build_clobber calls but defaulted the parameter - there > > are too many). With CLOBBER_BIRTH added for the fix for PR90348 > > the enum would be constructed like > > > > #define CLOBBER_KIND(NODE) \ > > ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1 > > | CONSTRUCTOR_CHECK (NODE)->base.protected_flag)) > > > > or so (maybe different dependent on bitfield endianess to make > > extracting the two adjacent bits cheap). That would leave us space > > for a fourth state. > > > > So do you think that makes it nicer? What do others think? > > This way looks cleaner to me FWIW. > > Which arm of tree_base::u do constructors use? If we need a 2-bit > enum then maybe we can carve one out from there. constructors are tcc_exceptional but since they are used where tree operands reside they need to be compatible to EXPR_P and thus various things like TREE_SIDE_EFFECTS need to work. Which means, we can't. Richard.
Richard Biener <rguenther@suse.de> writes: > On Thu, 3 Feb 2022, Richard Sandiford wrote: > >> Richard Biener <rguenther@suse.de> writes: >> > On Wed, 2 Feb 2022, Michael Matz wrote: >> > >> >> Hello, >> >> >> >> On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: >> >> >> >> > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this >> >> > marks the end-of-life of storage as opposed to just ending the lifetime >> >> > of the object that occupied it. The dangling pointer diagnostics uses >> >> > CLOBBERs but is confused by those emitted by the C++ frontend for >> >> > example which emits them for the second purpose at the start of CTORs. >> >> > The issue is also appearant for aarch64 in PR104092. >> >> > >> >> > Distinguishing the two cases is also necessary for the PR90348 fix. >> >> >> >> (Just FWIW: I agree with the plan to have different types of CLOBBERs, in >> >> particular those for marking births) >> >> >> >> A style nit: >> >> >> >> > tree clobber = build_clobber (TREE_TYPE (t)); >> >> > + CLOBBER_MARKS_EOL (clobber) = 1; >> >> >> >> I think it really were better if build_clobber() gained an additional >> >> argument (non-optional!) that sets the type of it. >> > >> > It indeed did occur to me as well, so as we're two now I tried to see >> > how it looks like. It does like the following (didn't bother to >> > replace all build_clobber calls but defaulted the parameter - there >> > are too many). With CLOBBER_BIRTH added for the fix for PR90348 >> > the enum would be constructed like >> > >> > #define CLOBBER_KIND(NODE) \ >> > ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1 >> > | CONSTRUCTOR_CHECK (NODE)->base.protected_flag)) >> > >> > or so (maybe different dependent on bitfield endianess to make >> > extracting the two adjacent bits cheap). That would leave us space >> > for a fourth state. >> > >> > So do you think that makes it nicer? What do others think? >> >> This way looks cleaner to me FWIW. >> >> Which arm of tree_base::u do constructors use? If we need a 2-bit >> enum then maybe we can carve one out from there. > > constructors are tcc_exceptional but since they are used where > tree operands reside they need to be compatible to EXPR_P and > thus various things like TREE_SIDE_EFFECTS need to work. > > Which means, we can't. But TREE_SIDE_EFFECTS is part of the main set of flags. For tree_base::u we have: union { /* The bits in the following structure should only be used with accessor macros that constrain inputs with tree checking. */ struct { unsigned lang_flag_0 : 1; unsigned lang_flag_1 : 1; unsigned lang_flag_2 : 1; unsigned lang_flag_3 : 1; unsigned lang_flag_4 : 1; unsigned lang_flag_5 : 1; unsigned lang_flag_6 : 1; unsigned saturating_flag : 1; unsigned unsigned_flag : 1; unsigned packed_flag : 1; unsigned user_align : 1; unsigned nameless_flag : 1; unsigned atomic_flag : 1; unsigned unavailable_flag : 1; unsigned spare0 : 2; unsigned spare1 : 8; /* This field is only used with TREE_TYPE nodes; the only reason it is present in tree_base instead of tree_type is to save space. The size of the field must be large enough to hold addr_space_t values. */ unsigned address_space : 8; } bits; /* The following fields are present in tree_base to save space. The nodes using them do not require any of the flags above and so can make better use of the 4-byte sized word. */ /* The number of HOST_WIDE_INTs in an INTEGER_CST. */ struct { /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in its native precision. */ unsigned char unextended; /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to wider precisions based on its TYPE_SIGN. */ unsigned char extended; /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in offset_int precision, with smaller integers being extended according to their TYPE_SIGN. This is equal to one of the two fields above but is cached for speed. */ unsigned char offset; } int_length; /* VEC length. This field is only used with TREE_VEC. */ int length; /* This field is only used with VECTOR_CST. */ struct { /* The value of VECTOR_CST_LOG2_NPATTERNS. */ unsigned int log2_npatterns : 8; /* The value of VECTOR_CST_NELTS_PER_PATTERN. */ unsigned int nelts_per_pattern : 8; /* For future expansion. */ unsigned int unused : 16; } vector_cst; /* SSA version number. This field is only used with SSA_NAME. */ unsigned int version; /* CHREC_VARIABLE. This field is only used with POLYNOMIAL_CHREC. */ unsigned int chrec_var; /* Internal function code. */ enum internal_fn ifn; /* OMP_ATOMIC* memory order. */ enum omp_memory_order omp_atomic_memory_order; /* The following two fields are used for MEM_REF and TARGET_MEM_REF expression trees and specify known data non-dependences. For two memory references in a function they are known to not alias if dependence_info.clique are equal and dependence_info.base are distinct. Clique number zero means there is no information, clique number one is populated from function global information and thus needs no remapping on transforms like loop unrolling. */ struct { unsigned short clique; unsigned short base; } dependence_info; } GTY((skip(""))) u; so there's spare room even if constructors use the general “bits” arm. Thanks, Richard
On Thu, 3 Feb 2022, Richard Sandiford wrote: > Richard Biener <rguenther@suse.de> writes: > > On Thu, 3 Feb 2022, Richard Sandiford wrote: > > > >> Richard Biener <rguenther@suse.de> writes: > >> > On Wed, 2 Feb 2022, Michael Matz wrote: > >> > > >> >> Hello, > >> >> > >> >> On Wed, 2 Feb 2022, Richard Biener via Gcc-patches wrote: > >> >> > >> >> > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > >> >> > marks the end-of-life of storage as opposed to just ending the lifetime > >> >> > of the object that occupied it. The dangling pointer diagnostics uses > >> >> > CLOBBERs but is confused by those emitted by the C++ frontend for > >> >> > example which emits them for the second purpose at the start of CTORs. > >> >> > The issue is also appearant for aarch64 in PR104092. > >> >> > > >> >> > Distinguishing the two cases is also necessary for the PR90348 fix. > >> >> > >> >> (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > >> >> particular those for marking births) > >> >> > >> >> A style nit: > >> >> > >> >> > tree clobber = build_clobber (TREE_TYPE (t)); > >> >> > + CLOBBER_MARKS_EOL (clobber) = 1; > >> >> > >> >> I think it really were better if build_clobber() gained an additional > >> >> argument (non-optional!) that sets the type of it. > >> > > >> > It indeed did occur to me as well, so as we're two now I tried to see > >> > how it looks like. It does like the following (didn't bother to > >> > replace all build_clobber calls but defaulted the parameter - there > >> > are too many). With CLOBBER_BIRTH added for the fix for PR90348 > >> > the enum would be constructed like > >> > > >> > #define CLOBBER_KIND(NODE) \ > >> > ((clobber_kind) (CONSTRUCTOR_CHECK (NODE)->base.private_flag << 1 > >> > | CONSTRUCTOR_CHECK (NODE)->base.protected_flag)) > >> > > >> > or so (maybe different dependent on bitfield endianess to make > >> > extracting the two adjacent bits cheap). That would leave us space > >> > for a fourth state. > >> > > >> > So do you think that makes it nicer? What do others think? > >> > >> This way looks cleaner to me FWIW. > >> > >> Which arm of tree_base::u do constructors use? If we need a 2-bit > >> enum then maybe we can carve one out from there. > > > > constructors are tcc_exceptional but since they are used where > > tree operands reside they need to be compatible to EXPR_P and > > thus various things like TREE_SIDE_EFFECTS need to work. > > > > Which means, we can't. > > But TREE_SIDE_EFFECTS is part of the main set of flags. For tree_base::u > we have: > > union { > /* The bits in the following structure should only be used with > accessor macros that constrain inputs with tree checking. */ > struct { > unsigned lang_flag_0 : 1; > unsigned lang_flag_1 : 1; > unsigned lang_flag_2 : 1; > unsigned lang_flag_3 : 1; > unsigned lang_flag_4 : 1; > unsigned lang_flag_5 : 1; > unsigned lang_flag_6 : 1; > unsigned saturating_flag : 1; > > unsigned unsigned_flag : 1; > unsigned packed_flag : 1; > unsigned user_align : 1; > unsigned nameless_flag : 1; > unsigned atomic_flag : 1; > unsigned unavailable_flag : 1; > unsigned spare0 : 2; > > unsigned spare1 : 8; > > /* This field is only used with TREE_TYPE nodes; the only reason it is > present in tree_base instead of tree_type is to save space. The size > of the field must be large enough to hold addr_space_t values. */ > unsigned address_space : 8; > } bits; > > /* The following fields are present in tree_base to save space. The > nodes using them do not require any of the flags above and so can > make better use of the 4-byte sized word. */ > > /* The number of HOST_WIDE_INTs in an INTEGER_CST. */ > struct { > /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in > its native precision. */ > unsigned char unextended; > > /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to > wider precisions based on its TYPE_SIGN. */ > unsigned char extended; > > /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in > offset_int precision, with smaller integers being extended > according to their TYPE_SIGN. This is equal to one of the two > fields above but is cached for speed. */ > unsigned char offset; > } int_length; > > /* VEC length. This field is only used with TREE_VEC. */ > int length; > > /* This field is only used with VECTOR_CST. */ > struct { > /* The value of VECTOR_CST_LOG2_NPATTERNS. */ > unsigned int log2_npatterns : 8; > > /* The value of VECTOR_CST_NELTS_PER_PATTERN. */ > unsigned int nelts_per_pattern : 8; > > /* For future expansion. */ > unsigned int unused : 16; > } vector_cst; > > /* SSA version number. This field is only used with SSA_NAME. */ > unsigned int version; > > /* CHREC_VARIABLE. This field is only used with POLYNOMIAL_CHREC. */ > unsigned int chrec_var; > > /* Internal function code. */ > enum internal_fn ifn; > > /* OMP_ATOMIC* memory order. */ > enum omp_memory_order omp_atomic_memory_order; > > /* The following two fields are used for MEM_REF and TARGET_MEM_REF > expression trees and specify known data non-dependences. For > two memory references in a function they are known to not > alias if dependence_info.clique are equal and dependence_info.base > are distinct. Clique number zero means there is no information, > clique number one is populated from function global information > and thus needs no remapping on transforms like loop unrolling. */ > struct { > unsigned short clique; > unsigned short base; > } dependence_info; > } GTY((skip(""))) u; > > so there's spare room even if constructors use the general “bits” arm. Ah, yes - I thought CTORs are using that for the number of elements but they don't, they use a pointer to a vec<>. So yes, for convenience we could use bits in that section (with a bit more churn as they need to be streamed for LTO, etc.) I'll see to simply stick the plain enum there for CTORs. Richard.
Hello, On Thu, 3 Feb 2022, Richard Biener wrote: > > > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > > > marks the end-of-life of storage as opposed to just ending the lifetime > > > of the object that occupied it. The dangling pointer diagnostics uses > > > CLOBBERs but is confused by those emitted by the C++ frontend for > > > example which emits them for the second purpose at the start of CTORs. > > > The issue is also appearant for aarch64 in PR104092. > > > > > > Distinguishing the two cases is also necessary for the PR90348 fix. > > > > (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > > particular those for marking births) > > > > A style nit: > > > > > tree clobber = build_clobber (TREE_TYPE (t)); > > > + CLOBBER_MARKS_EOL (clobber) = 1; > > > > I think it really were better if build_clobber() gained an additional > > argument (non-optional!) that sets the type of it. > > It indeed did occur to me as well, so as we're two now I tried to see > how it looks like. It does like the following (didn't bother to > replace all build_clobber calls but defaulted the parameter - there > are too many). Except for this part I like it (I wouldn't call ca. 25 calls too many). I often find optional arguments to be a long term maintenance burden when reading code. (And yeah, enum good, putting the enum to tree_base.u, if it works, otherwise use your bit shuffling) Ciao, Michael.
On Thu, 3 Feb 2022, Michael Matz wrote: > Hello, > > On Thu, 3 Feb 2022, Richard Biener wrote: > > > > > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > > > > marks the end-of-life of storage as opposed to just ending the lifetime > > > > of the object that occupied it. The dangling pointer diagnostics uses > > > > CLOBBERs but is confused by those emitted by the C++ frontend for > > > > example which emits them for the second purpose at the start of CTORs. > > > > The issue is also appearant for aarch64 in PR104092. > > > > > > > > Distinguishing the two cases is also necessary for the PR90348 fix. > > > > > > (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > > > particular those for marking births) > > > > > > A style nit: > > > > > > > tree clobber = build_clobber (TREE_TYPE (t)); > > > > + CLOBBER_MARKS_EOL (clobber) = 1; > > > > > > I think it really were better if build_clobber() gained an additional > > > argument (non-optional!) that sets the type of it. > > > > It indeed did occur to me as well, so as we're two now I tried to see > > how it looks like. It does like the following (didn't bother to > > replace all build_clobber calls but defaulted the parameter - there > > are too many). > > Except for this part I like it (I wouldn't call ca. 25 calls too > many). I often find optional arguments to be a long term maintenance > burden when reading code. But I think in this case it makes clear that the remaining callers are un-audited - as Jakub said some of them may want to use a specific kind. I also wanted to make the patch small just in case we're considering the fix for GCC 12 ... > (And yeah, enum good, putting the enum to tree_base.u, if it works, > otherwise use your bit shuffling) It seems to. Updated patch in testing. Richard.
On Thu, 3 Feb 2022, Richard Biener wrote: > On Thu, 3 Feb 2022, Michael Matz wrote: > > > Hello, > > > > On Thu, 3 Feb 2022, Richard Biener wrote: > > > > > > > This adds a flag to CONSTRUCTOR nodes indicating that for clobbers this > > > > > marks the end-of-life of storage as opposed to just ending the lifetime > > > > > of the object that occupied it. The dangling pointer diagnostics uses > > > > > CLOBBERs but is confused by those emitted by the C++ frontend for > > > > > example which emits them for the second purpose at the start of CTORs. > > > > > The issue is also appearant for aarch64 in PR104092. > > > > > > > > > > Distinguishing the two cases is also necessary for the PR90348 fix. > > > > > > > > (Just FWIW: I agree with the plan to have different types of CLOBBERs, in > > > > particular those for marking births) > > > > > > > > A style nit: > > > > > > > > > tree clobber = build_clobber (TREE_TYPE (t)); > > > > > + CLOBBER_MARKS_EOL (clobber) = 1; > > > > > > > > I think it really were better if build_clobber() gained an additional > > > > argument (non-optional!) that sets the type of it. > > > > > > It indeed did occur to me as well, so as we're two now I tried to see > > > how it looks like. It does like the following (didn't bother to > > > replace all build_clobber calls but defaulted the parameter - there > > > are too many). > > > > Except for this part I like it (I wouldn't call ca. 25 calls too > > many). I often find optional arguments to be a long term maintenance > > burden when reading code. > > But I think in this case it makes clear that the remaining callers > are un-audited - as Jakub said some of them may want to use a > specific kind. I also wanted to make the patch small just in case > we're considering the fix for GCC 12 ... > > > (And yeah, enum good, putting the enum to tree_base.u, if it works, > > otherwise use your bit shuffling) > > It seems to. Updated patch in testing. Meh. C++ uses LANG_FLAG_3 on CTORs at least, so I'm switching to u.bits.address_space. Richard.
Hello, On Thu, 3 Feb 2022, Richard Biener via Gcc-patches wrote: > > > It indeed did occur to me as well, so as we're two now I tried to > > > see how it looks like. It does like the following (didn't bother to > > > replace all build_clobber calls but defaulted the parameter - there > > > are too many). > > > > Except for this part I like it (I wouldn't call ca. 25 calls too > > many). I often find optional arguments to be a long term maintenance > > burden when reading code. > > But I think in this case it makes clear that the remaining callers are > un-audited My pedantic answer to that would be that to make something clear you want to be explicit, and being explicit means writing something, not leaving something out, so you'd add another "CLOBBER_DONTKNOW" and use that for the unaudited calls. Pedantic, as I said :) But, of course, you built the shed, so paint it green, all right :) Ciao, Michael.
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index ad5e2f4458e..4890737587c 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -4330,7 +4330,9 @@ is_auto_decl (tree x) void pass_waccess::check_stmt (gimple *stmt) { - if (m_check_dangling_p && gimple_clobber_p (stmt)) + if (m_check_dangling_p + && gimple_clobber_p (stmt) + && CLOBBER_MARKS_EOL (gimple_assign_rhs1 (stmt))) { /* Ignore clobber statemts in blocks with exceptional edges. */ basic_block bb = gimple_bb (stmt); diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index cd4b61362b4..253f2c9af64 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -1476,6 +1476,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) && flag_stack_reuse != SR_NONE) { tree clobber = build_clobber (TREE_TYPE (t)); + CLOBBER_MARKS_EOL (clobber) = 1; gimple *clobber_stmt; clobber_stmt = gimple_build_assign (t, clobber); gimple_set_location (clobber_stmt, end_locus); @@ -6982,6 +6983,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (flag_stack_reuse == SR_ALL) { tree clobber = build_clobber (TREE_TYPE (temp)); + CLOBBER_MARKS_EOL (clobber) = 1; clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber); gimple_push_cleanup (temp, clobber, false, pre_p, true); } diff --git a/gcc/testsuite/gcc.dg/pr87052.c b/gcc/testsuite/gcc.dg/pr87052.c index 2affc480f4e..18e092c4674 100644 --- a/gcc/testsuite/gcc.dg/pr87052.c +++ b/gcc/testsuite/gcc.dg/pr87052.c @@ -38,4 +38,4 @@ void test (void) { dg-final { scan-tree-dump-times "c = \"\";" 1 "gimple" } } { dg-final { scan-tree-dump-times "d = { *};" 1 "gimple" } } { dg-final { scan-tree-dump-times "e = " 1 "gimple" } } - { dg-final { scan-tree-dump-times "e = {CLOBBER}" 1 "gimple" } } */ + { dg-final { scan-tree-dump-times "e = {CLOBBER\\(eol\\)}" 1 "gimple" } } */ diff --git a/gcc/tree-core.h b/gcc/tree-core.h index e83669f20d8..924a6a2b2cf 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1281,6 +1281,9 @@ struct GTY(()) tree_base { ASM_INLINE_P in ASM_EXPR + CLOBBER_MARKS_EOL in + CONSTRUCTOR + side_effects_flag: TREE_SIDE_EFFECTS in diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 497aa667eb9..47e895dad68 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -5139,6 +5139,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, && !(id->debug_map && id->debug_map->get (p))) { tree clobber = build_clobber (TREE_TYPE (*varp)); + CLOBBER_MARKS_EOL (clobber) = 1; gimple *clobber_stmt; clobber_stmt = gimple_build_assign (*varp, clobber); gimple_set_location (clobber_stmt, gimple_location (stmt)); @@ -5208,6 +5209,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, && !stmt_ends_bb_p (stmt)) { tree clobber = build_clobber (TREE_TYPE (id->retvar)); + CLOBBER_MARKS_EOL (clobber) = 1; gimple *clobber_stmt; clobber_stmt = gimple_build_assign (id->retvar, clobber); gimple_set_location (clobber_stmt, gimple_location (old_stmt)); diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 6130c307e9a..dad46eb3adb 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -2500,7 +2500,11 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, } pp_left_brace (pp); if (TREE_CLOBBER_P (node)) - pp_string (pp, "CLOBBER"); + { + pp_string (pp, "CLOBBER"); + if (CLOBBER_MARKS_EOL (node)) + pp_string (pp, "(eol)"); + } else if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE) is_struct_init = true; diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc index 48683f04d49..71ac6a2ab34 100644 --- a/gcc/tree-ssa-ccp.cc +++ b/gcc/tree-ssa-ccp.cc @@ -2506,6 +2506,7 @@ insert_clobber_before_stack_restore (tree saved_val, tree var, if (gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE)) { clobber = build_clobber (TREE_TYPE (var)); + CLOBBER_MARKS_EOL (clobber) = 1; clobber_stmt = gimple_build_assign (var, clobber); i = gsi_for_stmt (stmt); diff --git a/gcc/tree.h b/gcc/tree.h index e2157d66d6c..ba9da13a165 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1154,6 +1154,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, such clobber instructions. */ #define TREE_CLOBBER_P(NODE) \ (TREE_CODE (NODE) == CONSTRUCTOR && TREE_THIS_VOLATILE (NODE)) +/* True if NODE marks the end-of-life of storage. */ +#define CLOBBER_MARKS_EOL(NODE) \ + (CONSTRUCTOR_CHECK (NODE)->base.protected_flag) /* Define fields and accessors for some nodes that represent expressions. */