On 03/14/2017 05:22 PM, Bernd Schmidt wrote:
This triggered a kernel miscompilation with an old (4.8 I think) aarch64
toolchain.

Here's the reloads for the insn where things go wrong:

Reloads for insn # 210
Reload 0: reload_in (DI) = (reg/v/f:DI 80 [ pgdata ])
        GENERAL_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 0)
        reload_in_reg: (reg/v/f:DI 80 [ pgdata ])
        reload_reg_rtx: (reg:DI 5 x5)
Reload 1: reload_in (DI) = (plus:DI (reg/v/f:DI 80 [ pgdata ])
                                                    (const_int 7172
[0x1c04]))
        GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 0), inc by 2
        reload_in_reg: (plus:DI (reg/v/f:DI 80 [ pgdata ])
                                                    (const_int 7172
[0x1c04]))
        reload_reg_rtx: (reg:DI 5 x5)

Note how the input and input_address reloads use the same reload
register. This is intended as the two categories aren't supposed to
conflict. The problem is that reload 1 is a PLUS expression, and when
reloading these, gen_reload may have to resort to tricks, such as
loading one of the operands (the constant 7172) into the reload
register, and then adding the other operand to it. In effect that's an
earlyclobber of the reload register, and that is not represented in the
for_input/for_input_address classification.

Most likely we haven't tripped over this earlier because on other
machines the addition can be done in a single insn.

The following fixes this by using RELOAD_OTHER in this case. This is
pessimistic, but at that point I don't think we can really know what
gen_reload will have to do. Bootstrapped and tested on x86_64-linux on
the 4.7 branch - that's the best method of testing that I can think of
(but I think I'll also run some c6x tests with trunk). If no one
objects, I'll check this in soonish.


Bernd

rld-other.diff


        * reload.c (find_reloads): When reloading a nonoffsettable address,
        use RELOAD_OTHER for it and its address reloads.
I've already got state on this...  OK.

jeff

Reply via email to