On March 26, 2015 6:01:21 PM GMT+01:00, Jan Hubicka <hubi...@ucw.cz> wrote: >Hi, >this is updated patch I am testing (along with the fixes to verifiew >and >inliner I will commit independently).
OK. Thanks, Richard. > * 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); >+}