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



Reply via email to