https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97085
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- #1 0x00000000015c8944 in gimple_expand_vec_cond_expr (gsi=0x7fffffffda50, vec_cond_ssa_name_uses=0x7fffffffda20) at ../../src/trunk/gcc/gimple-isel.cc:133 133 gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode)) (gdb) p mode $2 = E_VNx8BImode (gdb) p cmp_op_mode $3 = E_VNx8HImode (gdb) p debug_gimple_stmt (stmt) mask__31.28_102 = VEC_COND_EXPR <mask__23.26_97, { 0, ... }, { -1, ... }>; So veclower got to see vect_cst__96 = { 5, ... }; vect_cst__98 = { 1, ... }; vect_cst__99 = { 0, ... }; ... mask__23.26_97 = vect__50.25_95 == vect_cst__96; vect_patt_61.27_100 = VEC_COND_EXPR <mask__23.26_97, vect_cst__98, vect_cst__99>; mask__31.28_102 = vect_patt_61.27_100 == vect_cst__101; and in VRP2 we fold this to mask__31.28_102 = VEC_COND_EXPR <mask__23.26_97, { 0, ... }, { -1, ... }>; feeding vect_patt_63.29_105 = VEC_COND_EXPR <mask__31.28_102, { 1, ... }, { 0, ... }>; so it seems to me we're missing to fold the mask__31.28_102 def to a mask negation (it's of type vector([8,8]) <signed-boolean:2> mask__31.28). At least we're not at all expecting to have a VEC_COND_EXPR where the comparison feeding the mask has different operand modes than the VEC_COND_EXPR result mode. But we don't really expect a VEC_COND_EXPR to have VECTOR_BOOLEAN_TYPE ... So we could either handle this specially and ISEL it to a compare or a mask inversion or avoid such folding. For example diff --git a/gcc/match.pd b/gcc/match.pd index 7d63bb973cb..ff19b1cbeb4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3465,22 +3465,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op (vec_cond:s @0 @1 @2)) (vec_cond @0 (op! @1) (op! @2)))) -/* Sink binary operation to branches, but only if we can fold it. */ +/* Sink binary operation to branches, but only if we can fold it. Avoid + VEC_COND_EXPRs with boolean vector result. */ (for op (tcc_comparison plus minus mult bit_and bit_ior bit_xor rdiv trunc_div ceil_div floor_div round_div trunc_mod ceil_mod floor_mod round_mod min max) -/* (c ? a : b) op (c ? d : e) --> c ? (a op d) : (b op e) */ - (simplify - (op (vec_cond:s @0 @1 @2) (vec_cond:s @0 @3 @4)) - (vec_cond @0 (op! @1 @3) (op! @2 @4))) + (if (!VECTOR_BOOLEAN_TYPE_P (type)) + /* (c ? a : b) op (c ? d : e) --> c ? (a op d) : (b op e) */ + (simplify + (op (vec_cond:s @0 @1 @2) (vec_cond:s @0 @3 @4)) + (vec_cond @0 (op! @1 @3) (op! @2 @4))) -/* (c ? a : b) op d --> c ? (a op d) : (b op d) */ - (simplify - (op (vec_cond:s @0 @1 @2) @3) - (vec_cond @0 (op! @1 @3) (op! @2 @3))) - (simplify - (op @3 (vec_cond:s @0 @1 @2)) - (vec_cond @0 (op! @3 @1) (op! @3 @2)))) + /* (c ? a : b) op d --> c ? (a op d) : (b op d) */ + (simplify + (op (vec_cond:s @0 @1 @2) @3) + (vec_cond @0 (op! @1 @3) (op! @2 @3))) + (simplify + (op @3 (vec_cond:s @0 @1 @2)) + (vec_cond @0 (op! @3 @1) (op! @3 @2))))) #endif fixes this particular testcase (but there are more patterns producing vec_cond exprs). We'd also want to add verification if we do not want VECTOR_BOOLEAN_TYPE_P VEC_COND_EXPR.