This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[vta, PR41926, graphite?] track debug uses during vectorization
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 08 Nov 2009 06:07:38 -0200
- Subject: [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