From 38147a2a4e7c553840b45ba7d099a5f93ac192a4 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 27 Mar 2015 05:02:28 +0100 Subject: [PATCH] re PR ipa/65076 (16% tramp3d-v4.cpp compile time regression) 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 | 10 +++++ gcc/ipa-pure-const.c | 104 +++++++++++++++++++++++++++++++++++++++++++ gcc/passes.def | 1 + gcc/tree-pass.h | 1 + 4 files changed, 116 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 992cd5360b9..4706ad99f10 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-03-26 Jan Hubicka + + 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 * ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 73e80e8b141..a4cdae9508b 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -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); +} diff --git a/gcc/passes.def b/gcc/passes.def index c839b7984ca..1d598b29997 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -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); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index b59ae7a39d6..bc8763db165 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -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); -- 2.30.2