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]

[committed] Don't allow stos* insns to be randomly matched (PR target/55686)


Hi!

This patch fixes the following testcase, where *strset* insn got matched
just from a store followed by increment, instead of being expanded from
builtin memset.  This is undesirable, because the stos? insns require
specific hard registers for both operands and thus tie hands of the RA,
so while we don't need two insns for the store + adjustment, we'll likely
need even more insns because address and/or stored values need reloading
into the right registers.  Furthermore, if there are local register asm
vars, reloading might not be possible at all.

Bootstrapped/regtested on x86_64-linux and i686-linux, approved by Honza
on IRC, committed to trunk.

2013-01-22  Jakub Jelinek  <jakub@redhat.com>

	PR target/55686
	* config/i386/i386.md (UNSPEC_STOS): New.
	(strset_singleop, *strsetdi_rex_1, *strsetsi_1, *strsethi_1,
	*strsetqi_1): Add UNSPEC_STOS.

	* gcc.target/i386/pr55686.c: New test.

--- gcc/config/i386/i386.md.jj	2013-01-21 15:54:14.000000000 +0100
+++ gcc/config/i386/i386.md	2013-01-22 09:52:50.410458871 +0100
@@ -110,6 +110,7 @@ (define_c_enum "unspec" [
   UNSPEC_PAUSE
   UNSPEC_LEA_ADDR
   UNSPEC_XBEGIN_ABORT
+  UNSPEC_STOS
 
   ;; For SSE/MMX support:
   UNSPEC_FIX_NOTRUNC
@@ -15607,7 +15608,8 @@ (define_expand "strset_singleop"
   [(parallel [(set (match_operand 1 "memory_operand")
 		   (match_operand 2 "register_operand"))
 	      (set (match_operand 0 "register_operand")
-		   (match_operand 3))])]
+		   (match_operand 3))
+	      (unspec [(const_int 0)] UNSPEC_STOS)])]
   ""
   "ix86_current_function_needs_cld = 1;")
 
@@ -15616,7 +15618,8 @@ (define_insn "*strsetdi_rex_1"
 	(match_operand:DI 2 "register_operand" "a"))
    (set (match_operand:P 0 "register_operand" "=D")
 	(plus:P (match_dup 1)
-		(const_int 8)))]
+		(const_int 8)))
+   (unspec [(const_int 0)] UNSPEC_STOS)]
   "TARGET_64BIT
    && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "%^stosq"
@@ -15629,7 +15632,8 @@ (define_insn "*strsetsi_1"
 	(match_operand:SI 2 "register_operand" "a"))
    (set (match_operand:P 0 "register_operand" "=D")
 	(plus:P (match_dup 1)
-		(const_int 4)))]
+		(const_int 4)))
+   (unspec [(const_int 0)] UNSPEC_STOS)]
   "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "%^stos{l|d}"
   [(set_attr "type" "str")
@@ -15641,7 +15645,8 @@ (define_insn "*strsethi_1"
 	(match_operand:HI 2 "register_operand" "a"))
    (set (match_operand:P 0 "register_operand" "=D")
 	(plus:P (match_dup 1)
-		(const_int 2)))]
+		(const_int 2)))
+   (unspec [(const_int 0)] UNSPEC_STOS)]
   "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "%^stosw"
   [(set_attr "type" "str")
@@ -15653,7 +15658,8 @@ (define_insn "*strsetqi_1"
 	(match_operand:QI 2 "register_operand" "a"))
    (set (match_operand:P 0 "register_operand" "=D")
 	(plus:P (match_dup 1)
-		(const_int 1)))]
+		(const_int 1)))
+   (unspec [(const_int 0)] UNSPEC_STOS)]
   "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
   "%^stosb"
   [(set_attr "type" "str")
--- gcc/testsuite/gcc.target/i386/pr55686.c.jj	2013-01-22 10:14:47.048961454 +0100
+++ gcc/testsuite/gcc.target/i386/pr55686.c	2013-01-22 10:14:20.000000000 +0100
@@ -0,0 +1,16 @@
+/* PR target/55686 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (long x, long *y)
+{
+  long *a = y - 64, i;
+  for (i = 0; i < x; i++)
+    {
+      long v = y[i];
+      *a++ = v;
+    }
+  register void **c __asm__ ("di");
+  goto **c;
+}

	Jakub


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