On Thu, 13 Mar 2025, Jakub Jelinek wrote:

> Hi!
> 
> On Wed, Mar 12, 2025 at 02:01:14PM +0100, Richard Biener wrote:
> > On Wed, 12 Mar 2025, Jakub Jelinek wrote:
> > 
> > > On Tue, Mar 11, 2025 at 12:13:13PM +0100, Richard Biener wrote:
> > > > On Tue, 11 Mar 2025, Jakub Jelinek wrote:
> > > > 
> > > > > On Tue, Mar 11, 2025 at 10:18:18AM +0100, Richard Biener wrote:
> > > > > > I think the patch as-is is more robust, but still - ugh ... I wonder
> > > > > > whether we can instead avoid introducing the COMPLEX_EXPR at all
> > > > > > at -O0?
> > > > > 
> > > > > Can we set DECL_NOT_GIMPLE_REG_P at -O0 during gimplification (where
> > > > > we've already handled some uses/setters of it), at least when
> > > > > gimplify_modify_expr_complex_part sees {REAL,IMAG}PART_EXPR on
> > > > > {VAR,PARM,RESULT}_DECL?
> > > > 
> > > > Yes, that should work for LHS __real / __imag.
> > > 
> > > Unfortunately it doesn't.
> > > 
> > > Although successfully bootstrapped on x86_64-linux and i686-linux,
> > > it caused g++.dg/cpp1z/decomp2.C, g++.dg/torture/pr109262.C and
> > > g++.dg/torture/pr88149.C regressions.
> > > 
> > > Minimal testcase is -O0:
> > > void
> > > foo (float x, float y)
> > > {
> > >   __complex__ float z = x + y * 1.0fi;
> > >   __real__ z = 1.0f;
> > > }
> > > which ICEs with
> > > pr88149.c: In function ‘foo’:
> > > pr88149.c:2:1: error: non-register as LHS of binary operation
> > >     2 | foo (float x, float y)
> > >       | ^~~
> > > z = COMPLEX_EXPR <_2, y.0>;
> > > pr88149.c:2:1: internal compiler error: ‘verify_gimple’ failed
> > > When the initialization is being gimplified, z is still
> > > not DECL_NOT_GIMPLE_REG_P and so is_gimple_reg is true for it and
> > > so it gimplifies it as
> > >   z = COMPLEX_EXPR <_2, y.0>;
> > > later, instead of building
> > >   _3 = IMAGPART_EXPR <z>;
> > >   z = COMPLEX_EXPR <1.0e+0, _3>;
> > > like before, the patch forces z to be not a gimple reg and uses
> > >   REALPART_EXPR <z> = 1.0e+0;
> > > but it is too late, nothing fixes up the gimplification of the 
> > > COMPLEX_EXPR
> > > anymore.
> > 
> > Ah, yeah - setting DECL_NOT_GIMPLE_REG_P "after the fact" doesn't work.
> > 
> > > So, I think we'd really need to do it the old way with adjusted naming
> > > of the flag, so assume for all non-addressable
> > > VAR_DECLs/PARM_DECLs/RESULT_DECLs with COMPLEX_TYPE if (!optimize) they
> > > are DECL_NOT_GIMPLE_REG_P (perhaps with the exception of
> > > get_internal_tmp_var), and at some point (what) if at all optimize that
> > > away if the partial accesses aren't done.
> > 
> > We could of course do that in is_gimple_reg (), but I'm not sure if
> > all places that would need to check do so.  Alternatively gimplify
> > 
> > __real x = ..
> > 
> > into
> > 
> > tem[DECL_NOT_GIMPLE_REG_P] = x;
> > __real tem = ...;
> > x = tem;
> 
> We can't do that, that again causes the undesirable copying of often
> uninitialized part(s).
> 
> > when 'x' is a is_gimple_reg?  Of course for -O0 this would be quite bad.
> > Likewise for your idea - where would we do this optimization when not
> > optimizing?
> > 
> > So it would need to be the frontend(s) setting DECL_NOT_GIMPLE_REG_P
> > when producing lvalue __real/__imag accesses?
> 
> The following patch sets it in the FEs during genericization.
> I think Fortran doesn't have a way to modify just real or just complex
> part separately.
> 
> In short, this patch is for code like
>         _ComplexT __t;
>         __real__ __t = __z.real();
>         __imag__ __t = __z.imag();
>         _M_value *= __t;
>         return *this;
> at -O0 which used to appear widely even in libstdc++ before GCC 9
> and happens in real-world code.  At -O0 for debug info reasons (see
> PR119190) we don't want to aggressively DCE statements and when we
> since r0-100845 try to rewrite vars with COMPLEX_TYPE into SSA form
> aggressively, the above results in copying of uninitialized data
> when expanding COMPLEX_EXPRs added so that the vars can be in SSA form.
> The patch detects during genericization the partial initialization and
> doesn't rewrite such vars to SSA at -O0.  This has to be done before
> gimplification starts, otherwise e.g. the attached testcase ICEs.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

LGTM, please leave frontend maintainers a chance to comment though.

Thanks,
Richard.

> 2025-03-13  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR target/119120
>       * c-gimplify.cc (c_genericize_control_r): Set DECL_NOT_GIMPLE_REG_P
>       on {REAL,IMAG}PART_EXPR is_gimple_reg operand at -O0 if it is lhs
>       of a MODIFY_EXPR.
> 
>       * cp-gimplify.cc (cp_genericize_r): Set DECL_NOT_GIMPLE_REG_P
>       on {REAL,IMAG}PART_EXPR is_gimple_reg operand at -O0 if it is lhs
>       of a MODIFY_EXPR.
> 
>       * c-c++-common/pr119120.c: New test.
> 
> --- gcc/c-family/c-gimplify.cc.jj     2025-02-13 10:21:20.103421347 +0100
> +++ gcc/c-family/c-gimplify.cc        2025-03-12 15:15:57.286920683 +0100
> @@ -727,6 +727,18 @@ c_genericize_control_stmt (tree *stmt_p,
>  static tree
>  c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
>  {
> +  tree stmt = *stmt_p;
> +  /* Mark stores to parts of complex automatic non-addressable
> +     variables as DECL_NOT_GIMPLE_REG_P for -O0.  This can't be
> +     done during gimplification.  See PR119120.  */
> +  if (TREE_CODE (stmt) == MODIFY_EXPR
> +      && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
> +       || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
> +      && !optimize
> +      && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
> +      && is_gimple_reg (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)))
> +    DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
> +
>    c_genericize_control_stmt (stmt_p, walk_subtrees, data,
>                            c_genericize_control_r, NULL);
>    return NULL;
> --- gcc/cp/cp-gimplify.cc.jj  2025-03-07 16:34:02.266388660 +0100
> +++ gcc/cp/cp-gimplify.cc     2025-03-12 16:04:29.197874236 +0100
> @@ -2277,6 +2277,18 @@ cp_genericize_r (tree *stmt_p, int *walk
>                           TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
>        break;
>  
> +    case MODIFY_EXPR:
> +      /* Mark stores to parts of complex automatic non-addressable
> +      variables as DECL_NOT_GIMPLE_REG_P for -O0.  This can't be
> +      done during gimplification.  See PR119120.  */
> +      if ((TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
> +        || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
> +       && !optimize
> +       && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
> +       && is_gimple_reg (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)))
> +     DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
> +      break;
> +
>      default:
>        if (IS_TYPE_OR_DECL_P (stmt))
>       *walk_subtrees = 0;
> --- gcc/testsuite/c-c++-common/pr119120.c.jj  2025-03-12 15:58:17.716945271 
> +0100
> +++ gcc/testsuite/c-c++-common/pr119120.c     2025-03-13 00:21:28.393936936 
> +0100
> @@ -0,0 +1,40 @@
> +/* PR target/119120 */
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -fdump-tree-optimized" } */
> +/* { dg-final { scan-tree-dump "REALPART_EXPR <r> = " "optimized" } } */
> +/* { dg-final { scan-tree-dump "IMAGPART_EXPR <r> = " "optimized" } } */
> +/* { dg-final { scan-tree-dump "REALPART_EXPR <s> = " "optimized" } } */
> +/* { dg-final { scan-tree-dump-not "(REAL|IMAG)PART_EXPR <t> = " "optimized" 
> } } */
> +/* { dg-final { scan-tree-dump-not "(REAL|IMAG)PART_EXPR <u> = " "optimized" 
> } } */
> +
> +__complex__ double
> +foo (void)
> +{
> +  __complex__ double r;
> +  __imag__ r = 2.0;
> +  __real__ r = 1.0;
> +  return r + 1.0;
> +}
> +
> +__complex__ float
> +bar (float x, float y)
> +{
> +  __complex__ float s = x + y * 1.0fi;
> +  __real__ s = 1.0f;
> +  return s + 1.0f;
> +}
> +
> +__complex__ float
> +baz (float x, float y)
> +{
> +  __complex__ float t = x + y * 1.0fi;
> +  return t + 1.0f;
> +}
> +
> +__complex__ float
> +qux (__complex__ float x)
> +{
> +  __complex__ float u;
> +  u = x;
> +  return u + 1.0f;
> +}
> 
> 
>       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