/* Control flow optimization code for GNU compiler.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
#include "dce.h"
#include "dbgcnt.h"
#include "rtl-iter.h"
+#include "regs.h"
#define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK)
|| !rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1)))
return NULL;
+ /* Punt if BB_END (e->src) is doloop-like conditional jump that modifies
+ the registers used in cond1. */
+ if (modified_in_p (cond1, BB_END (e->src)))
+ return NULL;
+
/* Short circuit cases where block B contains some side effects, as we can't
safely bypass it. */
for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b));
insn != NEXT_INSN (BB_END (b)) && !failed;
insn = NEXT_INSN (insn))
{
+ /* cond2 must not mention any register that is not equal to the
+ former block. Check this before processing that instruction,
+ as BB_END (b) could contain also clobbers. */
+ if (insn == BB_END (b)
+ && mentions_nonequal_regs (cond2, nonequal))
+ goto failed_exit;
+
if (INSN_P (insn))
{
rtx pat = PATTERN (insn);
goto failed_exit;
}
- /* cond2 must not mention any register that is not equal to the
- former block. */
- if (mentions_nonequal_regs (cond2, nonequal))
- goto failed_exit;
-
EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi)
goto failed_exit;
}
}
}
+
+ HARD_REG_SET i1_used, i2_used;
+
+ get_call_reg_set_usage (i1, &i1_used, call_used_reg_set);
+ get_call_reg_set_usage (i2, &i2_used, call_used_reg_set);
+
+ if (!hard_reg_set_equal_p (i1_used, i2_used))
+ return dir_none;
}
/* If both i1 and i2 are frame related, verify all the CFA notes
if (crtl->shrink_wrapped
&& single_succ_p (bb1)
&& single_succ (bb1) == EXIT_BLOCK_PTR_FOR_FN (cfun)
- && !JUMP_P (BB_END (bb1))
+ && (!JUMP_P (BB_END (bb1))
+ /* Punt if the only successor is a fake edge to exit, the jump
+ must be some weird one. */
+ || (single_succ_edge (bb1)->flags & EDGE_FAKE) != 0)
&& !(CALL_P (BB_END (bb1)) && SIBLING_CALL_P (BB_END (bb1))))
return false;
-
+
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (single_succ_p (bb1)
if (current_ir_type () == IR_RTL_CFGLAYOUT)
{
- if (BB_FOOTER (b)
- && BARRIER_P (BB_FOOTER (b)))
+ rtx_insn *insn;
+ for (insn = BB_FOOTER (b);
+ insn; insn = NEXT_INSN (insn))
+ if (BARRIER_P (insn))
+ break;
+ if (insn)
FOR_EACH_EDGE (e, ei, b->preds)
- if ((e->flags & EDGE_FALLTHRU)
- && BB_FOOTER (e->src) == NULL)
+ if ((e->flags & EDGE_FALLTHRU))
{
- if (BB_FOOTER (b))
+ if (BB_FOOTER (b)
+ && BB_FOOTER (e->src) == NULL)
{
BB_FOOTER (e->src) = BB_FOOTER (b);
BB_FOOTER (b) = NULL;
}
else
- {
- start_sequence ();
- BB_FOOTER (e->src) = emit_barrier ();
- end_sequence ();
- }
+ emit_barrier_after_bb (e->src);
}
}
else
&& !delete_trivially_dead_insns (get_insns (), max_reg_num ()))
break;
if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occurred)
- run_fast_dce ();
+ {
+ run_fast_dce ();
+ mode &= ~CLEANUP_FORCE_FAST_DCE;
+ }
}
else
break;
if (mode & CLEANUP_CROSSJUMP)
remove_fake_exit_edges ();
+ if (mode & CLEANUP_FORCE_FAST_DCE)
+ run_fast_dce ();
+
/* Don't call delete_dead_jumptables in cfglayout mode, because
that function assumes that jump tables are in the insns stream.
But we also don't _have_ to delete dead jumptables in cfglayout
\f
namespace {
+const pass_data pass_data_postreload_jump =
+{
+ RTL_PASS, /* type */
+ "postreload_jump", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_JUMP, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_postreload_jump : public rtl_opt_pass
+{
+public:
+ pass_postreload_jump (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_postreload_jump, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *);
+
+}; // class pass_postreload_jump
+
+unsigned int
+pass_postreload_jump::execute (function *)
+{
+ cleanup_cfg (flag_thread_jumps ? CLEANUP_THREADING : 0);
+ return 0;
+}
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_postreload_jump (gcc::context *ctxt)
+{
+ return new pass_postreload_jump (ctxt);
+}
+
+namespace {
+
const pass_data pass_data_jump2 =
{
RTL_PASS, /* type */