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 <ja...@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