re PR ipa/65076 (16% tramp3d-v4.cpp compile time regression)
authorJan Hubicka <hubicka@ucw.cz>
Fri, 27 Mar 2015 04:02:28 +0000 (05:02 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 27 Mar 2015 04:02:28 +0000 (04:02 +0000)
PR ipa/65076
* passes.def: Add pass_nothrow.
* ipa-pure-const.c: (pass_data_nothrow): New.
(pass_nothrow): New.
(pass_nothrow::execute): New.
(make_pass_nothrow): New.
* tree-pass.h (make_pass_nothrow): Declare.

From-SVN: r221719

gcc/ChangeLog
gcc/ipa-pure-const.c
gcc/passes.def
gcc/tree-pass.h

index 992cd53..4706ad9 100644 (file)
@@ -1,5 +1,15 @@
 2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
 
+       PR ipa/65076
+       * passes.def: Add pass_nothrow.
+       * ipa-pure-const.c: (pass_data_nothrow): New.
+       (pass_nothrow): New.
+       (pass_nothrow::execute): New.
+       (make_pass_nothrow): New.
+       * tree-pass.h (make_pass_nothrow): Declare.
+
+2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
+
        * ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for
        edge to change by speculation resolution or redirection.
        (edge_set_predicate): Likewise.
index 73e80e8..a4cdae9 100644 (file)
@@ -86,6 +86,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "intl.h"
 #include "opts.h"
+#include "varasm.h"
 
 /* Lattice values for const and pure functions.  Everything starts out
    being const, then may drop to pure and then neither depending on
@@ -710,6 +711,16 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
   if (is_gimple_debug (stmt))
     return;
 
+  /* Do consider clobber as side effects before IPA, so we rather inline
+     C++ destructors and keep clobber semantics than eliminate them.
+
+     TODO: We may get smarter during early optimizations on these and let
+     functions containing only clobbers to be optimized more.  This is a common
+     case of C++ destructors.  */
+
+  if ((ipa || cfun->after_inlining) && gimple_clobber_p (stmt))
+    return;
+
   if (dump_file)
     {
       fprintf (dump_file, "  scanning: ");
@@ -1870,3 +1881,96 @@ make_pass_warn_function_noreturn (gcc::context *ctxt)
 {
   return new pass_warn_function_noreturn (ctxt);
 }
+
+/* Simple local pass for pure const discovery reusing the analysis from
+   ipa_pure_const.   This pass is effective when executed together with
+   other optimization passes in early optimization pass queue.  */
+
+namespace {
+
+const pass_data pass_data_nothrow =
+{
+  GIMPLE_PASS, /* type */
+  "nothrow", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_IPA_PURE_CONST, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_nothrow : public gimple_opt_pass
+{
+public:
+  pass_nothrow (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_nothrow, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  opt_pass * clone () { return new pass_nothrow (m_ctxt); }
+  virtual bool gate (function *) { return optimize; }
+  virtual unsigned int execute (function *);
+
+}; // class pass_nothrow
+
+unsigned int
+pass_nothrow::execute (function *)
+{
+  struct cgraph_node *node;
+  basic_block this_block;
+
+  if (TREE_NOTHROW (current_function_decl))
+    return 0;
+
+  node = cgraph_node::get (current_function_decl);
+
+  /* We run during lowering, we can not really use availability yet.  */
+  if (cgraph_node::get (current_function_decl)->get_availability ()
+      <= AVAIL_INTERPOSABLE)
+    {
+      if (dump_file)
+        fprintf (dump_file, "Function is interposable;"
+                " not analyzing.\n");
+      return true;
+    }
+
+  FOR_EACH_BB_FN (this_block, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_start_bb (this_block);
+          !gsi_end_p (gsi);
+          gsi_next (&gsi))
+        if (stmt_can_throw_external (gsi_stmt (gsi)))
+         {
+           if (is_gimple_call (gsi_stmt (gsi)))
+             {
+               tree callee_t = gimple_call_fndecl (gsi_stmt (gsi));
+               if (callee_t && recursive_call_p (current_function_decl,
+                                                 callee_t))
+                 continue;
+             }
+       
+           if (dump_file)
+             {
+               fprintf (dump_file, "Statement can throw: ");
+               print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0);
+             }
+           return 0;
+         }
+    }
+
+  node->set_nothrow_flag (true);
+  if (dump_file)
+    fprintf (dump_file, "Function found to be nothrow: %s\n",
+            current_function_name ());
+  return 0;
+}
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_nothrow (gcc::context *ctxt)
+{
+  return new pass_nothrow (ctxt);
+}
index c839b79..1d598b2 100644 (file)
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_build_ssa);
       NEXT_PASS (pass_ubsan);
       NEXT_PASS (pass_early_warn_uninitialized);
+      NEXT_PASS (pass_nothrow);
   POP_INSERT_PASSES ()
 
   NEXT_PASS (pass_chkp_instrumentation_passes);
index b59ae7a..bc8763d 100644 (file)
@@ -436,6 +436,7 @@ extern gimple_opt_pass *make_pass_remove_cgraph_callee_edges (gcc::context
                                                              *ctxt);
 extern gimple_opt_pass *make_pass_build_cgraph_edges (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_local_pure_const (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_nothrow (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_tracer (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_warn_unused_result (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_diagnose_tm_blocks (gcc::context *ctxt);