I'm seeing miscompilation of newlib's memcmp() for my 16-bit ix86 port. The
REG_RETVAL and REG_LIBCALL notes seem to play an important part in the
failure. From the first subreg dump:
;; Function memcmp (memcmp)
; Splitting reg 73 -> 89 90
; Splitting reg 74 -> 91 92
; Splitting reg 75 -> 93 94
[cut]
(insn 58 151 59 3 memcmp.c:81 (set (reg:HI 91)
(const_int 3 [0x3])) 23 {*movhi} (nil)
(nil))
(insn 59 58 63 3 memcmp.c:81 (set (reg:HI 92 [+2 ])
(const_int 0 [0x0])) 23 {*movhi} (nil)
(nil))
(insn 63 59 152 3 memcmp.c:81 (clobber (reg:HI 93)) -1 (nil)
(insn_list:REG_LIBCALL 62 (nil)))
(insn 152 63 61 3 memcmp.c:81 (clobber (reg:HI 94 [+2 ])) -1 (nil)
(nil))
(insn 61 152 62 3 memcmp.c:81 (parallel [
(set (reg:HI 93)
(and:HI (reg:HI 89)
(reg:HI 91)))
(clobber (reg:CC 13 cc))
]) 120 {*andhi3} (nil)
(nil))
(insn 62 61 64 3 memcmp.c:81 (parallel [
(set (reg:HI 94 [+2 ])
(and:HI (reg:HI 90 [+2 ])
(reg:HI 92 [+2 ])))
(clobber (reg:CC 13 cc))
]) 120 {*andhi3} (nil)
(insn_list:REG_RETVAL 63 (nil)))
(insn 64 62 65 3 memcmp.c:81 (set (reg:HI 76)
(reg:HI 93)) 23 {*movhi} (nil)
(nil))
(insn 65 64 66 3 memcmp.c:81 (parallel [
(set (reg:HI 76)
(ior:HI (reg:HI 76)
(reg:HI 94 [+2 ])))
(clobber (reg:CC 13 cc))
]) 122 {*iorhi3} (nil)
(nil))
(insn 66 65 67 3 memcmp.c:81 (set (reg:CC 13 cc)
(compare:CC (reg:HI 76)
(const_int 0 [0x0]))) 481 {*cmphi_const0_cc} (nil)
(nil))
CSE comes along, notices that insn 62 just sets reg 94 to zero. Reg 94,
btw, isn't used after insn 65.
;; Function memcmp (memcmp)
[cut]
(insn 58 151 59 3 memcmp.c:81 (set (reg:HI 91)
(const_int 3 [0x3])) 23 {*movhi} (nil)
(nil))
(insn 59 58 63 3 memcmp.c:81 (set (reg:HI 92 [+2 ])
(const_int 0 [0x0])) 23 {*movhi} (nil)
(nil))
(insn 63 59 152 3 memcmp.c:81 (clobber (reg:HI 93)) -1 (nil)
(insn_list:REG_LIBCALL 62 (nil)))
(insn 152 63 61 3 memcmp.c:81 (clobber (reg:HI 94 [+2 ])) -1 (nil)
(nil))
(insn 61 152 62 3 memcmp.c:81 (parallel [
(set (reg:HI 93)
(and:HI (reg:HI 89)
(reg:HI 91)))
(clobber (reg:CC 13 cc))
]) 120 {*andhi3} (nil)
(nil))
(insn 62 61 64 3 memcmp.c:81 (set (reg:HI 94 [+2 ])
(reg:HI 92 [+2 ])) 23 {*movhi} (nil)
(expr_list:REG_EQUAL (const_int 0 [0x0])
(insn_list:REG_RETVAL 63 (nil))))
(insn 64 62 65 3 memcmp.c:81 (set (reg:HI 76)
(reg:HI 93)) 23 {*movhi} (nil)
(nil))
(insn 65 64 66 3 memcmp.c:81 (set (reg:HI 76)
(reg:HI 93)) 23 {*movhi} (nil)
(nil))
(insn 66 65 67 3 memcmp.c:81 (set (reg:CC 13 cc)
(compare:CC (reg:HI 93)
(const_int 0 [0x0]))) 481 {*cmphi_const0_cc} (nil)
(nil))
Notice that we now have both a REG_EQUAL and a REG_RETVAL note on insn
62.
It isn't until the loop2_done dump that the problem shows up.
delete_trivially_dead_insns() is called. It calls dead_libcall_p() on insn
62 and seeing both the REQ_EQUAL and the REG_RETVAL note and successfully
replacing reg 92 with const_int 0, determines that the while libcall
sequence 63-152-61-62 is dead and can be deleted, without ever checking
insns 63, 152 or 61 for liveness. The result is disaster:
;; Function memcmp (memcmp)
[cut]
Register 91 used 1 times across 0 insns; set 1 time; dies in 0 places.
Register 92 used 1 times across 0 insns; set 1 time; dies in 0 places.
Register 95 used 1 times across 0 insns; set 1 time; dies in 0 places.
Register 96 used 1 times across 0 insns; set 1 time; dies in 0 places.
[cut - why is register 93 not listed?]
(insn 60 56 151 3 memcmp.c:81 (clobber (reg:HI 91)) -1 (nil)
(nil))
(insn 151 60 66 3 memcmp.c:81 (clobber (reg:HI 92 [+2 ])) -1 (nil)
(nil))
(insn 66 151 67 3 memcmp.c:81 (set (reg:CC 13 cc)
(compare:CC (reg:HI 93)
(const_int 0 [0x0]))) 481 {*cmphi_const0_cc} (nil)
(nil))
(jump_insn 67 66 68 3 memcmp.c:81 (set (pc)
(if_then_else (ne (reg:CC 13 cc)
(const_int 0 [0x0]))
(label_ref 93)
(pc))) 561 {*bne_cc} (nil)
(expr_list:REG_BR_PROB (const_int 5000 [0x1388])
(nil)))
--
Rask Ingemann Lambertsen