On Tue, 28 Jun 2016, Jakub Jelinek wrote:

> Hi!
> 
> This is just first small step towards this PR.
> It brings the ADDR_EXPR of DECL_P bases roughly on the same level as
> SSA_NAMEs pointers - so get_stridx_plus_constant works for them, and
> more importantly, before this patch there was a very severe bug in
> addr_stridxptr (missing list = list->next; in the loop), which meant that
> inside of a single decl we were tracking at most one string length, rather
> than the former 16 (or now 32) limit.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> As a follow-up, I'd like to introduce string length at least N, where we
> don't know the exact string length, but we know there are no '\0' chars
> within N bytes.
> 
> 2016-06-28  Jakub Jelinek  <ja...@redhat.com>
> 
>       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.
> 
> --- gcc/tree-ssa-strlen.c.jj  2016-06-28 10:21:22.103693623 +0200
> +++ gcc/tree-ssa-strlen.c     2016-06-28 13:41:56.797718522 +0200
> @@ -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 *bases
>        || 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 *bases
>       {
>         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
>       }
>      }
>    else
> -    idx = get_addr_stridx (lhs);
> +    idx = get_addr_stridx (lhs, NULL_TREE);
>  
>    if (idx > 0)
>      {
> --- gcc/testsuite/gcc.dg/strlenopt-28.c.jj    2016-06-28 13:57:06.768016510 
> +0200
> +++ gcc/testsuite/gcc.dg/strlenopt-28.c       2016-06-28 13:55:01.000000000 
> +0200
> @@ -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" } } */
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to