From 5fad51c9dc8f0b7491e38e0fbd74dc229781421c Mon Sep 17 00:00:00 2001
From: rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri, 29 Mar 2002 06:19:36 +0000
Subject: [PATCH]         PR target/6087         * reload1.c
 (fixup_abnormal_edges): Move insn to edge via sequence.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51543 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                        |  5 +++
 gcc/reload1.c                        | 13 +++++++-
 gcc/testsuite/g++.dg/opt/reg-stack.C | 47 ++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/opt/reg-stack.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f4b73ff0ed1b..ff8c89471392 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2002-03-28  Richard Henderson  <rth@redhat.com>
+
+	PR target/6087
+	* reload1.c (fixup_abnormal_edges): Move insn to edge via sequence.
+
 2002-03-28  Alexandre Oliva  <aoliva@redhat.com>
 
 	* config/i386/freebsd.h (LINK_SPEC): Don't pass default
diff --git a/gcc/reload1.c b/gcc/reload1.c
index fce489da0d02..c36799f4381f 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -9517,8 +9517,19 @@ fixup_abnormal_edges ()
 	      next = NEXT_INSN (insn);
 	      if (INSN_P (insn))
 		{
-	          insert_insn_on_edge (PATTERN (insn), e);
+		  rtx seq;
+
 	          delete_insn (insn);
+
+		  /* We're not deleting it, we're moving it.  */
+		  INSN_DELETED_P (insn) = 0;
+
+		  /* Emit a sequence, rather than scarfing the pattern, so
+		     that we don't lose REG_NOTES etc.  */
+		  /* ??? Could copy the test from gen_sequence, but don't
+		     think it's worth the bother.  */
+		  seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
+	          insert_insn_on_edge (seq, e);
 		}
 	      insn = next;
 	    }
diff --git a/gcc/testsuite/g++.dg/opt/reg-stack.C b/gcc/testsuite/g++.dg/opt/reg-stack.C
new file mode 100644
index 000000000000..76d3cee1b016
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/reg-stack.C
@@ -0,0 +1,47 @@
+// PR target/6087
+// The code that moves around insns emitted by reg-stack to cope with
+// exception edges lost the REG_DEAD note indicating a pop.  Which
+// eventually fills up the register stack resulting in Z == NaN.
+
+// { dg-do run }
+// { dg-options "-O" }
+
+extern "C" void abort ();
+
+struct Base
+{
+  virtual ~Base() {}
+};
+
+struct Foo : public Base
+{
+  Foo ();
+};
+
+double x = 3;
+double y = 4;
+
+double bar ()
+{
+  double z = x*x+y*y;
+  if (z != 25.0)
+    throw 1;
+  return z;
+}
+
+Foo::Foo ()
+{
+  bar ();
+}
+
+int main ()
+{
+  try {
+    int i;
+    for (i = 0; i < 10; ++i)
+      new Foo;
+  } catch (...) {
+    abort ();
+  }
+  return 0;
+}
-- 
GitLab