diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-09-19 17:48:25 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-09-19 17:48:25 +0000 |
commit | 4eddc42b63d1064dfb0fd4c4820616f672e0ccfa (patch) | |
tree | 5ed220b6357cc817fb1a12638afc59a543be4f50 /gcc | |
parent | 8b75f5506f72b100a6ac1eff4f0fc1acfdf8566c (diff) | |
download | gcc-4eddc42b63d1064dfb0fd4c4820616f672e0ccfa.zip gcc-4eddc42b63d1064dfb0fd4c4820616f672e0ccfa.tar.gz gcc-4eddc42b63d1064dfb0fd4c4820616f672e0ccfa.tar.bz2 |
re PR target/54089 ([SH] Refactor shift patterns)
PR target/54089
* config/sh/predicates.md (arith_reg_or_t_reg_operand): New predicate.
* config/sh/sh.md (*rotcr): Use arith_reg_or_t_reg_operand predicate.
Handle the case where one of the operands is T_REG.
Add new pattern to handle MSB extraction.
PR target/54089
* gcc.target/sh/pr54089-1.c (test_11, test_12, test_13, test_14): New
functions.
From-SVN: r191490
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/sh/predicates.md | 5 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 31 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr54089-1.c | 30 |
5 files changed, 78 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b4d2311..acdf3d6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2012-09-19 Oleg Endo <olegendo@gcc.gnu.org> + PR target/54089 + * config/sh/predicates.md (arith_reg_or_t_reg_operand): New predicate. + * config/sh/sh.md (*rotcr): Use arith_reg_or_t_reg_operand predicate. + Handle the case where one of the operands is T_REG. + Add new pattern to handle MSB extraction. + +2012-09-19 Oleg Endo <olegendo@gcc.gnu.org> + PR target/54236 * config/sh/sh.md (*addc): Add pattern to handle one bit left shifts. diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 8a4f7db..27e42f1 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -1028,3 +1028,8 @@ return 0; } }) + +;; Returns true of OP is arith_reg_operand or t_reg_operand. +(define_predicate "arith_reg_or_t_reg_operand" + (ior (match_operand 0 "arith_reg_operand") + (match_operand 0 "t_reg_operand"))) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 71e758b..27c5633 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3940,7 +3940,7 @@ label: [(set (match_operand:SI 0 "arith_reg_dest") (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") (match_operand:SI 2 "const_int_operand")) - (ashift:SI (match_operand:SI 3 "t_reg_operand") + (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand") (const_int 31)))) (clobber (reg:SI T_REG))] "TARGET_SH1" @@ -3992,6 +3992,17 @@ label: emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); } + /* For the rotcr insn to work, operands[3] must be in T_REG. + If it is not we can get it there by shifting it right one bit. + In this case T_REG is not an input for this insn, thus we don't have to + pay attention as of where to insert the shlr insn. */ + if (! t_reg_operand (operands[3], SImode)) + { + /* We don't care about the shifted result here, only the T_REG. */ + emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); + operands[3] = get_t_reg_rtx (); + } + emit_insn (gen_rotcr (operands[0], operands[1], operands[3])); DONE; }) @@ -4011,6 +4022,24 @@ label: (set (reg:SI T_REG) (and:SI (match_dup 0) (const_int 1)))])]) +(define_insn_and_split "*rotcr" + [(set (match_operand:SI 0 "arith_reg_dest") + (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int -2147483648)) ;; 0xffffffff80000000 + (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") + (const_int 1)))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(const_int 0)] +{ + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_shll (tmp, operands[1])); + emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ())); + DONE; +}) + ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;; SImode shift left diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c4c041f84..4117966 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2012-09-19 Oleg Endo <olegendo@gcc.gnu.org> + PR target/54089 + * gcc.target/sh/pr54089-1.c (test_11, test_12, test_13, test_14): New + functions. + +2012-09-19 Oleg Endo <olegendo@gcc.gnu.org> + PR target/54236 * gcc.target/sh/pr54236-1.c (test_08): Add one bit left shift case. diff --git a/gcc/testsuite/gcc.target/sh/pr54089-1.c b/gcc/testsuite/gcc.target/sh/pr54089-1.c index 2101c53..7792455 100644 --- a/gcc/testsuite/gcc.target/sh/pr54089-1.c +++ b/gcc/testsuite/gcc.target/sh/pr54089-1.c @@ -2,7 +2,8 @@ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-times "rotcr" 11 } } */ +/* { dg-final { scan-assembler-times "rotcr" 15 } } */ +/* { dg-final { scan-assembler-times "shll\t" 1 } } */ typedef char bool; @@ -81,3 +82,30 @@ test_10 (int a, int b) bool r = a == b; return r << 31; } + +unsigned int +test_11 (unsigned int a, int b) +{ + /* 1x shlr, 1x rotcr */ + return (a >> 1) | (b << 31); +} + +unsigned int +test_12 (unsigned int a, int b) +{ + return (a >> 2) | (b << 31); +} + +unsigned int +test_13 (unsigned int a, int b) +{ + return (a >> 3) | (b << 31); +} + +unsigned int +test_14 (unsigned int a, int b) +{ + /* 1x shll, 1x rotcr */ + bool r = b < 0; + return ((a >> 1) | (r << 31)); +} |