Fix REG_ARGS_SIZE handling when pushing TLS addresses
commitd7ea903985b3a4ce3f8645d86b258cac1b3abf26
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jan 2018 19:14:43 +0000 (2 19:14 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jan 2018 19:14:43 +0000 (2 19:14 +0000)
tree9b53d3cd8885f377cf6981cd74d08f43baa4c258
parent0f78b37a1a502b2f2ce4ab2a8aee0d307e3785a6
Fix REG_ARGS_SIZE handling when pushing TLS addresses

The new assert in add_args_size_note triggered for gcc.dg/tls/opt-3.c
and others on m68k.  This looks like a pre-existing bug: if we pushed
a value that needs a call to something like __tls_get_addr, we ended
up with two different REG_ARGS_SIZE notes on the same instruction.

It seems to be OK for emit_single_push_insn to push something that
needs a call to __tls_get_addr:

      /* We have to allow non-call_pop patterns for the case
 of emit_single_push_insn of a TLS address.  */
      if (GET_CODE (pat) != PARALLEL)
return 0;

so I think the bug is in the way this is handled rather than the fact
that it occurs at all.

If we're pushing a value X that needs a call C to calculate, we'll
add REG_ARGS_SIZE notes to the pushes and pops for C as part of the
call sequence.  Then emit_single_push_insn calls fixup_args_size_notes
on the whole push sequence (the calculation of X, including C,
and the push of X itself).  This is where the double notes came from.
But emit_single_push_insn_1 adjusted stack_pointer_delta *before* the
push, so the notes added for C were relative to the situation after
the future push of X rather than before it.

Presumably this didn't matter in practice because the note added
second tended to trump the note added first.  But code is allowed to
walk REG_NOTES without having to disregard secondary notes.

2018-01-02  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* expr.c (fixup_args_size_notes): Check that any existing
REG_ARGS_SIZE notes are correct, and don't try to re-add them.
(emit_single_push_insn_1): Move stack_pointer_delta adjustment to...
(emit_single_push_insn): ...here.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256105 138bc75d-0d04-0410-961f-82ee72b054a4
gcc/ChangeLog
gcc/expr.c