https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97085
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Marc Glisse from comment #4) > I would be happy with a revert of that patch, if the ARM backend gets fixed, > but indeed a missed optimization should not cause an ICE. Not sure what the ARM backend issue is. > (In reply to Richard Biener from comment #2) > > 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. > > Ah, I see why that might cause trouble, although I think supporting this > makes sense, when the modes have the same size or when we use AVX512-style > bool vectors. Well, VEC_COND_EXPR (as some other VEC_ tree codes) are special in that we are (try to...) be careful to only synthesize ones supported "directly" by the target. For the mask vectors (VECTOR_BOOLEAN_TYPE_P, in the AVX512/SVE case) I don't think the targets support ?: natively but they have bitwise instructions for this case. That means we could 'simply' expand mask x ? y : z as (y & x) | (z & ~x) I guess [requires x and y,z to be of the same type of course]. I wondered whether we ever need to translate between, say, vector<bool:1> and vector<bool:2> where lowering ?: this way would require '[un]packing' one of the vectors. > > We'd also want to add verification if we do not want > > VECTOR_BOOLEAN_TYPE_P VEC_COND_EXPR. > > I understand that a VEC_COND_EXPR which outputs a vector of bool (à la > AVX512) is a different thing from a VEC_COND_EXPR which outputs a "true" > vector, but VEC_COND_EXPR still looks like the right tree code to represent > both. True, unless you go to bitwise ops. For scalar flag ? bool_a : bool_b ?: isn't the natural representation either - at least I'm not aware of any pattern transforming (a & b) | (c & ~b) to b ? a : c for precision one integer types ;) > (In reply to Richard Biener from comment #3) > > +/* Canonicalize mask ? { 0, ... } : { -1, ...} to ~mask if the mask > > + types are compatible. */ > > +(simplify > > + (vec_cond @0 VECTOR_CST@1 VECTOR_CST@2) > > + (if (VECTOR_BOOLEAN_TYPE_P (type) > > + && types_match (type, TREE_TYPE (@0))) > > + (if (integer_zerop (@1) && integer_all_onesp (@2)) > > + (bit_not @0) > > + (if (integer_all_onesp (@1) && integer_zerop (@2)) > > + @0)))) > > Is the test VECTOR_BOOLEAN_TYPE_P necessary? Hmm, since the first operand of a VEC_COND_EXPR has to be VECTOR_BOOLEAN_TYPE_P the types_match may be enough indeed. Note types_match will treat vector<bool:8> and vector<char> as compatible but only the first one will be a VECTOR_BOOLEAN_TYPE_P. We already have half of this in fold-const btw: /* Convert A ? 1 : 0 to simply A. */ if ((code == VEC_COND_EXPR ? integer_all_onesp (op1) : (integer_onep (op1) && !VECTOR_TYPE_P (type))) && integer_zerop (op2) /* If we try to convert OP0 to our type, the call to fold will try to move the conversion inside a COND, which will recurse. In that case, the COND_EXPR is probably the best choice, so leave it alone. */ && type == TREE_TYPE (arg0)) return pedantic_non_lvalue_loc (loc, arg0); the other half is guarded with !VECTOR_TYPE_P /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR over COND_EXPR in cases such as floating point comparisons. */ if (integer_zerop (op1) && code == COND_EXPR && integer_onep (op2) && !VECTOR_TYPE_P (type) && truth_value_p (TREE_CODE (arg0))) return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, invert_truthvalue_loc (loc, arg0))); I'm going to test the original proposed simplification to fix the ICE for now. > (sorry, I may not be very reactive these days)