* auto-profile.c (afdo_annotate_cfg): Use update_max_bb_count.
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob2efa18275fd915d14ba010ff7b1edc4927779631
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 "fold-const.h"
34 #include "stor-layout.h"
35 #include "gimple-fold.h"
36 #include "tree-eh.h"
37 #include "gimplify.h"
38 #include "gimple-iterator.h"
39 #include "gimplify-me.h"
40 #include "expr.h"
41 #include "tree-dfa.h"
42 #include "domwalk.h"
43 #include "tree-ssa-alias.h"
44 #include "tree-ssa-propagate.h"
45 #include "params.h"
46 #include "ipa-chkp.h"
47 #include "tree-hash-traits.h"
48 #include "builtins.h"
49 #include "target.h"
50 #include "diagnostic-core.h"
51 #include "diagnostic.h"
52 #include "intl.h"
53 #include "attribs.h"
55 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
56 is an index into strinfo vector, negative value stands for
57 string length of a string literal (~strlen). */
58 static vec<int> ssa_ver_to_stridx;
60 /* Number of currently active string indexes plus one. */
61 static int max_stridx;
63 /* String information record. */
64 struct strinfo
66 /* Number of leading characters that are known to be nonzero. This is
67 also the length of the string if FULL_STRING_P.
69 The values in a list of related string pointers must be consistent;
70 that is, if strinfo B comes X bytes after strinfo A, it must be
71 the case that A->nonzero_chars == X + B->nonzero_chars. */
72 tree nonzero_chars;
73 /* Any of the corresponding pointers for querying alias oracle. */
74 tree ptr;
75 /* This is used for two things:
77 - To record the statement that should be used for delayed length
78 computations. We maintain the invariant that all related strinfos
79 have delayed lengths or none do.
81 - To record the malloc or calloc call that produced this result. */
82 gimple *stmt;
83 /* Pointer to '\0' if known, if NULL, it can be computed as
84 ptr + length. */
85 tree endptr;
86 /* Reference count. Any changes to strinfo entry possibly shared
87 with dominating basic blocks need unshare_strinfo first, except
88 for dont_invalidate which affects only the immediately next
89 maybe_invalidate. */
90 int refcount;
91 /* Copy of index. get_strinfo (si->idx) should return si; */
92 int idx;
93 /* These 3 fields are for chaining related string pointers together.
94 E.g. for
95 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
96 strcpy (c, d); e = c + dl;
97 strinfo(a) -> strinfo(c) -> strinfo(e)
98 All have ->first field equal to strinfo(a)->idx and are doubly
99 chained through prev/next fields. The later strinfos are required
100 to point into the same string with zero or more bytes after
101 the previous pointer and all bytes in between the two pointers
102 must be non-zero. Functions like strcpy or memcpy are supposed
103 to adjust all previous strinfo lengths, but not following strinfo
104 lengths (those are uncertain, usually invalidated during
105 maybe_invalidate, except when the alias oracle knows better).
106 Functions like strcat on the other side adjust the whole
107 related strinfo chain.
108 They are updated lazily, so to use the chain the same first fields
109 and si->prev->next == si->idx needs to be verified. */
110 int first;
111 int next;
112 int prev;
113 /* A flag whether the string is known to be written in the current
114 function. */
115 bool writable;
116 /* A flag for the next maybe_invalidate that this strinfo shouldn't
117 be invalidated. Always cleared by maybe_invalidate. */
118 bool dont_invalidate;
119 /* True if the string is known to be nul-terminated after NONZERO_CHARS
120 characters. False is useful when detecting strings that are built
121 up via successive memcpys. */
122 bool full_string_p;
125 /* Pool for allocating strinfo_struct entries. */
126 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
128 /* Vector mapping positive string indexes to strinfo, for the
129 current basic block. The first pointer in the vector is special,
130 it is either NULL, meaning the vector isn't shared, or it is
131 a basic block pointer to the owner basic_block if shared.
132 If some other bb wants to modify the vector, the vector needs
133 to be unshared first, and only the owner bb is supposed to free it. */
134 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
136 /* One OFFSET->IDX mapping. */
137 struct stridxlist
139 struct stridxlist *next;
140 HOST_WIDE_INT offset;
141 int idx;
144 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
145 struct decl_stridxlist_map
147 struct tree_map_base base;
148 struct stridxlist list;
151 /* Hash table for mapping decls to a chained list of offset -> idx
152 mappings. */
153 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
155 typedef std::pair<int, location_t> stridx_strlenloc;
156 static hash_map<tree, stridx_strlenloc> strlen_to_stridx;
158 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
159 static struct obstack stridx_obstack;
161 /* Last memcpy statement if it could be adjusted if the trailing
162 '\0' written is immediately overwritten, or
163 *x = '\0' store that could be removed if it is immediately overwritten. */
164 struct laststmt_struct
166 gimple *stmt;
167 tree len;
168 int stridx;
169 } laststmt;
171 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
173 /* Return:
175 - 1 if SI is known to start with more than OFF nonzero characters.
177 - 0 if SI is known to start with OFF nonzero characters,
178 but is not known to start with more.
180 - -1 if SI might not start with OFF nonzero characters. */
182 static inline int
183 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
185 if (si->nonzero_chars
186 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
187 return compare_tree_int (si->nonzero_chars, off);
188 else
189 return -1;
192 /* Return true if SI is known to be a zero-length string. */
194 static inline bool
195 zero_length_string_p (strinfo *si)
197 return si->full_string_p && integer_zerop (si->nonzero_chars);
200 /* Return strinfo vector entry IDX. */
202 static inline strinfo *
203 get_strinfo (int idx)
205 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
206 return NULL;
207 return (*stridx_to_strinfo)[idx];
210 /* Get the next strinfo in the chain after SI, or null if none. */
212 static inline strinfo *
213 get_next_strinfo (strinfo *si)
215 if (si->next == 0)
216 return NULL;
217 strinfo *nextsi = get_strinfo (si->next);
218 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
219 return NULL;
220 return nextsi;
223 /* Helper function for get_stridx. Return the strinfo index of the address
224 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
225 OK to return the index for some X <= &EXP and store &EXP - X in
226 *OFFSET_OUT. */
228 static int
229 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
231 HOST_WIDE_INT off;
232 struct stridxlist *list, *last = NULL;
233 tree base;
235 if (!decl_to_stridxlist_htab)
236 return 0;
238 base = get_addr_base_and_unit_offset (exp, &off);
239 if (base == NULL || !DECL_P (base))
240 return 0;
242 list = decl_to_stridxlist_htab->get (base);
243 if (list == NULL)
244 return 0;
248 if (list->offset == off)
250 if (offset_out)
251 *offset_out = 0;
252 return list->idx;
254 if (list->offset > off)
255 return 0;
256 last = list;
257 list = list->next;
259 while (list);
261 if ((offset_out || ptr) && last && last->idx > 0)
263 unsigned HOST_WIDE_INT rel_off
264 = (unsigned HOST_WIDE_INT) off - last->offset;
265 strinfo *si = get_strinfo (last->idx);
266 if (si && compare_nonzero_chars (si, rel_off) >= 0)
268 if (offset_out)
270 *offset_out = rel_off;
271 return last->idx;
273 else
274 return get_stridx_plus_constant (si, rel_off, ptr);
277 return 0;
280 /* Return string index for EXP. */
282 static int
283 get_stridx (tree exp)
285 tree s, o;
287 if (TREE_CODE (exp) == SSA_NAME)
289 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
290 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
291 int i;
292 tree e = exp;
293 HOST_WIDE_INT off = 0;
294 for (i = 0; i < 5; i++)
296 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
297 if (!is_gimple_assign (def_stmt)
298 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
299 return 0;
300 tree rhs1 = gimple_assign_rhs1 (def_stmt);
301 tree rhs2 = gimple_assign_rhs2 (def_stmt);
302 if (TREE_CODE (rhs1) != SSA_NAME
303 || !tree_fits_shwi_p (rhs2))
304 return 0;
305 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
306 if (this_off < 0)
307 return 0;
308 off = (unsigned HOST_WIDE_INT) off + this_off;
309 if (off < 0)
310 return 0;
311 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
313 strinfo *si
314 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
315 if (si && compare_nonzero_chars (si, off) >= 0)
316 return get_stridx_plus_constant (si, off, exp);
318 e = rhs1;
320 return 0;
323 if (TREE_CODE (exp) == ADDR_EXPR)
325 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
326 if (idx != 0)
327 return idx;
330 s = string_constant (exp, &o);
331 if (s != NULL_TREE
332 && (o == NULL_TREE || tree_fits_shwi_p (o))
333 && TREE_STRING_LENGTH (s) > 0)
335 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
336 const char *p = TREE_STRING_POINTER (s);
337 int max = TREE_STRING_LENGTH (s) - 1;
339 if (p[max] == '\0' && offset >= 0 && offset <= max)
340 return ~(int) strlen (p + offset);
342 return 0;
345 /* Return true if strinfo vector is shared with the immediate dominator. */
347 static inline bool
348 strinfo_shared (void)
350 return vec_safe_length (stridx_to_strinfo)
351 && (*stridx_to_strinfo)[0] != NULL;
354 /* Unshare strinfo vector that is shared with the immediate dominator. */
356 static void
357 unshare_strinfo_vec (void)
359 strinfo *si;
360 unsigned int i = 0;
362 gcc_assert (strinfo_shared ());
363 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
364 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
365 if (si != NULL)
366 si->refcount++;
367 (*stridx_to_strinfo)[0] = NULL;
370 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
371 Return a pointer to the location where the string index can
372 be stored (if 0) or is stored, or NULL if this can't be tracked. */
374 static int *
375 addr_stridxptr (tree exp)
377 HOST_WIDE_INT off;
379 tree base = get_addr_base_and_unit_offset (exp, &off);
380 if (base == NULL_TREE || !DECL_P (base))
381 return NULL;
383 if (!decl_to_stridxlist_htab)
385 decl_to_stridxlist_htab
386 = new hash_map<tree_decl_hash, stridxlist> (64);
387 gcc_obstack_init (&stridx_obstack);
390 bool existed;
391 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
392 if (existed)
394 int i;
395 stridxlist *before = NULL;
396 for (i = 0; i < 32; i++)
398 if (list->offset == off)
399 return &list->idx;
400 if (list->offset > off && before == NULL)
401 before = list;
402 if (list->next == NULL)
403 break;
404 list = list->next;
406 if (i == 32)
407 return NULL;
408 if (before)
410 list = before;
411 before = XOBNEW (&stridx_obstack, struct stridxlist);
412 *before = *list;
413 list->next = before;
414 list->offset = off;
415 list->idx = 0;
416 return &list->idx;
418 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
419 list = list->next;
422 list->next = NULL;
423 list->offset = off;
424 list->idx = 0;
425 return &list->idx;
428 /* Create a new string index, or return 0 if reached limit. */
430 static int
431 new_stridx (tree exp)
433 int idx;
434 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
435 return 0;
436 if (TREE_CODE (exp) == SSA_NAME)
438 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
439 return 0;
440 idx = max_stridx++;
441 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
442 return idx;
444 if (TREE_CODE (exp) == ADDR_EXPR)
446 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
447 if (pidx != NULL)
449 gcc_assert (*pidx == 0);
450 *pidx = max_stridx++;
451 return *pidx;
454 return 0;
457 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
459 static int
460 new_addr_stridx (tree exp)
462 int *pidx;
463 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
464 return 0;
465 pidx = addr_stridxptr (exp);
466 if (pidx != NULL)
468 gcc_assert (*pidx == 0);
469 *pidx = max_stridx++;
470 return *pidx;
472 return 0;
475 /* Create a new strinfo. */
477 static strinfo *
478 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
480 strinfo *si = strinfo_pool.allocate ();
481 si->nonzero_chars = nonzero_chars;
482 si->ptr = ptr;
483 si->stmt = NULL;
484 si->endptr = NULL_TREE;
485 si->refcount = 1;
486 si->idx = idx;
487 si->first = 0;
488 si->prev = 0;
489 si->next = 0;
490 si->writable = false;
491 si->dont_invalidate = false;
492 si->full_string_p = full_string_p;
493 return si;
496 /* Decrease strinfo refcount and free it if not referenced anymore. */
498 static inline void
499 free_strinfo (strinfo *si)
501 if (si && --si->refcount == 0)
502 strinfo_pool.remove (si);
505 /* Set strinfo in the vector entry IDX to SI. */
507 static inline void
508 set_strinfo (int idx, strinfo *si)
510 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
511 unshare_strinfo_vec ();
512 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
513 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
514 (*stridx_to_strinfo)[idx] = si;
517 /* Return the first strinfo in the related strinfo chain
518 if all strinfos in between belong to the chain, otherwise NULL. */
520 static strinfo *
521 verify_related_strinfos (strinfo *origsi)
523 strinfo *si = origsi, *psi;
525 if (origsi->first == 0)
526 return NULL;
527 for (; si->prev; si = psi)
529 if (si->first != origsi->first)
530 return NULL;
531 psi = get_strinfo (si->prev);
532 if (psi == NULL)
533 return NULL;
534 if (psi->next != si->idx)
535 return NULL;
537 if (si->idx != si->first)
538 return NULL;
539 return si;
542 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
543 Use LOC for folding. */
545 static void
546 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
548 si->endptr = endptr;
549 si->stmt = NULL;
550 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
551 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
552 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
553 end_as_size, start_as_size);
554 si->full_string_p = true;
557 /* Return string length, or NULL if it can't be computed. */
559 static tree
560 get_string_length (strinfo *si)
562 if (si->nonzero_chars)
563 return si->full_string_p ? si->nonzero_chars : NULL;
565 if (si->stmt)
567 gimple *stmt = si->stmt, *lenstmt;
568 bool with_bounds = gimple_call_with_bounds_p (stmt);
569 tree callee, lhs, fn, tem;
570 location_t loc;
571 gimple_stmt_iterator gsi;
573 gcc_assert (is_gimple_call (stmt));
574 callee = gimple_call_fndecl (stmt);
575 gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
576 lhs = gimple_call_lhs (stmt);
577 /* unshare_strinfo is intentionally not called here. The (delayed)
578 transformation of strcpy or strcat into stpcpy is done at the place
579 of the former strcpy/strcat call and so can affect all the strinfos
580 with the same stmt. If they were unshared before and transformation
581 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
582 just compute the right length. */
583 switch (DECL_FUNCTION_CODE (callee))
585 case BUILT_IN_STRCAT:
586 case BUILT_IN_STRCAT_CHK:
587 case BUILT_IN_STRCAT_CHKP:
588 case BUILT_IN_STRCAT_CHK_CHKP:
589 gsi = gsi_for_stmt (stmt);
590 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
591 gcc_assert (lhs == NULL_TREE);
592 tem = unshare_expr (gimple_call_arg (stmt, 0));
593 if (with_bounds)
595 lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl,
596 2, tem, gimple_call_arg (stmt, 1));
597 gimple_call_set_with_bounds (lenstmt, true);
599 else
600 lenstmt = gimple_build_call (fn, 1, tem);
601 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
602 gimple_call_set_lhs (lenstmt, lhs);
603 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
604 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
605 tem = gimple_call_arg (stmt, 0);
606 if (!ptrofftype_p (TREE_TYPE (lhs)))
608 lhs = convert_to_ptrofftype (lhs);
609 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
610 true, GSI_SAME_STMT);
612 lenstmt = gimple_build_assign
613 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
614 POINTER_PLUS_EXPR,tem, lhs);
615 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
616 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
617 lhs = NULL_TREE;
618 /* FALLTHRU */
619 case BUILT_IN_STRCPY:
620 case BUILT_IN_STRCPY_CHK:
621 case BUILT_IN_STRCPY_CHKP:
622 case BUILT_IN_STRCPY_CHK_CHKP:
623 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
624 if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2))
625 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
626 else
627 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
628 if (with_bounds)
629 fn = chkp_maybe_create_clone (fn)->decl;
630 gcc_assert (lhs == NULL_TREE);
631 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
633 fprintf (dump_file, "Optimizing: ");
634 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
636 gimple_call_set_fndecl (stmt, fn);
637 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
638 gimple_call_set_lhs (stmt, lhs);
639 update_stmt (stmt);
640 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
642 fprintf (dump_file, "into: ");
643 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
645 /* FALLTHRU */
646 case BUILT_IN_STPCPY:
647 case BUILT_IN_STPCPY_CHK:
648 case BUILT_IN_STPCPY_CHKP:
649 case BUILT_IN_STPCPY_CHK_CHKP:
650 gcc_assert (lhs != NULL_TREE);
651 loc = gimple_location (stmt);
652 set_endptr_and_length (loc, si, lhs);
653 for (strinfo *chainsi = verify_related_strinfos (si);
654 chainsi != NULL;
655 chainsi = get_next_strinfo (chainsi))
656 if (chainsi->nonzero_chars == NULL)
657 set_endptr_and_length (loc, chainsi, lhs);
658 break;
659 case BUILT_IN_MALLOC:
660 break;
661 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
662 default:
663 gcc_unreachable ();
664 break;
668 return si->nonzero_chars;
671 /* Invalidate string length information for strings whose length
672 might change due to stores in stmt. */
674 static bool
675 maybe_invalidate (gimple *stmt)
677 strinfo *si;
678 unsigned int i;
679 bool nonempty = false;
681 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
682 if (si != NULL)
684 if (!si->dont_invalidate)
686 ao_ref r;
687 /* Do not use si->nonzero_chars. */
688 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
689 if (stmt_may_clobber_ref_p_1 (stmt, &r))
691 set_strinfo (i, NULL);
692 free_strinfo (si);
693 continue;
696 si->dont_invalidate = false;
697 nonempty = true;
699 return nonempty;
702 /* Unshare strinfo record SI, if it has refcount > 1 or
703 if stridx_to_strinfo vector is shared with some other
704 bbs. */
706 static strinfo *
707 unshare_strinfo (strinfo *si)
709 strinfo *nsi;
711 if (si->refcount == 1 && !strinfo_shared ())
712 return si;
714 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
715 nsi->stmt = si->stmt;
716 nsi->endptr = si->endptr;
717 nsi->first = si->first;
718 nsi->prev = si->prev;
719 nsi->next = si->next;
720 nsi->writable = si->writable;
721 set_strinfo (si->idx, nsi);
722 free_strinfo (si);
723 return nsi;
726 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
727 strinfo if there is any. Return it's idx, or 0 if no strinfo has
728 been created. */
730 static int
731 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
732 tree ptr)
734 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
735 return 0;
737 if (compare_nonzero_chars (basesi, off) < 0
738 || !tree_fits_uhwi_p (basesi->nonzero_chars))
739 return 0;
741 unsigned HOST_WIDE_INT nonzero_chars
742 = tree_to_uhwi (basesi->nonzero_chars) - off;
743 strinfo *si = basesi, *chainsi;
744 if (si->first || si->prev || si->next)
745 si = verify_related_strinfos (basesi);
746 if (si == NULL
747 || si->nonzero_chars == NULL_TREE
748 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
749 return 0;
751 if (TREE_CODE (ptr) == SSA_NAME
752 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
753 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
755 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
756 for (chainsi = si; chainsi->next; chainsi = si)
758 si = get_next_strinfo (chainsi);
759 if (si == NULL
760 || si->nonzero_chars == NULL_TREE
761 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
762 break;
763 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
764 if (r != 1)
766 if (r == 0)
768 if (TREE_CODE (ptr) == SSA_NAME)
769 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
770 else
772 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
773 if (pidx != NULL && *pidx == 0)
774 *pidx = si->idx;
776 return si->idx;
778 break;
782 int idx = new_stridx (ptr);
783 if (idx == 0)
784 return 0;
785 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
786 basesi->full_string_p);
787 set_strinfo (idx, si);
788 if (chainsi->next)
790 strinfo *nextsi = unshare_strinfo (get_strinfo (chainsi->next));
791 si->next = nextsi->idx;
792 nextsi->prev = idx;
794 chainsi = unshare_strinfo (chainsi);
795 if (chainsi->first == 0)
796 chainsi->first = chainsi->idx;
797 chainsi->next = idx;
798 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
799 chainsi->endptr = ptr;
800 si->endptr = chainsi->endptr;
801 si->prev = chainsi->idx;
802 si->first = chainsi->first;
803 si->writable = chainsi->writable;
804 return si->idx;
807 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
808 to a zero-length string and if possible chain it to a related strinfo
809 chain whose part is or might be CHAINSI. */
811 static strinfo *
812 zero_length_string (tree ptr, strinfo *chainsi)
814 strinfo *si;
815 int idx;
816 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
817 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
818 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
819 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
821 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
822 return NULL;
823 if (chainsi != NULL)
825 si = verify_related_strinfos (chainsi);
826 if (si)
830 /* We shouldn't mix delayed and non-delayed lengths. */
831 gcc_assert (si->full_string_p);
832 if (si->endptr == NULL_TREE)
834 si = unshare_strinfo (si);
835 si->endptr = ptr;
837 chainsi = si;
838 si = get_next_strinfo (si);
840 while (si != NULL);
841 if (zero_length_string_p (chainsi))
843 if (chainsi->next)
845 chainsi = unshare_strinfo (chainsi);
846 chainsi->next = 0;
848 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
849 return chainsi;
852 else
854 /* We shouldn't mix delayed and non-delayed lengths. */
855 gcc_assert (chainsi->full_string_p);
856 if (chainsi->first || chainsi->prev || chainsi->next)
858 chainsi = unshare_strinfo (chainsi);
859 chainsi->first = 0;
860 chainsi->prev = 0;
861 chainsi->next = 0;
865 idx = new_stridx (ptr);
866 if (idx == 0)
867 return NULL;
868 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
869 set_strinfo (idx, si);
870 si->endptr = ptr;
871 if (chainsi != NULL)
873 chainsi = unshare_strinfo (chainsi);
874 if (chainsi->first == 0)
875 chainsi->first = chainsi->idx;
876 chainsi->next = idx;
877 if (chainsi->endptr == NULL_TREE)
878 chainsi->endptr = ptr;
879 si->prev = chainsi->idx;
880 si->first = chainsi->first;
881 si->writable = chainsi->writable;
883 return si;
886 /* For strinfo ORIGSI whose length has been just updated, adjust other
887 related strinfos so that they match the new ORIGSI. This involves:
889 - adding ADJ to the nonzero_chars fields
890 - copying full_string_p from the new ORIGSI. */
892 static void
893 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
895 strinfo *si = verify_related_strinfos (origsi);
897 if (si == NULL)
898 return;
900 while (1)
902 strinfo *nsi;
904 if (si != origsi)
906 tree tem;
908 si = unshare_strinfo (si);
909 /* We shouldn't see delayed lengths here; the caller must have
910 calculated the old length in order to calculate the
911 adjustment. */
912 gcc_assert (si->nonzero_chars);
913 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
914 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
915 TREE_TYPE (si->nonzero_chars),
916 si->nonzero_chars, tem);
917 si->full_string_p = origsi->full_string_p;
919 si->endptr = NULL_TREE;
920 si->dont_invalidate = true;
922 nsi = get_next_strinfo (si);
923 if (nsi == NULL)
924 return;
925 si = nsi;
929 /* Find if there are other SSA_NAME pointers equal to PTR
930 for which we don't track their string lengths yet. If so, use
931 IDX for them. */
933 static void
934 find_equal_ptrs (tree ptr, int idx)
936 if (TREE_CODE (ptr) != SSA_NAME)
937 return;
938 while (1)
940 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
941 if (!is_gimple_assign (stmt))
942 return;
943 ptr = gimple_assign_rhs1 (stmt);
944 switch (gimple_assign_rhs_code (stmt))
946 case SSA_NAME:
947 break;
948 CASE_CONVERT:
949 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
950 return;
951 if (TREE_CODE (ptr) == SSA_NAME)
952 break;
953 if (TREE_CODE (ptr) != ADDR_EXPR)
954 return;
955 /* FALLTHRU */
956 case ADDR_EXPR:
958 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
959 if (pidx != NULL && *pidx == 0)
960 *pidx = idx;
961 return;
963 default:
964 return;
967 /* We might find an endptr created in this pass. Grow the
968 vector in that case. */
969 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
970 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
972 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
973 return;
974 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
978 /* Return true if STMT is a call to a builtin function with the right
979 arguments and attributes that should be considered for optimization
980 by this pass. */
982 static bool
983 valid_builtin_call (gimple *stmt)
985 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
986 return false;
988 tree callee = gimple_call_fndecl (stmt);
989 switch (DECL_FUNCTION_CODE (callee))
991 case BUILT_IN_MEMCMP:
992 case BUILT_IN_MEMCMP_EQ:
993 case BUILT_IN_STRCHR:
994 case BUILT_IN_STRCHR_CHKP:
995 case BUILT_IN_STRLEN:
996 case BUILT_IN_STRLEN_CHKP:
997 /* The above functions should be pure. Punt if they aren't. */
998 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
999 return false;
1000 break;
1002 case BUILT_IN_CALLOC:
1003 case BUILT_IN_MALLOC:
1004 case BUILT_IN_MEMCPY:
1005 case BUILT_IN_MEMCPY_CHK:
1006 case BUILT_IN_MEMCPY_CHKP:
1007 case BUILT_IN_MEMCPY_CHK_CHKP:
1008 case BUILT_IN_MEMPCPY:
1009 case BUILT_IN_MEMPCPY_CHK:
1010 case BUILT_IN_MEMPCPY_CHKP:
1011 case BUILT_IN_MEMPCPY_CHK_CHKP:
1012 case BUILT_IN_MEMSET:
1013 case BUILT_IN_STPCPY:
1014 case BUILT_IN_STPCPY_CHK:
1015 case BUILT_IN_STPCPY_CHKP:
1016 case BUILT_IN_STPCPY_CHK_CHKP:
1017 case BUILT_IN_STRCAT:
1018 case BUILT_IN_STRCAT_CHK:
1019 case BUILT_IN_STRCAT_CHKP:
1020 case BUILT_IN_STRCAT_CHK_CHKP:
1021 case BUILT_IN_STRCPY:
1022 case BUILT_IN_STRCPY_CHK:
1023 case BUILT_IN_STRCPY_CHKP:
1024 case BUILT_IN_STRCPY_CHK_CHKP:
1025 /* The above functions should be neither const nor pure. Punt if they
1026 aren't. */
1027 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1028 return false;
1029 break;
1031 default:
1032 break;
1035 return true;
1038 /* If the last .MEM setter statement before STMT is
1039 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1040 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1041 just memcpy (x, y, strlen (y)). SI must be the zero length
1042 strinfo. */
1044 static void
1045 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1047 tree vuse, callee, len;
1048 struct laststmt_struct last = laststmt;
1049 strinfo *lastsi, *firstsi;
1050 unsigned len_arg_no = 2;
1052 laststmt.stmt = NULL;
1053 laststmt.len = NULL_TREE;
1054 laststmt.stridx = 0;
1056 if (last.stmt == NULL)
1057 return;
1059 vuse = gimple_vuse (stmt);
1060 if (vuse == NULL_TREE
1061 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1062 || !has_single_use (vuse))
1063 return;
1065 gcc_assert (last.stridx > 0);
1066 lastsi = get_strinfo (last.stridx);
1067 if (lastsi == NULL)
1068 return;
1070 if (lastsi != si)
1072 if (lastsi->first == 0 || lastsi->first != si->first)
1073 return;
1075 firstsi = verify_related_strinfos (si);
1076 if (firstsi == NULL)
1077 return;
1078 while (firstsi != lastsi)
1080 firstsi = get_next_strinfo (firstsi);
1081 if (firstsi == NULL)
1082 return;
1086 if (!is_strcat && !zero_length_string_p (si))
1087 return;
1089 if (is_gimple_assign (last.stmt))
1091 gimple_stmt_iterator gsi;
1093 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1094 return;
1095 if (stmt_could_throw_p (last.stmt))
1096 return;
1097 gsi = gsi_for_stmt (last.stmt);
1098 unlink_stmt_vdef (last.stmt);
1099 release_defs (last.stmt);
1100 gsi_remove (&gsi, true);
1101 return;
1104 if (!valid_builtin_call (last.stmt))
1105 return;
1107 callee = gimple_call_fndecl (last.stmt);
1108 switch (DECL_FUNCTION_CODE (callee))
1110 case BUILT_IN_MEMCPY:
1111 case BUILT_IN_MEMCPY_CHK:
1112 break;
1113 case BUILT_IN_MEMCPY_CHKP:
1114 case BUILT_IN_MEMCPY_CHK_CHKP:
1115 len_arg_no = 4;
1116 break;
1117 default:
1118 return;
1121 len = gimple_call_arg (last.stmt, len_arg_no);
1122 if (tree_fits_uhwi_p (len))
1124 if (!tree_fits_uhwi_p (last.len)
1125 || integer_zerop (len)
1126 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1127 return;
1128 /* Don't adjust the length if it is divisible by 4, it is more efficient
1129 to store the extra '\0' in that case. */
1130 if ((tree_to_uhwi (len) & 3) == 0)
1131 return;
1133 else if (TREE_CODE (len) == SSA_NAME)
1135 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1136 if (!is_gimple_assign (def_stmt)
1137 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1138 || gimple_assign_rhs1 (def_stmt) != last.len
1139 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1140 return;
1142 else
1143 return;
1145 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1146 update_stmt (last.stmt);
1149 /* Handle a strlen call. If strlen of the argument is known, replace
1150 the strlen call with the known value, otherwise remember that strlen
1151 of the argument is stored in the lhs SSA_NAME. */
1153 static void
1154 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1156 int idx;
1157 tree src;
1158 gimple *stmt = gsi_stmt (*gsi);
1159 tree lhs = gimple_call_lhs (stmt);
1161 if (lhs == NULL_TREE)
1162 return;
1164 src = gimple_call_arg (stmt, 0);
1165 idx = get_stridx (src);
1166 if (idx)
1168 strinfo *si = NULL;
1169 tree rhs;
1171 if (idx < 0)
1172 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1173 else
1175 rhs = NULL_TREE;
1176 si = get_strinfo (idx);
1177 if (si != NULL)
1178 rhs = get_string_length (si);
1180 if (rhs != NULL_TREE)
1182 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1184 fprintf (dump_file, "Optimizing: ");
1185 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1187 rhs = unshare_expr (rhs);
1188 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1189 rhs = fold_convert_loc (gimple_location (stmt),
1190 TREE_TYPE (lhs), rhs);
1191 if (!update_call_from_tree (gsi, rhs))
1192 gimplify_and_update_call_from_tree (gsi, rhs);
1193 stmt = gsi_stmt (*gsi);
1194 update_stmt (stmt);
1195 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1197 fprintf (dump_file, "into: ");
1198 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1200 if (si != NULL
1201 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1202 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1203 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1205 si = unshare_strinfo (si);
1206 si->nonzero_chars = lhs;
1207 gcc_assert (si->full_string_p);
1210 location_t loc = gimple_location (stmt);
1211 strlen_to_stridx.put (lhs, stridx_strlenloc (idx, loc));
1212 return;
1215 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1216 return;
1217 if (idx == 0)
1218 idx = new_stridx (src);
1219 else
1221 strinfo *si = get_strinfo (idx);
1222 if (si != NULL)
1224 if (!si->full_string_p && !si->stmt)
1226 /* Until now we only had a lower bound on the string length.
1227 Install LHS as the actual length. */
1228 si = unshare_strinfo (si);
1229 tree old = si->nonzero_chars;
1230 si->nonzero_chars = lhs;
1231 si->full_string_p = true;
1232 if (TREE_CODE (old) == INTEGER_CST)
1234 location_t loc = gimple_location (stmt);
1235 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1236 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1237 TREE_TYPE (lhs), lhs, old);
1238 adjust_related_strinfos (loc, si, adj);
1240 else
1242 si->first = 0;
1243 si->prev = 0;
1244 si->next = 0;
1247 return;
1250 if (idx)
1252 strinfo *si = new_strinfo (src, idx, lhs, true);
1253 set_strinfo (idx, si);
1254 find_equal_ptrs (src, idx);
1256 location_t loc = gimple_location (stmt);
1257 strlen_to_stridx.put (lhs, stridx_strlenloc (idx, loc));
1261 /* Handle a strchr call. If strlen of the first argument is known, replace
1262 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1263 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1265 static void
1266 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1268 int idx;
1269 tree src;
1270 gimple *stmt = gsi_stmt (*gsi);
1271 tree lhs = gimple_call_lhs (stmt);
1272 bool with_bounds = gimple_call_with_bounds_p (stmt);
1274 if (lhs == NULL_TREE)
1275 return;
1277 if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1)))
1278 return;
1280 src = gimple_call_arg (stmt, 0);
1281 idx = get_stridx (src);
1282 if (idx)
1284 strinfo *si = NULL;
1285 tree rhs;
1287 if (idx < 0)
1288 rhs = build_int_cst (size_type_node, ~idx);
1289 else
1291 rhs = NULL_TREE;
1292 si = get_strinfo (idx);
1293 if (si != NULL)
1294 rhs = get_string_length (si);
1296 if (rhs != NULL_TREE)
1298 location_t loc = gimple_location (stmt);
1300 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1302 fprintf (dump_file, "Optimizing: ");
1303 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1305 if (si != NULL && si->endptr != NULL_TREE)
1307 rhs = unshare_expr (si->endptr);
1308 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1309 TREE_TYPE (rhs)))
1310 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1312 else
1314 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1315 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1316 TREE_TYPE (src), src, rhs);
1317 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1318 TREE_TYPE (rhs)))
1319 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1321 if (!update_call_from_tree (gsi, rhs))
1322 gimplify_and_update_call_from_tree (gsi, rhs);
1323 stmt = gsi_stmt (*gsi);
1324 update_stmt (stmt);
1325 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1327 fprintf (dump_file, "into: ");
1328 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1330 if (si != NULL
1331 && si->endptr == NULL_TREE
1332 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1334 si = unshare_strinfo (si);
1335 si->endptr = lhs;
1337 zero_length_string (lhs, si);
1338 return;
1341 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1342 return;
1343 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1345 if (idx == 0)
1346 idx = new_stridx (src);
1347 else if (get_strinfo (idx) != NULL)
1349 zero_length_string (lhs, NULL);
1350 return;
1352 if (idx)
1354 location_t loc = gimple_location (stmt);
1355 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1356 tree srcu = fold_convert_loc (loc, size_type_node, src);
1357 tree length = fold_build2_loc (loc, MINUS_EXPR,
1358 size_type_node, lhsu, srcu);
1359 strinfo *si = new_strinfo (src, idx, length, true);
1360 si->endptr = lhs;
1361 set_strinfo (idx, si);
1362 find_equal_ptrs (src, idx);
1363 zero_length_string (lhs, si);
1366 else
1367 zero_length_string (lhs, NULL);
1370 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1371 If strlen of the second argument is known, strlen of the first argument
1372 is the same after this call. Furthermore, attempt to convert it to
1373 memcpy. */
1375 static void
1376 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1378 int idx, didx;
1379 tree src, dst, srclen, len, lhs, args, type, fn, oldlen;
1380 bool success;
1381 gimple *stmt = gsi_stmt (*gsi);
1382 strinfo *si, *dsi, *olddsi, *zsi;
1383 location_t loc;
1384 bool with_bounds = gimple_call_with_bounds_p (stmt);
1386 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1387 dst = gimple_call_arg (stmt, 0);
1388 lhs = gimple_call_lhs (stmt);
1389 idx = get_stridx (src);
1390 si = NULL;
1391 if (idx > 0)
1392 si = get_strinfo (idx);
1394 didx = get_stridx (dst);
1395 olddsi = NULL;
1396 oldlen = NULL_TREE;
1397 if (didx > 0)
1398 olddsi = get_strinfo (didx);
1399 else if (didx < 0)
1400 return;
1402 if (olddsi != NULL)
1403 adjust_last_stmt (olddsi, stmt, false);
1405 srclen = NULL_TREE;
1406 if (si != NULL)
1407 srclen = get_string_length (si);
1408 else if (idx < 0)
1409 srclen = build_int_cst (size_type_node, ~idx);
1411 loc = gimple_location (stmt);
1412 if (srclen == NULL_TREE)
1413 switch (bcode)
1415 case BUILT_IN_STRCPY:
1416 case BUILT_IN_STRCPY_CHK:
1417 case BUILT_IN_STRCPY_CHKP:
1418 case BUILT_IN_STRCPY_CHK_CHKP:
1419 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1420 return;
1421 break;
1422 case BUILT_IN_STPCPY:
1423 case BUILT_IN_STPCPY_CHK:
1424 case BUILT_IN_STPCPY_CHKP:
1425 case BUILT_IN_STPCPY_CHK_CHKP:
1426 if (lhs == NULL_TREE)
1427 return;
1428 else
1430 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1431 srclen = fold_convert_loc (loc, size_type_node, dst);
1432 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1433 lhsuint, srclen);
1435 break;
1436 default:
1437 gcc_unreachable ();
1440 if (didx == 0)
1442 didx = new_stridx (dst);
1443 if (didx == 0)
1444 return;
1446 if (olddsi != NULL)
1448 oldlen = olddsi->nonzero_chars;
1449 dsi = unshare_strinfo (olddsi);
1450 dsi->nonzero_chars = srclen;
1451 dsi->full_string_p = (srclen != NULL_TREE);
1452 /* Break the chain, so adjust_related_strinfo on later pointers in
1453 the chain won't adjust this one anymore. */
1454 dsi->next = 0;
1455 dsi->stmt = NULL;
1456 dsi->endptr = NULL_TREE;
1458 else
1460 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1461 set_strinfo (didx, dsi);
1462 find_equal_ptrs (dst, didx);
1464 dsi->writable = true;
1465 dsi->dont_invalidate = true;
1467 if (dsi->nonzero_chars == NULL_TREE)
1469 strinfo *chainsi;
1471 /* If string length of src is unknown, use delayed length
1472 computation. If string lenth of dst will be needed, it
1473 can be computed by transforming this strcpy call into
1474 stpcpy and subtracting dst from the return value. */
1476 /* Look for earlier strings whose length could be determined if
1477 this strcpy is turned into an stpcpy. */
1479 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1481 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1483 /* When setting a stmt for delayed length computation
1484 prevent all strinfos through dsi from being
1485 invalidated. */
1486 chainsi = unshare_strinfo (chainsi);
1487 chainsi->stmt = stmt;
1488 chainsi->nonzero_chars = NULL_TREE;
1489 chainsi->full_string_p = false;
1490 chainsi->endptr = NULL_TREE;
1491 chainsi->dont_invalidate = true;
1494 dsi->stmt = stmt;
1495 return;
1498 if (olddsi != NULL)
1500 tree adj = NULL_TREE;
1501 if (oldlen == NULL_TREE)
1503 else if (integer_zerop (oldlen))
1504 adj = srclen;
1505 else if (TREE_CODE (oldlen) == INTEGER_CST
1506 || TREE_CODE (srclen) == INTEGER_CST)
1507 adj = fold_build2_loc (loc, MINUS_EXPR,
1508 TREE_TYPE (srclen), srclen,
1509 fold_convert_loc (loc, TREE_TYPE (srclen),
1510 oldlen));
1511 if (adj != NULL_TREE)
1512 adjust_related_strinfos (loc, dsi, adj);
1513 else
1514 dsi->prev = 0;
1516 /* strcpy src may not overlap dst, so src doesn't need to be
1517 invalidated either. */
1518 if (si != NULL)
1519 si->dont_invalidate = true;
1521 fn = NULL_TREE;
1522 zsi = NULL;
1523 switch (bcode)
1525 case BUILT_IN_STRCPY:
1526 case BUILT_IN_STRCPY_CHKP:
1527 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1528 if (lhs)
1529 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1530 break;
1531 case BUILT_IN_STRCPY_CHK:
1532 case BUILT_IN_STRCPY_CHK_CHKP:
1533 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1534 if (lhs)
1535 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1536 break;
1537 case BUILT_IN_STPCPY:
1538 case BUILT_IN_STPCPY_CHKP:
1539 /* This would need adjustment of the lhs (subtract one),
1540 or detection that the trailing '\0' doesn't need to be
1541 written, if it will be immediately overwritten.
1542 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1543 if (lhs)
1545 dsi->endptr = lhs;
1546 zsi = zero_length_string (lhs, dsi);
1548 break;
1549 case BUILT_IN_STPCPY_CHK:
1550 case BUILT_IN_STPCPY_CHK_CHKP:
1551 /* This would need adjustment of the lhs (subtract one),
1552 or detection that the trailing '\0' doesn't need to be
1553 written, if it will be immediately overwritten.
1554 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1555 if (lhs)
1557 dsi->endptr = lhs;
1558 zsi = zero_length_string (lhs, dsi);
1560 break;
1561 default:
1562 gcc_unreachable ();
1564 if (zsi != NULL)
1565 zsi->dont_invalidate = true;
1567 if (fn == NULL_TREE)
1568 return;
1570 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1571 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1573 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1574 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1575 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1576 GSI_SAME_STMT);
1577 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1579 fprintf (dump_file, "Optimizing: ");
1580 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1582 if (with_bounds)
1584 fn = chkp_maybe_create_clone (fn)->decl;
1585 if (gimple_call_num_args (stmt) == 4)
1586 success = update_gimple_call (gsi, fn, 5, dst,
1587 gimple_call_arg (stmt, 1),
1588 src,
1589 gimple_call_arg (stmt, 3),
1590 len);
1591 else
1592 success = update_gimple_call (gsi, fn, 6, dst,
1593 gimple_call_arg (stmt, 1),
1594 src,
1595 gimple_call_arg (stmt, 3),
1596 len,
1597 gimple_call_arg (stmt, 4));
1599 else
1600 if (gimple_call_num_args (stmt) == 2)
1601 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1602 else
1603 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1604 gimple_call_arg (stmt, 2));
1605 if (success)
1607 stmt = gsi_stmt (*gsi);
1608 gimple_call_set_with_bounds (stmt, with_bounds);
1609 update_stmt (stmt);
1610 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1612 fprintf (dump_file, "into: ");
1613 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1615 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1616 laststmt.stmt = stmt;
1617 laststmt.len = srclen;
1618 laststmt.stridx = dsi->idx;
1620 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1621 fprintf (dump_file, "not possible.\n");
1624 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1625 way. LEN can either be an integer expression, or a pointer (to char).
1626 When it is the latter (such as in recursive calls to self) is is
1627 assumed to be the argument in some call to strlen() whose relationship
1628 to SRC is being ascertained. */
1630 static bool
1631 is_strlen_related_p (tree src, tree len)
1633 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1634 && operand_equal_p (src, len, 0))
1635 return true;
1637 if (TREE_CODE (len) != SSA_NAME)
1638 return false;
1640 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1641 if (!def_stmt)
1642 return false;
1644 if (is_gimple_call (def_stmt))
1646 tree func = gimple_call_fndecl (def_stmt);
1647 if (!valid_builtin_call (def_stmt)
1648 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1649 return false;
1651 tree arg = gimple_call_arg (def_stmt, 0);
1652 return is_strlen_related_p (src, arg);
1655 if (!is_gimple_assign (def_stmt))
1656 return false;
1658 tree_code code = gimple_assign_rhs_code (def_stmt);
1659 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1660 tree rhstype = TREE_TYPE (rhs1);
1662 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1663 || (INTEGRAL_TYPE_P (rhstype)
1664 && (code == BIT_AND_EXPR
1665 || code == NOP_EXPR)))
1667 /* Pointer plus (an integer) and integer cast or truncation are
1668 considered among the (potentially) related expressions to strlen.
1669 Others are not. */
1670 return is_strlen_related_p (src, rhs1);
1673 return false;
1676 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1677 bound is a) equal to the size of the destination DST and if so, b)
1678 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1679 and b) does not, warn. Otherwise, do nothing. Return true if
1680 diagnostic has been issued.
1682 The purpose is to diagnose calls to strncpy and stpncpy that do
1683 not nul-terminate the copy while allowing for the idiom where
1684 such a call is immediately followed by setting the last element
1685 to nul, as in:
1686 char a[32];
1687 strncpy (a, s, sizeof a);
1688 a[sizeof a - 1] = '\0';
1691 static bool
1692 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1694 if (!warn_stringop_truncation)
1695 return false;
1697 gimple *stmt = gsi_stmt (gsi);
1699 wide_int cntrange[2];
1701 if (TREE_CODE (cnt) == INTEGER_CST)
1702 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1703 else if (TREE_CODE (cnt) == SSA_NAME)
1705 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1706 if (rng == VR_RANGE)
1708 else if (rng == VR_ANTI_RANGE)
1710 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1712 if (wi::ltu_p (cntrange[1], maxobjsize))
1714 cntrange[0] = cntrange[1] + 1;
1715 cntrange[1] = maxobjsize;
1717 else
1719 cntrange[1] = cntrange[0] - 1;
1720 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1723 else
1724 return false;
1726 else
1727 return false;
1729 /* Negative value is the constant string length. If it's less than
1730 the lower bound there is no truncation. */
1731 int sidx = get_stridx (src);
1732 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1733 return false;
1735 tree dst = gimple_call_arg (stmt, 0);
1737 /* See if the destination is declared with attribute "nonstring"
1738 and if so, avoid the truncation warning. */
1739 if (TREE_CODE (dst) == SSA_NAME)
1741 if (SSA_NAME_IS_DEFAULT_DEF (dst))
1742 dst = SSA_NAME_VAR (dst);
1743 else
1745 gimple *def = SSA_NAME_DEF_STMT (dst);
1747 if (is_gimple_assign (def)
1748 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1749 dst = gimple_assign_rhs1 (def);
1753 tree dstdecl = dst;
1754 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1755 dstdecl = TREE_OPERAND (dstdecl, 0);
1758 tree d = dstdecl;
1759 if (TREE_CODE (d) == COMPONENT_REF)
1760 d = TREE_OPERAND (d, 1);
1762 if (DECL_P (d) && lookup_attribute ("nonstring", DECL_ATTRIBUTES (d)))
1763 return false;
1766 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1767 avoid the truncation warning. */
1768 gsi_next (&gsi);
1769 gimple *next_stmt = gsi_stmt (gsi);
1771 if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt))
1773 HOST_WIDE_INT off;
1774 dstdecl = get_addr_base_and_unit_offset (dstdecl, &off);
1776 tree lhs = gimple_assign_lhs (next_stmt);
1777 tree lhsbase = get_addr_base_and_unit_offset (lhs, &off);
1778 if (lhsbase && operand_equal_p (dstdecl, lhsbase, 0))
1779 return false;
1782 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1783 wide_int lenrange[2];
1784 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1786 lenrange[0] = (sisrc->nonzero_chars
1787 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1788 ? wi::to_wide (sisrc->nonzero_chars)
1789 : wi::zero (prec));
1790 lenrange[1] = lenrange[0];
1792 else if (sidx < 0)
1793 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1794 else
1796 tree range[2];
1797 get_range_strlen (src, range);
1798 if (range[0])
1800 lenrange[0] = wi::to_wide (range[0], prec);
1801 lenrange[1] = wi::to_wide (range[1], prec);
1803 else
1805 lenrange[0] = wi::shwi (0, prec);
1806 lenrange[1] = wi::shwi (-1, prec);
1810 location_t callloc = gimple_location (stmt);
1811 tree func = gimple_call_fndecl (stmt);
1813 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1815 /* If the longest source string is shorter than the lower bound
1816 of the specified count the copy is definitely nul-terminated. */
1817 if (wi::ltu_p (lenrange[1], cntrange[0]))
1818 return false;
1820 if (wi::neg_p (lenrange[1]))
1822 /* The length of one of the strings is unknown but at least
1823 one has non-zero length and that length is stored in
1824 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1825 warning below. */
1826 lenrange[1] = lenrange[0];
1827 lenrange[0] = wi::shwi (0, prec);
1830 if (wi::geu_p (lenrange[0], cntrange[1]))
1832 /* The shortest string is longer than the upper bound of
1833 the count so the truncation is certain. */
1834 if (cntrange[0] == cntrange[1])
1835 return warning_at (callloc, OPT_Wstringop_truncation,
1836 integer_onep (cnt)
1837 ? G_("%qD output truncated copying %E byte "
1838 "from a string of length %wu")
1839 : G_("%qD output truncated copying %E bytes "
1840 "from a string of length %wu"),
1841 func, cnt, lenrange[0].to_uhwi ());
1843 return warning_at (callloc, OPT_Wstringop_truncation,
1844 "%qD output truncated copying between %wu "
1845 "and %wu bytes from a string of length %wu",
1846 func, cntrange[0].to_uhwi (),
1847 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1849 else if (wi::geu_p (lenrange[1], cntrange[1]))
1851 /* The longest string is longer than the upper bound of
1852 the count so the truncation is possible. */
1853 if (cntrange[0] == cntrange[1])
1854 return warning_at (callloc, OPT_Wstringop_truncation,
1855 integer_onep (cnt)
1856 ? G_("%qD output may be truncated copying %E "
1857 "byte from a string of length %wu")
1858 : G_("%qD output may be truncated copying %E "
1859 "bytes from a string of length %wu"),
1860 func, cnt, lenrange[1].to_uhwi ());
1862 return warning_at (callloc, OPT_Wstringop_truncation,
1863 "%qD output may be truncated copying between %wu "
1864 "and %wu bytes from a string of length %wu",
1865 func, cntrange[0].to_uhwi (),
1866 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1869 if (cntrange[0] != cntrange[1]
1870 && wi::leu_p (cntrange[0], lenrange[0])
1871 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1873 /* If the source (including the terminating nul) is longer than
1874 the lower bound of the specified count but shorter than the
1875 upper bound the copy may (but need not) be truncated. */
1876 return warning_at (callloc, OPT_Wstringop_truncation,
1877 "%qD output may be truncated copying between %wu "
1878 "and %wu bytes from a string of length %wu",
1879 func, cntrange[0].to_uhwi (),
1880 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1884 if (tree dstsize = compute_objsize (dst, 1))
1886 /* The source length is uknown. Try to determine the destination
1887 size and see if it matches the specified bound. If not, bail.
1888 Otherwise go on to see if it should be diagnosed for possible
1889 truncation. */
1890 if (!dstsize)
1891 return false;
1893 if (wi::to_wide (dstsize) != cntrange[1])
1894 return false;
1896 if (cntrange[0] == cntrange[1])
1897 return warning_at (callloc, OPT_Wstringop_truncation,
1898 "%qD specified bound %E equals destination size",
1899 func, cnt);
1902 return false;
1905 /* Check the size argument to the built-in forms of stpncpy and strncpy
1906 to see if it's derived from calling strlen() on the source argument
1907 and if so, issue a warning. */
1909 static void
1910 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
1912 gimple *stmt = gsi_stmt (*gsi);
1914 bool with_bounds = gimple_call_with_bounds_p (stmt);
1916 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1917 tree len = gimple_call_arg (stmt, with_bounds ? 3 : 2);
1919 /* If the length argument was computed from strlen(S) for some string
1920 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
1921 the location of the strlen() call (PSS->SECOND). */
1922 stridx_strlenloc *pss = strlen_to_stridx.get (len);
1923 if (!pss || pss->first <= 0)
1925 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
1926 gimple_set_no_warning (stmt, true);
1928 return;
1931 int sidx = get_stridx (src);
1932 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
1934 /* Strncpy() et al. cannot modify the source string. Prevent the rest
1935 of the pass from invalidating the strinfo data. */
1936 if (sisrc)
1937 sisrc->dont_invalidate = true;
1939 /* Retrieve the strinfo data for the string S that LEN was computed
1940 from as some function F of strlen (S) (i.e., LEN need not be equal
1941 to strlen(S)). */
1942 strinfo *silen = get_strinfo (pss->first);
1944 location_t callloc = gimple_location (stmt);
1946 tree func = gimple_call_fndecl (stmt);
1948 bool warned = false;
1950 /* When -Wstringop-truncation is set, try to determine truncation
1951 before diagnosing possible overflow. Truncation is implied by
1952 the LEN argument being equal to strlen(SRC), regardless of
1953 whether its value is known. Otherwise, issue the more generic
1954 -Wstringop-overflow which triggers for LEN arguments that in
1955 any meaningful way depend on strlen(SRC). */
1956 if (warn_stringop_truncation
1957 && sisrc == silen
1958 && is_strlen_related_p (src, len))
1959 warned = warning_at (callloc, OPT_Wstringop_truncation,
1960 "%qD output truncated before terminating nul "
1961 "copying as many bytes from a string as its length",
1962 func);
1963 else if (silen && is_strlen_related_p (src, silen->ptr))
1964 warned = warning_at (callloc, OPT_Wstringop_overflow_,
1965 "%qD specified bound depends on the length "
1966 "of the source argument", func);
1967 if (warned)
1969 location_t strlenloc = pss->second;
1970 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
1971 inform (strlenloc, "length computed here");
1975 /* Check the size argument to the built-in forms of strncat to see if
1976 it's derived from calling strlen() on the source argument and if so,
1977 issue a warning. */
1979 static void
1980 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1982 /* Same as stxncpy(). */
1983 handle_builtin_stxncpy (bcode, gsi);
1986 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
1987 If strlen of the second argument is known and length of the third argument
1988 is that plus one, strlen of the first argument is the same after this
1989 call. */
1991 static void
1992 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1994 int idx, didx;
1995 tree src, dst, len, lhs, oldlen, newlen;
1996 gimple *stmt = gsi_stmt (*gsi);
1997 strinfo *si, *dsi, *olddsi;
1998 bool with_bounds = gimple_call_with_bounds_p (stmt);
2000 len = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2001 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2002 dst = gimple_call_arg (stmt, 0);
2003 idx = get_stridx (src);
2004 if (idx == 0)
2005 return;
2007 didx = get_stridx (dst);
2008 olddsi = NULL;
2009 if (didx > 0)
2010 olddsi = get_strinfo (didx);
2011 else if (didx < 0)
2012 return;
2014 if (olddsi != NULL
2015 && tree_fits_uhwi_p (len)
2016 && !integer_zerop (len))
2017 adjust_last_stmt (olddsi, stmt, false);
2019 bool full_string_p;
2020 if (idx > 0)
2022 gimple *def_stmt;
2024 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2025 is known. */
2026 si = get_strinfo (idx);
2027 if (si == NULL || si->nonzero_chars == NULL_TREE)
2028 return;
2029 if (TREE_CODE (len) == INTEGER_CST
2030 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2032 if (tree_int_cst_le (len, si->nonzero_chars))
2034 /* Copying LEN nonzero characters, where LEN is constant. */
2035 newlen = len;
2036 full_string_p = false;
2038 else
2040 /* Copying the whole of the analyzed part of SI. */
2041 newlen = si->nonzero_chars;
2042 full_string_p = si->full_string_p;
2045 else
2047 if (!si->full_string_p)
2048 return;
2049 if (TREE_CODE (len) != SSA_NAME)
2050 return;
2051 def_stmt = SSA_NAME_DEF_STMT (len);
2052 if (!is_gimple_assign (def_stmt)
2053 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2054 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2055 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2056 return;
2057 /* Copying variable-length string SI (and no more). */
2058 newlen = si->nonzero_chars;
2059 full_string_p = true;
2062 else
2064 si = NULL;
2065 /* Handle memcpy (x, "abcd", 5) or
2066 memcpy (x, "abc\0uvw", 7). */
2067 if (!tree_fits_uhwi_p (len))
2068 return;
2070 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2071 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2072 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2073 full_string_p = clen > nonzero_chars;
2076 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2077 adjust_last_stmt (olddsi, stmt, false);
2079 if (didx == 0)
2081 didx = new_stridx (dst);
2082 if (didx == 0)
2083 return;
2085 oldlen = NULL_TREE;
2086 if (olddsi != NULL)
2088 dsi = unshare_strinfo (olddsi);
2089 oldlen = olddsi->nonzero_chars;
2090 dsi->nonzero_chars = newlen;
2091 dsi->full_string_p = full_string_p;
2092 /* Break the chain, so adjust_related_strinfo on later pointers in
2093 the chain won't adjust this one anymore. */
2094 dsi->next = 0;
2095 dsi->stmt = NULL;
2096 dsi->endptr = NULL_TREE;
2098 else
2100 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2101 set_strinfo (didx, dsi);
2102 find_equal_ptrs (dst, didx);
2104 dsi->writable = true;
2105 dsi->dont_invalidate = true;
2106 if (olddsi != NULL)
2108 tree adj = NULL_TREE;
2109 location_t loc = gimple_location (stmt);
2110 if (oldlen == NULL_TREE)
2112 else if (integer_zerop (oldlen))
2113 adj = newlen;
2114 else if (TREE_CODE (oldlen) == INTEGER_CST
2115 || TREE_CODE (newlen) == INTEGER_CST)
2116 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2117 fold_convert_loc (loc, TREE_TYPE (newlen),
2118 oldlen));
2119 if (adj != NULL_TREE)
2120 adjust_related_strinfos (loc, dsi, adj);
2121 else
2122 dsi->prev = 0;
2124 /* memcpy src may not overlap dst, so src doesn't need to be
2125 invalidated either. */
2126 if (si != NULL)
2127 si->dont_invalidate = true;
2129 if (full_string_p)
2131 lhs = gimple_call_lhs (stmt);
2132 switch (bcode)
2134 case BUILT_IN_MEMCPY:
2135 case BUILT_IN_MEMCPY_CHK:
2136 case BUILT_IN_MEMCPY_CHKP:
2137 case BUILT_IN_MEMCPY_CHK_CHKP:
2138 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2139 laststmt.stmt = stmt;
2140 laststmt.len = dsi->nonzero_chars;
2141 laststmt.stridx = dsi->idx;
2142 if (lhs)
2143 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2144 break;
2145 case BUILT_IN_MEMPCPY:
2146 case BUILT_IN_MEMPCPY_CHK:
2147 case BUILT_IN_MEMPCPY_CHKP:
2148 case BUILT_IN_MEMPCPY_CHK_CHKP:
2149 break;
2150 default:
2151 gcc_unreachable ();
2156 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2157 If strlen of the second argument is known, strlen of the first argument
2158 is increased by the length of the second argument. Furthermore, attempt
2159 to convert it to memcpy/strcpy if the length of the first argument
2160 is known. */
2162 static void
2163 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2165 int idx, didx;
2166 tree src, dst, srclen, dstlen, len, lhs, args, type, fn, objsz, endptr;
2167 bool success;
2168 gimple *stmt = gsi_stmt (*gsi);
2169 strinfo *si, *dsi;
2170 location_t loc;
2171 bool with_bounds = gimple_call_with_bounds_p (stmt);
2173 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2174 dst = gimple_call_arg (stmt, 0);
2175 lhs = gimple_call_lhs (stmt);
2177 didx = get_stridx (dst);
2178 if (didx < 0)
2179 return;
2181 dsi = NULL;
2182 if (didx > 0)
2183 dsi = get_strinfo (didx);
2184 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2186 /* strcat (p, q) can be transformed into
2187 tmp = p + strlen (p); endptr = strpcpy (tmp, q);
2188 with length endptr - p if we need to compute the length
2189 later on. Don't do this transformation if we don't need
2190 it. */
2191 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2193 if (didx == 0)
2195 didx = new_stridx (dst);
2196 if (didx == 0)
2197 return;
2199 if (dsi == NULL)
2201 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2202 set_strinfo (didx, dsi);
2203 find_equal_ptrs (dst, didx);
2205 else
2207 dsi = unshare_strinfo (dsi);
2208 dsi->nonzero_chars = NULL_TREE;
2209 dsi->full_string_p = false;
2210 dsi->next = 0;
2211 dsi->endptr = NULL_TREE;
2213 dsi->writable = true;
2214 dsi->stmt = stmt;
2215 dsi->dont_invalidate = true;
2217 return;
2220 srclen = NULL_TREE;
2221 si = NULL;
2222 idx = get_stridx (src);
2223 if (idx < 0)
2224 srclen = build_int_cst (size_type_node, ~idx);
2225 else if (idx > 0)
2227 si = get_strinfo (idx);
2228 if (si != NULL)
2229 srclen = get_string_length (si);
2232 loc = gimple_location (stmt);
2233 dstlen = dsi->nonzero_chars;
2234 endptr = dsi->endptr;
2236 dsi = unshare_strinfo (dsi);
2237 dsi->endptr = NULL_TREE;
2238 dsi->stmt = NULL;
2239 dsi->writable = true;
2241 if (srclen != NULL_TREE)
2243 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2244 TREE_TYPE (dsi->nonzero_chars),
2245 dsi->nonzero_chars, srclen);
2246 gcc_assert (dsi->full_string_p);
2247 adjust_related_strinfos (loc, dsi, srclen);
2248 dsi->dont_invalidate = true;
2250 else
2252 dsi->nonzero_chars = NULL;
2253 dsi->full_string_p = false;
2254 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2255 dsi->dont_invalidate = true;
2258 if (si != NULL)
2259 /* strcat src may not overlap dst, so src doesn't need to be
2260 invalidated either. */
2261 si->dont_invalidate = true;
2263 /* For now. Could remove the lhs from the call and add
2264 lhs = dst; afterwards. */
2265 if (lhs)
2266 return;
2268 fn = NULL_TREE;
2269 objsz = NULL_TREE;
2270 switch (bcode)
2272 case BUILT_IN_STRCAT:
2273 case BUILT_IN_STRCAT_CHKP:
2274 if (srclen != NULL_TREE)
2275 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2276 else
2277 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2278 break;
2279 case BUILT_IN_STRCAT_CHK:
2280 case BUILT_IN_STRCAT_CHK_CHKP:
2281 if (srclen != NULL_TREE)
2282 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2283 else
2284 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2285 objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2286 break;
2287 default:
2288 gcc_unreachable ();
2291 if (fn == NULL_TREE)
2292 return;
2294 len = NULL_TREE;
2295 if (srclen != NULL_TREE)
2297 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2298 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2300 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2301 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2302 build_int_cst (type, 1));
2303 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2304 GSI_SAME_STMT);
2306 if (endptr)
2307 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2308 else
2309 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2310 TREE_TYPE (dst), unshare_expr (dst),
2311 fold_convert_loc (loc, sizetype,
2312 unshare_expr (dstlen)));
2313 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2314 GSI_SAME_STMT);
2315 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2317 fprintf (dump_file, "Optimizing: ");
2318 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2320 if (with_bounds)
2322 fn = chkp_maybe_create_clone (fn)->decl;
2323 if (srclen != NULL_TREE)
2324 success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE),
2325 dst,
2326 gimple_call_arg (stmt, 1),
2327 src,
2328 gimple_call_arg (stmt, 3),
2329 len, objsz);
2330 else
2331 success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE),
2332 dst,
2333 gimple_call_arg (stmt, 1),
2334 src,
2335 gimple_call_arg (stmt, 3),
2336 objsz);
2338 else
2339 if (srclen != NULL_TREE)
2340 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2341 dst, src, len, objsz);
2342 else
2343 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2344 dst, src, objsz);
2345 if (success)
2347 stmt = gsi_stmt (*gsi);
2348 gimple_call_set_with_bounds (stmt, with_bounds);
2349 update_stmt (stmt);
2350 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2352 fprintf (dump_file, "into: ");
2353 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2355 /* If srclen == NULL, note that current string length can be
2356 computed by transforming this strcpy into stpcpy. */
2357 if (srclen == NULL_TREE && dsi->dont_invalidate)
2358 dsi->stmt = stmt;
2359 adjust_last_stmt (dsi, stmt, true);
2360 if (srclen != NULL_TREE)
2362 laststmt.stmt = stmt;
2363 laststmt.len = srclen;
2364 laststmt.stridx = dsi->idx;
2367 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2368 fprintf (dump_file, "not possible.\n");
2371 /* Handle a call to malloc or calloc. */
2373 static void
2374 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2376 gimple *stmt = gsi_stmt (*gsi);
2377 tree lhs = gimple_call_lhs (stmt);
2378 if (lhs == NULL_TREE)
2379 return;
2381 gcc_assert (get_stridx (lhs) == 0);
2382 int idx = new_stridx (lhs);
2383 tree length = NULL_TREE;
2384 if (bcode == BUILT_IN_CALLOC)
2385 length = build_int_cst (size_type_node, 0);
2386 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2387 if (bcode == BUILT_IN_CALLOC)
2388 si->endptr = lhs;
2389 set_strinfo (idx, si);
2390 si->writable = true;
2391 si->stmt = stmt;
2392 si->dont_invalidate = true;
2395 /* Handle a call to memset.
2396 After a call to calloc, memset(,0,) is unnecessary.
2397 memset(malloc(n),0,n) is calloc(n,1). */
2399 static bool
2400 handle_builtin_memset (gimple_stmt_iterator *gsi)
2402 gimple *stmt2 = gsi_stmt (*gsi);
2403 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2404 return true;
2405 tree ptr = gimple_call_arg (stmt2, 0);
2406 int idx1 = get_stridx (ptr);
2407 if (idx1 <= 0)
2408 return true;
2409 strinfo *si1 = get_strinfo (idx1);
2410 if (!si1)
2411 return true;
2412 gimple *stmt1 = si1->stmt;
2413 if (!stmt1 || !is_gimple_call (stmt1))
2414 return true;
2415 tree callee1 = gimple_call_fndecl (stmt1);
2416 if (!valid_builtin_call (stmt1))
2417 return true;
2418 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2419 tree size = gimple_call_arg (stmt2, 2);
2420 if (code1 == BUILT_IN_CALLOC)
2421 /* Not touching stmt1 */ ;
2422 else if (code1 == BUILT_IN_MALLOC
2423 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2425 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2426 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2427 size, build_one_cst (size_type_node));
2428 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2429 si1->full_string_p = true;
2430 si1->stmt = gsi_stmt (gsi1);
2432 else
2433 return true;
2434 tree lhs = gimple_call_lhs (stmt2);
2435 unlink_stmt_vdef (stmt2);
2436 if (lhs)
2438 gimple *assign = gimple_build_assign (lhs, ptr);
2439 gsi_replace (gsi, assign, false);
2441 else
2443 gsi_remove (gsi, true);
2444 release_defs (stmt2);
2447 return false;
2450 /* Handle a call to memcmp. We try to handle small comparisons by
2451 converting them to load and compare, and replacing the call to memcmp
2452 with a __builtin_memcmp_eq call where possible. */
2454 static bool
2455 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2457 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2458 tree res = gimple_call_lhs (stmt2);
2459 tree arg1 = gimple_call_arg (stmt2, 0);
2460 tree arg2 = gimple_call_arg (stmt2, 1);
2461 tree len = gimple_call_arg (stmt2, 2);
2462 unsigned HOST_WIDE_INT leni;
2463 use_operand_p use_p;
2464 imm_use_iterator iter;
2466 if (!res)
2467 return true;
2469 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2471 gimple *ustmt = USE_STMT (use_p);
2473 if (is_gimple_debug (ustmt))
2474 continue;
2475 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2477 gassign *asgn = as_a <gassign *> (ustmt);
2478 tree_code code = gimple_assign_rhs_code (asgn);
2479 if ((code != EQ_EXPR && code != NE_EXPR)
2480 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2481 return true;
2483 else if (gimple_code (ustmt) == GIMPLE_COND)
2485 tree_code code = gimple_cond_code (ustmt);
2486 if ((code != EQ_EXPR && code != NE_EXPR)
2487 || !integer_zerop (gimple_cond_rhs (ustmt)))
2488 return true;
2490 else
2491 return true;
2494 if (tree_fits_uhwi_p (len)
2495 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2496 && pow2p_hwi (leni))
2498 leni *= CHAR_TYPE_SIZE;
2499 unsigned align1 = get_pointer_alignment (arg1);
2500 unsigned align2 = get_pointer_alignment (arg2);
2501 unsigned align = MIN (align1, align2);
2502 scalar_int_mode mode;
2503 if (int_mode_for_size (leni, 1).exists (&mode)
2504 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2506 location_t loc = gimple_location (stmt2);
2507 tree type, off;
2508 type = build_nonstandard_integer_type (leni, 1);
2509 gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type)) == leni);
2510 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2511 ptr_mode, true);
2512 off = build_int_cst (ptrtype, 0);
2513 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2514 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2515 tree tem1 = fold_const_aggregate_ref (arg1);
2516 if (tem1)
2517 arg1 = tem1;
2518 tree tem2 = fold_const_aggregate_ref (arg2);
2519 if (tem2)
2520 arg2 = tem2;
2521 res = fold_convert_loc (loc, TREE_TYPE (res),
2522 fold_build2_loc (loc, NE_EXPR,
2523 boolean_type_node,
2524 arg1, arg2));
2525 gimplify_and_update_call_from_tree (gsi, res);
2526 return false;
2530 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2531 return false;
2534 /* Handle a POINTER_PLUS_EXPR statement.
2535 For p = "abcd" + 2; compute associated length, or if
2536 p = q + off is pointing to a '\0' character of a string, call
2537 zero_length_string on it. */
2539 static void
2540 handle_pointer_plus (gimple_stmt_iterator *gsi)
2542 gimple *stmt = gsi_stmt (*gsi);
2543 tree lhs = gimple_assign_lhs (stmt), off;
2544 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2545 strinfo *si, *zsi;
2547 if (idx == 0)
2548 return;
2550 if (idx < 0)
2552 tree off = gimple_assign_rhs2 (stmt);
2553 if (tree_fits_uhwi_p (off)
2554 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2555 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2556 = ~(~idx - (int) tree_to_uhwi (off));
2557 return;
2560 si = get_strinfo (idx);
2561 if (si == NULL || si->nonzero_chars == NULL_TREE)
2562 return;
2564 off = gimple_assign_rhs2 (stmt);
2565 zsi = NULL;
2566 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2567 zsi = zero_length_string (lhs, si);
2568 else if (TREE_CODE (off) == SSA_NAME)
2570 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2571 if (gimple_assign_single_p (def_stmt)
2572 && si->full_string_p
2573 && operand_equal_p (si->nonzero_chars,
2574 gimple_assign_rhs1 (def_stmt), 0))
2575 zsi = zero_length_string (lhs, si);
2577 if (zsi != NULL
2578 && si->endptr != NULL_TREE
2579 && si->endptr != lhs
2580 && TREE_CODE (si->endptr) == SSA_NAME)
2582 enum tree_code rhs_code
2583 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2584 ? SSA_NAME : NOP_EXPR;
2585 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2586 gcc_assert (gsi_stmt (*gsi) == stmt);
2587 update_stmt (stmt);
2591 /* Handle a single character store. */
2593 static bool
2594 handle_char_store (gimple_stmt_iterator *gsi)
2596 int idx = -1;
2597 strinfo *si = NULL;
2598 gimple *stmt = gsi_stmt (*gsi);
2599 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
2600 tree rhs = gimple_assign_rhs1 (stmt);
2601 unsigned HOST_WIDE_INT offset = 0;
2603 if (TREE_CODE (lhs) == MEM_REF
2604 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
2606 tree mem_offset = TREE_OPERAND (lhs, 1);
2607 if (tree_fits_uhwi_p (mem_offset))
2609 /* Get the strinfo for the base, and use it if it starts with at
2610 least OFFSET nonzero characters. This is trivially true if
2611 OFFSET is zero. */
2612 offset = tree_to_uhwi (mem_offset);
2613 idx = get_stridx (TREE_OPERAND (lhs, 0));
2614 if (idx > 0)
2615 si = get_strinfo (idx);
2616 if (offset == 0)
2617 ssaname = TREE_OPERAND (lhs, 0);
2618 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
2619 return true;
2622 else
2624 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
2625 if (idx > 0)
2626 si = get_strinfo (idx);
2629 bool storing_zero_p = initializer_zerop (rhs);
2630 bool storing_nonzero_p = (!storing_zero_p
2631 && TREE_CODE (rhs) == INTEGER_CST
2632 && integer_nonzerop (rhs));
2634 if (si != NULL)
2636 int cmp = compare_nonzero_chars (si, offset);
2637 gcc_assert (offset == 0 || cmp >= 0);
2638 if (storing_zero_p && cmp == 0 && si->full_string_p)
2640 /* When overwriting a '\0' with a '\0', the store can be removed
2641 if we know it has been stored in the current function. */
2642 if (!stmt_could_throw_p (stmt) && si->writable)
2644 unlink_stmt_vdef (stmt);
2645 release_defs (stmt);
2646 gsi_remove (gsi, true);
2647 return false;
2649 else
2651 si->writable = true;
2652 gsi_next (gsi);
2653 return false;
2656 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2657 and if we aren't storing '\0', we know that the length of the
2658 string and any other zero terminated string in memory remains
2659 the same. In that case we move to the next gimple statement and
2660 return to signal the caller that it shouldn't invalidate anything.
2662 This is benefical for cases like:
2664 char p[20];
2665 void foo (char *q)
2667 strcpy (p, "foobar");
2668 size_t len = strlen (p); // This can be optimized into 6
2669 size_t len2 = strlen (q); // This has to be computed
2670 p[0] = 'X';
2671 size_t len3 = strlen (p); // This can be optimized into 6
2672 size_t len4 = strlen (q); // This can be optimized into len2
2673 bar (len, len2, len3, len4);
2676 else if (storing_nonzero_p && cmp > 0)
2678 gsi_next (gsi);
2679 return false;
2681 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
2683 /* When storing_nonzero_p, we know that the string now starts
2684 with OFFSET + 1 nonzero characters, but don't know whether
2685 there's a following nul terminator.
2687 When storing_zero_p, we know that the string is now OFFSET
2688 characters long.
2690 Otherwise, we're storing an unknown value at offset OFFSET,
2691 so need to clip the nonzero_chars to OFFSET. */
2692 location_t loc = gimple_location (stmt);
2693 tree oldlen = si->nonzero_chars;
2694 if (cmp == 0 && si->full_string_p)
2695 /* We're overwriting the nul terminator with a nonzero or
2696 unknown character. If the previous stmt was a memcpy,
2697 its length may be decreased. */
2698 adjust_last_stmt (si, stmt, false);
2699 si = unshare_strinfo (si);
2700 if (storing_nonzero_p)
2701 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
2702 else
2703 si->nonzero_chars = build_int_cst (size_type_node, offset);
2704 si->full_string_p = storing_zero_p;
2705 if (storing_zero_p
2706 && ssaname
2707 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2708 si->endptr = ssaname;
2709 else
2710 si->endptr = NULL;
2711 si->next = 0;
2712 si->stmt = NULL;
2713 si->writable = true;
2714 si->dont_invalidate = true;
2715 if (oldlen)
2717 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
2718 si->nonzero_chars, oldlen);
2719 adjust_related_strinfos (loc, si, adj);
2721 else
2722 si->prev = 0;
2725 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
2727 if (ssaname)
2728 idx = new_stridx (ssaname);
2729 else
2730 idx = new_addr_stridx (lhs);
2731 if (idx != 0)
2733 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
2734 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
2735 si = new_strinfo (ptr, idx, len, storing_zero_p);
2736 set_strinfo (idx, si);
2737 if (storing_zero_p
2738 && ssaname
2739 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2740 si->endptr = ssaname;
2741 si->dont_invalidate = true;
2742 si->writable = true;
2745 else if (idx == 0
2746 && TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST
2747 && ssaname == NULL_TREE
2748 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
2750 size_t l = strlen (TREE_STRING_POINTER (gimple_assign_rhs1 (stmt)));
2751 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
2752 if (a > 0 && (unsigned HOST_WIDE_INT) a > l)
2754 int idx = new_addr_stridx (lhs);
2755 if (idx != 0)
2757 si = new_strinfo (build_fold_addr_expr (lhs), idx,
2758 build_int_cst (size_type_node, l), true);
2759 set_strinfo (idx, si);
2760 si->dont_invalidate = true;
2765 if (si != NULL && offset == 0 && storing_zero_p)
2767 /* Allow adjust_last_stmt to remove it if the stored '\0'
2768 is immediately overwritten. */
2769 laststmt.stmt = stmt;
2770 laststmt.len = build_int_cst (size_type_node, 1);
2771 laststmt.stridx = si->idx;
2773 return true;
2776 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
2778 static void
2779 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
2781 if (TREE_CODE (rhs1) != SSA_NAME
2782 || TREE_CODE (rhs2) != SSA_NAME)
2783 return;
2785 gimple *call_stmt = NULL;
2786 for (int pass = 0; pass < 2; pass++)
2788 gimple *g = SSA_NAME_DEF_STMT (rhs1);
2789 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
2790 && has_single_use (rhs1)
2791 && gimple_call_arg (g, 0) == rhs2)
2793 call_stmt = g;
2794 break;
2796 std::swap (rhs1, rhs2);
2799 if (call_stmt)
2801 tree arg0 = gimple_call_arg (call_stmt, 0);
2803 if (arg0 == rhs2)
2805 tree arg1 = gimple_call_arg (call_stmt, 1);
2806 tree arg1_len = NULL_TREE;
2807 int idx = get_stridx (arg1);
2809 if (idx)
2811 if (idx < 0)
2812 arg1_len = build_int_cst (size_type_node, ~idx);
2813 else
2815 strinfo *si = get_strinfo (idx);
2816 if (si)
2817 arg1_len = get_string_length (si);
2821 if (arg1_len != NULL_TREE)
2823 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
2824 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
2825 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
2826 arg0, arg1, arg1_len);
2827 tree strncmp_lhs = make_ssa_name (integer_type_node);
2828 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
2829 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
2830 gsi_remove (&gsi, true);
2831 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
2832 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
2834 if (is_gimple_assign (stmt))
2836 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
2838 tree cond = gimple_assign_rhs1 (stmt);
2839 TREE_OPERAND (cond, 0) = strncmp_lhs;
2840 TREE_OPERAND (cond, 1) = zero;
2842 else
2844 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
2845 gimple_assign_set_rhs2 (stmt, zero);
2848 else
2850 gcond *cond = as_a<gcond *> (stmt);
2851 gimple_cond_set_lhs (cond, strncmp_lhs);
2852 gimple_cond_set_rhs (cond, zero);
2854 update_stmt (stmt);
2860 /* Attempt to optimize a single statement at *GSI using string length
2861 knowledge. */
2863 static bool
2864 strlen_optimize_stmt (gimple_stmt_iterator *gsi)
2866 gimple *stmt = gsi_stmt (*gsi);
2868 if (is_gimple_call (stmt))
2870 tree callee = gimple_call_fndecl (stmt);
2871 if (valid_builtin_call (stmt))
2872 switch (DECL_FUNCTION_CODE (callee))
2874 case BUILT_IN_STRLEN:
2875 case BUILT_IN_STRLEN_CHKP:
2876 handle_builtin_strlen (gsi);
2877 break;
2878 case BUILT_IN_STRCHR:
2879 case BUILT_IN_STRCHR_CHKP:
2880 handle_builtin_strchr (gsi);
2881 break;
2882 case BUILT_IN_STRCPY:
2883 case BUILT_IN_STRCPY_CHK:
2884 case BUILT_IN_STPCPY:
2885 case BUILT_IN_STPCPY_CHK:
2886 case BUILT_IN_STRCPY_CHKP:
2887 case BUILT_IN_STRCPY_CHK_CHKP:
2888 case BUILT_IN_STPCPY_CHKP:
2889 case BUILT_IN_STPCPY_CHK_CHKP:
2890 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
2891 break;
2893 case BUILT_IN_STRNCAT:
2894 case BUILT_IN_STRNCAT_CHK:
2895 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
2896 break;
2898 case BUILT_IN_STPNCPY:
2899 case BUILT_IN_STPNCPY_CHK:
2900 case BUILT_IN_STRNCPY:
2901 case BUILT_IN_STRNCPY_CHK:
2902 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
2903 break;
2905 case BUILT_IN_MEMCPY:
2906 case BUILT_IN_MEMCPY_CHK:
2907 case BUILT_IN_MEMPCPY:
2908 case BUILT_IN_MEMPCPY_CHK:
2909 case BUILT_IN_MEMCPY_CHKP:
2910 case BUILT_IN_MEMCPY_CHK_CHKP:
2911 case BUILT_IN_MEMPCPY_CHKP:
2912 case BUILT_IN_MEMPCPY_CHK_CHKP:
2913 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
2914 break;
2915 case BUILT_IN_STRCAT:
2916 case BUILT_IN_STRCAT_CHK:
2917 case BUILT_IN_STRCAT_CHKP:
2918 case BUILT_IN_STRCAT_CHK_CHKP:
2919 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
2920 break;
2921 case BUILT_IN_MALLOC:
2922 case BUILT_IN_CALLOC:
2923 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
2924 break;
2925 case BUILT_IN_MEMSET:
2926 if (!handle_builtin_memset (gsi))
2927 return false;
2928 break;
2929 case BUILT_IN_MEMCMP:
2930 if (!handle_builtin_memcmp (gsi))
2931 return false;
2932 break;
2933 default:
2934 break;
2937 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
2939 tree lhs = gimple_assign_lhs (stmt);
2941 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
2943 if (gimple_assign_single_p (stmt)
2944 || (gimple_assign_cast_p (stmt)
2945 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
2947 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2948 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
2950 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2951 handle_pointer_plus (gsi);
2953 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
2955 enum tree_code code = gimple_assign_rhs_code (stmt);
2956 if (code == COND_EXPR)
2958 tree cond = gimple_assign_rhs1 (stmt);
2959 enum tree_code cond_code = TREE_CODE (cond);
2961 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
2962 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
2963 TREE_OPERAND (cond, 1), stmt);
2965 else if (code == EQ_EXPR || code == NE_EXPR)
2966 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
2967 gimple_assign_rhs2 (stmt), stmt);
2969 tree rhs1 = gimple_assign_rhs1 (stmt);
2970 if (stridx_strlenloc *ps = strlen_to_stridx.get (rhs1))
2971 strlen_to_stridx.put (lhs, *ps);
2973 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
2975 tree type = TREE_TYPE (lhs);
2976 if (TREE_CODE (type) == ARRAY_TYPE)
2977 type = TREE_TYPE (type);
2978 if (TREE_CODE (type) == INTEGER_TYPE
2979 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
2980 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
2982 if (! handle_char_store (gsi))
2983 return false;
2987 else if (gcond *cond = dyn_cast<gcond *> (stmt))
2989 enum tree_code code = gimple_cond_code (cond);
2990 if (code == EQ_EXPR || code == NE_EXPR)
2991 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
2992 gimple_cond_rhs (stmt), stmt);
2995 if (gimple_vdef (stmt))
2996 maybe_invalidate (stmt);
2997 return true;
3000 /* Recursively call maybe_invalidate on stmts that might be executed
3001 in between dombb and current bb and that contain a vdef. Stop when
3002 *count stmts are inspected, or if the whole strinfo vector has
3003 been invalidated. */
3005 static void
3006 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3008 unsigned int i, n = gimple_phi_num_args (phi);
3010 for (i = 0; i < n; i++)
3012 tree vuse = gimple_phi_arg_def (phi, i);
3013 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3014 basic_block bb = gimple_bb (stmt);
3015 if (bb == NULL
3016 || bb == dombb
3017 || !bitmap_set_bit (visited, bb->index)
3018 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3019 continue;
3020 while (1)
3022 if (gimple_code (stmt) == GIMPLE_PHI)
3024 do_invalidate (dombb, stmt, visited, count);
3025 if (*count == 0)
3026 return;
3027 break;
3029 if (--*count == 0)
3030 return;
3031 if (!maybe_invalidate (stmt))
3033 *count = 0;
3034 return;
3036 vuse = gimple_vuse (stmt);
3037 stmt = SSA_NAME_DEF_STMT (vuse);
3038 if (gimple_bb (stmt) != bb)
3040 bb = gimple_bb (stmt);
3041 if (bb == NULL
3042 || bb == dombb
3043 || !bitmap_set_bit (visited, bb->index)
3044 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3045 break;
3051 class strlen_dom_walker : public dom_walker
3053 public:
3054 strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
3056 virtual edge before_dom_children (basic_block);
3057 virtual void after_dom_children (basic_block);
3060 /* Callback for walk_dominator_tree. Attempt to optimize various
3061 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3063 edge
3064 strlen_dom_walker::before_dom_children (basic_block bb)
3066 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3068 if (dombb == NULL)
3069 stridx_to_strinfo = NULL;
3070 else
3072 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3073 if (stridx_to_strinfo)
3075 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3076 gsi_next (&gsi))
3078 gphi *phi = gsi.phi ();
3079 if (virtual_operand_p (gimple_phi_result (phi)))
3081 bitmap visited = BITMAP_ALLOC (NULL);
3082 int count_vdef = 100;
3083 do_invalidate (dombb, phi, visited, &count_vdef);
3084 BITMAP_FREE (visited);
3085 if (count_vdef == 0)
3087 /* If there were too many vdefs in between immediate
3088 dominator and current bb, invalidate everything.
3089 If stridx_to_strinfo has been unshared, we need
3090 to free it, otherwise just set it to NULL. */
3091 if (!strinfo_shared ())
3093 unsigned int i;
3094 strinfo *si;
3096 for (i = 1;
3097 vec_safe_iterate (stridx_to_strinfo, i, &si);
3098 ++i)
3100 free_strinfo (si);
3101 (*stridx_to_strinfo)[i] = NULL;
3104 else
3105 stridx_to_strinfo = NULL;
3107 break;
3113 /* If all PHI arguments have the same string index, the PHI result
3114 has it as well. */
3115 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3116 gsi_next (&gsi))
3118 gphi *phi = gsi.phi ();
3119 tree result = gimple_phi_result (phi);
3120 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3122 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3123 if (idx != 0)
3125 unsigned int i, n = gimple_phi_num_args (phi);
3126 for (i = 1; i < n; i++)
3127 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3128 break;
3129 if (i == n)
3130 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3135 /* Attempt to optimize individual statements. */
3136 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3137 if (strlen_optimize_stmt (&gsi))
3138 gsi_next (&gsi);
3140 bb->aux = stridx_to_strinfo;
3141 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3142 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3143 return NULL;
3146 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3147 owned by the current bb, clear bb->aux. */
3149 void
3150 strlen_dom_walker::after_dom_children (basic_block bb)
3152 if (bb->aux)
3154 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3155 if (vec_safe_length (stridx_to_strinfo)
3156 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3158 unsigned int i;
3159 strinfo *si;
3161 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3162 free_strinfo (si);
3163 vec_free (stridx_to_strinfo);
3165 bb->aux = NULL;
3169 /* Main entry point. */
3171 namespace {
3173 const pass_data pass_data_strlen =
3175 GIMPLE_PASS, /* type */
3176 "strlen", /* name */
3177 OPTGROUP_NONE, /* optinfo_flags */
3178 TV_TREE_STRLEN, /* tv_id */
3179 ( PROP_cfg | PROP_ssa ), /* properties_required */
3180 0, /* properties_provided */
3181 0, /* properties_destroyed */
3182 0, /* todo_flags_start */
3183 0, /* todo_flags_finish */
3186 class pass_strlen : public gimple_opt_pass
3188 public:
3189 pass_strlen (gcc::context *ctxt)
3190 : gimple_opt_pass (pass_data_strlen, ctxt)
3193 /* opt_pass methods: */
3194 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3195 virtual unsigned int execute (function *);
3197 }; // class pass_strlen
3199 unsigned int
3200 pass_strlen::execute (function *fun)
3202 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3203 max_stridx = 1;
3205 calculate_dominance_info (CDI_DOMINATORS);
3207 /* String length optimization is implemented as a walk of the dominator
3208 tree and a forward walk of statements within each block. */
3209 strlen_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
3211 ssa_ver_to_stridx.release ();
3212 strinfo_pool.release ();
3213 if (decl_to_stridxlist_htab)
3215 obstack_free (&stridx_obstack, NULL);
3216 delete decl_to_stridxlist_htab;
3217 decl_to_stridxlist_htab = NULL;
3219 laststmt.stmt = NULL;
3220 laststmt.len = NULL_TREE;
3221 laststmt.stridx = 0;
3223 strlen_to_stridx.empty ();
3225 return 0;
3228 } // anon namespace
3230 gimple_opt_pass *
3231 make_pass_strlen (gcc::context *ctxt)
3233 return new pass_strlen (ctxt);