On Thu, 28 Nov 2019, Jakub Jelinek wrote:

> Hi!
> 
> The various routines propagate to the caller whether
>       if (check_and_optimize_stmt (&gsi, &cleanup_eh, evrp.get_vr_values ()))
>         gsi_next (&gsi);
> should do gsi_next or not (return false if e.g. gsi_remove is done, thus
> gsi is already moved to the next stmt).
> handle_printf_call returns that too, though with the values swapped,
> but since the move of handle_printf_call (then called handle_gimple_call)
> from the separate sprintf pass to strlen pass, the return value is ignored,
> while it must not be.  In some cases it means the following statement is not
> processed by the strlen pass, which can e.g. mean wrong-code because some
> strlen information is not invalidated when it should, or in other cases like
> in this testcase where the sprintf call that was removed was at the end of a 
> bb
> it means an ICE, because gsi_next when gsi is already at the end of bb is
> invalid.
> 
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?

OK.

Richard.

> 2019-11-27  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/92691
>       * tree-ssa-strlen.c (handle_store): Clarify return value meaning
>       in function comment.
>       (strlen_check_and_optimize_call): Likewise.  For handle_printf_call
>       calls, return !handle_printf_call rather than always returning true.
>       (check_and_optimize_stmt): Describe return value meaning in function
>       comment.  Formatting fix.
> 
>       * gcc.dg/tree-ssa/builtin-snprintf-10.c: New test.
> 
> --- gcc/tree-ssa-strlen.c.jj  2019-11-22 19:11:54.901951408 +0100
> +++ gcc/tree-ssa-strlen.c     2019-11-27 12:25:14.778564388 +0100
> @@ -4300,7 +4300,8 @@ count_nonzero_bytes (tree exp, unsigned
>  /* Handle a single or multibyte store other than by a built-in function,
>     either via a single character assignment or by multi-byte assignment
>     either via MEM_REF or via a type other than char (such as in
> -   '*(int*)a = 12345').  Return true when handled.  */
> +   '*(int*)a = 12345').  Return true to let the caller advance *GSI to
> +   the next statement in the basic block and false otherwise.  */
>  
>  static bool
>  handle_store (gimple_stmt_iterator *gsi, bool *zero_write, const vr_values 
> *rvals)
> @@ -4728,8 +4729,8 @@ is_char_type (tree type)
>  }
>  
>  /* Check the built-in call at GSI for validity and optimize it.
> -   Return true to let the caller advance *GSI to the statement
> -   in the CFG and false otherwise.  */
> +   Return true to let the caller advance *GSI to the next statement
> +   in the basic block and false otherwise.  */
>  
>  static bool
>  strlen_check_and_optimize_call (gimple_stmt_iterator *gsi,
> @@ -4738,16 +4739,13 @@ strlen_check_and_optimize_call (gimple_s
>  {
>    gimple *stmt = gsi_stmt (*gsi);
>  
> +  /* When not optimizing we must be checking printf calls which
> +     we do even for user-defined functions when they are declared
> +     with attribute format.  */
>    if (!flag_optimize_strlen
>        || !strlen_optimize
>        || !valid_builtin_call (stmt))
> -    {
> -      /* When not optimizing we must be checking printf calls which
> -      we do even for user-defined functions when they are declared
> -      with attribute format.  */
> -      handle_printf_call (gsi, rvals);
> -      return true;
> -    }
> +    return !handle_printf_call (gsi, rvals);
>  
>    tree callee = gimple_call_fndecl (stmt);
>    switch (DECL_FUNCTION_CODE (callee))
> @@ -4806,7 +4804,8 @@ strlen_check_and_optimize_call (gimple_s
>       return false;
>        break;
>      default:
> -      handle_printf_call (gsi, rvals);
> +      if (handle_printf_call (gsi, rvals))
> +     return false;
>        break;
>      }
>  
> @@ -4932,7 +4931,8 @@ handle_integral_assign (gimple_stmt_iter
>  /* Attempt to check for validity of the performed access a single statement
>     at *GSI using string length knowledge, and to optimize it.
>     If the given basic block needs clean-up of EH, CLEANUP_EH is set to
> -   true.  */
> +   true.  Return true to let the caller advance *GSI to the next statement
> +   in the basic block and false otherwise.  */
>  
>  static bool
>  check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
> @@ -4973,32 +4973,32 @@ check_and_optimize_stmt (gimple_stmt_ite
>       /* Handle assignment to a character.  */
>       handle_integral_assign (gsi, cleanup_eh);
>        else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
> -      {
> -     tree type = TREE_TYPE (lhs);
> -     if (TREE_CODE (type) == ARRAY_TYPE)
> -       type = TREE_TYPE (type);
> -
> -     bool is_char_store = is_char_type (type);
> -     if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
> -       {
> -         /* To consider stores into char objects via integer types
> -            other than char but not those to non-character objects,
> -            determine the type of the destination rather than just
> -            the type of the access.  */
> -         tree ref = TREE_OPERAND (lhs, 0);
> -         type = TREE_TYPE (ref);
> -         if (TREE_CODE (type) == POINTER_TYPE)
> -           type = TREE_TYPE (type);
> -         if (TREE_CODE (type) == ARRAY_TYPE)
> -           type = TREE_TYPE (type);
> -         if (is_char_type (type))
> -           is_char_store = true;
> -       }
> -
> -     /* Handle a single or multibyte assignment.  */
> -     if (is_char_store && !handle_store (gsi, &zero_write, rvals))
> -       return false;
> -      }
> +     {
> +       tree type = TREE_TYPE (lhs);
> +       if (TREE_CODE (type) == ARRAY_TYPE)
> +         type = TREE_TYPE (type);
> +
> +       bool is_char_store = is_char_type (type);
> +       if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
> +         {
> +           /* To consider stores into char objects via integer types
> +              other than char but not those to non-character objects,
> +              determine the type of the destination rather than just
> +              the type of the access.  */
> +           tree ref = TREE_OPERAND (lhs, 0);
> +           type = TREE_TYPE (ref);
> +           if (TREE_CODE (type) == POINTER_TYPE)
> +             type = TREE_TYPE (type);
> +           if (TREE_CODE (type) == ARRAY_TYPE)
> +             type = TREE_TYPE (type);
> +           if (is_char_type (type))
> +             is_char_store = true;
> +         }
> +
> +       /* Handle a single or multibyte assignment.  */
> +       if (is_char_store && !handle_store (gsi, &zero_write, rvals))
> +         return false;
> +     }
>      }
>    else if (gcond *cond = dyn_cast<gcond *> (stmt))
>      {
> --- gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c.jj    2019-11-27 
> 12:23:19.180349031 +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c       2019-11-27 
> 12:23:48.070903012 +0100
> @@ -0,0 +1,10 @@
> +/* PR tree-optimization/92691 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +void
> +foo (int x, char *y)
> +{
> +  if (x != 0)
> +    __builtin_snprintf (y, 0, "foo");
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to