Bug 102182 - Runtime error for gcc.dg/torture/fp-int-convert-float16.c
Summary: Runtime error for gcc.dg/torture/fp-int-convert-float16.c
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2021-09-03 05:56 UTC by Hongtao.liu
Modified: 2021-09-06 10:58 UTC (History)
2 users (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: x86_64-*-* i?86-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-09-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hongtao.liu 2021-09-03 05:56:18 UTC
I got

FAIL: gcc.dg/torture/fp-int-convert-float16.c   -Os  execution test
FAIL: gcc.dg/torture/fp-int-convert-float16-timode.c   -Os  execution test

with -m32:

[hjl@gnu-skx-1 gcc]$ ./xgcc -B./ -m32
/export/gnu/import/git/gitlab/x86-gcc/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c
 -m32  -Os -march=i686 -mfpmath=sse -msse2
[hjl@gnu-skx-1 gcc]$ ./a.out
Aborted (core dumped)
[hjl@gnu-skx-1 gcc]$
Comment 1 Hongtao.liu 2021-09-03 05:57:01 UTC
Iā€™m still trying to reduce a small testcase.
Comment 2 Hongtao.liu 2021-09-03 06:17:47 UTC
Reproduced case.

#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);
}
Comment 3 Hongtao.liu 2021-09-03 06:39:10 UTC
during pass_expand we got

(debug_insn 24 23 0 (debug_marker) "test1.c":10:3 -1
     (nil))
;; fv2.1_3 ={v} fv2;

(insn 25 24 0 (set (reg:HF 84 [ fv2.1_3 ])
        (mem/v/c:HF (symbol_ref:SI ("fv2.1") [flags 0x2]  <var_decl 0x7f1f0ae4c000 fv2>) [2 fv2+0 S2 A16])) "test1.c":10:9 -1
     (nil))

;; _4 = (unsigned int) fv2.1_3;

(insn 31 25 32 (parallel [
            (set (reg:DI 94)
                (fix:DI (reg:SF 93)))
            (clobber (reg:CC 17 flags))
        ]) "test1.c":10:9 -1
     (nil))

But __extendhfsf2 is ommited under -Os, 

For -O2 expand does the right thing

;; fv2.1_3 ={v} fv2;

(insn 17 16 0 (set (reg:HF 84 [ fv2.1_3 ])
        (mem/v/c:HF (symbol_ref:SI ("fv2.1") [flags 0x2]  <var_decl 0x7f166dab4360 fv2>) [2 fv2+0 S2 A16])) "test1.c":10:9 -1
     (nil))

;; _4 = (unsigned int) fv2.1_3;


(insn 18 17 19 (set (mem:HF (reg/f:SI 79 virtual-outgoing-args) [0  S2 A32])
        (reg:HF 84 [ fv2.1_3 ])) "test1.c":10:9 -1
     (nil))

(call_insn/u 19 18 20 (set (reg:SF 8 st)
        (call (mem:QI (symbol_ref:SI ("__extendhfsf2") [flags 0x41]  <function_decl 0x7f166dac5000 __extendhfsf2>) [0  S1 A8])
            (const_int 16 [0x10]))) "test1.c":10:9 -1
     (expr_list:REG_CALL_DECL (symbol_ref:SI ("__extendhfsf2") [flags 0x41]  <function_decl 0x7f166dac5000 __extendhfsf2>)
        (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
            (nil)))
    (expr_list (use (mem:HF (reg/f:SI 79 virtual-outgoing-args) [0  S2 A8]))
        (nil)))

(insn 20 19 21 (set (reg:SF 93)
        (reg:SF 8 st)) "test1.c":10:9 -1
     (expr_list:REG_EQUAL (float_extend:SF (reg:HF 84 [ fv2.1_3 ]))
        (nil)))

(insn 21 20 22 (set (reg:V4SF 95)
        (vec_duplicate:V4SF (mem/u/c:SF (symbol_ref/u:SI ("*.LC3") [flags 0x2]) [0  S4 A32]))) "test1.c":10:9 7413 {vec_dupv4sf}
     (nil))

(insn 22 21 23 (set (reg:V4SF 94)
        (reg:V4SF 95)) "test1.c":10:9 -1
     (expr_list:REG_EQUAL (const_vector:V4SF [
                (const_double:SF 2.147483648e+9 [0x0.8p+32]) repeated x4
            ])
        (nil)))

(insn 23 22 0 (parallel [
            (set (reg:SI 85 [ _4 ])
                (unsigned_fix:SI (reg:SF 93)))
            (use (reg:V4SF 94))
            (clobber (scratch:V4SF))
            (clobber (scratch:V4SF))
        ]) "test1.c":10:9 -1
     (expr_list:REG_EQUAL (unsigned_fix:SI (reg:SF 93))
        (nil)))
Comment 4 Hongtao.liu 2021-09-03 07:38:36 UTC
After emit libcall in convert_to_mode, it failed maybe_emit_unop_insn, so all insns deleted, but from here is already overrided, it seems to be a bug.

	if (icode != CODE_FOR_nothing)
	  {
	    rtx_insn *last = get_last_insn ();
	    if (fmode != GET_MODE (from))
	      from = 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,
				    temp, 0);
	      }

	    if (imode != GET_MODE (to))
	      target = gen_reg_rtx (imode);

	    if (maybe_emit_unop_insn (icode, target, from,
				      doing_unsigned ? UNSIGNED_FIX : FIX))
	      {
		if (target != to)
		  convert_move (to, target, unsignedp);
		return;
	      }
	    delete_insns_since (last);
	  }
Comment 5 GCC Commits 2021-09-06 10:58:15 UTC
The master branch has been updated by hongtao Liu <liuhongt@gcc.gnu.org>:

https://gcc.gnu.org/g:93e6809459f34ca7b5928f1729246b2e9dfb3eb4

commit r12-3368-g93e6809459f34ca7b5928f1729246b2e9dfb3eb4
Author: liuhongt <hongtao.liu@intel.com>
Date:   Mon Sep 6 17:09:38 2021 +0800

    Avoid FROM being overwritten in expand_fix.
    
    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.
    
    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.
Comment 6 Hongtao.liu 2021-09-06 10:58:47 UTC
Fixed in GCC12.