Commit b52485c6 by Devang Patel Committed by Devang Patel

tree-data-ref.c (build_classic_dist_vector, [...]): Make externally visible.

         * tree-data-ref.c (build_classic_dist_vector,
         compute_subscript_distance): Make externally visible.
         * tree-data-ref.h (build_classic_dist_vector,
         compute_subscript_distance): Same.
         * tree-vect-analyze.c (vect_analyze_data_ref_dependence):
         Check distance vector against vectorization factor.
         (vect_analyze_loop): Determine vectorizaion factor before
         analyzing data dependences.
         * tree-vectorizer.c (loops_num): Make it externally visible and
         rename ...
         * tree-vectorizer.c (vect_loops_num): ... new name.
         * tree-vectorizer.h  (vect_loops_num): New.

         * tree-vect-analyze.c (vect_analyze_operations): Check
         vectorizable codition.
         * tree-vect-transform.c (vect_is_simple_cond): New function.
         (vectorizable_condition): New function.
         (vect_transform_stmt): Handle condition_vec_info_type.
         * tree-vectorizer.h (enum stmt_vec_info_type): Add
         condition_vec_info_type.
         (vectorizable_condition): New.

         * lib/target-supports.exp (check_effective_target_vect_condition): New.
         * gcc.dg/vect/vect-ifcvt-1.c: New test.
         * gcc.dg/vect/vect-ifcvt-2.c: New test.
         * gcc.dg/vect/vect-ifcvt-3.c: New test.
         * gcc.dg/vect/vect-ifcvt-4.c: New test.
         * gcc.dg/vect/vect-ifcvt-5.c: New test.
         * gcc.dg/vect/vect-ifcvt-6.c: New test.
         * gcc.dg/vect/vect-ifcvt-7.c: New test.
         * gcc.dg/vect/vect-none.c: Now one loop is vectorized.

         * gcc.dg/vect/vect-dv-1.c: New test.
         * gcc.dg/vect/vect-dv-2.c: New test.

From-SVN: r97999
parent 45f27db0
2005-04-11 Devang Patel <dpatel@apple.com>
* tree-data-ref.c (build_classic_dist_vector,
compute_subscript_distance): Make externally visible.
* tree-data-ref.h (build_classic_dist_vector,
compute_subscript_distance): Same.
* tree-vect-analyze.c (vect_analyze_data_ref_dependence):
Check distance vector against vectorization factor.
(vect_analyze_loop): Determine vectorizaion factor before
analyzing data dependences.
* tree-vectorizer.c (loops_num): Make it externally visible and
rename ...
* tree-vectorizer.c (vect_loops_num): ... new name.
* tree-vectorizer.h (vect_loops_num): New.
2005-04-11 Devang Patel <dpatel@apple.com>
* tree-vect-analyze.c (vect_analyze_operations): Check
vectorizable codition.
* tree-vect-transform.c (vect_is_simple_cond): New function.
(vectorizable_condition): New function.
(vect_transform_stmt): Handle condition_vec_info_type.
* tree-vectorizer.h (enum stmt_vec_info_type): Add
condition_vec_info_type.
(vectorizable_condition): New.
2005-04-11 Geoffrey Keating <geoffk@apple.com> 2005-04-11 Geoffrey Keating <geoffk@apple.com>
* config/t-slibgcc-darwin: Don't put shared libraries in * config/t-slibgcc-darwin: Don't put shared libraries in
......
2004-04-11 Devang Patel <dpatel@apple.com>
* lib/target-supports.exp (check_effective_target_vect_condition): New.
* gcc.dg/vect/vect-ifcvt-1.c: New test.
* gcc.dg/vect/vect-ifcvt-2.c: New test.
* gcc.dg/vect/vect-ifcvt-3.c: New test.
* gcc.dg/vect/vect-ifcvt-4.c: New test.
* gcc.dg/vect/vect-ifcvt-5.c: New test.
* gcc.dg/vect/vect-ifcvt-6.c: New test.
* gcc.dg/vect/vect-ifcvt-7.c: New test.
* gcc.dg/vect/vect-none.c: Now one loop is vectorized.
2004-04-11 Devang Patel <dpatel@apple.com>
* gcc.dg/vect/vect-dv-1.c: New test.
* gcc.dg/vect/vect-dv-2.c: New test.
2005-04-11 Diego Novillo <dnovillo@redhat.com> 2005-04-11 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/20933 PR tree-optimization/20933
......
/* Test compiler crash when dependence analyzer can not represent
dependence relation by distance vector. */
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
int x[199];
void foo()
{
int t,j;
for (j=99;j>0;j--)
x [j+j]=x[j];
for (j=198;j>=100;j--)
if(x[j])
{
x[j-63]=x[j-3]-x[j];
}
}
/* { dg-do run } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include <signal.h>
#define N 64
#define MAX 42
extern void abort(void);
int main ()
{
int A[N];
int B[N];
int C[N];
int D[N];
int i, j;
for (i = 0; i < N; i++)
{
A[i] = i;
B[i] = i;
C[i] = i;
D[i] = i;
}
/* Vectorizable */
for (i = 0; i < 16; i++)
{
A[i] = A[i+20];
}
/* check results: */
for (i = 0; i < 16; i++)
{
if (A[i] != A[i+20])
abort ();
}
/* Vectorizable */
for (i = 0; i < 16; i++)
{
B[i] = B[i] + 5;
}
/* check results: */
for (i = 0; i < 16; i++)
{
if (B[i] != C[i] + 5)
abort ();
}
/* Not vectorizable */
for (i = 0; i < 4; i++)
{
C[i] = C[i+3];
}
/* check results: */
for (i = 0; i < 4; i++)
{
if (C[i] != D[i+3])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 64
#define MAX 42
extern void abort(void);
int main ()
{
int A[N];
int B[N];
int C[N];
int D[N];
int i, j;
for (i = 0; i < N; i++)
{
A[i] = i;
B[i] = i;
C[i] = i;
D[i] = i;
}
/* Vectorizable */
for (i = 0; i < 16; i++)
{
A[i] = A[i+20];
}
/* check results: */
for (i = 0; i < 16; i++)
{
if (A[i] != A[i+20])
abort ();
}
/* Vectorizable */
for (i = 0; i < 16; i++)
{
B[i] = B[i] + 5;
}
/* check results: */
for (i = 0; i < 16; i++)
{
if (B[i] != C[i] + 5)
abort ();
}
/* Not vectorizable */
for (i = 0; i < 4; i++)
{
C[i] = C[i+3];
}
/* check results: */
for (i = 0; i < 4; i++)
{
if (C[i] != D[i+3])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
int B[N] = {0,0,42,42,42,0,0,0,0,0,42,42,42,42,42,0};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] >= MAX ? MAX : 0);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
int B[N] = {0,0,0,42,42,0,0,0,0,0,42,42,42,42,42,0};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] > MAX ? MAX : 0);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
int B[N] = {42,42,42,0,0,42,42,42,42,42,0,0,0,0,0,42};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] <= MAX ? MAX : 0);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
int B[N] = {42,42,0,0,0,42,42,42,42,42,0,0,0,0,0,42};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] < MAX ? MAX : 0);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,42,23,34,45,56,67,42,89,11};
int B[N] = {42,42,0,42,42,42,42,0,42,42,42,42,42,0,42,42};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] != MAX ? MAX : 0);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int main ()
{
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,42,78,89,11};
int B[N] = {42,42,0,42,42,42,42,42,42,42,42,42,0,42,42,42};
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] == MAX ? 0 : MAX);
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-require-effective-target vect_condition } */
/* { dg-do run } */
#include <stdarg.h>
#include <signal.h>
#define N 16
#define MAX 42
extern void abort(void);
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
int B[N] = {0,0,42,42,42,0,0,0,0,0,42,42,42,42,42,0};
void foo () __attribute__((always_inline));
void foo ()
{
int i, j;
for (i = 0; i < 16; i++)
A[i] = ( A[i] >= MAX ? MAX : 0);
}
int main ()
{
int i, j;
foo ();
/* check results: */
for (i = 0; i < N; i++)
if (A[i] != B[i])
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */
...@@ -181,5 +181,6 @@ foo (int n) ...@@ -181,5 +181,6 @@ foo (int n)
} }
/* { dg-final { scan-tree-dump-times "vectorized " 3 "vect"} } */ /* { dg-final { scan-tree-dump-times "vectorized " 3 "vect"} } */
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 3 "vect"} } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"} } */
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 2 "vect"} } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -835,6 +835,25 @@ proc check_effective_target_vect_no_align { } { ...@@ -835,6 +835,25 @@ proc check_effective_target_vect_no_align { } {
return $et_vect_no_align_saved return $et_vect_no_align_saved
} }
# Return 1 if the target supports vector conditional operations, 0 otherwise.
proc check_effective_target_vect_condition { } {
global et_vect_cond_saved
if [info exists et_vect_int_cond] {
verbose "check_effective_target_vect_cond: using cached result" 2
} else {
set et_vect_cond_saved 0
if { [istarget powerpc*-*-*] } {
set et_vect_cond_saved 1
}
}
verbose "check_effective_target_vect_cond: returning $et_vect_cond_saved" 2
return $et_vect_cond_saved
}
# Return 1 if the target matches the effective target 'arg', 0 otherwise. # Return 1 if the target matches the effective target 'arg', 0 otherwise.
# This can be used with any check_* proc that takes no argument and # This can be used with any check_* proc that takes no argument and
# returns only 1 or 0. It could be used with check_* procs that take # returns only 1 or 0. It could be used with check_* procs that take
......
...@@ -646,7 +646,7 @@ all_chrecs_equal_p (tree chrec) ...@@ -646,7 +646,7 @@ all_chrecs_equal_p (tree chrec)
/* Determine for each subscript in the data dependence relation DDR /* Determine for each subscript in the data dependence relation DDR
the distance. */ the distance. */
static void void
compute_subscript_distance (struct data_dependence_relation *ddr) compute_subscript_distance (struct data_dependence_relation *ddr)
{ {
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
...@@ -1769,7 +1769,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) ...@@ -1769,7 +1769,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
starting at FIRST_LOOP_DEPTH. starting at FIRST_LOOP_DEPTH.
Return TRUE otherwise. */ Return TRUE otherwise. */
static bool bool
build_classic_dist_vector (struct data_dependence_relation *ddr, build_classic_dist_vector (struct data_dependence_relation *ddr,
int nb_loops, int first_loop_depth) int nb_loops, int first_loop_depth)
{ {
......
...@@ -176,6 +176,8 @@ extern bool array_base_name_differ_p (struct data_reference *, ...@@ -176,6 +176,8 @@ extern bool array_base_name_differ_p (struct data_reference *,
extern void free_dependence_relation (struct data_dependence_relation *); extern void free_dependence_relation (struct data_dependence_relation *);
extern void free_dependence_relations (varray_type); extern void free_dependence_relations (varray_type);
extern void free_data_refs (varray_type); extern void free_data_refs (varray_type);
extern void compute_subscript_distance (struct data_dependence_relation *);
extern bool build_classic_dist_vector (struct data_dependence_relation *, int, int);
......
...@@ -494,7 +494,8 @@ vect_analyze_operations (loop_vec_info loop_vinfo) ...@@ -494,7 +494,8 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
ok = (vectorizable_operation (stmt, NULL, NULL) ok = (vectorizable_operation (stmt, NULL, NULL)
|| vectorizable_assignment (stmt, NULL, NULL) || vectorizable_assignment (stmt, NULL, NULL)
|| vectorizable_load (stmt, NULL, NULL) || vectorizable_load (stmt, NULL, NULL)
|| vectorizable_store (stmt, NULL, NULL)); || vectorizable_store (stmt, NULL, NULL)
|| vectorizable_condition (stmt, NULL, NULL));
if (!ok) if (!ok)
{ {
...@@ -774,6 +775,12 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, ...@@ -774,6 +775,12 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
{ {
bool differ_p; bool differ_p;
struct data_dependence_relation *ddr; struct data_dependence_relation *ddr;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
int dist = 0;
unsigned int loop_depth = 0;
struct loop *loop_nest = loop;
if (!vect_base_addr_differ_p (dra, drb, &differ_p)) if (!vect_base_addr_differ_p (dra, drb, &differ_p))
{ {
...@@ -797,7 +804,65 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, ...@@ -797,7 +804,65 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
if (DDR_ARE_DEPENDENT (ddr) == chrec_known) if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
return false; return false;
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo)))
{
fprintf (vect_dump,
"not vectorized: can't determine dependence between ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
}
return true;
}
/* Find loop depth. */
while (loop_nest)
{
if (loop_nest->outer && loop_nest->outer->outer)
{
loop_nest = loop_nest->outer;
loop_depth++;
}
else
break;
}
/* Compute distance vector. */
compute_subscript_distance (ddr);
build_classic_dist_vector (ddr, vect_loops_num, loop_nest->depth);
if (!DDR_DIST_VECT (ddr))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo)))
{
fprintf (vect_dump, "not vectorized: bad dist vector for ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
}
return true;
}
dist = DDR_DIST_VECT (ddr)[loop_depth];
/* Same loop iteration. */
if (dist == 0)
{
if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
fprintf (vect_dump, "dependence distance 0.");
return false;
}
if (dist >= vectorization_factor)
/* Dependence distance does not create dependence, as far as vectorization
is concerned, in this case. */
return false;
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo))) LOOP_LOC (loop_vinfo)))
{ {
...@@ -815,10 +880,7 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, ...@@ -815,10 +880,7 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
/* Function vect_analyze_data_ref_dependences. /* Function vect_analyze_data_ref_dependences.
Examine all the data references in the loop, and make sure there do not Examine all the data references in the loop, and make sure there do not
exist any data dependences between them. exist any data dependences between them. */
TODO: dependences which distance is greater than the vectorization factor
can be ignored. */
static bool static bool
vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
...@@ -2567,6 +2629,15 @@ vect_analyze_loop (struct loop *loop) ...@@ -2567,6 +2629,15 @@ vect_analyze_loop (struct loop *loop)
return NULL; return NULL;
} }
ok = vect_determine_vectorization_factor (loop_vinfo);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
fprintf (vect_dump, "can't determine vectorization factor.");
destroy_loop_vec_info (loop_vinfo);
return NULL;
}
/* Analyze data dependences between the data-refs in the loop. /* Analyze data dependences between the data-refs in the loop.
FORNOW: fail at the first data dependence that we encounter. */ FORNOW: fail at the first data dependence that we encounter. */
...@@ -2591,15 +2662,6 @@ vect_analyze_loop (struct loop *loop) ...@@ -2591,15 +2662,6 @@ vect_analyze_loop (struct loop *loop)
return NULL; return NULL;
} }
ok = vect_determine_vectorization_factor (loop_vinfo);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
fprintf (vect_dump, "can't determine vectorization factor.");
destroy_loop_vec_info (loop_vinfo);
return NULL;
}
/* Analyze the alignment of the data-refs in the loop. /* Analyze the alignment of the data-refs in the loop.
FORNOW: Only aligned accesses are handled. */ FORNOW: Only aligned accesses are handled. */
......
...@@ -57,6 +57,7 @@ static tree vect_get_vec_def_for_operand (tree, tree); ...@@ -57,6 +57,7 @@ static tree vect_get_vec_def_for_operand (tree, tree);
static tree vect_init_vector (tree, tree); static tree vect_init_vector (tree, tree);
static void vect_finish_stmt_generation static void vect_finish_stmt_generation
(tree stmt, tree vec_stmt, block_stmt_iterator *bsi); (tree stmt, tree vec_stmt, block_stmt_iterator *bsi);
static bool vect_is_simple_cond (tree, loop_vec_info);
static void update_vuses_to_preheader (tree, struct loop*); static void update_vuses_to_preheader (tree, struct loop*);
/* Utility function dealing with loop peeling (not peeling itself). */ /* Utility function dealing with loop peeling (not peeling itself). */
...@@ -1141,6 +1142,145 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) ...@@ -1141,6 +1142,145 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
return true; return true;
} }
/* Function vect_is_simple_cond.
Input:
LOOP - the loop that is being vectorized.
COND - Condition that is checked for simple use.
Returns whether a COND can be vectorized. Checkes whether
condition operands are supportable using vec_is_simple_use. */
static bool
vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
{
tree lhs, rhs;
if (TREE_CODE_CLASS (TREE_CODE (cond)) != tcc_comparison)
return false;
lhs = TREE_OPERAND (cond, 0);
rhs = TREE_OPERAND (cond, 1);
if (TREE_CODE (lhs) == SSA_NAME)
{
tree lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt))
return false;
}
else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST)
return false;
if (TREE_CODE (rhs) == SSA_NAME)
{
tree rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt))
return false;
}
else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST)
return false;
return true;
}
/* vectorizable_condition.
Check if STMT is conditional modify expression that can be vectorized.
If VEC_STMT is also passed, vectorize the STMT: create a vectorized
stmt using VEC_COND_EXPR to replace it, put it in VEC_STMT, and insert it
at BSI.
Return FALSE if not a vectorizable STMT, TRUE otherwise. */
bool
vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
{
tree scalar_dest = NULL_TREE;
tree vec_dest = NULL_TREE;
tree op = NULL_TREE;
tree cond_expr, then_clause, else_clause;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree vec_cond_lhs, vec_cond_rhs, vec_then_clause, vec_else_clause;
tree vec_compare, vec_cond_expr;
tree new_temp;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum machine_mode vec_mode;
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
if (TREE_CODE (stmt) != MODIFY_EXPR)
return false;
op = TREE_OPERAND (stmt, 1);
if (TREE_CODE (op) != COND_EXPR)
return false;
cond_expr = TREE_OPERAND (op, 0);
then_clause = TREE_OPERAND (op, 1);
else_clause = TREE_OPERAND (op, 2);
if (!vect_is_simple_cond (cond_expr, loop_vinfo))
return false;
if (TREE_CODE (then_clause) == SSA_NAME)
{
tree then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
if (!vect_is_simple_use (then_clause, loop_vinfo, &then_def_stmt))
return false;
}
else if (TREE_CODE (then_clause) != INTEGER_CST
&& TREE_CODE (then_clause) != REAL_CST)
return false;
if (TREE_CODE (else_clause) == SSA_NAME)
{
tree else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
if (!vect_is_simple_use (else_clause, loop_vinfo, &else_def_stmt))
return false;
}
else if (TREE_CODE (else_clause) != INTEGER_CST
&& TREE_CODE (else_clause) != REAL_CST)
return false;
vec_mode = TYPE_MODE (vectype);
if (!vec_stmt)
{
STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
return expand_vec_cond_expr_p (op, vec_mode);
}
/* Transform */
/* Handle def. */
scalar_dest = TREE_OPERAND (stmt, 0);
vec_dest = vect_create_destination_var (scalar_dest, vectype);
/* Handle cond expr. */
vec_cond_lhs =
vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt);
vec_cond_rhs =
vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt);
vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt);
vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt);
/* Arguments are ready. create the new vector stmt. */
vec_compare = build2 (TREE_CODE (cond_expr), vectype,
vec_cond_lhs, vec_cond_rhs);
vec_cond_expr = build (VEC_COND_EXPR, vectype,
vec_compare, vec_then_clause, vec_else_clause);
*vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_cond_expr);
new_temp = make_ssa_name (vec_dest, *vec_stmt);
TREE_OPERAND (*vec_stmt, 0) = new_temp;
vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
return true;
}
/* Function vect_transform_stmt. /* Function vect_transform_stmt.
...@@ -1176,6 +1316,12 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi) ...@@ -1176,6 +1316,12 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi)
gcc_assert (done); gcc_assert (done);
is_store = true; is_store = true;
break; break;
case condition_vec_info_type:
done = vectorizable_condition (stmt, bsi, &vec_stmt);
gcc_assert (done);
break;
default: default:
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "stmt not supported."); fprintf (vect_dump, "stmt not supported.");
......
...@@ -178,7 +178,8 @@ FILE *vect_dump; ...@@ -178,7 +178,8 @@ FILE *vect_dump;
to mark that it's uninitialized. */ to mark that it's uninitialized. */
enum verbosity_levels vect_verbosity_level = MAX_VERBOSITY_LEVEL; enum verbosity_levels vect_verbosity_level = MAX_VERBOSITY_LEVEL;
/* Number of loops, at the beginning of vectorization. */
unsigned int vect_loops_num;
/************************************************************************* /*************************************************************************
Simple Loop Peeling Utilities Simple Loop Peeling Utilities
...@@ -1821,7 +1822,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, ...@@ -1821,7 +1822,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
void void
vectorize_loops (struct loops *loops) vectorize_loops (struct loops *loops)
{ {
unsigned int i, loops_num; unsigned int i;
unsigned int num_vectorized_loops = 0; unsigned int num_vectorized_loops = 0;
/* Fix the verbosity level if not defined explicitly by the user. */ /* Fix the verbosity level if not defined explicitly by the user. */
...@@ -1841,8 +1842,8 @@ vectorize_loops (struct loops *loops) ...@@ -1841,8 +1842,8 @@ vectorize_loops (struct loops *loops)
/* If some loop was duplicated, it gets bigger number /* If some loop was duplicated, it gets bigger number
than all previously defined loops. This fact allows us to run than all previously defined loops. This fact allows us to run
only over initial loops skipping newly generated ones. */ only over initial loops skipping newly generated ones. */
loops_num = loops->num; vect_loops_num = loops->num;
for (i = 1; i < loops_num; i++) for (i = 1; i < vect_loops_num; i++)
{ {
loop_vec_info loop_vinfo; loop_vec_info loop_vinfo;
struct loop *loop = loops->parray[i]; struct loop *loop = loops->parray[i];
...@@ -1866,7 +1867,7 @@ vectorize_loops (struct loops *loops) ...@@ -1866,7 +1867,7 @@ vectorize_loops (struct loops *loops)
/* ----------- Finalize. ----------- */ /* ----------- Finalize. ----------- */
for (i = 1; i < loops_num; i++) for (i = 1; i < vect_loops_num; i++)
{ {
struct loop *loop = loops->parray[i]; struct loop *loop = loops->parray[i];
loop_vec_info loop_vinfo; loop_vec_info loop_vinfo;
......
...@@ -144,7 +144,8 @@ enum stmt_vec_info_type { ...@@ -144,7 +144,8 @@ enum stmt_vec_info_type {
load_vec_info_type, load_vec_info_type,
store_vec_info_type, store_vec_info_type,
op_vec_info_type, op_vec_info_type,
assignment_vec_info_type assignment_vec_info_type,
condition_vec_info_type
}; };
typedef struct _stmt_vec_info { typedef struct _stmt_vec_info {
...@@ -277,6 +278,8 @@ known_alignment_for_access_p (struct data_reference *data_ref_info) ...@@ -277,6 +278,8 @@ known_alignment_for_access_p (struct data_reference *data_ref_info)
extern FILE *vect_dump; extern FILE *vect_dump;
extern enum verbosity_levels vect_verbosity_level; extern enum verbosity_levels vect_verbosity_level;
/* Number of loops, at the beginning of vectorization. */
extern unsigned int vect_loops_num;
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
/* Function prototypes. */ /* Function prototypes. */
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
...@@ -327,6 +330,7 @@ extern bool vectorizable_load (tree, block_stmt_iterator *, tree *); ...@@ -327,6 +330,7 @@ extern bool vectorizable_load (tree, block_stmt_iterator *, tree *);
extern bool vectorizable_store (tree, block_stmt_iterator *, tree *); 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 *);
/* 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