public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Remove empty loop with assumed finiteness (PR tree-optimization/89713)
@ 2019-05-17  4:17 Feng Xue OS
  2019-05-17 16:47 ` Jeff Law
  2020-04-01 13:36 ` [PATCH][RFC] c/94392 - only enable -ffinite-loops for C++ Richard Biener
  0 siblings, 2 replies; 45+ messages in thread
From: Feng Xue OS @ 2019-05-17  4:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: Feng Xue OS

This patch is meant to give user a way to optimize away those empty loops which are impossible to be recognized by compiler, such as C++ STL container-based loop,

    void f (std::map<int, int> &m)
    {
        for (auto it = m.begin (); it != m.end (); ++it);
    }
 
An option "-ffinite-loop" is added to tell compiler about finiteness of loops so that compiler can apply the optimization.

Feng

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d8bed3a..c55f2e6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2019-05-16  Feng Xue  <fxue@os.amperecomputing.com>
+
+        PR tree-optimization/89713
+        * doc/invoke.texi (-ffinite-loop): Document new option.
+        * common.opt (-ffinite-loop): New option.
+        * passes.def: Replace pass_cd_dce with pass_cd_dce2.
+        * tree-pass.h (pass_cd_dce2): New declaration.
+        * tree-ssa-dce.c (loop_has_true_exits): New function.
+        (find_obviously_necessary_stmts): Add aggressive_loop_removal
+        parameter.
+        (perform_tree_ssa_dce, tree_ssa_cd_dce): Likewise.
+        (class pass_cd_dce): Add new member aggressive_loop_removal.
+        (pass_cd_dce::pass_cd_dce: Add alr parameter.
+        (make_pass_cd_dce2): New function.
+
 2019-05-16  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/90484
diff --git a/gcc/common.opt b/gcc/common.opt
index d342c4f..e98a34d 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1437,6 +1437,10 @@ ffinite-math-only
 Common Report Var(flag_finite_math_only) Optimization SetByCombined
 Assume no NaNs or infinities are generated.
 
+ffinite-loop
+Common Report Var(flag_finite_loop) Optimization
+Assume loops are finite if can not be analytically determined.
+
 ffixed-
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -ffixed-<register>	Mark <register> as being unavailable to the compiler.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5e3e887..9a3882c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -412,6 +412,7 @@ Objective-C and Objective-C++ Dialects}.
 -fdevirtualize-at-ltrans  -fdse @gol
 -fearly-inlining  -fipa-sra  -fexpensive-optimizations  -ffat-lto-objects @gol
 -ffast-math  -ffinite-math-only  -ffloat-store  -fexcess-precision=@var{style} @gol
+-ffinite-loop @gol
 -fforward-propagate  -ffp-contract=@var{style}  -ffunction-sections @gol
 -fgcse  -fgcse-after-reload  -fgcse-las  -fgcse-lm  -fgraphite-identity @gol
 -fgcse-sm  -fhoist-adjacent-loads  -fif-conversion @gol
@@ -9501,6 +9502,20 @@ that may set @code{errno} but are otherwise free of side effects.  This flag is
 enabled by default at @option{-O2} and higher if @option{-Os} is not also
 specified.
 
+@item -ffinite-loop
+@opindex ffinite-loop
+@opindex fno-finite-loop
+Allow the compiler to assume that if finiteness of a loop can not be
+analytically determined, the loop must be finite. With the assumption, some
+aggressive transformation could be possible, such as removal of this kind
+of empty loop by dead code elimination (DCE).
+
+This option is not turned on by any @option{-O} option since it might result
+in incorrect behaviour for programs that contain seemly finite, but actually
+infinite loop.
+
+The default is @option{-fno-finite-loop}.
+
 @item -ftree-dominator-opts
 @opindex ftree-dominator-opts
 Perform a variety of simple scalar cleanups (constant/copy
diff --git a/gcc/passes.def b/gcc/passes.def
index ad2efab..b84ee34 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -322,7 +322,7 @@ along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_copy_prop);
       NEXT_PASS (pass_warn_restrict);
       NEXT_PASS (pass_dse);
-      NEXT_PASS (pass_cd_dce);
+      NEXT_PASS (pass_cd_dce2);
       NEXT_PASS (pass_forwprop);
       NEXT_PASS (pass_phiopt, false /* early_p */);
       NEXT_PASS (pass_fold_builtins);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 3a0b380..2392bc5 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -395,6 +395,7 @@ extern gimple_opt_pass *make_pass_build_ealias (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_dominator (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_dce (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_cd_dce (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cd_dce2 (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_call_cdce (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_merge_phi (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_thread_jumps (gcc::context *ctxt);
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 2478219..d4659df 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -356,6 +356,27 @@ mark_control_dependent_edges_necessary (basic_block bb, bool ignore_self)
     bitmap_set_bit (visited_control_parents, bb->index);
 }
 
+/* Check whether a loop has any non-EH exit. */
+
+static bool
+loop_has_true_exits (const struct loop *loop)
+{
+  vec<edge> exits = get_loop_exit_edges (loop);
+  bool found = false;
+  edge e;
+  unsigned i;
+
+  FOR_EACH_VEC_ELT (exits, i, e)
+    if (!(e->flags & EDGE_EH))
+      {
+        found = true;
+        break;
+      }
+
+  exits.release ();
+  return found;
+}
+
 
 /* Find obviously necessary statements.  These are things like most function
    calls, and stores to file level variables.
@@ -365,7 +386,7 @@ mark_control_dependent_edges_necessary (basic_block bb, bool ignore_self)
    dependence analysis.  */
 
 static void
-find_obviously_necessary_stmts (bool aggressive)
+find_obviously_necessary_stmts (bool aggressive, bool aggressive_loop_removal)
 {
   basic_block bb;
   gimple_stmt_iterator gsi;
@@ -417,7 +438,8 @@ find_obviously_necessary_stmts (bool aggressive)
 	  }
 
       FOR_EACH_LOOP (loop, 0)
-	if (!finite_loop_p (loop))
+	if (!finite_loop_p (loop)
+	    && (!aggressive_loop_removal || !loop_has_true_exits (loop)))
 	  {
 	    if (dump_file)
 	      fprintf (dump_file, "cannot prove finiteness of loop %i\n", loop->num);
@@ -1532,6 +1554,8 @@ tree_dce_done (bool aggressive)
 /* Main routine to eliminate dead code.
 
    AGGRESSIVE controls the aggressiveness of the algorithm.
+   If aggressive mode is on, AGGRESSIVE_LOOP_REMOVAL enables more aggressive
+   removal of empty loop whose finiteness can not be statically determined.
    In conservative mode, we ignore control dependence and simply declare
    all but the most trivially dead branches necessary.  This mode is fast.
    In aggressive mode, control dependences are taken into account, which
@@ -1544,7 +1568,7 @@ tree_dce_done (bool aggressive)
 	  start experimenting with pass ordering.  */
 
 static unsigned int
-perform_tree_ssa_dce (bool aggressive)
+perform_tree_ssa_dce (bool aggressive, bool aggressive_loop_removal = false)
 {
   bool something_changed = 0;
 
@@ -1576,7 +1600,7 @@ perform_tree_ssa_dce (bool aggressive)
       mark_dfs_back_edges ();
     }
 
-  find_obviously_necessary_stmts (aggressive);
+  find_obviously_necessary_stmts (aggressive, aggressive_loop_removal);
 
   if (aggressive && ! in_loop_pipeline)
     {
@@ -1631,9 +1655,10 @@ tree_ssa_dce (void)
 }
 
 static unsigned int
-tree_ssa_cd_dce (void)
+tree_ssa_cd_dce (bool aggressive_loop_removal)
 {
-  return perform_tree_ssa_dce (/*aggressive=*/optimize >= 2);
+  return perform_tree_ssa_dce (/*aggressive=*/optimize >= 2,
+                               aggressive_loop_removal && flag_finite_loop);
 }
 
 namespace {
@@ -1690,15 +1715,20 @@ const pass_data pass_data_cd_dce =
 
 class pass_cd_dce : public gimple_opt_pass
 {
+  bool aggressive_loop_removal;
 public:
-  pass_cd_dce (gcc::context *ctxt)
+  pass_cd_dce (gcc::context *ctxt, bool alr = false)
     : gimple_opt_pass (pass_data_cd_dce, ctxt)
+    , aggressive_loop_removal (alr)
   {}
 
   /* opt_pass methods: */
   opt_pass * clone () { return new pass_cd_dce (m_ctxt); }
   virtual bool gate (function *) { return flag_tree_dce != 0; }
-  virtual unsigned int execute (function *) { return tree_ssa_cd_dce (); }
+  virtual unsigned int execute (function *)
+  {
+    return tree_ssa_cd_dce (aggressive_loop_removal);
+  }
 
 }; // class pass_cd_dce
 
@@ -1710,6 +1740,12 @@ make_pass_cd_dce (gcc::context *ctxt)
   return new pass_cd_dce (ctxt);
 }
 
+gimple_opt_pass *
+make_pass_cd_dce2 (gcc::context *ctxt)
+{
+  return new pass_cd_dce (ctxt, true);
+}
+
 
 /* A cheap DCE interface.  WORKLIST is a list of possibly dead stmts and
    is consumed by this function.  The function has linear complexity in

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2020-10-30 14:17 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-17  4:17 [PATCH] Remove empty loop with assumed finiteness (PR tree-optimization/89713) Feng Xue OS
2019-05-17 16:47 ` Jeff Law
2019-05-17 18:50   ` Richard Biener
2019-05-18 14:00     ` Marc Glisse
2019-05-20  7:50       ` Richard Biener
2019-05-20  8:27         ` Feng Xue OS
2019-05-20  9:19           ` Richard Biener
2019-05-20  9:48             ` Feng Xue OS
2019-05-20 11:54               ` Richard Biener
2019-05-20 14:00                 ` Feng Xue OS
2019-05-20 14:04                   ` Richard Biener
2019-05-20 14:51                     ` Feng Xue OS
2019-05-21 10:12                       ` Richard Biener
2019-05-21 14:24                         ` Richard Biener
2019-05-22 13:44                           ` Michael Matz
2019-05-24 16:02                             ` [PATCH V3] " Feng Xue OS
2019-05-24  9:15                           ` [PATCH V2] " Feng Xue OS
2019-05-29 11:16                             ` Richard Biener
2019-06-04  6:49                               ` [PATCH V4] " Feng Xue OS
2019-06-04  8:24                                 ` Marc Glisse
2019-06-04 15:16                                   ` [PATCH V5] " Feng Xue OS
2019-06-04 15:24                                     ` [PATCH V6] " Feng Xue OS
2019-06-05 11:05                                       ` Richard Biener
2019-06-06 10:00                                         ` [PATCH V7] " Feng Xue OS
2019-06-11  2:40                                           ` [PATCH V8] " Feng Xue OS
2019-06-12  9:43                                             ` Richard Biener
2019-06-15 12:05                                               ` [committed][nvptx, libgomp] Update pr85381-{2,4}.c test-cases Tom de Vries
2019-05-20 13:04         ` [PATCH] Remove empty loop with assumed finiteness (PR tree-optimization/89713) Marc Glisse
2019-05-20 13:26           ` Richard Biener
2019-05-20 14:49             ` Michael Matz
2019-05-21  8:06               ` Marc Glisse
2020-04-01 13:36 ` [PATCH][RFC] c/94392 - only enable -ffinite-loops for C++ Richard Biener
2020-04-01 13:47   ` Jakub Jelinek
2020-04-01 13:52     ` Richard Biener
2020-04-01 15:56       ` Jan Hubicka
2020-04-01 16:59         ` Richard Biener
2020-04-01 19:15   ` Jason Merrill
2020-04-02  9:12     ` Richard Biener
2020-04-02  9:17       ` Jakub Jelinek
2020-04-02  9:41         ` Richard Biener
2020-04-03  8:29       ` Revert "[nvptx, libgomp] Update pr85381-{2, 4}.c test-cases" [PR89713, PR94392] (was: [PATCH][RFC] c/94392 - only enable -ffinite-loops for C++) Thomas Schwinge
2020-04-03  9:36         ` Revert "[nvptx, libgomp] Update pr85381-{2,4}.c " Richard Biener
2020-04-03 10:34           ` Jakub Jelinek
2020-10-30 14:09           ` Revert "[nvptx, libgomp] Update pr85381-{2, 4}.c " Thomas Schwinge
2020-10-30 14:16             ` Revert "[nvptx, libgomp] Update pr85381-{2,4}.c " Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).