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

Reply via email to