This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]