https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77889

            Bug ID: 77889
           Summary: missing optimization on strlen(p + offset) with a
                    bounded offset
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

While testing my patch for bug 77608 I noticed another case of the same
limitation, this one in the tree-ssa-strlen pass.  The test case below shows
that while (with my patch) __builtin_object_size is able to compute the range
the smallest sizes of the string that p points to (i.e., either 2 or 3 bytes),
__builtin_strlen is not able to compute the range of lengths of the string that
p points to, even though the range of the offsets into the string is available
via the get_range_info function.  (The test cases uses _Bool only to constrain
the range to small bounds; the problem is general and not specific to a
particular type of the offset variable.)

$ cat rng.c && /build/gcc-77608/gcc/xgcc -B /build/gcc-77608/gcc -O2 -S -Wall
-Wextra -Wpedantic -fdump-tree-vrp=/dev/stdout rng.c
void f (_Bool i)
{
  const char *p = "abc";
  p += i;

  unsigned long n = __builtin_strlen (p);

  if (n < 2 || 3 < n)
    __builtin_abort ();
}

void g (_Bool i)
{
  const char *p = "ab";
  p += i;

  unsigned long n = __builtin_object_size (p, 2);

  if (n < 2 || 3 < n)
    __builtin_abort ();
}


;; Function f (f, funcdef_no=0, decl_uid=1791, cgraph_uid=0, symbol_order=0)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { }
;; 4 succs { 1 }

Value ranges after VRP:

_1: [0, 1]
_2: [0, +INF]
i_3(D): VARYING
p_4: VARYING
n_6: VARYING


f (_Bool i)
{
  long unsigned int n;
  const char * p;
  sizetype _1;
  long unsigned int _2;

  <bb 2>:
  _1 = (sizetype) i_3(D);
  p_4 = "abc" + _1;
  n_6 = __builtin_strlen (p_4);
  _2 = n_6 + 18446744073709551614;
  if (_2 > 1)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  __builtin_abort ();

  <bb 4>:
  return;

}



;; Function f (f, funcdef_no=0, decl_uid=1791, cgraph_uid=0, symbol_order=0)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { }
;; 4 succs { 1 }

Value ranges after VRP:

_1: [0, 1]
_2: [0, +INF]
i_3(D): VARYING
p_4: VARYING
n_6: VARYING


f (_Bool i)
{
  long unsigned int n;
  const char * p;
  sizetype _1;
  long unsigned int _2;

  <bb 2>:
  _1 = (sizetype) i_3(D);
  p_4 = "abc" + _1;
  n_6 = __builtin_strlen (p_4);
  _2 = n_6 + 18446744073709551614;
  if (_2 > 1)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  __builtin_abort ();

  <bb 4>:
  return;

}


;; Function g (g, funcdef_no=1, decl_uid=1796, cgraph_uid=1, symbol_order=1)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }

Value ranges after VRP:

_1: [0, 1]
i_3(D): VARYING
p_4: VARYING
n_6: VARYING


g (_Bool i)
{
  long unsigned int n;
  const char * p;
  sizetype _1;

  <bb 2>:
  _1 = (sizetype) i_3(D);
  p_4 = "ab" + _1;
  n_6 = __builtin_object_size (p_4, 2);
  return;

}



;; Function g (g, funcdef_no=1, decl_uid=1796, cgraph_uid=1, symbol_order=1)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }

Value ranges after VRP:



g (_Bool i)
{
  long unsigned int n;
  const char * p;

  <bb 2>:
  return;

}

Reply via email to