Ping. Though I wonder if there's any point adding a check at all over just swapping the order that mem_loc_descriptor and tls_mem_loc_descriptor are called in.
Iain. On 07/08/2020 13:33, Iain Buclaw wrote: > 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) > + 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_a <scalar_int_mode> (mode, &int_mode) > @@ -16631,10 +16646,11 @@ loc_descriptor (rtx rtl, machine_mode mode, > break; > > case MEM: > - loc_result = mem_loc_descriptor (XEXP (rtl, 0), get_address_mode (rtl), > - GET_MODE (rtl), initialized); > - if (loc_result == NULL) > + if (is_tls_mem_loc (rtl)) > loc_result = tls_mem_loc_descriptor (rtl); > + if (loc_result == NULL) > + loc_result = mem_loc_descriptor (XEXP (rtl, 0), get_address_mode (rtl), > + GET_MODE (rtl), initialized); > if (loc_result == NULL) > { > rtx new_rtl = avoid_constant_pool_reference (rtl); > diff --git a/gcc/testsuite/g++.dg/other/pr96347.C > b/gcc/testsuite/g++.dg/other/pr96347.C > new file mode 100644 > index 00000000000..414d10c73de > --- /dev/null > +++ b/gcc/testsuite/g++.dg/other/pr96347.C > @@ -0,0 +1,61 @@ > +/* { dg-do compile { target c++11 } } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-O2 -g -fchecking" } */ > + > +struct DArray > +{ > + __SIZE_TYPE__ length; > + int *ptr; > +}; > + > +__thread DArray testYearsBC; > + > +struct FilterResult > +{ > + DArray input; > + bool primed; > + > + static FilterResult Dthis (FilterResult &pthis, DArray r) > + { > + pthis.input = r; > + return pthis; > + } > + > + int front (void) > + { > + if (input.length == 0) > + __builtin_abort (); > + return input.ptr[0]; > + } > +}; > + > +FilterResult filter (DArray range) > +{ > + FilterResult retval; > + FilterResult::Dthis (retval, range); > + return retval; > +} > + > +DArray chain (DArray rs) > +{ > + return rs; > +} > + > +struct SysTime > +{ > + static SysTime Dthis (int); > +}; > + > +int main (void) > +{ > + while (1) > + { > + FilterResult val; > + __builtin_memset (&val, 0, sizeof (FilterResult)); > + val = filter (chain (testYearsBC)); > + int year = val.front (); > + (void)year; > + SysTime::Dthis (0); > + } > + return 0; > +} >