This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[4.0 PATCH] Backport find_first_parameter_load fix (PR rtl-optimization/23299)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 11 Aug 2005 02:21:01 -0400
- Subject: [4.0 PATCH] Backport find_first_parameter_load fix (PR rtl-optimization/23299)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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