From 01216d27de7de69ce1f09697e5f61ab414113824 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 9 Jan 2017 12:44:52 +0100 Subject: [PATCH] re PR tree-optimization/78938 (ICE in expand_vec_cond_expr, at optabs.c:5636 w/ -mavx512bw -ftree-loop-vectorize -O1) PR tree-optimization/78938 * tree-vect-stmts.c (vectorizable_condition): For non-masked COND_EXPR where comp_vectype is VECTOR_BOOLEAN_TYPE_P, use BIT_{NOT,XOR,AND,IOR}_EXPR on the comparison operands instead of {EQ,NE,GE,GT,LE,LT}_EXPR directly inside of VEC_COND_EXPR. Formatting fixes. * gcc.dg/vect/pr78938.c: New test. From-SVN: r244223 --- gcc/ChangeLog | 9 ++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/vect/pr78938.c | 18 ++++ gcc/tree-vect-stmts.c | 131 ++++++++++++++++++++++++---- 4 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr78938.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 540c2bdf75f..860d7c3fa05 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-01-09 Jakub Jelinek + + PR tree-optimization/78938 + * tree-vect-stmts.c (vectorizable_condition): For non-masked COND_EXPR + where comp_vectype is VECTOR_BOOLEAN_TYPE_P, use + BIT_{NOT,XOR,AND,IOR}_EXPR on the comparison operands instead of + {EQ,NE,GE,GT,LE,LT}_EXPR directly inside of VEC_COND_EXPR. Formatting + fixes. + 2017-01-09 Kyrylo Tkachov * tree-ssa-address.c (gen_addr_rtx): Don't handle index if it diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 14e24a8c3c1..854121ec921 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-01-09 Jakub Jelinek + + PR tree-optimization/78938 + * gcc.dg/vect/pr78938.c: New test. + 2017-01-09 Kyrylo Tkachov * gcc.dg/20161219.c: New test. diff --git a/gcc/testsuite/gcc.dg/vect/pr78938.c b/gcc/testsuite/gcc.dg/vect/pr78938.c new file mode 100644 index 00000000000..095e674adf5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr78938.c @@ -0,0 +1,18 @@ +/* PR tree-optimization/78938 */ +/* { dg-do compile } */ +/* { dg-additional-options "-mavx512bw" { target i?86-*-* x86_64-*-* } } */ + +short int v; + +int +foo (char x, int *b) +{ + int a = 1; + for (; x < 1; x++) + { + int c = *b != v; + int d = x != 0; + a = c == d ? 2 : 0; + } + return a; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 2ba7f64d222..e8b454b7eff 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -7731,7 +7731,8 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, { tree scalar_dest = NULL_TREE; tree vec_dest = NULL_TREE; - tree cond_expr, then_clause, else_clause; + tree cond_expr, cond_expr0 = NULL_TREE, cond_expr1 = NULL_TREE; + tree then_clause, else_clause; stmt_vec_info stmt_info = vinfo_for_stmt (stmt); tree comp_vectype = NULL_TREE; tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE; @@ -7741,7 +7742,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); enum vect_def_type dt, dts[4]; int ncopies; - enum tree_code code; + enum tree_code code, cond_code, bitop1 = NOP_EXPR, bitop2 = NOP_EXPR; stmt_vec_info prev_stmt_info = NULL; int i, j; bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); @@ -7825,11 +7826,76 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, if (vec_cmp_type == NULL_TREE) return false; + cond_code = TREE_CODE (cond_expr); + if (!masked) + { + cond_expr0 = TREE_OPERAND (cond_expr, 0); + cond_expr1 = TREE_OPERAND (cond_expr, 1); + } + + if (!masked && VECTOR_BOOLEAN_TYPE_P (comp_vectype)) + { + /* Boolean values may have another representation in vectors + and therefore we prefer bit operations over comparison for + them (which also works for scalar masks). We store opcodes + to use in bitop1 and bitop2. Statement is vectorized as + BITOP2 (rhs1 BITOP1 rhs2) or rhs1 BITOP2 (BITOP1 rhs2) + depending on bitop1 and bitop2 arity. */ + switch (cond_code) + { + case GT_EXPR: + bitop1 = BIT_NOT_EXPR; + bitop2 = BIT_AND_EXPR; + break; + case GE_EXPR: + bitop1 = BIT_NOT_EXPR; + bitop2 = BIT_IOR_EXPR; + break; + case LT_EXPR: + bitop1 = BIT_NOT_EXPR; + bitop2 = BIT_AND_EXPR; + std::swap (cond_expr0, cond_expr1); + break; + case LE_EXPR: + bitop1 = BIT_NOT_EXPR; + bitop2 = BIT_IOR_EXPR; + std::swap (cond_expr0, cond_expr1); + break; + case NE_EXPR: + bitop1 = BIT_XOR_EXPR; + break; + case EQ_EXPR: + bitop1 = BIT_XOR_EXPR; + bitop2 = BIT_NOT_EXPR; + break; + default: + return false; + } + cond_code = SSA_NAME; + } + if (!vec_stmt) { STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type; + if (bitop1 != NOP_EXPR) + { + machine_mode mode = TYPE_MODE (comp_vectype); + optab optab; + + optab = optab_for_tree_code (bitop1, comp_vectype, optab_default); + if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing) + return false; + + if (bitop2 != NOP_EXPR) + { + optab = optab_for_tree_code (bitop2, comp_vectype, + optab_default); + if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing) + return false; + } + } return expand_vec_cond_expr_p (vectype, comp_vectype, - TREE_CODE (cond_expr)); + cond_code); } /* Transform. */ @@ -7858,11 +7924,11 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, auto_vec, 4> vec_defs; if (masked) - ops.safe_push (cond_expr); + ops.safe_push (cond_expr); else { - ops.safe_push (TREE_OPERAND (cond_expr, 0)); - ops.safe_push (TREE_OPERAND (cond_expr, 1)); + ops.safe_push (cond_expr0); + ops.safe_push (cond_expr1); } ops.safe_push (then_clause); ops.safe_push (else_clause); @@ -7886,17 +7952,15 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, } else { - vec_cond_lhs = - vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), - stmt, comp_vectype); - vect_is_simple_use (TREE_OPERAND (cond_expr, 0), - loop_vinfo, >emp, &dts[0]); - - vec_cond_rhs = - vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), - stmt, comp_vectype); - vect_is_simple_use (TREE_OPERAND (cond_expr, 1), - loop_vinfo, >emp, &dts[1]); + vec_cond_lhs + = vect_get_vec_def_for_operand (cond_expr0, + stmt, comp_vectype); + vect_is_simple_use (cond_expr0, loop_vinfo, >emp, &dts[0]); + + vec_cond_rhs + = vect_get_vec_def_for_operand (cond_expr1, + stmt, comp_vectype); + vect_is_simple_use (cond_expr1, loop_vinfo, >emp, &dts[1]); } if (reduc_index == 1) vec_then_clause = reduc_def; @@ -7953,8 +8017,37 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi, else { vec_cond_rhs = vec_oprnds1[i]; - vec_compare = build2 (TREE_CODE (cond_expr), vec_cmp_type, - vec_cond_lhs, vec_cond_rhs); + if (bitop1 == NOP_EXPR) + vec_compare = build2 (cond_code, vec_cmp_type, + vec_cond_lhs, vec_cond_rhs); + else + { + new_temp = make_ssa_name (vec_cmp_type); + if (bitop1 == BIT_NOT_EXPR) + new_stmt = gimple_build_assign (new_temp, bitop1, + vec_cond_rhs); + else + new_stmt + = gimple_build_assign (new_temp, bitop1, vec_cond_lhs, + vec_cond_rhs); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + if (bitop2 == NOP_EXPR) + vec_compare = new_temp; + else if (bitop2 == BIT_NOT_EXPR) + { + /* Instead of doing ~x ? y : z do x ? z : y. */ + vec_compare = new_temp; + std::swap (vec_then_clause, vec_else_clause); + } + else + { + vec_compare = make_ssa_name (vec_cmp_type); + new_stmt + = gimple_build_assign (vec_compare, bitop2, + vec_cond_lhs, new_temp); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + } + } } new_temp = make_ssa_name (vec_dest); new_stmt = gimple_build_assign (new_temp, VEC_COND_EXPR, -- 2.30.2