This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Bug with copyprop_hardreg_forward and shared RTX
- From: "Ulrich Weigand" <Ulrich dot Weigand at de dot ibm dot com>
- To: rth at redhat dot com
- Cc: gcc at gcc dot gnu dot org
- Date: Fri, 1 Mar 2002 16:58:53 +0100
- Subject: Bug with copyprop_hardreg_forward and shared RTX
Hello Richard,
when running a Linux kernel compiled with gcc 3.1, I've noticed an
intermittent bug with terminal echo handling that I've finally traced
to a routine from the TTY layer being miscompiled.
It looks like the bug is introduced by copyprop_hardreg_forward not
handling shared RTX correctly in certain cases:
Before reload, the code looks like this:
(insn 31 16 46 (set (reg:SI 52)
(mem/s:SI (plus:SI (reg/v/f:SI 42)
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])) 56 {*movsi} (insn_list 8 (nil))
(expr_list:REG_EQUIV (mem/s:SI (plus:SI (reg/v/f:SI 42)
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])
(nil)))
(insn 32 17 47 (parallel[
(set (reg:SI 53)
(xor:SI (reg:SI 52)
(const_int -1 [0xffffffffffffffff])))
(clobber (reg:CC 33 %cc))
] ) 202 {xorsi3} (insn_list 31 (nil))
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(nil)))
[snip]
(insn 40 35 50 (parallel[
(set (reg:SI 56)
(and:SI (reg:SI 56)
(reg:SI 52)))
(clobber (reg:CC 33 %cc))
] ) 164 {andsi3} (insn_list 37 (insn_list 31 (nil)))
(expr_list:REG_DEAD (reg:SI 52)
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(nil))))
Note that reg 52 is equivalent to a memory location, and is used twice.
Therefore, after reload, the uses of reg 52 are replaced by a *shared*
copy of this memory RTX:
(gdb) call debug_rtx (cfun->emit->x_regno_reg_rtx[52])
(mem/s:SI (plus:SI (reg/v/f:SI 6 %r6 [42])
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])
and the code looks now like this:
(insn 174 17 32 (set (reg:SI 9 %r9 [53])
(mem/s:SI (plus:SI (reg/v/f:SI 6 %r6 [42])
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])) 56 {*movsi} (nil)
(nil))
(insn 32 174 177 (parallel[
(set (reg:SI 9 %r9 [53])
(xor:SI (reg:SI 9 %r9 [53])
(mem/u/f:SI (symbol_ref/u:SI ("*.LC0")) [5 S4 A32])))
(clobber (reg:CC 33 %cc))
] ) 202 {xorsi3} (insn_list 31 (nil))
(nil))
[snip]
(insn 40 35 50 (parallel[
(set (reg:SI 4 %r4 [56])
(and:SI (reg:SI 4 %r4 [56])
(mem/s:SI (plus:SI (reg/v/f:SI 6 %r6 [42])
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])))
(clobber (reg:CC 33 %cc))
] ) 164 {andsi3} (insn_list 37 (insn_list 31 (nil)))
(nil))
Now copyprop_hardreg_forward decides to replace reg 6 in insn 174
by reg 4, which is completely correct at this point. However, because
the memory RTX is in fact shared between insns 174 and 40, this
replacement gets also done in insn 40, where is it obviously broken
as reg 4 was clobbered in the meantime.
insn 174: replaced reg 6 with 4
(insn 174 17 32 (set (reg:SI 9 %r9 [53])
(mem/s:SI (plus:SI (reg:SI 4 %r4 [42])
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])) 56 {*movsi} (nil)
(nil))
(insn 32 174 177 (parallel[
(set (reg:SI 9 %r9 [53])
(xor:SI (reg:SI 9 %r9 [53])
(mem/u/f:SI (symbol_ref/u:SI ("*.LC0")) [5 S4 A32])))
(clobber (reg:CC 33 %cc))
] ) 202 {xorsi3} (insn_list 174 (nil))
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(nil)))
[snip]
(insn 40 35 50 (parallel[
(set (reg:SI 4 %r4 [56])
(and:SI (reg:SI 4 %r4 [56])
(mem/s:SI (plus:SI (reg:SI 4 %r4 [42])
(const_int 4 [0x4])) [5 <variable>.c_oflag+0 S4 A32])))
(clobber (reg:CC 33 %cc))
] ) 164 {andsi3} (insn_list 37 (nil))
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(nil)))
Am I missing something here? How is this supposed to work?
Thanks,
Ulrich