This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[SH] PR 54988
- From: Oleg Endo <oleg dot endo at t-online dot de>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 30 Oct 2012 00:14:33 +0100
- Subject: [SH] PR 54988
Hello,
This fixes the issues of PR 54988.
Tested on rev 192482 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.
Cheers,
Oleg
gcc/ChangeLog:
PR target/54988
* config/sh/sh.md (tstqi_t_zero): Rename to *tstqi_t_zero.
(*tst<mode>_t_zero): New insns.
* config/sh/iterators.md (lowpart_be, lowpart_le): New mode
attributes.
testsuite/ChangeLog:
PR target/54988
gcc.target/sh/pr53988.c: New.
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 192482)
+++ gcc/config/sh/sh.md (working copy)
@@ -633,13 +633,39 @@
;; Test low QI subreg against zero.
;; This avoids unnecessary zero extension before the test.
-(define_insn "tstqi_t_zero"
+(define_insn "*tstqi_t_zero"
[(set (reg:SI T_REG)
(eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
"TARGET_SH1"
"tst #255,%0"
[(set_attr "type" "mt_group")])
+;; This pattern might be risky because it also tests the upper bits and not
+;; only the subreg. However, it seems that combine will get to this only
+;; when testing sign/zero extended values. In this case the extended upper
+;; bits do not matter.
+(define_insn "*tst<mode>_t_zero"
+ [(set (reg:SI T_REG)
+ (eq:SI
+ (subreg:QIHI
+ (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
+ (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
+ (const_int 0)))]
+ "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
+ "tst %0,%1"
+ [(set_attr "type" "mt_group")])
+
+(define_insn "*tst<mode>_t_zero"
+ [(set (reg:SI T_REG)
+ (eq:SI
+ (subreg:QIHI
+ (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
+ (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
+ (const_int 0)))]
+ "TARGET_SH1 && !TARGET_LITTLE_ENDIAN"
+ "tst %0,%1"
+ [(set_attr "type" "mt_group")])
+
;; Extract LSB, negate and store in T bit.
(define_insn "tstsi_t_and_not"
@@ -3514,7 +3540,7 @@
/* If it is possible to turn the and insn into a zero extension
already, redundant zero extensions will be folded, which results
in better code.
- Ideally the splitter of *andsi_compact would be enough, if reundant
+ Ideally the splitter of *andsi_compact would be enough, if redundant
zero extensions were detected after the combine pass, which does not
happen at the moment. */
if (TARGET_SH1)
Index: gcc/config/sh/iterators.md
===================================================================
--- gcc/config/sh/iterators.md (revision 192482)
+++ gcc/config/sh/iterators.md (working copy)
@@ -38,3 +38,6 @@
;; Return codes.
(define_code_iterator any_return [return simple_return])
+;; Lowpart subreg byte position code attributes for big and little endian.
+(define_mode_attr lowpart_be [(QI "3") (HI "2")])
+(define_mode_attr lowpart_le [(QI "0") (HI "0")])
Index: gcc/testsuite/gcc.target/sh/pr53988.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr53988.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr53988.c (revision 0)
@@ -0,0 +1,74 @@
+/* Check that the tst Rm,Rn instruction is generated for QImode and HImode
+ values loaded from memory. If everything goes as expected we won't see
+ any sign/zero extensions or and ops. On SH2A we don't expect to see the
+ movu insn. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "tst\tr" 8 } } */
+/* { dg-final { scan-assembler-not "tst\t#255" } } */
+/* { dg-final { scan-assembler-not "exts|extu|and|movu" } } */
+
+int
+test00 (char* a, char* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test01 (unsigned char* a, unsigned char* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test02 (short* a, short* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test03 (unsigned short* a, unsigned short* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test04 (char* a, short* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test05 (short* a, char* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test06 (int* a, char* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}
+
+int
+test07 (int* a, short* b, int c, int d)
+{
+ if (*a & *b)
+ return c;
+ return d;
+}