$ cat ice.i int foo() { return bar(); } $ ./xgcc -v Using built-in specs. COLLECT_GCC=./xgcc Target: mips-unknown-linux-uclibc Configured with: ../configure --target=mips-unknown-linux-uclibc --prefix=/home/ryan/x-tools/mips-unknown-linux-uclibc --with-sysroot=/home/ryan/x-tools/mips-unknown-linux-uclibc/mips-unknown-linux-uclibc/sys-root --enable-languages=c --disable-multilib --with-float=soft --enable-__cxa_atexit --with-local-prefix=/home/ryan/x-tools/mips-unknown-linux-uclibc/mips-unknown-linux-uclibc/sys-root --disable-nls --enable-threads=posix --enable-symvers=gnu --enable-c99 --enable-long-long --enable-target-optspace Thread model: posix gcc version 4.7.0 20110429 (experimental) [trunk revision 173156] (GCC) $ ./xgcc -B. -O -g ice.i ice.i: In function 'foo': ice.i:3:1: internal compiler error: in dwarf2out_var_location, at dwarf2out.c:22013 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions.
The change that introduced this ICE is rev171033. http://gcc.gnu.org/viewcvs?view=revision&revision=171033
After rev171033 debugging is completely broken for this mips configuration. i.e. everything build I compile with -g ICEs this way.
Most probably the backend is reordering insns after var-tracking, it shouldn't be doing that. ARM/SH/S390 backends all have fixed similar bugs very quickly after this patch went in.
The issue with ARM/SH/S390 backends appears to be there was a literal pool split happening in between a call insn and the NOTE_INSN_CALL_ARG_LOCATION. It looks like on mips the issue, at least for my testcase, is the gp store in mips_split_call is getting emitted in between the call insn and the note. (call_insn 39 5 40 (parallel [ (set (reg:SI 2 $2) (call (mem:SI (reg:SI 25 $25 [196]) [0 S4 A32]) (const_int 16 [0x10]))) (clobber (reg:SI 31 $31)) (clobber (reg:SI 28 $28)) ]) /home/ryan/ice.i:2 575 {call_value_split} (nil) (expr_list:REG_DEP_TRUE (use (reg:SI 79 $fakec)) (expr_list:REG_DEP_TRUE (use (reg:SI 28 $28)) (nil)))) (insn 40 39 32 (set (reg:SI 28 $28) (mem/c:SI (plus:SI (reg/f:SI 29 $sp) (const_int 16 [0x10])) [0 S4 A32])) /home/ryan/ice.i:2 280 {*movsi_internal} (nil)) (note 32 40 7 (expr_list:REG_DEP_TRUE (concat:SI (reg:SI 79 $fakec) (reg:SI 79 $fakec)) (expr_list:REG_DEP_TRUE (concat:SI (reg:SI 28 $28) (reg:SI 28 $28)) (nil))) NOTE_INSN_CALL_ARG_LOCATION)
About to post a patch.
Author: rsandifo Date: Mon May 23 17:57:35 2011 New Revision: 174080 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=174080 Log: gcc/ PR rtl-optimization/48826 * emit-rtl.c (try_split): When splitting a call that is followed by a NOTE_INSN_CALL_ARG_LOCATION, move the note after the new call. Modified: trunk/gcc/ChangeLog trunk/gcc/emit-rtl.c
Fixed on trunk.
*** Bug 48843 has been marked as a duplicate of this bug. ***
Richard, thanks for your patch. It fixed most of the failures I saw but there are still cases where the note doesn't get moved after call split. The following example ICEs with rev174285. void foo () { int *const pc = __builtin_return_address (0); bar (pc); }
The code is broken in the latest code because beside NOTE instruction there could be BARRIER too, for instance the RTX list I am seeing: (call_insn 32 35 33 (parallel [ (set (reg:SI 2 $2) (call (mem:SI (reg:SI 25 $25 [198]) [0 S4 A32]) (const_int 16 [0x10]))) (clobber (reg:SI 31 $31)) (clobber (reg:SI 28 $28)) ]) min.c:20 603 {call_value_split} (nil) (expr_list (use (reg:SI 79 $fakec)) (expr_list (use (reg:SI 28 $28)) (expr_list:SI (use (reg:SI 5 $5)) (expr_list:SI (use (reg:SI 4 $4)) (nil)))))) (insn 33 32 34 (set (reg:SI 28 $28) (mem/c:SI (plus:SI (reg/f:SI 29 $sp) (const_int 16 [0x10])) [0 S4 A32])) min.c:20 288 {*movsi_internal} (nil)) (barrier 34 33 18) (barrier 18 34 30) (note 30 18 21 (expr_list:REG_DEP_TRUE (concat:SI (pc) (unspec:SI [ (reg:SI 28 $28) (const:SI (unspec:SI [ (symbol_ref:SI ("signal") [flags 0x41] <function_decl 0xb71f6700 signal>) ] 227)) (reg:SI 79 $fakec) ] UNSPEC_LOAD_CALL)) (expr_list:REG_DEP_TRUE (concat:SI (reg:SI 5 $5) (const_int 0 [0])) (expr_list:REG_DEP_TRUE (concat:SI (reg:SI 4 $4) (const_int 2 [0x2])) (nil)))) NOTE_INSN_CALL_ARG_LOCATION) (note 21 30 0 NOTE_INSN_DELETED)
And I don't thing it is the best place to fix this bug in function try_split(). Why not fix it at where the ICE occurs? It is just the wrong expectation from function dwarf2out_var_location(). Why not just look forward further if the 'prev'is not what we want? I like to add this code before gcc_assert() to fix this issue: while(prev && !CALL_P(prev) && !(GET_CODE (PATTERN (prev)) == SEQUENCE && CALL_P (XVECEXP (PATTERN (prev), 0, 0)))){ gcc_assert(NONJUMP_INSN_P (prev)); prev = prev_real_insn (prev); }