This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[SH] PR 54089 - Add another rotcr case
- From: Oleg Endo <oleg dot endo at t-online dot de>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 18 Sep 2012 21:05:19 +0200
- Subject: [SH] PR 54089 - Add another rotcr case
Hello,
There is another opportunity where SH's rotcr insn can be used.
Tested on rev 191342 with
make -k check RUNTESTFLAGS="--target_board=sh-sim
\{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and no new failures.
OK to install?
Cheers,
Oleg
gcc/ChangeLog:
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.
testsuite/ChangeLog:
PR target/54089
* gcc.target/sh/pr54089-1.c (test_11, test_12, test_13,
test_14): New functions.
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 191342)
+++ gcc/config/sh/sh.md (working copy)
@@ -3924,7 +3924,7 @@
[(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"
@@ -3976,6 +3976,17 @@
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;
})
@@ -3995,6 +4006,24 @@
(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
Index: gcc/config/sh/predicates.md
===================================================================
--- gcc/config/sh/predicates.md (revision 191342)
+++ gcc/config/sh/predicates.md (working copy)
@@ -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")))
Index: gcc/testsuite/gcc.target/sh/pr54089-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54089-1.c (revision 191342)
+++ gcc/testsuite/gcc.target/sh/pr54089-1.c (working copy)
@@ -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 @@
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));
+}