This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Discover nothorow functions before into_ssa


Hi,
this is updated patch I am testing (along with the fixes to verifiew and
inliner I will commit independently).

	* 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.
Index: passes.def
===================================================================
--- passes.def	(revision 221682)
+++ passes.def	(working copy)
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.
       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: tree-pass.h
===================================================================
--- tree-pass.h	(revision 221682)
+++ tree-pass.h	(working copy)
@@ -436,6 +436,7 @@ extern gimple_opt_pass *make_pass_remove
 							      *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);
Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c	(revision 221682)
+++ ipa-pure-const.c	(working copy)
@@ -710,6 +711,16 @@ check_stmt (gimple_stmt_iterator *gsip,
   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,93 @@ make_pass_warn_function_noreturn (gcc::c
 {
   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)
+    {
+      gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_bb (this_block);
+	   !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+        if (stmt_can_throw_external (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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]