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

Reply via email to