https://gcc.gnu.org/g:e543eaa671d40868575385360d13ef37d87fb2a0

commit r16-188-ge543eaa671d40868575385360d13ef37d87fb2a0
Author: Richard Biener <rguent...@suse.de>
Date:   Tue Feb 18 12:52:34 2025 +0100

    middle-end/60779 - LTO vs. -fcx-fortran-rules and -fcx-limited-range
    
    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.
    
            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.

Diff:
---
 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(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index d10a6b7e533a..3edc5907ec85 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
 
@@ -1315,12 +1309,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 5b1861815de0..7fcf7dee4977 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -578,7 +578,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
@@ -15603,8 +15603,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
@@ -15617,7 +15616,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 d2c9a2da6ded..e00887be481b 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 d9fc111a9e76..7c2feeeffbb6 100644
--- a/gcc/ipa-inline.cc
+++ b/gcc/ipa-inline.cc
@@ -587,7 +587,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 ffcbdfef0bd9..d3e3a2dc0d12 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1384,16 +1384,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
@@ -3465,8 +3457,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 000000000000..360cdc9b51f4
--- /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 000000000000..caad9030ab56
--- /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;
+}

Reply via email to