From 89f8797ee13b8ce48c50ad829cf0989564b5bfb8 Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Wed, 17 Dec 2014 23:08:14 +0000 Subject: [PATCH] re PR target/51244 ([SH] Inefficient conditional branch and code around T bit) 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. From-SVN: r218850 --- gcc/ChangeLog | 15 ++++++++ gcc/config/sh/sh.md | 41 --------------------- gcc/config/sh/sh_treg_combine.cc | 62 +++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 49 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00b37280adc..f9e1af53b42 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2014-12-17 Oleg Endo + + 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. + 2014-12-17 Oleg Endo PR target/51244 diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 644dd06a966..5aa50a25af9 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -1086,47 +1086,6 @@ (label_ref (match_dup 2)) (pc)))]) -;; Conditional move combine pattern for div0s comparisons. -;; This is used when TARGET_PRETEND_CMOVE is in effect. -(define_insn_and_split "*movsicc_div0s" - [(set (match_operand:SI 0 "arith_reg_dest" "") - (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "") - (match_operand:SI 2 "arith_reg_operand" "")) - (const_int 0)) - (match_operand:SI 3 "arith_reg_operand" "") - (match_operand:SI 4 "general_movsrc_operand" ""))) - (clobber (reg:SI T_REG))] - "TARGET_PRETEND_CMOVE" - "#" - "&& 1" - [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2)) - (const_int 0))) - (set (match_dup 0) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (match_dup 4) - (match_dup 3)))]) - -(define_insn_and_split "*movsicc_div0s" - [(set (match_operand:SI 0 "arith_reg_dest") - (if_then_else:SI (eq (lshiftrt:SI - (match_operand:SI 1 "arith_reg_operand") - (const_int 31)) - (lshiftrt:SI - (match_operand:SI 2 "arith_reg_operand") - (const_int 31))) - (match_operand:SI 3 "arith_reg_operand") - (match_operand:SI 4 "general_movsrc_operand"))) - (clobber (reg:SI T_REG))] - "TARGET_PRETEND_CMOVE" - "#" - "&& 1" - [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2)) - (const_int 0))) - (set (match_dup 0) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (match_dup 4) - (match_dup 3)))]) - ;; ------------------------------------------------------------------------- ;; SImode unsigned integer comparisons ;; ------------------------------------------------------------------------- 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");