public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH to add -fno-lifetime-dse
@ 2015-02-12 20:28 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2015-02-12 20:28 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

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.

[-- Attachment #2: lifetime.patch --]
[-- Type: text/x-patch, Size: 3828 bytes --]

commit ca9986d97112f804e4cc416b15f9baf74d713aab
Author: Jason Merrill <jason@redhat.com>
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();
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-02-12 20:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-12 20:28 C++ PATCH to add -fno-lifetime-dse Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).