Commit 0bc69b81 by Joern Rennecke Committed by Joern Rennecke

arc.c (arc_predicate_delay_insns): New function.

        * config/arc/arc.c (arc_predicate_delay_insns): New function.
        (pass_data_arc_predicate_delay_insns): New pass_data instance.
        (pass_arc_predicate_delay_insns): New subclass of rtl_opt_class.
        (make_pass_arc_predicate_delay_insns): New function.
        (arc_init): Register pass_arc_predicate_delay_insns if
        flag_delayed_branch is active.

From-SVN: r204901
parent 036def0f
2013-11-16 Joern Rennecke <joern.rennecke@embecosm.com> 2013-11-16 Joern Rennecke <joern.rennecke@embecosm.com>
* config/arc/arc.c (arc_predicate_delay_insns): New function.
(pass_data_arc_predicate_delay_insns): New pass_data instance.
(pass_arc_predicate_delay_insns): New subclass of rtl_opt_class.
(make_pass_arc_predicate_delay_insns): New function.
(arc_init): Register pass_arc_predicate_delay_insns if
flag_delayed_branch is active.
2013-11-16 Joern Rennecke <joern.rennecke@embecosm.com>
* config/arc/constraints.md (Rcq): Simplify register number test. * config/arc/constraints.md (Rcq): Simplify register number test.
2013-11-15 Aldy Hernandez <aldyh@redhat.com> 2013-11-15 Aldy Hernandez <aldyh@redhat.com>
...@@ -632,6 +632,44 @@ make_pass_arc_ifcvt (gcc::context *ctxt) ...@@ -632,6 +632,44 @@ make_pass_arc_ifcvt (gcc::context *ctxt)
return new pass_arc_ifcvt (ctxt); return new pass_arc_ifcvt (ctxt);
} }
static unsigned arc_predicate_delay_insns (void);
namespace {
const pass_data pass_data_arc_predicate_delay_insns =
{
RTL_PASS,
"arc_predicate_delay_insns", /* name */
OPTGROUP_NONE, /* optinfo_flags */
false, /* has_gate */
true, /* has_execute */
TV_IFCVT2, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_df_finish /* todo_flags_finish */
};
class pass_arc_predicate_delay_insns : public rtl_opt_pass
{
public:
pass_arc_predicate_delay_insns(gcc::context *ctxt)
: rtl_opt_pass(pass_data_arc_predicate_delay_insns, ctxt)
{}
/* opt_pass methods: */
unsigned int execute () { return arc_predicate_delay_insns (); }
};
} // anon namespace
rtl_opt_pass *
make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
{
return new pass_arc_predicate_delay_insns (ctxt);
}
/* Called by OVERRIDE_OPTIONS to initialize various things. */ /* Called by OVERRIDE_OPTIONS to initialize various things. */
void void
...@@ -752,6 +790,16 @@ arc_init (void) ...@@ -752,6 +790,16 @@ arc_init (void)
register_pass (&arc_ifcvt4_info); register_pass (&arc_ifcvt4_info);
register_pass (&arc_ifcvt5_info); register_pass (&arc_ifcvt5_info);
} }
if (flag_delayed_branch)
{
opt_pass *pass_arc_predicate_delay_insns
= make_pass_arc_predicate_delay_insns (g);
struct register_pass_info arc_predicate_delay_info
= { pass_arc_predicate_delay_insns, "dbr", 1, PASS_POS_INSERT_AFTER };
register_pass (&arc_predicate_delay_info);
}
} }
/* Check ARC options, generate derived target attributes. */ /* Check ARC options, generate derived target attributes. */
...@@ -8297,6 +8345,74 @@ arc_ifcvt (void) ...@@ -8297,6 +8345,74 @@ arc_ifcvt (void)
return 0; return 0;
} }
/* Find annulled delay insns and convert them to use the appropriate predicate.
This allows branch shortening to size up these insns properly. */
static unsigned
arc_predicate_delay_insns (void)
{
for (rtx insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx pat, jump, dlay, src, cond, *patp;
int reverse;
if (!NONJUMP_INSN_P (insn)
|| GET_CODE (pat = PATTERN (insn)) != SEQUENCE)
continue;
jump = XVECEXP (pat, 0, 0);
dlay = XVECEXP (pat, 0, 1);
if (!JUMP_P (jump) || !INSN_ANNULLED_BRANCH_P (jump))
continue;
/* If the branch insn does the annulling, leave the delay insn alone. */
if (!TARGET_AT_DBR_CONDEXEC && !INSN_FROM_TARGET_P (dlay))
continue;
/* ??? Could also leave DLAY un-conditionalized if its target is dead
on the other path. */
gcc_assert (GET_CODE (PATTERN (jump)) == SET);
gcc_assert (SET_DEST (PATTERN (jump)) == pc_rtx);
src = SET_SRC (PATTERN (jump));
gcc_assert (GET_CODE (src) == IF_THEN_ELSE);
cond = XEXP (src, 0);
if (XEXP (src, 2) == pc_rtx)
reverse = 0;
else if (XEXP (src, 1) == pc_rtx)
reverse = 1;
else
gcc_unreachable ();
if (!INSN_FROM_TARGET_P (dlay) != reverse)
{
enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
enum rtx_code code = reverse_condition (GET_CODE (cond));
if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
code = reverse_condition_maybe_unordered (GET_CODE (cond));
cond = gen_rtx_fmt_ee (code, GET_MODE (cond),
copy_rtx (XEXP (cond, 0)),
copy_rtx (XEXP (cond, 1)));
}
else
cond = copy_rtx (cond);
patp = &PATTERN (dlay);
pat = *patp;
/* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
what to do with COND_EXEC. */
if (RTX_FRAME_RELATED_P (dlay))
{
/* As this is the delay slot insn of an anulled branch,
dwarf2out.c:scan_trace understands the anulling semantics
without the COND_EXEC. */
rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
REG_NOTES (dlay));
validate_change (dlay, &REG_NOTES (dlay), note, 1);
}
pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
validate_change (dlay, patp, pat, 1);
if (!apply_change_group ())
gcc_unreachable ();
}
return 0;
}
/* For ARC600: If a write to a core reg >=32 appears in a delay slot /* For ARC600: If a write to a core reg >=32 appears in a delay slot
(other than of a forward brcc), it creates a hazard when there is a read (other than of a forward brcc), it creates a hazard when there is a read
of the same register at the branch target. We can't know what is at the of the same register at the branch target. We can't know what is at the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment