/* Control flow optimization code for GNU compiler.
- Copyright (C) 1987-2019 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "insn-config.h"
#include "emit-rtl.h"
#include "cselib.h"
-#include "params.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "cfgrtl.h"
#include "dce.h"
#include "dbgcnt.h"
#include "rtl-iter.h"
+#include "regs.h"
+#include "function-abi.h"
#define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK)
bool failed = false;
reg_set_iterator rsi;
+ /* Jump threading may cause fixup_partitions to introduce new crossing edges,
+ which is not allowed after reload. */
+ gcc_checking_assert (!reload_completed || !crtl->has_bb_partition);
+
if (b->flags & BB_NONTHREADABLE_BLOCK)
return NULL;
|| !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));
}
}
}
+
+ if (insn_callee_abi (i1) != insn_callee_abi (i2))
+ return dir_none;
}
/* If both i1 and i2 are frame related, verify all the CFA notes
if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0)))
SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0)));
- if (!hard_reg_set_equal_p (i1_regset, i2_regset))
+ if (i1_regset != i2_regset)
return dir_none;
}
#endif
of matching instructions or the 'from' block was totally matched
(such that its predecessors will hopefully be redirected and the
block removed). */
- if ((nmatch < PARAM_VALUE (PARAM_MIN_CROSSJUMP_INSNS))
+ if ((nmatch < param_min_crossjump_insns)
&& (newpos1 != BB_HEAD (src1)))
return false;
a block that falls through into BB, as that adds no branches to the
program. We'll try that combination first. */
fallthru = NULL;
- max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES);
+ max = param_max_crossjump_edges;
if (EDGE_COUNT (bb->preds) > max)
return false;
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 =
+const pass_data pass_data_jump_after_combine =
{
RTL_PASS, /* type */
- "postreload_jump", /* name */
+ "jump_after_combine", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_JUMP, /* tv_id */
0, /* properties_required */
0, /* todo_flags_finish */
};
-class pass_postreload_jump : public rtl_opt_pass
+class pass_jump_after_combine : public rtl_opt_pass
{
public:
- pass_postreload_jump (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_postreload_jump, ctxt)
+ pass_jump_after_combine (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_jump_after_combine, ctxt)
{}
/* opt_pass methods: */
+ virtual bool gate (function *) { return flag_thread_jumps; }
virtual unsigned int execute (function *);
-}; // class pass_postreload_jump
+}; // class pass_jump_after_combine
unsigned int
-pass_postreload_jump::execute (function *)
+pass_jump_after_combine::execute (function *)
{
- cleanup_cfg (flag_thread_jumps ? CLEANUP_THREADING : 0);
+ /* Jump threading does not keep dominators up-to-date. */
+ free_dominance_info (CDI_DOMINATORS);
+ cleanup_cfg (CLEANUP_THREADING);
return 0;
}
} // anon namespace
rtl_opt_pass *
-make_pass_postreload_jump (gcc::context *ctxt)
+make_pass_jump_after_combine (gcc::context *ctxt)
{
- return new pass_postreload_jump (ctxt);
+ return new pass_jump_after_combine (ctxt);
}
namespace {