Bug 19689 - [4.0 Regression] ICE in store_bit_field, at expmed.c
Summary: [4.0 Regression] ICE in store_bit_field, at expmed.c
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Richard Henderson
URL:
Keywords: build, ice-checking, ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2005-01-29 08:38 UTC by Andreas Jaeger
Modified: 2005-01-30 02:35 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.4.4
Known to fail: 4.0.0
Last reconfirmed: 2005-01-29 21:58:17


Attachments
Preprocessed source file (64.54 KB, application/octet-stream)
2005-01-29 08:39 UTC, Andreas Jaeger
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Jaeger 2005-01-29 08:38:10 UTC
Compiling gdb on i586 I get the following ICE: 
 
gcc -c -O2 -march=i686 -mtune=i686 -fmessage-length=0 -Wall -Wno-pointer-sign  
-I. -I. -I./config -DLOCALEDIR="\"/usr/share/locale\"" -DHAVE_CONFIG_H 
-I./../include/opcode  -I../bfd -I./../bfd-I./../include -I../intl -I./../intl  
-DMI_OUT=1 -DTUI=1 -Wimplicit -Wreturn-type -Wcomment -Wtrigraphs -Wformat 
-Wparentheses -Wpointer-arith -Wuninitialized -Wformat-nonliteral 
-Wunused-label -Wunused-function  coffread.c -v -save-temps 
Using built-in specs. 
Configured with: ../configure --enable-threads=posix --prefix=/usr 
--with-local-prefix=/usr/local --infodir=/usr/share/info 
--mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib 
--enable-languages=c,c++,objc,f95,java,ada --enable-checking 
--with-gxx-include-dir=/usr/include/c++/4.0.0 --with-slibdir=/lib 
--with-system-zlib --enable-shared --enable-__cxa_atexit 
--without-system-libunwind i586-suse-linux 
Thread model: posix 
gcc version 4.0.0 20050128 (experimental) (SUSE Linux) 
 /usr/lib/gcc/i586-suse-linux/4.0.0/cc1 -E -quiet -v -I. -I. -I./config 
-I./../include/opcode -I../bfd -I./../bfd -I./../include -I../intl -I./../intl 
-DLOCALEDIR="/usr/share/locale" -DHAVE_CONFIG_H -DMI_OUT=1 -DTUI=1 coffread.c 
-march=i686 -mtune=i686 -Wall -Wno-pointer-sign -Wimplicit -Wreturn-type 
-Wcomment -Wtrigraphs -Wformat -Wparentheses -Wpointer-arith -Wuninitialized 
-Wformat-nonliteral -Wunused-label -Wunused-function -fmessage-length=0 -O2 
-fpch-preprocess -o coffread.i 
ignoring duplicate directory "." 
ignoring duplicate directory "./../bfd" 
ignoring nonexistent directory "../intl" 
ignoring nonexistent directory "./../intl" 
#include "..." search starts here: 
#include <...> search starts here: 
 . 
 ./config 
 ./../include/opcode 
 ../bfd 
 ./../include 
 /usr/local/include 
 /usr/lib/gcc/i586-suse-linux/4.0.0/include 
 /usr/lib/gcc/i586-suse-linux/4.0.0/../../../../i586-suse-linux/include 
 /usr/include 
End of search list. 
 /usr/lib/gcc/i586-suse-linux/4.0.0/cc1 -fpreprocessed coffread.i -quiet 
-dumpbase coffread.c -march=i686 -mtune=i686 -auxbase coffread -O2 -Wall 
-Wno-pointer-sign -Wimplicit -Wreturn-type -Wcomment -Wtrigraphs -Wformat 
-Wparentheses -Wpointer-arith -Wuninitialized -Wformat-nonliteral 
-Wunused-label -Wunused-function -version -fmessage-length=0 -o coffread.s 
GNU C version 4.0.0 20050128 (experimental) (SUSE Linux) (i586-suse-linux) 
        compiled by GNU C version 4.0.0 20050128 (experimental) (SUSE Linux). 
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 
coffread.c: In function ?coff_symfile_read?: 
coffread.c:513: warning: unused variable ?target? 
coffread.c:512: warning: unused variable ?len? 
coffread.c: In function ?coff_read_struct_type?: 
coffread.c:1993: internal compiler error: in store_bit_field, at expmed.c:731 
Please submit a full bug report, 
with preprocessed source if appropriate. 
 
Note the same ICE occurs also on Linux/ia64 and Linux/x86-64.
Comment 1 Andreas Jaeger 2005-01-29 08:39:14 UTC
Created attachment 8098 [details]
Preprocessed source file
Comment 2 Andreas Jaeger 2005-01-29 08:46:08 UTC
Note this bug has been introduced after 2005-01-25. 
Comment 3 Serge Belyshev 2005-01-29 09:28:34 UTC
// reduced testcase, compile with '-O1':

struct
{
  int b : 29;
} f;

void foo (short j)
{
  f.b = j;
}
Comment 4 Serge Belyshev 2005-01-29 12:03:07 UTC
Caused by this patch:

2005-01-26  Richard Henderson  <rth@redhat.com>

	PR middle-end/18008
	* c-decl.c (finish_struct): Set DECL_MODE after resetting a
	field's type.
	* expr.c (store_field): Strip conversions to odd-bit-sized types
	if the destination field width matches.
Comment 5 Steven Bosscher 2005-01-29 12:34:09 UTC
#1  0x0000000000645c3a in store_bit_field (str_rtx=0x2a9598d7e0, bitsize=29, 
bitnum=0, 
    fieldmode=VOIDmode, value=0x2a9598d6c0) at expmed.c:731 
731                 gcc_assert (CONSTANT_P (value)); 
(gdb) l 
726               else 
727                 /* Parse phase is supposed to make VALUE's data type 
728                    match that of the component reference, which is a type 
729                    at least as wide as the field; so VALUE should have 
730                    a mode that corresponds to that type.  */ 
731                 gcc_assert (CONSTANT_P (value)); 
732             } 
733 
734           /* If this machine's insv insists on a register, 
735              get VALUE1 into a register.  */ 
(gdb) p debug_rtx(value) 
(reg/v:HI 58 [ j ]) 
$1 = void 
(gdb) bt 
#0  fancy_abort (file=0xa73574 "../../mainline/gcc/expmed.c", line=731, 
    function=0xa73590 "store_bit_field") at diagnostic.c:556 
#1  0x0000000000645c3a in store_bit_field (str_rtx=0x2a9598d7e0, bitsize=29, 
bitnum=0, 
    fieldmode=VOIDmode, value=0x2a9598d6c0) at expmed.c:731 
#2  0x0000000000645a16 in store_bit_field (str_rtx=0x2a9598d7a0, bitsize=29, 
bitnum=0, 
    fieldmode=VOIDmode, value=0x2a9598d6c0) at expmed.c:667 
#3  0x000000000065fc01 in store_field (target=0x2a9598d7a0, bitsize=29, 
bitpos=0, mode=VOIDmode, 
    exp=0x2a95988c30, type=0x2a959888f0, alias_set=0) at expr.c:5270 
#4  0x000000000065a23f in expand_assignment (to=0x2a95895870, 
from=0x2a95a31000) at expr.c:3876 
#5  0x00000000006755e2 in expand_expr_real_1 (exp=0x2a958958c0, target=0x0, 
tmode=VOIDmode, 
    modifier=EXPAND_NORMAL, alt_rtl=0x0) at expr.c:8120 
#6  0x0000000000664d4a in expand_expr_real (exp=0x2a958958c0, 
target=0x2a95894400, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL, alt_rtl=0x0) at expr.c:6336 
#7  0x00000000008aaff1 in expand_expr (exp=0x2a958958c0, target=0x2a95894400, 
mode=VOIDmode, 
    modifier=EXPAND_NORMAL) at expr.h:482 
#8  0x00000000008a3d79 in expand_expr_stmt (exp=0x2a958958c0) at stmt.c:1326 
 
The statement we choque on is "fD.1449.bD.1447 = (<unnamed type>) jD.1450;" 
 
The final_cleanup dumps looks like this: 
 
;; Function foo (foo) 
 
foo (jD.1450) 
{ 
  # BLOCK 0 
  # PRED: ENTRY [100.0%]  (fallthru,exec) 
  #   fD.1449_4 = V_MAY_DEF <fD.1449_3>; 
  fD.1449.bD.1447 = (<unnamed type>) jD.1450; 
  return; 
  # SUCC: EXIT [100.0%] 
 
} 
 
(note btw that the virtual operands are still renamed, which is also 
a but really... :-/) 
 
The patch that introduced this bug is this one: 
http://gcc.gnu.org/ml/gcc-cvs/2005-01/msg01091.html 
 
Comment 6 Steven Bosscher 2005-01-29 12:49:57 UTC
rth's comment on the patch: 
5220          /* If EXP is a NOP_EXPR of precision less than its mode, then 
that 
5221             implies a mask operation.  If the precision is the same size 
as 
5222             the field we're storing into, that mask is redundant.  This 
is 
5223             particularly common with bit field assignments generated by 
the 
5224             C front end.  */ 
5225          if (TREE_CODE (exp) == NOP_EXPR 
5226              && INTEGRAL_TYPE_P (TREE_TYPE (exp)) 
5227              && (TYPE_PRECISION (TREE_TYPE (exp)) 
5228                  < GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)))) 
5229              && bitsize == TYPE_PRECISION (TREE_TYPE (exp))) 
 
But in this case the NOP_EXPR also changes the mode of its operand from 
HImode to SImode: 
(gdb) p debug_tree(exp) 
 <nop_expr 0x2a95a31000 
    type <integer_type 0x2a95988a90 SI 
        size <integer_cst 0x2a95890a80 constant invariant 32> 
        unit size <integer_cst 0x2a958905a0 constant invariant 4> 
        align 32 symtab 0 alias set -1 precision 29 min <integer_cst 
0x2a958a8d80 -268435456> max <integer_cst 0x2a95a2e270 268435455>> 
 
    arg 0 <parm_decl 0x2a95988c30 j 
        type <integer_type 0x2a958968f0 short int HI 
            size <integer_cst 0x2a958908a0 constant invariant 16> 
            unit size <integer_cst 0x2a958908d0 constant invariant 2> 
            align 16 symtab 0 alias set -1 precision 16 min <integer_cst 
0x2a958907e0 -32768> max <integer_cst 0x2a95890840 32767> 
            pointer_to_this <pointer_type 0x2a95928000>> 
        used HI file t.c line 8 size <integer_cst 0x2a958908a0 16> unit size 
<integer_cst 0x2a958908d0 2> 
        align 16 context <function_decl 0x2a95988dd0 foo> result <integer_type 
0x2a958968f0 short int> initial <integer_type 0x2a95896a90 int> 
        (reg/v:HI 58 [ j ]) 
        arg-type <integer_type 0x2a95896a90 int public SI size <integer_cst 
0x2a95890a80 32> unit size <integer_cst 0x2a958905a0 4> 
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x2a958909f0 -2147483648> max <integer_cst 0x2a95890a20 2147483647> 
            pointer_to_this <pointer_type 0x2a958ae4e0>> arg-type-as-written 
<integer_type 0x2a958968f0 short int> 
        incoming-rtl (reg:SI 5 di [ j ])>> 
 
Comment 7 Steven Bosscher 2005-01-29 12:54:44 UTC
Something like this?? 
Index: expr.c 
=================================================================== 
RCS file: /cvs/gcc/gcc/gcc/expr.c,v 
retrieving revision 1.776 
diff -u -3 -p -r1.776 expr.c 
--- expr.c      27 Jan 2005 00:07:41 -0000      1.776 
+++ expr.c      29 Jan 2005 12:54:25 -0000 
@@ -5224,6 +5224,8 @@ store_field (rtx target, HOST_WIDE_INT b 
         C front end.  */ 
       if (TREE_CODE (exp) == NOP_EXPR 
          && INTEGRAL_TYPE_P (TREE_TYPE (exp)) 
+         && (TYPE_MODE (TREE_TYPE (exp)) 
+             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) 
          && (TYPE_PRECISION (TREE_TYPE (exp)) 
              < GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)))) 
          && bitsize == TYPE_PRECISION (TREE_TYPE (exp))) 
 
Comment 8 GCC Commits 2005-01-30 02:34:12 UTC
Subject: Bug 19689

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	rth@gcc.gnu.org	2005-01-30 02:33:28

Modified files:
	gcc            : ChangeLog expr.c 
Added files:
	gcc/testsuite/gcc.c-torture/execute: pr19689.c 

Log message:
	PR middle-end/19689
	* expr.c (store_field): Don't strip sub-mode cast when the input
	data is even smaller.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7328&r2=2.7329
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/expr.c.diff?cvsroot=gcc&r1=1.777&r2=1.778
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/pr19689.c.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 9 Richard Henderson 2005-01-30 02:35:50 UTC
Fixed.