On Fri, 8 Nov 2024, Jakub Jelinek wrote:

> Hi!
> 
> My https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668065.html
> patch regressed
> +FAIL: g++.dg/tm/pr45940-3.C  -std=gnu++11 (internal compiler error: in 
> create_tmp_var, at gimple-expr.cc:484)
> +FAIL: g++.dg/tm/pr45940-3.C  -std=gnu++11 (test for excess errors)
> +FAIL: g++.dg/tm/pr45940-3.C  -std=gnu++14 (internal compiler error: in 
> create_tmp_var, at gimple-expr.cc:484)
> +FAIL: g++.dg/tm/pr45940-3.C  -std=gnu++14 (test for excess errors)
> ...
> +FAIL: g++.dg/tm/pr45940-4.C  -std=gnu++26 (internal compiler error: in 
> create_tmp_var, at gimple-expr.cc:484)
> +FAIL: g++.dg/tm/pr45940-4.C  -std=gnu++26 (test for excess errors)
> +FAIL: g++.dg/tm/pr45940-4.C  -std=gnu++98 (internal compiler error: in 
> create_tmp_var, at gimple-expr.cc:484)
> +FAIL: g++.dg/tm/pr45940-4.C  -std=gnu++98 (test for excess errors)
> tests, but it turns out it is a preexisting bug.
> If I modify the pr45940-3.C testcase
> --- gcc/testsuite/g++.dg/tm/pr45940-3.C       2020-01-12 11:54:37.258400660 
> +0100
> +++ gcc/testsuite/g++.dg/tm/pr45940-3.C       2024-11-08 10:35:11.918390743 
> +0100
> @@ -16,6 +16,7 @@ class sp_counted_base
>  {
>  protected:
>      int use_count_;        // #shared
> +    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, 
> x, y, z, aa, ab, ac, ad, ae, af;
>  public:
>      __attribute__((transaction_safe))
>      virtual void dispose() = 0; // nothrow
> then it ICEs already on vanilla trunk.
> 
> The problem is that expand_assign_tm just wants to force it into
> TM memcpy argument, if is_gimple_reg (reg), then it creates a temporary,
> stores the value there and takes temporary address, otherwise it takes
> address of rhs.  That doesn't work if rhs is an empty CONSTRUCTOR with
> C++ non-POD type (TREE_ADDRESSABLE type), we ICE trying to create temporary,
> because we shouldn't be creating a temporary.
> Now before my patch with the CONSTRUCTOR only having a vtable pointer
> (64bit) and 32-bit field, we gimplified the zero initialization just
> as storing of 0s to the 2 fields, but as we are supposed to also clear
> padding bits, we now gimplify it as MEM[...] = {}; to make sure
> even the padding bits are cleared.  With the adjusted testcase,
> we gimplified it even before as MEM[...] = {}; because it was simply
> too large and clearing everything looked beneficial.
> 
> The following patch fixes this ICE by using TM memset, it is both
> wasteful to force zero constructor into a temporary just to TM memcpy
> it into the lhs, and in C++ cases like this invalid.
> 
> Ok for trunk if it passes bootstrap/regtest?

OK.

Richard.

> 2024-11-08  Jakub Jelinek  <ja...@redhat.com>
> 
>       * trans-mem.cc (expand_assign_tm): Don't take address
>       of empty CONSTRUCTOR, instead use BUILT_IN_TM_MEMSET
>       to clear lhs in that case.  Formatting fixes.
> 
> --- gcc/trans-mem.cc.jj       2024-10-25 10:00:29.527767013 +0200
> +++ gcc/trans-mem.cc  2024-11-08 09:55:08.963557301 +0100
> @@ -2442,26 +2442,33 @@ expand_assign_tm (struct tm_region *regi
>         gcall = gimple_build_assign (rtmp, rhs);
>         gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
>       }
> +      else if (TREE_CODE (rhs) == CONSTRUCTOR
> +            && CONSTRUCTOR_NELTS (rhs) == 0)
> +     {
> +       /* Don't take address of an empty CONSTRUCTOR, it might not
> +          work for C++ non-POD constructors at all and otherwise
> +          would be inefficient.  Use tm memset to clear lhs.  */
> +       gcc_assert (!load_p && store_p);
> +       rhs_addr = integer_zero_node;
> +     }
>        else
>       rhs_addr = gimplify_addr (gsi, rhs);
>  
>        // Choose the appropriate memory transfer function.
> -      if (load_p && store_p)
> -     {
> -       // ??? Figure out if there's any possible overlap between
> -       // the LHS and the RHS and if not, use MEMCPY.
> -       copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMMOVE);
> -     }
> +      if (store_p
> +       && TREE_CODE (rhs) == CONSTRUCTOR
> +       && CONSTRUCTOR_NELTS (rhs) == 0)
> +     copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMSET);
> +      else if (load_p && store_p)
> +     // ??? Figure out if there's any possible overlap between
> +     // the LHS and the RHS and if not, use MEMCPY.
> +     copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMMOVE);
>        else if (load_p)
> -     {
> -       // Note that the store is non-transactional and cannot overlap.
> -       copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RTWN);
> -     }
> +     // Note that the store is non-transactional and cannot overlap.
> +     copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RTWN);
>        else
> -     {
> -       // Note that the load is non-transactional and cannot overlap.
> -       copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RNWT);
> -     }
> +     // Note that the load is non-transactional and cannot overlap.
> +     copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RNWT);
>  
>        gcall = gimple_build_call (copy_fn, 3, lhs_addr, rhs_addr,
>                                TYPE_SIZE_UNIT (TREE_TYPE (lhs)));
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to