[vta, PR41926, graphite?] track debug uses during vectorization

View: New views
3 Messages — Rating Filter:   Alert me  

[vta, PR41926, graphite?] track debug uses during vectorization

by Alexandre Oliva-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

PR debug/41926 was a case in which a debug use outside a vectorized loop
remained, referencing an SSA DEF that no longer dominated the use
because of vectorization.

In order to fix this, I extended the live-tracking information so as to
record debug uses in addition to nondebug uses.  Then, if a name in the
vectorized loop is found to be referenced outside the loop only by debug
insns (case in which we won't create a PHI node at the join point), we
reset the debug use.

I managed to convert the testcase to C, but it requires the patch I've
just posted to exercise the bug fixed by the patch below.  I'm not happy
with the options-management in this testcase, though.  I need
-ffast-math and -funroll-loops to trigger it, so the standard names
handled by vect.exp don't work, and I can't add options to the default
per-machine vectorization options vect.exp sets up.  So I made in
x86-only, but I'd appreciate suggestions on how to make it better.
Anyone?

Bootstrapped on x86_64-linux-gnu; regstrapping on that and
ia64-linux-gnu.  Ok to install?


for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@...>

        PR debug/41926
        * tree-vectorizer.h (enum vect_live): New.
        (struct _stmt_vec_info): Change type of live to it.
        (STMT_VINFO_LIVE_P): Adjust.
        (STMT_VINFO_LIVE): New.
        (STMT_VINFO_LIVE_IN_DEBUG_ONLY_P): New.
        * tree-vect-loop.c (vect_loop_kill_debug_uses): New.
        (vect_transform_loop): Call it.
        * tree-vect-stmts.c (vect_mark_relevant): Use new type and macros.
        (vect_stmt_relevant_p): Use new enum type and values.
        (process_use): Use new type.  Adjust comments.
        (vect_mark_stmts_to_be_vectorized): Likewise.
        (new_stmt_vec_info): Use new enum type and values.

for  gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@...>

        PR debug/41926
        * gcc.dg/vect/vect-debug-pr41926.c: New.

Index: gcc/tree-vectorizer.h
===================================================================
--- gcc/tree-vectorizer.h.orig 2009-11-05 04:26:06.000000000 -0200
+++ gcc/tree-vectorizer.h 2009-11-05 04:36:47.000000000 -0200
@@ -359,6 +359,14 @@ enum vect_relevant {
   vect_used_in_scope
 };
 
+/* Indicates how a variable is used outside the loop.  This is used
+   sort of like an array of booleans.  */
+enum vect_live {
+  vect_dead = 0,
+  vect_live_for_debug = 1,
+  vect_live_for_real = 2
+};
+
 /* The type of vectorization that can be applied to the stmt: regular loop-based
    vectorization; pure SLP - the stmt is a part of SLP instances and does not
    have uses outside SLP instances; or hybrid SLP and loop-based - the stmt is
@@ -403,7 +411,7 @@ typedef struct _stmt_vec_info {
 
   /* Indicates whether this stmts is part of a computation whose result is
      used outside the loop.  */
-  bool live;
+  enum vect_live live;
 
   /* The vector type to be used.  */
   tree vectype;
@@ -489,7 +497,11 @@ typedef struct _stmt_vec_info {
 #define STMT_VINFO_LOOP_VINFO(S)           (S)->loop_vinfo
 #define STMT_VINFO_BB_VINFO(S)             (S)->bb_vinfo
 #define STMT_VINFO_RELEVANT(S)             (S)->relevant
-#define STMT_VINFO_LIVE_P(S)               (S)->live
+#define STMT_VINFO_LIVE(S)   (S)->live
+#define STMT_VINFO_LIVE_P(S)               (STMT_VINFO_LIVE (S) \
+    > vect_live_for_debug)
+#define STMT_VINFO_LIVE_IN_DEBUG_ONLY_P(S) (STMT_VINFO_LIVE (S) \
+    == vect_live_for_debug)
 #define STMT_VINFO_VECTYPE(S)              (S)->vectype
 #define STMT_VINFO_VEC_STMT(S)             (S)->vectorized_stmt
 #define STMT_VINFO_DATA_REF(S)             (S)->data_ref_info
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c.orig 2009-11-05 04:26:06.000000000 -0200
+++ gcc/tree-vect-loop.c 2009-11-05 04:36:47.000000000 -0200
@@ -4112,6 +4112,44 @@ vectorizable_live_operation (gimple stmt
   return true;
 }
 
+/* Kill any debug uses outside LOOP of SSA names defined in STMT.  */
+
+static void
+vect_loop_kill_debug_uses (struct loop *loop, gimple stmt)
+{
+  ssa_op_iter op_iter;
+  imm_use_iterator imm_iter;
+  def_operand_p def_p;
+  gimple ustmt;
+
+  FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
+    {
+      FOR_EACH_IMM_USE_STMT (ustmt, imm_iter, DEF_FROM_PTR (def_p))
+ {
+  basic_block bb;
+
+  if (!is_gimple_debug (ustmt))
+    continue;
+
+  bb = gimple_bb (ustmt);
+
+  if (!flow_bb_inside_loop_p (loop, bb))
+    {
+      if (gimple_debug_bind_p (ustmt))
+ {
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "killing debug use");
+
+  gimple_debug_bind_reset_value (ustmt);
+  update_stmt (ustmt);
+ }
+      else
+ gcc_unreachable ();
+    }
+ }
+    }
+}
+
 /* Function vect_transform_loop.
 
    The analysis phase has determined that the loop is vectorizable.
@@ -4202,7 +4240,11 @@ vect_transform_loop (loop_vec_info loop_
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info)
       && !STMT_VINFO_LIVE_P (stmt_info))
-    continue;
+    {
+      if (STMT_VINFO_LIVE_IN_DEBUG_ONLY_P (stmt_info))
+ vect_loop_kill_debug_uses (loop, phi);
+      continue;
+    }
 
   if ((TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info))
         != (unsigned HOST_WIDE_INT) vectorization_factor)
@@ -4242,6 +4284,8 @@ vect_transform_loop (loop_vec_info loop_
   if (!STMT_VINFO_RELEVANT_P (stmt_info)
       && !STMT_VINFO_LIVE_P (stmt_info))
     {
+      if (STMT_VINFO_LIVE_IN_DEBUG_ONLY_P (stmt_info))
+ vect_loop_kill_debug_uses (loop, stmt);
       gsi_next (&si);
       continue;
     }
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c.orig 2009-11-05 04:26:06.000000000 -0200
+++ gcc/tree-vect-stmts.c 2009-11-05 04:36:47.000000000 -0200
@@ -49,14 +49,14 @@ along with GCC; see the file COPYING3.  
 
 static void
 vect_mark_relevant (VEC(gimple,heap) **worklist, gimple stmt,
-    enum vect_relevant relevant, bool live_p)
+    enum vect_relevant relevant, enum vect_live live)
 {
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   enum vect_relevant save_relevant = STMT_VINFO_RELEVANT (stmt_info);
-  bool save_live_p = STMT_VINFO_LIVE_P (stmt_info);
+  enum vect_live save_live = STMT_VINFO_LIVE (stmt_info);
 
   if (vect_print_dump_info (REPORT_DETAILS))
-    fprintf (vect_dump, "mark relevant %d, live %d.", relevant, live_p);
+    fprintf (vect_dump, "mark relevant %d, live %d.", relevant, live);
 
   if (STMT_VINFO_IN_PATTERN_P (stmt_info))
     {
@@ -74,16 +74,17 @@ vect_mark_relevant (VEC(gimple,heap) **w
       stmt_info = vinfo_for_stmt (pattern_stmt);
       gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
       save_relevant = STMT_VINFO_RELEVANT (stmt_info);
-      save_live_p = STMT_VINFO_LIVE_P (stmt_info);
+      save_live = STMT_VINFO_LIVE (stmt_info);
       stmt = pattern_stmt;
     }
 
-  STMT_VINFO_LIVE_P (stmt_info) |= live_p;
+  STMT_VINFO_LIVE (stmt_info) = (enum vect_live)
+    (STMT_VINFO_LIVE (stmt_info) | live);
   if (relevant > STMT_VINFO_RELEVANT (stmt_info))
     STMT_VINFO_RELEVANT (stmt_info) = relevant;
 
   if (STMT_VINFO_RELEVANT (stmt_info) == save_relevant
-      && STMT_VINFO_LIVE_P (stmt_info) == save_live_p)
+      && STMT_VINFO_LIVE (stmt_info) == save_live)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "already marked relevant/live.");
@@ -108,7 +109,7 @@ vect_mark_relevant (VEC(gimple,heap) **w
 
 static bool
 vect_stmt_relevant_p (gimple stmt, loop_vec_info loop_vinfo,
-      enum vect_relevant *relevant, bool *live_p)
+      enum vect_relevant *relevant, enum vect_live *live)
 {
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   ssa_op_iter op_iter;
@@ -117,7 +118,7 @@ vect_stmt_relevant_p (gimple stmt, loop_
   def_operand_p def_p;
 
   *relevant = vect_unused_in_scope;
-  *live_p = false;
+  *live = vect_dead;
 
   /* cond stmt other than loop exit cond.  */
   if (is_ctrl_stmt (stmt)
@@ -146,19 +147,22 @@ vect_stmt_relevant_p (gimple stmt, loop_
  fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
 
       if (is_gimple_debug (USE_STMT (use_p)))
- continue;
+ {
+  *live = vect_live_for_debug;
+  continue;
+ }
 
       /* We expect all such uses to be in the loop exit phis
  (because of loop closed form)   */
       gcc_assert (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI);
       gcc_assert (bb == single_exit (loop)->dest);
 
-              *live_p = true;
+      *live = vect_live_for_real;
     }
  }
     }
 
-  return (*live_p || *relevant);
+  return (*live || *relevant);
 }
 
 
@@ -212,14 +216,14 @@ exist_non_indexing_operands_for_use_p (t
 
    Inputs:
    - a USE in STMT in a loop represented by LOOP_VINFO
-   - LIVE_P, RELEVANT - enum values to be set in the STMT_VINFO of the stmt
+   - LIVE, RELEVANT - enum values to be set in the STMT_VINFO of the stmt
      that defined USE. This is done by calling mark_relevant and passing it
      the WORKLIST (to add DEF_STMT to the WORKLIST in case it is relevant).
 
    Outputs:
-   Generally, LIVE_P and RELEVANT are used to define the liveness and
+   Generally, LIVE and RELEVANT are used to define the liveness and
    relevance info of the DEF_STMT of this USE:
-       STMT_VINFO_LIVE_P (DEF_STMT_info) <-- live_p
+       STMT_VINFO_LIVE (DEF_STMT_info) <-- live
        STMT_VINFO_RELEVANT (DEF_STMT_info) <-- relevant
    Exceptions:
    - case 1: If USE is used only for address computations (e.g. array indexing),
@@ -233,8 +237,9 @@ exist_non_indexing_operands_for_use_p (t
    Return true if everything is as expected. Return false otherwise.  */
 
 static bool
-process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
-     enum vect_relevant relevant, VEC(gimple,heap) **worklist)
+process_use (gimple stmt, tree use, loop_vec_info loop_vinfo,
+     enum vect_live live, enum vect_relevant relevant,
+     VEC(gimple,heap) **worklist)
 {
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
@@ -360,7 +365,7 @@ process_use (gimple stmt, tree use, loop
         }
     }
 
-  vect_mark_relevant (worklist, def_stmt, relevant, live_p);
+  vect_mark_relevant (worklist, def_stmt, relevant, live);
   return true;
 }
 
@@ -394,7 +399,7 @@ vect_mark_stmts_to_be_vectorized (loop_v
   stmt_vec_info stmt_vinfo;
   basic_block bb;
   gimple phi;
-  bool live_p;
+  enum vect_live live;
   enum vect_relevant relevant, tmp_relevant;
   enum vect_def_type def_type;
 
@@ -416,8 +421,8 @@ vect_mark_stmts_to_be_vectorized (loop_v
       print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
     }
 
-  if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live_p))
-    vect_mark_relevant (&worklist, phi, relevant, live_p);
+  if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live))
+    vect_mark_relevant (&worklist, phi, relevant, live);
  }
       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
  {
@@ -428,8 +433,8 @@ vect_mark_stmts_to_be_vectorized (loop_v
       print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
     }
 
-  if (vect_stmt_relevant_p (stmt, loop_vinfo, &relevant, &live_p))
-            vect_mark_relevant (&worklist, stmt, relevant, live_p);
+  if (vect_stmt_relevant_p (stmt, loop_vinfo, &relevant, &live))
+            vect_mark_relevant (&worklist, stmt, relevant, live);
  }
     }
 
@@ -451,16 +456,16 @@ vect_mark_stmts_to_be_vectorized (loop_v
  liveness and relevance properties of STMT.  */
       stmt_vinfo = vinfo_for_stmt (stmt);
       relevant = STMT_VINFO_RELEVANT (stmt_vinfo);
-      live_p = STMT_VINFO_LIVE_P (stmt_vinfo);
+      live = STMT_VINFO_LIVE (stmt_vinfo);
 
       /* Generally, the liveness and relevance properties of STMT are
  propagated as is to the DEF_STMTs of its USEs:
-  live_p <-- STMT_VINFO_LIVE_P (STMT_VINFO)
+  live <-- STMT_VINFO_LIVE (STMT_VINFO)
   relevant <-- STMT_VINFO_RELEVANT (STMT_VINFO)
 
  One exception is when STMT has been identified as defining a reduction
  variable; in this case we set the liveness/relevance as follows:
-   live_p = false
+   live &= vect_live_for_debug
    relevant = vect_used_by_reduction
  This is because we distinguish between two kinds of relevant stmts -
  those that are used by a reduction computation, and those that are
@@ -492,7 +497,7 @@ vect_mark_stmts_to_be_vectorized (loop_v
           return false;
       }
 
-    live_p = false;
+    live = (enum vect_live) (live & vect_live_for_debug);
     break;
 
           case vect_nested_cycle:
@@ -507,7 +512,7 @@ vect_mark_stmts_to_be_vectorized (loop_v
                 return false;
               }
 
-            live_p = false;
+    live = (enum vect_live) (live & vect_live_for_debug);
             break;
       
           case vect_double_reduction_def:
@@ -521,7 +526,7 @@ vect_mark_stmts_to_be_vectorized (loop_v
                 return false;
               }
 
-            live_p = false;
+    live = (enum vect_live) (live & vect_live_for_debug);
             break;
 
           default:
@@ -531,7 +536,7 @@ vect_mark_stmts_to_be_vectorized (loop_v
       FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
  {
   tree op = USE_FROM_PTR (use_p);
-  if (!process_use (stmt, op, loop_vinfo, live_p, relevant, &worklist))
+  if (!process_use (stmt, op, loop_vinfo, live, relevant, &worklist))
     {
       VEC_free (gimple, heap, worklist);
       return false;
@@ -4319,7 +4324,7 @@ new_stmt_vec_info (gimple stmt, loop_vec
   STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
   STMT_VINFO_BB_VINFO (res) = bb_vinfo;
   STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
-  STMT_VINFO_LIVE_P (res) = false;
+  STMT_VINFO_LIVE (res) = vect_dead;
   STMT_VINFO_VECTYPE (res) = NULL;
   STMT_VINFO_VEC_STMT (res) = NULL;
   STMT_VINFO_IN_PATTERN_P (res) = false;
Index: gcc/testsuite/gcc.dg/vect/vect-debug-pr41926.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/vect/vect-debug-pr41926.c 2009-11-05 04:36:47.000000000 -0200
@@ -0,0 +1,20 @@
+/* PR debug/41926 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -ffast-math -funroll-loops -ftree-vectorize -msse2" { target { i?86-*-* x86_64-*-* } } } */
+
+void
+foo (double (*__restrict p)[4], double (*__restrict q)[4],
+     double *__restrict prim, double scale, double pp, double pq)
+{
+  int md, mc, mb, ma, p_index = 0;
+
+  for (md = 0; md < 1; md++)
+    for (mc = 0; mc < 1; mc++)
+      for (mb = 0; mb < 1; mb++)
+ for (ma = 0; ma < 4; ma++)
+  {
+    double tmp = scale * prim[p_index++];
+    p[md][ma] = p[md][ma] - tmp * pp;
+    q[mc][ma] = q[mc][ma] - tmp * pq;
+  }
+}



--
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

Re: [vta, PR41926, graphite?] track debug uses during vectorization

by Richard Guenther-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sun, Nov 8, 2009 at 9:07 AM, Alexandre Oliva <aoliva@...> wrote:

> PR debug/41926 was a case in which a debug use outside a vectorized loop
> remained, referencing an SSA DEF that no longer dominated the use
> because of vectorization.
>
> In order to fix this, I extended the live-tracking information so as to
> record debug uses in addition to nondebug uses.  Then, if a name in the
> vectorized loop is found to be referenced outside the loop only by debug
> insns (case in which we won't create a PHI node at the join point), we
> reset the debug use.
>
> I managed to convert the testcase to C, but it requires the patch I've
> just posted to exercise the bug fixed by the patch below.  I'm not happy
> with the options-management in this testcase, though.  I need
> -ffast-math and -funroll-loops to trigger it, so the standard names
> handled by vect.exp don't work, and I can't add options to the default
> per-machine vectorization options vect.exp sets up.  So I made in
> x86-only, but I'd appreciate suggestions on how to make it better.
> Anyone?
>
> Bootstrapped on x86_64-linux-gnu; regstrapping on that and
> ia64-linux-gnu.  Ok to install?

Ugh.  You could simplify the patch if you'd unconditionally do

          if (!STMT_VINFO_RELEVANT_P (stmt_info)
              && !STMT_VINFO_LIVE_P (stmt_info))
            {
               if (MAY_HAVE_DEBUG_STMTS)
                 vect_loop_kill_debug_uses (loop, phi);
               continue;
            }

it looks wrong to have a tri-state liveness to me, at least it confuses
the occasional reader and the enum casts are ugly anyway.

If the above works out for you a patch along the above is pre-approved.

Thanks,
Richard.

>
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist      Red Hat Brazil Compiler Engineer
>
>

Re: [vta, PR41926, graphite?] track debug uses during vectorization

by Alexandre Oliva-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Nov  8, 2009, Richard Guenther <richard.guenther@...> wrote:

> Ugh.  You could simplify the patch if you'd unconditionally do

>           if (!STMT_VINFO_RELEVANT_P (stmt_info)
>               && !STMT_VINFO_LIVE_P (stmt_info))
>             {
>                if (MAY_HAVE_DEBUG_STMTS)
>                  vect_loop_kill_debug_uses (loop, phi);
>                continue;
>             }

> If the above works out for you a patch along the above is pre-approved.

Thanks, here's what I checked in.


for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@...>

        PR debug/41926
        * tree-vect-loop.c (vect_loop_kill_debug_uses): New.
        (vect_transform_loop): Call it.

for  gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@...>

        PR debug/41926
        * gcc.dg/vect/vect-debug-pr41926.c: New.

Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c.orig 2009-11-16 20:25:28.000000000 -0200
+++ gcc/tree-vect-loop.c 2009-11-16 20:27:24.000000000 -0200
@@ -4112,6 +4112,44 @@ vectorizable_live_operation (gimple stmt
   return true;
 }
 
+/* Kill any debug uses outside LOOP of SSA names defined in STMT.  */
+
+static void
+vect_loop_kill_debug_uses (struct loop *loop, gimple stmt)
+{
+  ssa_op_iter op_iter;
+  imm_use_iterator imm_iter;
+  def_operand_p def_p;
+  gimple ustmt;
+
+  FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
+    {
+      FOR_EACH_IMM_USE_STMT (ustmt, imm_iter, DEF_FROM_PTR (def_p))
+ {
+  basic_block bb;
+
+  if (!is_gimple_debug (ustmt))
+    continue;
+
+  bb = gimple_bb (ustmt);
+
+  if (!flow_bb_inside_loop_p (loop, bb))
+    {
+      if (gimple_debug_bind_p (ustmt))
+ {
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "killing debug use");
+
+  gimple_debug_bind_reset_value (ustmt);
+  update_stmt (ustmt);
+ }
+      else
+ gcc_unreachable ();
+    }
+ }
+    }
+}
+
 /* Function vect_transform_loop.
 
    The analysis phase has determined that the loop is vectorizable.
@@ -4202,7 +4240,11 @@ vect_transform_loop (loop_vec_info loop_
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info)
       && !STMT_VINFO_LIVE_P (stmt_info))
-    continue;
+    {
+      if (MAY_HAVE_DEBUG_STMTS)
+ vect_loop_kill_debug_uses (loop, phi);
+      continue;
+    }
 
   if ((TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info))
         != (unsigned HOST_WIDE_INT) vectorization_factor)
@@ -4242,6 +4284,8 @@ vect_transform_loop (loop_vec_info loop_
   if (!STMT_VINFO_RELEVANT_P (stmt_info)
       && !STMT_VINFO_LIVE_P (stmt_info))
     {
+      if (MAY_HAVE_DEBUG_STMTS)
+ vect_loop_kill_debug_uses (loop, stmt);
       gsi_next (&si);
       continue;
     }
Index: gcc/testsuite/gcc.dg/vect/vect-debug-pr41926.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/vect/vect-debug-pr41926.c 2009-11-16 20:27:24.000000000 -0200
@@ -0,0 +1,20 @@
+/* PR debug/41926 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -ffast-math -funroll-loops -ftree-vectorize -msse2" { target { i?86-*-* x86_64-*-* } } } */
+
+void
+foo (double (*__restrict p)[4], double (*__restrict q)[4],
+     double *__restrict prim, double scale, double pp, double pq)
+{
+  int md, mc, mb, ma, p_index = 0;
+
+  for (md = 0; md < 1; md++)
+    for (mc = 0; mc < 1; mc++)
+      for (mb = 0; mb < 1; mb++)
+ for (ma = 0; ma < 4; ma++)
+  {
+    double tmp = scale * prim[p_index++];
+    p[md][ma] = p[md][ma] - tmp * pp;
+    q[mc][ma] = q[mc][ma] - tmp * pq;
+  }
+}


--
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer