On Wed, May 17, 2017 at 07:52:38AM +0100, Richard Sandiford wrote: > 2017-05-17 Richard Sandiford <richard.sandif...@linaro.org> > > gcc/ > * tree-ssa-strlen.c (strinfo): Rename the length field to > nonzero_chars. Add a full_string_p field. > (compare_nonzero_chars, zero_length_string_p): New functions. > (get_addr_stridx): Add an offset_out parameter. > Use compare_nonzero_chars. > (get_stridx): Update accordingly. Use compare_nonzero_chars. > (new_strinfo): Update after above changes to strinfo. > (set_endptr_and_length): Set full_string_p. > (get_string_length): Update after above changes to strinfo. > (unshare_strinfo): Update call to new_strinfo. > (maybe_invalidate): Likewise. > (get_stridx_plus_constant): Change off to unsigned HOST_WIDE_INT. > Use compare_nonzero_chars and zero_string_p. Treat nonzero_chars > as a uhwi instead of an shwi. Update after above changes to > strinfo and new_strinfo. > (zero_length_string): Assert that chainsi contains full strings. > Use zero_length_string_p. Update call to new_strinfo. > (adjust_related_strinfos): Update after above changes to strinfo. > Copy full_string_p from origsi. > (adjust_last_stmt): Use zero_length_string_p. > (handle_builtin_strlen): Update after above changes to strinfo and > new_strinfo. Install the lhs as the string length if the previous > entry didn't describe a full string. > (handle_builtin_strchr): Update after above changes to strinfo > and new_strinfo. > (handle_builtin_strcpy): Likewise. > (handle_builtin_strcat): Likewise. > (handle_builtin_malloc): Likewise. > (handle_pointer_plus): Likewise. > (handle_builtin_memcpy): Likewise. Track nonzero characters > that aren't necessarily followed by a nul terminator. > (handle_char_store): Likewise. > > gcc/testsuite/ > * gcc.dg/strlenopt-32.c: New testcase. > * gcc.dg/strlenopt-33.c: Likewise. > * gcc.dg/strlenopt-33g.c: Likewise. > * gcc.dg/strlenopt-34.c: Likewise. > * gcc.dg/strlenopt-35.c: Likewise.
Ok, with a small nit. > @@ -501,8 +550,8 @@ set_endptr_and_length (location_t loc, s > static tree > get_string_length (strinfo *si) > { > - if (si->length) > - return si->length; > + if (si->nonzero_chars) > + return si->full_string_p ? si->nonzero_chars : NULL; This should be NULL_TREE. > > if (si->stmt) > { > @@ -595,19 +644,19 @@ get_string_length (strinfo *si) > for (strinfo *chainsi = verify_related_strinfos (si); > chainsi != NULL; > chainsi = get_next_strinfo (chainsi)) > - if (chainsi->length == NULL) > + if (chainsi->nonzero_chars == NULL) and this actually too (though it is preexisting). For future work, it would be nice if we could handle not just memcpy and single character stores, but also cases where a memcpy is folded into a store of couple of adjacent bytes, say MEM_REF[ptr, 0] = 0x12345678; is storing 4 non-zero bytes, while = 0x345678; would be zero nonzero_chars + full_string_p for big endian and 3 non-zero bytes plus zero byte on little endian. One could use native_encode_expr on the rhs and then determine the nonzero count at the start and optional presence of a zero char afterwards. Jakub