https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90662
--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- The inequality in g() should be != 3, not != 5: void g (int n) { char a[n]; __builtin_strcpy (a, "12345"); if (__builtin_strlen (&a[2]) != 3) // not folded __builtin_abort (); } The expression '&*a.1_9[2]' in the GIMPLE can be traced to the original IL (below). I wonder how many other transformations make the same assumption as strlen that such ADDR_EXPRs are simplified into POINTER_PLUS_EXPRs. ;; Function g (null) ;; enabled by -tree-original { char a[0:(sizetype) ((long int) SAVE_EXPR <n> + -1)]; (void) SAVE_EXPR <n>; char a[0:(sizetype) ((long int) SAVE_EXPR <n> + -1)]; __builtin_strcpy ((char *) &a, (const char *) "12345"); if (__builtin_strlen ((const char *) &a[2]) != 3) { __builtin_abort (); } } ;; Function h (null) ;; enabled by -tree-original { char * a = (char *) __builtin_malloc (6); char * a = (char *) __builtin_malloc (6); __builtin_strcpy (a, (const char *) "12345"); if (__builtin_strlen ((const char *) (a + 2)) != 3) { __builtin_abort (); } }