[PATCH] PR target/96347: non-delegitimized UNSPEC UNSPEC_TP (19) found in variable location
Wed Aug 19 11:22:55 GMT 2020
Iain Buclaw via Gcc-patches <firstname.lastname@example.org> writes:
> On x86, a memory reference reference to a TLS address can be broken out
> and stored in a register, for instance:
> movq %fs:8+testYearsBC@tpoff, %rdx
> Subsequently becomes:
> pushq %rbp
> leaq 8+testYearsBC@tpoff, %rbp
> // later...
> movq %fs:0(%rbp), %rdx
> When it comes to representing this in Dwarf, mem_loc_descriptor is left
> with the following RTL, which ix86_delegitimize_tls_address is unable to
> handle as the symbol_ref has been swapped out with the temporary.
> (plus:DI (unspec:DI [
> (const_int 0 )
> ] UNSPEC_TP)
> (reg/f:DI 6 bp ))
> The UNSPEC_TP expression is checked, ix86_const_not_ok_for_debug_p
> returns false as it only lets through UNSPEC_GOTOFF, and finally
> const_ok_for_output is either not smart enough or does not have the
> information needed to recognize that UNSPEC_TP is a TLS UNSPEC that
> should be ignored. This results in informational warnings being fired
> under -fchecking.
> The entrypoint that triggers this warning to occur is that MEM codes are
> first lowered with mem_loc_descriptor, with tls_mem_loc_descriptor only
> being used if that failed. This patch switches that around so that TLS
> memory expressions first call tls_mem_loc_descriptor, and only use
> mem_loc_descriptor if that fails (which may result in UNSPEC warnings).
> Bootstrapped and regression tested on x86_64-linux-gnu, I do also have a
> sparc64-linux-gnu build at hand, but have not yet got the results to
> check for a before/after comparison.
> OK for mainline?
> PR target/96347
> * dwarf2out.c (is_tls_mem_loc): New.
> (mem_loc_descriptor): Call tls_mem_loc_descriptor on TLS memory
> expressions, fallback to mem_loc_descriptor if unsuccessful.
> (loc_descriptor): Likewise.
> PR target/96347
> * g++.dg/other/pr96347.C: New test.
> gcc/dwarf2out.c | 30 ++++++++++----
> gcc/testsuite/g++.dg/other/pr96347.C | 61 ++++++++++++++++++++++++++++
> 2 files changed, 84 insertions(+), 7 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/other/pr96347.C
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 9deca031fc2..093ceb23c7a 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -14435,6 +14435,20 @@ is_based_loc (const_rtx rtl)
> && CONST_INT_P (XEXP (rtl, 1)))));
> +/* Return true if this MEM expression is for a TLS variable. */
> +static bool
> +is_tls_mem_loc (rtx mem)
> + tree base;
> + if (MEM_EXPR (mem) == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
> + return false;
> + base = get_base_address (MEM_EXPR (mem));
> + return (base && VAR_P (base) && DECL_THREAD_LOCAL_P (base));
> /* Try to handle TLS MEMs, for which mem_loc_descriptor on XEXP (mem, 0)
> failed. */
> @@ -15671,11 +15685,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
> return mem_loc_result;
> - mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0),
> - get_address_mode (rtl), mode,
> - VAR_INIT_STATUS_INITIALIZED);
> - if (mem_loc_result == NULL)
> + if (is_tls_mem_loc (rtl))
> mem_loc_result = tls_mem_loc_descriptor (rtl);
> + if (mem_loc_result == NULL)
Is the is_tls_mem_loc part necessary? It looks like it's just
repeating the first part of tls_mem_loc_descriptor, and so we
could call that unconditionally instead.
I guess this raises the question: if we swapping the order for
TLS so that MEM_EXPR trumps the MEM address, why shouldn't we take
that approach more generally? I.e. is there any reason to look at
the MEM_EXPR only when DECL_THREAD_LOCAL_P is true for the base address,
rather than for all symbolic base addresses?
More information about the Gcc-patches