Prefer to use strlen call instead of inline expansion (PR target/88809).
2019-05-02 Martin Liska <mliska@suse.cz> PR target/88809 * config/i386/i386.c (ix86_expand_strlen): Use strlen call. With -minline-all-stringops use inline expansion using 4B loop. * doc/invoke.texi: Document the change of -minline-all-stringops. 2019-05-02 Martin Liska <mliska@suse.cz> PR target/88809 * gcc.target/i386/pr88809.c: New test. * gcc.target/i386/pr88809-2.c: New test. From-SVN: r270787
This commit is contained in:
parent
06ceaa1d78
commit
786e0e5239
@ -1,3 +1,11 @@
|
||||
2019-05-02 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR target/88809
|
||||
* config/i386/i386.c (ix86_expand_strlen): Use strlen call.
|
||||
With -minline-all-stringops use inline expansion using 4B loop.
|
||||
* doc/invoke.texi: Document the change of
|
||||
-minline-all-stringops.
|
||||
|
||||
2019-05-01 Jeff Law <law@redhat.com>
|
||||
|
||||
PR tree-optimization/88797
|
||||
|
@ -28270,68 +28270,34 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
|
||||
bool
|
||||
ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
|
||||
{
|
||||
rtx addr, scratch1, scratch2, scratch3, scratch4;
|
||||
|
||||
/* The generic case of strlen expander is long. Avoid it's
|
||||
expanding unless TARGET_INLINE_ALL_STRINGOPS. */
|
||||
|
||||
if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
|
||||
&& !TARGET_INLINE_ALL_STRINGOPS
|
||||
&& !optimize_insn_for_size_p ()
|
||||
&& (!CONST_INT_P (align) || INTVAL (align) < 4))
|
||||
return false;
|
||||
|
||||
addr = force_reg (Pmode, XEXP (src, 0));
|
||||
scratch1 = gen_reg_rtx (Pmode);
|
||||
|
||||
if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
|
||||
&& !optimize_insn_for_size_p ())
|
||||
if (TARGET_UNROLL_STRLEN
|
||||
&& TARGET_INLINE_ALL_STRINGOPS
|
||||
&& eoschar == const0_rtx
|
||||
&& optimize > 1)
|
||||
{
|
||||
/* The generic case of strlen expander is long. Avoid it's
|
||||
expanding unless TARGET_INLINE_ALL_STRINGOPS. */
|
||||
rtx addr = force_reg (Pmode, XEXP (src, 0));
|
||||
/* Well it seems that some optimizer does not combine a call like
|
||||
foo(strlen(bar), strlen(bar));
|
||||
when the move and the subtraction is done here. It does calculate
|
||||
the length just once when these instructions are done inside of
|
||||
output_strlen_unroll(). But I think since &bar[strlen(bar)] is
|
||||
often used and I use one fewer register for the lifetime of
|
||||
output_strlen_unroll() this is better. */
|
||||
foo(strlen(bar), strlen(bar));
|
||||
when the move and the subtraction is done here. It does calculate
|
||||
the length just once when these instructions are done inside of
|
||||
output_strlen_unroll(). But I think since &bar[strlen(bar)] is
|
||||
often used and I use one fewer register for the lifetime of
|
||||
output_strlen_unroll() this is better. */
|
||||
|
||||
emit_move_insn (out, addr);
|
||||
|
||||
ix86_expand_strlensi_unroll_1 (out, src, align);
|
||||
|
||||
/* strlensi_unroll_1 returns the address of the zero at the end of
|
||||
the string, like memchr(), so compute the length by subtracting
|
||||
the start address. */
|
||||
the string, like memchr(), so compute the length by subtracting
|
||||
the start address. */
|
||||
emit_insn (ix86_gen_sub3 (out, out, addr));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx unspec;
|
||||
|
||||
/* Can't use this if the user has appropriated eax, ecx, or edi. */
|
||||
if (fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
|
||||
return false;
|
||||
/* Can't use this for non-default address spaces. */
|
||||
if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src)))
|
||||
return false;
|
||||
|
||||
scratch2 = gen_reg_rtx (Pmode);
|
||||
scratch3 = gen_reg_rtx (Pmode);
|
||||
scratch4 = force_reg (Pmode, constm1_rtx);
|
||||
|
||||
emit_move_insn (scratch3, addr);
|
||||
eoschar = force_reg (QImode, eoschar);
|
||||
|
||||
src = replace_equiv_address_nv (src, scratch3);
|
||||
|
||||
/* If .md starts supporting :P, this can be done in .md. */
|
||||
unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (4, src, eoschar, align,
|
||||
scratch4), UNSPEC_SCAS);
|
||||
emit_insn (gen_strlenqi_1 (scratch1, scratch3, unspec));
|
||||
emit_insn (ix86_gen_one_cmpl2 (scratch2, scratch1));
|
||||
emit_insn (ix86_gen_add3 (out, scratch2, constm1_rtx));
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For given symbol (function) construct code to compute address of it's PLT
|
||||
|
@ -28506,8 +28506,9 @@ By default GCC inlines string operations only when the destination is
|
||||
known to be aligned to least a 4-byte boundary.
|
||||
This enables more inlining and increases code
|
||||
size, but may improve performance of code that depends on fast
|
||||
@code{memcpy}, @code{strlen},
|
||||
and @code{memset} for short lengths.
|
||||
@code{memcpy} and @code{memset} for short lengths.
|
||||
The option enables inline expansion of @code{strlen} for all
|
||||
pointer alignments.
|
||||
|
||||
@item -minline-stringops-dynamically
|
||||
@opindex minline-stringops-dynamically
|
||||
|
@ -1,3 +1,9 @@
|
||||
2019-05-02 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR target/88809
|
||||
* gcc.target/i386/pr88809.c: New test.
|
||||
* gcc.target/i386/pr88809-2.c: New test.
|
||||
|
||||
2019-05-01 Dominique d'Humieres <dominiq@gcc.gnu.org>
|
||||
|
||||
PR fortran/60144
|
||||
|
9
gcc/testsuite/gcc.target/i386/pr88809-2.c
Normal file
9
gcc/testsuite/gcc.target/i386/pr88809-2.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* PR target/88809 */
|
||||
/* { dg-options "-Os" } */
|
||||
|
||||
unsigned int foo (const char *ptr)
|
||||
{
|
||||
return __builtin_strlen (ptr);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "call\[ \t\]strlen" } } */
|
9
gcc/testsuite/gcc.target/i386/pr88809.c
Normal file
9
gcc/testsuite/gcc.target/i386/pr88809.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* PR target/88809 */
|
||||
/* { dg-options "-O" } */
|
||||
|
||||
unsigned int foo (const char *ptr)
|
||||
{
|
||||
return __builtin_strlen (ptr);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "call\[ \t\]strlen" } } */
|
Loading…
Reference in New Issue
Block a user