Fix PR c/7153

Eric Botcazou ebotcazou@libertysurf.fr
Sat Jun 29 15:36:00 GMT 2002


Hello,

It should be PR optimization/7153.

GCC emits 'movsbl %ebx, %eax' (sign-extend %ebx to %eax) which is an illegal
i386 instruction because sizeof(%ebx) == sizeof(%eax). It should have been
'movsbl %bl, %eax' where %bl is the lowpart 8-bit subreg of %ebx.

The problem originates in the register movement optimization pass: it turns


;; Start of basic block 1, registers live: 6 [bp] 7 [sp] 16 [] 20 [frame] 62
(note 53 16 21 [bb 1] NOTE_INSN_BASIC_BLOCK)

(insn 21 53 27 (set (reg/v:QI 61)
        (mem:QI (reg/v/f:SI 62) [0 S1 A8])) 60 {*movqi_1} (nil)
    (expr_list:REG_DEAD (reg/v/f:SI 62)
        (nil)))

(call_insn 27 21 30 (call (mem:QI (symbol_ref:SI ("g")) [0 S1 A8])
        (const_int 0 [0x0])) -1 (nil)
    (nil)
    (nil))

(insn 30 27 69 (set (reg:SI 66)
        (sign_extend:SI (reg/v:QI 61))) 126 {extendqisi2} (insn_list 21 (nil))
    (expr_list:REG_DEAD (reg/v:QI 61)
        (nil)))

(jump_insn 69 30 70 (set (pc)
        (label_ref 32)) -1 (nil)
    (nil))
;; End of basic block 1, registers live:
 6 [bp] 7 [sp] 16 [] 20 [frame] 66

(barrier 70 69 72)

;; Start of basic block 2, registers live: 6 [bp] 7 [sp] 16 [] 20 [frame] 61
(code_label 72 70 71 3 "" "" [1 uses])

(note 71 72 65 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 65 71 32 (set (reg:SI 66)
        (sign_extend:SI (reg/v:QI 61))) 126 {extendqisi2} (nil)
    (expr_list:REG_DEAD (reg/v:QI 61)
        (nil)))
;; End of basic block 2, registers live:
 6 [bp] 7 [sp] 16 [] 20 [frame] 66


into


;; Start of basic block 1, registers live: 6 [bp] 7 [sp] 16 [] 20 [frame] 62
(note 53 16 21 [bb 1] NOTE_INSN_BASIC_BLOCK)

(insn 21 53 27 (set (reg/v:SI 61)
        (sign_extend:SI (mem:QI (reg/v/f:SI 62) [0 S1 A8]))) 126 {extendqisi2} (nil)
    (expr_list:REG_DEAD (reg/v/f:SI 62)
        (nil)))

(call_insn 27 21 30 (call (mem:QI (symbol_ref:SI ("g")) [0 S1 A8])
        (const_int 0 [0x0])) 510 {*call_0} (nil)
    (nil)
    (nil))

(insn 30 27 69 (set (reg:SI 66)
        (reg/v:SI 61)) 45 {*movsi_1} (insn_list 21 (nil))
    (expr_list:REG_DEAD (reg/v:SI 61)
        (nil)))

(jump_insn 69 30 70 (set (pc)
        (label_ref 32)) 502 {jump} (nil)
    (nil))
;; End of basic block 1, registers live:
 6 [bp] 7 [sp] 16 [] 20 [frame] 66

(barrier 70 69 72)

;; Start of basic block 2, registers live: 6 [bp] 7 [sp] 16 [] 20 [frame] 61
(code_label 72 70 71 3 "" "" [1 uses])

(note 71 72 65 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 65 71 32 (set (reg:SI 66)
        (sign_extend:SI (reg/v:SI 61))) 126 {extendqisi2} (nil)
    (expr_list:REG_DEAD (reg/v:SI 61)
        (nil)))
;; End of basic block 2, registers live:
 6 [bp] 7 [sp] 16 [] 20 [frame] 66


Note the bogus modified insn 65: extendqisi2 is applied to a SI register.

The culprit is regmove.c:optimize_reg_copy_3 which thinks that it can safely
combine the sign_extend of insn 30 with the load of insn 21. More precisely,
it thinks that the lifetime of reg 61 is 21->30 and does a mere PUT_MODE()
on (reg/v:QI 61), then scans 27->30 to correct the chilling effects this
could have had. But it forgets insn 65.

The very reason is that the function implicitly expects pseudo-registers to
be set before being accessed, which is not the case for reg 61 on the
BB0 -> BB2 path. So it doesn't detect the use of reg 61 in insn 65.

The proposed fix is to disallow this optimization when the lifetime of the
register is not limited to a single BB, which was the original intent of the
code. Allowing it in that situation would lead to walk down the chain of
insns to detect every use of the reg.

Bootstrapped/regtested (C/C++) on k6-pc-linux-gnu (gcc-3_1-branch).


2002-06-29  Eric Botcazou  <ebotcazou@multimania.com>

 PR optimization/7153
 * regmove.c (optimize_reg_copy_3): Don't optimize if the register
 dies in more than one insn.


--
Eric Botcazou
ebotcazou@multimania.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pr7153.diff
Type: application/octet-stream
Size: 408 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20020629/6a45eecc/attachment.obj>


More information about the Gcc-patches mailing list