From patchwork Thu Mar 5 23:25:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 446957 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 209C51400DE for ; Fri, 6 Mar 2015 10:25:22 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=TomtNVwA; dkim-adsp=none (unprotected policy); 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 :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=B/02OH7EWGnda2Ehh8OOfnH6k+HjuCJm+wSSrJui7MOFDd JBfe/5e4ARPlo0j8SjWIEUZhn9yIQhA29EdNmlBl1XqyWPd4K2JI7+n/4pO89tzP kWRLXNssnmOGk1ivYcbAhQB60nTrl72e0KSWMZSlAhnxar/KKp6rm9hLn1mBA= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=TVRVnxWcLez+MtGrcweax2x3+JY=; b=TomtNVwAx7YFAuPd+5oq ikWYHou1/+bckPtr0OjyL+TViaKNiaSSCjsgcVmX125EERmnvp1C5+U2aGZnohAV XZsIltxm5A7300k0ooETRLWBXK0jPrE7Ewmj0yB8xplszPot79fmGHVJ8fmWiRAM 479E+SuPoHNx1xaL3jAi8TI= Received: (qmail 46600 invoked by alias); 5 Mar 2015 23:25:14 -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 46514 invoked by uid 89); 5 Mar 2015 23:25:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 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; Thu, 05 Mar 2015 23:25:09 +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 t25NP8KF006760 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 5 Mar 2015 18:25:08 -0500 Received: from reynosa.quesejoda.com (vpn-62-162.rdu2.redhat.com [10.10.62.162]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t25NP7Sb018534; Thu, 5 Mar 2015 18:25:07 -0500 Message-ID: <54F8E5D3.4050607@redhat.com> Date: Thu, 05 Mar 2015 15:25:07 -0800 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: jason merrill , gcc-patches Subject: [patch] Optimize empty class copies within a C++ return statement While looking at PR65284, I was confused by the gimple we generate for returns of empty classes by value: class obj { public: obj(int); }; obj funky(){ return obj(555); } For the above snippet, we generate: obj funky() () { struct obj D.2248; struct obj D.2246; obj::obj (&D.2246, 555); try { return D.2248; } finally { D.2246 = {CLOBBER}; } } Particularly confusing is the return of uninitialized D.2248. Jason tried to beat into me today the fact that it doesn't matter because there is no value to initialize since the class is empty. I still think it's weird, however... What led us to the above gimple was the fact that we lowered into: return retval = D.2248 = D.2246 which was later optimized by cp_gimplify_expr into "return D.2248" because the C++ gimplifier hook notices that the copy is unnecessary. Jason suggested that it would be nice to remove D.2248 altogether. With the attached patch we notice the superfluous copy in the return value and optimize it away. After some hoops we now get: obj::obj (&D.2246, 555); try { return ; } finally { D.2246 = {CLOBBER}; } Tested on x86-64 Linux. OK? commit 8fd545d608f2a6c11f889e11c700711b8f911c02 Author: Aldy Hernandez Date: Thu Mar 5 12:23:27 2015 -0800 * cp-gimplify.c (cp_gimplify_expr): Optimize empty class copies within a return statement. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 4233a64..f8d4559 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -740,6 +740,29 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) } break; + case RETURN_EXPR: + { + /* Optimize `return = object' where object's type is + an empty class. Avoid the copy, altogether and just return + retval. */ + tree ret = TREE_OPERAND (*expr_p, 0); + if (ret && (TREE_CODE (ret) == INIT_EXPR + || TREE_CODE (ret) == MODIFY_EXPR) + && TREE_CODE (TREE_OPERAND (ret, 0)) == RESULT_DECL + && is_gimple_lvalue (TREE_OPERAND (ret, 0)) + && is_really_empty_class (TREE_TYPE (TREE_OPERAND (ret, 0)))) + { + tree result_decl = TREE_OPERAND (ret, 0); + tree list = alloc_stmt_list (); + append_to_statement_list (TREE_OPERAND (ret, 1), &list); + append_to_statement_list (build1 (RETURN_EXPR, void_type_node, + result_decl), &list); + *expr_p = list; + return GS_OK; + } + /* Otherwise fall through. */ + } + default: ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); break; diff --git a/gcc/testsuite/g++.dg/other/empty-class.C b/gcc/testsuite/g++.dg/other/empty-class.C new file mode 100644 index 0000000..a14c437 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/empty-class.C @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +/* Test that we return retval directly, instead of going through an + intermediate temporary, when returning an empty class. */ + +class obj { + public: + obj(int); +}; + +obj funky(){ + return obj(555); +} + +/* { dg-final { scan-tree-dump-times "return ;" 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */