Am Mon, Aug 05, 2024 at 01:00:31PM +0200 schrieb Richard Biener: > On Fri, Aug 2, 2024 at 2:43 PM Juergen Christ <jchr...@linux.ibm.com> wrote: > > > > Do not convert floats to ints in multiple step if trapping math is > > enabled. This might hide some inexact signals. > > > > Also use correct sign (the sign of the target integer type) for the > > intermediate steps. This only affects undefined behaviour (casting > > floats to unsigned datatype where the float is negative). > > > > gcc/ChangeLog: > > > > * tree-vect-stmts.cc (vectorizable_conversion): multi-step > > float to int conversion only with trapping math and correct > > sign. > > > > Signed-off-by: Juergen Christ <jchr...@linux.ibm.com> > > > > Bootstrapped and tested on x84 and s390. Ok for trunk? > > > > --- > > gcc/tree-vect-stmts.cc | 8 +++++--- > > 1 file changed, 5 insertions(+), 3 deletions(-) > > > > diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc > > index fdcda0d2abae..2ddd13383193 100644 > > --- a/gcc/tree-vect-stmts.cc > > +++ b/gcc/tree-vect-stmts.cc > > @@ -5448,7 +5448,8 @@ vectorizable_conversion (vec_info *vinfo, > > break; > > > > cvt_type > > - = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), > > 0); > > + = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), > > + TYPE_UNSIGNED (lhs_type)); > > But lhs_type should be a float type here, the idea that for a > FLOAT_EXPR (int -> float) > a signed integer type is the natural one to use - as it's 2x wider > than the original > RHS type it's signedness doesn't matter. Note all float types should be > !TYPE_UNSIGNED so this hunk is a no-op but still less clear on the intent IMO. > > Please drop it.
Will do. Sorry about that. > > cvt_type = get_same_sized_vectype (cvt_type, vectype_in); > > if (cvt_type == NULL_TREE) > > goto unsupported; > > @@ -5505,10 +5506,11 @@ vectorizable_conversion (vec_info *vinfo, > > if (GET_MODE_SIZE (lhs_mode) >= GET_MODE_SIZE (rhs_mode)) > > goto unsupported; > > > > - if (code == FIX_TRUNC_EXPR) > > + if (code == FIX_TRUNC_EXPR && !flag_trapping_math) > > { > > cvt_type > > - = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), > > 0); > > + = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), > > + TYPE_UNSIGNED (lhs_type)); > > Here it might be relevant for correctness - we have to choose between > sfix and ufix for the float -> [u]int conversion. > > Do you have a testcase? Shouldn't the exactness be independent of the > integer > type we convert to? I was looking at this little program which contains undefined behaviour: #include <stdio.h> __attribute__((noinline,noclone,noipa)) void vec_pack_ufix_trunc_v2df (double *in, unsigned int *out); void vec_pack_ufix_trunc_v2df (double *in, unsigned int *out) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; } int main() { double in[] = {-1,-2,-3,-4}; unsigned int out[4]; vec_pack_ufix_trunc_v2df (in, out); for (int i = 0; i < 4; ++i) printf("out[%d] = %u\n", i, out[i]); return 0; } On s390x, I get different results after vectorization: out[0] = 4294967295 out[1] = 4294967294 out[2] = 4294967293 out[3] = 4294967292 than without vectorization: out[0] = 0 out[1] = 0 out[2] = 0 out[3] = 0 Even if this is undefined behaviour, I think it would be nice to have consistent results here. Also, while I added an expander to circumvent this problem in a previous patch, reviewers requested to hide this behind trapping math. Thus, I looked into this. Seeing the result from the CI for aarch64, I guess there are some tests that actually expect this vectorization to always happen even though it might not be save w.r.t. trapping math. > > > cvt_type = get_same_sized_vectype (cvt_type, vectype_in); > > if (cvt_type == NULL_TREE) > > goto unsupported; > > -- > > 2.43.5 > >