Commit bc1edb77 by Victor Kaplansky Committed by Victor Kaplansky

tree-vectorizer.c (new_loop_vec_info): Initialize new field.


gcc/ChangeLog

	* tree-vectorizer.c (new_loop_vec_info): Initialize new 
	field.
	(destroy_loop_vec_info): Add call to VEC_free.
	* tree-vectorizer.h (may_alias_ddrs): Define.
	(LOOP_VINFO_MAY_ALIAS_DDRS): Define.
	* tree-vect-analyze.c (vect_analyze_data_ref_dependence):
	Change reporting to dump.
	(vect_is_duplicate_ddr): New.
	(vect_mark_for_runtime_alias_test): New.
	(vect_analyze_data_ref_dependences) Add call to
	vect_mark_for_runtime_alias_test.
	(vect_enhance_data_refs_alignment): Define local variable
	vect_versioning_for_alias_required, don't perform
	peeling for alignment if versioning for alias is
	required.
	(vect_enhance_data_refs_alignment): Use
	PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS instead of
	PARAM_VECT_MAX_VERSION_CHECKS.
	* tree-vect-transform.c
	(vect_create_cond_for_alias_checks): New.
	(vect_transform_loop): Add call to
	vect_create_cond_for_alias_checks.
	(vect_vfa_segment_size): New.
	* params.def (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS):
	Rename.
	(PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS): Define.
	* gcc/doc/invoke.texi
	(vect-max-version-for-alignment-checks): Document.
	(vect-max-version-for-alias-checks): Document.
	(vect-max-version-checks): Remove.
     
gcc/testsuite/ChangeLog

	* gcc.dg/vect/vect-vfa-01.c: New.
	* gcc.dg/vect/vect-vfa-02.c: New.
	* gcc.dg/vect/vect-vfa-03.c: New.
	* gcc.dg/vect/vect-vfa-04.c: New.
	* gcc.dg/vect/vect-102a.c, gcc.dg/vect/vect-51.c,
	gcc.dg/vect/pr29145.c, gcc.dg/vect/vect-43.c,
	gcc.dg/vect/vect-61.c, gcc.dg/vect/vect-53.c,
	gcc.dg/vect/vect-45.c, gcc.dg/vect/vect-101.c,
	gcc.dg/vect/vect-37.c, gcc.dg/vect/vect-79.c,
	gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-dv-2.c,
	gcc.dg/vect/vect-57.c, gcc.dg/vect/vect-49.c,
	gfortran.dg/vect/pr19049.f90: Rename to start with
	prefix no-vfa-.
	* gcc.dg/vect/vect.exp: Disable versioning for alias
	when test starts with no-vfa-.
	* gfortran.dg/vect/vect.exp: Likewise.

From-SVN: r127559
parent 57c2d13f
2007-08-16 Victor Kaplansky <victork@il.ibm.com>
* tree-vectorizer.c (new_loop_vec_info): Initialize new
field.
(destroy_loop_vec_info): Add call to VEC_free.
* tree-vectorizer.h (may_alias_ddrs): Define.
(LOOP_VINFO_MAY_ALIAS_DDRS): Define.
* tree-vect-analyze.c (vect_analyze_data_ref_dependence):
Change reporting to dump.
(vect_is_duplicate_ddr): New.
(vect_mark_for_runtime_alias_test): New.
(vect_analyze_data_ref_dependences) Add call to
vect_mark_for_runtime_alias_test.
(vect_enhance_data_refs_alignment): Define local variable
vect_versioning_for_alias_required, don't perform
peeling for alignment if versioning for alias is
required.
(vect_enhance_data_refs_alignment): Use
PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS instead of
PARAM_VECT_MAX_VERSION_CHECKS.
* tree-vect-transform.c
(vect_create_cond_for_alias_checks): New.
(vect_transform_loop): Add call to
vect_create_cond_for_alias_checks.
(vect_vfa_segment_size): New.
* params.def (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS):
Rename.
(PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS): Define.
* gcc/doc/invoke.texi
(vect-max-version-for-alignment-checks): Document.
(vect-max-version-for-alias-checks): Document.
(vect-max-version-checks): Remove.
2007-08-16 Uros Bizjak <ubizjak@gmail.com> 2007-08-16 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*rep_movdi_rex64): Emit "rep" prefix on * config/i386/i386.md (*rep_movdi_rex64): Emit "rep" prefix on
......
...@@ -6741,10 +6741,15 @@ value is 500. ...@@ -6741,10 +6741,15 @@ value is 500.
When set to 1, use expensive methods to eliminate all redundant When set to 1, use expensive methods to eliminate all redundant
constraints. The default value is 0. constraints. The default value is 0.
@item vect-max-version-checks @item vect-max-version-for-alignment-checks
The maximum number of runtime checks that can be performed when doing The maximum number of runtime checks that can be performed when
loop versioning in the vectorizer. See option ftree-vect-loop-version doing loop versioning for alignment in the vectorizer. See option
for more information. ftree-vect-loop-version for more information.
@item vect-max-version-for-alias-checks
The maximum number of runtime checks that can be performed when
doing loop versioning for alias in the vectorizer. See option
ftree-vect-loop-version for more information.
@item max-iterations-to-track @item max-iterations-to-track
......
...@@ -485,11 +485,16 @@ DEFPARAM(PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS, ...@@ -485,11 +485,16 @@ DEFPARAM(PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS,
"When set to 1, use expensive methods to eliminate all redundant constraints", "When set to 1, use expensive methods to eliminate all redundant constraints",
0, 0, 1) 0, 0, 1)
DEFPARAM(PARAM_VECT_MAX_VERSION_CHECKS, DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS,
"vect-max-version-checks", "vect-max-version-for-alignment-checks",
"Bound on number of runtime checks inserted by the vectorizer's loop versioning", "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check",
6, 0, 0) 6, 0, 0)
DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS,
"vect-max-version-for-alias-checks",
"Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check",
10, 0, 0)
DEFPARAM(PARAM_MAX_CSELIB_MEMORY_LOCATIONS, DEFPARAM(PARAM_MAX_CSELIB_MEMORY_LOCATIONS,
"max-cselib-memory-locations", "max-cselib-memory-locations",
"The maximum memory locations recorded by cselib", "The maximum memory locations recorded by cselib",
......
2007-08-16 Victor Kaplansky <victork@il.ibm.com>
* gcc.dg/vect/vect-vfa-01.c: New.
* gcc.dg/vect/vect-vfa-02.c: New.
* gcc.dg/vect/vect-vfa-03.c: New.
* gcc.dg/vect/vect-vfa-04.c: New.
* gcc.dg/vect/vect-102a.c, gcc.dg/vect/vect-51.c,
gcc.dg/vect/pr29145.c, gcc.dg/vect/vect-43.c,
gcc.dg/vect/vect-61.c, gcc.dg/vect/vect-53.c,
gcc.dg/vect/vect-45.c, gcc.dg/vect/vect-101.c,
gcc.dg/vect/vect-37.c, gcc.dg/vect/vect-79.c,
gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-dv-2.c,
gcc.dg/vect/vect-57.c, gcc.dg/vect/vect-49.c,
gfortran.dg/vect/pr19049.f90: Rename to start with
prefix no-vfa-.
* gcc.dg/vect/vect.exp: Disable versioning for alias
when test starts with no-vfa-.
* gfortran.dg/vect/vect.exp: Likewise.
2007-08-16 Richard Sandiford <richard@codesourcery.com> 2007-08-16 Richard Sandiford <richard@codesourcery.com>
* gcc.dg/torture/pr32897.c: New test. * gcc.dg/torture/pr32897.c: New test.
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
int result[N] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
int X[N] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
int Y[N] = {};
void
foo (int *in, int *out)
{
int i;
for (i = 0; i < N; i++)
out[i] = in[i] + 2;
}
int
main (void)
{
int i;
check_vect ();
foo (X, Y);
/* check results: */
for (i = 0; i < N; i++)
{
if (Y[i] != result[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
int resultY[N] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
int resultZ[N] = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28};
int X[N] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
int Y[N] = {};
int Z[N] = {};
void
foo (int *in, int *out1, int *out2)
{
int i;
for (i = 0; i < N; i++)
{
out1[i] = in[i] + 2;
out2[i] = in[i] + 3;
}
}
int
main (void)
{
int i;
check_vect ();
foo (X, Y, Z);
/* check results: */
for (i = 0; i < N; i++)
{
if (Y[i] != resultY[i])
abort ();
if (Z[i] != resultZ[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
struct S
{
unsigned short a;
unsigned short b;
};
struct S result[N] = {12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24,
24, 25, 25, 26, 26, 27, 27, 28};
struct S X[N] = {10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25};
struct S Y[N] = {};
void
foo (struct S * in, struct S * out)
{
int i;
for (i = 0; i < N; i++)
{
out[i].a = in[i].a + 2;
out[i].b = in[i].b + 3;
}
}
int
main (void)
{
int i;
check_vect ();
foo (X, Y);
/* check results: */
for (i = 0; i < N; i++)
{
if (Y[i].a != result[i].a)
abort ();
if (Y[i].b != result[i].b)
abort ();
}
return 0;
}
/* Needs interleaving support. */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail { vect_interleave && vect_extract_even_odd } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 16
int result[] = {10, 11, 15, 16, 20, 21, 25, 26, 30, 31, 35, 36, 40, 41, 45, 46, 50, 51};
int X[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0};
void
foo (int *in, int *out)
{
int i;
for (i = 0; i < N; i++)
out[i] = in[i] + 5;
}
int
main (void)
{
int i;
check_vect ();
foo (X, &X[2]);
/* check results: */
for (i = 0; i < N+2; i++)
{
if (X[i] != result[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -113,6 +113,12 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \ ...@@ -113,6 +113,12 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \
global SAVED_DEFAULT_VECTCFLAGS global SAVED_DEFAULT_VECTCFLAGS
set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS
# --param vect-max-version-for-alias-checks=0 tests
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
lappend DEFAULT_VECTCFLAGS "--param" "vect-max-version-for-alias-checks=0"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-vfa-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
# -ffast-math tests # -ffast-math tests
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
lappend DEFAULT_VECTCFLAGS "-ffast-math" lappend DEFAULT_VECTCFLAGS "-ffast-math"
......
...@@ -90,7 +90,18 @@ proc check_effective_target_lp64_or_vect_no_align { } { ...@@ -90,7 +90,18 @@ proc check_effective_target_lp64_or_vect_no_align { } {
dg-init dg-init
# Main loop. # Main loop.
gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS
gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr-*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS
#### Tests with special options
global SAVED_DEFAULT_VECTCFLAGS
set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS
# --param vect-max-version-for-alias-checks=0 tests
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
lappend DEFAULT_VECTCFLAGS "--param" "vect-max-version-for-alias-checks=0"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-vfa-*.\[fF\]{,90,95,03} ]] \
"" $DEFAULT_VECTCFLAGS
# Clean up. # Clean up.
set dg-do-what-default ${save-dg-do-what-default} set dg-do-what-default ${save-dg-do-what-default}
......
...@@ -1039,10 +1039,10 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -1039,10 +1039,10 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
{ {
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) if (vect_print_dump_info (REPORT_DR_DETAILS))
{ {
fprintf (vect_dump, fprintf (vect_dump,
"not vectorized: can't determine dependence between "); "versioning for alias required: can't determine dependence between ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and "); fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
...@@ -1052,9 +1052,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -1052,9 +1052,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (DDR_NUM_DIST_VECTS (ddr) == 0) if (DDR_NUM_DIST_VECTS (ddr) == 0)
{ {
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) if (vect_print_dump_info (REPORT_DR_DETAILS))
{ {
fprintf (vect_dump, "not vectorized: bad dist vector for "); fprintf (vect_dump, "versioning for alias required: bad dist vector for ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and "); fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
...@@ -1108,10 +1108,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -1108,10 +1108,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
continue; continue;
} }
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) if (vect_print_dump_info (REPORT_DR_DETAILS))
{ {
fprintf (vect_dump, fprintf (vect_dump,
"not vectorized: possible dependence between data-refs "); "versioning for alias required: possible dependence "
"between data-refs ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and "); fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
...@@ -1123,6 +1124,77 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -1123,6 +1124,77 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
return false; return false;
} }
/* Return TRUE if DDR_NEW is already found in MAY_ALIAS_DDRS list. */
static bool
vect_is_duplicate_ddr (VEC (ddr_p, heap) * may_alias_ddrs, ddr_p ddr_new)
{
unsigned i;
ddr_p ddr;
for (i = 0; VEC_iterate (ddr_p, may_alias_ddrs, i, ddr); i++)
{
tree dref_A_i, dref_B_i, dref_A_j, dref_B_j;
dref_A_i = DR_REF (DDR_A (ddr));
dref_B_i = DR_REF (DDR_B (ddr));
dref_A_j = DR_REF (DDR_A (ddr_new));
dref_B_j = DR_REF (DDR_B (ddr_new));
if ((operand_equal_p (dref_A_i, dref_A_j, 0)
&& operand_equal_p (dref_B_i, dref_B_j, 0))
|| (operand_equal_p (dref_A_i, dref_B_j, 0)
&& operand_equal_p (dref_B_i, dref_A_j, 0)))
{
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
fprintf (vect_dump, "found same pair of data references ");
print_generic_expr (vect_dump, dref_A_i, TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, dref_B_i, TDF_SLIM);
}
return true;
}
}
return false;
}
/* Save DDR in LOOP_VINFO list of ddrs that may alias and need to be
tested at run-time. Returns false if number of run-time checks
inserted by vectorizer is greater than maximum defined by
PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS. */
static bool
vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
{
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
fprintf (vect_dump, "mark for run-time aliasing test between ");
print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM);
}
/* Do not add to the list duplicate ddrs. */
if (vect_is_duplicate_ddr (LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), ddr))
return true;
if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))
>= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
{
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
fprintf (vect_dump,
"disable versioning for alias - max number of generated "
"checks exceeded.");
}
VEC_truncate (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), 0);
return false;
}
VEC_safe_push (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), ddr);
return true;
}
/* Function vect_analyze_data_ref_dependences. /* Function vect_analyze_data_ref_dependences.
...@@ -1133,7 +1205,7 @@ static bool ...@@ -1133,7 +1205,7 @@ static bool
vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
{ {
unsigned int i; unsigned int i;
VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo); VEC (ddr_p, heap) * ddrs = LOOP_VINFO_DDRS (loop_vinfo);
struct data_dependence_relation *ddr; struct data_dependence_relation *ddr;
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
...@@ -1141,7 +1213,11 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) ...@@ -1141,7 +1213,11 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++) for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
if (vect_analyze_data_ref_dependence (ddr, loop_vinfo)) if (vect_analyze_data_ref_dependence (ddr, loop_vinfo))
{
/* Add to list of ddrs that need to be tested at run-time. */
if (!vect_mark_for_runtime_alias_test (ddr, loop_vinfo))
return false; return false;
}
return true; return true;
} }
...@@ -1554,6 +1630,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) ...@@ -1554,6 +1630,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
bool stat; bool stat;
tree stmt; tree stmt;
stmt_vec_info stmt_info; stmt_vec_info stmt_info;
int vect_versioning_for_alias_required;
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_enhance_data_refs_alignment ==="); fprintf (vect_dump, "=== vect_enhance_data_refs_alignment ===");
...@@ -1619,9 +1696,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) ...@@ -1619,9 +1696,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
} }
} }
/* Often peeling for alignment will require peeling for loop-bound, which in vect_versioning_for_alias_required =
turn requires that we know how to adjust the loop ivs after the loop. */ (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)) > 0);
if (!vect_can_advance_ivs_p (loop_vinfo)
/* Temporarily, if versioning for alias is required, we disable peeling
until we support peeling and versioning. Often peeling for alignment
will require peeling for loop-bound, which in turn requires that we
know how to adjust the loop ivs after the loop. */
if (vect_versioning_for_alias_required
|| !vect_can_advance_ivs_p (loop_vinfo)
|| !slpeel_can_duplicate_loop_p (loop, single_exit (loop))) || !slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
do_peeling = false; do_peeling = false;
...@@ -1749,7 +1832,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) ...@@ -1749,7 +1832,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (known_alignment_for_access_p (dr) if (known_alignment_for_access_p (dr)
|| VEC_length (tree, || VEC_length (tree,
LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)) LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
>= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_CHECKS)) >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS))
{ {
do_versioning = false; do_versioning = false;
break; break;
......
...@@ -5805,6 +5805,146 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo, ...@@ -5805,6 +5805,146 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
and_tmp_name, ptrsize_zero); and_tmp_name, ptrsize_zero);
} }
/* Function vect_vfa_segment_size.
Create an expression that computes the size of segment
that will be accessed for a data reference. The functions takes into
account that realignment loads may access one more vector.
Input:
DR: The data reference.
VECT_FACTOR: vectorization factor.
Return an exrpession whose value is the size of segment which will be
accessed by DR. */
static tree
vect_vfa_segment_size (struct data_reference *dr, tree vect_factor)
{
tree segment_length;
if (vect_supportable_dr_alignment (dr) == dr_unaligned_software_pipeline)
{
tree vector_size =
build_int_cst (integer_type_node,
GET_MODE_SIZE (TYPE_MODE (STMT_VINFO_VECTYPE
(vinfo_for_stmt (DR_STMT (dr))))));
segment_length =
fold_convert (sizetype,
fold_build2 (PLUS_EXPR, integer_type_node,
fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr),
vect_factor),
vector_size));
}
else
{
segment_length =
fold_convert (sizetype,
fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr),
vect_factor));
}
return segment_length;
}
/* Function vect_create_cond_for_alias_checks.
Create a conditional expression that represents the run-time checks for
overlapping of address ranges represented by a list of data references
relations passed as input.
Input:
COND_EXPR - input conditional expression. New conditions will be chained
with logical and operation.
LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs
to be checked.
Output:
COND_EXPR - conditional expression.
COND_EXPR_STMT_LIST - statements needed to construct the conditional
expression.
The returned value is the conditional expression to be used in the if
statement that controls which version of the loop gets executed at runtime.
*/
static void
vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
tree * cond_expr,
tree * cond_expr_stmt_list)
{
VEC (ddr_p, heap) * may_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
tree vect_factor =
build_int_cst (integer_type_node, LOOP_VINFO_VECT_FACTOR (loop_vinfo));
ddr_p ddr;
unsigned int i;
tree part_cond_expr;
/* Create expression
((store_ptr_0 + store_segment_length_0) < load_ptr_0)
|| (load_ptr_0 + load_segment_length_0) < store_ptr_0))
&&
...
&&
((store_ptr_n + store_segment_length_n) < load_ptr_n)
|| (load_ptr_n + load_segment_length_n) < store_ptr_n)) */
if (VEC_empty (ddr_p, may_alias_ddrs))
return;
for (i = 0; VEC_iterate (ddr_p, may_alias_ddrs, i, ddr); i++)
{
tree stmt_a = DR_STMT (DDR_A (ddr));
tree stmt_b = DR_STMT (DDR_B (ddr));
tree addr_base_a =
vect_create_addr_base_for_vector_ref (stmt_a, cond_expr_stmt_list,
NULL_TREE);
tree addr_base_b =
vect_create_addr_base_for_vector_ref (stmt_b, cond_expr_stmt_list,
NULL_TREE);
tree segment_length_a = vect_vfa_segment_size (DDR_A (ddr), vect_factor);
tree segment_length_b = vect_vfa_segment_size (DDR_B (ddr), vect_factor);
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
fprintf (vect_dump,
"create runtime check for data references ");
print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM);
}
part_cond_expr =
fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
fold_build2 (LT_EXPR, boolean_type_node,
fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_a),
addr_base_a,
segment_length_a),
addr_base_b),
fold_build2 (LT_EXPR, boolean_type_node,
fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_b),
addr_base_b,
segment_length_b),
addr_base_a));
if (*cond_expr)
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
*cond_expr, part_cond_expr);
else
*cond_expr = part_cond_expr;
}
if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
fprintf (vect_dump, "created %u versioning for alias checks.\n",
VEC_length (ddr_p, may_alias_ddrs));
}
/* Function vect_transform_loop. /* Function vect_transform_loop.
...@@ -5827,16 +5967,21 @@ vect_transform_loop (loop_vec_info loop_vinfo) ...@@ -5827,16 +5967,21 @@ vect_transform_loop (loop_vec_info loop_vinfo)
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vec_transform_loop ==="); fprintf (vect_dump, "=== vec_transform_loop ===");
/* If the loop has data references that may or may not be aligned then /* If the loop has data references that may or may not be aligned or/and
has data reference relations whose independence was not proven then
two versions of the loop need to be generated, one which is vectorized two versions of the loop need to be generated, one which is vectorized
and one which isn't. A test is then generated to control which of the and one which isn't. A test is then generated to control which of the
loops is executed. The test checks for the alignment of all of the loops is executed. The test checks for the alignment of all of the
data references that may or may not be aligned. */ data references that may or may not be aligned. An additional
sequence of runtime tests is generated for each pairs of DDRs whose
independence was not proven. The vectorized version of loop is
executed only if both alias and alignment tests are passed. */
if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))) if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
|| VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
{ {
struct loop *nloop; struct loop *nloop;
tree cond_expr; tree cond_expr = NULL_TREE;
tree cond_expr_stmt_list = NULL_TREE; tree cond_expr_stmt_list = NULL_TREE;
basic_block condition_bb; basic_block condition_bb;
block_stmt_iterator cond_exp_bsi; block_stmt_iterator cond_exp_bsi;
...@@ -5845,9 +5990,23 @@ vect_transform_loop (loop_vec_info loop_vinfo) ...@@ -5845,9 +5990,23 @@ vect_transform_loop (loop_vec_info loop_vinfo)
edge new_exit_e, e; edge new_exit_e, e;
tree orig_phi, new_phi, arg; tree orig_phi, new_phi, arg;
unsigned prob = 4 * REG_BR_PROB_BASE / 5; unsigned prob = 4 * REG_BR_PROB_BASE / 5;
tree gimplify_stmt_list;
cond_expr = vect_create_cond_for_align_checks (loop_vinfo, if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
cond_expr =
vect_create_cond_for_align_checks (loop_vinfo, &cond_expr_stmt_list);
if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr,
&cond_expr_stmt_list); &cond_expr_stmt_list);
cond_expr =
fold_build2 (NE_EXPR, boolean_type_node, cond_expr, integer_zero_node);
cond_expr =
force_gimple_operand (cond_expr, &gimplify_stmt_list, true,
NULL_TREE);
append_to_statement_list (gimplify_stmt_list, &cond_expr_stmt_list);
initialize_original_copy_tables (); initialize_original_copy_tables ();
nloop = loop_version (loop, cond_expr, &condition_bb, nloop = loop_version (loop, cond_expr, &condition_bb,
prob, prob, REG_BR_PROB_BASE - prob, true); prob, prob, REG_BR_PROB_BASE - prob, true);
......
...@@ -1414,8 +1414,11 @@ new_loop_vec_info (struct loop *loop) ...@@ -1414,8 +1414,11 @@ new_loop_vec_info (struct loop *loop)
LOOP_VINFO_DATAREFS (res) = VEC_alloc (data_reference_p, heap, 10); LOOP_VINFO_DATAREFS (res) = VEC_alloc (data_reference_p, heap, 10);
LOOP_VINFO_DDRS (res) = VEC_alloc (ddr_p, heap, 10 * 10); LOOP_VINFO_DDRS (res) = VEC_alloc (ddr_p, heap, 10 * 10);
LOOP_VINFO_UNALIGNED_DR (res) = NULL; LOOP_VINFO_UNALIGNED_DR (res) = NULL;
LOOP_VINFO_MAY_MISALIGN_STMTS (res) LOOP_VINFO_MAY_MISALIGN_STMTS (res) =
= VEC_alloc (tree, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_CHECKS)); VEC_alloc (tree, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS));
LOOP_VINFO_MAY_ALIAS_DDRS (res) =
VEC_alloc (ddr_p, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS));
return res; return res;
} }
...@@ -1495,6 +1498,7 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo) ...@@ -1495,6 +1498,7 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo)
free_data_refs (LOOP_VINFO_DATAREFS (loop_vinfo)); free_data_refs (LOOP_VINFO_DATAREFS (loop_vinfo));
free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo)); free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo));
VEC_free (tree, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)); VEC_free (tree, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo));
VEC_free (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo));
free (loop_vinfo); free (loop_vinfo);
loop->aux = NULL; loop->aux = NULL;
......
...@@ -133,6 +133,10 @@ typedef struct _loop_vec_info { ...@@ -133,6 +133,10 @@ typedef struct _loop_vec_info {
/* All data dependences in the loop. */ /* All data dependences in the loop. */
VEC (ddr_p, heap) *ddrs; VEC (ddr_p, heap) *ddrs;
/* Data Dependence Relations defining address ranges that are candidates
for a run-time aliasing check. */
VEC (ddr_p, heap) *may_alias_ddrs;
/* Statements in the loop that have data references that are candidates for a /* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */ runtime (loop versioning) misalignment check. */
VEC(tree,heap) *may_misalign_stmts; VEC(tree,heap) *may_misalign_stmts;
...@@ -157,6 +161,7 @@ typedef struct _loop_vec_info { ...@@ -157,6 +161,7 @@ typedef struct _loop_vec_info {
#define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr #define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr
#define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts #define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts
#define LOOP_VINFO_LOC(L) (L)->loop_line_number #define LOOP_VINFO_LOC(L) (L)->loop_line_number
#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs
#define NITERS_KNOWN_P(n) \ #define NITERS_KNOWN_P(n) \
(host_integerp ((n),0) \ (host_integerp ((n),0) \
......
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