Commit ad2dd72a by Ira Rosen Committed by Ira Rosen

tree-vectorizer.c: Depend on langhooks.h.

	* tree-vectorizer.c: Depend on langhooks.h.
	(supportable_widening_operation): Add two arguments. Support double
	type conversions.
	(supportable_narrowing_operation): Likewise.
	* tree-vectorizer.h (supportable_widening_operation): Add two
	arguments.
	(supportable_narrowing_operation): Likewise.
	* tree-vect-patterns.c (vect_recog_widen_mult_pattern) : Call
	supportable_widening_operation with correct arguments.
	* tree-vect-transform.c (vectorizable_conversion): Likewise.
	(vectorizable_type_demotion): Support double type conversions.
	(vectorizable_type_promotion): Likewise.
	* Makefile.in (tree-vectorizer.o): Depend on langhooks.h.

From-SVN: r138988
parent 62641193
2008-08-12 Ira Rosen <irar@il.ibm.com>
* tree-vectorizer.c: Depend on langhooks.h.
(supportable_widening_operation): Add two arguments. Support double
type conversions.
(supportable_narrowing_operation): Likewise.
* tree-vectorizer.h (supportable_widening_operation): Add two
arguments.
(supportable_narrowing_operation): Likewise.
* tree-vect-patterns.c (vect_recog_widen_mult_pattern) : Call
supportable_widening_operation with correct arguments.
* tree-vect-transform.c (vectorizable_conversion): Likewise.
(vectorizable_type_demotion): Support double type conversions.
(vectorizable_type_promotion): Likewise.
* Makefile.in (tree-vectorizer.o): Depend on langhooks.h.
2008-08-11 Michael Matz <matz@suse.de>
* i386/i386.c (override_options): Move initialisation from
......
......@@ -2344,7 +2344,7 @@ tree-vectorizer.o: tree-vectorizer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
tree-pass.h $(EXPR_H) $(RECOG_H) tree-vectorizer.h $(TREE_DATA_REF_H) $(SCEV_H) \
$(INPUT_H) $(TARGET_H) $(CFGLAYOUT_H) $(TOPLEV_H) tree-chrec.h
$(INPUT_H) $(TARGET_H) $(CFGLAYOUT_H) $(TOPLEV_H) tree-chrec.h langhooks.h
tree-loop-linear.o: tree-loop-linear.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
......
2008-08-12 Ira Rosen <irar@il.ibm.com>
* gcc.dg/vect/vect-multitypes-12.c: New.
* gcc.dg/vect/vect-multitypes-13.c, gcc.dg/vect/vect-multitypes-14.c,
gcc.dg/vect/vect-multitypes-15.c : Likewise.
* gcc.dg/vect/vect-reduc-dot-u8a.c: Avoid vectorization of the
init loop.
* gcc.dg/vect/vect-72.c, gcc.dg/vect/vect-strided-store-a-u8-i2.c:
Likewise.
* gcc.dg/vect/vect-reduc-dot-u8b.c: Avoid vectorization of the init
loop.
Should be vectorizable on targets that support vector unpack.
* gcc.dg/vect/vect-widen-mult-u8.c,
gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c,.
gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c: Likewise.
* gcc.dg/vect/vect-35.c: Should be vectorizable on targets that
support vector pack. Avoid vectorization of the init loop.
* gcc.dg/vect/vect-reduc-pattern-1b.c: Should be vectorizable on
targets that support vector unpack.
* gcc.dg/vect/vect-reduc-pattern-2b.c,
gcc.dg/vect/vect-reduc-dot-s8c.c, gcc.dg/vect/vect-112.c: Likewise.
2008-08-11 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/36998
......
......@@ -32,7 +32,7 @@ int main (void)
return main1 ();
}
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_unpack } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -18,6 +18,8 @@ int main1 ()
for (i = 0; i < N; i++)
{
s.b[i] = 3*i;
if (i%3 == 0)
s.b[i] = 3*i;
}
/* Dependence analysis fails cause s.a and s.b may overlap.
......
......@@ -18,6 +18,9 @@ int main1 ()
for (i=0; i < N+1; i++)
{
ib[i] = i;
/* Avoid vectorization. */
if (i%3 == 0)
ib[i] = 5;
}
for (i = 1; i < N+1; i++)
......
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 64
char x[N] __attribute__ ((__aligned__(16)));
__attribute__ ((noinline)) int
foo (int len, int *z) {
int i;
for (i=0; i<len; i++) {
z[i] = x[i];
}
}
int main (void)
{
char i;
int z[N+4];
check_vect ();
for (i=0; i<N; i++) {
x[i] = i;
}
foo (N,z+2);
for (i=0; i<N; i++) {
if (z[i+2] != x[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_unpack } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! vect_unpack } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 64
unsigned char uX[N] __attribute__ ((__aligned__(16)));
unsigned int uresult[N];
signed char X[N] __attribute__ ((__aligned__(16)));
int result[N];
/* Unsigned type promotion (qi->si) */
__attribute__ ((noinline)) int
foo1(int len) {
int i;
for (i=0; i<len; i++) {
uresult[i] = (unsigned int)uX[i];
}
}
/* Signed type promotion (qi->si) */
__attribute__ ((noinline)) int
foo2(int len) {
int i;
for (i=0; i<len; i++) {
result[i] = (int)X[i];
}
}
int main (void)
{
int i;
check_vect ();
for (i=0; i<N; i++) {
X[i] = 16-i;
uX[i] = 16-i;
}
foo1 (N);
for (i=0; i<N; i++) {
if (uresult[i] != (unsigned int)uX[i])
abort ();
}
foo2 (N);
for (i=0; i<N; i++) {
if (result[i] != (int)X[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_unpack } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#define N 64
unsigned char uX[N] __attribute__ ((__aligned__(16)));
unsigned char uresultX[N];
unsigned int uY[N] __attribute__ ((__aligned__(16)));
unsigned char uresultY[N];
/* Unsigned type demotion (si->qi) */
__attribute__ ((noinline)) int
foo1(int len) {
int i;
for (i=0; i<len; i++) {
uresultX[i] = uX[i];
uresultY[i] = (unsigned char)uY[i];
}
}
int main (void)
{
int i;
check_vect ();
for (i=0; i<N; i++) {
uX[i] = 16-i;
uY[i] = 16-i;
}
foo1 (N);
for (i=0; i<N; i++) {
if (uresultX[i] != uX[i])
abort ();
if (uresultY[i] != (unsigned char)uY[i])
abort ();
}
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_pack_trunc } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include <stdarg.h>
#include "tree-vect.h"
#include <stdio.h>
#define N 64
#define DOT1 43680
#define DOT2 -20832
signed char X[N] __attribute__ ((__aligned__(16)));
signed char Y[N] __attribute__ ((__aligned__(16)));
unsigned char CX[N] __attribute__ ((__aligned__(16)));
__attribute__ ((noinline)) void
foo1(int len) {
int i;
int result1 = 0;
for (i=0; i<len; i++) {
result1 += (X[i] * Y[i]);
CX[i] = 5;
}
if (result1 != DOT1)
abort ();
}
int main (void)
{
int i, dot1, dot2;
check_vect ();
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
CX[i] = i;
}
foo1 (N);
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_sdot_hi || vect_uncpack } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -11,8 +11,7 @@ signed char X[N] __attribute__ ((__aligned__(16)));
signed char Y[N] __attribute__ ((__aligned__(16)));
/* char->int->int dot product.
Not detected as a dot-product pattern.
Currently fails to be vectorized due to presence of type conversions. */
Not detected as a dot-product pattern. */
__attribute__ ((noinline)) int
foo3(int len) {
int i;
......@@ -42,6 +41,5 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_unpack } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -44,6 +44,8 @@ int main (void)
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
if (i%5 == 0)
X[i] = i;
}
dot = foo (N);
......
......@@ -39,6 +39,9 @@ int main (void)
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
/* Avoid vectorization. */
if (i%100 == 0)
X[i] = i;
}
dot = foo (N);
......@@ -54,7 +57,7 @@ int main (void)
targets that support accumulation into int (powerpc, ia64) we'd have:
dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_udot_qi || vect_widen_mult_qi_to_hi } }
*/
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {target vect_widen_mult_qi_to_hi} } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -35,6 +35,6 @@ main (void)
}
/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_qi_to_si } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { ! vect_widen_sum_qi_to_si } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_sum_qi_to_si || vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { { ! vect_widen_sum_qi_to_si } && { ! vect_unpack } } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -35,6 +35,6 @@ main (void)
}
/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_qi_to_si } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { ! vect_widen_sum_qi_to_si } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_sum_qi_to_si && vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { { ! vect_widen_sum_qi_to_si } && { ! vect_unpack } } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -24,8 +24,8 @@ main1 ()
{
a[i] = i;
b[i] = i * 2;
if (a[i] == 178)
abort();
if (i%3 == 0)
a[i] = 10;
}
for (i = 0; i < N; i++)
......
......@@ -28,6 +28,8 @@ int main (void)
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
if (i%4 == 0)
X[i] = 5;
}
foo1 (N);
......@@ -40,6 +42,6 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_mult_qi_to_hi } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -40,6 +40,8 @@ int main (void)
for (i=0; i<N; i++) {
X[i] = i;
Y[i] = 64-i;
if (i%5 == 0)
X[i] = i;
}
dot = foo (N);
......@@ -57,6 +59,6 @@ int main (void)
dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_sdot_qi } }
*/
/* In the meantime expect: */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_mult_qi_to_hi } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
......@@ -374,6 +374,7 @@ vect_recog_widen_mult_pattern (gimple last_stmt,
tree dummy;
tree var;
enum tree_code dummy_code;
bool dummy_bool;
if (!is_gimple_assign (last_stmt))
return NULL;
......@@ -414,7 +415,7 @@ vect_recog_widen_mult_pattern (gimple last_stmt,
if (!vectype
|| !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, vectype,
&dummy, &dummy, &dummy_code,
&dummy_code))
&dummy_code, &dummy_bool, &dummy))
return NULL;
*type_in = vectype;
......
......@@ -147,6 +147,7 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h"
#include "tree-vectorizer.h"
#include "tree-pass.h"
#include "langhooks.h"
/*************************************************************************
General Vectorization Utilities
......@@ -2136,12 +2137,17 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, gimple *def_stmt,
vectorizing the operation, if available.
- DECL1 and DECL2 are decls of target builtin functions to be used
when vectorizing the operation, if available. In this case,
CODE1 and CODE2 are CALL_EXPR. */
CODE1 and CODE2 are CALL_EXPR.
- DOUBLE_OP determines if the operation is a double cast, like
char->short->int
- INTERM_TYPE is the intermediate type required to perform the
widening operation (short in the above example) */
bool
supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
tree *decl1, tree *decl2,
enum tree_code *code1, enum tree_code *code2)
enum tree_code *code1, enum tree_code *code2,
bool *double_op, tree *interm_type)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info);
......@@ -2154,6 +2160,8 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
tree wide_vectype = get_vectype_for_scalar_type (type);
enum tree_code c1, c2;
*double_op = false;
/* The result of a vectorized widening operation usually requires two vectors
(because the widened results do not fit int one vector). The generated
vector results would normally be expected to be generated in the same
......@@ -2264,12 +2272,57 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
vec_mode = TYPE_MODE (vectype);
if ((icode1 = optab_handler (optab1, vec_mode)->insn_code) == CODE_FOR_nothing
|| insn_data[icode1].operand[0].mode != TYPE_MODE (wide_vectype)
|| (icode2 = optab_handler (optab2, vec_mode)->insn_code)
== CODE_FOR_nothing
|| insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
== CODE_FOR_nothing)
return false;
/* Check if it's a double cast, like char->int. In such case the intermediate
type is short, and we check that char->short->int operaion is supported by
the target. */
if (insn_data[icode1].operand[0].mode != TYPE_MODE (wide_vectype)
|| insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
{
if (code == NOP_EXPR)
{
enum machine_mode intermediate_mode =
insn_data[icode1].operand[0].mode;
tree intermediate_type =
lang_hooks.types.type_for_mode (intermediate_mode,
TYPE_UNSIGNED (vectype));
optab optab3 = optab_for_tree_code (c1, intermediate_type,
optab_default);
optab optab4 = optab_for_tree_code (c2, intermediate_type,
optab_default);
if (!optab3 || !optab4)
return false;
if ((icode1 = optab1->handlers[(int) vec_mode].insn_code)
== CODE_FOR_nothing
|| insn_data[icode1].operand[0].mode != intermediate_mode
|| (icode2 = optab2->handlers[(int) vec_mode].insn_code)
== CODE_FOR_nothing
|| insn_data[icode2].operand[0].mode != intermediate_mode
|| (icode1 = optab3->handlers[(int) intermediate_mode].insn_code)
== CODE_FOR_nothing
|| insn_data[icode1].operand[0].mode != TYPE_MODE (wide_vectype)
|| (icode2 = optab4->handlers[(int) intermediate_mode].insn_code)
== CODE_FOR_nothing
|| insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
return false;
else
{
*double_op = true;
*interm_type = intermediate_type;
*code1 = c1;
*code2 = c2;
return true;
}
}
return false;
}
*code1 = c1;
*code2 = c2;
return true;
......@@ -2288,16 +2341,21 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
Output:
- CODE1 is the code of a vector operation to be used when
vectorizing the operation, if available. */
vectorizing the operation, if available.
- DOUBLE_OP determines if the operation is a double cast, like
int->short->char
- INTERMIDIATE_TYPE is the intermediate type required to perform the
widening operation (short in the above example) */
bool
supportable_narrowing_operation (enum tree_code code,
const_gimple stmt, const_tree vectype,
enum tree_code *code1)
enum tree_code *code1, bool *double_op,
tree *intermediate_type)
{
enum machine_mode vec_mode;
enum insn_code icode1;
optab optab1;
optab optab1, interm_optab;
tree type = gimple_expr_type (stmt);
tree narrow_vectype = get_vectype_for_scalar_type (type);
enum tree_code c1;
......@@ -2331,10 +2389,30 @@ supportable_narrowing_operation (enum tree_code code,
return false;
vec_mode = TYPE_MODE (vectype);
if ((icode1 = optab_handler (optab1, vec_mode)->insn_code) == CODE_FOR_nothing
|| insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
if ((icode1 = optab_handler (optab1, vec_mode)->insn_code)
== CODE_FOR_nothing)
return false;
/* In case of NUNITS_IN == NUNITS_OUT/4 check that the it is possible to
perform the operation using an intermediate type of NUNITS_OUT/2. */
if (insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
{
enum machine_mode intermediate_mode = insn_data[icode1].operand[0].mode;
*intermediate_type = lang_hooks.types.type_for_mode (intermediate_mode,
TYPE_UNSIGNED (vectype));
interm_optab = optab_for_tree_code (VEC_PACK_TRUNC_EXPR,
*intermediate_type, optab_default);
if (!interm_optab)
return false;
if ((icode1 = interm_optab->handlers[(int) intermediate_mode].insn_code)
== CODE_FOR_nothing
|| insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
return false;
*double_op = true;
}
*code1 = c1;
return true;
}
......
......@@ -671,9 +671,9 @@ extern enum dr_alignment_support vect_supportable_dr_alignment
(struct data_reference *);
extern bool reduction_code_for_scalar_code (enum tree_code, enum tree_code *);
extern bool supportable_widening_operation (enum tree_code, gimple, tree,
tree *, tree *, enum tree_code *, enum tree_code *);
tree *, tree *, enum tree_code *, enum tree_code *, bool *, tree *);
extern bool supportable_narrowing_operation (enum tree_code, const_gimple,
const_tree, enum tree_code *);
const_tree, enum tree_code *, bool *, tree *);
/* Creation and deletion of loop and stmt info structs. */
extern loop_vec_info new_loop_vec_info (struct loop *loop);
......
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