This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[4.0 PATCH] Backport find_first_parameter_load fix (PR rtl-optimization/23299)


Hi!

The testcase below is miscompiled, because insert_insn_end_bb
inserts the hoisted insn before the instruction that sets up
the pseudo it is using.  When it is searching for a parameter
load of a call with EH edge and the parameter load has been CSEd
out (r3 is incoming argument as well as outgoing argument and contains the
same value), it will keep searching till the beginning of the BB.
This has been fixed on mainline by Dale Johannesen, ok for
4.0 (and the testcase for HEAD as well)?
Bootstrapped/regtested on {i386,x86_64,ia64,ppc,ppc64,s390,s390x}-linux.

2005-08-11  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/23299
	Backport from mainline
	2005-03-16 Dale Johannesen  <dalej@apple.com>
	* rtlanal.c (find_first_parameter_load):  Rewrite to
	return actual first param load or the call if none,
	instead of first in block, when not all loads exist.

	* g++.dg/opt/pr23299.C: New test.

--- gcc/rtlanal.c	11 Mar 2005 03:14:44 -0000	1.212
+++ gcc/rtlanal.c	16 Mar 2005 20:42:37 -0000	1.213
@@ -3159,12 +3159,15 @@ parms_set (rtx x, rtx pat ATTRIBUTE_UNUS
 }
 
 /* Look backward for first parameter to be loaded.
+   Note that loads of all parameters will not necessarily be
+   found if CSE has eliminated some of them (e.g., an argument
+   to the outer function is passed down as a parameter).
    Do not skip BOUNDARY.  */
 rtx
 find_first_parameter_load (rtx call_insn, rtx boundary)
 {
   struct parms_set_data parm;
-  rtx p, before;
+  rtx p, before, first_set;
 
   /* Since different machines initialize their parameter registers
      in different orders, assume nothing.  Collect the set of all
@@ -3186,6 +3189,7 @@ find_first_parameter_load (rtx call_insn
 	parm.nregs++;
       }
   before = call_insn;
+  first_set = call_insn;
 
   /* Search backward for the first set of a register in this set.  */
   while (parm.nregs && before != boundary)
@@ -3208,9 +3212,20 @@ find_first_parameter_load (rtx call_insn
 	}
 
       if (INSN_P (before))
-	note_stores (PATTERN (before), parms_set, &parm);
+	{
+	  int nregs_old = parm.nregs;
+	  note_stores (PATTERN (before), parms_set, &parm);
+	  /* If we found something that did not set a parameter reg,
+	     we're done.  Do not keep going, as that might result
+	     in hoisting an insn before the setting of a pseudo
+	     that is used by the hoisted insn. */
+	  if (nregs_old != parm.nregs)
+	    first_set = before;
+	  else
+	    break;
+	}
     }
-  return before;
+  return first_set;
 }
 
 /* Return true if we should avoid inserting code between INSN and preceding
--- gcc/testsuite/g++.dg/opt/pr23299.C.jj	2005-08-09 19:59:26.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr23299.C	2005-08-09 19:59:38.000000000 +0200
@@ -0,0 +1,63 @@
+// PR rtl-optimization/23299
+// { dg-do run }
+// { dg-options "-Os" }
+
+extern "C" void abort ();
+
+struct A
+{
+  virtual int a () {}
+};
+struct B : public A
+{
+  virtual int b () {}
+};
+struct C : public A
+{
+  virtual int c () {}
+};
+struct D
+{
+  D () { d = 64; }
+  ~D ();
+  int d;
+};
+
+int x;
+D::~D ()
+{
+  x |= 1;
+  if (d != 64)
+    abort ();
+}
+
+struct E : public B, public C
+{
+  E () {}
+  virtual int c ();
+  ~E ();
+  D dv;
+};
+
+E::~E ()
+{
+  int r = c ();
+}
+
+int
+E::c ()
+{
+  if (x > 10)
+    throw 1;
+  x |= 2;
+}
+
+int
+main (void)
+{
+  {
+    E e;
+  }
+  if (x != 3)
+    abort ();
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]