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;
> +}
> 

Reply via email to