Iain Buclaw via Gcc-patches <gcc-patches@gcc.gnu.org> writes: > Hi, > > 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 [0]) > ] UNSPEC_TP) > (reg/f:DI 6 bp [90])) > > 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? > > Regards > Iain > > --- > gcc/ChangeLog: > > 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. > > gcc/testsuite/ChangeLog: > > 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? Thanks, Richard