From patchwork Thu Feb 12 20:28:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 439326 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 7ADE4140187 for ; Fri, 13 Feb 2015 07:41:52 +1100 (AEDT) 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=YvxYCcd9Gv0mXlGoq/Dt+oBLulX2+pJWJrMvFwcG5wHSsR RaSj9pnxbhlCqsO91iDrxp0b7lCW/o1TfjkxLz6RbrjxWDbq1Z6sudCCTKrxmArb d8X5YVsewcaksCR7VvhfYoPkbWL54BjEm7G/PTrsiHAkCGytcV12rMfTLx8vE= 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=OePa2A4geXE5QJgF02nGJhnyr2w=; b=XsopReIe1M3JRrw/d6ZY u3PeGFZ3WTXq/Vuv6VnXYz2wSAZpFZXilTehjbv01yp+xeIsuQajkM646/pSU4w1 aJUtmZCFC+H6ZGUyTa8qn4HG+8MzvW38ugzxCJo0sQbA+zPaDHVoHFDpsANU+s2P jIqqln0qbq0xQxbySz4fiGg= Received: (qmail 19304 invoked by alias); 12 Feb 2015 20:28: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 19278 invoked by uid 89); 12 Feb 2015 20:28:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL, BAYES_00, SPF_HELO_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, 12 Feb 2015 20:28:08 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t1CKS6mc017967 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 12 Feb 2015 15:28:07 -0500 Received: from [10.10.116.30] ([10.10.116.30]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t1CKS6lc003998 for ; Thu, 12 Feb 2015 15:28:06 -0500 Message-ID: <54DD0CD1.2040708@redhat.com> Date: Thu, 12 Feb 2015 15:28:01 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to add -fno-lifetime-dse Folks at Google reported to me that some packages they are building rely on changes to an object persisting in the underlying storage after the object is destroyed, and the more aggressive DSE in GCC 4.9 breaks this. Such code has undefined behavior, but this seems like a reasonable thing to have a flag for, along the lines of -fno-strict-aliasing. Tested x86_64-pc-linux-gnu, applying to trunk. commit ca9986d97112f804e4cc416b15f9baf74d713aab Author: Jason Merrill Date: Tue Feb 10 23:45:19 2015 -0500 gcc/ * common.opt (-flifetime-dse): New. gcc/cp/ * decl.c (begin_destructor_body): Condition clobber on -flifetime-dse. diff --git a/gcc/common.opt b/gcc/common.opt index cf4e503..6e65757 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1856,6 +1856,11 @@ fregmove Common Ignore Does nothing. Preserved for backward compatibility. +flifetime-dse +Common Report Var(flag_lifetime_dse) Init(1) Optimization +Tell DSE that the storage for a C++ object is dead when the constructor +starts and when the destructor finishes. + flive-range-shrinkage Common Report Var(flag_live_range_shrinkage) Init(0) Optimization Relief of register pressure through live range shrinkage diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 50b0624..810acd5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13936,15 +13936,19 @@ begin_destructor_body (void) initialize_vtbl_ptrs (current_class_ptr); finish_compound_stmt (compound_stmt); - /* Insert a cleanup to let the back end know that the object is dead - when we exit the destructor, either normally or via exception. */ - tree btype = CLASSTYPE_AS_BASE (current_class_type); - tree clobber = build_constructor (btype, NULL); - TREE_THIS_VOLATILE (clobber) = true; - tree bref = build_nop (build_reference_type (btype), current_class_ptr); - bref = convert_from_reference (bref); - tree exprstmt = build2 (MODIFY_EXPR, btype, bref, clobber); - finish_decl_cleanup (NULL_TREE, exprstmt); + if (flag_lifetime_dse) + { + /* Insert a cleanup to let the back end know that the object is dead + when we exit the destructor, either normally or via exception. */ + tree btype = CLASSTYPE_AS_BASE (current_class_type); + tree clobber = build_constructor (btype, NULL); + TREE_THIS_VOLATILE (clobber) = true; + tree bref = build_nop (build_reference_type (btype), + current_class_ptr); + bref = convert_from_reference (bref); + tree exprstmt = build2 (MODIFY_EXPR, btype, bref, clobber); + finish_decl_cleanup (NULL_TREE, exprstmt); + } /* And insert cleanups for our bases and members so that they will be properly destroyed if we throw. */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8a04790..5cce4f7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -7888,6 +7888,16 @@ registers after writing to their lower 32-bit half. Enabled for Alpha, AArch64 and x86 at levels @option{-O2}, @option{-O3}, @option{-Os}. +@item -fno-lifetime-dse +@opindex fno-lifetime-dse +In C++ the value of an object is only affected by changes within its +lifetime: when the constructor begins, the object has an indeterminate +value, and any changes during the lifetime of the object are dead when +the object is destroyed. Normally dead store elimination will take +advantage of this; if your code relies on the value of the object +storage persisting beyond the lifetime of the object, you can use this +flag to disable this optimization. + @item -flive-range-shrinkage @opindex flive-range-shrinkage Attempt to decrease register pressure through register live range diff --git a/gcc/testsuite/g++.dg/opt/flifetime-dse1.C b/gcc/testsuite/g++.dg/opt/flifetime-dse1.C new file mode 100644 index 0000000..733d28a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/flifetime-dse1.C @@ -0,0 +1,23 @@ +// { dg-options "-O3 -fno-lifetime-dse" } +// { dg-do run } + +typedef __SIZE_TYPE__ size_t; +inline void * operator new (size_t, void *p) { return p; } + +struct A +{ + int i; + A() {} + ~A() {} +}; + +int main() +{ + int ar[1]; + + A* ap = new(ar) A; + ap->i = 42; + ap->~A(); + + if (ar[0] != 42) __builtin_abort(); +}