diff options
author | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-07-02 19:23:56 +0000 |
---|---|---|
committer | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-07-02 19:23:56 +0000 |
commit | a6be78214b09079e38f8950d7a5b06039d017cd4 (patch) | |
tree | 38e129004dd353049b54d9731e1f700766fd9cde /gcc | |
parent | b1039d0226ef24ed25257d064ff4c181ce7c4d4c (diff) | |
download | ppe42-gcc-a6be78214b09079e38f8950d7a5b06039d017cd4.tar.gz ppe42-gcc-a6be78214b09079e38f8950d7a5b06039d017cd4.zip |
PR target/51244
* config/sh/predicates.md (t_reg_operand, negt_reg_operand): New
predicates.
* config/sh/sh-protos.h (get_t_reg_rtx): New prototype.
* config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking
gen_branch_true and gen_branch_false.
* config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and
gen_branch_false.
(branch_true, branch_false): Use t_reg_operand predicate.
(*branch_true, *branch_false): Delete.
(movt): Use t_reg_operand predicate.
(*negnegt): Use negt_reg_operand predicate and fold little and big
endian variants.
(*movtt): Use t_reg_operand and fold little and big endian variants.
(*movt_qi): Delete.
PR target/51244
* gcc.target/sh/pr51244-1.c: Check that movt insn is not generated.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189177 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/config/sh/predicates.md | 39 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 27 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 113 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-1.c | 2 |
7 files changed, 98 insertions, 107 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bee63bb8f13..231e624be89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2012-07-02 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * config/sh/predicates.md (t_reg_operand, negt_reg_operand): New + predicates. + * config/sh/sh-protos.h (get_t_reg_rtx): New prototype. + * config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking + gen_branch_true and gen_branch_false. + * config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and + gen_branch_false. + (branch_true, branch_false): Use t_reg_operand predicate. + (*branch_true, *branch_false): Delete. + (movt): Use t_reg_operand predicate. + (*negnegt): Use negt_reg_operand predicate and fold little and big + endian variants. + (*movtt): Use t_reg_operand and fold little and big endian variants. + (*movt_qi): Delete. + 2012-07-02 Steven Bosscher <steven@gcc.gnu.org> * stmt.c (emit_case_bit_tests): Remove. diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index f75675ec096..d58f657c857 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -898,3 +898,42 @@ (match_test "mode != HImode") (match_test "TARGET_SH4A_ARCH")))) +;; A predicate describing the T bit register in any form. +(define_predicate "t_reg_operand" + (match_code "reg,subreg,sign_extend,zero_extend") +{ + switch (GET_CODE (op)) + { + case REG: + return REGNO (op) == T_REG; + + case SUBREG: + return REGNO (SUBREG_REG (op)) == T_REG; + + case ZERO_EXTEND: + case SIGN_EXTEND: + return GET_CODE (XEXP (op, 0)) == SUBREG + && REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG; + + default: + return 0; + } +}) + +;; A predicate describing a negated T bit register. +(define_predicate "negt_reg_operand" + (match_code "subreg,xor") +{ + switch (GET_CODE (op)) + { + case XOR: + return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) + && satisfies_constraint_M (XEXP (op, 1)); + + case SUBREG: + return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))); + + default: + return 0; + } +}) diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index cb9ad0f203f..3fcfe29a28a 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -109,6 +109,7 @@ extern bool sh_vector_mode_supported_p (enum machine_mode); #endif /* RTX_CODE */ extern const char *output_jump_label_table (void); +extern rtx get_t_reg_rtx (void); extern rtx get_fpscr_rtx (void); extern int sh_media_register_for_return (void); extern void sh_expand_prologue (void); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 7e0c2c17515..77324b66c94 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1874,7 +1874,7 @@ prepare_cbranch_operands (rtx *operands, enum machine_mode mode, void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability) { - rtx (*branch_expander) (rtx) = gen_branch_true; + rtx (*branch_expander) (rtx, rtx) = gen_branch_true; rtx jump; comparison = prepare_cbranch_operands (operands, SImode, comparison); @@ -1888,7 +1888,7 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability) emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, T_REG), gen_rtx_fmt_ee (comparison, SImode, operands[1], operands[2]))); - jump = emit_jump_insn (branch_expander (operands[3])); + jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ())); if (probability >= 0) add_reg_note (jump, REG_BR_PROB, GEN_INT (probability)); @@ -1941,7 +1941,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison) if (TARGET_CMPEQDI_T) { emit_insn (gen_cmpeqdi_t (operands[1], operands[2])); - emit_jump_insn (gen_branch_true (operands[3])); + emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ())); return true; } msw_skip = NE; @@ -1969,7 +1969,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison) if (TARGET_CMPEQDI_T) { emit_insn (gen_cmpeqdi_t (operands[1], operands[2])); - emit_jump_insn (gen_branch_false (operands[3])); + emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ())); return true; } msw_taken = NE; @@ -2304,9 +2304,9 @@ sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode) sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode); if (branch_code == code) - emit_jump_insn (gen_branch_true (operands[3])); + emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ())); else - emit_jump_insn (gen_branch_false (operands[3])); + emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ())); } void @@ -2340,7 +2340,7 @@ sh_emit_compare_and_set (rtx *operands, enum machine_mode mode) { lab = gen_label_rtx (); sh_emit_scc_to_t (EQ, op0, op1); - emit_jump_insn (gen_branch_true (lab)); + emit_jump_insn (gen_branch_true (lab, get_t_reg_rtx ())); code = GT; } else @@ -3360,7 +3360,7 @@ gen_shifty_op (int code, rtx *operands) if (code == LSHIFTRT) { emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); - emit_insn (gen_movt (operands[0])); + emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); return; } else if (code == ASHIFT) @@ -9504,6 +9504,15 @@ reg_unused_after (rtx reg, rtx insn) #include "ggc.h" +static GTY(()) rtx t_reg_rtx; +rtx +get_t_reg_rtx (void) +{ + if (! t_reg_rtx) + t_reg_rtx = gen_rtx_REG (SImode, T_REG); + return t_reg_rtx; +} + static GTY(()) rtx fpscr_rtx; rtx get_fpscr_rtx (void) @@ -12049,7 +12058,7 @@ sh_expand_t_scc (rtx operands[]) result = gen_reg_rtx (SImode); val = INTVAL (op1); if ((code == EQ && val == 1) || (code == NE && val == 0)) - emit_insn (gen_movt (result)); + emit_insn (gen_movt (result, get_t_reg_rtx ())); else if ((code == EQ && val == 0) || (code == NE && val == 1)) emit_insn (gen_movnegt (result)); else if (code == EQ || code == NE) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 852f9fd36ea..4e2425f4888 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -4450,8 +4450,8 @@ label: emit_insn (gen_movsi (operands[0], operands[1])); emit_jump_insn (INTVAL (operands[3]) - ? gen_branch_true (skip_neg_label) - : gen_branch_false (skip_neg_label)); + ? gen_branch_true (skip_neg_label, get_t_reg_rtx ()) + : gen_branch_false (skip_neg_label, get_t_reg_rtx ())); emit_label_after (skip_neg_label, emit_insn (gen_negsi2 (operands[0], operands[1]))); @@ -4519,8 +4519,8 @@ label: emit_insn (gen_movsi (high_dst, high_src)); emit_jump_insn (INTVAL (operands[3]) - ? gen_branch_true (skip_neg_label) - : gen_branch_false (skip_neg_label)); + ? gen_branch_true (skip_neg_label, get_t_reg_rtx ()) + : gen_branch_false (skip_neg_label, get_t_reg_rtx ())); if (!INTVAL (operands[3])) emit_insn (gen_clrt ()); @@ -7195,66 +7195,22 @@ label: ;; ------------------------------------------------------------------------ (define_insn "branch_true" - [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_SH1" -{ - return output_branch (1, insn, operands); -} - [(set_attr "type" "cbranch")]) - -;; The *branch_true patterns help combine when trying to invert conditions. -(define_insn "*branch_true" - [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)) + [(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "") (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_SH1 && TARGET_LITTLE_ENDIAN" -{ - return output_branch (1, insn, operands); -} - [(set_attr "type" "cbranch")]) - -(define_insn "*branch_true" - [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN" + "TARGET_SH1" { return output_branch (1, insn, operands); } [(set_attr "type" "cbranch")]) (define_insn "branch_false" - [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_SH1" -{ - return output_branch (0, insn, operands); -} - [(set_attr "type" "cbranch")]) - -;; The *branch_false patterns help combine when trying to invert conditions. -(define_insn "*branch_false" - [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_SH1 && TARGET_LITTLE_ENDIAN" -{ - return output_branch (0, insn, operands); -} - [(set_attr "type" "cbranch")]) - -(define_insn "*branch_false" - [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)) + [(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "") (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN" + "TARGET_SH1" { return output_branch (0, insn, operands); } @@ -9672,7 +9628,7 @@ label: (define_insn "movt" [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (eq:SI (reg:SI T_REG) (const_int 1)))] + (match_operand:SI 1 "t_reg_operand"))] "TARGET_SH1" "movt %0" [(set_attr "type" "arith")]) @@ -9854,62 +9810,25 @@ label: "negc %1,%0" [(set_attr "type" "arith")]) -;; The *negnegt patterns help the combine pass to figure out how to fold +;; The *negnegt pattern helps the combine pass to figure out how to fold ;; an explicit double T bit negation. (define_insn_and_split "*negnegt" [(set (reg:SI T_REG) - (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3) - (const_int 0)))] - "! TARGET_LITTLE_ENDIAN" - "#" - "" - [(const_int 0)]) - -(define_insn_and_split "*negnegt" - [(set (reg:SI T_REG) - (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0) - (const_int 0)))] - "TARGET_LITTLE_ENDIAN" - "#" - "" - [(const_int 0)]) - -;; The *movtt patterns eliminate redundant T bit to T bit moves / tests. -(define_insn_and_split "*movtt" - [(set (reg:SI T_REG) - (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)) - (const_int 1)))] - "! TARGET_LITTLE_ENDIAN" + (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))] + "TARGET_SH1" "#" "" [(const_int 0)]) +;; The *movtt pattern eliminates redundant T bit to T bit moves / tests. (define_insn_and_split "*movtt" [(set (reg:SI T_REG) - (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)) - (const_int 1)))] - "TARGET_LITTLE_ENDIAN" + (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))] + "TARGET_SH1" "#" "" [(const_int 0)]) -;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern -;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function -;; returns the inverted T bit value. -(define_insn "*movt_qi" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))] - "! TARGET_LITTLE_ENDIAN" - "movt %0" - [(set_attr "type" "arith")]) - -(define_insn "*movt_qi" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))] - "TARGET_LITTLE_ENDIAN" - "movt %0" - [(set_attr "type" "arith")]) - (define_expand "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "sh_float_comparison_operator" @@ -13960,7 +13879,7 @@ label: else { emit_insn (gen_stack_protect_test_si (operands[0], operands[1])); - emit_jump_insn (gen_branch_true (operands[2])); + emit_jump_insn (gen_branch_true (operands[2], get_t_reg_rtx ())); } DONE; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b62e76f0b4f..916fcfbb606 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-07-02 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * gcc.target/sh/pr51244-1.c: Check that movt insn is not generated. + 2012-07-02 Jason Merrill <jason@redhat.com> PR c++/53821 diff --git a/gcc/testsuite/gcc.target/sh/pr51244-1.c b/gcc/testsuite/gcc.target/sh/pr51244-1.c index 34e1b023326..601c1c1c269 100644 --- a/gcc/testsuite/gcc.target/sh/pr51244-1.c +++ b/gcc/testsuite/gcc.target/sh/pr51244-1.c @@ -4,7 +4,7 @@ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1 -mbranch-cost=2" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-not "tst|negc|extu" } } */ +/* { dg-final { scan-assembler-not "movt|tst|negc|extu" } } */ int testfunc_00 (int a, int b, int c, int d) |