On Thu, 13 Mar 2025, Jason Merrill wrote:

> On 3/13/25 3:54 AM, Richard Biener wrote:
> > 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.
> 
> No objection.
> 
> Though I notice that the documentation of DECL_NOT_GIMPLE_REG_P seems
> backwards?

Oops - I'll fix that up.

Richard.

> Jason
> 
> 
> 

-- 
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