This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] Don't allow stos* insns to be randomly matched (PR target/55686)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jan Hubicka <jh at suse dot cz>
- Date: Tue, 22 Jan 2013 17:45:45 +0100
- Subject: [committed] Don't allow stos* insns to be randomly matched (PR target/55686)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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