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)