From: Oleg Endo Date: Sat, 22 Nov 2014 15:06:34 +0000 (+0000) Subject: re PR target/63986 ([SH] gcc.target/sh/pr51244-15.c failures) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=355e99758bceb3ffed95a0c4fc41fb348e0109d3;p=gcc.git re PR target/63986 ([SH] gcc.target/sh/pr51244-15.c failures) gcc/ PR target/63986 PR target/51244 * config/sh/sh.c (sh_is_logical_t_store_expr, sh_try_omit_signzero_extend): Use rtx_insn* for insn argument. (sh_split_movrt_negc_to_movt_xor): New function. (sh_find_set_of_reg): Move to ... * config/sh/sh-protos.h (sh_find_set_of_reg): ... here and convert to template function. (set_of_reg): Use rtx_insn* for insn member. (sh_is_logical_t_store_expr, sh_try_omit_signzero_extend): Use rtx_insn* for insn argument. * config/sh/sh.md (movrt_negc, *movrt_negc): Split into movt-xor sequence using new sh_split_movrt_negc_to_movt_xor function. (movrt_xor): Allow also for SH2A. (*movt_movrt): Delete insns and splits. From-SVN: r217968 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08ee16aa574..bbab5022ffd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2014-11-22 Oleg Endo + + PR target/63986 + PR target/51244 + * config/sh/sh.c (sh_is_logical_t_store_expr, + sh_try_omit_signzero_extend): Use rtx_insn* for insn argument. + (sh_split_movrt_negc_to_movt_xor): New function. + (sh_find_set_of_reg): Move to ... + * config/sh/sh-protos.h (sh_find_set_of_reg): ... here and convert + to template function. + (set_of_reg): Use rtx_insn* for insn member. + (sh_is_logical_t_store_expr, sh_try_omit_signzero_extend): Use + rtx_insn* for insn argument. + * config/sh/sh.md (movrt_negc, *movrt_negc): Split into movt-xor + sequence using new sh_split_movrt_negc_to_movt_xor function. + (movrt_xor): Allow also for SH2A. + (*movt_movrt): Delete insns and splits. + 2014-11-22 Marc Glisse PR tree-optimization/60770 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index e01b91e2db7..262c4fb556a 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -165,7 +165,7 @@ struct set_of_reg { /* The insn where sh_find_set_of_reg stopped looking. Can be NULL_RTX if the end of the insn list was reached. */ - rtx insn; + rtx_insn* insn; /* The set rtx of the specified reg if found, NULL_RTX otherwise. */ const_rtx set_rtx; @@ -175,9 +175,47 @@ struct set_of_reg rtx set_src; }; -extern set_of_reg sh_find_set_of_reg (rtx reg, rtx insn, rtx_insn *(*stepfunc)(rtx)); -extern bool sh_is_logical_t_store_expr (rtx op, rtx insn); -extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx insn); +/* Given a reg rtx and a start insn, try to find the insn that sets the + specified reg by using the specified insn stepping function, such as + 'prev_nonnote_insn_bb'. When the insn is found, try to extract the rtx + of the reg set. */ +template inline set_of_reg +sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc) +{ + set_of_reg result; + result.insn = insn; + result.set_rtx = NULL_RTX; + result.set_src = NULL_RTX; + + if (!REG_P (reg) || insn == NULL_RTX) + return result; + + for (result.insn = stepfunc (insn); result.insn != NULL_RTX; + result.insn = stepfunc (result.insn)) + { + if (BARRIER_P (result.insn)) + return result; + if (!NONJUMP_INSN_P (result.insn)) + continue; + if (reg_set_p (reg, result.insn)) + { + result.set_rtx = set_of (reg, result.insn); + + if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET) + return result; + + result.set_src = XEXP (result.set_rtx, 1); + return result; + } + } + + return result; +} + +extern bool sh_is_logical_t_store_expr (rtx op, rtx_insn* insn); +extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn); +extern bool sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn, + rtx operands[]); #endif /* RTX_CODE */ extern void sh_cpu_cpp_builtins (cpp_reader* pfile); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index d6d50a4e8c1..f578b43976b 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -13503,47 +13503,10 @@ sh_find_equiv_gbr_addr (rtx_insn* insn, rtx mem) Manual insn combine support code. */ -/* Given a reg rtx and a start insn, try to find the insn that sets the - specified reg by using the specified insn stepping function, such as - 'prev_nonnote_insn_bb'. When the insn is found, try to extract the rtx - of the reg set. */ -set_of_reg -sh_find_set_of_reg (rtx reg, rtx insn, rtx_insn *(*stepfunc)(rtx)) -{ - set_of_reg result; - result.insn = insn; - result.set_rtx = NULL_RTX; - result.set_src = NULL_RTX; - - if (!REG_P (reg) || insn == NULL_RTX) - return result; - - for (result.insn = stepfunc (insn); result.insn != NULL_RTX; - result.insn = stepfunc (result.insn)) - { - if (BARRIER_P (result.insn)) - return result; - if (!NONJUMP_INSN_P (result.insn)) - continue; - if (reg_set_p (reg, result.insn)) - { - result.set_rtx = set_of (reg, result.insn); - - if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET) - return result; - - result.set_src = XEXP (result.set_rtx, 1); - return result; - } - } - - return result; -} - /* Given an op rtx and an insn, try to find out whether the result of the specified op consists only of logical operations on T bit stores. */ bool -sh_is_logical_t_store_expr (rtx op, rtx insn) +sh_is_logical_t_store_expr (rtx op, rtx_insn* insn) { if (!logical_operator (op, SImode)) return false; @@ -13579,7 +13542,7 @@ sh_is_logical_t_store_expr (rtx op, rtx insn) by a simple reg-reg copy. If so, the replacement reg rtx is returned, NULL_RTX otherwise. */ rtx -sh_try_omit_signzero_extend (rtx extended_op, rtx insn) +sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn) { if (REG_P (extended_op)) extended_op = extended_op; @@ -13609,6 +13572,42 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn) return NULL_RTX; } +/* Given the current insn, which is assumed to be a movrt_negc insn, try to + figure out whether it should be converted into a movt-xor sequence in + the movrt_negc splitter. + Returns true if insns have been modified and the splitter has succeeded. */ +bool +sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn, rtx operands[]) +{ + /* In cases such as + tst r4,r4 + mov #-1,r1 + negc r1,r1 + tst r4,r4 + we can replace the T bit clobbering negc with a movt-xor sequence and + eliminate the redundant comparison. + Because the xor insn depends on register allocation results, allow this + only before reload. */ + if (!can_create_pseudo_p ()) + return false; + + set_of_reg t_before_negc = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn, + prev_nonnote_insn_bb); + set_of_reg t_after_negc = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn, + next_nonnote_insn_bb); + + if (t_before_negc.set_rtx != NULL_RTX && t_after_negc.set_rtx != NULL_RTX + && rtx_equal_p (t_before_negc.set_rtx, t_after_negc.set_rtx) + && !reg_used_between_p (get_t_reg_rtx (), curr_insn, t_after_negc.insn)) + { + emit_insn (gen_movrt_xor (operands[0], get_t_reg_rtx ())); + set_insn_deleted (t_after_negc.insn); + return true; + } + else + return false; +} + static void sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode, int prev_mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 7b902953ac6..085a806e9f5 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -11445,13 +11445,21 @@ label: DONE; }) -(define_insn "movrt_negc" +(define_insn_and_split "movrt_negc" [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1))) + (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) (set (reg:SI T_REG) (const_int 1)) (use (match_operand:SI 2 "arith_reg_operand" "r"))] "TARGET_SH1" "negc %2,%0" + "&& 1" + [(const_int 0)] +{ + if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) + DONE; + else + FAIL; +} [(set_attr "type" "arith")]) ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the @@ -11460,17 +11468,25 @@ label: ;; generating a pseudo reg before reload. (define_insn_and_split "*movrt_negc" [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1))) + (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) (clobber (match_scratch:SI 2 "=r")) (clobber (reg:SI T_REG))] "TARGET_SH1 && ! TARGET_SH2A" "#" - "&& reload_completed" - [(set (match_dup 2) (const_int -1)) - (parallel - [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1))) - (set (reg:SI T_REG) (const_int 1)) - (use (match_dup 2))])]) + "&& 1" + [(const_int 0)] +{ + if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) + DONE; + else if (reload_completed) + { + emit_move_insn (operands[2], gen_int_mode (-1, SImode)); + emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2])); + DONE; + } + else + FAIL; +}) ;; Store the negated T bit in a reg using r0 and xor. This one doesn't ;; clobber the T bit, which is useful when storing the T bit and the @@ -11481,45 +11497,12 @@ label: [(set (match_operand:SI 0 "arith_reg_dest" "=z") (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) (use (reg:SI T_REG))] - "TARGET_SH1 && !TARGET_SH2A" + "TARGET_SH1" "#" "&& reload_completed" [(set (match_dup 0) (reg:SI T_REG)) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]) -;; Store the T bit and the negated T bit in two regs in parallel. There is -;; no real insn to do that, but specifying this pattern will give combine -;; some opportunities. -(define_insn_and_split "*movt_movrt" - [(parallel [(set (match_operand:SI 0 "arith_reg_dest") - (match_operand:SI 1 "negt_reg_operand")) - (set (match_operand:SI 2 "arith_reg_dest") - (match_operand:SI 3 "t_reg_operand"))])] - "TARGET_SH1" - "#" - "&& 1" - [(const_int 0)] -{ - rtx i = TARGET_SH2A - ? gen_movrt (operands[0], get_t_reg_rtx ()) - : gen_movrt_xor (operands[0], get_t_reg_rtx ()); - - emit_insn (i); - emit_insn (gen_movt (operands[2], get_t_reg_rtx ())); - DONE; -}) - -(define_insn_and_split "*movt_movrt" - [(parallel [(set (match_operand:SI 0 "arith_reg_dest") - (match_operand:SI 1 "t_reg_operand")) - (set (match_operand:SI 2 "arith_reg_dest") - (match_operand:SI 3 "negt_reg_operand"))])] - "TARGET_SH1" - "#" - "&& 1" - [(parallel [(set (match_dup 2) (match_dup 3)) - (set (match_dup 0) (match_dup 1))])]) - ;; Use negc to store the T bit in a MSB of a reg in the following way: ;; T = 1: 0x80000000 -> reg ;; T = 0: 0x7FFFFFFF -> reg