From patchwork Tue Nov 24 03:22:41 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 547806 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 651DA1401F6 for ; Tue, 24 Nov 2015 14:23:18 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Tsrata8B; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; q=dns; s=default; b=C0L65piR0tWS3yh mz8Yo8+ZmN6uF6GxnMlcnCcMOnUM/dBLTQAwvEBtFlUMKHVdJp5h3Q0BxkD2/fWK Uxmx4GQQhvjc/YCV3tg5NtJIWUC0clqQ5Z6fNrHZ5KOHQW4iqCgkdwGzUhbjXNaj Xwiftdklw+6VFsT6GczW1/edO4Ws= 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 :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; s=default; bh=2QkEi29Mz3VYTXyR3kmSu QqTvRo=; b=Tsrata8BW0CE6AQ0DkKIpVQgeJukzP4J9/bnVvN/j3J+GLGeqEiP5 mB5A9kx8Zb05rmfRFECr35n+rVRNKUmP1h44Or1lrx7MbuXff08AuEEzj8voxjUp /P/FiNchvJ0TpmE8lrvKc4K+nVwQPw6Q3wJ5/rCCko63MX8ywexJMI= Received: (qmail 93220 invoked by alias); 24 Nov 2015 03:23:10 -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 93165 invoked by uid 89); 24 Nov 2015 03:23:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-oi0-f51.google.com Received: from mail-oi0-f51.google.com (HELO mail-oi0-f51.google.com) (209.85.218.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 24 Nov 2015 03:23:02 +0000 Received: by oiww189 with SMTP id w189so2600604oiw.3 for ; Mon, 23 Nov 2015 19:23:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-type; bh=u0SKvsRfJ5T68CY0bb5deTVW1Sxr61pMRxmTSk1FZWs=; b=h4inDJFlsFcOnQ6BYGXy7wkSAQ8kTD10orfM1+z0TJIJEeCh5+CJ/sK4yV6vlzkIB/ YTNgvQ6kuowlPFhhJJyynFHY50O2G/EsbpUUhmiVOTGIxC7PtABVAk7i1hR4Ruc0/qgf lyH7Oi0KrfOnnUwasY5xUApUhGxnLlZJb9/RQJYbrVstozYoD+uyeItXc4P6NXdmH3LE sPoOp4ugDIUHAsAvtmag8/vr94xLWRGVYzXEbNwl0drLhzmxkpSBSJx2BloUUwl8lQGH wXecTQBTDJ6sdMY/kUSt/1E3qL7fTATZ9cVvc5SvF5uy5ZWDr65cZ/6L6HgqNwQjyarD rJRA== X-Gm-Message-State: ALoCoQk0kJn5Bzf5hxhLuYerkOidPQ9yIDPmTfJqeDJFU+8rsHPKk0oI+vetKy/KKk83bd6FwXTj X-Received: by 10.202.76.87 with SMTP id z84mr15892169oia.92.1448335380521; Mon, 23 Nov 2015 19:23:00 -0800 (PST) MIME-Version: 1.0 Received: by 10.182.93.197 with HTTP; Mon, 23 Nov 2015 19:22:41 -0800 (PST) In-Reply-To: References: <1447758067-4440-1-git-send-email-hjl.tools@gmail.com> <564F9BE9.5040003@redhat.com> From: Patrick Palka Date: Mon, 23 Nov 2015 22:22:41 -0500 Message-ID: Subject: Re: [PATCH] Add LANG_HOOKS_EMPTY_RECORD_P for C++ empty class To: "H.J. Lu" Cc: Richard Biener , Jason Merrill , GCC Patches On Mon, Nov 23, 2015 at 3:53 PM, H.J. Lu wrote: > On Mon, Nov 23, 2015 at 1:57 AM, Richard Biener > wrote: >> On Sat, Nov 21, 2015 at 12:46 AM, H.J. Lu wrote: >>> On Fri, Nov 20, 2015 at 2:17 PM, Jason Merrill wrote: >>>> On 11/20/2015 01:52 PM, H.J. Lu wrote: >>>>> >>>>> On Tue, Nov 17, 2015 at 4:22 AM, Richard Biener >>>>> wrote: >>>>>> >>>>>> On Tue, Nov 17, 2015 at 12:01 PM, H.J. Lu wrote: >>>>>>> >>>>>>> Empty record should be returned and passed the same way in C and C++. >>>>>>> This patch adds LANG_HOOKS_EMPTY_RECORD_P for C++ empty class, which >>>>>>> defaults to return false. For C++, LANG_HOOKS_EMPTY_RECORD_P is defined >>>>>>> to is_really_empty_class, which returns true for C++ empty classes. For >>>>>>> LTO, we stream out a bit to indicate if a record is empty and we store >>>>>>> it in TYPE_LANG_FLAG_0 when streaming in. get_ref_base_and_extent is >>>>>>> changed to set bitsize to 0 for empty records. Middle-end and x86 >>>>>>> backend are updated to ignore empty records for parameter passing and >>>>>>> function value return. Other targets may need similar changes. >>>>>> >>>>>> >>>>>> Please avoid a new langhook for this and instead claim a bit in >>>>>> tree_type_common >>>>>> like for example restrict_flag (double-check it is unused for >>>>>> non-pointers). >>>>> >>>>> >>>>> There is no bit in tree_type_common I can overload. restrict_flag is >>>>> checked for non-pointers to issue an error when it is used on >>>>> non-pointers: >>>>> >>>>> >>>>> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.dg/template/qualttp20.C:19:38: >>>>> error: ‘__restrict__’ qualifiers cannot be applied to ‘AS::L’ >>>>> typedef typename T::L __restrict__ r;// { dg-error "'__restrict__' >>>>> qualifiers cannot" "" } >>>> >>>> >>>> The C++ front end only needs to check TYPE_RESTRICT for this purpose on >>>> front-end-specific type codes like TEMPLATE_TYPE_PARM; cp_type_quals could >>>> handle that specifically if you change TYPE_RESTRICT to only apply to >>>> pointers. >>>> >>> >>> restrict_flag is also checked in this case: >>> >>> [hjl@gnu-6 gcc]$ cat x.i >>> struct dummy { }; >>> >>> struct dummy >>> foo (struct dummy __restrict__ i) >>> { >>> return i; >>> } >>> [hjl@gnu-6 gcc]$ gcc -S x.i -Wall >>> x.i:4:13: error: invalid use of ‘restrict’ >>> foo (struct dummy __restrict__ i) >>> ^ >>> x.i:4:13: error: invalid use of ‘restrict’ >>> [hjl@gnu-6 gcc]$ >>> >>> restrict_flag can't also be used to indicate `i' is an empty record. >> >> I'm sure this error can be done during parsing w/o relying on TYPE_RESTRICT. >> >> But well, use any other free bit (but do not enlarge >> tree_type_common). Eventually >> you can free up a bit by putting sth into type_lang_specific currently >> using bits >> in tree_type_common. > > There are no bits in tree_type_common I can move. Instead, > this patch overloads side_effects_flag in tree_base. Tested on > Linux/x86-64. OK for trunk? > Hi, Coincidentally a few months ago I was experimenting with making empty-struct function arguments zero-cost (and thus making them behave the same way as in GNU C). My approach (patch attached) was to assign empty-struct arguments to a virtual register (instead of on the stack or to a hard register) during RTL call expansion. These virtual-register assignments would then be trivially DCE'd later. This approach seemed to work surprisingly well with minimal code changes. I wonder what your thoughts are on this approach.. From 8eb52639992ad0f6e5482783604f362bcc04d230 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Mon, 23 Nov 2015 21:02:09 -0500 Subject: [PATCH] zero-cost structs --- gcc/calls.c | 15 +++++++++++++++ gcc/tree-tailcall.c | 7 ++++++- gcc/tree.c | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/gcc/calls.c b/gcc/calls.c index b56556a..4ca668c 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1394,6 +1394,21 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args[i].reg = targetm.calls.function_arg (args_so_far, mode, type, argpos < n_named_args); + bool empty_record_or_union_type_p (const_tree); + + if (type != NULL_TREE +#if 0 + /* ??? This condition was necessary to fix a C regression whose + details I have forgot about. In GNU C the mode of an empty struct is BLKmode + (and TYPE_SIZE 0) so this condition makes it so that we don't mess + with the codegen of empty structs in C. In C++ the mode of the empty struct + is QImode and TYPE_SIZE_UNIT 1. Maybe it's not necessary anymore? */ + && mode != BLKmode +#endif + && args[i].reg == NULL_RTX + && empty_record_or_union_type_p (type)) + args[i].reg = gen_reg_rtx (mode); + if (args[i].reg && CONST_INT_P (args[i].reg)) { args[i].special_slot = args[i].reg; diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index bbd1b29..fa8f66a 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -497,6 +497,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret) tail_recursion = true; } + bool empty_record_or_union_type_p (const_tree); + /* Make sure the tail invocation of this function does not refer to local variables. */ FOR_EACH_LOCAL_DECL (cfun, idx, var) @@ -504,7 +506,10 @@ find_tail_calls (basic_block bb, struct tailcall **ret) if (TREE_CODE (var) != PARM_DECL && auto_var_in_fn_p (var, cfun->decl) && (ref_maybe_used_by_stmt_p (call, var) - || call_may_clobber_ref_p (call, var))) + || call_may_clobber_ref_p (call, var)) + /* This change does the same thing as your aliasing change, to allow + tail calling of functions taking by argument empty structs. */ + && !empty_record_or_union_type_p (TREE_TYPE (var))) return; } diff --git a/gcc/tree.c b/gcc/tree.c index 779fe93..f710d15 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9069,6 +9069,23 @@ auto_var_in_fn_p (const_tree var, const_tree fn) || TREE_CODE (var) == RESULT_DECL)); } +/* Return true if if type TYPE is an empty record or union type. */ + +/* This predicate is inferior to your TYPE_EMPTY_RECORD-flag approach. */ + +bool +empty_record_or_union_type_p (const_tree type) +{ + if (!RECORD_OR_UNION_TYPE_P (type)) + return false; + + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + return false; + + return true; +} + /* Subprogram of following function. Called by walk_tree. Return *TP if it is an automatic variable or parameter of the -- 2.6.3.424.g74c917e.dirty