aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2019-05-02 09:57:38 +0200
committerMartin Liska <marxin@gcc.gnu.org>2019-05-02 07:57:38 +0000
commit786e0e5239529de9a4254fe8411a0e8f843e721a (patch)
tree8b319e19012eea14cba954edfd1ac8b95a7a6ff3
parent06ceaa1d78d586eba492699075a8dee31ab3a3e8 (diff)
downloadgcc-786e0e5239529de9a4254fe8411a0e8f843e721a.zip
gcc-786e0e5239529de9a4254fe8411a0e8f843e721a.tar.gz
gcc-786e0e5239529de9a4254fe8411a0e8f843e721a.tar.bz2
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.c70
-rw-r--r--gcc/doc/invoke.texi5
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88809-2.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88809.c9
6 files changed, 53 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7f6ccd9..1883e4d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 43ee776..e7ee83d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 516eb24..de7e1aa 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 45b181a..30227ca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.target/i386/pr88809-2.c b/gcc/testsuite/gcc.target/i386/pr88809-2.c
new file mode 100644
index 0000000..b8ef51d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88809-2.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr88809.c b/gcc/testsuite/gcc.target/i386/pr88809.c
new file mode 100644
index 0000000..20844dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88809.c
@@ -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" } } */