From: Ira Rosen Date: Tue, 12 Aug 2008 06:31:57 +0000 (+0000) Subject: tree-vectorizer.c: Depend on langhooks.h. X-Git-Tag: releases/gcc-4.4.0~3189 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad2dd72a0e83c5f5a4f395c1f818872b618550a5;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f1ce9eead9c..dfa628ef3026 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2008-08-12 Ira Rosen + + * 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 * i386/i386.c (override_options): Move initialisation from diff --git a/gcc/Makefile.in b/gcc/Makefile.in index d5ee8c57be71..8970d1bf6a3d 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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) \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 942a81ae798a..55f170602d6a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,25 @@ +2008-08-12 Ira Rosen + + * 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 PR rtl-optimization/36998 diff --git a/gcc/testsuite/gcc.dg/vect/vect-112.c b/gcc/testsuite/gcc.dg/vect/vect-112.c index 4b963eb26616..0bc185b361ef 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-112.c +++ b/gcc/testsuite/gcc.dg/vect/vect-112.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-35.c b/gcc/testsuite/gcc.dg/vect/vect-35.c index 569907c50b29..d75308f22fea 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-35.c +++ b/gcc/testsuite/gcc.dg/vect/vect-35.c @@ -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. diff --git a/gcc/testsuite/gcc.dg/vect/vect-72.c b/gcc/testsuite/gcc.dg/vect/vect-72.c index 95bc7caede07..67a197519521 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-72.c +++ b/gcc/testsuite/gcc.dg/vect/vect-72.c @@ -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++) diff --git a/gcc/testsuite/gcc.dg/vect/vect-multitypes-12.c b/gcc/testsuite/gcc.dg/vect/vect-multitypes-12.c new file mode 100644 index 000000000000..e4d5417547e1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-multitypes-12.c @@ -0,0 +1,44 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#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 +#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; isi) */ +__attribute__ ((noinline)) int +foo2(int len) { + int i; + + for (i=0; i +#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 +#include "tree-vect.h" +#include + +#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; iint->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" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c index 38f8a6955bad..d8aefdad1a62 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c @@ -44,6 +44,8 @@ int main (void) for (i=0; iint promotion), and then for each of the + created vectors we generate a promotion statement from the intermediate + type to the destination type. */ /* Generate first half of the widened result: */ - new_stmt = vect_gen_widened_results_half (code1, vectype_out, decl1, + new_stmt = vect_gen_widened_results_half (code1, wide_type, decl1, vec_oprnd0, vec_oprnd1, op_type, vec_dest, gsi, stmt); - if (j == 0) - STMT_VINFO_VEC_STMT (stmt_info) = new_stmt; + if (is_gimple_call (new_stmt)) + first_vector = gimple_call_lhs (new_stmt); else - STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; - prev_stmt_info = vinfo_for_stmt (new_stmt); + first_vector = gimple_assign_lhs (new_stmt); + + if (!double_op) + { + if (j == 0) + STMT_VINFO_VEC_STMT (stmt_info) = new_stmt; + else + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + } /* Generate second half of the widened result: */ - new_stmt = vect_gen_widened_results_half (code2, vectype_out, decl2, + new_stmt = vect_gen_widened_results_half (code2, wide_type, decl2, vec_oprnd0, vec_oprnd1, op_type, vec_dest, gsi, stmt); - STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; - prev_stmt_info = vinfo_for_stmt (new_stmt); + if (is_gimple_call (new_stmt)) + second_vector = gimple_call_lhs (new_stmt); + else + second_vector = gimple_assign_lhs (new_stmt); + if (!double_op) + { + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + } + else + { + /* FIRST_VECTOR and SECOND_VECTOR are the results of source type + to intermediate type promotion. Now we generate promotions + for both of them to the destination type (i.e., four + statements). */ + new_stmt = vect_gen_widened_results_half (code1, vectype_out, + decl1, first_vector, NULL_TREE, op_type, + double_vec_dest, gsi, stmt); + if (j == 0) + STMT_VINFO_VEC_STMT (stmt_info) = new_stmt; + else + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + + new_stmt = vect_gen_widened_results_half (code2, vectype_out, + decl2, first_vector, NULL_TREE, op_type, + double_vec_dest, gsi, stmt); + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + + new_stmt = vect_gen_widened_results_half (code1, vectype_out, + decl1, second_vector, NULL_TREE, op_type, + double_vec_dest, gsi, stmt); + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + + new_stmt = vect_gen_widened_results_half (code2, vectype_out, + decl2, second_vector, NULL_TREE, op_type, + double_vec_dest, gsi, stmt); + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + prev_stmt_info = vinfo_for_stmt (new_stmt); + } } *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 22e2e0c4cee2..78f82624c236 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -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; } diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index ea80a8d3d30f..cf7c5b123e9e 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -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);