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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P2
             Status|UNCONFIRMED                 |NEW
           Keywords|lto                         |
   Last reconfirmed|                            |2018-06-21
                 CC|                            |msebor at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org
     Ever confirmed|0                           |1
            Summary|min(4, strlen(s)) optimized |[8/9 Regression] min(4,
                   |to strlen(s) with -flto     |strlen(s)) optimized to
                   |                            |strlen(s) with -flto
   Target Milestone|---                         |8.2

--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Vladimir Panteleev from comment #5)
> (In reply to Andrew Pinski from comment #2)
> > Note gcc thinks strlen(s) is less than or equal to 3 as s is really T.s
> > which is an array of 4 in size and there for the last element has to be a
> > null char.
> 
> Hmm. Here is a simpler example which illustrates this:
> 
> /////////////////// test.c ///////////////////
> #include <stdio.h>
> #include <string.h>
> 
> struct S
> {
>     int x[1];
> };
> 
> union U
> {
>     struct S arr[64];
>     char s[256];
> };
> 
> int main()
> {
>     union U u;
>     strcpy(u.s, "abcdefghijklmnopqrstuvwxyz");
>     size_t len = strlen((char*)&u.arr[1].x);
>     puts(len > 10 ? "YES" : "NO");
>     return 0;
> }
> //////////////////////////////////////////////
> 
> This prints "NO" with -O1 and above. clang always prints "YES".
> 
> Are you sure this is an optimization the compiler is allowed to make,
> though? I would think that the explicit cast to char* removes all bets as to
> how long the string really is.

the explicit conversion to char * is unimportant (strlen formal argument
is of type const char * already).  Indeed strlen may read any memory
and thus is not bound to type layout.

GCC optimizes this during CCP which nowadays uses get_range_strlen (),
IMHO indeed a questionable optimization we shouldn't perform.  The
optimization happens because of

  if (tree lhs = gimple_call_lhs (stmt))
    if (TREE_CODE (lhs) == SSA_NAME
        && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
      set_range_info (lhs, VR_RANGE, minlen, maxlen);

and we compute maxlen to 3.

That function was designed for warnings we may not use it for optimization.

Reply via email to