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]

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


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@redhat.com>

	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@redhat.com>

	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

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