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]

[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;
}

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