On Tue, Feb 18, 2025 at 1:44 PM Richard Biener <rguent...@suse.de> wrote: > > The following changes how flag_complex_method is managed towards > being able to record that in the optimization set so we can stream > and restore it per function. Currently -fcx-fortran-rules and > -fcx-limited-range are separate recorded options but saving/restoring > does not restore flag_complex_method which is later used in the > middle-end. > > The solution is to make -fcx-fortran-rules and -fcx-limited-range > aliases of a new -fcx-method= switch that represents flag_complex_method > directly so we can save and restore it. > > Bootstrap and regtest running on x86_64-unknown-linux-gnu. How do > we go about documenting Aliased flags? I'm hoping for test coverage > of language-specific defaults. > > We allowed inlining of -fcx-limited-range into -fno-cx-limited-range > (but failed to check -fcx-fortran-rules). Such inlining would > pessimize complex multiplication/division, but I've preserved this > behavior and properly based it on flag_complex_method. > > OK for stage1?
I have pushed this now. Richard. > Thanks, > Richard. > > PR middle-end/60779 > * common.opt (fcx-method=): New, map to flag_complex_method. > (Enum complex_method): New. > (fcx-limited-range): Alias to -fcx-method=limited-range. > (fcx-fortran-rules): Alias to -fcx-medhot=fortran. > * ipa-inline-transform.cc (inline_call): Check flag_complex_method. > * ipa-inline.cc (can_inline_edge_by_limits_p): Likewise. > * opts.cc (finish_options): Adjust. > (set_fast_math_flags): Likewise. > * doc/invoke.texi (fcx-method=): Document. > > * gcc.dg/lto/pr60779_0.c: New testcase. > * gcc.dg/lto/pr60779_1.c: Likewise. > --- > gcc/common.opt | 28 ++++++++++++++++++++-------- > gcc/doc/invoke.texi | 14 ++++++++++---- > gcc/ipa-inline-transform.cc | 8 ++++---- > gcc/ipa-inline.cc | 2 +- > gcc/opts.cc | 16 ++++------------ > gcc/testsuite/gcc.dg/lto/pr60779_0.c | 21 +++++++++++++++++++++ > gcc/testsuite/gcc.dg/lto/pr60779_1.c | 6 ++++++ > 7 files changed, 66 insertions(+), 29 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/lto/pr60779_0.c > create mode 100644 gcc/testsuite/gcc.dg/lto/pr60779_1.c > > diff --git a/gcc/common.opt b/gcc/common.opt > index 4c2560a0632..b5c1d41abe9 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -53,12 +53,6 @@ bool in_lto_p = false > Variable > enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE > > -; 0 means straightforward implementation of complex divide acceptable. > -; 1 means wide ranges of inputs must work for complex divide. > -; 2 means C99-like requirements for complex multiply and divide. > -Variable > -int flag_complex_method = 1 > - > Variable > int flag_default_complex_method = 1 > > @@ -1292,12 +1286,30 @@ fcse-skip-blocks > Common Ignore > Does nothing. Preserved for backward compatibility. > > +fcx-method= > +Common Joined RejectNegative Enum(complex_method) Var(flag_complex_method) > Optimization SetByCombined > + > +Enum > +Name(complex_method) Type(int) > + > +; straightforward implementation of complex divide acceptable. > +EnumValue > +Enum(complex_method) String(limited-range) Value(0) > + > +; wide ranges of inputs must work for complex divide. > +EnumValue > +Enum(complex_method) String(fortran) Value(1) > + > +; C99-like requirements for complex multiply and divide. > +EnumValue > +Enum(complex_method) String(stdc) Value(2) > + > fcx-limited-range > -Common Var(flag_cx_limited_range) Optimization SetByCombined > +Common Alias(fcx-method=,limited-range,stdc) > Omit range reduction step when performing complex division. > > fcx-fortran-rules > -Common Var(flag_cx_fortran_rules) Optimization > +Common Alias(fcx-method=,fortran,stdc) > Complex multiplication and division follow Fortran rules. > > fdata-sections > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index d9b0278228f..8779488027b 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -574,7 +574,7 @@ Objective-C and Objective-C++ Dialects}. > -ffold-mem-offsets > -fcompare-elim -fcprop-registers -fcrossjumping > -fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules > --fcx-limited-range > +-fcx-limited-range -fcx-method > -fdata-sections -fdce -fdelayed-branch > -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively > -fdevirtualize-at-ltrans -fdse > @@ -15482,8 +15482,7 @@ When enabled, this option states that a range > reduction step is not > needed when performing complex division. Also, there is no checking > whether the result of a complex multiplication or division is @code{NaN > + I*NaN}, with an attempt to rescue the situation in that case. The > -default is @option{-fno-cx-limited-range}, but is enabled by > -@option{-ffast-math}. > +option is enabled by @option{-ffast-math}. > > This option controls the default setting of the ISO C99 > @code{CX_LIMITED_RANGE} pragma. Nevertheless, the option applies to > @@ -15496,7 +15495,14 @@ reduction is done as part of complex division, but > there is no checking > whether the result of a complex multiplication or division is @code{NaN > + I*NaN}, with an attempt to rescue the situation in that case. > > -The default is @option{-fno-cx-fortran-rules}. > +@opindex fcx-method > +@item -fcx-method=@var{method} > +Complex multiplication and division follow the stated @var{method}. The > +@var{method} argument should be one of @samp{limited-range}, @samp{fortran} > +or @samp{stdc}. > + > +The default is to honor language specific constraints which means > +@samp{fortran} for Fortran and @samp{stdc} otherwise. > > @end table > > diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc > index d2c9a2da6de..e00887be481 100644 > --- a/gcc/ipa-inline-transform.cc > +++ b/gcc/ipa-inline-transform.cc > @@ -438,8 +438,8 @@ inline_call (struct cgraph_edge *e, bool update_original, > != opt_for_fn (to->decl, flag_finite_math_only) > || opt_for_fn (callee->decl, flag_signaling_nans) > != opt_for_fn (to->decl, flag_signaling_nans) > - || opt_for_fn (callee->decl, flag_cx_limited_range) > - != opt_for_fn (to->decl, flag_cx_limited_range) > + || opt_for_fn (callee->decl, flag_complex_method) > + != opt_for_fn (to->decl, flag_complex_method) > || opt_for_fn (callee->decl, flag_signed_zeros) > != opt_for_fn (to->decl, flag_signed_zeros) > || opt_for_fn (callee->decl, flag_associative_math) > @@ -465,8 +465,8 @@ inline_call (struct cgraph_edge *e, bool update_original, > = opt_for_fn (callee->decl, flag_finite_math_only); > opts.x_flag_signaling_nans > = opt_for_fn (callee->decl, flag_signaling_nans); > - opts.x_flag_cx_limited_range > - = opt_for_fn (callee->decl, flag_cx_limited_range); > + opts.x_flag_complex_method > + = opt_for_fn (callee->decl, flag_complex_method); > opts.x_flag_signed_zeros > = opt_for_fn (callee->decl, flag_signed_zeros); > opts.x_flag_associative_math > diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc > index 163129540ac..46a8d2e9516 100644 > --- a/gcc/ipa-inline.cc > +++ b/gcc/ipa-inline.cc > @@ -585,7 +585,7 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, int > flags) > || check_maybe_down (flag_unsafe_math_optimizations) > || check_maybe_down (flag_finite_math_only) > || check_maybe_up (flag_signaling_nans) > - || check_maybe_down (flag_cx_limited_range) > + || check_maybe_up (flag_complex_method) > || check_maybe_up (flag_signed_zeros) > || check_maybe_down (flag_associative_math) > || check_maybe_down (flag_reciprocal_math) > diff --git a/gcc/opts.cc b/gcc/opts.cc > index 23900c7b1c0..4eda7ea49d0 100644 > --- a/gcc/opts.cc > +++ b/gcc/opts.cc > @@ -1363,16 +1363,8 @@ finish_options (struct gcc_options *opts, struct > gcc_options *opts_set, > || opts->x_flag_peel_loops > || opts->x_optimize >= 3); > > - /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */ > - if (opts->x_flag_cx_limited_range) > - opts->x_flag_complex_method = 0; > - else if (opts_set->x_flag_cx_limited_range) > - opts->x_flag_complex_method = opts->x_flag_default_complex_method; > - > - /* With -fcx-fortran-rules, we do something in-between cheap and C99. */ > - if (opts->x_flag_cx_fortran_rules) > - opts->x_flag_complex_method = 1; > - else if (opts_set->x_flag_cx_fortran_rules) > + /* Use a frontend provided default for the complex eval method. */ > + if (!opts_set->x_flag_complex_method) > opts->x_flag_complex_method = opts->x_flag_default_complex_method; > > /* Use -fvect-cost-model=cheap instead of -fvect-cost-mode=very-cheap > @@ -3444,8 +3436,8 @@ set_fast_math_flags (struct gcc_options *opts, int set) > opts->x_flag_signaling_nans = 0; > if (!opts->frontend_set_flag_rounding_math) > opts->x_flag_rounding_math = 0; > - if (!opts->frontend_set_flag_cx_limited_range) > - opts->x_flag_cx_limited_range = 1; > + if (!opts->frontend_set_flag_complex_method) > + opts->x_flag_complex_method = 0; > } > } > > diff --git a/gcc/testsuite/gcc.dg/lto/pr60779_0.c > b/gcc/testsuite/gcc.dg/lto/pr60779_0.c > new file mode 100644 > index 00000000000..360cdc9b51f > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr60779_0.c > @@ -0,0 +1,21 @@ > +/* { dg-lto-do link } */ > +/* { dg-lto-options { { -O -flto -fdump-tree-optimized } } } */ > + > +_Complex double bar (_Complex double x, _Complex double y); > + > +_Complex double foo (_Complex double x, _Complex double y) > +{ > + return x / y; > +} > + > +volatile double r; > + > +int main () > +{ > + _Complex double x = r + 1.0iF * r; > + _Complex double y = r + 1.0iF * r; > + _Complex double z = foo (x, y); > + volatile _Complex double w = bar (z, x); > +} > + > +/* { dg-final { scan-ltrans-tree-dump-times "divdc3" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/lto/pr60779_1.c > b/gcc/testsuite/gcc.dg/lto/pr60779_1.c > new file mode 100644 > index 00000000000..caad9030ab5 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr60779_1.c > @@ -0,0 +1,6 @@ > +/* { dg-options "-fcx-limited-range" } */ > + > +_Complex double bar (_Complex double x, _Complex double y) > +{ > + return x / y; > +} > -- > 2.43.0