c/94392 - only enable -ffinite-loops for C++
authorRichard Biener <rguenther@suse.de>
Thu, 2 Apr 2020 08:46:20 +0000 (10:46 +0200)
committerRichard Biener <rguenther@suse.de>
Thu, 2 Apr 2020 14:53:21 +0000 (16:53 +0200)
This does away with enabling -ffinite-loops at -O2+ for all languages
and instead enables it selectively for C++ only.

It also makes -ffinite-loops loop-private at CFG construction time
fixing correctness issues with inlining.

2020-04-02  Richard Biener  <rguenther@suse.de>

PR c/94392
* c-opts.c (c_common_post_options): Enable -ffinite-loops
for -O2 and C++11 or newer.

* common.opt (ffinite-loops): Initialize to zero.
* opts.c (default_options_table): Remove OPT_ffinite_loops
entry.
* cfgloop.h (loop::finite_p): New member.
* cfgloopmanip.c (copy_loop_info): Copy finite_p.
* ipa-icf-gimple.c (func_checker::compare_loops): Compare
finite_p.
* lto-streamer-in.c (input_cfg): Stream finite_p.
* lto-streamer-out.c (output_cfg): Likewise.
* tree-cfg.c (replace_loop_annotate): Initialize finite_p
from flag_finite_loops at CFG build time.
* tree-ssa-loop-niter.c (finite_loop_p): Check the loops
finite_p flag instead of flag_finite_loops.
* doc/invoke.texi (ffinite-loops): Adjust documentation of
default setting.

* gcc.dg/torture/pr94392.c: New testcase.

15 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/cfgloop.h
gcc/cfgloopmanip.c
gcc/common.opt
gcc/doc/invoke.texi
gcc/ipa-icf-gimple.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/opts.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr94392.c [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-ssa-loop-niter.c

index 8a302811d6c1b547af2057861ee711e96cbb703c..4250204f15d9502bc09e2bc0041171481c9e9e95 100644 (file)
@@ -1,3 +1,22 @@
+2020-04-02  Richard Biener  <rguenther@suse.de>
+
+       PR c/94392
+       * common.opt (ffinite-loops): Initialize to zero.
+       * opts.c (default_options_table): Remove OPT_ffinite_loops
+       entry.
+       * cfgloop.h (loop::finite_p): New member.
+       * cfgloopmanip.c (copy_loop_info): Copy finite_p.
+       * ipa-icf-gimple.c (func_checker::compare_loops): Compare
+       finite_p.
+       * lto-streamer-in.c (input_cfg): Stream finite_p.
+       * lto-streamer-out.c (output_cfg): Likewise.
+       * tree-cfg.c (replace_loop_annotate): Initialize finite_p
+       from flag_finite_loops at CFG build time.
+       * tree-ssa-loop-niter.c (finite_loop_p): Check the loops
+       finite_p flag instead of flag_finite_loops.
+       * doc/invoke.texi (ffinite-loops): Adjust documentation of
+       default setting.
+
 2020-04-02  Richard Biener  <rguenther@suse.de>
 
        PR debug/94450
index 38406a8c551a8372f7e5236a69aaff46dea25c0b..92aed0ed7ce1c3b2055dad097437aef90c1571ec 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-02  Richard Biener  <rguenther@suse.de>
+
+       PR c/94392
+       * c-opts.c (c_common_post_options): Enable -ffinite-loops
+       for -O2 and C++11 or newer.
+
 2020-03-28  Patrick Palka  <ppalka@redhat.com>
 
        * c.opt: Add -fconcepts-diagnostics-depth.
index 6b6c754ad86f14577bee0f3ba11516183867c8c4..58ba0948e792731a93b46f7e8a8524d31db95f13 100644 (file)
@@ -989,6 +989,10 @@ c_common_post_options (const char **pfilename)
   SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_new_ttp,
                       cxx_dialect >= cxx17);
 
+  /* C++11 guarantees forward progress.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_finite_loops,
+                      optimize >= 2 && cxx_dialect >= cxx11);
+
   if (cxx_dialect >= cxx11)
     {
       /* If we're allowing C++0x constructs, don't warn about C++98
index 1c49a8b8c2d86ed95e769222005f2665e625bb7c..18b404e292f456e00f70c519195f951d38ba0b33 100644 (file)
@@ -226,6 +226,10 @@ public:
   /* True if the loop is part of an oacc kernels region.  */
   unsigned in_oacc_kernels_region : 1;
 
+  /* True if the loop is known to be finite.  This is a localized
+     flag_finite_loops or similar pragmas state.  */
+  unsigned finite_p : 1;
+
   /* The number of times to unroll the loop.  0 means no information given,
      just do what we always do.  A value of 1 means do not unroll the loop.
      A value of USHRT_MAX means unroll with no specific unrolling factor.
index c9375565f62e8eac1b8a1dcbb4071126b0950992..50c7267ec49e7a01fb80407fbc2838a188bd309f 100644 (file)
@@ -1023,6 +1023,7 @@ copy_loop_info (class loop *loop, class loop *target)
   target->dont_vectorize = loop->dont_vectorize;
   target->force_vectorize = loop->force_vectorize;
   target->in_oacc_kernels_region = loop->in_oacc_kernels_region;
+  target->finite_p = loop->finite_p;
   target->unroll = loop->unroll;
   target->owned_clique = loop->owned_clique;
 }
index 4368910cb54171fe6f8d9a40c48ab77856fd4a9a..bb2ea4c905d0a78cb2080e8b78f3d42e645a85d5 100644 (file)
@@ -1490,7 +1490,7 @@ Common Report Var(flag_finite_math_only) Optimization SetByCombined
 Assume no NaNs or infinities are generated.
 
 ffinite-loops
-Common Report Var(flag_finite_loops) Optimization
+Common Report Var(flag_finite_loops) Optimization Init(0)
 Assume that loops with an exit will terminate and not loop indefinitely.
 
 ffixed-
index e9e1683e9a8744027eb1f6f9a0e18c56f5eba0ba..e3e652ff6c15b1e953fa133869337c822d0524b9 100644 (file)
@@ -10432,7 +10432,8 @@ Assume that a loop with an exit will eventually take the exit and not loop
 indefinitely.  This allows the compiler to remove loops that otherwise have
 no side-effects, not considering eventual endless looping as such.
 
-This option is enabled by default at @option{-O2}.
+This option is enabled by default at @option{-O2} for C++ with -std=c++11
+or higher.
 
 @item -ftree-dominator-opts
 @opindex ftree-dominator-opts
index 3e5b2d4bd6d3207a612bcc172178b52cbf3189ce..d306fec56cec5f0e38f659d7350c2e264a294066 100644 (file)
@@ -395,6 +395,8 @@ func_checker::compare_loops (basic_block bb1, basic_block bb2)
     return return_false_with_msg ("dont_vectorize");
   if (l1->force_vectorize != l2->force_vectorize)
     return return_false_with_msg ("force_vectorize");
+  if (l1->finite_p != l2->finite_p)
+    return return_false_with_msg ("finite_p");
   if (l1->unroll != l2->unroll)
     return return_false_with_msg ("unroll");
   if (!compare_variable_decl (l1->simduid, l2->simduid))
index 9566e5ee102f2e09f07bf59a00d600d38d87dedd..244f5b8aa5c7f64fefd7812bd8b6c4300f245183 100644 (file)
@@ -821,6 +821,7 @@ input_cfg (class lto_input_block *ib, class data_in *data_in,
       loop->owned_clique = streamer_read_hwi (ib);
       loop->dont_vectorize = streamer_read_hwi (ib);
       loop->force_vectorize = streamer_read_hwi (ib);
+      loop->finite_p = streamer_read_hwi (ib);
       loop->simduid = stream_read_tree (ib, data_in);
 
       place_new_loop (fn, loop);
index a219c1d0dd1a02bfdd6f04fcc0de5bbeea543bd8..52ef94718db5e528b1f3d7929cef7ffb7c18d815 100644 (file)
@@ -1950,6 +1950,7 @@ output_cfg (struct output_block *ob, struct function *fn)
       streamer_write_hwi (ob, loop->owned_clique);
       streamer_write_hwi (ob, loop->dont_vectorize);
       streamer_write_hwi (ob, loop->force_vectorize);
+      streamer_write_hwi (ob, loop->finite_p);
       stream_write_tree (ob, loop->simduid, true);
     }
 
index 5dc7d65dedd244b65d239b995fc20f78cc28a4bf..d4df8627bf7f6dd20de1bec725380bf64419aef7 100644 (file)
@@ -478,7 +478,6 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },
-    { OPT_LEVELS_2_PLUS, OPT_ffinite_loops, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },
index 16940b44c826a02ac937870753da62df9624f973..c3803b69bdb3459722694b99ac93ec8a0e6769c1 100644 (file)
@@ -1,3 +1,8 @@
+2020-04-02  Richard Biener  <rguenther@suse.de>
+
+       PR c/94392
+       * gcc.dg/torture/pr94392.c: New testcase.
+
 2020-04-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/94435
diff --git a/gcc/testsuite/gcc.dg/torture/pr94392.c b/gcc/testsuite/gcc.dg/torture/pr94392.c
new file mode 100644 (file)
index 0000000..373f18c
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-skip-if "finite loops" { *-*-* } { "-ffinite-loops" } } */
+/* { dg-skip-if "LTO optimizes the test" { *-*-* } { "-flto" } } */
+/* { dg-additional-options "-fdump-tree-optimized" } */
+
+int a, b;
+
+int
+main()
+{
+  while (1)
+    {
+      /* Try really hard.  */
+      if (a != b)
+       return 1;
+    }
+  return 0;
+}
+
+/* ISO C does not guarantee forward progress like C++ does so we
+   cannot assume the loop is finite and optimize it to return 1.  */
+/* { dg-final { scan-tree-dump "if" "optimized" } } */
index f7b817d94e64dfcb943789db3f91ea96cb0b6574..e99fb9ff5d12b368400f352c1cf0bbaa4e392ef9 100644 (file)
@@ -324,6 +324,9 @@ replace_loop_annotate (void)
       /* Then look into the latch, if any.  */
       if (loop->latch)
        replace_loop_annotate_in_block (loop->latch, loop);
+
+      /* Push the global flag_finite_loops state down to individual loops.  */
+      loop->finite_p = flag_finite_loops;
     }
 
   /* Remove IFN_ANNOTATE.  Safeguard for the case loop->latch == NULL.  */
index 6e6df0bfdb898de948c917640ff488b19cf7911f..7d61ef080ebac88982d4567d90b43d0c3931f0d0 100644 (file)
@@ -2834,7 +2834,7 @@ finite_loop_p (class loop *loop)
       return true;
     }
 
-  if (flag_finite_loops)
+  if (loop->finite_p)
     {
       unsigned i;
       vec<edge> exits = get_loop_exit_edges (loop);