Bug 47968 - ICE: in gen_lowpart_general, at rtlhooks.c:51 when converting vector of double to vector of float
Summary: ICE: in gen_lowpart_general, at rtlhooks.c:51 when converting vector of doubl...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 4.6.0
Assignee: Richard Biener
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2011-03-03 13:05 UTC by Zdenek Sojka
Modified: 2011-03-04 10:32 UTC (History)
1 user (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build:
Known to work:
Known to fail: 4.4.6, 4.5.3, 4.6.0
Last reconfirmed: 2011-03-03 13:15:19


Attachments
reduced testcase (88 bytes, text/plain)
2011-03-03 13:05 UTC, Zdenek Sojka
Details
reduced testcase (123 bytes, text/plain)
2011-03-03 13:06 UTC, Zdenek Sojka
Details
testcase using long instead of double (122 bytes, text/plain)
2011-03-03 15:19 UTC, Zdenek Sojka
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Zdenek Sojka 2011-03-03 13:05:22 UTC
Created attachment 23527 [details]
reduced testcase

Compiler output:
$ gcc -O testcase.c
testcase.c: In function 'foo':
testcase.c:7:3: internal compiler error: in gen_lowpart_general, at rtlhooks.c:51
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


(gdb) bt
#0  fancy_abort (file=0x115e428 "/mnt/svn/gcc-trunk/gcc/rtlhooks.c", line=51, function=0x115e490 "gen_lowpart_general")
    at /mnt/svn/gcc-trunk/gcc/diagnostic.c:892
#1  0x0000000000874ccb in gen_lowpart_general (mode=SFmode, x=<value optimized out>) at /mnt/svn/gcc-trunk/gcc/rtlhooks.c:51
#2  0x000000000069bb04 in extract_bit_field (str_rtx=<value optimized out>, bitsize=<value optimized out>, bitnum=<value optimized out>, 
    unsignedp=<value optimized out>, packedp=<value optimized out>, target=<value optimized out>, mode=SFmode, tmode=SFmode)
    at /mnt/svn/gcc-trunk/gcc/expmed.c:1684
#3  0x00000000006a9562 in expand_expr_real_1 (exp=0x7ffff5ba5280, target=<value optimized out>, tmode=SFmode, modifier=EXPAND_NORMAL, alt_rtl=0x0)
    at /mnt/svn/gcc-trunk/gcc/expr.c:9211
#4  0x00000000006af03d in expand_expr_real (exp=0x7ffff5ba5280, target=<value optimized out>, tmode=<value optimized out>, 
    modifier=<value optimized out>, alt_rtl=<value optimized out>) at /mnt/svn/gcc-trunk/gcc/expr.c:7206
#5  expand_expr_real (exp=0x7ffff5ba5280, target=<value optimized out>, tmode=<value optimized out>, modifier=<value optimized out>, 
    alt_rtl=<value optimized out>) at /mnt/svn/gcc-trunk/gcc/expr.c:7174
#6  0x00000000006ab820 in expand_expr (exp=0x7ffff5ba41b8, target=0x7ffff5b948e0, tmode=SFmode, modifier=EXPAND_NORMAL, alt_rtl=0x0)
    at /mnt/svn/gcc-trunk/gcc/expr.h:422
#7  expand_expr_real_1 (exp=0x7ffff5ba41b8, target=0x7ffff5b948e0, tmode=SFmode, modifier=EXPAND_NORMAL, alt_rtl=0x0)
    at /mnt/svn/gcc-trunk/gcc/expr.c:8807
#8  0x00000000008d065b in expand_expr (retval=0x7ffff7ff91f8) at /mnt/svn/gcc-trunk/gcc/expr.h:422
#9  expand_return (retval=0x7ffff7ff91f8) at /mnt/svn/gcc-trunk/gcc/stmt.c:1812
#10 0x00000000005e0e8b in expand_gimple_stmt_1 (stmt=0x7ffff5b89510) at /mnt/svn/gcc-trunk/gcc/cfgexpand.c:1951
#11 expand_gimple_stmt (stmt=0x7ffff5b89510) at /mnt/svn/gcc-trunk/gcc/cfgexpand.c:2080
#12 0x00000000005e2f29 in expand_gimple_basic_block (bb=0x7ffff5b851a0) at /mnt/svn/gcc-trunk/gcc/cfgexpand.c:3609
#13 0x00000000005e81d9 in gimple_expand_cfg () at /mnt/svn/gcc-trunk/gcc/cfgexpand.c:4092
#14 0x00000000007f7056 in execute_one_pass (pass=0x1638ac0) at /mnt/svn/gcc-trunk/gcc/passes.c:1556
#15 0x00000000007f7355 in execute_pass_list (pass=0x1638ac0) at /mnt/svn/gcc-trunk/gcc/passes.c:1611
#16 0x000000000093a2b6 in tree_rest_of_compilation (fndecl=0x7ffff5b86f00) at /mnt/svn/gcc-trunk/gcc/tree-optimize.c:422
#17 0x0000000000b02312 in cgraph_expand_function (node=0x7ffff5ba6000) at /mnt/svn/gcc-trunk/gcc/cgraphunit.c:1576
#18 0x0000000000b04a5a in cgraph_expand_all_functions () at /mnt/svn/gcc-trunk/gcc/cgraphunit.c:1635
#19 cgraph_optimize () at /mnt/svn/gcc-trunk/gcc/cgraphunit.c:1899
#20 0x0000000000b04fda in cgraph_finalize_compilation_unit () at /mnt/svn/gcc-trunk/gcc/cgraphunit.c:1096
#21 0x00000000005097bc in c_write_global_declarations () at /mnt/svn/gcc-trunk/gcc/c-decl.c:9872
#22 0x00000000008e3248 in compile_file (argc=13, argv=0x7fffffffdbd8) at /mnt/svn/gcc-trunk/gcc/toplev.c:591
#23 do_compile (argc=13, argv=0x7fffffffdbd8) at /mnt/svn/gcc-trunk/gcc/toplev.c:1900
#24 toplev_main (argc=13, argv=0x7fffffffdbd8) at /mnt/svn/gcc-trunk/gcc/toplev.c:1963
#25 0x00007ffff6446bbd in __libc_start_main () from /lib/libc.so.6
#26 0x00000000004f036d in _start ()

Tested revisions:
r170622 - crash
4.5 r170013 - crash
4.4 r170013 - crash
4.4.5 (release checking) - crash
4.3.5 (release checking) - OK

Maybe it's a regression from 4.3.
Comment 1 Zdenek Sojka 2011-03-03 13:06:51 UTC
Created attachment 23528 [details]
reduced testcase

http://gcc.gnu.org/bugzilla/attachment.cgi?id=23527&action=edit is for PR47967
Comment 2 Richard Biener 2011-03-03 13:15:19 UTC
Confirmed.

#1  0x000000000098a3b8 in gen_lowpart_general (mode=SFmode, x=0x7ffff5b36900)
    at /space/rguenther/src/svn/trunk/gcc/rtlhooks.c:51
51          gcc_assert (result != 0);
(gdb) p x
$1 = (rtx) 0x7ffff5b36900
(gdb) call debug_rtx (x)
(reg:DF 64)

Happens during expanding of BIT_FIELD_REF <f4.0_2, 32, 0> from

;; Function foo (foo)

foo (double2 d2)
{
  float D.2687;
  vector(4) float f4.0;

  # BLOCK 2 freq:10000
  # PRED: ENTRY [100.0%]  (fallthru,exec)
  f4.0_2 = VIEW_CONVERT_EXPR<vector(4) float>(d2_1(D));
  D.2687_3 = BIT_FIELD_REF <f4.0_2, 32, 0>;
  return D.2687_3;
Comment 3 Richard Biener 2011-03-03 13:30:28 UTC
We call extract_bit_field SFmode [0, 32] on (subreg:V4SF (reg/v:V2DF 62 [ d2 ]) 0) which then ends up using the vec_extract optabs, but those are obviously
not designed for a mode-changing extraction (and we stripped the subreg
before using it - whether that's a good idea is another question).

We try to find a "better" vector mode but end up with V2DF again because
we want to preserve NUNITS of the inner reg (for whatever reason again).

We can obviously guard the vec_extract optab use by GET_MODE_INNER (GET_MODE (op0)) == tmode, but we can as well try to find a "better" mode that also
is going to work ...

Testing a patch, CCing Andrew who added this code.

Patch:

Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c        (revision 170649)
+++ gcc/expmed.c        (working copy)
@@ -1205,7 +1205,6 @@ extract_bit_field_1 (rtx str_rtx, unsign
       && GET_MODE_INNER (GET_MODE (op0)) != tmode)
     {
       enum machine_mode new_mode;
-      int nunits = GET_MODE_NUNITS (GET_MODE (op0));
 
       if (GET_MODE_CLASS (tmode) == MODE_FLOAT)
        new_mode = MIN_MODE_VECTOR_FLOAT;
@@ -1221,8 +1220,7 @@ extract_bit_field_1 (rtx str_rtx, unsign
        new_mode = MIN_MODE_VECTOR_INT;
 
       for (; new_mode != VOIDmode ; new_mode = GET_MODE_WIDER_MODE (new_mode))
-       if (GET_MODE_NUNITS (new_mode) == nunits
-           && GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0))
+       if (GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0))
            && targetm.vector_mode_supported_p (new_mode))
          break;
       if (new_mode != VOIDmode)
Comment 4 Richard Biener 2011-03-03 13:34:50 UTC
Btw, I wonder since when (and why) we accept

  float4 f4 = (float4) d2;

as valid code.
Comment 5 Zdenek Sojka 2011-03-03 13:56:06 UTC
The testcase is accepted (compiles fine) by 3.3.6, 3.4.6, 4.0.4, 4.1.2, 4.2.4, 4.3.5.

The are files in the testsuite that use that style, at least gcc.c-torture/compile/vector-[123].c

Changing the code to
  float4 f4 = *(float4 *) &d2;
doesn't prevent the crash
Comment 6 Zdenek Sojka 2011-03-03 15:19:55 UTC
Created attachment 23532 [details]
testcase using long instead of double

This one fails the same way.
Comment 7 Andrew Pinski 2011-03-03 17:47:42 UTC
(In reply to comment #3)
> Patch:
> 
> Index: gcc/expmed.c

IIRC this is the patch which I had applied to the PS3 toolchain while at Sony.  I don't have access to the sources any more so I cannot check.  But it looks correct.

Thanks,
Andrew Pinski
Comment 8 Andrew Pinski 2011-03-03 17:50:38 UTC
(In reply to comment #4)
> Btw, I wonder since when (and why) we accept
> 
>   float4 f4 = (float4) d2;
> 
> as valid code.

Because it is documented as being valid code that is you can cast between the same size of the vectors (not to mention integers that are the same size as the vector also).  It acts like a bitwise conversion rather than a promotion.  This is needed for compatibility with the Altivec and SPU specs.

-- Andrew
Comment 9 Richard Biener 2011-03-04 10:31:38 UTC
Author: rguenth
Date: Fri Mar  4 10:31:33 2011
New Revision: 170673

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170673
Log:
2011-03-04  Richard Guenther  <rguenther@suse.de>

	PR middle-end/47968
	* expmed.c (extract_bit_field_1): Prefer vector modes that
	vec_extract patterns can handle.

	* gcc.dg/torture/pr47968.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr47968.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/expmed.c
    trunk/gcc/testsuite/ChangeLog
Comment 10 Richard Biener 2011-03-04 10:32:45 UTC
Fixed.