pa.c (pa_som_asm_init_sections): Fix comment.
[official-gcc.git] / gcc / tree-ssa-strlen.c
blobe75d13392f6e3ee48ebf4abca20faeed375cd162
1 /* String length optimization
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "alloc-pool.h"
29 #include "tree-pass.h"
30 #include "ssa.h"
31 #include "cgraph.h"
32 #include "gimple-pretty-print.h"
33 #include "gimple-ssa-warn-restrict.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
36 #include "gimple-fold.h"
37 #include "tree-eh.h"
38 #include "gimplify.h"
39 #include "gimple-iterator.h"
40 #include "gimplify-me.h"
41 #include "expr.h"
42 #include "tree-dfa.h"
43 #include "domwalk.h"
44 #include "tree-ssa-alias.h"
45 #include "tree-ssa-propagate.h"
46 #include "params.h"
47 #include "ipa-chkp.h"
48 #include "tree-hash-traits.h"
49 #include "builtins.h"
50 #include "target.h"
51 #include "diagnostic-core.h"
52 #include "diagnostic.h"
53 #include "intl.h"
54 #include "attribs.h"
55 #include "calls.h"
57 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
58 is an index into strinfo vector, negative value stands for
59 string length of a string literal (~strlen). */
60 static vec<int> ssa_ver_to_stridx;
62 /* Number of currently active string indexes plus one. */
63 static int max_stridx;
65 /* String information record. */
66 struct strinfo
68 /* Number of leading characters that are known to be nonzero. This is
69 also the length of the string if FULL_STRING_P.
71 The values in a list of related string pointers must be consistent;
72 that is, if strinfo B comes X bytes after strinfo A, it must be
73 the case that A->nonzero_chars == X + B->nonzero_chars. */
74 tree nonzero_chars;
75 /* Any of the corresponding pointers for querying alias oracle. */
76 tree ptr;
77 /* This is used for two things:
79 - To record the statement that should be used for delayed length
80 computations. We maintain the invariant that all related strinfos
81 have delayed lengths or none do.
83 - To record the malloc or calloc call that produced this result. */
84 gimple *stmt;
85 /* Pointer to '\0' if known, if NULL, it can be computed as
86 ptr + length. */
87 tree endptr;
88 /* Reference count. Any changes to strinfo entry possibly shared
89 with dominating basic blocks need unshare_strinfo first, except
90 for dont_invalidate which affects only the immediately next
91 maybe_invalidate. */
92 int refcount;
93 /* Copy of index. get_strinfo (si->idx) should return si; */
94 int idx;
95 /* These 3 fields are for chaining related string pointers together.
96 E.g. for
97 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
98 strcpy (c, d); e = c + dl;
99 strinfo(a) -> strinfo(c) -> strinfo(e)
100 All have ->first field equal to strinfo(a)->idx and are doubly
101 chained through prev/next fields. The later strinfos are required
102 to point into the same string with zero or more bytes after
103 the previous pointer and all bytes in between the two pointers
104 must be non-zero. Functions like strcpy or memcpy are supposed
105 to adjust all previous strinfo lengths, but not following strinfo
106 lengths (those are uncertain, usually invalidated during
107 maybe_invalidate, except when the alias oracle knows better).
108 Functions like strcat on the other side adjust the whole
109 related strinfo chain.
110 They are updated lazily, so to use the chain the same first fields
111 and si->prev->next == si->idx needs to be verified. */
112 int first;
113 int next;
114 int prev;
115 /* A flag whether the string is known to be written in the current
116 function. */
117 bool writable;
118 /* A flag for the next maybe_invalidate that this strinfo shouldn't
119 be invalidated. Always cleared by maybe_invalidate. */
120 bool dont_invalidate;
121 /* True if the string is known to be nul-terminated after NONZERO_CHARS
122 characters. False is useful when detecting strings that are built
123 up via successive memcpys. */
124 bool full_string_p;
127 /* Pool for allocating strinfo_struct entries. */
128 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
130 /* Vector mapping positive string indexes to strinfo, for the
131 current basic block. The first pointer in the vector is special,
132 it is either NULL, meaning the vector isn't shared, or it is
133 a basic block pointer to the owner basic_block if shared.
134 If some other bb wants to modify the vector, the vector needs
135 to be unshared first, and only the owner bb is supposed to free it. */
136 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
138 /* One OFFSET->IDX mapping. */
139 struct stridxlist
141 struct stridxlist *next;
142 HOST_WIDE_INT offset;
143 int idx;
146 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
147 struct decl_stridxlist_map
149 struct tree_map_base base;
150 struct stridxlist list;
153 /* Hash table for mapping decls to a chained list of offset -> idx
154 mappings. */
155 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
157 /* Hash table mapping strlen calls to stridx instances describing
158 the calls' arguments. Non-null only when warn_stringop_truncation
159 is non-zero. */
160 typedef std::pair<int, location_t> stridx_strlenloc;
161 static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
163 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
164 static struct obstack stridx_obstack;
166 /* Last memcpy statement if it could be adjusted if the trailing
167 '\0' written is immediately overwritten, or
168 *x = '\0' store that could be removed if it is immediately overwritten. */
169 struct laststmt_struct
171 gimple *stmt;
172 tree len;
173 int stridx;
174 } laststmt;
176 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
177 static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
179 /* Return:
181 - 1 if SI is known to start with more than OFF nonzero characters.
183 - 0 if SI is known to start with OFF nonzero characters,
184 but is not known to start with more.
186 - -1 if SI might not start with OFF nonzero characters. */
188 static inline int
189 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
191 if (si->nonzero_chars
192 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
193 return compare_tree_int (si->nonzero_chars, off);
194 else
195 return -1;
198 /* Return true if SI is known to be a zero-length string. */
200 static inline bool
201 zero_length_string_p (strinfo *si)
203 return si->full_string_p && integer_zerop (si->nonzero_chars);
206 /* Return strinfo vector entry IDX. */
208 static inline strinfo *
209 get_strinfo (int idx)
211 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
212 return NULL;
213 return (*stridx_to_strinfo)[idx];
216 /* Get the next strinfo in the chain after SI, or null if none. */
218 static inline strinfo *
219 get_next_strinfo (strinfo *si)
221 if (si->next == 0)
222 return NULL;
223 strinfo *nextsi = get_strinfo (si->next);
224 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
225 return NULL;
226 return nextsi;
229 /* Helper function for get_stridx. Return the strinfo index of the address
230 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
231 OK to return the index for some X <= &EXP and store &EXP - X in
232 *OFFSET_OUT. */
234 static int
235 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
237 HOST_WIDE_INT off;
238 struct stridxlist *list, *last = NULL;
239 tree base;
241 if (!decl_to_stridxlist_htab)
242 return 0;
244 base = get_addr_base_and_unit_offset (exp, &off);
245 if (base == NULL || !DECL_P (base))
246 return 0;
248 list = decl_to_stridxlist_htab->get (base);
249 if (list == NULL)
250 return 0;
254 if (list->offset == off)
256 if (offset_out)
257 *offset_out = 0;
258 return list->idx;
260 if (list->offset > off)
261 return 0;
262 last = list;
263 list = list->next;
265 while (list);
267 if ((offset_out || ptr) && last && last->idx > 0)
269 unsigned HOST_WIDE_INT rel_off
270 = (unsigned HOST_WIDE_INT) off - last->offset;
271 strinfo *si = get_strinfo (last->idx);
272 if (si && compare_nonzero_chars (si, rel_off) >= 0)
274 if (offset_out)
276 *offset_out = rel_off;
277 return last->idx;
279 else
280 return get_stridx_plus_constant (si, rel_off, ptr);
283 return 0;
286 /* Return string index for EXP. */
288 static int
289 get_stridx (tree exp)
291 tree s, o;
293 if (TREE_CODE (exp) == SSA_NAME)
295 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
296 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
297 int i;
298 tree e = exp;
299 HOST_WIDE_INT off = 0;
300 for (i = 0; i < 5; i++)
302 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
303 if (!is_gimple_assign (def_stmt)
304 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
305 return 0;
306 tree rhs1 = gimple_assign_rhs1 (def_stmt);
307 tree rhs2 = gimple_assign_rhs2 (def_stmt);
308 if (TREE_CODE (rhs1) != SSA_NAME
309 || !tree_fits_shwi_p (rhs2))
310 return 0;
311 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
312 if (this_off < 0)
313 return 0;
314 off = (unsigned HOST_WIDE_INT) off + this_off;
315 if (off < 0)
316 return 0;
317 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
319 strinfo *si
320 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
321 if (si && compare_nonzero_chars (si, off) >= 0)
322 return get_stridx_plus_constant (si, off, exp);
324 e = rhs1;
326 return 0;
329 if (TREE_CODE (exp) == ADDR_EXPR)
331 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
332 if (idx != 0)
333 return idx;
336 s = string_constant (exp, &o);
337 if (s != NULL_TREE
338 && (o == NULL_TREE || tree_fits_shwi_p (o))
339 && TREE_STRING_LENGTH (s) > 0)
341 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
342 const char *p = TREE_STRING_POINTER (s);
343 int max = TREE_STRING_LENGTH (s) - 1;
345 if (p[max] == '\0' && offset >= 0 && offset <= max)
346 return ~(int) strlen (p + offset);
348 return 0;
351 /* Return true if strinfo vector is shared with the immediate dominator. */
353 static inline bool
354 strinfo_shared (void)
356 return vec_safe_length (stridx_to_strinfo)
357 && (*stridx_to_strinfo)[0] != NULL;
360 /* Unshare strinfo vector that is shared with the immediate dominator. */
362 static void
363 unshare_strinfo_vec (void)
365 strinfo *si;
366 unsigned int i = 0;
368 gcc_assert (strinfo_shared ());
369 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
370 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
371 if (si != NULL)
372 si->refcount++;
373 (*stridx_to_strinfo)[0] = NULL;
376 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
377 Return a pointer to the location where the string index can
378 be stored (if 0) or is stored, or NULL if this can't be tracked. */
380 static int *
381 addr_stridxptr (tree exp)
383 HOST_WIDE_INT off;
385 tree base = get_addr_base_and_unit_offset (exp, &off);
386 if (base == NULL_TREE || !DECL_P (base))
387 return NULL;
389 if (!decl_to_stridxlist_htab)
391 decl_to_stridxlist_htab
392 = new hash_map<tree_decl_hash, stridxlist> (64);
393 gcc_obstack_init (&stridx_obstack);
396 bool existed;
397 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
398 if (existed)
400 int i;
401 stridxlist *before = NULL;
402 for (i = 0; i < 32; i++)
404 if (list->offset == off)
405 return &list->idx;
406 if (list->offset > off && before == NULL)
407 before = list;
408 if (list->next == NULL)
409 break;
410 list = list->next;
412 if (i == 32)
413 return NULL;
414 if (before)
416 list = before;
417 before = XOBNEW (&stridx_obstack, struct stridxlist);
418 *before = *list;
419 list->next = before;
420 list->offset = off;
421 list->idx = 0;
422 return &list->idx;
424 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
425 list = list->next;
428 list->next = NULL;
429 list->offset = off;
430 list->idx = 0;
431 return &list->idx;
434 /* Create a new string index, or return 0 if reached limit. */
436 static int
437 new_stridx (tree exp)
439 int idx;
440 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
441 return 0;
442 if (TREE_CODE (exp) == SSA_NAME)
444 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
445 return 0;
446 idx = max_stridx++;
447 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
448 return idx;
450 if (TREE_CODE (exp) == ADDR_EXPR)
452 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
453 if (pidx != NULL)
455 gcc_assert (*pidx == 0);
456 *pidx = max_stridx++;
457 return *pidx;
460 return 0;
463 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
465 static int
466 new_addr_stridx (tree exp)
468 int *pidx;
469 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
470 return 0;
471 pidx = addr_stridxptr (exp);
472 if (pidx != NULL)
474 gcc_assert (*pidx == 0);
475 *pidx = max_stridx++;
476 return *pidx;
478 return 0;
481 /* Create a new strinfo. */
483 static strinfo *
484 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
486 strinfo *si = strinfo_pool.allocate ();
487 si->nonzero_chars = nonzero_chars;
488 si->ptr = ptr;
489 si->stmt = NULL;
490 si->endptr = NULL_TREE;
491 si->refcount = 1;
492 si->idx = idx;
493 si->first = 0;
494 si->prev = 0;
495 si->next = 0;
496 si->writable = false;
497 si->dont_invalidate = false;
498 si->full_string_p = full_string_p;
499 return si;
502 /* Decrease strinfo refcount and free it if not referenced anymore. */
504 static inline void
505 free_strinfo (strinfo *si)
507 if (si && --si->refcount == 0)
508 strinfo_pool.remove (si);
511 /* Set strinfo in the vector entry IDX to SI. */
513 static inline void
514 set_strinfo (int idx, strinfo *si)
516 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
517 unshare_strinfo_vec ();
518 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
519 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
520 (*stridx_to_strinfo)[idx] = si;
523 /* Return the first strinfo in the related strinfo chain
524 if all strinfos in between belong to the chain, otherwise NULL. */
526 static strinfo *
527 verify_related_strinfos (strinfo *origsi)
529 strinfo *si = origsi, *psi;
531 if (origsi->first == 0)
532 return NULL;
533 for (; si->prev; si = psi)
535 if (si->first != origsi->first)
536 return NULL;
537 psi = get_strinfo (si->prev);
538 if (psi == NULL)
539 return NULL;
540 if (psi->next != si->idx)
541 return NULL;
543 if (si->idx != si->first)
544 return NULL;
545 return si;
548 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
549 Use LOC for folding. */
551 static void
552 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
554 si->endptr = endptr;
555 si->stmt = NULL;
556 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
557 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
558 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
559 end_as_size, start_as_size);
560 si->full_string_p = true;
563 /* Return string length, or NULL if it can't be computed. */
565 static tree
566 get_string_length (strinfo *si)
568 if (si->nonzero_chars)
569 return si->full_string_p ? si->nonzero_chars : NULL;
571 if (si->stmt)
573 gimple *stmt = si->stmt, *lenstmt;
574 bool with_bounds = gimple_call_with_bounds_p (stmt);
575 tree callee, lhs, fn, tem;
576 location_t loc;
577 gimple_stmt_iterator gsi;
579 gcc_assert (is_gimple_call (stmt));
580 callee = gimple_call_fndecl (stmt);
581 gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
582 lhs = gimple_call_lhs (stmt);
583 /* unshare_strinfo is intentionally not called here. The (delayed)
584 transformation of strcpy or strcat into stpcpy is done at the place
585 of the former strcpy/strcat call and so can affect all the strinfos
586 with the same stmt. If they were unshared before and transformation
587 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
588 just compute the right length. */
589 switch (DECL_FUNCTION_CODE (callee))
591 case BUILT_IN_STRCAT:
592 case BUILT_IN_STRCAT_CHK:
593 case BUILT_IN_STRCAT_CHKP:
594 case BUILT_IN_STRCAT_CHK_CHKP:
595 gsi = gsi_for_stmt (stmt);
596 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
597 gcc_assert (lhs == NULL_TREE);
598 tem = unshare_expr (gimple_call_arg (stmt, 0));
599 if (with_bounds)
601 lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl,
602 2, tem, gimple_call_arg (stmt, 1));
603 gimple_call_set_with_bounds (lenstmt, true);
605 else
606 lenstmt = gimple_build_call (fn, 1, tem);
607 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
608 gimple_call_set_lhs (lenstmt, lhs);
609 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
610 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
611 tem = gimple_call_arg (stmt, 0);
612 if (!ptrofftype_p (TREE_TYPE (lhs)))
614 lhs = convert_to_ptrofftype (lhs);
615 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
616 true, GSI_SAME_STMT);
618 lenstmt = gimple_build_assign
619 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
620 POINTER_PLUS_EXPR,tem, lhs);
621 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
622 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
623 lhs = NULL_TREE;
624 /* FALLTHRU */
625 case BUILT_IN_STRCPY:
626 case BUILT_IN_STRCPY_CHK:
627 case BUILT_IN_STRCPY_CHKP:
628 case BUILT_IN_STRCPY_CHK_CHKP:
629 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
630 if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2))
631 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
632 else
633 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
634 if (with_bounds)
635 fn = chkp_maybe_create_clone (fn)->decl;
636 gcc_assert (lhs == NULL_TREE);
637 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
639 fprintf (dump_file, "Optimizing: ");
640 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
642 gimple_call_set_fndecl (stmt, fn);
643 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
644 gimple_call_set_lhs (stmt, lhs);
645 update_stmt (stmt);
646 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
648 fprintf (dump_file, "into: ");
649 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
651 /* FALLTHRU */
652 case BUILT_IN_STPCPY:
653 case BUILT_IN_STPCPY_CHK:
654 case BUILT_IN_STPCPY_CHKP:
655 case BUILT_IN_STPCPY_CHK_CHKP:
656 gcc_assert (lhs != NULL_TREE);
657 loc = gimple_location (stmt);
658 set_endptr_and_length (loc, si, lhs);
659 for (strinfo *chainsi = verify_related_strinfos (si);
660 chainsi != NULL;
661 chainsi = get_next_strinfo (chainsi))
662 if (chainsi->nonzero_chars == NULL)
663 set_endptr_and_length (loc, chainsi, lhs);
664 break;
665 case BUILT_IN_MALLOC:
666 break;
667 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
668 default:
669 gcc_unreachable ();
670 break;
674 return si->nonzero_chars;
677 /* Invalidate string length information for strings whose length
678 might change due to stores in stmt. */
680 static bool
681 maybe_invalidate (gimple *stmt)
683 strinfo *si;
684 unsigned int i;
685 bool nonempty = false;
687 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
688 if (si != NULL)
690 if (!si->dont_invalidate)
692 ao_ref r;
693 /* Do not use si->nonzero_chars. */
694 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
695 if (stmt_may_clobber_ref_p_1 (stmt, &r))
697 set_strinfo (i, NULL);
698 free_strinfo (si);
699 continue;
702 si->dont_invalidate = false;
703 nonempty = true;
705 return nonempty;
708 /* Unshare strinfo record SI, if it has refcount > 1 or
709 if stridx_to_strinfo vector is shared with some other
710 bbs. */
712 static strinfo *
713 unshare_strinfo (strinfo *si)
715 strinfo *nsi;
717 if (si->refcount == 1 && !strinfo_shared ())
718 return si;
720 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
721 nsi->stmt = si->stmt;
722 nsi->endptr = si->endptr;
723 nsi->first = si->first;
724 nsi->prev = si->prev;
725 nsi->next = si->next;
726 nsi->writable = si->writable;
727 set_strinfo (si->idx, nsi);
728 free_strinfo (si);
729 return nsi;
732 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
733 strinfo if there is any. Return it's idx, or 0 if no strinfo has
734 been created. */
736 static int
737 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
738 tree ptr)
740 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
741 return 0;
743 if (compare_nonzero_chars (basesi, off) < 0
744 || !tree_fits_uhwi_p (basesi->nonzero_chars))
745 return 0;
747 unsigned HOST_WIDE_INT nonzero_chars
748 = tree_to_uhwi (basesi->nonzero_chars) - off;
749 strinfo *si = basesi, *chainsi;
750 if (si->first || si->prev || si->next)
751 si = verify_related_strinfos (basesi);
752 if (si == NULL
753 || si->nonzero_chars == NULL_TREE
754 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
755 return 0;
757 if (TREE_CODE (ptr) == SSA_NAME
758 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
759 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
761 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
762 for (chainsi = si; chainsi->next; chainsi = si)
764 si = get_next_strinfo (chainsi);
765 if (si == NULL
766 || si->nonzero_chars == NULL_TREE
767 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
768 break;
769 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
770 if (r != 1)
772 if (r == 0)
774 if (TREE_CODE (ptr) == SSA_NAME)
775 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
776 else
778 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
779 if (pidx != NULL && *pidx == 0)
780 *pidx = si->idx;
782 return si->idx;
784 break;
788 int idx = new_stridx (ptr);
789 if (idx == 0)
790 return 0;
791 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
792 basesi->full_string_p);
793 set_strinfo (idx, si);
794 if (chainsi->next)
796 strinfo *nextsi = unshare_strinfo (get_strinfo (chainsi->next));
797 si->next = nextsi->idx;
798 nextsi->prev = idx;
800 chainsi = unshare_strinfo (chainsi);
801 if (chainsi->first == 0)
802 chainsi->first = chainsi->idx;
803 chainsi->next = idx;
804 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
805 chainsi->endptr = ptr;
806 si->endptr = chainsi->endptr;
807 si->prev = chainsi->idx;
808 si->first = chainsi->first;
809 si->writable = chainsi->writable;
810 return si->idx;
813 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
814 to a zero-length string and if possible chain it to a related strinfo
815 chain whose part is or might be CHAINSI. */
817 static strinfo *
818 zero_length_string (tree ptr, strinfo *chainsi)
820 strinfo *si;
821 int idx;
822 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
823 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
824 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
825 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
827 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
828 return NULL;
829 if (chainsi != NULL)
831 si = verify_related_strinfos (chainsi);
832 if (si)
836 /* We shouldn't mix delayed and non-delayed lengths. */
837 gcc_assert (si->full_string_p);
838 if (si->endptr == NULL_TREE)
840 si = unshare_strinfo (si);
841 si->endptr = ptr;
843 chainsi = si;
844 si = get_next_strinfo (si);
846 while (si != NULL);
847 if (zero_length_string_p (chainsi))
849 if (chainsi->next)
851 chainsi = unshare_strinfo (chainsi);
852 chainsi->next = 0;
854 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
855 return chainsi;
858 else
860 /* We shouldn't mix delayed and non-delayed lengths. */
861 gcc_assert (chainsi->full_string_p);
862 if (chainsi->first || chainsi->prev || chainsi->next)
864 chainsi = unshare_strinfo (chainsi);
865 chainsi->first = 0;
866 chainsi->prev = 0;
867 chainsi->next = 0;
871 idx = new_stridx (ptr);
872 if (idx == 0)
873 return NULL;
874 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
875 set_strinfo (idx, si);
876 si->endptr = ptr;
877 if (chainsi != NULL)
879 chainsi = unshare_strinfo (chainsi);
880 if (chainsi->first == 0)
881 chainsi->first = chainsi->idx;
882 chainsi->next = idx;
883 if (chainsi->endptr == NULL_TREE)
884 chainsi->endptr = ptr;
885 si->prev = chainsi->idx;
886 si->first = chainsi->first;
887 si->writable = chainsi->writable;
889 return si;
892 /* For strinfo ORIGSI whose length has been just updated, adjust other
893 related strinfos so that they match the new ORIGSI. This involves:
895 - adding ADJ to the nonzero_chars fields
896 - copying full_string_p from the new ORIGSI. */
898 static void
899 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
901 strinfo *si = verify_related_strinfos (origsi);
903 if (si == NULL)
904 return;
906 while (1)
908 strinfo *nsi;
910 if (si != origsi)
912 tree tem;
914 si = unshare_strinfo (si);
915 /* We shouldn't see delayed lengths here; the caller must have
916 calculated the old length in order to calculate the
917 adjustment. */
918 gcc_assert (si->nonzero_chars);
919 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
920 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
921 TREE_TYPE (si->nonzero_chars),
922 si->nonzero_chars, tem);
923 si->full_string_p = origsi->full_string_p;
925 si->endptr = NULL_TREE;
926 si->dont_invalidate = true;
928 nsi = get_next_strinfo (si);
929 if (nsi == NULL)
930 return;
931 si = nsi;
935 /* Find if there are other SSA_NAME pointers equal to PTR
936 for which we don't track their string lengths yet. If so, use
937 IDX for them. */
939 static void
940 find_equal_ptrs (tree ptr, int idx)
942 if (TREE_CODE (ptr) != SSA_NAME)
943 return;
944 while (1)
946 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
947 if (!is_gimple_assign (stmt))
948 return;
949 ptr = gimple_assign_rhs1 (stmt);
950 switch (gimple_assign_rhs_code (stmt))
952 case SSA_NAME:
953 break;
954 CASE_CONVERT:
955 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
956 return;
957 if (TREE_CODE (ptr) == SSA_NAME)
958 break;
959 if (TREE_CODE (ptr) != ADDR_EXPR)
960 return;
961 /* FALLTHRU */
962 case ADDR_EXPR:
964 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
965 if (pidx != NULL && *pidx == 0)
966 *pidx = idx;
967 return;
969 default:
970 return;
973 /* We might find an endptr created in this pass. Grow the
974 vector in that case. */
975 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
976 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
978 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
979 return;
980 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
984 /* Return true if STMT is a call to a builtin function with the right
985 arguments and attributes that should be considered for optimization
986 by this pass. */
988 static bool
989 valid_builtin_call (gimple *stmt)
991 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
992 return false;
994 tree callee = gimple_call_fndecl (stmt);
995 switch (DECL_FUNCTION_CODE (callee))
997 case BUILT_IN_MEMCMP:
998 case BUILT_IN_MEMCMP_EQ:
999 case BUILT_IN_STRCHR:
1000 case BUILT_IN_STRCHR_CHKP:
1001 case BUILT_IN_STRLEN:
1002 case BUILT_IN_STRLEN_CHKP:
1003 /* The above functions should be pure. Punt if they aren't. */
1004 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
1005 return false;
1006 break;
1008 case BUILT_IN_CALLOC:
1009 case BUILT_IN_MALLOC:
1010 case BUILT_IN_MEMCPY:
1011 case BUILT_IN_MEMCPY_CHK:
1012 case BUILT_IN_MEMCPY_CHKP:
1013 case BUILT_IN_MEMCPY_CHK_CHKP:
1014 case BUILT_IN_MEMPCPY:
1015 case BUILT_IN_MEMPCPY_CHK:
1016 case BUILT_IN_MEMPCPY_CHKP:
1017 case BUILT_IN_MEMPCPY_CHK_CHKP:
1018 case BUILT_IN_MEMSET:
1019 case BUILT_IN_STPCPY:
1020 case BUILT_IN_STPCPY_CHK:
1021 case BUILT_IN_STPCPY_CHKP:
1022 case BUILT_IN_STPCPY_CHK_CHKP:
1023 case BUILT_IN_STRCAT:
1024 case BUILT_IN_STRCAT_CHK:
1025 case BUILT_IN_STRCAT_CHKP:
1026 case BUILT_IN_STRCAT_CHK_CHKP:
1027 case BUILT_IN_STRCPY:
1028 case BUILT_IN_STRCPY_CHK:
1029 case BUILT_IN_STRCPY_CHKP:
1030 case BUILT_IN_STRCPY_CHK_CHKP:
1031 /* The above functions should be neither const nor pure. Punt if they
1032 aren't. */
1033 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1034 return false;
1035 break;
1037 default:
1038 break;
1041 return true;
1044 /* If the last .MEM setter statement before STMT is
1045 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1046 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1047 just memcpy (x, y, strlen (y)). SI must be the zero length
1048 strinfo. */
1050 static void
1051 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1053 tree vuse, callee, len;
1054 struct laststmt_struct last = laststmt;
1055 strinfo *lastsi, *firstsi;
1056 unsigned len_arg_no = 2;
1058 laststmt.stmt = NULL;
1059 laststmt.len = NULL_TREE;
1060 laststmt.stridx = 0;
1062 if (last.stmt == NULL)
1063 return;
1065 vuse = gimple_vuse (stmt);
1066 if (vuse == NULL_TREE
1067 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1068 || !has_single_use (vuse))
1069 return;
1071 gcc_assert (last.stridx > 0);
1072 lastsi = get_strinfo (last.stridx);
1073 if (lastsi == NULL)
1074 return;
1076 if (lastsi != si)
1078 if (lastsi->first == 0 || lastsi->first != si->first)
1079 return;
1081 firstsi = verify_related_strinfos (si);
1082 if (firstsi == NULL)
1083 return;
1084 while (firstsi != lastsi)
1086 firstsi = get_next_strinfo (firstsi);
1087 if (firstsi == NULL)
1088 return;
1092 if (!is_strcat && !zero_length_string_p (si))
1093 return;
1095 if (is_gimple_assign (last.stmt))
1097 gimple_stmt_iterator gsi;
1099 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1100 return;
1101 if (stmt_could_throw_p (last.stmt))
1102 return;
1103 gsi = gsi_for_stmt (last.stmt);
1104 unlink_stmt_vdef (last.stmt);
1105 release_defs (last.stmt);
1106 gsi_remove (&gsi, true);
1107 return;
1110 if (!valid_builtin_call (last.stmt))
1111 return;
1113 callee = gimple_call_fndecl (last.stmt);
1114 switch (DECL_FUNCTION_CODE (callee))
1116 case BUILT_IN_MEMCPY:
1117 case BUILT_IN_MEMCPY_CHK:
1118 break;
1119 case BUILT_IN_MEMCPY_CHKP:
1120 case BUILT_IN_MEMCPY_CHK_CHKP:
1121 len_arg_no = 4;
1122 break;
1123 default:
1124 return;
1127 len = gimple_call_arg (last.stmt, len_arg_no);
1128 if (tree_fits_uhwi_p (len))
1130 if (!tree_fits_uhwi_p (last.len)
1131 || integer_zerop (len)
1132 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1133 return;
1134 /* Don't adjust the length if it is divisible by 4, it is more efficient
1135 to store the extra '\0' in that case. */
1136 if ((tree_to_uhwi (len) & 3) == 0)
1137 return;
1139 else if (TREE_CODE (len) == SSA_NAME)
1141 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1142 if (!is_gimple_assign (def_stmt)
1143 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1144 || gimple_assign_rhs1 (def_stmt) != last.len
1145 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1146 return;
1148 else
1149 return;
1151 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1152 update_stmt (last.stmt);
1155 /* Handle a strlen call. If strlen of the argument is known, replace
1156 the strlen call with the known value, otherwise remember that strlen
1157 of the argument is stored in the lhs SSA_NAME. */
1159 static void
1160 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1162 int idx;
1163 tree src;
1164 gimple *stmt = gsi_stmt (*gsi);
1165 tree lhs = gimple_call_lhs (stmt);
1167 if (lhs == NULL_TREE)
1168 return;
1170 src = gimple_call_arg (stmt, 0);
1171 idx = get_stridx (src);
1172 if (idx)
1174 strinfo *si = NULL;
1175 tree rhs;
1177 if (idx < 0)
1178 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1179 else
1181 rhs = NULL_TREE;
1182 si = get_strinfo (idx);
1183 if (si != NULL)
1184 rhs = get_string_length (si);
1186 if (rhs != NULL_TREE)
1188 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1190 fprintf (dump_file, "Optimizing: ");
1191 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1193 rhs = unshare_expr (rhs);
1194 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1195 rhs = fold_convert_loc (gimple_location (stmt),
1196 TREE_TYPE (lhs), rhs);
1197 if (!update_call_from_tree (gsi, rhs))
1198 gimplify_and_update_call_from_tree (gsi, rhs);
1199 stmt = gsi_stmt (*gsi);
1200 update_stmt (stmt);
1201 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1203 fprintf (dump_file, "into: ");
1204 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1206 if (si != NULL
1207 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1208 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1209 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1211 si = unshare_strinfo (si);
1212 si->nonzero_chars = lhs;
1213 gcc_assert (si->full_string_p);
1216 if (strlen_to_stridx)
1218 location_t loc = gimple_location (stmt);
1219 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1221 return;
1224 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1225 return;
1226 if (idx == 0)
1227 idx = new_stridx (src);
1228 else
1230 strinfo *si = get_strinfo (idx);
1231 if (si != NULL)
1233 if (!si->full_string_p && !si->stmt)
1235 /* Until now we only had a lower bound on the string length.
1236 Install LHS as the actual length. */
1237 si = unshare_strinfo (si);
1238 tree old = si->nonzero_chars;
1239 si->nonzero_chars = lhs;
1240 si->full_string_p = true;
1241 if (TREE_CODE (old) == INTEGER_CST)
1243 location_t loc = gimple_location (stmt);
1244 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1245 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1246 TREE_TYPE (lhs), lhs, old);
1247 adjust_related_strinfos (loc, si, adj);
1249 else
1251 si->first = 0;
1252 si->prev = 0;
1253 si->next = 0;
1256 return;
1259 if (idx)
1261 strinfo *si = new_strinfo (src, idx, lhs, true);
1262 set_strinfo (idx, si);
1263 find_equal_ptrs (src, idx);
1265 if (strlen_to_stridx)
1267 location_t loc = gimple_location (stmt);
1268 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1273 /* Handle a strchr call. If strlen of the first argument is known, replace
1274 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1275 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1277 static void
1278 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1280 int idx;
1281 tree src;
1282 gimple *stmt = gsi_stmt (*gsi);
1283 tree lhs = gimple_call_lhs (stmt);
1284 bool with_bounds = gimple_call_with_bounds_p (stmt);
1286 if (lhs == NULL_TREE)
1287 return;
1289 if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1)))
1290 return;
1292 src = gimple_call_arg (stmt, 0);
1293 idx = get_stridx (src);
1294 if (idx)
1296 strinfo *si = NULL;
1297 tree rhs;
1299 if (idx < 0)
1300 rhs = build_int_cst (size_type_node, ~idx);
1301 else
1303 rhs = NULL_TREE;
1304 si = get_strinfo (idx);
1305 if (si != NULL)
1306 rhs = get_string_length (si);
1308 if (rhs != NULL_TREE)
1310 location_t loc = gimple_location (stmt);
1312 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1314 fprintf (dump_file, "Optimizing: ");
1315 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1317 if (si != NULL && si->endptr != NULL_TREE)
1319 rhs = unshare_expr (si->endptr);
1320 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1321 TREE_TYPE (rhs)))
1322 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1324 else
1326 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1327 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1328 TREE_TYPE (src), src, rhs);
1329 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1330 TREE_TYPE (rhs)))
1331 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1333 if (!update_call_from_tree (gsi, rhs))
1334 gimplify_and_update_call_from_tree (gsi, rhs);
1335 stmt = gsi_stmt (*gsi);
1336 update_stmt (stmt);
1337 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1339 fprintf (dump_file, "into: ");
1340 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1342 if (si != NULL
1343 && si->endptr == NULL_TREE
1344 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1346 si = unshare_strinfo (si);
1347 si->endptr = lhs;
1349 zero_length_string (lhs, si);
1350 return;
1353 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1354 return;
1355 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1357 if (idx == 0)
1358 idx = new_stridx (src);
1359 else if (get_strinfo (idx) != NULL)
1361 zero_length_string (lhs, NULL);
1362 return;
1364 if (idx)
1366 location_t loc = gimple_location (stmt);
1367 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1368 tree srcu = fold_convert_loc (loc, size_type_node, src);
1369 tree length = fold_build2_loc (loc, MINUS_EXPR,
1370 size_type_node, lhsu, srcu);
1371 strinfo *si = new_strinfo (src, idx, length, true);
1372 si->endptr = lhs;
1373 set_strinfo (idx, si);
1374 find_equal_ptrs (src, idx);
1375 zero_length_string (lhs, si);
1378 else
1379 zero_length_string (lhs, NULL);
1382 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1383 If strlen of the second argument is known, strlen of the first argument
1384 is the same after this call. Furthermore, attempt to convert it to
1385 memcpy. */
1387 static void
1388 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1390 int idx, didx;
1391 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1392 bool success;
1393 gimple *stmt = gsi_stmt (*gsi);
1394 strinfo *si, *dsi, *olddsi, *zsi;
1395 location_t loc;
1396 bool with_bounds = gimple_call_with_bounds_p (stmt);
1398 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1399 dst = gimple_call_arg (stmt, 0);
1400 lhs = gimple_call_lhs (stmt);
1401 idx = get_stridx (src);
1402 si = NULL;
1403 if (idx > 0)
1404 si = get_strinfo (idx);
1406 didx = get_stridx (dst);
1407 olddsi = NULL;
1408 oldlen = NULL_TREE;
1409 if (didx > 0)
1410 olddsi = get_strinfo (didx);
1411 else if (didx < 0)
1412 return;
1414 if (olddsi != NULL)
1415 adjust_last_stmt (olddsi, stmt, false);
1417 srclen = NULL_TREE;
1418 if (si != NULL)
1419 srclen = get_string_length (si);
1420 else if (idx < 0)
1421 srclen = build_int_cst (size_type_node, ~idx);
1423 loc = gimple_location (stmt);
1424 if (srclen == NULL_TREE)
1425 switch (bcode)
1427 case BUILT_IN_STRCPY:
1428 case BUILT_IN_STRCPY_CHK:
1429 case BUILT_IN_STRCPY_CHKP:
1430 case BUILT_IN_STRCPY_CHK_CHKP:
1431 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1432 return;
1433 break;
1434 case BUILT_IN_STPCPY:
1435 case BUILT_IN_STPCPY_CHK:
1436 case BUILT_IN_STPCPY_CHKP:
1437 case BUILT_IN_STPCPY_CHK_CHKP:
1438 if (lhs == NULL_TREE)
1439 return;
1440 else
1442 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1443 srclen = fold_convert_loc (loc, size_type_node, dst);
1444 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1445 lhsuint, srclen);
1447 break;
1448 default:
1449 gcc_unreachable ();
1452 if (didx == 0)
1454 didx = new_stridx (dst);
1455 if (didx == 0)
1456 return;
1458 if (olddsi != NULL)
1460 oldlen = olddsi->nonzero_chars;
1461 dsi = unshare_strinfo (olddsi);
1462 dsi->nonzero_chars = srclen;
1463 dsi->full_string_p = (srclen != NULL_TREE);
1464 /* Break the chain, so adjust_related_strinfo on later pointers in
1465 the chain won't adjust this one anymore. */
1466 dsi->next = 0;
1467 dsi->stmt = NULL;
1468 dsi->endptr = NULL_TREE;
1470 else
1472 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1473 set_strinfo (didx, dsi);
1474 find_equal_ptrs (dst, didx);
1476 dsi->writable = true;
1477 dsi->dont_invalidate = true;
1479 if (dsi->nonzero_chars == NULL_TREE)
1481 strinfo *chainsi;
1483 /* If string length of src is unknown, use delayed length
1484 computation. If string lenth of dst will be needed, it
1485 can be computed by transforming this strcpy call into
1486 stpcpy and subtracting dst from the return value. */
1488 /* Look for earlier strings whose length could be determined if
1489 this strcpy is turned into an stpcpy. */
1491 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1493 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1495 /* When setting a stmt for delayed length computation
1496 prevent all strinfos through dsi from being
1497 invalidated. */
1498 chainsi = unshare_strinfo (chainsi);
1499 chainsi->stmt = stmt;
1500 chainsi->nonzero_chars = NULL_TREE;
1501 chainsi->full_string_p = false;
1502 chainsi->endptr = NULL_TREE;
1503 chainsi->dont_invalidate = true;
1506 dsi->stmt = stmt;
1508 /* Try to detect overlap before returning. This catches cases
1509 like strcpy (d, d + n) where n is non-constant whose range
1510 is such that (n <= strlen (d) holds).
1512 OLDDSI->NONZERO_chars may have been reset by this point with
1513 oldlen holding it original value. */
1514 if (olddsi && oldlen)
1516 /* Add 1 for the terminating NUL. */
1517 tree type = TREE_TYPE (oldlen);
1518 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1519 build_int_cst (type, 1));
1520 check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
1521 oldlen, NULL_TREE);
1524 return;
1527 if (olddsi != NULL)
1529 tree adj = NULL_TREE;
1530 if (oldlen == NULL_TREE)
1532 else if (integer_zerop (oldlen))
1533 adj = srclen;
1534 else if (TREE_CODE (oldlen) == INTEGER_CST
1535 || TREE_CODE (srclen) == INTEGER_CST)
1536 adj = fold_build2_loc (loc, MINUS_EXPR,
1537 TREE_TYPE (srclen), srclen,
1538 fold_convert_loc (loc, TREE_TYPE (srclen),
1539 oldlen));
1540 if (adj != NULL_TREE)
1541 adjust_related_strinfos (loc, dsi, adj);
1542 else
1543 dsi->prev = 0;
1545 /* strcpy src may not overlap dst, so src doesn't need to be
1546 invalidated either. */
1547 if (si != NULL)
1548 si->dont_invalidate = true;
1550 fn = NULL_TREE;
1551 zsi = NULL;
1552 switch (bcode)
1554 case BUILT_IN_STRCPY:
1555 case BUILT_IN_STRCPY_CHKP:
1556 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1557 if (lhs)
1558 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1559 break;
1560 case BUILT_IN_STRCPY_CHK:
1561 case BUILT_IN_STRCPY_CHK_CHKP:
1562 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1563 if (lhs)
1564 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1565 break;
1566 case BUILT_IN_STPCPY:
1567 case BUILT_IN_STPCPY_CHKP:
1568 /* This would need adjustment of the lhs (subtract one),
1569 or detection that the trailing '\0' doesn't need to be
1570 written, if it will be immediately overwritten.
1571 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1572 if (lhs)
1574 dsi->endptr = lhs;
1575 zsi = zero_length_string (lhs, dsi);
1577 break;
1578 case BUILT_IN_STPCPY_CHK:
1579 case BUILT_IN_STPCPY_CHK_CHKP:
1580 /* This would need adjustment of the lhs (subtract one),
1581 or detection that the trailing '\0' doesn't need to be
1582 written, if it will be immediately overwritten.
1583 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1584 if (lhs)
1586 dsi->endptr = lhs;
1587 zsi = zero_length_string (lhs, dsi);
1589 break;
1590 default:
1591 gcc_unreachable ();
1593 if (zsi != NULL)
1594 zsi->dont_invalidate = true;
1596 if (fn)
1598 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1599 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1601 else
1602 type = size_type_node;
1604 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1605 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1607 /* Set the no-warning bit on the transformed statement? */
1608 bool set_no_warning = false;
1610 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1611 if (si
1612 && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
1613 NULL_TREE, len))
1615 gimple_set_no_warning (stmt, true);
1616 set_no_warning = true;
1619 if (fn == NULL_TREE)
1620 return;
1622 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1623 GSI_SAME_STMT);
1624 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1626 fprintf (dump_file, "Optimizing: ");
1627 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1629 if (with_bounds)
1631 fn = chkp_maybe_create_clone (fn)->decl;
1632 if (gimple_call_num_args (stmt) == 4)
1633 success = update_gimple_call (gsi, fn, 5, dst,
1634 gimple_call_arg (stmt, 1),
1635 src,
1636 gimple_call_arg (stmt, 3),
1637 len);
1638 else
1639 success = update_gimple_call (gsi, fn, 6, dst,
1640 gimple_call_arg (stmt, 1),
1641 src,
1642 gimple_call_arg (stmt, 3),
1643 len,
1644 gimple_call_arg (stmt, 4));
1646 else
1647 if (gimple_call_num_args (stmt) == 2)
1648 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1649 else
1650 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1651 gimple_call_arg (stmt, 2));
1652 if (success)
1654 stmt = gsi_stmt (*gsi);
1655 gimple_call_set_with_bounds (stmt, with_bounds);
1656 update_stmt (stmt);
1657 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1659 fprintf (dump_file, "into: ");
1660 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1662 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1663 laststmt.stmt = stmt;
1664 laststmt.len = srclen;
1665 laststmt.stridx = dsi->idx;
1667 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1668 fprintf (dump_file, "not possible.\n");
1670 if (set_no_warning)
1671 gimple_set_no_warning (stmt, true);
1674 /* Check the size argument to the built-in forms of stpncpy and strncpy
1675 for out-of-bounds offsets or overlapping access, and to see if the
1676 size argument is derived from a call to strlen() on the source argument,
1677 and if so, issue an appropriate warning. */
1679 static void
1680 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1682 /* Same as stxncpy(). */
1683 handle_builtin_stxncpy (bcode, gsi);
1686 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1687 way. LEN can either be an integer expression, or a pointer (to char).
1688 When it is the latter (such as in recursive calls to self) is is
1689 assumed to be the argument in some call to strlen() whose relationship
1690 to SRC is being ascertained. */
1692 static bool
1693 is_strlen_related_p (tree src, tree len)
1695 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1696 && operand_equal_p (src, len, 0))
1697 return true;
1699 if (TREE_CODE (len) != SSA_NAME)
1700 return false;
1702 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1703 if (!def_stmt)
1704 return false;
1706 if (is_gimple_call (def_stmt))
1708 tree func = gimple_call_fndecl (def_stmt);
1709 if (!valid_builtin_call (def_stmt)
1710 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1711 return false;
1713 tree arg = gimple_call_arg (def_stmt, 0);
1714 return is_strlen_related_p (src, arg);
1717 if (!is_gimple_assign (def_stmt))
1718 return false;
1720 tree_code code = gimple_assign_rhs_code (def_stmt);
1721 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1722 tree rhstype = TREE_TYPE (rhs1);
1724 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1725 || (INTEGRAL_TYPE_P (rhstype)
1726 && (code == BIT_AND_EXPR
1727 || code == NOP_EXPR)))
1729 /* Pointer plus (an integer) and integer cast or truncation are
1730 considered among the (potentially) related expressions to strlen.
1731 Others are not. */
1732 return is_strlen_related_p (src, rhs1);
1735 return false;
1738 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1739 bound is a) equal to the size of the destination DST and if so, b)
1740 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1741 and b) does not, warn. Otherwise, do nothing. Return true if
1742 diagnostic has been issued.
1744 The purpose is to diagnose calls to strncpy and stpncpy that do
1745 not nul-terminate the copy while allowing for the idiom where
1746 such a call is immediately followed by setting the last element
1747 to nul, as in:
1748 char a[32];
1749 strncpy (a, s, sizeof a);
1750 a[sizeof a - 1] = '\0';
1753 static bool
1754 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1756 gimple *stmt = gsi_stmt (gsi);
1758 wide_int cntrange[2];
1760 if (TREE_CODE (cnt) == INTEGER_CST)
1761 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1762 else if (TREE_CODE (cnt) == SSA_NAME)
1764 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1765 if (rng == VR_RANGE)
1767 else if (rng == VR_ANTI_RANGE)
1769 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1771 if (wi::ltu_p (cntrange[1], maxobjsize))
1773 cntrange[0] = cntrange[1] + 1;
1774 cntrange[1] = maxobjsize;
1776 else
1778 cntrange[1] = cntrange[0] - 1;
1779 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1782 else
1783 return false;
1785 else
1786 return false;
1788 /* Negative value is the constant string length. If it's less than
1789 the lower bound there is no truncation. */
1790 int sidx = get_stridx (src);
1791 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1792 return false;
1794 tree dst = gimple_call_arg (stmt, 0);
1795 tree dstdecl = dst;
1796 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1797 dstdecl = TREE_OPERAND (dstdecl, 0);
1799 /* If the destination refers to a an array/pointer declared nonstring
1800 return early. */
1801 tree ref = NULL_TREE;
1802 if (get_attr_nonstring_decl (dstdecl, &ref))
1803 return false;
1805 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1806 avoid the truncation warning. */
1807 gsi_next (&gsi);
1808 gimple *next_stmt = gsi_stmt (gsi);
1810 if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt))
1812 tree lhs = gimple_assign_lhs (next_stmt);
1813 tree_code code = TREE_CODE (lhs);
1814 if (code == ARRAY_REF || code == MEM_REF)
1815 lhs = TREE_OPERAND (lhs, 0);
1817 tree func = gimple_call_fndecl (stmt);
1818 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1820 tree ret = gimple_call_lhs (stmt);
1821 if (ret && operand_equal_p (ret, lhs, 0))
1822 return false;
1825 /* Determine the base address and offset of the reference,
1826 ignoring the innermost array index. */
1827 if (TREE_CODE (ref) == ARRAY_REF)
1828 ref = TREE_OPERAND (ref, 0);
1830 HOST_WIDE_INT dstoff;
1831 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1833 HOST_WIDE_INT lhsoff;
1834 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1835 if (lhsbase
1836 && dstoff == lhsoff
1837 && operand_equal_p (dstbase, lhsbase, 0))
1838 return false;
1841 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1842 wide_int lenrange[2];
1843 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1845 lenrange[0] = (sisrc->nonzero_chars
1846 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1847 ? wi::to_wide (sisrc->nonzero_chars)
1848 : wi::zero (prec));
1849 lenrange[1] = lenrange[0];
1851 else if (sidx < 0)
1852 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1853 else
1855 tree range[2];
1856 get_range_strlen (src, range);
1857 if (range[0])
1859 lenrange[0] = wi::to_wide (range[0], prec);
1860 lenrange[1] = wi::to_wide (range[1], prec);
1862 else
1864 lenrange[0] = wi::shwi (0, prec);
1865 lenrange[1] = wi::shwi (-1, prec);
1869 location_t callloc = gimple_location (stmt);
1870 tree func = gimple_call_fndecl (stmt);
1872 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1874 /* If the longest source string is shorter than the lower bound
1875 of the specified count the copy is definitely nul-terminated. */
1876 if (wi::ltu_p (lenrange[1], cntrange[0]))
1877 return false;
1879 if (wi::neg_p (lenrange[1]))
1881 /* The length of one of the strings is unknown but at least
1882 one has non-zero length and that length is stored in
1883 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1884 warning below. */
1885 lenrange[1] = lenrange[0];
1886 lenrange[0] = wi::shwi (0, prec);
1889 if (wi::geu_p (lenrange[0], cntrange[1]))
1891 /* The shortest string is longer than the upper bound of
1892 the count so the truncation is certain. */
1893 if (cntrange[0] == cntrange[1])
1894 return warning_at (callloc, OPT_Wstringop_truncation,
1895 integer_onep (cnt)
1896 ? G_("%qD output truncated copying %E byte "
1897 "from a string of length %wu")
1898 : G_("%qD output truncated copying %E bytes "
1899 "from a string of length %wu"),
1900 func, cnt, lenrange[0].to_uhwi ());
1902 return warning_at (callloc, OPT_Wstringop_truncation,
1903 "%qD output truncated copying between %wu "
1904 "and %wu bytes from a string of length %wu",
1905 func, cntrange[0].to_uhwi (),
1906 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1908 else if (wi::geu_p (lenrange[1], cntrange[1]))
1910 /* The longest string is longer than the upper bound of
1911 the count so the truncation is possible. */
1912 if (cntrange[0] == cntrange[1])
1913 return warning_at (callloc, OPT_Wstringop_truncation,
1914 integer_onep (cnt)
1915 ? G_("%qD output may be truncated copying %E "
1916 "byte from a string of length %wu")
1917 : G_("%qD output may be truncated copying %E "
1918 "bytes from a string of length %wu"),
1919 func, cnt, lenrange[1].to_uhwi ());
1921 return warning_at (callloc, OPT_Wstringop_truncation,
1922 "%qD output may be truncated copying between %wu "
1923 "and %wu bytes from a string of length %wu",
1924 func, cntrange[0].to_uhwi (),
1925 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1928 if (cntrange[0] != cntrange[1]
1929 && wi::leu_p (cntrange[0], lenrange[0])
1930 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1932 /* If the source (including the terminating nul) is longer than
1933 the lower bound of the specified count but shorter than the
1934 upper bound the copy may (but need not) be truncated. */
1935 return warning_at (callloc, OPT_Wstringop_truncation,
1936 "%qD output may be truncated copying between %wu "
1937 "and %wu bytes from a string of length %wu",
1938 func, cntrange[0].to_uhwi (),
1939 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1943 if (tree dstsize = compute_objsize (dst, 1))
1945 /* The source length is uknown. Try to determine the destination
1946 size and see if it matches the specified bound. If not, bail.
1947 Otherwise go on to see if it should be diagnosed for possible
1948 truncation. */
1949 if (!dstsize)
1950 return false;
1952 if (wi::to_wide (dstsize) != cntrange[1])
1953 return false;
1955 if (cntrange[0] == cntrange[1])
1956 return warning_at (callloc, OPT_Wstringop_truncation,
1957 "%qD specified bound %E equals destination size",
1958 func, cnt);
1961 return false;
1964 /* Check the arguments to the built-in forms of stpncpy and strncpy for
1965 out-of-bounds offsets or overlapping access, and to see if the size
1966 is derived from calling strlen() on the source argument, and if so,
1967 issue the appropriate warning. */
1969 static void
1970 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
1972 if (!strlen_to_stridx)
1973 return;
1975 gimple *stmt = gsi_stmt (*gsi);
1977 bool with_bounds = gimple_call_with_bounds_p (stmt);
1979 tree dst = gimple_call_arg (stmt, with_bounds ? 1 : 0);
1980 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1981 tree len = gimple_call_arg (stmt, with_bounds ? 3 : 2);
1982 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
1984 int didx = get_stridx (dst);
1985 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
1987 /* Compute the size of the destination string including the NUL. */
1988 if (sidst->nonzero_chars)
1990 tree type = TREE_TYPE (sidst->nonzero_chars);
1991 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
1992 build_int_cst (type, 1));
1994 dst = sidst->ptr;
1997 int sidx = get_stridx (src);
1998 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
1999 if (sisrc)
2001 /* strncat() and strncpy() can modify the source string by writing
2002 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2003 clear. */
2005 /* Compute the size of the source string including the NUL. */
2006 if (sisrc->nonzero_chars)
2008 tree type = TREE_TYPE (sisrc->nonzero_chars);
2009 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2010 build_int_cst (type, 1));
2013 src = sisrc->ptr;
2015 else
2016 srcsize = NULL_TREE;
2018 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
2019 dstsize, srcsize))
2021 gimple_set_no_warning (stmt, true);
2022 return;
2025 /* If the length argument was computed from strlen(S) for some string
2026 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2027 the location of the strlen() call (PSS->SECOND). */
2028 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2029 if (!pss || pss->first <= 0)
2031 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2032 gimple_set_no_warning (stmt, true);
2034 return;
2037 /* Retrieve the strinfo data for the string S that LEN was computed
2038 from as some function F of strlen (S) (i.e., LEN need not be equal
2039 to strlen(S)). */
2040 strinfo *silen = get_strinfo (pss->first);
2042 location_t callloc = gimple_location (stmt);
2044 tree func = gimple_call_fndecl (stmt);
2046 bool warned = false;
2048 /* When -Wstringop-truncation is set, try to determine truncation
2049 before diagnosing possible overflow. Truncation is implied by
2050 the LEN argument being equal to strlen(SRC), regardless of
2051 whether its value is known. Otherwise, issue the more generic
2052 -Wstringop-overflow which triggers for LEN arguments that in
2053 any meaningful way depend on strlen(SRC). */
2054 if (sisrc == silen
2055 && is_strlen_related_p (src, len)
2056 && warning_at (callloc, OPT_Wstringop_truncation,
2057 "%qD output truncated before terminating nul "
2058 "copying as many bytes from a string as its length",
2059 func))
2060 warned = true;
2061 else if (silen && is_strlen_related_p (src, silen->ptr))
2062 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2063 "%qD specified bound depends on the length "
2064 "of the source argument", func);
2065 if (warned)
2067 location_t strlenloc = pss->second;
2068 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2069 inform (strlenloc, "length computed here");
2073 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2074 If strlen of the second argument is known and length of the third argument
2075 is that plus one, strlen of the first argument is the same after this
2076 call. */
2078 static void
2079 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2081 int idx, didx;
2082 tree src, dst, len, lhs, oldlen, newlen;
2083 gimple *stmt = gsi_stmt (*gsi);
2084 strinfo *si, *dsi, *olddsi;
2085 bool with_bounds = gimple_call_with_bounds_p (stmt);
2087 len = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2088 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2089 dst = gimple_call_arg (stmt, 0);
2090 idx = get_stridx (src);
2091 if (idx == 0)
2092 return;
2094 didx = get_stridx (dst);
2095 olddsi = NULL;
2096 if (didx > 0)
2097 olddsi = get_strinfo (didx);
2098 else if (didx < 0)
2099 return;
2101 if (olddsi != NULL
2102 && tree_fits_uhwi_p (len)
2103 && !integer_zerop (len))
2104 adjust_last_stmt (olddsi, stmt, false);
2106 bool full_string_p;
2107 if (idx > 0)
2109 gimple *def_stmt;
2111 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2112 is known. */
2113 si = get_strinfo (idx);
2114 if (si == NULL || si->nonzero_chars == NULL_TREE)
2115 return;
2116 if (TREE_CODE (len) == INTEGER_CST
2117 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2119 if (tree_int_cst_le (len, si->nonzero_chars))
2121 /* Copying LEN nonzero characters, where LEN is constant. */
2122 newlen = len;
2123 full_string_p = false;
2125 else
2127 /* Copying the whole of the analyzed part of SI. */
2128 newlen = si->nonzero_chars;
2129 full_string_p = si->full_string_p;
2132 else
2134 if (!si->full_string_p)
2135 return;
2136 if (TREE_CODE (len) != SSA_NAME)
2137 return;
2138 def_stmt = SSA_NAME_DEF_STMT (len);
2139 if (!is_gimple_assign (def_stmt)
2140 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2141 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2142 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2143 return;
2144 /* Copying variable-length string SI (and no more). */
2145 newlen = si->nonzero_chars;
2146 full_string_p = true;
2149 else
2151 si = NULL;
2152 /* Handle memcpy (x, "abcd", 5) or
2153 memcpy (x, "abc\0uvw", 7). */
2154 if (!tree_fits_uhwi_p (len))
2155 return;
2157 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2158 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2159 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2160 full_string_p = clen > nonzero_chars;
2163 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2164 adjust_last_stmt (olddsi, stmt, false);
2166 if (didx == 0)
2168 didx = new_stridx (dst);
2169 if (didx == 0)
2170 return;
2172 oldlen = NULL_TREE;
2173 if (olddsi != NULL)
2175 dsi = unshare_strinfo (olddsi);
2176 oldlen = olddsi->nonzero_chars;
2177 dsi->nonzero_chars = newlen;
2178 dsi->full_string_p = full_string_p;
2179 /* Break the chain, so adjust_related_strinfo on later pointers in
2180 the chain won't adjust this one anymore. */
2181 dsi->next = 0;
2182 dsi->stmt = NULL;
2183 dsi->endptr = NULL_TREE;
2185 else
2187 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2188 set_strinfo (didx, dsi);
2189 find_equal_ptrs (dst, didx);
2191 dsi->writable = true;
2192 dsi->dont_invalidate = true;
2193 if (olddsi != NULL)
2195 tree adj = NULL_TREE;
2196 location_t loc = gimple_location (stmt);
2197 if (oldlen == NULL_TREE)
2199 else if (integer_zerop (oldlen))
2200 adj = newlen;
2201 else if (TREE_CODE (oldlen) == INTEGER_CST
2202 || TREE_CODE (newlen) == INTEGER_CST)
2203 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2204 fold_convert_loc (loc, TREE_TYPE (newlen),
2205 oldlen));
2206 if (adj != NULL_TREE)
2207 adjust_related_strinfos (loc, dsi, adj);
2208 else
2209 dsi->prev = 0;
2211 /* memcpy src may not overlap dst, so src doesn't need to be
2212 invalidated either. */
2213 if (si != NULL)
2214 si->dont_invalidate = true;
2216 if (full_string_p)
2218 lhs = gimple_call_lhs (stmt);
2219 switch (bcode)
2221 case BUILT_IN_MEMCPY:
2222 case BUILT_IN_MEMCPY_CHK:
2223 case BUILT_IN_MEMCPY_CHKP:
2224 case BUILT_IN_MEMCPY_CHK_CHKP:
2225 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2226 laststmt.stmt = stmt;
2227 laststmt.len = dsi->nonzero_chars;
2228 laststmt.stridx = dsi->idx;
2229 if (lhs)
2230 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2231 break;
2232 case BUILT_IN_MEMPCPY:
2233 case BUILT_IN_MEMPCPY_CHK:
2234 case BUILT_IN_MEMPCPY_CHKP:
2235 case BUILT_IN_MEMPCPY_CHK_CHKP:
2236 break;
2237 default:
2238 gcc_unreachable ();
2243 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2244 If strlen of the second argument is known, strlen of the first argument
2245 is increased by the length of the second argument. Furthermore, attempt
2246 to convert it to memcpy/strcpy if the length of the first argument
2247 is known. */
2249 static void
2250 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2252 int idx, didx;
2253 tree srclen, args, type, fn, objsz, endptr;
2254 bool success;
2255 gimple *stmt = gsi_stmt (*gsi);
2256 strinfo *si, *dsi;
2257 location_t loc = gimple_location (stmt);
2258 bool with_bounds = gimple_call_with_bounds_p (stmt);
2260 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2261 tree dst = gimple_call_arg (stmt, 0);
2263 /* Bail if the source is the same as destination. It will be diagnosed
2264 elsewhere. */
2265 if (operand_equal_p (src, dst, 0))
2266 return;
2268 tree lhs = gimple_call_lhs (stmt);
2270 didx = get_stridx (dst);
2271 if (didx < 0)
2272 return;
2274 dsi = NULL;
2275 if (didx > 0)
2276 dsi = get_strinfo (didx);
2278 srclen = NULL_TREE;
2279 si = NULL;
2280 idx = get_stridx (src);
2281 if (idx < 0)
2282 srclen = build_int_cst (size_type_node, ~idx);
2283 else if (idx > 0)
2285 si = get_strinfo (idx);
2286 if (si != NULL)
2287 srclen = get_string_length (si);
2290 /* Set the no-warning bit on the transformed statement? */
2291 bool set_no_warning = false;
2293 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2296 /* The concatenation always involves copying at least one byte
2297 (the terminating nul), even if the source string is empty.
2298 If the source is unknown assume it's one character long and
2299 used that as both sizes. */
2300 tree slen = srclen;
2301 if (slen)
2303 tree type = TREE_TYPE (slen);
2304 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2307 tree sptr = si && si->ptr ? si->ptr : src;
2309 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2310 NULL_TREE, slen))
2312 gimple_set_no_warning (stmt, true);
2313 set_no_warning = true;
2317 /* strcat (p, q) can be transformed into
2318 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2319 with length endptr - p if we need to compute the length
2320 later on. Don't do this transformation if we don't need
2321 it. */
2322 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2324 if (didx == 0)
2326 didx = new_stridx (dst);
2327 if (didx == 0)
2328 return;
2330 if (dsi == NULL)
2332 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2333 set_strinfo (didx, dsi);
2334 find_equal_ptrs (dst, didx);
2336 else
2338 dsi = unshare_strinfo (dsi);
2339 dsi->nonzero_chars = NULL_TREE;
2340 dsi->full_string_p = false;
2341 dsi->next = 0;
2342 dsi->endptr = NULL_TREE;
2344 dsi->writable = true;
2345 dsi->stmt = stmt;
2346 dsi->dont_invalidate = true;
2348 return;
2351 tree dstlen = dsi->nonzero_chars;
2352 endptr = dsi->endptr;
2354 dsi = unshare_strinfo (dsi);
2355 dsi->endptr = NULL_TREE;
2356 dsi->stmt = NULL;
2357 dsi->writable = true;
2359 if (srclen != NULL_TREE)
2361 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2362 TREE_TYPE (dsi->nonzero_chars),
2363 dsi->nonzero_chars, srclen);
2364 gcc_assert (dsi->full_string_p);
2365 adjust_related_strinfos (loc, dsi, srclen);
2366 dsi->dont_invalidate = true;
2368 else
2370 dsi->nonzero_chars = NULL;
2371 dsi->full_string_p = false;
2372 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2373 dsi->dont_invalidate = true;
2376 if (si != NULL)
2377 /* strcat src may not overlap dst, so src doesn't need to be
2378 invalidated either. */
2379 si->dont_invalidate = true;
2381 /* For now. Could remove the lhs from the call and add
2382 lhs = dst; afterwards. */
2383 if (lhs)
2384 return;
2386 fn = NULL_TREE;
2387 objsz = NULL_TREE;
2388 switch (bcode)
2390 case BUILT_IN_STRCAT:
2391 case BUILT_IN_STRCAT_CHKP:
2392 if (srclen != NULL_TREE)
2393 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2394 else
2395 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2396 break;
2397 case BUILT_IN_STRCAT_CHK:
2398 case BUILT_IN_STRCAT_CHK_CHKP:
2399 if (srclen != NULL_TREE)
2400 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2401 else
2402 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2403 objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2404 break;
2405 default:
2406 gcc_unreachable ();
2409 if (fn == NULL_TREE)
2410 return;
2412 if (dsi && dstlen)
2414 tree type = TREE_TYPE (dstlen);
2416 /* Compute the size of the source sequence, including the nul. */
2417 tree srcsize = srclen ? srclen : size_zero_node;
2418 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2420 tree sptr = si && si->ptr ? si->ptr : src;
2422 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2423 dstlen, srcsize))
2425 gimple_set_no_warning (stmt, true);
2426 set_no_warning = true;
2430 tree len = NULL_TREE;
2431 if (srclen != NULL_TREE)
2433 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2434 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2436 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2437 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2438 build_int_cst (type, 1));
2439 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2440 GSI_SAME_STMT);
2442 if (endptr)
2443 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2444 else
2445 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2446 TREE_TYPE (dst), unshare_expr (dst),
2447 fold_convert_loc (loc, sizetype,
2448 unshare_expr (dstlen)));
2449 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2450 GSI_SAME_STMT);
2451 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2453 fprintf (dump_file, "Optimizing: ");
2454 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2456 if (with_bounds)
2458 fn = chkp_maybe_create_clone (fn)->decl;
2459 if (srclen != NULL_TREE)
2460 success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE),
2461 dst,
2462 gimple_call_arg (stmt, 1),
2463 src,
2464 gimple_call_arg (stmt, 3),
2465 len, objsz);
2466 else
2467 success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE),
2468 dst,
2469 gimple_call_arg (stmt, 1),
2470 src,
2471 gimple_call_arg (stmt, 3),
2472 objsz);
2474 else
2475 if (srclen != NULL_TREE)
2476 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2477 dst, src, len, objsz);
2478 else
2479 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2480 dst, src, objsz);
2481 if (success)
2483 stmt = gsi_stmt (*gsi);
2484 gimple_call_set_with_bounds (stmt, with_bounds);
2485 update_stmt (stmt);
2486 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2488 fprintf (dump_file, "into: ");
2489 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2491 /* If srclen == NULL, note that current string length can be
2492 computed by transforming this strcpy into stpcpy. */
2493 if (srclen == NULL_TREE && dsi->dont_invalidate)
2494 dsi->stmt = stmt;
2495 adjust_last_stmt (dsi, stmt, true);
2496 if (srclen != NULL_TREE)
2498 laststmt.stmt = stmt;
2499 laststmt.len = srclen;
2500 laststmt.stridx = dsi->idx;
2503 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2504 fprintf (dump_file, "not possible.\n");
2506 if (set_no_warning)
2507 gimple_set_no_warning (stmt, true);
2510 /* Handle a call to malloc or calloc. */
2512 static void
2513 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2515 gimple *stmt = gsi_stmt (*gsi);
2516 tree lhs = gimple_call_lhs (stmt);
2517 if (lhs == NULL_TREE)
2518 return;
2520 gcc_assert (get_stridx (lhs) == 0);
2521 int idx = new_stridx (lhs);
2522 tree length = NULL_TREE;
2523 if (bcode == BUILT_IN_CALLOC)
2524 length = build_int_cst (size_type_node, 0);
2525 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2526 if (bcode == BUILT_IN_CALLOC)
2527 si->endptr = lhs;
2528 set_strinfo (idx, si);
2529 si->writable = true;
2530 si->stmt = stmt;
2531 si->dont_invalidate = true;
2534 /* Handle a call to memset.
2535 After a call to calloc, memset(,0,) is unnecessary.
2536 memset(malloc(n),0,n) is calloc(n,1). */
2538 static bool
2539 handle_builtin_memset (gimple_stmt_iterator *gsi)
2541 gimple *stmt2 = gsi_stmt (*gsi);
2542 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2543 return true;
2544 tree ptr = gimple_call_arg (stmt2, 0);
2545 int idx1 = get_stridx (ptr);
2546 if (idx1 <= 0)
2547 return true;
2548 strinfo *si1 = get_strinfo (idx1);
2549 if (!si1)
2550 return true;
2551 gimple *stmt1 = si1->stmt;
2552 if (!stmt1 || !is_gimple_call (stmt1))
2553 return true;
2554 tree callee1 = gimple_call_fndecl (stmt1);
2555 if (!valid_builtin_call (stmt1))
2556 return true;
2557 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2558 tree size = gimple_call_arg (stmt2, 2);
2559 if (code1 == BUILT_IN_CALLOC)
2560 /* Not touching stmt1 */ ;
2561 else if (code1 == BUILT_IN_MALLOC
2562 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2564 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2565 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2566 size, build_one_cst (size_type_node));
2567 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2568 si1->full_string_p = true;
2569 si1->stmt = gsi_stmt (gsi1);
2571 else
2572 return true;
2573 tree lhs = gimple_call_lhs (stmt2);
2574 unlink_stmt_vdef (stmt2);
2575 if (lhs)
2577 gimple *assign = gimple_build_assign (lhs, ptr);
2578 gsi_replace (gsi, assign, false);
2580 else
2582 gsi_remove (gsi, true);
2583 release_defs (stmt2);
2586 return false;
2589 /* Handle a call to memcmp. We try to handle small comparisons by
2590 converting them to load and compare, and replacing the call to memcmp
2591 with a __builtin_memcmp_eq call where possible. */
2593 static bool
2594 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2596 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2597 tree res = gimple_call_lhs (stmt2);
2598 tree arg1 = gimple_call_arg (stmt2, 0);
2599 tree arg2 = gimple_call_arg (stmt2, 1);
2600 tree len = gimple_call_arg (stmt2, 2);
2601 unsigned HOST_WIDE_INT leni;
2602 use_operand_p use_p;
2603 imm_use_iterator iter;
2605 if (!res)
2606 return true;
2608 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2610 gimple *ustmt = USE_STMT (use_p);
2612 if (is_gimple_debug (ustmt))
2613 continue;
2614 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2616 gassign *asgn = as_a <gassign *> (ustmt);
2617 tree_code code = gimple_assign_rhs_code (asgn);
2618 if ((code != EQ_EXPR && code != NE_EXPR)
2619 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2620 return true;
2622 else if (gimple_code (ustmt) == GIMPLE_COND)
2624 tree_code code = gimple_cond_code (ustmt);
2625 if ((code != EQ_EXPR && code != NE_EXPR)
2626 || !integer_zerop (gimple_cond_rhs (ustmt)))
2627 return true;
2629 else
2630 return true;
2633 if (tree_fits_uhwi_p (len)
2634 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2635 && pow2p_hwi (leni))
2637 leni *= CHAR_TYPE_SIZE;
2638 unsigned align1 = get_pointer_alignment (arg1);
2639 unsigned align2 = get_pointer_alignment (arg2);
2640 unsigned align = MIN (align1, align2);
2641 scalar_int_mode mode;
2642 if (int_mode_for_size (leni, 1).exists (&mode)
2643 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2645 location_t loc = gimple_location (stmt2);
2646 tree type, off;
2647 type = build_nonstandard_integer_type (leni, 1);
2648 gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type)) == leni);
2649 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2650 ptr_mode, true);
2651 off = build_int_cst (ptrtype, 0);
2652 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2653 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2654 tree tem1 = fold_const_aggregate_ref (arg1);
2655 if (tem1)
2656 arg1 = tem1;
2657 tree tem2 = fold_const_aggregate_ref (arg2);
2658 if (tem2)
2659 arg2 = tem2;
2660 res = fold_convert_loc (loc, TREE_TYPE (res),
2661 fold_build2_loc (loc, NE_EXPR,
2662 boolean_type_node,
2663 arg1, arg2));
2664 gimplify_and_update_call_from_tree (gsi, res);
2665 return false;
2669 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2670 return false;
2673 /* Handle a POINTER_PLUS_EXPR statement.
2674 For p = "abcd" + 2; compute associated length, or if
2675 p = q + off is pointing to a '\0' character of a string, call
2676 zero_length_string on it. */
2678 static void
2679 handle_pointer_plus (gimple_stmt_iterator *gsi)
2681 gimple *stmt = gsi_stmt (*gsi);
2682 tree lhs = gimple_assign_lhs (stmt), off;
2683 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2684 strinfo *si, *zsi;
2686 if (idx == 0)
2687 return;
2689 if (idx < 0)
2691 tree off = gimple_assign_rhs2 (stmt);
2692 if (tree_fits_uhwi_p (off)
2693 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2694 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2695 = ~(~idx - (int) tree_to_uhwi (off));
2696 return;
2699 si = get_strinfo (idx);
2700 if (si == NULL || si->nonzero_chars == NULL_TREE)
2701 return;
2703 off = gimple_assign_rhs2 (stmt);
2704 zsi = NULL;
2705 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2706 zsi = zero_length_string (lhs, si);
2707 else if (TREE_CODE (off) == SSA_NAME)
2709 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2710 if (gimple_assign_single_p (def_stmt)
2711 && si->full_string_p
2712 && operand_equal_p (si->nonzero_chars,
2713 gimple_assign_rhs1 (def_stmt), 0))
2714 zsi = zero_length_string (lhs, si);
2716 if (zsi != NULL
2717 && si->endptr != NULL_TREE
2718 && si->endptr != lhs
2719 && TREE_CODE (si->endptr) == SSA_NAME)
2721 enum tree_code rhs_code
2722 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2723 ? SSA_NAME : NOP_EXPR;
2724 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2725 gcc_assert (gsi_stmt (*gsi) == stmt);
2726 update_stmt (stmt);
2730 /* Handle a single character store. */
2732 static bool
2733 handle_char_store (gimple_stmt_iterator *gsi)
2735 int idx = -1;
2736 strinfo *si = NULL;
2737 gimple *stmt = gsi_stmt (*gsi);
2738 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
2739 tree rhs = gimple_assign_rhs1 (stmt);
2740 unsigned HOST_WIDE_INT offset = 0;
2742 if (TREE_CODE (lhs) == MEM_REF
2743 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
2745 tree mem_offset = TREE_OPERAND (lhs, 1);
2746 if (tree_fits_uhwi_p (mem_offset))
2748 /* Get the strinfo for the base, and use it if it starts with at
2749 least OFFSET nonzero characters. This is trivially true if
2750 OFFSET is zero. */
2751 offset = tree_to_uhwi (mem_offset);
2752 idx = get_stridx (TREE_OPERAND (lhs, 0));
2753 if (idx > 0)
2754 si = get_strinfo (idx);
2755 if (offset == 0)
2756 ssaname = TREE_OPERAND (lhs, 0);
2757 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
2758 return true;
2761 else
2763 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
2764 if (idx > 0)
2765 si = get_strinfo (idx);
2768 bool storing_zero_p = initializer_zerop (rhs);
2769 bool storing_nonzero_p = (!storing_zero_p
2770 && TREE_CODE (rhs) == INTEGER_CST
2771 && integer_nonzerop (rhs));
2773 if (si != NULL)
2775 int cmp = compare_nonzero_chars (si, offset);
2776 gcc_assert (offset == 0 || cmp >= 0);
2777 if (storing_zero_p && cmp == 0 && si->full_string_p)
2779 /* When overwriting a '\0' with a '\0', the store can be removed
2780 if we know it has been stored in the current function. */
2781 if (!stmt_could_throw_p (stmt) && si->writable)
2783 unlink_stmt_vdef (stmt);
2784 release_defs (stmt);
2785 gsi_remove (gsi, true);
2786 return false;
2788 else
2790 si->writable = true;
2791 gsi_next (gsi);
2792 return false;
2795 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2796 and if we aren't storing '\0', we know that the length of the
2797 string and any other zero terminated string in memory remains
2798 the same. In that case we move to the next gimple statement and
2799 return to signal the caller that it shouldn't invalidate anything.
2801 This is benefical for cases like:
2803 char p[20];
2804 void foo (char *q)
2806 strcpy (p, "foobar");
2807 size_t len = strlen (p); // This can be optimized into 6
2808 size_t len2 = strlen (q); // This has to be computed
2809 p[0] = 'X';
2810 size_t len3 = strlen (p); // This can be optimized into 6
2811 size_t len4 = strlen (q); // This can be optimized into len2
2812 bar (len, len2, len3, len4);
2815 else if (storing_nonzero_p && cmp > 0)
2817 gsi_next (gsi);
2818 return false;
2820 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
2822 /* When storing_nonzero_p, we know that the string now starts
2823 with OFFSET + 1 nonzero characters, but don't know whether
2824 there's a following nul terminator.
2826 When storing_zero_p, we know that the string is now OFFSET
2827 characters long.
2829 Otherwise, we're storing an unknown value at offset OFFSET,
2830 so need to clip the nonzero_chars to OFFSET. */
2831 location_t loc = gimple_location (stmt);
2832 tree oldlen = si->nonzero_chars;
2833 if (cmp == 0 && si->full_string_p)
2834 /* We're overwriting the nul terminator with a nonzero or
2835 unknown character. If the previous stmt was a memcpy,
2836 its length may be decreased. */
2837 adjust_last_stmt (si, stmt, false);
2838 si = unshare_strinfo (si);
2839 if (storing_nonzero_p)
2840 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
2841 else
2842 si->nonzero_chars = build_int_cst (size_type_node, offset);
2843 si->full_string_p = storing_zero_p;
2844 if (storing_zero_p
2845 && ssaname
2846 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2847 si->endptr = ssaname;
2848 else
2849 si->endptr = NULL;
2850 si->next = 0;
2851 si->stmt = NULL;
2852 si->writable = true;
2853 si->dont_invalidate = true;
2854 if (oldlen)
2856 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
2857 si->nonzero_chars, oldlen);
2858 adjust_related_strinfos (loc, si, adj);
2860 else
2861 si->prev = 0;
2864 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
2866 if (ssaname)
2867 idx = new_stridx (ssaname);
2868 else
2869 idx = new_addr_stridx (lhs);
2870 if (idx != 0)
2872 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
2873 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
2874 si = new_strinfo (ptr, idx, len, storing_zero_p);
2875 set_strinfo (idx, si);
2876 if (storing_zero_p
2877 && ssaname
2878 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2879 si->endptr = ssaname;
2880 si->dont_invalidate = true;
2881 si->writable = true;
2884 else if (idx == 0
2885 && TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST
2886 && ssaname == NULL_TREE
2887 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
2889 size_t l = strlen (TREE_STRING_POINTER (gimple_assign_rhs1 (stmt)));
2890 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
2891 if (a > 0 && (unsigned HOST_WIDE_INT) a > l)
2893 int idx = new_addr_stridx (lhs);
2894 if (idx != 0)
2896 si = new_strinfo (build_fold_addr_expr (lhs), idx,
2897 build_int_cst (size_type_node, l), true);
2898 set_strinfo (idx, si);
2899 si->dont_invalidate = true;
2904 if (si != NULL && offset == 0 && storing_zero_p)
2906 /* Allow adjust_last_stmt to remove it if the stored '\0'
2907 is immediately overwritten. */
2908 laststmt.stmt = stmt;
2909 laststmt.len = build_int_cst (size_type_node, 1);
2910 laststmt.stridx = si->idx;
2912 return true;
2915 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
2917 static void
2918 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
2920 if (TREE_CODE (rhs1) != SSA_NAME
2921 || TREE_CODE (rhs2) != SSA_NAME)
2922 return;
2924 gimple *call_stmt = NULL;
2925 for (int pass = 0; pass < 2; pass++)
2927 gimple *g = SSA_NAME_DEF_STMT (rhs1);
2928 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
2929 && has_single_use (rhs1)
2930 && gimple_call_arg (g, 0) == rhs2)
2932 call_stmt = g;
2933 break;
2935 std::swap (rhs1, rhs2);
2938 if (call_stmt)
2940 tree arg0 = gimple_call_arg (call_stmt, 0);
2942 if (arg0 == rhs2)
2944 tree arg1 = gimple_call_arg (call_stmt, 1);
2945 tree arg1_len = NULL_TREE;
2946 int idx = get_stridx (arg1);
2948 if (idx)
2950 if (idx < 0)
2951 arg1_len = build_int_cst (size_type_node, ~idx);
2952 else
2954 strinfo *si = get_strinfo (idx);
2955 if (si)
2956 arg1_len = get_string_length (si);
2960 if (arg1_len != NULL_TREE)
2962 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
2963 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
2964 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
2965 arg0, arg1, arg1_len);
2966 tree strncmp_lhs = make_ssa_name (integer_type_node);
2967 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
2968 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
2969 gsi_remove (&gsi, true);
2970 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
2971 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
2973 if (is_gimple_assign (stmt))
2975 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
2977 tree cond = gimple_assign_rhs1 (stmt);
2978 TREE_OPERAND (cond, 0) = strncmp_lhs;
2979 TREE_OPERAND (cond, 1) = zero;
2981 else
2983 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
2984 gimple_assign_set_rhs2 (stmt, zero);
2987 else
2989 gcond *cond = as_a<gcond *> (stmt);
2990 gimple_cond_set_lhs (cond, strncmp_lhs);
2991 gimple_cond_set_rhs (cond, zero);
2993 update_stmt (stmt);
2999 /* Attempt to check for validity of the performed access a single statement
3000 at *GSI using string length knowledge, and to optimize it. */
3002 static bool
3003 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi)
3005 gimple *stmt = gsi_stmt (*gsi);
3007 if (is_gimple_call (stmt))
3009 tree callee = gimple_call_fndecl (stmt);
3010 if (valid_builtin_call (stmt))
3011 switch (DECL_FUNCTION_CODE (callee))
3013 case BUILT_IN_STRLEN:
3014 case BUILT_IN_STRLEN_CHKP:
3015 handle_builtin_strlen (gsi);
3016 break;
3017 case BUILT_IN_STRCHR:
3018 case BUILT_IN_STRCHR_CHKP:
3019 handle_builtin_strchr (gsi);
3020 break;
3021 case BUILT_IN_STRCPY:
3022 case BUILT_IN_STRCPY_CHK:
3023 case BUILT_IN_STPCPY:
3024 case BUILT_IN_STPCPY_CHK:
3025 case BUILT_IN_STRCPY_CHKP:
3026 case BUILT_IN_STRCPY_CHK_CHKP:
3027 case BUILT_IN_STPCPY_CHKP:
3028 case BUILT_IN_STPCPY_CHK_CHKP:
3029 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3030 break;
3032 case BUILT_IN_STRNCAT:
3033 case BUILT_IN_STRNCAT_CHK:
3034 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3035 break;
3037 case BUILT_IN_STPNCPY:
3038 case BUILT_IN_STPNCPY_CHK:
3039 case BUILT_IN_STRNCPY:
3040 case BUILT_IN_STRNCPY_CHK:
3041 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3042 break;
3044 case BUILT_IN_MEMCPY:
3045 case BUILT_IN_MEMCPY_CHK:
3046 case BUILT_IN_MEMPCPY:
3047 case BUILT_IN_MEMPCPY_CHK:
3048 case BUILT_IN_MEMCPY_CHKP:
3049 case BUILT_IN_MEMCPY_CHK_CHKP:
3050 case BUILT_IN_MEMPCPY_CHKP:
3051 case BUILT_IN_MEMPCPY_CHK_CHKP:
3052 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3053 break;
3054 case BUILT_IN_STRCAT:
3055 case BUILT_IN_STRCAT_CHK:
3056 case BUILT_IN_STRCAT_CHKP:
3057 case BUILT_IN_STRCAT_CHK_CHKP:
3058 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3059 break;
3060 case BUILT_IN_MALLOC:
3061 case BUILT_IN_CALLOC:
3062 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3063 break;
3064 case BUILT_IN_MEMSET:
3065 if (!handle_builtin_memset (gsi))
3066 return false;
3067 break;
3068 case BUILT_IN_MEMCMP:
3069 if (!handle_builtin_memcmp (gsi))
3070 return false;
3071 break;
3072 default:
3073 break;
3076 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3078 tree lhs = gimple_assign_lhs (stmt);
3080 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3082 if (gimple_assign_single_p (stmt)
3083 || (gimple_assign_cast_p (stmt)
3084 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3086 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3087 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3089 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3090 handle_pointer_plus (gsi);
3092 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3094 enum tree_code code = gimple_assign_rhs_code (stmt);
3095 if (code == COND_EXPR)
3097 tree cond = gimple_assign_rhs1 (stmt);
3098 enum tree_code cond_code = TREE_CODE (cond);
3100 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3101 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3102 TREE_OPERAND (cond, 1), stmt);
3104 else if (code == EQ_EXPR || code == NE_EXPR)
3105 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3106 gimple_assign_rhs2 (stmt), stmt);
3108 if (strlen_to_stridx)
3110 tree rhs1 = gimple_assign_rhs1 (stmt);
3111 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3112 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3115 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3117 tree type = TREE_TYPE (lhs);
3118 if (TREE_CODE (type) == ARRAY_TYPE)
3119 type = TREE_TYPE (type);
3120 if (TREE_CODE (type) == INTEGER_TYPE
3121 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3122 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3124 if (! handle_char_store (gsi))
3125 return false;
3129 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3131 enum tree_code code = gimple_cond_code (cond);
3132 if (code == EQ_EXPR || code == NE_EXPR)
3133 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3134 gimple_cond_rhs (stmt), stmt);
3137 if (gimple_vdef (stmt))
3138 maybe_invalidate (stmt);
3139 return true;
3142 /* Recursively call maybe_invalidate on stmts that might be executed
3143 in between dombb and current bb and that contain a vdef. Stop when
3144 *count stmts are inspected, or if the whole strinfo vector has
3145 been invalidated. */
3147 static void
3148 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3150 unsigned int i, n = gimple_phi_num_args (phi);
3152 for (i = 0; i < n; i++)
3154 tree vuse = gimple_phi_arg_def (phi, i);
3155 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3156 basic_block bb = gimple_bb (stmt);
3157 if (bb == NULL
3158 || bb == dombb
3159 || !bitmap_set_bit (visited, bb->index)
3160 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3161 continue;
3162 while (1)
3164 if (gimple_code (stmt) == GIMPLE_PHI)
3166 do_invalidate (dombb, stmt, visited, count);
3167 if (*count == 0)
3168 return;
3169 break;
3171 if (--*count == 0)
3172 return;
3173 if (!maybe_invalidate (stmt))
3175 *count = 0;
3176 return;
3178 vuse = gimple_vuse (stmt);
3179 stmt = SSA_NAME_DEF_STMT (vuse);
3180 if (gimple_bb (stmt) != bb)
3182 bb = gimple_bb (stmt);
3183 if (bb == NULL
3184 || bb == dombb
3185 || !bitmap_set_bit (visited, bb->index)
3186 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3187 break;
3193 class strlen_dom_walker : public dom_walker
3195 public:
3196 strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
3198 virtual edge before_dom_children (basic_block);
3199 virtual void after_dom_children (basic_block);
3202 /* Callback for walk_dominator_tree. Attempt to optimize various
3203 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3205 edge
3206 strlen_dom_walker::before_dom_children (basic_block bb)
3208 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3210 if (dombb == NULL)
3211 stridx_to_strinfo = NULL;
3212 else
3214 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3215 if (stridx_to_strinfo)
3217 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3218 gsi_next (&gsi))
3220 gphi *phi = gsi.phi ();
3221 if (virtual_operand_p (gimple_phi_result (phi)))
3223 bitmap visited = BITMAP_ALLOC (NULL);
3224 int count_vdef = 100;
3225 do_invalidate (dombb, phi, visited, &count_vdef);
3226 BITMAP_FREE (visited);
3227 if (count_vdef == 0)
3229 /* If there were too many vdefs in between immediate
3230 dominator and current bb, invalidate everything.
3231 If stridx_to_strinfo has been unshared, we need
3232 to free it, otherwise just set it to NULL. */
3233 if (!strinfo_shared ())
3235 unsigned int i;
3236 strinfo *si;
3238 for (i = 1;
3239 vec_safe_iterate (stridx_to_strinfo, i, &si);
3240 ++i)
3242 free_strinfo (si);
3243 (*stridx_to_strinfo)[i] = NULL;
3246 else
3247 stridx_to_strinfo = NULL;
3249 break;
3255 /* If all PHI arguments have the same string index, the PHI result
3256 has it as well. */
3257 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3258 gsi_next (&gsi))
3260 gphi *phi = gsi.phi ();
3261 tree result = gimple_phi_result (phi);
3262 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3264 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3265 if (idx != 0)
3267 unsigned int i, n = gimple_phi_num_args (phi);
3268 for (i = 1; i < n; i++)
3269 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3270 break;
3271 if (i == n)
3272 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3277 /* Attempt to optimize individual statements. */
3278 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3279 if (strlen_check_and_optimize_stmt (&gsi))
3280 gsi_next (&gsi);
3282 bb->aux = stridx_to_strinfo;
3283 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3284 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3285 return NULL;
3288 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3289 owned by the current bb, clear bb->aux. */
3291 void
3292 strlen_dom_walker::after_dom_children (basic_block bb)
3294 if (bb->aux)
3296 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3297 if (vec_safe_length (stridx_to_strinfo)
3298 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3300 unsigned int i;
3301 strinfo *si;
3303 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3304 free_strinfo (si);
3305 vec_free (stridx_to_strinfo);
3307 bb->aux = NULL;
3311 /* Main entry point. */
3313 namespace {
3315 const pass_data pass_data_strlen =
3317 GIMPLE_PASS, /* type */
3318 "strlen", /* name */
3319 OPTGROUP_NONE, /* optinfo_flags */
3320 TV_TREE_STRLEN, /* tv_id */
3321 ( PROP_cfg | PROP_ssa ), /* properties_required */
3322 0, /* properties_provided */
3323 0, /* properties_destroyed */
3324 0, /* todo_flags_start */
3325 0, /* todo_flags_finish */
3328 class pass_strlen : public gimple_opt_pass
3330 public:
3331 pass_strlen (gcc::context *ctxt)
3332 : gimple_opt_pass (pass_data_strlen, ctxt)
3335 /* opt_pass methods: */
3336 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3337 virtual unsigned int execute (function *);
3339 }; // class pass_strlen
3341 unsigned int
3342 pass_strlen::execute (function *fun)
3344 gcc_assert (!strlen_to_stridx);
3345 if (warn_stringop_overflow || warn_stringop_truncation)
3346 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3348 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3349 max_stridx = 1;
3351 calculate_dominance_info (CDI_DOMINATORS);
3353 /* String length optimization is implemented as a walk of the dominator
3354 tree and a forward walk of statements within each block. */
3355 strlen_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
3357 ssa_ver_to_stridx.release ();
3358 strinfo_pool.release ();
3359 if (decl_to_stridxlist_htab)
3361 obstack_free (&stridx_obstack, NULL);
3362 delete decl_to_stridxlist_htab;
3363 decl_to_stridxlist_htab = NULL;
3365 laststmt.stmt = NULL;
3366 laststmt.len = NULL_TREE;
3367 laststmt.stridx = 0;
3369 if (strlen_to_stridx)
3371 strlen_to_stridx->empty ();
3372 delete strlen_to_stridx;
3373 strlen_to_stridx = NULL;
3376 return 0;
3379 } // anon namespace
3381 gimple_opt_pass *
3382 make_pass_strlen (gcc::context *ctxt)
3384 return new pass_strlen (ctxt);