Hi! The following testcase ICEs, because after the veclower pass which is the last point which lowers unsupported vector operations to supported ones (or scalars) match.pd simplifies a supported vector operation into unsupported one (vec << 1 >> 1 into vec & { ~1, ... }). Guarding each match.pd pattern that could do it manually would be IMHO a nightmare and it could affect hundreds of them, so this patch instead performs the verification and punting in the infrastructure (of course only in PROP_gimple_lvec state which is set after the vector lowering). The function attempts to match expand_vector_operations_1 (except I haven't added VEC_PERM_EXPR, VEC_COND_EXPR and COND_EXPR cases there, so those aren't checked and can be added later if we find it a problem).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2021-02-02 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/98287 * gimple-match.h (check_gimple_lvec): New declaration. * gimple-match-head.c (check_gimple_lvec): New function. (maybe_push_res_to_seq): Use it. * gimple-fold.c: Include tree-pass.h. (replace_stmt_with_simplification): Use it. * gcc.dg/pr98287.c: New test. --- gcc/gimple-match.h.jj 2021-01-04 10:25:38.456238093 +0100 +++ gcc/gimple-match.h 2021-02-01 13:19:30.393860766 +0100 @@ -335,6 +335,7 @@ extern tree (*mprts_hook) (gimple_match_ bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *, tree (*)(tree), tree (*)(tree)); +bool check_gimple_lvec (gimple_match_op *); tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *, tree res = NULL_TREE); void maybe_build_generic_op (gimple_match_op *); --- gcc/gimple-match-head.c.jj 2021-01-16 19:46:53.511672837 +0100 +++ gcc/gimple-match-head.c 2021-02-01 13:18:58.676225427 +0100 @@ -549,6 +549,109 @@ build_call_internal (internal_fn fn, gim res_op->op_or_null (4)); } +/* In PROP_gimple_lvec mode, perform extra checking if RES_OP and return + true if RES_OP is not appropriate - would require vector operations that + would need to be lowered before expansion. */ + +bool +check_gimple_lvec (gimple_match_op *res_op) +{ + enum tree_code code = res_op->code; + enum gimple_rhs_class rhs_class = get_gimple_rhs_class (code); + if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS) + return false; + + tree rhs1 = res_op->op_or_null (0); + tree rhs2 = res_op->op_or_null (1); + tree type = res_op->type; + + if (!VECTOR_TYPE_P (type) || !VECTOR_TYPE_P (TREE_TYPE (rhs1))) + return false; + + /* A scalar operation pretending to be a vector one. */ + if (VECTOR_BOOLEAN_TYPE_P (type) + && !VECTOR_MODE_P (TYPE_MODE (type)) + && TYPE_MODE (type) != BLKmode + && (TREE_CODE_CLASS (code) != tcc_comparison + || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)) + && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1))) + && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode))) + return false; + + machine_mode mode = TYPE_MODE (type); + optab op; + switch (code) + { + CASE_CONVERT: + case FLOAT_EXPR: + case FIX_TRUNC_EXPR: + case VIEW_CONVERT_EXPR: + return false; + + case VEC_UNPACK_FLOAT_HI_EXPR: + case VEC_UNPACK_FLOAT_LO_EXPR: + case VEC_PACK_FLOAT_EXPR: + return false; + + case WIDEN_SUM_EXPR: + case VEC_WIDEN_PLUS_HI_EXPR: + case VEC_WIDEN_PLUS_LO_EXPR: + case VEC_WIDEN_MINUS_HI_EXPR: + case VEC_WIDEN_MINUS_LO_EXPR: + case VEC_WIDEN_MULT_HI_EXPR: + case VEC_WIDEN_MULT_LO_EXPR: + case VEC_WIDEN_MULT_EVEN_EXPR: + case VEC_WIDEN_MULT_ODD_EXPR: + case VEC_UNPACK_HI_EXPR: + case VEC_UNPACK_LO_EXPR: + case VEC_UNPACK_FIX_TRUNC_HI_EXPR: + case VEC_UNPACK_FIX_TRUNC_LO_EXPR: + case VEC_PACK_TRUNC_EXPR: + case VEC_PACK_SAT_EXPR: + case VEC_PACK_FIX_TRUNC_EXPR: + case VEC_WIDEN_LSHIFT_HI_EXPR: + case VEC_WIDEN_LSHIFT_LO_EXPR: + return false; + + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: + if (!VECTOR_MODE_P (mode)) + return true; + if (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2))) + { + op = optab_for_tree_code (code, type, optab_scalar); + if (op && optab_handler (op, mode) != CODE_FOR_nothing) + return false; + } + op = optab_for_tree_code (code, type, optab_vector); + if (op && optab_handler (op, mode) != CODE_FOR_nothing) + return false; + return true; + + case MULT_HIGHPART_EXPR: + if (!VECTOR_MODE_P (mode) + || !can_mult_highpart_p (mode, TYPE_UNSIGNED (type))) + return true; + return false; + + default: + if (!VECTOR_MODE_P (mode)) + return true; + op = optab_for_tree_code (code, type, optab_default); + if (op == unknown_optab + && code == NEGATE_EXPR + && INTEGRAL_TYPE_P (TREE_TYPE (type))) + op = optab_for_tree_code (MINUS_EXPR, type, optab_default); + if (op && optab_handler (op, mode) != CODE_FOR_nothing) + return false; + return true; + } + + return false; +} + /* Push the exploded expression described by RES_OP as a statement to SEQ if necessary and return a gimple value denoting the value of the expression. If RES is not NULL then the result will be always RES @@ -597,6 +700,12 @@ maybe_push_res_to_seq (gimple_match_op * if (res_op->code.is_tree_code ()) { + if (VECTOR_TYPE_P (res_op->type) + && cfun + && (cfun->curr_properties & PROP_gimple_lvec) != 0 + && check_gimple_lvec (res_op)) + return NULL_TREE; + if (!res) { if (gimple_in_ssa_p (cfun)) --- gcc/gimple-fold.c.jj 2021-01-22 11:41:56.510499898 +0100 +++ gcc/gimple-fold.c 2021-02-01 13:22:11.992002840 +0100 @@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. #include "tree-vector-builder.h" #include "tree-ssa-strlen.h" #include "varasm.h" +#include "tree-pass.h" enum strlen_range_kind { /* Compute the exact constant string length. */ @@ -5678,6 +5679,11 @@ replace_stmt_with_simplification (gimple if (!inplace || gimple_num_ops (stmt) > get_gimple_rhs_num_ops (res_op->code)) { + if (VECTOR_TYPE_P (res_op->type) + && cfun + && (cfun->curr_properties & PROP_gimple_lvec) != 0 + && check_gimple_lvec (res_op)) + return false; maybe_build_generic_op (res_op); gimple_assign_set_rhs_with_ops (gsi, res_op->code, res_op->op_or_null (0), --- gcc/testsuite/gcc.dg/pr98287.c.jj 2021-02-01 13:32:22.735981006 +0100 +++ gcc/testsuite/gcc.dg/pr98287.c 2021-02-01 13:32:01.155229122 +0100 @@ -0,0 +1,19 @@ +/* PR tree-optimization/98287 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -Wno-psabi -w" } */ + +typedef unsigned long __attribute__((__vector_size__ (8))) V; +V v; + +static __attribute__((noinline, noclone)) V +bar (unsigned short s) +{ + return v >> s << s | v >> s >> 63; +} + +unsigned long +foo (void) +{ + V x = bar (1); + return x[0]; +} Jakub