From 0f3f4ffeafae6e4ae50bba50fae11ed82ab1b33b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 1 Mar 2017 09:34:48 +0100 Subject: [PATCH] re PR tree-optimization/79734 (ICE: verify_gimple failed) PR tree-optimization/79734 * tree-vect-generic.c (expand_vector_condition): Optimize AVX512 vector boolean VEC_COND_EXPRs into bitwise operations. Handle VEC_COND_EXPR where comparison has different inner width from type's inner width. * g++.dg/opt/pr79734.C: New test. From-SVN: r245801 --- gcc/ChangeLog | 8 +++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/opt/pr79734.C | 12 ++++++++ gcc/tree-vect-generic.c | 48 +++++++++++++++++++++++++++--- 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr79734.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 32dbf1cc635..12ee03af800 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-03-01 Jakub Jelinek + + PR tree-optimization/79734 + * tree-vect-generic.c (expand_vector_condition): Optimize + AVX512 vector boolean VEC_COND_EXPRs into bitwise operations. + Handle VEC_COND_EXPR where comparison has different inner width from + type's inner width. + 2017-02-28 Sandra Loosemore * doc/invoke.texi (ARC Options): Copy-edit to fix punctuation, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 483e9030905..369233795c5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-03-01 Jakub Jelinek + + PR tree-optimization/79734 + * g++.dg/opt/pr79734.C: New test. + 2017-02-28 Jakub Jelinek PR tree-optimization/79737 diff --git a/gcc/testsuite/g++.dg/opt/pr79734.C b/gcc/testsuite/g++.dg/opt/pr79734.C new file mode 100644 index 00000000000..ec9d4616c0d --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr79734.C @@ -0,0 +1,12 @@ +// PR tree-optimization/79734 +// { dg-do compile } +// { dg-options "-O2" } +// { dg-additional-options "-mavx512vl" { target i?86-*-* x86_64-*-* } } + +typedef float V __attribute__ ((vector_size (4 * sizeof (float)))); + +void +foo (V *a, V *b) +{ + *a = (*a < 1 && !(*b > 2)) ? *a + *b : 3; +} diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 22f2840b8bf..c1b3c24a0b4 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -865,6 +865,8 @@ expand_vector_condition (gimple_stmt_iterator *gsi) tree comp_inner_type = cond_type; tree width = TYPE_SIZE (inner_type); tree index = bitsize_int (0); + tree comp_width = width; + tree comp_index = index; int nunits = TYPE_VECTOR_SUBPARTS (type); int i; location_t loc = gimple_location (gsi_stmt (*gsi)); @@ -876,27 +878,60 @@ expand_vector_condition (gimple_stmt_iterator *gsi) a1 = TREE_OPERAND (a, 0); a2 = TREE_OPERAND (a, 1); comp_inner_type = TREE_TYPE (TREE_TYPE (a1)); + comp_width = TYPE_SIZE (comp_inner_type); } if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a))) return; + /* Handle vector boolean types with bitmasks. If there is a comparison + and we can expand the comparison into the vector boolean bitmask, + or otherwise if it is compatible with type, we can transform + vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5; + into + tmp_6 = x_2 < y_3; + tmp_7 = tmp_6 & vbfld_4; + tmp_8 = ~tmp_6; + tmp_9 = tmp_8 & vbfld_5; + vbfld_1 = tmp_7 | tmp_9; + Similarly for vbfld_10 instead of x_2 < y_3. */ + if (VECTOR_BOOLEAN_TYPE_P (type) + && SCALAR_INT_MODE_P (TYPE_MODE (type)) + && (GET_MODE_BITSIZE (TYPE_MODE (type)) + < (TYPE_VECTOR_SUBPARTS (type) + * GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))))) + && (a_is_comparison + ? useless_type_conversion_p (type, TREE_TYPE (a)) + : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a)))) + { + if (a_is_comparison) + a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2); + a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b); + a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a); + a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c); + a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2); + gimple_assign_set_rhs_from_tree (gsi, a); + update_stmt (gsi_stmt (*gsi)); + return; + } + /* TODO: try and find a smaller vector type. */ warning_at (loc, OPT_Wvector_operation_performance, "vector condition will be expanded piecewise"); vec_alloc (v, nunits); - for (i = 0; i < nunits; - i++, index = int_const_binop (PLUS_EXPR, index, width)) + for (i = 0; i < nunits; i++) { tree aa, result; tree bb = tree_vec_extract (gsi, inner_type, b, width, index); tree cc = tree_vec_extract (gsi, inner_type, c, width, index); if (a_is_comparison) { - tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index); - tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index); + tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, + comp_width, comp_index); + tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, + comp_width, comp_index); aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2); } else @@ -904,6 +939,11 @@ expand_vector_condition (gimple_stmt_iterator *gsi) result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc); constructor_elt ce = {NULL_TREE, result}; v->quick_push (ce); + index = int_const_binop (PLUS_EXPR, index, width); + if (width == comp_width) + comp_index = index; + else + comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width); } constr = build_constructor (type, v); -- 2.30.2