Bug 20928 - [4.0/4.1 regression] ICE: unrecognizable insns with -fPIC -O1
Summary: [4.0/4.1 regression] ICE: unrecognizable insns with -fPIC -O1
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.0.0
: P1 critical
Target Milestone: 4.0.3
Assignee: Not yet assigned to anyone
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: ice-on-valid-code, patch
: 24443 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-04-10 15:07 UTC by Andreas Jaeger
Modified: 2005-10-31 18:45 UTC (History)
7 users (show)

See Also:
Host:
Target: x86_64-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-10-27 20:40:13


Attachments
Preprocessed source file (96.00 KB, application/octet-stream)
2005-04-10 15:08 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-04-10 15:07:29 UTC
Compiling clisp with gcc 4 CVS fails with the following ICE.  This is a
regression from GCC 3.3.

$ gcc -fPIC -D_GNU_SOURCE  -W -Wswitch -Wcomment -Wpointer-arith -Wimplicit
-Wreturn-type   -O -DUNICODE -DDYNAMIC_FFI -DDYNAMIC_MODULES -DNO_SIGSEGV -I. -c
spvw.c -save-temps -v
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr
--with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man
--libdir=/usr/lib64 --libexecdir=/usr/lib64
--enable-languages=c,c++,objc,f95,java,ada --enable-checking
--with-gxx-include-dir=/usr/include/c++/4.0.0 --with-slibdir=/lib64
--with-system-zlib --enable-shared --enable-__cxa_atexit
--without-system-libunwind --host=x86_64-suse-linux
Thread model: posix
gcc version 4.0.0 20050410 (prerelease) (SUSE Linux)
 /usr/lib64/gcc/x86_64-suse-linux/4.0.0/cc1 -E -quiet -v -I. -D_GNU_SOURCE
-DUNICODE -DDYNAMIC_FFI -DDYNAMIC_MODULES -DNO_SIGSEGV spvw.c -mtune=k8 -W
-Wswitch -Wcomment -Wpointer-arith -Wimplicit -Wreturn-type -fPIC -O
-fpch-preprocess -o spvw.i
#include "..." search starts here:
#include <...> search starts here:
 .
 /usr/local/include
 /usr/lib64/gcc/x86_64-suse-linux/4.0.0/include
 /usr/lib64/gcc/x86_64-suse-linux/4.0.0/../../../../x86_64-suse-linux/include
 /usr/include
End of search list.
 /usr/lib64/gcc/x86_64-suse-linux/4.0.0/cc1 -fpreprocessed spvw.i -quiet
-dumpbase spvw.c -mtune=k8 -auxbase spvw -O -W -Wswitch -Wcomment
-Wpointer-arith -Wimplicit -Wreturn-type -version -fPIC -o spvw.s
GNU C version 4.0.0 20050410 (prerelease) (SUSE Linux) (x86_64-suse-linux)
        compiled by GNU C version 4.0.0 20050410 (prerelease) (SUSE Linux).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
In file included from spvw.d:25:
lispbibl.d:7430: warning: volatile register variables don’t work as you might wish
In file included from spvw.d:563:
spvw_typealloc.d: In function ‘allocate_vector’:
spvw_typealloc.d:94: error: unrecognizable insn:
(insn 93 92 88 4 (set (reg/f:DI 87)
        (plus:DI (reg:DI 91)
            (const_int 1125899906842624 [0x4000000000000]))) -1
(insn_list:REG_DEP_TRUE 92 (nil))
    (expr_list:REG_DEAD (reg:DI 91)
        (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI
("symbol_tab_data") [flags 0x40] <var_decl 0x2aaaab1cc750 symbol_tab_data>)
                    (const_int 1125899906842624 [0x4000000000000])))
            (nil))))
spvw_typealloc.d:94: internal compiler error: in extract_insn, at recog.c:2060
Please submit a full bug report,
with preprocessed source if appropriate.
Comment 1 Andreas Jaeger 2005-04-10 15:08:32 UTC
Created attachment 8579 [details]
Preprocessed source file
Comment 2 Steven Bosscher 2005-04-10 16:01:49 UTC
Also happens with mainline. 
 
extern struct symbol_tab_ 
{ 
  void *S_nil; 
} symbol_tab_data; 
 
typedef struct 
{ 
  unsigned int length; 
  void *data[0]; 
} s; 
 
void * 
allocate_vector (unsigned int len) 
{ 
  unsigned int need; 
  s *ptr; 
  void *obj; 
  ptr->length = len; 
  void **p = &ptr->data[0]; 
  do { 
    *p++ = ((((unsigned char *) ((&symbol_tab_data.S_nil)) + 
              ((unsigned long int) (((1L << (2)))) << 48)))); 
  } while (!(--len == 0)); 
  return obj; 
} 
 
t.c: In function 'allocate_vector': 
t.c:25: error: unrecognizable insn: 
(insn 56 55 51 0 (set (reg/f:DI 70) 
        (plus:DI (reg:DI 73) 
            (const_int 1125899906842624 [0x4000000000000]))) -1 
(insn_list:REG_DEP_TRUE 55 (nil)) 
    (expr_list:REG_DEAD (reg:DI 73) 
        (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI 
("symbol_tab_data") [flags 0x40] <var_decl 0x2a95a36270 symbol_tab_data>) 
                    (const_int 1125899906842624 [0x4000000000000]))) 
            (nil)))) 
t.c:25: internal compiler error: in extract_insn, at recog.c:2082 
 
Comment 3 Steven Bosscher 2005-04-10 16:03:14 UTC
Needs "-O -mtune=k8 -fPIC" of course.  -fPIC seems to cause the problem. 
Comment 4 Steven Bosscher 2005-04-10 16:08:43 UTC
Double *sigh*. 
The old loop optimizer introduces the offending insn.  From the .loop dump: 
 
Insn 26: regno 70 (life 1), move-insn forces 25 savings 1  moved to 56 
Hoisted regno 74 r/o from (mem/u/c:DI (const:DI (unspec:DI [ 
                (symbol_ref:DI ("symbol_tab_data") [flags 0x40] <var_decl 
0x2a95a36270 symbol_tab_data>) 
            ] 2)) [0 S8 A8]) 
... 
(insn 56 55 51 0 (set (reg/f:DI 70) 
        (plus:DI (reg:DI 73) 
            (const_int 1125899906842624 [0x4000000000000]))) -1 (nil) 
    (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI ("symbol_tab_data") 
[flags 0x40] <var_decl 0x2a95a36270 symbol_tab_data>) 
                (const_int 1125899906842624 [0x4000000000000]))) 
        (nil))) 
 
Comment 5 Steven Bosscher 2005-04-10 17:24:10 UTC
After CSE1 (t.c.04.cse) we have: 
 
(insn 20 18 22 1 (set (reg:DI 66) 
        (mem/u/c:DI (const:DI (unspec:DI [ 
                        (symbol_ref:DI ("bar") [flags 0x40] <var_decl 
0x2a95a2f000 bar>) 
                    ] 2)) [0 S8 A8])) 81 {*movdi_1_rex64} (nil) 
    (nil)) 
 
(insn 22 20 23 1 (set (reg:DI 68) 
        (const_int 2147483648 [0x80000000])) 81 {*movdi_1_rex64} (nil) 
    (nil)) 
 
(insn 23 22 24 1 (parallel [ 
            (set (reg:DI 67) 
                (plus:DI (reg:DI 66) 
                    (reg:DI 68))) 
            (clobber (reg:CC 17 flags)) 
        ]) 193 {*adddi_1_rex64} (nil) 
    (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI ("bar") [flags 
0x40] <var_decl 0x2a95a2f000 bar>) 
                (const_int 2147483648 [0x80000000]))) 
        (nil))) 
 
but old loop (t.c.06.loop) somehow turns this into: 
 
(insn 45 48 46 0 (set (reg:DI 69) 
        (mem/u/c:DI (const:DI (unspec:DI [ 
                        (symbol_ref:DI ("bar") [flags 0x40] <var_decl 
0x2a95a2f000 bar>) 
                    ] 2)) [0 S8 A8])) -1 (nil) 
    (nil)) 
 
(insn 46 45 41 0 (set (reg/f:DI 67) 
        (plus:DI (reg:DI 69) 
            (const_int 2147483648 [0x80000000]))) -1 (nil) 
    (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI ("bar") [flags 
0x40] <var_decl 0x2a95a2f000 bar>) 
                (const_int 2147483648 [0x80000000]))) 
        (nil))) 
 
Note how we have lost a clobber and turned a reg+reg addition into a reg+imm; 
from: 
(set (reg:DI 66) (mem:DI (const:DI (unspec:DI [(symbol_ref:DI ("bar"))])))) 
(set (reg:DI 68) (const_int 2147483648 [0x80000000])) 
(parallel [ 
  (set (reg:DI 67) (plus:DI (reg:DI 66) (reg:DI 68))) 
  (clobber (reg:CC 17 flags))]) 
 
to: 
(set (reg:DI 69) (mem:DI (const:DI (unspec:DI [(symbol_ref:DI ("bar"))])))) 
(set (reg/f:DI 67) (plus:DI (reg:DI 69) (const_int 2147483648 [0x80000000]))) 
 
 
Comment 6 Steven Bosscher 2005-04-10 17:39:36 UTC
The offending insn is created by emit_move_insn in loop.c, here: 
2354                start_sequence (); 
2355                emit_move_insn (m->insert_temp ? newreg : m->set_dest, 
2356                                m->set_src); 
2357                seq = get_insns (); 
2358                end_sequence (); 
 
(gdb) p debug_rtx_list (seq, 10) 
(insn 45 0 46 (set (reg:DI 69) 
        (mem/u/c:DI (const:DI (unspec:DI [ 
                        (symbol_ref:DI ("bar") [flags 0x40] <var_decl 
0x2a95a2f000 bar>) 
                    ] 2)) [0 S8 A8])) -1 (nil) 
    (nil)) 
 
(insn 46 45 0 (set (reg/f:DI 67) 
        (plus:DI (reg:DI 69) 
            (const_int 2147483648 [0x80000000]))) -1 (nil) 
    (expr_list:REG_EQUAL (const:DI (plus:DI (symbol_ref:DI ("bar") [flags 
0x40] <var_decl 0x2a95a2f000 bar>) 
                (const_int 2147483648 [0x80000000]))) 
        (nil))) 
 
 
Comment 7 Steven Bosscher 2005-04-10 17:52:33 UTC
My RTL-fu is way below par, so perhaps this doesn't make sense at all, but... 
 
It seems that emit_move_insn must always produce valid move insns.  So it 
should check that an immediate is a valid PIC operand if -fPIC.  In this case 
I'd say LEGITIMATE_CONSTANT_P is the wrong target macro to use.  So you would 
have this instead: 
 
Index: expr.c 
=================================================================== 
RCS file: /cvs/gcc/gcc/gcc/expr.c,v 
retrieving revision 1.783 
diff -u -3 -p -r1.783 expr.c 
--- expr.c      30 Mar 2005 21:34:23 -0000      1.783 
+++ expr.c      10 Apr 2005 17:51:01 -0000 
@@ -3093,7 +3093,8 @@ emit_move_insn (rtx x, rtx y) 
 
       y_cst = y; 
 
-      if (!LEGITIMATE_CONSTANT_P (y)) 
+      if ((!flag_pic && !LEGITIMATE_CONSTANT_P (y)) 
+          || (flag_pic && !LEGITIMATE_PIC_OPERAND_P (y))) 
        { 
          y = force_const_mem (mode, y); 
 
Comment 8 Steven Bosscher 2005-04-10 19:03:13 UTC
FWIW, smallest test case I could find: 
 
extern struct bar_t bar; 
void 
foo (void) 
{ 
  void **p; 
  do { 
    *p++ = ((unsigned char *) &bar + ((unsigned long int) 1L << 31)); 
  } while (p); 
} 
 
Comment 9 Steven Bosscher 2005-04-10 21:05:38 UTC
Alexandre Oliva pointed out to me that it was probably the expander who 
should produce a proper legitimate insn.  I looked at this some more and 
found that in legitimize_pic_address we do not check if a displacement 
is a valid PIC displacement: 
 
Index: config/i386/i386.c 
=================================================================== 
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v 
retrieving revision 1.807 
diff -u -3 -p -r1.807 i386.c 
--- config/i386/i386.c  9 Apr 2005 17:19:48 -0000       1.807 
+++ config/i386/i386.c  10 Apr 2005 21:01:26 -0000 
@@ -5612,7 +5612,13 @@ legitimize_pic_address (rtx orig, rtx re 
                                             base == reg ? NULL_RTX : reg); 
 
              if (GET_CODE (new) == CONST_INT) 
-               new = plus_constant (base, INTVAL (new)); 
+               { 
+                 if (legitimate_pic_address_disp_p (new)) 
+                   new = plus_constant (base, INTVAL (new)); 
+                 else 
+                   new = gen_rtx_PLUS (Pmode, base, 
+                                       copy_to_mode_reg (Pmode, new)); 
+               } 
              else 
                { 
                  if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1))) 
 
This looks to me like much better hack (maybe even a proper fix!) so I'll 
test this to see what happens... 
Comment 10 Andreas Jaeger 2005-05-21 07:00:11 UTC
Steven, any update on this one?  Would you like to get it assigned to? 
Comment 11 Richard Henderson 2005-06-08 00:08:55 UTC
This patch trivially "fixes" the problem because the argument to 
legitimate_pic_address_disp_p is incorrect, and it will always
return false.
Comment 12 Mark Mitchell 2005-07-06 17:03:05 UTC
Postponed until 4.0.2.
Comment 13 Kazu Hirata 2005-10-10 03:20:29 UTC
The testcase in comment #8 still triggers an ICE if run with -O -mtune=k8 -fPIC.
Comment 14 Pawel Sikora 2005-10-19 13:50:53 UTC
(In reply to comment #13)
> The testcase in comment #8 still triggers an ICE if run with -O -mtune=k8
> -fPIC.
> 

it works with my patched gcc41:

(...)
        .section        .data.rel.ro,"aw",@progbits
        .align 8
.LC1:   .quad   bar+2147483648
(...)
        .text
foo:    movq    .LC1(%rip), %rdx
.L3:    movq    %rdx, (%rax)
        addq    $8, %rax
        jne     .L3
        rep ; ret
(...)
Comment 15 Andrew Pinski 2005-10-19 14:02:02 UTC
*** Bug 24443 has been marked as a duplicate of this bug. ***
Comment 16 Jan Hubicka 2005-10-30 18:00:05 UTC
testing fix that should make legitimize_pic_address correctly decompose the address. Similar to Steven's but I think it actually works ;)
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c  (revision 106026)
+++ config/i386/i386.c  (working copy)
@@ -6016,7 +6016,18 @@ legitimize_pic_address (rtx orig, rtx re
     }
   else
     {
-      if (GET_CODE (addr) == CONST)
+      if (GET_CODE (addr) == CONST_INT
+         && !x86_64_immediate_operand (addr, VOIDmode))
+       {
+         if (reg)
+           {
+             emit_move_insn (reg, addr);
+             new = reg;
+           }
+         else
+           new = force_reg (DImode, addr);
+       }
+      else if (GET_CODE (addr) == CONST)
        {
          addr = XEXP (addr, 0);
Comment 17 Mark Mitchell 2005-10-31 03:06:19 UTC
This prevents compiling a reasonably popular program; it's a showstopper.
Comment 18 Steven Bosscher 2005-10-31 17:14:22 UTC
See comment #16 for a patch.
Comment 19 Andrew Pinski 2005-10-31 17:16:03 UTC
(In reply to comment #18)
> See comment #16 for a patch.
More than that, it has been posted:
http://gcc.gnu.org/ml/gcc-patches/2005-10/msg01792.html
Comment 20 Jan Hubicka 2005-10-31 18:45:57 UTC
Patch comitted.  For some reason don't seem to appear in logs?