https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66796

--- Comment #4 from Jeffrey A. Law <law at redhat dot com> ---
It's a difference in linux vs hpux, specifically the former does not use space
registers, which gives us a flat address space (rather than segmented) and
allows the compiler to generate indexed addressing modes more aggressively.

This shows up in fwprop1 where we propagate an address computation into a load.
 However, the address computation is still needed for the store.   so the RTL
after fwprop1 on linux looks something like this:

(insn 10 9 11 2 (set (reg:SI 111 [ D.1438 ])
        (ashift:SI (reg:SI 110 [ __word ])
            (const_int 2 [0x2]))) 171 {*pa.md:6303}
     (expr_list:REG_DEAD (reg:SI 110 [ __word ])
        (nil)))

(insn 11 10 12 2 (set (reg/f:SI 104 [ D.1439 ])
        (plus:SI (reg/v/f:SI 106 [ __set ])
            (reg:SI 111 [ D.1438 ]))) 114 {addsi3}
     (expr_list:REG_DEAD (reg:SI 111 [ D.1438 ])
        (expr_list:REG_DEAD (reg/v/f:SI 106 [ __set ])
            (nil))))

(insn 12 11 13 2 (set (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ])
        (mem:SI (plus:SI (reg/v/f:SI 106 [ __set ])
                (reg:SI 111 [ D.1438 ])) [2 MEM[(struct __sigset_t *)_14]+0 S4
A32])) j.c:15 40 {*pa.md:2204}
     (nil))

(insn 13 12 14 2 (set (reg:SI 101 [ D.1437 ])
        (ior:SI (reg/v:SI 108 [ __stuff ])
            (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ]))) j.c:15 132
{*pa.md:5741}
     (expr_list:REG_DEAD (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ])
        (expr_list:REG_DEAD (reg/v:SI 108 [ __stuff ])
            (nil))))

(insn 14 13 19 2 (set (mem:SI (reg/f:SI 104 [ D.1439 ]) [2 MEM[(struct
__sigset_t *)_14]+0 S4 A32])
        (reg:SI 101 [ D.1437 ])) j.c:15 40 {*pa.md:2204}
     (expr_list:REG_DEAD (reg/f:SI 104 [ D.1439 ])
        (nil)))

Ignore the REG_DEAD note for reg:111 on insn 11.  It's out of date and will get
updated via the usual mechanisms (reg:111 actually dies at insn 12 after fwprop
has done its job).

Note how reg111 now has two uses.  One in insn 11 the other in insn 12.  That
prevents combine from creating the natural shadd at insn 11.

On the hpux configurations which use space registers and thus have to be more
conservative about the generation of indexed addressing modes, fwprop does
nothing and we have this going into combine:

(insn 10 9 11 2 (set (reg:SI 111 [ D.1430 ])
        (ashift:SI (reg:SI 110 [ __word ])
            (const_int 2 [0x2]))) 171 {*pa.md:6303}
     (expr_list:REG_DEAD (reg:SI 110 [ __word ])
        (nil)))
(insn 11 10 12 2 (set (reg/f:SI 104 [ D.1431 ])
        (plus:SI (reg/v/f:SI 106 [ __set ])
            (reg:SI 111 [ D.1430 ]))) 114 {addsi3}
     (expr_list:REG_DEAD (reg:SI 111 [ D.1430 ])
        (expr_list:REG_DEAD (reg/v/f:SI 106 [ __set ])
            (nil))))
(insn 12 11 13 2 (set (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ])
        (mem:SI (reg/f:SI 104 [ D.1431 ]) [2 MEM[(struct __sigset_t *)_14]+0 S4
A32])) j.c:15 40 {*pa.md:2204}
     (nil))
(insn 13 12 14 2 (set (reg:SI 101 [ D.1429 ])
        (ior:SI (reg/v:SI 108 [ __stuff ])
            (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ]))) j.c:15 132
{*pa.md:5741}
     (expr_list:REG_DEAD (reg:SI 112 [ MEM[(struct __sigset_t *)_14] ])
        (expr_list:REG_DEAD (reg/v:SI 108 [ __stuff ])
            (nil))))
(insn 14 13 19 2 (set (mem:SI (reg/f:SI 104 [ D.1431 ]) [2 MEM[(struct
__sigset_t *)_14]+0 S4 A32])
        (reg:SI 101 [ D.1429 ])) j.c:15 40 {*pa.md:2204}
     (expr_list:REG_DEAD (reg/f:SI 104 [ D.1431 ])
        (nil)))

Note there's a single use of reg 111 and combine can trivially combine insns 10
and 11 into a shadd without needing to preserve the value of reg 111.

Thus we get the shadd on hpux, but not on linux and thus the failure on linux.

The easiest thing to do is change the testsuite slightly so that we have a
single memory reference rather than a read-modify-write.  That doesn't
compromise the test and allows it to pass on hpux and linux.  I'll take care of
that momentarily.

Reply via email to