On Thu, Aug 5, 2021 at 8:33 PM liuhongt via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > Hi: > --- > OK, I think sth is amiss here upthread. insv/extv do look like they > are designed > to work on integer modes (but docs do not say anything about this here). > In fact the caller of extract_bit_field_using_extv is named > extract_integral_bit_field. Of course nothing seems to check what kind of > modes we're dealing with, but we're for example happily doing > expand_shift in 'mode'. In the extract_integral_bit_field call 'mode' is > some integer mode and op0 is HFmode? From the above I get it's > the other way around? In that case we should wrap the > call to extract_integral_bit_field, extracting in an integer mode with the > same size as 'mode' and then converting the result as (subreg:HF (reg:HI > ...)).
This seems related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93235 . I wonder why the fix for that did not help here. Thanks, Andrew Pinski > --- > This is a separate patch as a follow up of upper comments. > > gcc/ChangeLog: > > * expmed.c (extract_bit_field_1): Wrap the call to > extract_integral_bit_field, extracting in an integer mode with > the same size as 'tmode' and then converting the result > as (subreg:tmode (reg:imode)). > > gcc/testsuite/ChangeLog: > * gcc.target/i386/float16-5.c: New test. > --- > gcc/expmed.c | 19 +++++++++++++++++++ > gcc/testsuite/gcc.target/i386/float16-5.c | 12 ++++++++++++ > 2 files changed, 31 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/i386/float16-5.c > > diff --git a/gcc/expmed.c b/gcc/expmed.c > index 3143f38e057..72790693ef0 100644 > --- a/gcc/expmed.c > +++ b/gcc/expmed.c > @@ -1850,6 +1850,25 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, > poly_uint64 bitnum, > op0_mode = opt_scalar_int_mode (); > } > > + /* Make sure we are playing with integral modes. Pun with subregs > + if we aren't. When tmode is HFmode, op0 is SImode, there will be ICE > + in extract_integral_bit_field. */ > + if (int_mode_for_mode (tmode).exists (&imode) > + && imode != tmode > + && imode != GET_MODE (op0)) > + { > + rtx ret = extract_integral_bit_field (op0, op0_mode, > + bitsize.to_constant (), > + bitnum.to_constant (), unsignedp, > + NULL, imode, imode, > + reverse, fallback_p); > + gcc_assert (ret); > + > + if (!REG_P (ret)) > + ret = force_reg (imode, ret); > + return gen_lowpart_SUBREG (tmode, ret); > + } > + > /* It's possible we'll need to handle other cases here for > polynomial bitnum and bitsize. */ > > diff --git a/gcc/testsuite/gcc.target/i386/float16-5.c > b/gcc/testsuite/gcc.target/i386/float16-5.c > new file mode 100644 > index 00000000000..ebc0af1490b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/float16-5.c > @@ -0,0 +1,12 @@ > +/* { dg-do compile } */ > +/* { dg-options "-msse2 -O2" } */ > +_Float16 > +foo (int a) > +{ > + union { > + int a; > + _Float16 b; > + }c; > + c.a = a; > + return c.b; > +} > -- > 2.27.0 >