Hello all, I tracing bug in GCC for Coldfire target, but I end in dead water and I need some help from real experts :). Both gcc 4.4 and 4.3 have same problem
GCC miscompile this small test case. //----------------------------------------------------------------- //m68k-elf-gcc -save-temps -da -fdump-tree-all -fdump-ipa-all -c test.c -o test.o void dummy(char *arg); static void test1(void) { char tmp[2] = "0"; } void test2(void) { dummy("0"); } //------------------------------------------------------------------ The file is compiled to: #NO_APP .file "test.c" .section .rodata .LC0: .string "0" .text .align 2 .type test1, @function test1: link.w %fp,#-4 lea .LC0,%a0 move.w (%a0),-2(%fp) unlk %fp rts .size test1, .-test1 .align 2 .globl test2 .type test2, @function test2: link.w %fp,#0 move.l %a0,-(%sp) <-- note: a0 is used uninitialized here jsr dummy addq.l #4,%sp unlk %fp rts .size test2, .-test2 .ident "GCC: (GNU) 4.4.0 20081031 (experimental)" And relevant part of RTL after expand pass: ;; Function test1 (test1) ;; Generating RTL for gimple basic block 2 ;; tmp ={v} "0"; (insn 5 4 0 test.c:8 (set (mem/s/c:HI (plus:SI (reg/f:SI 26 virtual-stack-vars) (const_int -2 [0xfffffffe])) [0 tmp+0 S2 A16]) (mem/s:HI (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>) [0 S2 A8])) -1 (nil)) ;; Function test2 (test2) ;; Generating RTL for gimple basic block 2 ;; dummy (&"0"[0]); <--- !!!! bad insn here ----- (insn 5 4 6 test.c:15 (set (mem/f/i:SI (pre_dec:SI (reg/f:SI 15 %sp)) [0 S4 A16]) (reg:SI 8 %a0)) -1 (nil)) <------------------------------ (call_insn 6 5 7 test.c:15 (call (mem:QI (symbol_ref:SI ("dummy") [flags 0x41] <function_decl 0x7fdd4580 dummy>) [0 S1 A8]) (const_int 4 [0x4])) -1 (nil) (nil)) (insn 7 6 0 test.c:15 (set (reg/f:SI 15 %sp) (plus:SI (reg/f:SI 15 %sp) (const_int 4 [0x4]))) -1 (nil)) After some debugging, I found cause of this bug, but proper solution is not clear for me. When "char tmp[2] = "0";" is compiled, the function "output_constant_def" is called and proper insn is stored into cache: (gdb) call debug_rtx(desc->rtl) (mem/s:HI (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>) [0 S2 A8]) Later, in ira pass, this insn is spitted to this (Coldfire has no memory to memory move): Reloads for insn # 5 Reload 0: reload_in (SI) = (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>) ADDR_REGS, RELOAD_FOR_INPUT (opnum = 1), inc by 2 reload_in_reg: (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>) reload_reg_rtx: (reg:SI 8 %a0) ... (note 2 3 14 2 NOTE_INSN_FUNCTION_BEG) (insn 14 2 5 2 test.c:7 (set (reg:SI 8 %a0) (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>)) 38 {*movsi_cf} (nil)) (insn 5 14 13 2 test.c:7 (set (mem/s/c:HI (plus:SI (reg/f:SI 14 %a6) (const_int -2 [0xfffffffe])) [0 tmp+0 S2 A16]) (mem/s:HI (reg:SI 8 %a0) [0 S2 A8])) 41 {*m68k.md:906} (nil)) ;; End of basic block 2 -> ( 1) ;; lr out 14 [%a6] 15 [%sp] 24 [%argptr] The first insn is newly allocated, but second one overwrites original insn. >From local point of view, this is still OK, but this corrupt the >output_constant_def cache (cache holds pointer to overwritten insn. So every next access to "0" constat returns (mem/s:HI (reg:SI 8 %a0) [0 S2 A8])) 41 {*m68k.md:906} (nil)) and not (symbol_ref/f:SI ("*.LC0") [flags 0x2] <string_cst 0x7fdf7700>)) 38 {*movsi_cf} (nil)) But how to fix this? By my mean, the cache must hold own immutable copy of insn. But im not gcc expert, so I need help with proper solution. Is this patch OK? Any other solution? --- varasm.c.orig 2008-11-14 18:04:27.693643900 +0100 +++ varasm.c 2008-11-14 17:58:06.522748300 +0100 @@ -3245,7 +3245,7 @@ } maybe_output_constant_def_contents (desc, defer); - return desc->rtl; + return copy_rtx (desc->rtl); } /* Subroutine of output_constant_def: Decide whether or not we need to --------------------------------------------- Moreover, this can be common problem on more places (at least at gen_rtx_CONST_INT). Ohh, and sorry for my english. Many thanks Michal Meloun