Commit 88088c03 by Dorit Nuzman Committed by Dorit Nuzman

tree-flow.h (stmt_ann_d): Move aux to ...

        * tree-flow.h (stmt_ann_d): Move aux to ...
        (tree_ann_common_d): ... here.
        * tree-ssa-loop-im.c (LIM_DATA, determine_invariantness_stmt,
        move_computations_stmt, schedule_sm): Update references to
        aux.
        * tree-vectorizer.h (set_stmt_info, vinfo_for_stmt): Likewise.
        * tree-vect-transform.c (vect_create_index_for_vector_ref): Update
        call to set_stmt_info.
        (vect_transform_loop): Likewise.
        * tree-vectorizer.c (new_loop_vec_info, destroy_loop_vec_info):
        Likewise.

        * tree-vect-analyze.c (vect_analyze_scalar_cycles): Made void instead of
        bool.
        (vect_mark_relevant): Takes two additional arguments - live_p and
        relevant_p. Set RELEVANT_P and LIVE_P according to these arguments.
        (vect_stmt_relevant_p): Differentiate between a live stmt and a
        relevant stmt. Return two values = live_p and relevant_p.
        (vect_mark_stmts_to_be_vectorized): Call vect_mark_relevant and
        vect_stmt_relevant_p with additional arguments. Phis are no longer
        put into the worklist (analyzed seperately in analyze_scalar_cycles).
        (vect_determine_vectorization_factor): Also check for LIVE_P, because a
        stmt that is marked as irrelevant and live, cause it's only used out
        side the loop, may need to be vectorized (e.g. reduction).
        (vect_analyze_operations): Examine phis. Call
        vectorizable_live_operation for for LIVE_P stmts. Check if
        need_to_vectorize.
        (vect_analyze_scalar_cycles): Update documentation. Don't fail
        vectorization - just classify the scalar cycles created by the loop
        phis. Call vect_is_simple_reduction.
        (vect_analyze_loop): Call to analyze_scalar_cycles moved earlier.
        * tree-vect-transform.c (vect_create_index_for_vector_ref): Update
        call to set_stmt_info.
        (vect_get_vec_def_for_operand): Code reorganized - the code that
        classifies the type of use was factored out to vect_is_simple_use.
        (vectorizable_store, vect_is_simple_cond): Call vect_is_simple_use with
        additional arguments.
        (vectorizable_assignment): Likewise. Also make sure the stmt is relevant
        and computes a loop_vec_def.
        (vectorizable_operation, vectorizable_load, vectorizable_condition):
        Likewise.
        (vectorizable_live_operation): New.
        (vect_transform_stmt): Handle LIVE_P stmts.
        * tree-vectorizer.c (new_stmt_vec_info): Initialize the new fields
        STMT_VINFO_LIVE_P and STMT_VINFO_DEF_TYPE.
        (new_loop_vec_info, destroy_loop_vec_info): Also handle phis.
        (vect_is_simple_use): Determine the type of the def and return it
        in a new function argument. Consider vect_reduction_def and
        vect_induction_def, but for now these are not supported.
        (vect_is_simple_reduction): New. Empty for now.
        * tree-vectorizer.h (vect_def_type): New enum type.
        (_stmt_vec_info): Added new fields - live and _stmt_vec_info.
        (STMT_VINFO_LIVE_P, STMT_VINFO_DEF_TYPE): New accessor macros.
        (vect_is_simple_use): New arguments added to function declaration.
        (vect_is_simple_reduction): New function declaration.
        (vectorizable_live_operation): New function declaration.

        * tree-vect-analyze.c (vect_can_advance_ivs_p): Add debug printout.
        (vect_can_advance_ivs_p): Likewise.
        * tree-vect-transform.c (vect_update_ivs_after_vectorizer): Likewise.

From-SVN: r100617
parent 57049d39
2005-06-05 Dorit Nuzman <dorit@il.ibm.com>
* tree-flow.h (stmt_ann_d): Move aux to ...
(tree_ann_common_d): ... here.
* tree-ssa-loop-im.c (LIM_DATA, determine_invariantness_stmt,
move_computations_stmt, schedule_sm): Update references to
aux.
* tree-vectorizer.h (set_stmt_info, vinfo_for_stmt): Likewise.
* tree-vect-transform.c (vect_create_index_for_vector_ref): Update
call to set_stmt_info.
(vect_transform_loop): Likewise.
* tree-vectorizer.c (new_loop_vec_info, destroy_loop_vec_info):
Likewise.
* tree-vect-analyze.c (vect_analyze_scalar_cycles): Made void instead of
bool.
(vect_mark_relevant): Takes two additional arguments - live_p and
relevant_p. Set RELEVANT_P and LIVE_P according to these arguments.
(vect_stmt_relevant_p): Differentiate between a live stmt and a
relevant stmt. Return two values = live_p and relevant_p.
(vect_mark_stmts_to_be_vectorized): Call vect_mark_relevant and
vect_stmt_relevant_p with additional arguments. Phis are no longer
put into the worklist (analyzed seperately in analyze_scalar_cycles).
(vect_determine_vectorization_factor): Also check for LIVE_P, because a
stmt that is marked as irrelevant and live, cause it's only used out
side the loop, may need to be vectorized (e.g. reduction).
(vect_analyze_operations): Examine phis. Call
vectorizable_live_operation for for LIVE_P stmts. Check if
need_to_vectorize.
(vect_analyze_scalar_cycles): Update documentation. Don't fail
vectorization - just classify the scalar cycles created by the loop
phis. Call vect_is_simple_reduction.
(vect_analyze_loop): Call to analyze_scalar_cycles moved earlier.
* tree-vect-transform.c (vect_create_index_for_vector_ref): Update
call to set_stmt_info.
(vect_get_vec_def_for_operand): Code reorganized - the code that
classifies the type of use was factored out to vect_is_simple_use.
(vectorizable_store, vect_is_simple_cond): Call vect_is_simple_use with
additional arguments.
(vectorizable_assignment): Likewise. Also make sure the stmt is relevant
and computes a loop_vec_def.
(vectorizable_operation, vectorizable_load, vectorizable_condition):
Likewise.
(vectorizable_live_operation): New.
(vect_transform_stmt): Handle LIVE_P stmts.
* tree-vectorizer.c (new_stmt_vec_info): Initialize the new fields
STMT_VINFO_LIVE_P and STMT_VINFO_DEF_TYPE.
(new_loop_vec_info, destroy_loop_vec_info): Also handle phis.
(vect_is_simple_use): Determine the type of the def and return it
in a new function argument. Consider vect_reduction_def and
vect_induction_def, but for now these are not supported.
(vect_is_simple_reduction): New. Empty for now.
* tree-vectorizer.h (vect_def_type): New enum type.
(_stmt_vec_info): Added new fields - live and _stmt_vec_info.
(STMT_VINFO_LIVE_P, STMT_VINFO_DEF_TYPE): New accessor macros.
(vect_is_simple_use): New arguments added to function declaration.
(vect_is_simple_reduction): New function declaration.
(vectorizable_live_operation): New function declaration.
* tree-vect-analyze.c (vect_can_advance_ivs_p): Add debug printout.
(vect_can_advance_ivs_p): Likewise.
* tree-vect-transform.c (vect_update_ivs_after_vectorizer): Likewise.
2005-06-05 Eric Christopher <echristo@redhat.com> 2005-06-05 Eric Christopher <echristo@redhat.com>
* config/mips/mips.c (mips_rtx_costs): Remove unused variable. * config/mips/mips.c (mips_rtx_costs): Remove unused variable.
......
2005-06-05 Dorit Nuzman <dorit@il.ibm.com>
* gcc.dg/vect/vect-62: Check that second loop is not vectorized.
* gcc.dg/vect/vect-reduc-1.c: New.
* gcc.dg/vect/vect-reduc-2.c: New.
* gcc.dg/vect/vect-reduc-3.c: New.
2005-06-04 Dale Johannesen <dalej@apple.com> 2005-06-04 Dale Johannesen <dalej@apple.com>
* gcc.c-torture/execute/20050603-1.c: New. * gcc.c-torture/execute/20050603-1.c: New.
......
...@@ -32,7 +32,9 @@ int main1 () ...@@ -32,7 +32,9 @@ int main1 ()
} }
/* Multidimensional array. Aligned. The "inner" dimensions /* Multidimensional array. Aligned. The "inner" dimensions
are invariant in the inner loop. Store. */ are invariant in the inner loop. Vectorizable, but the
vectorizer detects that everything is invariant and that
the loop is better left untouched. (it should be optimized away). */
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
{ {
for (j = 0; j < N; j++) for (j = 0; j < N; j++)
...@@ -62,6 +64,7 @@ int main (void) ...@@ -62,6 +64,7 @@ int main (void)
return main1 (); return main1 ();
} }
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */ /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "not vectorized: redundant loop. no profit to vectorize." 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
#define DIFF 242
/* Test vectorization of reduction of unsigned-int. */
/* Not supported yet. */
int main1 (unsigned int x, unsigned int max_result)
{
int i;
unsigned int ub[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};
unsigned int uc[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned int udiff = 2;
unsigned int umax = x;
unsigned int umin = 10;
/* Summation. */
for (i = 0; i < N; i++) {
udiff += (ub[i] - uc[i]);
}
/* Maximum. */
for (i = 0; i < N; i++) {
umax = umax < uc[i] ? uc[i] : umax;
}
/* Minimum. */
for (i = 0; i < N; i++) {
umin = umin > uc[i] ? uc[i] : umin;
}
/* check results: */
if (udiff != DIFF)
abort ();
if (umax != max_result)
abort ();
if (umin != 0)
abort ();
return 0;
}
int main (void)
{
check_vect ();
return main1 (100, 100);
return main1 (0, 15);
}
/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "not vectorized: unsupported use in stmt." 3 "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
#define DIFF 242
/* Test vectorization of reduction of signed-int. */
/* Not supported yet. */
int main1 (int x, int max_result)
{
int i;
int b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};
int c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int diff = 2;
int max = x;
int min = 10;
for (i = 0; i < N; i++) {
diff += (b[i] - c[i]);
}
for (i = 0; i < N; i++) {
max = max < c[i] ? c[i] : max;
}
for (i = 0; i < N; i++) {
min = min > c[i] ? c[i] : min;
}
/* check results: */
if (diff != DIFF)
abort ();
if (max != max_result)
abort ();
if (min != 0)
abort ();
return 0;
}
int main (void)
{
check_vect ();
return main1 (100, 100);
return main1 (0, 15);
}
/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "not vectorized: unsupported use in stmt." 3 "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
#define DIFF 240
/* Test vectorization of reduction of unsigned-int in the presence
of unknown-loop-bound. */
/* Not supported yet. */
int main1 (int n)
{
int i;
unsigned int ub[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};
unsigned int uc[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned int udiff;
udiff = 0;
for (i = 0; i < n; i++) {
udiff += (ub[i] - uc[i]);
}
/* check results: */
if (udiff != DIFF)
abort ();
return 0;
}
int main (void)
{
check_vect ();
return main1 (N);
return main1 (N-1);
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "not vectorized: unsupported use in stmt." 1 "vect" } } */
...@@ -93,6 +93,10 @@ struct tree_ann_common_d GTY(()) ...@@ -93,6 +93,10 @@ struct tree_ann_common_d GTY(())
/* Annotation type. */ /* Annotation type. */
enum tree_ann_type type; enum tree_ann_type type;
/* Auxiliary info specific to a pass. At all times, this
should either point to valid data or be NULL. */
PTR GTY ((skip (""))) aux;
/* The value handle for this expression. Used by GVN-PRE. */ /* The value handle for this expression. Used by GVN-PRE. */
tree GTY((skip)) value_handle; tree GTY((skip)) value_handle;
}; };
...@@ -293,10 +297,6 @@ struct stmt_ann_d GTY(()) ...@@ -293,10 +297,6 @@ struct stmt_ann_d GTY(())
pass which needs statement UIDs. */ pass which needs statement UIDs. */
unsigned int uid; unsigned int uid;
/* Auxiliary info specific to a pass. At all times, this
should either point to valid data or be NULL. */
PTR GTY ((skip (""))) aux;
/* Linked list of histograms for value-based profiling. This is really a /* Linked list of histograms for value-based profiling. This is really a
struct histogram_value*. We use void* to avoid having to export that struct histogram_value*. We use void* to avoid having to export that
everywhere, and to avoid having to put it in GC memory. */ everywhere, and to avoid having to put it in GC memory. */
......
...@@ -102,7 +102,7 @@ struct lim_aux_data ...@@ -102,7 +102,7 @@ struct lim_aux_data
#define LIM_DATA(STMT) (TREE_CODE (STMT) == PHI_NODE \ #define LIM_DATA(STMT) (TREE_CODE (STMT) == PHI_NODE \
? NULL \ ? NULL \
: (struct lim_aux_data *) (stmt_ann (STMT)->aux)) : (struct lim_aux_data *) (stmt_ann (STMT)->common.aux))
/* Description of a memory reference location for store motion. */ /* Description of a memory reference location for store motion. */
...@@ -632,7 +632,7 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED, ...@@ -632,7 +632,7 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
stmt = stmt1; stmt = stmt1;
} }
stmt_ann (stmt)->aux = xcalloc (1, sizeof (struct lim_aux_data)); stmt_ann (stmt)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
LIM_DATA (stmt)->always_executed_in = outermost; LIM_DATA (stmt)->always_executed_in = outermost;
if (maybe_never && pos == MOVE_PRESERVE_EXECUTION) if (maybe_never && pos == MOVE_PRESERVE_EXECUTION)
...@@ -723,7 +723,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED, ...@@ -723,7 +723,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
cost = LIM_DATA (stmt)->cost; cost = LIM_DATA (stmt)->cost;
level = LIM_DATA (stmt)->tgt_loop; level = LIM_DATA (stmt)->tgt_loop;
free_lim_aux_data (LIM_DATA (stmt)); free_lim_aux_data (LIM_DATA (stmt));
stmt_ann (stmt)->aux = NULL; stmt_ann (stmt)->common.aux = NULL;
if (!level) if (!level)
{ {
...@@ -952,7 +952,7 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref, ...@@ -952,7 +952,7 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
/* Emit the load & stores. */ /* Emit the load & stores. */
load = build (MODIFY_EXPR, void_type_node, tmp_var, ref); load = build (MODIFY_EXPR, void_type_node, tmp_var, ref);
get_stmt_ann (load)->aux = xcalloc (1, sizeof (struct lim_aux_data)); get_stmt_ann (load)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
LIM_DATA (load)->max_loop = loop; LIM_DATA (load)->max_loop = loop;
LIM_DATA (load)->tgt_loop = loop; LIM_DATA (load)->tgt_loop = loop;
......
...@@ -1338,9 +1338,14 @@ new_stmt_vec_info (tree stmt, loop_vec_info loop_vinfo) ...@@ -1338,9 +1338,14 @@ new_stmt_vec_info (tree stmt, loop_vec_info loop_vinfo)
STMT_VINFO_STMT (res) = stmt; STMT_VINFO_STMT (res) = stmt;
STMT_VINFO_LOOP_VINFO (res) = loop_vinfo; STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
STMT_VINFO_RELEVANT_P (res) = 0; STMT_VINFO_RELEVANT_P (res) = 0;
STMT_VINFO_LIVE_P (res) = 0;
STMT_VINFO_VECTYPE (res) = NULL; STMT_VINFO_VECTYPE (res) = NULL;
STMT_VINFO_VEC_STMT (res) = NULL; STMT_VINFO_VEC_STMT (res) = NULL;
STMT_VINFO_DATA_REF (res) = NULL; STMT_VINFO_DATA_REF (res) = NULL;
if (TREE_CODE (stmt) == PHI_NODE)
STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
else
STMT_VINFO_DEF_TYPE (res) = vect_loop_def;
STMT_VINFO_MEMTAG (res) = NULL; STMT_VINFO_MEMTAG (res) = NULL;
STMT_VINFO_PTR_INFO (res) = NULL; STMT_VINFO_PTR_INFO (res) = NULL;
STMT_VINFO_SUBVARS (res) = NULL; STMT_VINFO_SUBVARS (res) = NULL;
...@@ -1375,13 +1380,21 @@ new_loop_vec_info (struct loop *loop) ...@@ -1375,13 +1380,21 @@ new_loop_vec_info (struct loop *loop)
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
{ {
basic_block bb = bbs[i]; basic_block bb = bbs[i];
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree_ann_t ann = get_tree_ann (phi);
set_stmt_info (ann, new_stmt_vec_info (phi, res));
}
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{ {
tree stmt = bsi_stmt (si); tree stmt = bsi_stmt (si);
stmt_ann_t ann; stmt_ann_t ann;
ann = stmt_ann (stmt); ann = stmt_ann (stmt);
set_stmt_info (ann, new_stmt_vec_info (stmt, res)); set_stmt_info ((tree_ann_t)ann, new_stmt_vec_info (stmt, res));
} }
} }
...@@ -1428,13 +1441,26 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo) ...@@ -1428,13 +1441,26 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo)
for (j = 0; j < nbbs; j++) for (j = 0; j < nbbs; j++)
{ {
basic_block bb = bbs[j]; basic_block bb = bbs[j];
tree phi;
stmt_vec_info stmt_info;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree_ann_t ann = get_tree_ann (phi);
stmt_info = vinfo_for_stmt (phi);
free (stmt_info);
set_stmt_info (ann, NULL);
}
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{ {
tree stmt = bsi_stmt (si); tree stmt = bsi_stmt (si);
stmt_ann_t ann = stmt_ann (stmt); stmt_ann_t ann = stmt_ann (stmt);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt); stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
free (stmt_info); free (stmt_info);
set_stmt_info (ann, NULL); set_stmt_info ((tree_ann_t)ann, NULL);
} }
} }
...@@ -1596,64 +1622,148 @@ vect_supportable_dr_alignment (struct data_reference *dr) ...@@ -1596,64 +1622,148 @@ vect_supportable_dr_alignment (struct data_reference *dr)
in reduction/induction computations). */ in reduction/induction computations). */
bool bool
vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, tree *def) vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, tree *def_stmt,
tree *def, enum vect_def_type *dt)
{ {
tree def_stmt;
basic_block bb; basic_block bb;
stmt_vec_info stmt_vinfo;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
if (def) *def_stmt = NULL_TREE;
*def = NULL_TREE; *def = NULL_TREE;
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
{
fprintf (vect_dump, "vect_is_simple_use: operand ");
print_generic_expr (vect_dump, operand, TDF_SLIM);
}
if (TREE_CODE (operand) == INTEGER_CST || TREE_CODE (operand) == REAL_CST) if (TREE_CODE (operand) == INTEGER_CST || TREE_CODE (operand) == REAL_CST)
{
*dt = vect_constant_def;
return true; return true;
}
if (TREE_CODE (operand) != SSA_NAME) if (TREE_CODE (operand) != SSA_NAME)
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "not ssa-name.");
return false; return false;
}
def_stmt = SSA_NAME_DEF_STMT (operand); *def_stmt = SSA_NAME_DEF_STMT (operand);
if (def_stmt == NULL_TREE ) if (*def_stmt == NULL_TREE )
{ {
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "no def_stmt."); fprintf (vect_dump, "no def_stmt.");
return false; return false;
} }
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
{
fprintf (vect_dump, "def_stmt: ");
print_generic_expr (vect_dump, *def_stmt, TDF_SLIM);
}
/* empty stmt is expected only in case of a function argument. /* empty stmt is expected only in case of a function argument.
(Otherwise - we expect a phi_node or a modify_expr). */ (Otherwise - we expect a phi_node or a modify_expr). */
if (IS_EMPTY_STMT (def_stmt)) if (IS_EMPTY_STMT (*def_stmt))
{ {
tree arg = TREE_OPERAND (def_stmt, 0); tree arg = TREE_OPERAND (*def_stmt, 0);
if (TREE_CODE (arg) == INTEGER_CST || TREE_CODE (arg) == REAL_CST) if (TREE_CODE (arg) == INTEGER_CST || TREE_CODE (arg) == REAL_CST)
{
*def = operand;
*dt = vect_invariant_def;
return true; return true;
}
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "Unexpected empty stmt.");
return false;
}
bb = bb_for_stmt (*def_stmt);
if (!flow_bb_inside_loop_p (loop, bb))
*dt = vect_invariant_def;
else
{ {
fprintf (vect_dump, "Unexpected empty stmt: "); stmt_vinfo = vinfo_for_stmt (*def_stmt);
print_generic_expr (vect_dump, def_stmt, TDF_SLIM); *dt = STMT_VINFO_DEF_TYPE (stmt_vinfo);
} }
if (*dt == vect_unknown_def_type)
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "Unsupported pattern.");
return false; return false;
} }
/* phi_node inside the loop indicates an induction/reduction pattern. /* stmts inside the loop that have been identified as performing
This is not supported yet. */ a reduction operation cannot have uses in the loop. */
bb = bb_for_stmt (def_stmt); if (*dt == vect_reduction_def && TREE_CODE (*def_stmt) != PHI_NODE)
if (TREE_CODE (def_stmt) == PHI_NODE && flow_bb_inside_loop_p (loop, bb))
{ {
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "reduction/induction - unsupported."); fprintf (vect_dump, "reduction used in loop.");
return false; /* FORNOW: not supported yet. */ return false;
} }
/* Expecting a modify_expr or a phi_node. */ if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
if (TREE_CODE (def_stmt) == MODIFY_EXPR fprintf (vect_dump, "type of def: %d.",*dt);
|| TREE_CODE (def_stmt) == PHI_NODE)
switch (TREE_CODE (*def_stmt))
{ {
if (def) case PHI_NODE:
*def = def_stmt; *def = PHI_RESULT (*def_stmt);
return true; gcc_assert (*dt == vect_induction_def || *dt == vect_reduction_def
|| *dt == vect_invariant_def);
break;
case MODIFY_EXPR:
*def = TREE_OPERAND (*def_stmt, 0);
gcc_assert (*dt == vect_loop_def || *dt == vect_invariant_def);
break;
default:
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "unsupported defining stmt: ");
return false;
} }
if (*dt == vect_induction_def)
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "induction not supported.");
return false; return false;
}
return true;
}
/* Function vect_is_simple_reduction
TODO:
Detect a cross-iteration def-use cucle that represents a simple
reduction computation. We look for the followng pattern:
loop_header:
a1 = phi < a0, a2 >
a3 = ...
a2 = operation (a3, a1)
such that:
1. operation is...
2. no uses for a2 in the loop (elsewhere) */
tree
vect_is_simple_reduction (struct loop *loop ATTRIBUTE_UNUSED,
tree phi ATTRIBUTE_UNUSED)
{
/* FORNOW */
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "reduction: unknown pattern.");
return NULL_TREE;
} }
......
...@@ -56,6 +56,16 @@ enum dr_alignment_support { ...@@ -56,6 +56,16 @@ enum dr_alignment_support {
dr_aligned dr_aligned
}; };
/* Define type of def-use cross-iteraiton cycle. */
enum vect_def_type {
vect_constant_def,
vect_invariant_def,
vect_loop_def,
vect_induction_def,
vect_reduction_def,
vect_unknown_def_type
};
/* Define verbosity levels. */ /* Define verbosity levels. */
enum verbosity_levels { enum verbosity_levels {
REPORT_NONE, REPORT_NONE,
...@@ -163,6 +173,10 @@ typedef struct _stmt_vec_info { ...@@ -163,6 +173,10 @@ typedef struct _stmt_vec_info {
indicates whether the stmt needs to be vectorized. */ indicates whether the stmt needs to be vectorized. */
bool relevant; bool relevant;
/* Indicates whether this stmts is part of a computation whose result is
used outside the loop. */
bool live;
/* The vector type to be used. */ /* The vector type to be used. */
tree vectype; tree vectype;
...@@ -215,6 +229,10 @@ typedef struct _stmt_vec_info { ...@@ -215,6 +229,10 @@ typedef struct _stmt_vec_info {
/* Alignment information. The offset of the data-reference from its base /* Alignment information. The offset of the data-reference from its base
in bytes. */ in bytes. */
tree misalignment; tree misalignment;
/* Classify the def of this stmt. */
enum vect_def_type def_type;
} *stmt_vec_info; } *stmt_vec_info;
/* Access Functions. */ /* Access Functions. */
...@@ -222,6 +240,7 @@ typedef struct _stmt_vec_info { ...@@ -222,6 +240,7 @@ typedef struct _stmt_vec_info {
#define STMT_VINFO_STMT(S) (S)->stmt #define STMT_VINFO_STMT(S) (S)->stmt
#define STMT_VINFO_LOOP_VINFO(S) (S)->loop_vinfo #define STMT_VINFO_LOOP_VINFO(S) (S)->loop_vinfo
#define STMT_VINFO_RELEVANT_P(S) (S)->relevant #define STMT_VINFO_RELEVANT_P(S) (S)->relevant
#define STMT_VINFO_LIVE_P(S) (S)->live
#define STMT_VINFO_VECTYPE(S) (S)->vectype #define STMT_VINFO_VECTYPE(S) (S)->vectype
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt #define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info #define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
...@@ -233,22 +252,23 @@ typedef struct _stmt_vec_info { ...@@ -233,22 +252,23 @@ typedef struct _stmt_vec_info {
#define STMT_VINFO_VECT_STEP(S) (S)->step #define STMT_VINFO_VECT_STEP(S) (S)->step
#define STMT_VINFO_VECT_BASE_ALIGNED_P(S) (S)->base_aligned_p #define STMT_VINFO_VECT_BASE_ALIGNED_P(S) (S)->base_aligned_p
#define STMT_VINFO_VECT_MISALIGNMENT(S) (S)->misalignment #define STMT_VINFO_VECT_MISALIGNMENT(S) (S)->misalignment
#define STMT_VINFO_DEF_TYPE(S) (S)->def_type
static inline void set_stmt_info (stmt_ann_t ann, stmt_vec_info stmt_info); static inline void set_stmt_info (tree_ann_t ann, stmt_vec_info stmt_info);
static inline stmt_vec_info vinfo_for_stmt (tree stmt); static inline stmt_vec_info vinfo_for_stmt (tree stmt);
static inline void static inline void
set_stmt_info (stmt_ann_t ann, stmt_vec_info stmt_info) set_stmt_info (tree_ann_t ann, stmt_vec_info stmt_info)
{ {
if (ann) if (ann)
ann->aux = (char *) stmt_info; ann->common.aux = (char *) stmt_info;
} }
static inline stmt_vec_info static inline stmt_vec_info
vinfo_for_stmt (tree stmt) vinfo_for_stmt (tree stmt)
{ {
stmt_ann_t ann = stmt_ann (stmt); tree_ann_t ann = tree_ann (stmt);
return ann ? (stmt_vec_info) ann->aux : NULL; return ann ? (stmt_vec_info) ann->common.aux : NULL;
} }
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
...@@ -309,8 +329,10 @@ extern void slpeel_verify_cfg_after_peeling (struct loop *, struct loop *); ...@@ -309,8 +329,10 @@ extern void slpeel_verify_cfg_after_peeling (struct loop *, struct loop *);
/** In tree-vectorizer.c **/ /** In tree-vectorizer.c **/
extern tree vect_strip_conversion (tree); extern tree vect_strip_conversion (tree);
extern tree get_vectype_for_scalar_type (tree); extern tree get_vectype_for_scalar_type (tree);
extern bool vect_is_simple_use (tree , loop_vec_info, tree *); extern bool vect_is_simple_use (tree, loop_vec_info, tree *, tree *,
enum vect_def_type *);
extern bool vect_is_simple_iv_evolution (unsigned, tree, tree *, tree *); extern bool vect_is_simple_iv_evolution (unsigned, tree, tree *, tree *);
extern tree vect_is_simple_reduction (struct loop *, tree);
extern bool vect_can_force_dr_alignment_p (tree, unsigned int); extern bool vect_can_force_dr_alignment_p (tree, unsigned int);
extern enum dr_alignment_support vect_supportable_dr_alignment extern enum dr_alignment_support vect_supportable_dr_alignment
(struct data_reference *); (struct data_reference *);
...@@ -331,6 +353,7 @@ extern bool vectorizable_store (tree, block_stmt_iterator *, tree *); ...@@ -331,6 +353,7 @@ extern bool vectorizable_store (tree, block_stmt_iterator *, tree *);
extern bool vectorizable_operation (tree, block_stmt_iterator *, tree *); extern bool vectorizable_operation (tree, block_stmt_iterator *, tree *);
extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *); extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *);
extern bool vectorizable_condition (tree, block_stmt_iterator *, tree *); extern bool vectorizable_condition (tree, block_stmt_iterator *, tree *);
extern bool vectorizable_live_operation (tree, block_stmt_iterator *, tree *);
/* Driver for transformation stage. */ /* Driver for transformation stage. */
extern void vect_transform_loop (loop_vec_info, struct loops *); extern void vect_transform_loop (loop_vec_info, struct loops *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment