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

Jakub Jelinek jakub@redhat.com
Tue Jan 22 16:45:00 GMT 2013


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



More information about the Gcc-patches mailing list