On Tue, 11 Mar 2025, Jakub Jelinek wrote:

> Hi!
> 
> The PR119190 patch I've posted regresses the PR119120 testcase (not adding
> to testsuite, as it is fairly hard to scan for that problem).
> The issue is that for the partial setting of _Complex floating vars
> through __real__ on it first and __imag__ later (or vice versa) and since
> we forced all complex vars into SSA form we often have undefined (D)
> arguments of those COMPLEX_EXPRs.  When we don't DCE them (for -O0 debug
> info reasons), their expansion will copy both the real and imag parts
> using the floating mode and on some targets like 387 that copying alone can
> unfortunately trigger exceptions on sNaNs or other problematic bit patterns
> and for uninitialized memory it can be triggered randomly based on whatever
> is on the stack before.
> 
> The following patch deals just with the unused COMPLEX_EXPRs at -O0,
> if it is used, either complex lowering should have replaced its parts or
> it represents a user store somewhere, or passing to function argument etc.,
> all that should be really avoided for partially uninitialized complex.
> And the patch attempts to find the uninitialized arguments (unfortunately
> at -O0 we don't forward propagate the (D) SSA_NAMEs) and only copy the
> initialized parts.  Another option would be to arrange for the copying
> to be done in integral mode rather than floating, kind of VCE and back.
> Though, not sure how to handle then XFmode or on 32-bit targets TFmode
> when there is no corresponding intergral mode or it isn't usable.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> Or shall I go the VCE route instead?

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?

> 2025-03-11  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR target/119120
>       * cfgexpand.cc (expand_gimple_stmt_1): At -O0 expand a COMPLEX_EXPR
>       with zero uses of lhs if it has complex floating point mode as
>       stores of just the parts which aren't known to be uninitialized.
> 
> --- gcc/cfgexpand.cc.jj       2025-01-07 20:11:04.632662813 +0100
> +++ gcc/cfgexpand.cc  2025-03-10 21:28:01.071078448 +0100
> @@ -4294,6 +4294,70 @@ expand_gimple_stmt_1 (gimple *stmt)
>           if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
>             promoted = true;
>  
> +         /* At -O0 an unused COMPLEX_EXPR might be kept in the IL by
> +            cplxlower0 pass to ensure correct debug info.  If one or both
> +            arguments of COMPLEX_EXPR is unitialized and it is a complex
> +            floating-point mode, don't actually copy the uninitialized
> +            part(s) using floating-point mode, as that could cause extra
> +            exceptions.  */
> +         if (!optimize
> +             && gimple_assign_rhs_code (assign_stmt) == COMPLEX_EXPR
> +             && TREE_CODE (lhs) == SSA_NAME
> +             && has_zero_uses (lhs)
> +             && MEM_P (target)
> +             && SCALAR_FLOAT_MODE_P (GET_MODE_INNER (GET_MODE (target))))
> +           {
> +             op0 = gimple_assign_rhs1 (assign_stmt);
> +             tree op1 = gimple_assign_rhs2 (assign_stmt);
> +             gimple *g;
> +             bool ignore_op0 = (TREE_CODE (op0) == SSA_NAME
> +                                && SSA_NAME_IS_DEFAULT_DEF (op0)
> +                                && (!SSA_NAME_VAR (op0)
> +                                    || VAR_P (SSA_NAME_VAR (op0))));
> +             bool ignore_op1 = (TREE_CODE (op1) == SSA_NAME
> +                                && SSA_NAME_IS_DEFAULT_DEF (op1)
> +                                && (!SSA_NAME_VAR (op1)
> +                                    || VAR_P (SSA_NAME_VAR (op1))));
> +             tree tem = op0;
> +             while (!ignore_op0
> +                    && TREE_CODE (tem) == SSA_NAME
> +                    && (g = SSA_NAME_DEF_STMT (tem))
> +                    && is_gimple_assign (g)
> +                    && gimple_assign_rhs_code (g) == SSA_NAME)
> +               {
> +                 tem = gimple_assign_rhs1 (g);
> +                 if (SSA_NAME_IS_DEFAULT_DEF (tem)
> +                     && (!SSA_NAME_VAR (tem) || VAR_P (SSA_NAME_VAR (tem))))
> +                   ignore_op0 = true;
> +               }
> +             tem = op1;
> +             while (!ignore_op1
> +                    && TREE_CODE (tem) == SSA_NAME
> +                    && (g = SSA_NAME_DEF_STMT (tem))
> +                    && is_gimple_assign (g)
> +                    && gimple_assign_rhs_code (g) == SSA_NAME)
> +               {
> +                 tem = gimple_assign_rhs1 (g);
> +                 if (SSA_NAME_IS_DEFAULT_DEF (tem)
> +                     && (!SSA_NAME_VAR (tem) || VAR_P (SSA_NAME_VAR (tem))))
> +                   ignore_op1 = true;
> +               }
> +             if (ignore_op0 || ignore_op1)
> +               {
> +                 if (!ignore_op0)
> +                   {
> +                     rtx rop0 = expand_normal (op0);
> +                     write_complex_part (target, rop0, 0, true);
> +                   }
> +                 else if (!ignore_op1)
> +                   {
> +                     rtx rop1 = expand_normal (op1);
> +                     write_complex_part (target, rop1, 1, true);
> +                   }
> +                 break;
> +               }
> +           }
> +
>          /* If we store into a promoted register, don't directly
>             expand to target.  */
>           temp = promoted ? NULL_RTX : target;
> 
>       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