On Wed, Nov 19, 2025 at 7:34 AM Andrew Pinski
<[email protected]> wrote:
>
> I found that the strlen pass ignores stores via references.
> This shows up with C++ code more than C.
> A simple:
> ```
> int g(void)
> {
>   std::string a="a";
>   return __builtin_strlen(a.c_str());
> }
> ```
> Should be optimized to just `return 1` but does not
> currently due to use of references.
> The problem in the code is direct comparison with POINTER_TYPE instead
> of using POINTER_TYPE_P.
> This fixes the cases I found all related to strings passes. All of them
> were added by Martin Sebor which makes me think this was an oversight on his
> part.

OK.

Richard.

> Bootstrapped and tested on x86_64-linux-gnu.
>
>         PR tree-optimization/122754
> gcc/ChangeLog:
>
>         * gimple-fold.cc (get_range_strlen_tree): Use POINTER_TYPE_P instead
>         of direct comparing to POINTER_TYPE.
>         * gimple-ssa-sprintf.cc (format_integer): Likewise.
>         * gimple-ssa-warn-access.cc (maybe_warn_nonstring_arg): Likewise.
>         * gimple-ssa-warn-restrict.cc (pass_wrestrict::check_call): Likewise.
>         * tree-ssa-strlen.cc (maybe_set_strlen_range): Likewise.
>         (is_strlen_related_p): Likewise.
>         (strlen_pass::handle_assign): Likewise.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/tree-ssa/string-strlen-1.C: New test.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
>  gcc/gimple-fold.cc                            |  2 +-
>  gcc/gimple-ssa-sprintf.cc                     |  6 +++---
>  gcc/gimple-ssa-warn-access.cc                 |  2 +-
>  gcc/gimple-ssa-warn-restrict.cc               |  4 ++--
>  .../g++.dg/tree-ssa/string-strlen-1.C         | 20 +++++++++++++++++++
>  gcc/tree-ssa-strlen.cc                        |  8 ++++----
>  6 files changed, 31 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/tree-ssa/string-strlen-1.C
>
> diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
> index 8f72dbb929b..3fc76313622 100644
> --- a/gcc/gimple-fold.cc
> +++ b/gcc/gimple-fold.cc
> @@ -1806,7 +1806,7 @@ get_range_strlen_tree (tree arg, bitmap visited, 
> strlen_range_kind rkind,
>              the size of the enclosing object minus the offset of
>              the referenced subobject minus 1 (for the terminating nul).  */
>           tree type = TREE_TYPE (base);
> -         if (TREE_CODE (type) == POINTER_TYPE
> +         if (POINTER_TYPE_P (type)
>               || (TREE_CODE (base) != PARM_DECL && !VAR_P (base))
>               || !(val = DECL_SIZE_UNIT (base)))
>             val = build_all_ones_cst (size_type_node);
> diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
> index bcec5405242..3c2a742f512 100644
> --- a/gcc/gimple-ssa-sprintf.cc
> +++ b/gcc/gimple-ssa-sprintf.cc
> @@ -1372,7 +1372,7 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
>        return res;
>      }
>    else if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
> -          || TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE)
> +          || POINTER_TYPE_P (TREE_TYPE (arg)))
>      /* Determine the type of the provided non-constant argument.  */
>      argtype = TREE_TYPE (arg);
>    else
> @@ -1434,7 +1434,7 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
>                 {
>                   tree type = TREE_TYPE (gimple_assign_rhs1 (def));
>                   if (INTEGRAL_TYPE_P (type)
> -                     || TREE_CODE (type) == POINTER_TYPE)
> +                     || POINTER_TYPE_P (type))
>                     argtype = type;
>                 }
>             }
> @@ -1443,7 +1443,7 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
>
>    if (!argmin)
>      {
> -      if (TREE_CODE (argtype) == POINTER_TYPE)
> +      if (POINTER_TYPE_P (argtype))
>         {
>           argmin = build_int_cst (pointer_sized_int_node, 0);
>           argmax = build_all_ones_cst (pointer_sized_int_node);
> diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
> index abfb8685ce7..d12f797f36b 100644
> --- a/gcc/gimple-ssa-warn-access.cc
> +++ b/gcc/gimple-ssa-warn-access.cc
> @@ -554,7 +554,7 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
>        if (!argtype)
>         break;
>
> -      if (TREE_CODE (argtype) != POINTER_TYPE)
> +      if (!POINTER_TYPE_P (argtype))
>         continue;
>
>        argtype = TREE_TYPE (argtype);
> diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
> index e48fe1eb841..0b383cced44 100644
> --- a/gcc/gimple-ssa-warn-restrict.cc
> +++ b/gcc/gimple-ssa-warn-restrict.cc
> @@ -1998,8 +1998,8 @@ pass_wrestrict::check_call (gimple *call)
>    /* DST, SRC, or DSTWR can also have the wrong type in a call to
>       a function declared without a prototype.  Avoid checking such
>       invalid calls.  */
> -  if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
> -      || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
> +  if (!POINTER_TYPE_P (TREE_TYPE (dst))
> +      || (src && !POINTER_TYPE_P (TREE_TYPE (src)))
>        || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
>      return;
>
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/string-strlen-1.C 
> b/gcc/testsuite/g++.dg/tree-ssa/string-strlen-1.C
> new file mode 100644
> index 00000000000..fb7f9200f25
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/string-strlen-1.C
> @@ -0,0 +1,20 @@
> +// { dg-do compile } */
> +// { dg-additional-options "-fdump-tree-optimized -O2" }
> +// { dg-skip-if "requires hosted libstdc++ for string" { ! hostedlib } }
> +// PR tree-optimization/122754
> +
> +#include <string>
> +
> +int g(void)
> +{
> +  std::string a="a";
> +  return __builtin_strlen(a.c_str());
> +}
> +
> +// This should be optimized to just `return 1` without any
> +// references to struct string or any other variables.
> +
> +// { dg-final { scan-tree-dump-not "strlen " "optimized" } }
> +// { dg-final { scan-tree-dump-not "struct string" "optimized" } }
> +// { dg-final { scan-tree-dump "return 1" "optimized" } }
> +
> diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
> index bb6561cde03..b9457c988ac 100644
> --- a/gcc/tree-ssa-strlen.cc
> +++ b/gcc/tree-ssa-strlen.cc
> @@ -1997,7 +1997,7 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
>                   if (tree size = DECL_SIZE_UNIT (base))
>                     if (size
>                         && TREE_CODE (size) == INTEGER_CST
> -                       && TREE_CODE (TREE_TYPE (base)) != POINTER_TYPE)
> +                       && !POINTER_TYPE_P (TREE_TYPE (base)))
>                       max = wi::to_wide (size);
>                 }
>             }
> @@ -2792,7 +2792,7 @@ strlen_pass::handle_builtin_strncat (built_in_function)
>  bool
>  is_strlen_related_p (tree src, tree len)
>  {
> -  if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
> +  if (POINTER_TYPE_P (TREE_TYPE (len))
>        && operand_equal_p (src, len, 0))
>      return true;
>
> @@ -2853,7 +2853,7 @@ is_strlen_related_p (tree src, tree len)
>    tree rhs1 = gimple_assign_rhs1 (lendef);
>    tree rhstype = TREE_TYPE (rhs1);
>
> -  if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
> +  if ((POINTER_TYPE_P (rhstype) && code == POINTER_PLUS_EXPR)
>        || (INTEGRAL_TYPE_P (rhstype)
>           && (code == BIT_AND_EXPR
>               || code == NOP_EXPR)))
> @@ -5746,7 +5746,7 @@ strlen_pass::handle_assign (tree lhs, tree rhs, bool 
> *zero_write)
>         {
>           tree ref = TREE_OPERAND (lhs, i);
>           type = TREE_TYPE (ref);
> -         if (TREE_CODE (type) == POINTER_TYPE)
> +         if (POINTER_TYPE_P (type))
>             type = TREE_TYPE (type);
>           if (TREE_CODE (type) == ARRAY_TYPE)
>             type = TREE_TYPE (type);
> --
> 2.43.0
>

Reply via email to