diff options
author | Martin Sebor <msebor@redhat.com> | 2018-07-26 16:45:43 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-07-26 10:45:43 -0600 |
commit | aca8570e11d28b8c33d26593df6d4725a6140aab (patch) | |
tree | bea2270f62332f8d85e1bcd3adcb0c246cb32648 /gcc/tree.c | |
parent | 4b8b1f5997e7f16713be5c05e7fd40c122fa9381 (diff) | |
download | gcc-aca8570e11d28b8c33d26593df6d4725a6140aab.zip gcc-aca8570e11d28b8c33d26593df6d4725a6140aab.tar.gz gcc-aca8570e11d28b8c33d26593df6d4725a6140aab.tar.bz2 |
PR tree-optimization/86043 - strlen after memcpy partially overwriting a string not optimized
PR tree-optimization/86043 - strlen after memcpy partially overwriting a string not optimized
PR tree-optimization/86042 - missing strlen optimization after second strcpy
gcc/ChangeLog:
PR tree-optimization/86043
PR tree-optimization/86042
* tree-ssa-strlen.c (handle_builtin_memcpy): Handle strict overlaps.
(get_string_cst_length): Rename...
(get_min_string_length): ...to this. Add argument.
(handle_char_store): Extend to handle multi-character stores by
MEM_REF.
* tree.c (initializer_zerop): Use new argument. Handle MEM_REF.
* tree.h (initializer_zerop): Add argument.
gcc/testsuite/ChangeLog:
PR tree-optimization/86043
PR tree-optimization/86042
* gcc/testsuite/gcc.dg/attr-nonstring-2.c: Xfail test cases due to
pr86688.
* gcc.dg/strlenopt-44.c: New test.
From-SVN: r263018
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 103 |
1 files changed, 83 insertions, 20 deletions
@@ -10643,61 +10643,124 @@ vector_cst_elt (const_tree t, unsigned int i) } /* Given an initializer INIT, return TRUE if INIT is zero or some - aggregate of zeros. Otherwise return FALSE. */ + aggregate of zeros. Otherwise return FALSE. If NONZERO is not + null, set *NONZERO if and only if INIT is known not to be all + zeros. The combination of return value of false and *NONZERO + false implies that INIT may but need not be all zeros. Other + combinations indicate definitive answers. */ + bool -initializer_zerop (const_tree init) +initializer_zerop (const_tree init, bool *nonzero /* = NULL */) { - tree elt; + bool dummy; + if (!nonzero) + nonzero = &dummy; + + /* Conservatively clear NONZERO and set it only if INIT is definitely + not all zero. */ + *nonzero = false; STRIP_NOPS (init); + unsigned HOST_WIDE_INT off = 0; + switch (TREE_CODE (init)) { case INTEGER_CST: - return integer_zerop (init); + if (integer_zerop (init)) + return true; + + *nonzero = true; + return false; case REAL_CST: /* ??? Note that this is not correct for C4X float formats. There, a bit pattern of all zeros is 1.0; 0.0 is encoded with the most negative exponent. */ - return real_zerop (init) - && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init)); + if (real_zerop (init) + && !REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init))) + return true; + + *nonzero = true; + return false; case FIXED_CST: - return fixed_zerop (init); + if (fixed_zerop (init)) + return true; + + *nonzero = true; + return false; case COMPLEX_CST: - return integer_zerop (init) - || (real_zerop (init) - && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init))) - && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init)))); + if (integer_zerop (init) + || (real_zerop (init) + && !REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init))) + && !REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))))) + return true; + + *nonzero = true; + return false; case VECTOR_CST: - return (VECTOR_CST_NPATTERNS (init) == 1 - && VECTOR_CST_DUPLICATE_P (init) - && initializer_zerop (VECTOR_CST_ENCODED_ELT (init, 0))); + if (VECTOR_CST_NPATTERNS (init) == 1 + && VECTOR_CST_DUPLICATE_P (init) + && initializer_zerop (VECTOR_CST_ENCODED_ELT (init, 0))) + return true; + + *nonzero = true; + return false; case CONSTRUCTOR: { - unsigned HOST_WIDE_INT idx; - if (TREE_CLOBBER_P (init)) return false; + + unsigned HOST_WIDE_INT idx; + tree elt; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) - if (!initializer_zerop (elt)) + if (!initializer_zerop (elt, nonzero)) return false; + return true; } + case MEM_REF: + { + tree arg = TREE_OPERAND (init, 0); + if (TREE_CODE (arg) != ADDR_EXPR) + return false; + tree offset = TREE_OPERAND (init, 1); + if (TREE_CODE (offset) != INTEGER_CST + || !tree_fits_uhwi_p (offset)) + return false; + off = tree_to_uhwi (offset); + if (INT_MAX < off) + return false; + arg = TREE_OPERAND (arg, 0); + if (TREE_CODE (arg) != STRING_CST) + return false; + init = arg; + } + /* Fall through. */ + case STRING_CST: { - int i; + gcc_assert (off <= INT_MAX); + + int i = off; + int n = TREE_STRING_LENGTH (init); + if (n <= i) + return false; /* We need to loop through all elements to handle cases like "\0" and "\0foobar". */ - for (i = 0; i < TREE_STRING_LENGTH (init); ++i) + for (i = 0; i < n; ++i) if (TREE_STRING_POINTER (init)[i] != '\0') - return false; + { + *nonzero = true; + return false; + } return true; } |