This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH/RFC] Fix PR optimization/11304
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 25 Jun 2003 00:34:34 +0200
- Subject: [PATCH/RFC] Fix PR optimization/11304
Hi,
This is a regression from GCC 3.0.4, present in all released versions since
then but already fixed on mainline. The function
int hux(int x)
{
if (x)
{
set_eax(0);
return x;
}
foo(x);
}
is miscompiled at -O -fomit-frame-pointer on x86: if x is not null, the
function will return 0 anyway, because it fails to restore %eax after the
call to set_eax().
The problem comes from the cross-jumping pass: it considers that the
predecessors of two edges with the same destination block share common code.
Now the first one sets %eax, while the second one only clobbers %eax. So we
end up with a SET before a CLOBBER and the SET is deleted.
This was recently fixed on mainline by
2003-04-18 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* cfgcleanup.c (flow_find_cross_jump): Use INSN_P, not active_insn_p.
but Jan seemed to have some reserve:
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg01445.html
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg01482.html
Is this patch appropriate for a backport? Do we want to fix the bug on the
3.3 branch?
--
Eric Botcazou
2003-06-24 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/11304
Backport from mainline:
2003-04-18 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* cfgcleanup.c (flow_find_cross_jump): Use INSN_P, not active_insn_p.
2003-06-24 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/i386-call-1.c: New test.
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -p -r1.81 -r1.82
--- cfgcleanup.c 30 Mar 2003 20:46:56 -0000 1.81
+++ cfgcleanup.c 18 Apr 2003 22:34:20 -0000 1.82
@@ -1044,10 +1044,10 @@ flow_find_cross_jump (mode, bb1, bb2, f1
while (true)
{
/* Ignore notes. */
- while (!active_insn_p (i1) && i1 != bb1->head)
+ while (!INSN_P (i1) && i1 != bb1->head)
i1 = PREV_INSN (i1);
- while (!active_insn_p (i2) && i2 != bb2->head)
+ while (!INSN_P (i2) && i2 != bb2->head)
i2 = PREV_INSN (i2);
if (i1 == bb1->head || i2 == bb2->head)
@@ -1056,8 +1056,8 @@ flow_find_cross_jump (mode, bb1, bb2, f1
if (!insns_match_p (mode, i1, i2))
break;
- /* Don't begin a cross-jump with a USE or CLOBBER insn. */
- if (active_insn_p (i1))
+ /* Don't begin a cross-jump with a NOTE insn. */
+ if (INSN_P (i1))
{
/* If the merged insns have different REG_EQUAL notes, then
remove them. */
@@ -1096,13 +1096,13 @@ flow_find_cross_jump (mode, bb1, bb2, f1
Two, it keeps line number notes as matched as may be. */
if (ninsns)
{
- while (last1 != bb1->head && !active_insn_p (PREV_INSN (last1)))
+ while (last1 != bb1->head && !INSN_P (PREV_INSN (last1)))
last1 = PREV_INSN (last1);
if (last1 != bb1->head && GET_CODE (PREV_INSN (last1)) == CODE_LABEL)
last1 = PREV_INSN (last1);
- while (last2 != bb2->head && !active_insn_p (PREV_INSN (last2)))
+ while (last2 != bb2->head && !INSN_P (PREV_INSN (last2)))
last2 = PREV_INSN (last2);
if (last2 != bb2->head && GET_CODE (PREV_INSN (last2)) == CODE_LABEL)
/* PR optimization/11304 */
/* Originator: <manuel.serrano@sophia.inria.fr> */
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-O -fomit-frame-pointer" } */
/* Verify that %eax is always restored after a call. */
extern void abort(void);
volatile int r;
void set_eax(int val)
{
__asm__ __volatile__ ("mov %0, %%eax" : : "m" (val));
}
void foo(int val)
{
r = val;
}
int bar(int x)
{
if (x)
{
set_eax(0);
return x;
}
foo(x);
}
int main(void)
{
if (bar(1) != 1)
abort();
return 0;
}