On Mon, 6 Sep 2021, liuhongt wrote:

> Hi:
>   For the conversion from _Float16 to int, if the corresponding optab
> does not exist, the compiler will try the wider mode (SFmode here),
> but when floatsfsi exists but FAIL, FROM will be rewritten, which
> leads to a PR runtime error.
> 
>   Boostrapped and regtested on x86_64-linux-gnu{-m32,}.
>   Ok for trunk?
> 
> gcc/ChangeLog:
> 
>       PR middle-end/102182
>       * optabs.c (expand_fix): Add from1 to avoid from being
>       overwritten.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR middle-end/102182
>       *gcc.target/i386/pr101282.c: New test.
> ---
>  gcc/optabs.c                             | 10 +++++++---
>  gcc/testsuite/gcc.target/i386/pr101282.c | 18 ++++++++++++++++++
>  2 files changed, 25 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr101282.c
> 
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index ebed78fda3f..6af67d05253 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -5480,6 +5480,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
>      FOR_EACH_MODE_FROM (imode, GET_MODE (to))
>        {
>       int doing_unsigned = unsignedp;
> +     rtx from1 = NULL_RTX;
>  
>       icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
>       if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
> @@ -5489,19 +5490,22 @@ expand_fix (rtx to, rtx from, int unsignedp)
>         {
>           rtx_insn *last = get_last_insn ();

better declare from1 here

>           if (fmode != GET_MODE (from))
> -           from = convert_to_mode (fmode, from, 0);
> +           from1 = convert_to_mode (fmode, from, 0);
>  
>           if (must_trunc)
>             {
>               rtx temp = gen_reg_rtx (GET_MODE (from));
> -             from = expand_unop (GET_MODE (from), ftrunc_optab, from,
> +             from1 = expand_unop (GET_MODE (from), ftrunc_optab, from,

this must use from1 as well?

>                                   temp, 0);
>             }
>  
>           if (imode != GET_MODE (to))
>             target = gen_reg_rtx (imode);
>
> -         if (maybe_emit_unop_insn (icode, target, from,
> +         if (!from1)
> +           from1 = from;

so move this up.

> +         if (maybe_emit_unop_insn (icode, target, from1,
>                                     doing_unsigned ? UNSIGNED_FIX : FIX))
>             {
>               if (target != to)
> diff --git a/gcc/testsuite/gcc.target/i386/pr101282.c 
> b/gcc/testsuite/gcc.target/i386/pr101282.c
> new file mode 100644
> index 00000000000..2148b9294ef
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr101282.c
> @@ -0,0 +1,18 @@
> +/* { dg-do run { target { ia32 } } } */
> +/* { dg-options "-Os -march=i686 -mfpmath=sse -msse2" } */
> +
> +#include<stdlib.h>
> +int
> +main (void)
> +{
> +  static volatile unsigned int ivin, ivout;
> +  static volatile _Float16 fv1, fv2;
> +  ivin = ((unsigned int)1);
> +  fv1 = ((unsigned int)1);
> +  fv2 = ivin;
> +  ivout = fv2;
> +  if (ivout != ((unsigned int)1))
> +    abort ();
> +
> +  exit (0);
> +}
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to