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.1] Fix PR rtl-optimization/30931


It's again a regression from the 3.x series present on the 4.1 branch and due 
to the old loop optimizer, a variant of PR rtl-optimization/30787.

The GIV associated with the second p[i].first

  for (i=0; i < 2; i++)
      while (p[i].first && p[i].done)
        p[i].first = 0;

is correctly detected as not "always executed", but it is nevertheless reduced 
because it is first combined with the "always executed" first p[i].first.

Fixed by disallowing combining for GIVs that are not "always executed".  
Bootstrapped/regtested on x86_64-suse-linux and applied to 4.1 branch.


2007-02-27  Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR rtl-optimization/30931
        * loop.c (combine_givs_p): Return false if either GIV is not
	always executed.


2007-02-27  Eric Botcazou  <ebotcazou@libertysurf.fr>

        * gcc.c-torture/execute/20070227-1.c: New test.


-- 
Eric Botcazou
Index: loop.c
===================================================================
--- loop.c	(revision 122251)
+++ loop.c	(working copy)
@@ -8700,6 +8700,10 @@ combine_givs_p (struct induction *g1, st
 {
   rtx comb, ret;
 
+  /* We cannot combine givs that are not always in sync.  */
+  if (!g1->always_executed || !g2->always_executed)
+    return NULL_RTX;
+
   /* With the introduction of ext dependent givs, we must care for modes.
      G2 must not use a wider mode than G1.  */
   if (GET_MODE_SIZE (g1->mode) < GET_MODE_SIZE (g2->mode))
@@ -8708,6 +8712,7 @@ combine_givs_p (struct induction *g1, st
   ret = comb = express_from (g1, g2);
   if (comb == NULL_RTX)
     return NULL_RTX;
+
   if (g1->mode != g2->mode)
     ret = gen_lowpart (g2->mode, comb);
 
@@ -8718,9 +8723,7 @@ combine_givs_p (struct induction *g1, st
      combination to be the other way round.  */
   if (comb == g1->dest_reg
       && (g1->giv_type == DEST_REG || g2->giv_type == DEST_ADDR))
-    {
-      return ret;
-    }
+    return ret;
 
   /* If G2 can be expressed as a function of G1 and that function is valid
      as an address and no more expensive than using a register for G2,
/* PR rtl-optimization/30931 */
/* Testcase by Peter Bergner <bergner@gcc.gnu.org> */

struct s
{
  int first;
  int done;
};

void bug (struct s *p)
{
  int i;
  for (i=0; i < 2; i++)
    {
      while (p[i].first && p[i].done)
        p[i].first = 0;
    }
}

int main (void)
{
  struct s array[2];
  array[0].first = 1;
  array[0].done = 1;
  array[1].first = 0;
  array[1].done = 0;

  bug (array);

  return 0;
}

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