summaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh_treg_combine.cc
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-12-17 23:08:14 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-12-17 23:08:14 +0000
commitb578ea749cc137c610c16e646507693fcd4e4f77 (patch)
tree0712f51fab9bdec89bec5432d03c151f3e270220 /gcc/config/sh/sh_treg_combine.cc
parent195ead9a6952c6f4b34a5dae6822b36ca84c3df2 (diff)
downloadgcc-b578ea749cc137c610c16e646507693fcd4e4f77.tar.gz
gcc/
PR target/51244 * config/sh/sh_treg_combine.cc (is_conditional_insn): New function. (cbranch_trace): Add member rtx* condition_rtx_in_insn, initialize it accordingly in constructor. (cbranch_trace::branch_condition_rtx_ref): New function. (cbranch_trace::branch_condition_rtx): Use branch_condition_rtx_ref. (sh_treg_combine::try_invert_branch_condition): Invert condition rtx in insn using reversed_comparison_code and validate_change instead of invert_jump_1. (sh_treg_combine::execute): Look for conditional insns in basic blocks in addition to conditional branches. * config/sh/sh.md (*movsicc_div0s): Remove combine patterns. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@218850 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sh/sh_treg_combine.cc')
-rw-r--r--gcc/config/sh/sh_treg_combine.cc62
1 files changed, 54 insertions, 8 deletions
diff --git a/gcc/config/sh/sh_treg_combine.cc b/gcc/config/sh/sh_treg_combine.cc
index 62392d81f1b..97e677da50c 100644
--- a/gcc/config/sh/sh_treg_combine.cc
+++ b/gcc/config/sh/sh_treg_combine.cc
@@ -432,6 +432,16 @@ trace_reg_uses (rtx reg, rtx_insn *start_insn, rtx abort_at_insn)
return count;
}
+static bool
+is_conditional_insn (rtx_insn* i)
+{
+ if (! (INSN_P (i) && NONDEBUG_INSN_P (i)))
+ return false;
+
+ rtx p = PATTERN (i);
+ return GET_CODE (p) == SET && GET_CODE (XEXP (p, 1)) == IF_THEN_ELSE;
+}
+
// FIXME: Remove dependency on SH predicate function somehow.
extern int t_reg_operand (rtx, machine_mode);
extern int negt_reg_operand (rtx, machine_mode);
@@ -484,6 +494,7 @@ private:
struct cbranch_trace
{
rtx_insn *cbranch_insn;
+ rtx* condition_rtx_in_insn;
branch_condition_type_t cbranch_type;
// The comparison against zero right before the conditional branch.
@@ -495,9 +506,14 @@ private:
cbranch_trace (rtx_insn *insn)
: cbranch_insn (insn),
+ condition_rtx_in_insn (NULL),
cbranch_type (unknown_branch_condition),
setcc ()
{
+ if (is_conditional_insn (cbranch_insn))
+ condition_rtx_in_insn = &XEXP (XEXP (PATTERN (cbranch_insn), 1), 0);
+ else if (rtx x = pc_set (cbranch_insn))
+ condition_rtx_in_insn = &XEXP (XEXP (x, 1), 0);
}
basic_block bb (void) const { return BLOCK_FOR_INSN (cbranch_insn); }
@@ -505,8 +521,16 @@ private:
rtx
branch_condition_rtx (void) const
{
- rtx x = pc_set (cbranch_insn);
- return x == NULL_RTX ? NULL_RTX : XEXP (XEXP (x, 1), 0);
+ return condition_rtx_in_insn != NULL ? *condition_rtx_in_insn : NULL;
+ }
+ rtx&
+ branch_condition_rtx_ref (void) const
+ {
+ // Before anything gets to invoke this function, there are other checks
+ // in place to make sure that we have a known branch condition and thus
+ // the ref to the rtx in the insn.
+ gcc_assert (condition_rtx_in_insn != NULL);
+ return *condition_rtx_in_insn;
}
bool
@@ -1033,8 +1057,18 @@ sh_treg_combine::try_invert_branch_condition (cbranch_trace& trace)
{
log_msg ("inverting branch condition\n");
- if (!invert_jump_1 (trace.cbranch_insn, JUMP_LABEL (trace.cbranch_insn)))
- log_return (false, "invert_jump_1 failed\n");
+ rtx& comp = trace.branch_condition_rtx_ref ();
+
+ rtx_code rev_cmp_code = reversed_comparison_code (comp, trace.cbranch_insn);
+
+ if (rev_cmp_code == UNKNOWN)
+ log_return (false, "reversed_comparison_code = UNKNOWN\n");
+
+ validate_change (trace.cbranch_insn, &comp,
+ gen_rtx_fmt_ee (rev_cmp_code,
+ GET_MODE (comp), XEXP (comp, 0),
+ XEXP (comp, 1)),
+ 1);
if (verify_changes (num_validated_changes ()))
confirm_change_group ();
@@ -1531,14 +1565,26 @@ sh_treg_combine::execute (function *fun)
log_rtx (m_ccreg);
log_msg (" STORE_FLAG_VALUE = %d\n", STORE_FLAG_VALUE);
- // Look for basic blocks that end with a conditional branch and try to
- // optimize them.
+ // Look for basic blocks that end with a conditional branch or for
+ // conditional insns and try to optimize them.
basic_block bb;
FOR_EACH_BB_FN (bb, fun)
{
- rtx_insn *i = BB_END (bb);
+ rtx_insn* i = BB_END (bb);
+ if (i == NULL || i == PREV_INSN (BB_HEAD (bb)))
+ continue;
+
+ // A conditional branch is always the last insn of a basic block.
if (any_condjump_p (i) && onlyjump_p (i))
- try_optimize_cbranch (i);
+ {
+ try_optimize_cbranch (i);
+ i = PREV_INSN (i);
+ }
+
+ // Check all insns in block for conditional insns.
+ for (; i != NULL && i != PREV_INSN (BB_HEAD (bb)); i = PREV_INSN (i))
+ if (is_conditional_insn (i))
+ try_optimize_cbranch (i);
}
log_msg ("\n\n");