aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/ipa-pure-const.c104
-rw-r--r--gcc/passes.def1
-rw-r--r--gcc/tree-pass.h1
4 files changed, 116 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 992cd53..4706ad9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 73e80e8..a4cdae9 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 c839b79..1d598b2 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 b59ae7a..bc8763d 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);