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)