diff options
author | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-12-17 23:08:14 +0000 |
---|---|---|
committer | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-12-17 23:08:14 +0000 |
commit | b578ea749cc137c610c16e646507693fcd4e4f77 (patch) | |
tree | 0712f51fab9bdec89bec5432d03c151f3e270220 /gcc/config/sh/sh_treg_combine.cc | |
parent | 195ead9a6952c6f4b34a5dae6822b36ca84c3df2 (diff) | |
download | gcc-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.cc | 62 |
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"); |