mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
45f27db0d4
commit
b52485c631
|
@ -1,3 +1,29 @@
|
|||
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>
|
||||
|
||||
* config/t-slibgcc-darwin: Don't put shared libraries in
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
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>
|
||||
|
||||
PR tree-optimization/20933
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* 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];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/* { 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 } } } */
|
|
@ -0,0 +1,74 @@
|
|||
/* { 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 } } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,31 @@
|
|||
/* { 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" } } */
|
|
@ -0,0 +1,36 @@
|
|||
/* { 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)
|
|||
}
|
||||
|
||||
/* { 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" } } */
|
||||
|
|
|
@ -835,6 +835,25 @@ proc check_effective_target_vect_no_align { } {
|
|||
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.
|
||||
# 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
|
||||
|
|
|
@ -646,7 +646,7 @@ all_chrecs_equal_p (tree chrec)
|
|||
/* Determine for each subscript in the data dependence relation DDR
|
||||
the distance. */
|
||||
|
||||
static void
|
||||
void
|
||||
compute_subscript_distance (struct data_dependence_relation *ddr)
|
||||
{
|
||||
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
|
||||
|
@ -1769,7 +1769,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
|
|||
starting at FIRST_LOOP_DEPTH.
|
||||
Return TRUE otherwise. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
build_classic_dist_vector (struct data_dependence_relation *ddr,
|
||||
int nb_loops, int first_loop_depth)
|
||||
{
|
||||
|
|
|
@ -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_relations (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)
|
|||
ok = (vectorizable_operation (stmt, NULL, NULL)
|
||||
|| vectorizable_assignment (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)
|
||||
{
|
||||
|
@ -774,6 +775,12 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
|
|||
{
|
||||
bool differ_p;
|
||||
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))
|
||||
{
|
||||
|
@ -797,7 +804,65 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
|
|||
|
||||
if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
|
||||
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,
|
||||
LOOP_LOC (loop_vinfo)))
|
||||
{
|
||||
|
@ -815,10 +880,7 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
|
|||
/* Function vect_analyze_data_ref_dependences.
|
||||
|
||||
Examine all the data references in the loop, and make sure there do not
|
||||
exist any data dependences between them.
|
||||
|
||||
TODO: dependences which distance is greater than the vectorization factor
|
||||
can be ignored. */
|
||||
exist any data dependences between them. */
|
||||
|
||||
static bool
|
||||
vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
|
||||
|
@ -2567,6 +2629,15 @@ vect_analyze_loop (struct loop *loop)
|
|||
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.
|
||||
FORNOW: fail at the first data dependence that we encounter. */
|
||||
|
||||
|
@ -2591,15 +2662,6 @@ vect_analyze_loop (struct loop *loop)
|
|||
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.
|
||||
FORNOW: Only aligned accesses are handled. */
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ static tree vect_get_vec_def_for_operand (tree, tree);
|
|||
static tree vect_init_vector (tree, tree);
|
||||
static void vect_finish_stmt_generation
|
||||
(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*);
|
||||
|
||||
/* Utility function dealing with loop peeling (not peeling itself). */
|
||||
|
@ -1141,6 +1142,145 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
|
|||
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.
|
||||
|
||||
|
@ -1176,6 +1316,12 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi)
|
|||
gcc_assert (done);
|
||||
is_store = true;
|
||||
break;
|
||||
|
||||
case condition_vec_info_type:
|
||||
done = vectorizable_condition (stmt, bsi, &vec_stmt);
|
||||
gcc_assert (done);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
|
||||
fprintf (vect_dump, "stmt not supported.");
|
||||
|
|
|
@ -178,7 +178,8 @@ FILE *vect_dump;
|
|||
to mark that it's uninitialized. */
|
||||
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
|
||||
|
@ -1821,7 +1822,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
|
|||
void
|
||||
vectorize_loops (struct loops *loops)
|
||||
{
|
||||
unsigned int i, loops_num;
|
||||
unsigned int i;
|
||||
unsigned int num_vectorized_loops = 0;
|
||||
|
||||
/* Fix the verbosity level if not defined explicitly by the user. */
|
||||
|
@ -1841,8 +1842,8 @@ vectorize_loops (struct loops *loops)
|
|||
/* If some loop was duplicated, it gets bigger number
|
||||
than all previously defined loops. This fact allows us to run
|
||||
only over initial loops skipping newly generated ones. */
|
||||
loops_num = loops->num;
|
||||
for (i = 1; i < loops_num; i++)
|
||||
vect_loops_num = loops->num;
|
||||
for (i = 1; i < vect_loops_num; i++)
|
||||
{
|
||||
loop_vec_info loop_vinfo;
|
||||
struct loop *loop = loops->parray[i];
|
||||
|
@ -1866,7 +1867,7 @@ vectorize_loops (struct loops *loops)
|
|||
|
||||
/* ----------- Finalize. ----------- */
|
||||
|
||||
for (i = 1; i < loops_num; i++)
|
||||
for (i = 1; i < vect_loops_num; i++)
|
||||
{
|
||||
struct loop *loop = loops->parray[i];
|
||||
loop_vec_info loop_vinfo;
|
||||
|
|
|
@ -144,7 +144,8 @@ enum stmt_vec_info_type {
|
|||
load_vec_info_type,
|
||||
store_vec_info_type,
|
||||
op_vec_info_type,
|
||||
assignment_vec_info_type
|
||||
assignment_vec_info_type,
|
||||
condition_vec_info_type
|
||||
};
|
||||
|
||||
typedef struct _stmt_vec_info {
|
||||
|
@ -277,6 +278,8 @@ known_alignment_for_access_p (struct data_reference *data_ref_info)
|
|||
extern FILE *vect_dump;
|
||||
extern enum verbosity_levels vect_verbosity_level;
|
||||
|
||||
/* Number of loops, at the beginning of vectorization. */
|
||||
extern unsigned int vect_loops_num;
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Function prototypes. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -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_operation (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. */
|
||||
extern void vect_transform_loop (loop_vec_info, struct loops *);
|
||||
|
||||
|
|
Loading…
Reference in New Issue