From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 0551C385B1AE for ; Thu, 8 Dec 2022 22:01:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0551C385B1AE Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670536877; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=gdTalr0EaPF7o03jeRY+JVKOenScK2Idrm6j1SNd9Oc=; b=Q8JLLFip7Ykesmm8m2qzvQmcQqGRsf8JZ/1RzMNg/ZLkk3CuGC0f2JgXoXmqXSJfRUbzYS GqxcoV2nZlqdarAtVbAro2uOwkBJkYF0BhM2upJfDSocapQv0kBllaeJ0wPS8UGGrSekmG Iwly6iLbYBTMNhouZE4syN3faZLpluM= Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-97-2J-bbmejOgCinqa5FbUvGw-1; Thu, 08 Dec 2022 17:01:16 -0500 X-MC-Unique: 2J-bbmejOgCinqa5FbUvGw-1 Received: by mail-qt1-f199.google.com with SMTP id fg11-20020a05622a580b00b003a7eaa5cb47so2642911qtb.15 for ; Thu, 08 Dec 2022 14:01:16 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=gdTalr0EaPF7o03jeRY+JVKOenScK2Idrm6j1SNd9Oc=; b=HOmtyV7gnSKWKvuxAxl9mQcQYVjsAuAnm08qFGdCi0AdKA2uhYGfnvDE9EL5riVEWd R2mXDkjlA8LVHtbhBowW2/PvFoCvXHxjulQh/G4CgMdwmuJvDRqcgizkg8hFVlhgXDb+ yp6A0JwYDATOfEyrnZE7Em2FHEfK+4/fDYWyQSkvppHcZyz+cptYBVfxFqPsCQGQ+5EO cgvMMYi7rEpXpa06zPLTMyf1WmHg0OZlorHKBUx3gLPiSWuyxnHf9fyVfhWAAJstWqyx +DqF32x1Nd0Ux9TA3AeN6OfqTM9MfwxeAunMZRyl32MccpwFoKwhpYQ0M4W8U9qB4WGO hJag== X-Gm-Message-State: ANoB5pl8QHcdmoC8nn9SS1szXDX0nnxXKJLReiLrAArqhNPGPkD775z4 qSK2zsBbmQzxwygeljpAJF/qg77p6khMGR2Ptf52BYfeE63a6jC9mcEYchYmBuT9DnMUf7Wc8q/ iCg4tU8T2QOJt2uL7YzWnQfjhNhA1JIq1z4bAnKCwGs+oD4UE4sUsdXfm4P0bN19R6w== X-Received: by 2002:ac8:544b:0:b0:3a5:3136:6be8 with SMTP id d11-20020ac8544b000000b003a531366be8mr4217947qtq.45.1670536875722; Thu, 08 Dec 2022 14:01:15 -0800 (PST) X-Google-Smtp-Source: AA0mqf6npbtNfccuSB8dW8nBbMwkxtJzrFjAWbekzRXk6mU/9nvrrAwy0LPlrP7sQMQu+8uaNRD7Nw== X-Received: by 2002:ac8:544b:0:b0:3a5:3136:6be8 with SMTP id d11-20020ac8544b000000b003a531366be8mr4217893qtq.45.1670536874924; Thu, 08 Dec 2022 14:01:14 -0800 (PST) Received: from jason.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id y6-20020a05620a44c600b006fa7b5ea2d1sm20508053qkp.125.2022.12.08.14.01.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Dec 2022 14:01:14 -0800 (PST) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [PATCH RFA] gimplify: avoid unnecessary copy of init array [PR105838] Date: Thu, 8 Dec 2022 17:01:12 -0500 Message-Id: <20221208220112.1700553-1-jason@redhat.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: After the previous patches, I noticed that we were putting the array of strings into .rodata, but then memcpying it into an automatic array, which is pointless; we should be able to use it directly. C++ doesn't allow us to do this for the backing array of an initializer_list, but should be able to do it for the implementation detail array we use to construct the backing array. This doesn't happen automatically because TREE_ADDRESSABLE is set, and gimplify_init_constructor uses that to decide whether to promote a variable to static. Ideally this could use escape analysis to recognize that the address, though taken, never leaves the function; that should allow promotion when we're only using the address for indexing within the function, as in initlist-opt2.C. But in initlist-opt1.C, we're passing the array address to another function, so it definitely escapes; it's only safe in this case because it's calling a standard library function that we know only uses it for indexing. So, a flag seems needed. I first thought to put the flag on the TARGET_EXPR, but the VAR_DECL seems more appropriate. Bikeshedding, or other approaches, welcome. PR c++/105838 gcc/ChangeLog: * tree.h (DECL_NOT_OBSERVABLE): New. * tree-core.h (struct tree_decl_common): Mention it. * gimplify.cc (gimplify_init_constructor): Check it. gcc/cp/ChangeLog: * call.cc (maybe_init_list_as_array): Set DECL_NOT_OBSERVABLE. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/initlist-opt1.C: Check for static array. * g++.dg/tree-ssa/initlist-opt2.C: Likewise. --- gcc/tree-core.h | 3 ++- gcc/tree.h | 5 +++++ gcc/cp/call.cc | 4 +++- gcc/gimplify.cc | 3 ++- gcc/testsuite/g++.dg/tree-ssa/initlist-opt1.C | 1 + gcc/testsuite/g++.dg/tree-ssa/initlist-opt2.C | 1 + 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/gcc/tree-core.h b/gcc/tree-core.h index e146b133dbd..c0d63632c1e 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1808,7 +1808,8 @@ struct GTY(()) tree_decl_common { In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_HAS_VALUE_EXPR_P. */ unsigned decl_flag_2 : 1; - /* In FIELD_DECL, this is DECL_PADDING_P. */ + /* In FIELD_DECL, this is DECL_PADDING_P. + In VAR_DECL, this is DECL_NOT_OBSERVABLE. */ unsigned decl_flag_3 : 1; /* Logically, these two would go in a theoretical base shared by var and parm decl. */ diff --git a/gcc/tree.h b/gcc/tree.h index 23223ca0c87..7ba88fd16db 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3221,6 +3221,11 @@ extern void decl_fini_priority_insert (tree, priority_type); #define DECL_NONALIASED(NODE) \ (VAR_DECL_CHECK (NODE)->base.nothrow_flag) +/* In a VAR_DECL, nonzero if this variable is not observable by user code (and + so e.g. it can be promoted to static even if it's addressable). */ +#define DECL_NOT_OBSERVABLE(NODE) \ + (VAR_DECL_CHECK (NODE)->decl_common.decl_flag_3) + /* This field is used to reference anything in decl.result and is meant only for use by the garbage collector. */ #define DECL_RESULT_FLD(NODE) \ diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 14aa96dd328..a9052c64265 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -4247,7 +4247,9 @@ maybe_init_list_as_array (tree elttype, tree init) init_elttype = cp_build_qualified_type (init_elttype, TYPE_QUAL_CONST); tree arr = build_array_of_n_type (init_elttype, CONSTRUCTOR_NELTS (init)); - return finish_compound_literal (arr, init, tf_none); + arr = finish_compound_literal (arr, init, tf_none); + DECL_NOT_OBSERVABLE (TARGET_EXPR_SLOT (arr)) = true; + return arr; } /* If we were going to call e.g. vector(initializer_list) starting diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 250782b1140..87c913c48c5 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -5234,7 +5234,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && TREE_READONLY (object) && VAR_P (object) && !DECL_REGISTER (object) - && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)) + && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object) + || DECL_NOT_OBSERVABLE (object)) /* For ctors that have many repeated nonzero elements represented through RANGE_EXPRs, prefer initializing those through runtime loops over copies of large amounts diff --git a/gcc/testsuite/g++.dg/tree-ssa/initlist-opt1.C b/gcc/testsuite/g++.dg/tree-ssa/initlist-opt1.C index 053317b59d8..b1d2d25faf4 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/initlist-opt1.C +++ b/gcc/testsuite/g++.dg/tree-ssa/initlist-opt1.C @@ -4,6 +4,7 @@ // Test that we do range-initialization from const char *. // { dg-final { scan-tree-dump {_M_range_initialize} "gimple" } } +// { dg-final { scan-tree-dump {static const char.*72} "gimple" } } #include #include diff --git a/gcc/testsuite/g++.dg/tree-ssa/initlist-opt2.C b/gcc/testsuite/g++.dg/tree-ssa/initlist-opt2.C index fc928bb5405..6730b758ac7 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/initlist-opt2.C +++ b/gcc/testsuite/g++.dg/tree-ssa/initlist-opt2.C @@ -4,6 +4,7 @@ // Check that we call the basic_string constructor once (and define it once). // { dg-final { scan-tree-dump-times {>::basic_string} 2 "gimple" } } +// { dg-final { scan-tree-dump {static const char.*72} "gimple" } } #include base-commit: bd0485f20f4794f9787237706a6308473a8e9415 -- 2.31.1