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

Submitted by Jakub Jelinek on Jan. 22, 2013, 4:45 p.m.

Details

Message ID 20130122164545.GW7269@tucnak.redhat.com
State New
Headers show

Commit Message

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 hide | download patch | download mbox

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