From 5f3cd7c3f31373789dbc8360fa3d46fcaf473f99 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 29 Jun 2016 10:47:46 +0200 Subject: [PATCH] re PR tree-optimization/71625 (missing strlen optimization on different array initialization style) PR tree-optimization/71625 * tree-ssa-strlen.c (get_addr_stridx): Add PTR argument. Assume list is sorted by ascending list->offset. If PTR is non-NULL and there is previous strinfo, call get_stridx_plus_constant. (get_stridx): Pass exp as second argument to get_addr_stridx. (addr_stridxptr): Add missing list = list->next, so that there can be more than one entries in the list. Bump limit from 16 to 32. Ensure the list is sorted by ascending list->offset. (get_stridx_plus_constant): Adjust so that it can be also called with ADDR_EXPR instead of SSA_NAME as PTR. (handle_char_store): Pass NULL_TREE as second argument to get_addr_stridx. * gcc.dg/strlenopt-28.c: New test. From-SVN: r237841 --- gcc/ChangeLog | 15 ++++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/strlenopt-28.c | 59 +++++++++++++++++++++++++++++ gcc/tree-ssa-strlen.c | 47 ++++++++++++++++++----- 4 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/strlenopt-28.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f6dcb3866b..2d4f9b3f6e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2016-06-29 Jakub Jelinek + + PR tree-optimization/71625 + * tree-ssa-strlen.c (get_addr_stridx): Add PTR argument. Assume list + is sorted by ascending list->offset. If PTR is non-NULL and there is + previous strinfo, call get_stridx_plus_constant. + (get_stridx): Pass exp as second argument to get_addr_stridx. + (addr_stridxptr): Add missing list = list->next, so that there can be + more than one entries in the list. Bump limit from 16 to 32. Ensure + the list is sorted by ascending list->offset. + (get_stridx_plus_constant): Adjust so that it can be also called with + ADDR_EXPR instead of SSA_NAME as PTR. + (handle_char_store): Pass NULL_TREE as second argument to + get_addr_stridx. + 2016-06-29 Richard Biener PR rtl-optimization/68961 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 70e90482ba0..c1c9a31a8e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-29 Jakub Jelinek + + PR tree-optimization/71625 + * gcc.dg/strlenopt-28.c: New test. + 2016-06-29 Richard Biener PR middle-end/71002 diff --git a/gcc/testsuite/gcc.dg/strlenopt-28.c b/gcc/testsuite/gcc.dg/strlenopt-28.c new file mode 100644 index 00000000000..03fb01781bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-28.c @@ -0,0 +1,59 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-strlen" } */ + +#include "strlenopt.h" + +volatile int v; + +size_t +f1 (void) +{ + char a[30]; + v += 1; + memcpy (a, "1234567", 8); + memcpy (a + 7, "89abcdefg", 10); + memcpy (a + 16, "h", 2); + return strlen (a); // This strlen should be optimized into 17. +} + +size_t +f2 (void) +{ + char a[30]; + v += 2; + strcpy (a, "1234567"); + strcpy (a + 7, "89abcdefg"); + strcpy (a + 16, "h"); + return strlen (a); // This strlen should be optimized into 17. +} + +size_t +f3 (char *a) +{ + v += 3; + memcpy (a, "1234567", 8); + memcpy (a + 7, "89abcdefg", 10); + memcpy (a + 16, "h", 2); + return strlen (a); // This strlen should be optimized into 17. +} + +size_t +f4 (char *a) +{ + v += 4; + strcpy (a, "1234567"); + strcpy (a + 7, "89abcdefg"); + strcpy (a + 16, "h"); + return strlen (a); // This strlen should be optimized into 17. +} + +int +main () +{ + char a[30]; + if (f1 () != 17 || f2 () != 17 || f3 (a) != 17 || f4 (a) != 17) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index f306a9c9f3d..232594b92ab 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -159,10 +159,10 @@ get_strinfo (int idx) /* Helper function for get_stridx. */ static int -get_addr_stridx (tree exp) +get_addr_stridx (tree exp, tree ptr) { HOST_WIDE_INT off; - struct stridxlist *list; + struct stridxlist *list, *last = NULL; tree base; if (!decl_to_stridxlist_htab) @@ -180,9 +180,22 @@ get_addr_stridx (tree exp) { if (list->offset == off) return list->idx; + if (list->offset > off) + return 0; + last = list; list = list->next; } while (list); + + if (ptr && last && last->idx > 0) + { + strinfo *si = get_strinfo (last->idx); + if (si + && si->length + && TREE_CODE (si->length) == INTEGER_CST + && compare_tree_int (si->length, off - last->offset) != -1) + return get_stridx_plus_constant (si, off - last->offset, ptr); + } return 0; } @@ -234,7 +247,7 @@ get_stridx (tree exp) if (TREE_CODE (exp) == ADDR_EXPR) { - int idx = get_addr_stridx (TREE_OPERAND (exp, 0)); + int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp); if (idx != 0) return idx; } @@ -304,15 +317,29 @@ addr_stridxptr (tree exp) if (existed) { int i; - for (i = 0; i < 16; i++) + stridxlist *before = NULL; + for (i = 0; i < 32; i++) { if (list->offset == off) return &list->idx; + if (list->offset > off && before == NULL) + before = list; if (list->next == NULL) break; + list = list->next; } - if (i == 16) + if (i == 32) return NULL; + if (before) + { + list = before; + before = XOBNEW (&stridx_obstack, struct stridxlist); + *before = *list; + list->next = before; + list->offset = off; + list->idx = 0; + return &list->idx; + } list->next = XOBNEW (&stridx_obstack, struct stridxlist); list = list->next; } @@ -613,9 +640,7 @@ verify_related_strinfos (strinfo *origsi) static int get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr) { - gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME); - - if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)) + if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)) return 0; if (basesi->length == NULL_TREE @@ -633,7 +658,8 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr) || TREE_CODE (si->length) != INTEGER_CST) return 0; - if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr)) + if (TREE_CODE (ptr) == SSA_NAME + && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr)) ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names); gcc_checking_assert (compare_tree_int (si->length, off) != -1); @@ -651,6 +677,7 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr) { if (r == 0) { + gcc_assert (TREE_CODE (ptr) == SSA_NAME); ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx; return si->idx; } @@ -2063,7 +2090,7 @@ handle_char_store (gimple_stmt_iterator *gsi) } } else - idx = get_addr_stridx (lhs); + idx = get_addr_stridx (lhs, NULL_TREE); if (idx > 0) {