On 2019-05-20 9:58 p.m., Hans-Peter Nilsson wrote:
I was looking into why I couldn't trivially move cris-elf to
"use init_array". It appeared that it wasn't the hooks into
that machinery that went wrong, but that a compiler bug is
plaguing __libc_init_array. It's been there since at least
4.7-era, hiding under the covers of the __init_array being empty
(everything being in .init).
Looking into it, it seems that IRA is treating this insn:
(call_insn 16 14 17 4 (parallel [
(call (mem:QI (mem/f:SI (post_inc:SI (reg:SI 27 [ ivtmp.7 ])) [1
MEM[base: _8, offset: 0B]+0 S4 A8]) [0 *_1 S1 A8])
(const_int 0 [0]))
(clobber (reg:SI 16 srp))
]) "t.c":7:5 220 {*expanded_call_non_v32}
(expr_list:REG_INC (reg:SI 27 [ ivtmp.7 ])
(expr_list:REG_CALL_DECL (nil)
(nil)))
(nil))
...as if the read-part of the post-increment happens before the
call, and the write-part to happen after the call, supposedly
with the value magically kept unclobbered or treated as some
kind of return-value. Looking around, it seems only the VAX
port would also be affected; grepping around I see no other port
having a call instruction capable of loading a value indirectly,
with a side-effect.
Now, I'm ok with deliberately forbidding autoinc and other
side-effect constructs on call insns during register allocation
and will do the documentation legwork of that part (and the more
involved target-fixing) if there's consensus for that, but it
seems that for IRA the fix is as simple as follows.
LRA seems to have the same issue, but I have no way to reproduce
it there; I'll just have to watch out when I move the port to
LRA. I don't know if reload is affected, but I believe
autoincdec doesn't count as an output reload. (Please correct
me if I'm wrong! An output-reload on a call insn is not
allowed, says a comment in find_reloads, but AFAICS that's still
undocumented.)
Probably this case was a reason to prohibit output reloads for calls.
So, is this ok? Regtested on cris-elf and x86_64-linux-gnu
(though the latter uses LRA). Note that this does *not* cause
the return-value for f3 and f4 in the test-case to be allocated
a call-saved register after the value.
Yes, the patch is ok to commit. Thank you for working on the problem.
It is hard to reproduce the same problem in LRA as LRA mostly follows
IRA decisions.
I'll probably do the analogous patch for LRA on this week.
gcc:
* lra-lives.c (process_bb_node_lives): Consider defs
It should be ira-lives.c here.
for a call insn to be die before the call, not after.