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

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 22, 2013, 4:45 p.m.
Message ID <20130122164545.GW7269@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/214599/
State New
Headers show

Comments

Jakub Jelinek - Jan. 22, 2013, 4:45 p.m.
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.


	Jakub

Patch

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