2018-02-09 Sebastian Perta <sebastian.perta@renesas.com>
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob94ed2bedc03958ddaf919a60e8cd9023a18f7f91
1 /* String length optimization
2 Copyright (C) 2011-2018 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-cfg.h"
43 #include "tree-dfa.h"
44 #include "domwalk.h"
45 #include "tree-ssa-alias.h"
46 #include "tree-ssa-propagate.h"
47 #include "params.h"
48 #include "ipa-chkp.h"
49 #include "tree-hash-traits.h"
50 #include "builtins.h"
51 #include "target.h"
52 #include "diagnostic-core.h"
53 #include "diagnostic.h"
54 #include "intl.h"
55 #include "attribs.h"
56 #include "calls.h"
58 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
59 is an index into strinfo vector, negative value stands for
60 string length of a string literal (~strlen). */
61 static vec<int> ssa_ver_to_stridx;
63 /* Number of currently active string indexes plus one. */
64 static int max_stridx;
66 /* String information record. */
67 struct strinfo
69 /* Number of leading characters that are known to be nonzero. This is
70 also the length of the string if FULL_STRING_P.
72 The values in a list of related string pointers must be consistent;
73 that is, if strinfo B comes X bytes after strinfo A, it must be
74 the case that A->nonzero_chars == X + B->nonzero_chars. */
75 tree nonzero_chars;
76 /* Any of the corresponding pointers for querying alias oracle. */
77 tree ptr;
78 /* This is used for two things:
80 - To record the statement that should be used for delayed length
81 computations. We maintain the invariant that all related strinfos
82 have delayed lengths or none do.
84 - To record the malloc or calloc call that produced this result. */
85 gimple *stmt;
86 /* Pointer to '\0' if known, if NULL, it can be computed as
87 ptr + length. */
88 tree endptr;
89 /* Reference count. Any changes to strinfo entry possibly shared
90 with dominating basic blocks need unshare_strinfo first, except
91 for dont_invalidate which affects only the immediately next
92 maybe_invalidate. */
93 int refcount;
94 /* Copy of index. get_strinfo (si->idx) should return si; */
95 int idx;
96 /* These 3 fields are for chaining related string pointers together.
97 E.g. for
98 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
99 strcpy (c, d); e = c + dl;
100 strinfo(a) -> strinfo(c) -> strinfo(e)
101 All have ->first field equal to strinfo(a)->idx and are doubly
102 chained through prev/next fields. The later strinfos are required
103 to point into the same string with zero or more bytes after
104 the previous pointer and all bytes in between the two pointers
105 must be non-zero. Functions like strcpy or memcpy are supposed
106 to adjust all previous strinfo lengths, but not following strinfo
107 lengths (those are uncertain, usually invalidated during
108 maybe_invalidate, except when the alias oracle knows better).
109 Functions like strcat on the other side adjust the whole
110 related strinfo chain.
111 They are updated lazily, so to use the chain the same first fields
112 and si->prev->next == si->idx needs to be verified. */
113 int first;
114 int next;
115 int prev;
116 /* A flag whether the string is known to be written in the current
117 function. */
118 bool writable;
119 /* A flag for the next maybe_invalidate that this strinfo shouldn't
120 be invalidated. Always cleared by maybe_invalidate. */
121 bool dont_invalidate;
122 /* True if the string is known to be nul-terminated after NONZERO_CHARS
123 characters. False is useful when detecting strings that are built
124 up via successive memcpys. */
125 bool full_string_p;
128 /* Pool for allocating strinfo_struct entries. */
129 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
131 /* Vector mapping positive string indexes to strinfo, for the
132 current basic block. The first pointer in the vector is special,
133 it is either NULL, meaning the vector isn't shared, or it is
134 a basic block pointer to the owner basic_block if shared.
135 If some other bb wants to modify the vector, the vector needs
136 to be unshared first, and only the owner bb is supposed to free it. */
137 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
139 /* One OFFSET->IDX mapping. */
140 struct stridxlist
142 struct stridxlist *next;
143 HOST_WIDE_INT offset;
144 int idx;
147 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
148 struct decl_stridxlist_map
150 struct tree_map_base base;
151 struct stridxlist list;
154 /* Hash table for mapping decls to a chained list of offset -> idx
155 mappings. */
156 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
158 /* Hash table mapping strlen calls to stridx instances describing
159 the calls' arguments. Non-null only when warn_stringop_truncation
160 is non-zero. */
161 typedef std::pair<int, location_t> stridx_strlenloc;
162 static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
164 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
165 static struct obstack stridx_obstack;
167 /* Last memcpy statement if it could be adjusted if the trailing
168 '\0' written is immediately overwritten, or
169 *x = '\0' store that could be removed if it is immediately overwritten. */
170 struct laststmt_struct
172 gimple *stmt;
173 tree len;
174 int stridx;
175 } laststmt;
177 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
178 static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
180 /* Return:
182 - 1 if SI is known to start with more than OFF nonzero characters.
184 - 0 if SI is known to start with OFF nonzero characters,
185 but is not known to start with more.
187 - -1 if SI might not start with OFF nonzero characters. */
189 static inline int
190 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
192 if (si->nonzero_chars
193 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
194 return compare_tree_int (si->nonzero_chars, off);
195 else
196 return -1;
199 /* Return true if SI is known to be a zero-length string. */
201 static inline bool
202 zero_length_string_p (strinfo *si)
204 return si->full_string_p && integer_zerop (si->nonzero_chars);
207 /* Return strinfo vector entry IDX. */
209 static inline strinfo *
210 get_strinfo (int idx)
212 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
213 return NULL;
214 return (*stridx_to_strinfo)[idx];
217 /* Get the next strinfo in the chain after SI, or null if none. */
219 static inline strinfo *
220 get_next_strinfo (strinfo *si)
222 if (si->next == 0)
223 return NULL;
224 strinfo *nextsi = get_strinfo (si->next);
225 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
226 return NULL;
227 return nextsi;
230 /* Helper function for get_stridx. Return the strinfo index of the address
231 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
232 OK to return the index for some X <= &EXP and store &EXP - X in
233 *OFFSET_OUT. */
235 static int
236 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
238 HOST_WIDE_INT off;
239 struct stridxlist *list, *last = NULL;
240 tree base;
242 if (!decl_to_stridxlist_htab)
243 return 0;
245 poly_int64 poff;
246 base = get_addr_base_and_unit_offset (exp, &poff);
247 if (base == NULL || !DECL_P (base) || !poff.is_constant (&off))
248 return 0;
250 list = decl_to_stridxlist_htab->get (base);
251 if (list == NULL)
252 return 0;
256 if (list->offset == off)
258 if (offset_out)
259 *offset_out = 0;
260 return list->idx;
262 if (list->offset > off)
263 return 0;
264 last = list;
265 list = list->next;
267 while (list);
269 if ((offset_out || ptr) && last && last->idx > 0)
271 unsigned HOST_WIDE_INT rel_off
272 = (unsigned HOST_WIDE_INT) off - last->offset;
273 strinfo *si = get_strinfo (last->idx);
274 if (si && compare_nonzero_chars (si, rel_off) >= 0)
276 if (offset_out)
278 *offset_out = rel_off;
279 return last->idx;
281 else
282 return get_stridx_plus_constant (si, rel_off, ptr);
285 return 0;
288 /* Return string index for EXP. */
290 static int
291 get_stridx (tree exp)
293 tree s, o;
295 if (TREE_CODE (exp) == SSA_NAME)
297 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
298 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
299 int i;
300 tree e = exp;
301 HOST_WIDE_INT off = 0;
302 for (i = 0; i < 5; i++)
304 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
305 if (!is_gimple_assign (def_stmt)
306 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
307 return 0;
308 tree rhs1 = gimple_assign_rhs1 (def_stmt);
309 tree rhs2 = gimple_assign_rhs2 (def_stmt);
310 if (TREE_CODE (rhs1) != SSA_NAME
311 || !tree_fits_shwi_p (rhs2))
312 return 0;
313 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
314 if (this_off < 0)
315 return 0;
316 off = (unsigned HOST_WIDE_INT) off + this_off;
317 if (off < 0)
318 return 0;
319 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
321 strinfo *si
322 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
323 if (si && compare_nonzero_chars (si, off) >= 0)
324 return get_stridx_plus_constant (si, off, exp);
326 e = rhs1;
328 return 0;
331 if (TREE_CODE (exp) == ADDR_EXPR)
333 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
334 if (idx != 0)
335 return idx;
338 s = string_constant (exp, &o);
339 if (s != NULL_TREE
340 && (o == NULL_TREE || tree_fits_shwi_p (o))
341 && TREE_STRING_LENGTH (s) > 0)
343 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
344 const char *p = TREE_STRING_POINTER (s);
345 int max = TREE_STRING_LENGTH (s) - 1;
347 if (p[max] == '\0' && offset >= 0 && offset <= max)
348 return ~(int) strlen (p + offset);
350 return 0;
353 /* Return true if strinfo vector is shared with the immediate dominator. */
355 static inline bool
356 strinfo_shared (void)
358 return vec_safe_length (stridx_to_strinfo)
359 && (*stridx_to_strinfo)[0] != NULL;
362 /* Unshare strinfo vector that is shared with the immediate dominator. */
364 static void
365 unshare_strinfo_vec (void)
367 strinfo *si;
368 unsigned int i = 0;
370 gcc_assert (strinfo_shared ());
371 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
372 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
373 if (si != NULL)
374 si->refcount++;
375 (*stridx_to_strinfo)[0] = NULL;
378 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
379 Return a pointer to the location where the string index can
380 be stored (if 0) or is stored, or NULL if this can't be tracked. */
382 static int *
383 addr_stridxptr (tree exp)
385 HOST_WIDE_INT off;
387 poly_int64 poff;
388 tree base = get_addr_base_and_unit_offset (exp, &poff);
389 if (base == NULL_TREE || !DECL_P (base) || !poff.is_constant (&off))
390 return NULL;
392 if (!decl_to_stridxlist_htab)
394 decl_to_stridxlist_htab
395 = new hash_map<tree_decl_hash, stridxlist> (64);
396 gcc_obstack_init (&stridx_obstack);
399 bool existed;
400 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
401 if (existed)
403 int i;
404 stridxlist *before = NULL;
405 for (i = 0; i < 32; i++)
407 if (list->offset == off)
408 return &list->idx;
409 if (list->offset > off && before == NULL)
410 before = list;
411 if (list->next == NULL)
412 break;
413 list = list->next;
415 if (i == 32)
416 return NULL;
417 if (before)
419 list = before;
420 before = XOBNEW (&stridx_obstack, struct stridxlist);
421 *before = *list;
422 list->next = before;
423 list->offset = off;
424 list->idx = 0;
425 return &list->idx;
427 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
428 list = list->next;
431 list->next = NULL;
432 list->offset = off;
433 list->idx = 0;
434 return &list->idx;
437 /* Create a new string index, or return 0 if reached limit. */
439 static int
440 new_stridx (tree exp)
442 int idx;
443 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
444 return 0;
445 if (TREE_CODE (exp) == SSA_NAME)
447 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
448 return 0;
449 idx = max_stridx++;
450 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
451 return idx;
453 if (TREE_CODE (exp) == ADDR_EXPR)
455 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
456 if (pidx != NULL)
458 gcc_assert (*pidx == 0);
459 *pidx = max_stridx++;
460 return *pidx;
463 return 0;
466 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
468 static int
469 new_addr_stridx (tree exp)
471 int *pidx;
472 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
473 return 0;
474 pidx = addr_stridxptr (exp);
475 if (pidx != NULL)
477 gcc_assert (*pidx == 0);
478 *pidx = max_stridx++;
479 return *pidx;
481 return 0;
484 /* Create a new strinfo. */
486 static strinfo *
487 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
489 strinfo *si = strinfo_pool.allocate ();
490 si->nonzero_chars = nonzero_chars;
491 si->ptr = ptr;
492 si->stmt = NULL;
493 si->endptr = NULL_TREE;
494 si->refcount = 1;
495 si->idx = idx;
496 si->first = 0;
497 si->prev = 0;
498 si->next = 0;
499 si->writable = false;
500 si->dont_invalidate = false;
501 si->full_string_p = full_string_p;
502 return si;
505 /* Decrease strinfo refcount and free it if not referenced anymore. */
507 static inline void
508 free_strinfo (strinfo *si)
510 if (si && --si->refcount == 0)
511 strinfo_pool.remove (si);
514 /* Set strinfo in the vector entry IDX to SI. */
516 static inline void
517 set_strinfo (int idx, strinfo *si)
519 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
520 unshare_strinfo_vec ();
521 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
522 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
523 (*stridx_to_strinfo)[idx] = si;
526 /* Return the first strinfo in the related strinfo chain
527 if all strinfos in between belong to the chain, otherwise NULL. */
529 static strinfo *
530 verify_related_strinfos (strinfo *origsi)
532 strinfo *si = origsi, *psi;
534 if (origsi->first == 0)
535 return NULL;
536 for (; si->prev; si = psi)
538 if (si->first != origsi->first)
539 return NULL;
540 psi = get_strinfo (si->prev);
541 if (psi == NULL)
542 return NULL;
543 if (psi->next != si->idx)
544 return NULL;
546 if (si->idx != si->first)
547 return NULL;
548 return si;
551 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
552 Use LOC for folding. */
554 static void
555 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
557 si->endptr = endptr;
558 si->stmt = NULL;
559 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
560 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
561 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
562 end_as_size, start_as_size);
563 si->full_string_p = true;
566 /* Return string length, or NULL if it can't be computed. */
568 static tree
569 get_string_length (strinfo *si)
571 if (si->nonzero_chars)
572 return si->full_string_p ? si->nonzero_chars : NULL;
574 if (si->stmt)
576 gimple *stmt = si->stmt, *lenstmt;
577 bool with_bounds = gimple_call_with_bounds_p (stmt);
578 tree callee, lhs, fn, tem;
579 location_t loc;
580 gimple_stmt_iterator gsi;
582 gcc_assert (is_gimple_call (stmt));
583 callee = gimple_call_fndecl (stmt);
584 gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
585 lhs = gimple_call_lhs (stmt);
586 /* unshare_strinfo is intentionally not called here. The (delayed)
587 transformation of strcpy or strcat into stpcpy is done at the place
588 of the former strcpy/strcat call and so can affect all the strinfos
589 with the same stmt. If they were unshared before and transformation
590 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
591 just compute the right length. */
592 switch (DECL_FUNCTION_CODE (callee))
594 case BUILT_IN_STRCAT:
595 case BUILT_IN_STRCAT_CHK:
596 case BUILT_IN_STRCAT_CHKP:
597 case BUILT_IN_STRCAT_CHK_CHKP:
598 gsi = gsi_for_stmt (stmt);
599 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
600 gcc_assert (lhs == NULL_TREE);
601 tem = unshare_expr (gimple_call_arg (stmt, 0));
602 if (with_bounds)
604 lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl,
605 2, tem, gimple_call_arg (stmt, 1));
606 gimple_call_set_with_bounds (lenstmt, true);
608 else
609 lenstmt = gimple_build_call (fn, 1, tem);
610 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
611 gimple_call_set_lhs (lenstmt, lhs);
612 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
613 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
614 tem = gimple_call_arg (stmt, 0);
615 if (!ptrofftype_p (TREE_TYPE (lhs)))
617 lhs = convert_to_ptrofftype (lhs);
618 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
619 true, GSI_SAME_STMT);
621 lenstmt = gimple_build_assign
622 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
623 POINTER_PLUS_EXPR,tem, lhs);
624 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
625 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
626 lhs = NULL_TREE;
627 /* FALLTHRU */
628 case BUILT_IN_STRCPY:
629 case BUILT_IN_STRCPY_CHK:
630 case BUILT_IN_STRCPY_CHKP:
631 case BUILT_IN_STRCPY_CHK_CHKP:
632 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
633 if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2))
634 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
635 else
636 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
637 if (with_bounds)
638 fn = chkp_maybe_create_clone (fn)->decl;
639 gcc_assert (lhs == NULL_TREE);
640 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
642 fprintf (dump_file, "Optimizing: ");
643 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
645 gimple_call_set_fndecl (stmt, fn);
646 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
647 gimple_call_set_lhs (stmt, lhs);
648 update_stmt (stmt);
649 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
651 fprintf (dump_file, "into: ");
652 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
654 /* FALLTHRU */
655 case BUILT_IN_STPCPY:
656 case BUILT_IN_STPCPY_CHK:
657 case BUILT_IN_STPCPY_CHKP:
658 case BUILT_IN_STPCPY_CHK_CHKP:
659 gcc_assert (lhs != NULL_TREE);
660 loc = gimple_location (stmt);
661 set_endptr_and_length (loc, si, lhs);
662 for (strinfo *chainsi = verify_related_strinfos (si);
663 chainsi != NULL;
664 chainsi = get_next_strinfo (chainsi))
665 if (chainsi->nonzero_chars == NULL)
666 set_endptr_and_length (loc, chainsi, lhs);
667 break;
668 case BUILT_IN_MALLOC:
669 break;
670 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
671 default:
672 gcc_unreachable ();
673 break;
677 return si->nonzero_chars;
680 /* Invalidate string length information for strings whose length
681 might change due to stores in stmt. */
683 static bool
684 maybe_invalidate (gimple *stmt)
686 strinfo *si;
687 unsigned int i;
688 bool nonempty = false;
690 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
691 if (si != NULL)
693 if (!si->dont_invalidate)
695 ao_ref r;
696 /* Do not use si->nonzero_chars. */
697 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
698 if (stmt_may_clobber_ref_p_1 (stmt, &r))
700 set_strinfo (i, NULL);
701 free_strinfo (si);
702 continue;
705 si->dont_invalidate = false;
706 nonempty = true;
708 return nonempty;
711 /* Unshare strinfo record SI, if it has refcount > 1 or
712 if stridx_to_strinfo vector is shared with some other
713 bbs. */
715 static strinfo *
716 unshare_strinfo (strinfo *si)
718 strinfo *nsi;
720 if (si->refcount == 1 && !strinfo_shared ())
721 return si;
723 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
724 nsi->stmt = si->stmt;
725 nsi->endptr = si->endptr;
726 nsi->first = si->first;
727 nsi->prev = si->prev;
728 nsi->next = si->next;
729 nsi->writable = si->writable;
730 set_strinfo (si->idx, nsi);
731 free_strinfo (si);
732 return nsi;
735 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
736 strinfo if there is any. Return it's idx, or 0 if no strinfo has
737 been created. */
739 static int
740 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
741 tree ptr)
743 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
744 return 0;
746 if (compare_nonzero_chars (basesi, off) < 0
747 || !tree_fits_uhwi_p (basesi->nonzero_chars))
748 return 0;
750 unsigned HOST_WIDE_INT nonzero_chars
751 = tree_to_uhwi (basesi->nonzero_chars) - off;
752 strinfo *si = basesi, *chainsi;
753 if (si->first || si->prev || si->next)
754 si = verify_related_strinfos (basesi);
755 if (si == NULL
756 || si->nonzero_chars == NULL_TREE
757 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
758 return 0;
760 if (TREE_CODE (ptr) == SSA_NAME
761 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
762 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
764 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
765 for (chainsi = si; chainsi->next; chainsi = si)
767 si = get_next_strinfo (chainsi);
768 if (si == NULL
769 || si->nonzero_chars == NULL_TREE
770 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
771 break;
772 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
773 if (r != 1)
775 if (r == 0)
777 if (TREE_CODE (ptr) == SSA_NAME)
778 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
779 else
781 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
782 if (pidx != NULL && *pidx == 0)
783 *pidx = si->idx;
785 return si->idx;
787 break;
791 int idx = new_stridx (ptr);
792 if (idx == 0)
793 return 0;
794 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
795 basesi->full_string_p);
796 set_strinfo (idx, si);
797 if (chainsi->next)
799 strinfo *nextsi = unshare_strinfo (get_strinfo (chainsi->next));
800 si->next = nextsi->idx;
801 nextsi->prev = idx;
803 chainsi = unshare_strinfo (chainsi);
804 if (chainsi->first == 0)
805 chainsi->first = chainsi->idx;
806 chainsi->next = idx;
807 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
808 chainsi->endptr = ptr;
809 si->endptr = chainsi->endptr;
810 si->prev = chainsi->idx;
811 si->first = chainsi->first;
812 si->writable = chainsi->writable;
813 return si->idx;
816 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
817 to a zero-length string and if possible chain it to a related strinfo
818 chain whose part is or might be CHAINSI. */
820 static strinfo *
821 zero_length_string (tree ptr, strinfo *chainsi)
823 strinfo *si;
824 int idx;
825 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
826 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
827 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
828 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
830 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
831 return NULL;
832 if (chainsi != NULL)
834 si = verify_related_strinfos (chainsi);
835 if (si)
839 /* We shouldn't mix delayed and non-delayed lengths. */
840 gcc_assert (si->full_string_p);
841 if (si->endptr == NULL_TREE)
843 si = unshare_strinfo (si);
844 si->endptr = ptr;
846 chainsi = si;
847 si = get_next_strinfo (si);
849 while (si != NULL);
850 if (zero_length_string_p (chainsi))
852 if (chainsi->next)
854 chainsi = unshare_strinfo (chainsi);
855 chainsi->next = 0;
857 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
858 return chainsi;
861 else
863 /* We shouldn't mix delayed and non-delayed lengths. */
864 gcc_assert (chainsi->full_string_p);
865 if (chainsi->first || chainsi->prev || chainsi->next)
867 chainsi = unshare_strinfo (chainsi);
868 chainsi->first = 0;
869 chainsi->prev = 0;
870 chainsi->next = 0;
874 idx = new_stridx (ptr);
875 if (idx == 0)
876 return NULL;
877 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
878 set_strinfo (idx, si);
879 si->endptr = ptr;
880 if (chainsi != NULL)
882 chainsi = unshare_strinfo (chainsi);
883 if (chainsi->first == 0)
884 chainsi->first = chainsi->idx;
885 chainsi->next = idx;
886 if (chainsi->endptr == NULL_TREE)
887 chainsi->endptr = ptr;
888 si->prev = chainsi->idx;
889 si->first = chainsi->first;
890 si->writable = chainsi->writable;
892 return si;
895 /* For strinfo ORIGSI whose length has been just updated, adjust other
896 related strinfos so that they match the new ORIGSI. This involves:
898 - adding ADJ to the nonzero_chars fields
899 - copying full_string_p from the new ORIGSI. */
901 static void
902 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
904 strinfo *si = verify_related_strinfos (origsi);
906 if (si == NULL)
907 return;
909 while (1)
911 strinfo *nsi;
913 if (si != origsi)
915 tree tem;
917 si = unshare_strinfo (si);
918 /* We shouldn't see delayed lengths here; the caller must have
919 calculated the old length in order to calculate the
920 adjustment. */
921 gcc_assert (si->nonzero_chars);
922 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
923 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
924 TREE_TYPE (si->nonzero_chars),
925 si->nonzero_chars, tem);
926 si->full_string_p = origsi->full_string_p;
928 si->endptr = NULL_TREE;
929 si->dont_invalidate = true;
931 nsi = get_next_strinfo (si);
932 if (nsi == NULL)
933 return;
934 si = nsi;
938 /* Find if there are other SSA_NAME pointers equal to PTR
939 for which we don't track their string lengths yet. If so, use
940 IDX for them. */
942 static void
943 find_equal_ptrs (tree ptr, int idx)
945 if (TREE_CODE (ptr) != SSA_NAME)
946 return;
947 while (1)
949 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
950 if (!is_gimple_assign (stmt))
951 return;
952 ptr = gimple_assign_rhs1 (stmt);
953 switch (gimple_assign_rhs_code (stmt))
955 case SSA_NAME:
956 break;
957 CASE_CONVERT:
958 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
959 return;
960 if (TREE_CODE (ptr) == SSA_NAME)
961 break;
962 if (TREE_CODE (ptr) != ADDR_EXPR)
963 return;
964 /* FALLTHRU */
965 case ADDR_EXPR:
967 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
968 if (pidx != NULL && *pidx == 0)
969 *pidx = idx;
970 return;
972 default:
973 return;
976 /* We might find an endptr created in this pass. Grow the
977 vector in that case. */
978 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
979 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
981 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
982 return;
983 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
987 /* Return true if STMT is a call to a builtin function with the right
988 arguments and attributes that should be considered for optimization
989 by this pass. */
991 static bool
992 valid_builtin_call (gimple *stmt)
994 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
995 return false;
997 tree callee = gimple_call_fndecl (stmt);
998 switch (DECL_FUNCTION_CODE (callee))
1000 case BUILT_IN_MEMCMP:
1001 case BUILT_IN_MEMCMP_EQ:
1002 case BUILT_IN_STRCHR:
1003 case BUILT_IN_STRCHR_CHKP:
1004 case BUILT_IN_STRLEN:
1005 case BUILT_IN_STRLEN_CHKP:
1006 /* The above functions should be pure. Punt if they aren't. */
1007 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
1008 return false;
1009 break;
1011 case BUILT_IN_CALLOC:
1012 case BUILT_IN_MALLOC:
1013 case BUILT_IN_MEMCPY:
1014 case BUILT_IN_MEMCPY_CHK:
1015 case BUILT_IN_MEMCPY_CHKP:
1016 case BUILT_IN_MEMCPY_CHK_CHKP:
1017 case BUILT_IN_MEMPCPY:
1018 case BUILT_IN_MEMPCPY_CHK:
1019 case BUILT_IN_MEMPCPY_CHKP:
1020 case BUILT_IN_MEMPCPY_CHK_CHKP:
1021 case BUILT_IN_MEMSET:
1022 case BUILT_IN_STPCPY:
1023 case BUILT_IN_STPCPY_CHK:
1024 case BUILT_IN_STPCPY_CHKP:
1025 case BUILT_IN_STPCPY_CHK_CHKP:
1026 case BUILT_IN_STRCAT:
1027 case BUILT_IN_STRCAT_CHK:
1028 case BUILT_IN_STRCAT_CHKP:
1029 case BUILT_IN_STRCAT_CHK_CHKP:
1030 case BUILT_IN_STRCPY:
1031 case BUILT_IN_STRCPY_CHK:
1032 case BUILT_IN_STRCPY_CHKP:
1033 case BUILT_IN_STRCPY_CHK_CHKP:
1034 /* The above functions should be neither const nor pure. Punt if they
1035 aren't. */
1036 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1037 return false;
1038 break;
1040 default:
1041 break;
1044 return true;
1047 /* If the last .MEM setter statement before STMT is
1048 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1049 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1050 just memcpy (x, y, strlen (y)). SI must be the zero length
1051 strinfo. */
1053 static void
1054 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1056 tree vuse, callee, len;
1057 struct laststmt_struct last = laststmt;
1058 strinfo *lastsi, *firstsi;
1059 unsigned len_arg_no = 2;
1061 laststmt.stmt = NULL;
1062 laststmt.len = NULL_TREE;
1063 laststmt.stridx = 0;
1065 if (last.stmt == NULL)
1066 return;
1068 vuse = gimple_vuse (stmt);
1069 if (vuse == NULL_TREE
1070 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1071 || !has_single_use (vuse))
1072 return;
1074 gcc_assert (last.stridx > 0);
1075 lastsi = get_strinfo (last.stridx);
1076 if (lastsi == NULL)
1077 return;
1079 if (lastsi != si)
1081 if (lastsi->first == 0 || lastsi->first != si->first)
1082 return;
1084 firstsi = verify_related_strinfos (si);
1085 if (firstsi == NULL)
1086 return;
1087 while (firstsi != lastsi)
1089 firstsi = get_next_strinfo (firstsi);
1090 if (firstsi == NULL)
1091 return;
1095 if (!is_strcat && !zero_length_string_p (si))
1096 return;
1098 if (is_gimple_assign (last.stmt))
1100 gimple_stmt_iterator gsi;
1102 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1103 return;
1104 if (stmt_could_throw_p (last.stmt))
1105 return;
1106 gsi = gsi_for_stmt (last.stmt);
1107 unlink_stmt_vdef (last.stmt);
1108 release_defs (last.stmt);
1109 gsi_remove (&gsi, true);
1110 return;
1113 if (!valid_builtin_call (last.stmt))
1114 return;
1116 callee = gimple_call_fndecl (last.stmt);
1117 switch (DECL_FUNCTION_CODE (callee))
1119 case BUILT_IN_MEMCPY:
1120 case BUILT_IN_MEMCPY_CHK:
1121 break;
1122 case BUILT_IN_MEMCPY_CHKP:
1123 case BUILT_IN_MEMCPY_CHK_CHKP:
1124 len_arg_no = 4;
1125 break;
1126 default:
1127 return;
1130 len = gimple_call_arg (last.stmt, len_arg_no);
1131 if (tree_fits_uhwi_p (len))
1133 if (!tree_fits_uhwi_p (last.len)
1134 || integer_zerop (len)
1135 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1136 return;
1137 /* Don't adjust the length if it is divisible by 4, it is more efficient
1138 to store the extra '\0' in that case. */
1139 if ((tree_to_uhwi (len) & 3) == 0)
1140 return;
1142 else if (TREE_CODE (len) == SSA_NAME)
1144 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1145 if (!is_gimple_assign (def_stmt)
1146 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1147 || gimple_assign_rhs1 (def_stmt) != last.len
1148 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1149 return;
1151 else
1152 return;
1154 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1155 update_stmt (last.stmt);
1158 /* For an LHS that is an SSA_NAME and for strlen() argument SRC, set
1159 LHS range info to [0, N] if SRC refers to a character array A[N]
1160 with unknown length bounded by N. */
1162 static void
1163 maybe_set_strlen_range (tree lhs, tree src)
1165 if (TREE_CODE (lhs) != SSA_NAME)
1166 return;
1168 if (TREE_CODE (src) == SSA_NAME)
1170 gimple *def = SSA_NAME_DEF_STMT (src);
1171 if (is_gimple_assign (def)
1172 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1173 src = gimple_assign_rhs1 (def);
1176 if (TREE_CODE (src) != ADDR_EXPR)
1177 return;
1179 /* The last array member of a struct can be bigger than its size
1180 suggests if it's treated as a poor-man's flexible array member. */
1181 src = TREE_OPERAND (src, 0);
1182 if (TREE_CODE (TREE_TYPE (src)) != ARRAY_TYPE
1183 || array_at_struct_end_p (src))
1184 return;
1186 tree type = TREE_TYPE (src);
1187 if (tree dom = TYPE_DOMAIN (type))
1188 if (tree maxval = TYPE_MAX_VALUE (dom))
1190 wide_int max = wi::to_wide (maxval);
1191 wide_int min = wi::zero (max.get_precision ());
1192 set_range_info (lhs, VR_RANGE, min, max);
1196 /* Handle a strlen call. If strlen of the argument is known, replace
1197 the strlen call with the known value, otherwise remember that strlen
1198 of the argument is stored in the lhs SSA_NAME. */
1200 static void
1201 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1203 int idx;
1204 tree src;
1205 gimple *stmt = gsi_stmt (*gsi);
1206 tree lhs = gimple_call_lhs (stmt);
1208 if (lhs == NULL_TREE)
1209 return;
1211 src = gimple_call_arg (stmt, 0);
1212 idx = get_stridx (src);
1213 if (idx)
1215 strinfo *si = NULL;
1216 tree rhs;
1218 if (idx < 0)
1219 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1220 else
1222 rhs = NULL_TREE;
1223 si = get_strinfo (idx);
1224 if (si != NULL)
1225 rhs = get_string_length (si);
1227 if (rhs != NULL_TREE)
1229 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1231 fprintf (dump_file, "Optimizing: ");
1232 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1234 rhs = unshare_expr (rhs);
1235 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1236 rhs = fold_convert_loc (gimple_location (stmt),
1237 TREE_TYPE (lhs), rhs);
1238 if (!update_call_from_tree (gsi, rhs))
1239 gimplify_and_update_call_from_tree (gsi, rhs);
1240 stmt = gsi_stmt (*gsi);
1241 update_stmt (stmt);
1242 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1244 fprintf (dump_file, "into: ");
1245 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1247 if (si != NULL
1248 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1249 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1250 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1252 si = unshare_strinfo (si);
1253 si->nonzero_chars = lhs;
1254 gcc_assert (si->full_string_p);
1257 if (strlen_to_stridx)
1259 location_t loc = gimple_location (stmt);
1260 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1262 return;
1265 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1266 return;
1267 if (idx == 0)
1268 idx = new_stridx (src);
1269 else
1271 strinfo *si = get_strinfo (idx);
1272 if (si != NULL)
1274 if (!si->full_string_p && !si->stmt)
1276 /* Until now we only had a lower bound on the string length.
1277 Install LHS as the actual length. */
1278 si = unshare_strinfo (si);
1279 tree old = si->nonzero_chars;
1280 si->nonzero_chars = lhs;
1281 si->full_string_p = true;
1282 if (TREE_CODE (old) == INTEGER_CST)
1284 location_t loc = gimple_location (stmt);
1285 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1286 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1287 TREE_TYPE (lhs), lhs, old);
1288 adjust_related_strinfos (loc, si, adj);
1290 else
1292 si->first = 0;
1293 si->prev = 0;
1294 si->next = 0;
1297 return;
1300 if (idx)
1302 strinfo *si = new_strinfo (src, idx, lhs, true);
1303 set_strinfo (idx, si);
1304 find_equal_ptrs (src, idx);
1306 /* For SRC that is an array of N elements, set LHS's range
1307 to [0, N]. */
1308 maybe_set_strlen_range (lhs, src);
1310 if (strlen_to_stridx)
1312 location_t loc = gimple_location (stmt);
1313 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1318 /* Handle a strchr call. If strlen of the first argument is known, replace
1319 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1320 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1322 static void
1323 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1325 int idx;
1326 tree src;
1327 gimple *stmt = gsi_stmt (*gsi);
1328 tree lhs = gimple_call_lhs (stmt);
1329 bool with_bounds = gimple_call_with_bounds_p (stmt);
1331 if (lhs == NULL_TREE)
1332 return;
1334 if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1)))
1335 return;
1337 src = gimple_call_arg (stmt, 0);
1338 idx = get_stridx (src);
1339 if (idx)
1341 strinfo *si = NULL;
1342 tree rhs;
1344 if (idx < 0)
1345 rhs = build_int_cst (size_type_node, ~idx);
1346 else
1348 rhs = NULL_TREE;
1349 si = get_strinfo (idx);
1350 if (si != NULL)
1351 rhs = get_string_length (si);
1353 if (rhs != NULL_TREE)
1355 location_t loc = gimple_location (stmt);
1357 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1359 fprintf (dump_file, "Optimizing: ");
1360 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1362 if (si != NULL && si->endptr != NULL_TREE)
1364 rhs = unshare_expr (si->endptr);
1365 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1366 TREE_TYPE (rhs)))
1367 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1369 else
1371 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1372 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1373 TREE_TYPE (src), src, rhs);
1374 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1375 TREE_TYPE (rhs)))
1376 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1378 if (!update_call_from_tree (gsi, rhs))
1379 gimplify_and_update_call_from_tree (gsi, rhs);
1380 stmt = gsi_stmt (*gsi);
1381 update_stmt (stmt);
1382 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1384 fprintf (dump_file, "into: ");
1385 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1387 if (si != NULL
1388 && si->endptr == NULL_TREE
1389 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1391 si = unshare_strinfo (si);
1392 si->endptr = lhs;
1394 zero_length_string (lhs, si);
1395 return;
1398 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1399 return;
1400 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1402 if (idx == 0)
1403 idx = new_stridx (src);
1404 else if (get_strinfo (idx) != NULL)
1406 zero_length_string (lhs, NULL);
1407 return;
1409 if (idx)
1411 location_t loc = gimple_location (stmt);
1412 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1413 tree srcu = fold_convert_loc (loc, size_type_node, src);
1414 tree length = fold_build2_loc (loc, MINUS_EXPR,
1415 size_type_node, lhsu, srcu);
1416 strinfo *si = new_strinfo (src, idx, length, true);
1417 si->endptr = lhs;
1418 set_strinfo (idx, si);
1419 find_equal_ptrs (src, idx);
1420 zero_length_string (lhs, si);
1423 else
1424 zero_length_string (lhs, NULL);
1427 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1428 If strlen of the second argument is known, strlen of the first argument
1429 is the same after this call. Furthermore, attempt to convert it to
1430 memcpy. */
1432 static void
1433 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1435 int idx, didx;
1436 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1437 bool success;
1438 gimple *stmt = gsi_stmt (*gsi);
1439 strinfo *si, *dsi, *olddsi, *zsi;
1440 location_t loc;
1441 bool with_bounds = gimple_call_with_bounds_p (stmt);
1443 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1444 dst = gimple_call_arg (stmt, 0);
1445 lhs = gimple_call_lhs (stmt);
1446 idx = get_stridx (src);
1447 si = NULL;
1448 if (idx > 0)
1449 si = get_strinfo (idx);
1451 didx = get_stridx (dst);
1452 olddsi = NULL;
1453 oldlen = NULL_TREE;
1454 if (didx > 0)
1455 olddsi = get_strinfo (didx);
1456 else if (didx < 0)
1457 return;
1459 if (olddsi != NULL)
1460 adjust_last_stmt (olddsi, stmt, false);
1462 srclen = NULL_TREE;
1463 if (si != NULL)
1464 srclen = get_string_length (si);
1465 else if (idx < 0)
1466 srclen = build_int_cst (size_type_node, ~idx);
1468 loc = gimple_location (stmt);
1469 if (srclen == NULL_TREE)
1470 switch (bcode)
1472 case BUILT_IN_STRCPY:
1473 case BUILT_IN_STRCPY_CHK:
1474 case BUILT_IN_STRCPY_CHKP:
1475 case BUILT_IN_STRCPY_CHK_CHKP:
1476 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1477 return;
1478 break;
1479 case BUILT_IN_STPCPY:
1480 case BUILT_IN_STPCPY_CHK:
1481 case BUILT_IN_STPCPY_CHKP:
1482 case BUILT_IN_STPCPY_CHK_CHKP:
1483 if (lhs == NULL_TREE)
1484 return;
1485 else
1487 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1488 srclen = fold_convert_loc (loc, size_type_node, dst);
1489 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1490 lhsuint, srclen);
1492 break;
1493 default:
1494 gcc_unreachable ();
1497 if (didx == 0)
1499 didx = new_stridx (dst);
1500 if (didx == 0)
1501 return;
1503 if (olddsi != NULL)
1505 oldlen = olddsi->nonzero_chars;
1506 dsi = unshare_strinfo (olddsi);
1507 dsi->nonzero_chars = srclen;
1508 dsi->full_string_p = (srclen != NULL_TREE);
1509 /* Break the chain, so adjust_related_strinfo on later pointers in
1510 the chain won't adjust this one anymore. */
1511 dsi->next = 0;
1512 dsi->stmt = NULL;
1513 dsi->endptr = NULL_TREE;
1515 else
1517 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1518 set_strinfo (didx, dsi);
1519 find_equal_ptrs (dst, didx);
1521 dsi->writable = true;
1522 dsi->dont_invalidate = true;
1524 if (dsi->nonzero_chars == NULL_TREE)
1526 strinfo *chainsi;
1528 /* If string length of src is unknown, use delayed length
1529 computation. If string lenth of dst will be needed, it
1530 can be computed by transforming this strcpy call into
1531 stpcpy and subtracting dst from the return value. */
1533 /* Look for earlier strings whose length could be determined if
1534 this strcpy is turned into an stpcpy. */
1536 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1538 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1540 /* When setting a stmt for delayed length computation
1541 prevent all strinfos through dsi from being
1542 invalidated. */
1543 chainsi = unshare_strinfo (chainsi);
1544 chainsi->stmt = stmt;
1545 chainsi->nonzero_chars = NULL_TREE;
1546 chainsi->full_string_p = false;
1547 chainsi->endptr = NULL_TREE;
1548 chainsi->dont_invalidate = true;
1551 dsi->stmt = stmt;
1553 /* Try to detect overlap before returning. This catches cases
1554 like strcpy (d, d + n) where n is non-constant whose range
1555 is such that (n <= strlen (d) holds).
1557 OLDDSI->NONZERO_chars may have been reset by this point with
1558 oldlen holding it original value. */
1559 if (olddsi && oldlen)
1561 /* Add 1 for the terminating NUL. */
1562 tree type = TREE_TYPE (oldlen);
1563 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1564 build_int_cst (type, 1));
1565 check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
1566 oldlen, NULL_TREE);
1569 return;
1572 if (olddsi != NULL)
1574 tree adj = NULL_TREE;
1575 if (oldlen == NULL_TREE)
1577 else if (integer_zerop (oldlen))
1578 adj = srclen;
1579 else if (TREE_CODE (oldlen) == INTEGER_CST
1580 || TREE_CODE (srclen) == INTEGER_CST)
1581 adj = fold_build2_loc (loc, MINUS_EXPR,
1582 TREE_TYPE (srclen), srclen,
1583 fold_convert_loc (loc, TREE_TYPE (srclen),
1584 oldlen));
1585 if (adj != NULL_TREE)
1586 adjust_related_strinfos (loc, dsi, adj);
1587 else
1588 dsi->prev = 0;
1590 /* strcpy src may not overlap dst, so src doesn't need to be
1591 invalidated either. */
1592 if (si != NULL)
1593 si->dont_invalidate = true;
1595 fn = NULL_TREE;
1596 zsi = NULL;
1597 switch (bcode)
1599 case BUILT_IN_STRCPY:
1600 case BUILT_IN_STRCPY_CHKP:
1601 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1602 if (lhs)
1603 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1604 break;
1605 case BUILT_IN_STRCPY_CHK:
1606 case BUILT_IN_STRCPY_CHK_CHKP:
1607 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1608 if (lhs)
1609 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1610 break;
1611 case BUILT_IN_STPCPY:
1612 case BUILT_IN_STPCPY_CHKP:
1613 /* This would need adjustment of the lhs (subtract one),
1614 or detection that the trailing '\0' doesn't need to be
1615 written, if it will be immediately overwritten.
1616 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1617 if (lhs)
1619 dsi->endptr = lhs;
1620 zsi = zero_length_string (lhs, dsi);
1622 break;
1623 case BUILT_IN_STPCPY_CHK:
1624 case BUILT_IN_STPCPY_CHK_CHKP:
1625 /* This would need adjustment of the lhs (subtract one),
1626 or detection that the trailing '\0' doesn't need to be
1627 written, if it will be immediately overwritten.
1628 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1629 if (lhs)
1631 dsi->endptr = lhs;
1632 zsi = zero_length_string (lhs, dsi);
1634 break;
1635 default:
1636 gcc_unreachable ();
1638 if (zsi != NULL)
1639 zsi->dont_invalidate = true;
1641 if (fn)
1643 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1644 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1646 else
1647 type = size_type_node;
1649 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1650 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1652 /* Set the no-warning bit on the transformed statement? */
1653 bool set_no_warning = false;
1655 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1656 if (si
1657 && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
1658 NULL_TREE, len))
1660 gimple_set_no_warning (stmt, true);
1661 set_no_warning = true;
1664 if (fn == NULL_TREE)
1665 return;
1667 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1668 GSI_SAME_STMT);
1669 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1671 fprintf (dump_file, "Optimizing: ");
1672 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1674 if (with_bounds)
1676 fn = chkp_maybe_create_clone (fn)->decl;
1677 if (gimple_call_num_args (stmt) == 4)
1678 success = update_gimple_call (gsi, fn, 5, dst,
1679 gimple_call_arg (stmt, 1),
1680 src,
1681 gimple_call_arg (stmt, 3),
1682 len);
1683 else
1684 success = update_gimple_call (gsi, fn, 6, dst,
1685 gimple_call_arg (stmt, 1),
1686 src,
1687 gimple_call_arg (stmt, 3),
1688 len,
1689 gimple_call_arg (stmt, 4));
1691 else
1692 if (gimple_call_num_args (stmt) == 2)
1693 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1694 else
1695 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1696 gimple_call_arg (stmt, 2));
1697 if (success)
1699 stmt = gsi_stmt (*gsi);
1700 gimple_call_set_with_bounds (stmt, with_bounds);
1701 update_stmt (stmt);
1702 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1704 fprintf (dump_file, "into: ");
1705 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1707 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1708 laststmt.stmt = stmt;
1709 laststmt.len = srclen;
1710 laststmt.stridx = dsi->idx;
1712 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1713 fprintf (dump_file, "not possible.\n");
1715 if (set_no_warning)
1716 gimple_set_no_warning (stmt, true);
1719 /* Check the size argument to the built-in forms of stpncpy and strncpy
1720 for out-of-bounds offsets or overlapping access, and to see if the
1721 size argument is derived from a call to strlen() on the source argument,
1722 and if so, issue an appropriate warning. */
1724 static void
1725 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1727 /* Same as stxncpy(). */
1728 handle_builtin_stxncpy (bcode, gsi);
1731 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1732 way. LEN can either be an integer expression, or a pointer (to char).
1733 When it is the latter (such as in recursive calls to self) is is
1734 assumed to be the argument in some call to strlen() whose relationship
1735 to SRC is being ascertained. */
1737 static bool
1738 is_strlen_related_p (tree src, tree len)
1740 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1741 && operand_equal_p (src, len, 0))
1742 return true;
1744 if (TREE_CODE (len) != SSA_NAME)
1745 return false;
1747 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1748 if (!def_stmt)
1749 return false;
1751 if (is_gimple_call (def_stmt))
1753 tree func = gimple_call_fndecl (def_stmt);
1754 if (!valid_builtin_call (def_stmt)
1755 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1756 return false;
1758 tree arg = gimple_call_arg (def_stmt, 0);
1759 return is_strlen_related_p (src, arg);
1762 if (!is_gimple_assign (def_stmt))
1763 return false;
1765 tree_code code = gimple_assign_rhs_code (def_stmt);
1766 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1767 tree rhstype = TREE_TYPE (rhs1);
1769 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1770 || (INTEGRAL_TYPE_P (rhstype)
1771 && (code == BIT_AND_EXPR
1772 || code == NOP_EXPR)))
1774 /* Pointer plus (an integer) and integer cast or truncation are
1775 considered among the (potentially) related expressions to strlen.
1776 Others are not. */
1777 return is_strlen_related_p (src, rhs1);
1780 return false;
1783 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1784 bound is a) equal to the size of the destination DST and if so, b)
1785 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1786 and b) does not, warn. Otherwise, do nothing. Return true if
1787 diagnostic has been issued.
1789 The purpose is to diagnose calls to strncpy and stpncpy that do
1790 not nul-terminate the copy while allowing for the idiom where
1791 such a call is immediately followed by setting the last element
1792 to nul, as in:
1793 char a[32];
1794 strncpy (a, s, sizeof a);
1795 a[sizeof a - 1] = '\0';
1798 static bool
1799 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1801 gimple *stmt = gsi_stmt (gsi);
1803 wide_int cntrange[2];
1805 if (TREE_CODE (cnt) == INTEGER_CST)
1806 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1807 else if (TREE_CODE (cnt) == SSA_NAME)
1809 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1810 if (rng == VR_RANGE)
1812 else if (rng == VR_ANTI_RANGE)
1814 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1816 if (wi::ltu_p (cntrange[1], maxobjsize))
1818 cntrange[0] = cntrange[1] + 1;
1819 cntrange[1] = maxobjsize;
1821 else
1823 cntrange[1] = cntrange[0] - 1;
1824 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1827 else
1828 return false;
1830 else
1831 return false;
1833 /* Negative value is the constant string length. If it's less than
1834 the lower bound there is no truncation. */
1835 int sidx = get_stridx (src);
1836 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1837 return false;
1839 tree dst = gimple_call_arg (stmt, 0);
1840 tree dstdecl = dst;
1841 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1842 dstdecl = TREE_OPERAND (dstdecl, 0);
1844 /* If the destination refers to a an array/pointer declared nonstring
1845 return early. */
1846 tree ref = NULL_TREE;
1847 if (get_attr_nonstring_decl (dstdecl, &ref))
1848 return false;
1850 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1851 avoid the truncation warning. */
1852 gsi_next_nondebug (&gsi);
1853 gimple *next_stmt = gsi_stmt (gsi);
1855 if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt))
1857 tree lhs = gimple_assign_lhs (next_stmt);
1858 tree_code code = TREE_CODE (lhs);
1859 if (code == ARRAY_REF || code == MEM_REF)
1860 lhs = TREE_OPERAND (lhs, 0);
1862 tree func = gimple_call_fndecl (stmt);
1863 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1865 tree ret = gimple_call_lhs (stmt);
1866 if (ret && operand_equal_p (ret, lhs, 0))
1867 return false;
1870 /* Determine the base address and offset of the reference,
1871 ignoring the innermost array index. */
1872 if (TREE_CODE (ref) == ARRAY_REF)
1873 ref = TREE_OPERAND (ref, 0);
1875 poly_int64 dstoff;
1876 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1878 poly_int64 lhsoff;
1879 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1880 if (lhsbase
1881 && known_eq (dstoff, lhsoff)
1882 && operand_equal_p (dstbase, lhsbase, 0))
1883 return false;
1886 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1887 wide_int lenrange[2];
1888 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1890 lenrange[0] = (sisrc->nonzero_chars
1891 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1892 ? wi::to_wide (sisrc->nonzero_chars)
1893 : wi::zero (prec));
1894 lenrange[1] = lenrange[0];
1896 else if (sidx < 0)
1897 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1898 else
1900 tree range[2];
1901 get_range_strlen (src, range);
1902 if (range[0] != NULL_TREE
1903 && TREE_CODE (range[0]) == INTEGER_CST
1904 && range[1] != NULL_TREE
1905 && TREE_CODE (range[1]) == INTEGER_CST)
1907 lenrange[0] = wi::to_wide (range[0], prec);
1908 lenrange[1] = wi::to_wide (range[1], prec);
1910 else
1912 lenrange[0] = wi::shwi (0, prec);
1913 lenrange[1] = wi::shwi (-1, prec);
1917 location_t callloc = gimple_location (stmt);
1918 tree func = gimple_call_fndecl (stmt);
1920 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1922 /* If the longest source string is shorter than the lower bound
1923 of the specified count the copy is definitely nul-terminated. */
1924 if (wi::ltu_p (lenrange[1], cntrange[0]))
1925 return false;
1927 if (wi::neg_p (lenrange[1]))
1929 /* The length of one of the strings is unknown but at least
1930 one has non-zero length and that length is stored in
1931 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1932 warning below. */
1933 lenrange[1] = lenrange[0];
1934 lenrange[0] = wi::shwi (0, prec);
1937 if (wi::geu_p (lenrange[0], cntrange[1]))
1939 /* The shortest string is longer than the upper bound of
1940 the count so the truncation is certain. */
1941 if (cntrange[0] == cntrange[1])
1942 return warning_at (callloc, OPT_Wstringop_truncation,
1943 integer_onep (cnt)
1944 ? G_("%qD output truncated copying %E byte "
1945 "from a string of length %wu")
1946 : G_("%qD output truncated copying %E bytes "
1947 "from a string of length %wu"),
1948 func, cnt, lenrange[0].to_uhwi ());
1950 return warning_at (callloc, OPT_Wstringop_truncation,
1951 "%qD output truncated copying between %wu "
1952 "and %wu bytes from a string of length %wu",
1953 func, cntrange[0].to_uhwi (),
1954 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1956 else if (wi::geu_p (lenrange[1], cntrange[1]))
1958 /* The longest string is longer than the upper bound of
1959 the count so the truncation is possible. */
1960 if (cntrange[0] == cntrange[1])
1961 return warning_at (callloc, OPT_Wstringop_truncation,
1962 integer_onep (cnt)
1963 ? G_("%qD output may be truncated copying %E "
1964 "byte from a string of length %wu")
1965 : G_("%qD output may be truncated copying %E "
1966 "bytes from a string of length %wu"),
1967 func, cnt, lenrange[1].to_uhwi ());
1969 return warning_at (callloc, OPT_Wstringop_truncation,
1970 "%qD output may be truncated copying between %wu "
1971 "and %wu bytes from a string of length %wu",
1972 func, cntrange[0].to_uhwi (),
1973 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1976 if (cntrange[0] != cntrange[1]
1977 && wi::leu_p (cntrange[0], lenrange[0])
1978 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1980 /* If the source (including the terminating nul) is longer than
1981 the lower bound of the specified count but shorter than the
1982 upper bound the copy may (but need not) be truncated. */
1983 return warning_at (callloc, OPT_Wstringop_truncation,
1984 "%qD output may be truncated copying between %wu "
1985 "and %wu bytes from a string of length %wu",
1986 func, cntrange[0].to_uhwi (),
1987 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1991 if (tree dstsize = compute_objsize (dst, 1))
1993 /* The source length is uknown. Try to determine the destination
1994 size and see if it matches the specified bound. If not, bail.
1995 Otherwise go on to see if it should be diagnosed for possible
1996 truncation. */
1997 if (!dstsize)
1998 return false;
2000 if (wi::to_wide (dstsize) != cntrange[1])
2001 return false;
2003 if (cntrange[0] == cntrange[1])
2004 return warning_at (callloc, OPT_Wstringop_truncation,
2005 "%qD specified bound %E equals destination size",
2006 func, cnt);
2009 return false;
2012 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2013 out-of-bounds offsets or overlapping access, and to see if the size
2014 is derived from calling strlen() on the source argument, and if so,
2015 issue the appropriate warning. */
2017 static void
2018 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2020 if (!strlen_to_stridx)
2021 return;
2023 gimple *stmt = gsi_stmt (*gsi);
2025 bool with_bounds = gimple_call_with_bounds_p (stmt);
2027 tree dst = gimple_call_arg (stmt, with_bounds ? 1 : 0);
2028 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2029 tree len = gimple_call_arg (stmt, with_bounds ? 3 : 2);
2030 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2032 int didx = get_stridx (dst);
2033 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2035 /* Compute the size of the destination string including the NUL. */
2036 if (sidst->nonzero_chars)
2038 tree type = TREE_TYPE (sidst->nonzero_chars);
2039 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2040 build_int_cst (type, 1));
2042 dst = sidst->ptr;
2045 int sidx = get_stridx (src);
2046 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2047 if (sisrc)
2049 /* strncat() and strncpy() can modify the source string by writing
2050 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2051 clear. */
2053 /* Compute the size of the source string including the NUL. */
2054 if (sisrc->nonzero_chars)
2056 tree type = TREE_TYPE (sisrc->nonzero_chars);
2057 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2058 build_int_cst (type, 1));
2061 src = sisrc->ptr;
2063 else
2064 srcsize = NULL_TREE;
2066 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
2067 dstsize, srcsize))
2069 gimple_set_no_warning (stmt, true);
2070 return;
2073 /* If the length argument was computed from strlen(S) for some string
2074 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2075 the location of the strlen() call (PSS->SECOND). */
2076 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2077 if (!pss || pss->first <= 0)
2079 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2080 gimple_set_no_warning (stmt, true);
2082 return;
2085 /* Retrieve the strinfo data for the string S that LEN was computed
2086 from as some function F of strlen (S) (i.e., LEN need not be equal
2087 to strlen(S)). */
2088 strinfo *silen = get_strinfo (pss->first);
2090 location_t callloc = gimple_location (stmt);
2092 tree func = gimple_call_fndecl (stmt);
2094 bool warned = false;
2096 /* When -Wstringop-truncation is set, try to determine truncation
2097 before diagnosing possible overflow. Truncation is implied by
2098 the LEN argument being equal to strlen(SRC), regardless of
2099 whether its value is known. Otherwise, issue the more generic
2100 -Wstringop-overflow which triggers for LEN arguments that in
2101 any meaningful way depend on strlen(SRC). */
2102 if (sisrc == silen
2103 && is_strlen_related_p (src, len)
2104 && warning_at (callloc, OPT_Wstringop_truncation,
2105 "%qD output truncated before terminating nul "
2106 "copying as many bytes from a string as its length",
2107 func))
2108 warned = true;
2109 else if (silen && is_strlen_related_p (src, silen->ptr))
2110 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2111 "%qD specified bound depends on the length "
2112 "of the source argument", func);
2113 if (warned)
2115 location_t strlenloc = pss->second;
2116 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2117 inform (strlenloc, "length computed here");
2121 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2122 If strlen of the second argument is known and length of the third argument
2123 is that plus one, strlen of the first argument is the same after this
2124 call. */
2126 static void
2127 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2129 int idx, didx;
2130 tree src, dst, len, lhs, oldlen, newlen;
2131 gimple *stmt = gsi_stmt (*gsi);
2132 strinfo *si, *dsi, *olddsi;
2133 bool with_bounds = gimple_call_with_bounds_p (stmt);
2135 len = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2136 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2137 dst = gimple_call_arg (stmt, 0);
2138 idx = get_stridx (src);
2139 if (idx == 0)
2140 return;
2142 didx = get_stridx (dst);
2143 olddsi = NULL;
2144 if (didx > 0)
2145 olddsi = get_strinfo (didx);
2146 else if (didx < 0)
2147 return;
2149 if (olddsi != NULL
2150 && tree_fits_uhwi_p (len)
2151 && !integer_zerop (len))
2152 adjust_last_stmt (olddsi, stmt, false);
2154 bool full_string_p;
2155 if (idx > 0)
2157 gimple *def_stmt;
2159 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2160 is known. */
2161 si = get_strinfo (idx);
2162 if (si == NULL || si->nonzero_chars == NULL_TREE)
2163 return;
2164 if (TREE_CODE (len) == INTEGER_CST
2165 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2167 if (tree_int_cst_le (len, si->nonzero_chars))
2169 /* Copying LEN nonzero characters, where LEN is constant. */
2170 newlen = len;
2171 full_string_p = false;
2173 else
2175 /* Copying the whole of the analyzed part of SI. */
2176 newlen = si->nonzero_chars;
2177 full_string_p = si->full_string_p;
2180 else
2182 if (!si->full_string_p)
2183 return;
2184 if (TREE_CODE (len) != SSA_NAME)
2185 return;
2186 def_stmt = SSA_NAME_DEF_STMT (len);
2187 if (!is_gimple_assign (def_stmt)
2188 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2189 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2190 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2191 return;
2192 /* Copying variable-length string SI (and no more). */
2193 newlen = si->nonzero_chars;
2194 full_string_p = true;
2197 else
2199 si = NULL;
2200 /* Handle memcpy (x, "abcd", 5) or
2201 memcpy (x, "abc\0uvw", 7). */
2202 if (!tree_fits_uhwi_p (len))
2203 return;
2205 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2206 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2207 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2208 full_string_p = clen > nonzero_chars;
2211 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2212 adjust_last_stmt (olddsi, stmt, false);
2214 if (didx == 0)
2216 didx = new_stridx (dst);
2217 if (didx == 0)
2218 return;
2220 oldlen = NULL_TREE;
2221 if (olddsi != NULL)
2223 dsi = unshare_strinfo (olddsi);
2224 oldlen = olddsi->nonzero_chars;
2225 dsi->nonzero_chars = newlen;
2226 dsi->full_string_p = full_string_p;
2227 /* Break the chain, so adjust_related_strinfo on later pointers in
2228 the chain won't adjust this one anymore. */
2229 dsi->next = 0;
2230 dsi->stmt = NULL;
2231 dsi->endptr = NULL_TREE;
2233 else
2235 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2236 set_strinfo (didx, dsi);
2237 find_equal_ptrs (dst, didx);
2239 dsi->writable = true;
2240 dsi->dont_invalidate = true;
2241 if (olddsi != NULL)
2243 tree adj = NULL_TREE;
2244 location_t loc = gimple_location (stmt);
2245 if (oldlen == NULL_TREE)
2247 else if (integer_zerop (oldlen))
2248 adj = newlen;
2249 else if (TREE_CODE (oldlen) == INTEGER_CST
2250 || TREE_CODE (newlen) == INTEGER_CST)
2251 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2252 fold_convert_loc (loc, TREE_TYPE (newlen),
2253 oldlen));
2254 if (adj != NULL_TREE)
2255 adjust_related_strinfos (loc, dsi, adj);
2256 else
2257 dsi->prev = 0;
2259 /* memcpy src may not overlap dst, so src doesn't need to be
2260 invalidated either. */
2261 if (si != NULL)
2262 si->dont_invalidate = true;
2264 if (full_string_p)
2266 lhs = gimple_call_lhs (stmt);
2267 switch (bcode)
2269 case BUILT_IN_MEMCPY:
2270 case BUILT_IN_MEMCPY_CHK:
2271 case BUILT_IN_MEMCPY_CHKP:
2272 case BUILT_IN_MEMCPY_CHK_CHKP:
2273 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2274 laststmt.stmt = stmt;
2275 laststmt.len = dsi->nonzero_chars;
2276 laststmt.stridx = dsi->idx;
2277 if (lhs)
2278 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2279 break;
2280 case BUILT_IN_MEMPCPY:
2281 case BUILT_IN_MEMPCPY_CHK:
2282 case BUILT_IN_MEMPCPY_CHKP:
2283 case BUILT_IN_MEMPCPY_CHK_CHKP:
2284 break;
2285 default:
2286 gcc_unreachable ();
2291 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2292 If strlen of the second argument is known, strlen of the first argument
2293 is increased by the length of the second argument. Furthermore, attempt
2294 to convert it to memcpy/strcpy if the length of the first argument
2295 is known. */
2297 static void
2298 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2300 int idx, didx;
2301 tree srclen, args, type, fn, objsz, endptr;
2302 bool success;
2303 gimple *stmt = gsi_stmt (*gsi);
2304 strinfo *si, *dsi;
2305 location_t loc = gimple_location (stmt);
2306 bool with_bounds = gimple_call_with_bounds_p (stmt);
2308 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2309 tree dst = gimple_call_arg (stmt, 0);
2311 /* Bail if the source is the same as destination. It will be diagnosed
2312 elsewhere. */
2313 if (operand_equal_p (src, dst, 0))
2314 return;
2316 tree lhs = gimple_call_lhs (stmt);
2318 didx = get_stridx (dst);
2319 if (didx < 0)
2320 return;
2322 dsi = NULL;
2323 if (didx > 0)
2324 dsi = get_strinfo (didx);
2326 srclen = NULL_TREE;
2327 si = NULL;
2328 idx = get_stridx (src);
2329 if (idx < 0)
2330 srclen = build_int_cst (size_type_node, ~idx);
2331 else if (idx > 0)
2333 si = get_strinfo (idx);
2334 if (si != NULL)
2335 srclen = get_string_length (si);
2338 /* Set the no-warning bit on the transformed statement? */
2339 bool set_no_warning = false;
2341 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2344 /* The concatenation always involves copying at least one byte
2345 (the terminating nul), even if the source string is empty.
2346 If the source is unknown assume it's one character long and
2347 used that as both sizes. */
2348 tree slen = srclen;
2349 if (slen)
2351 tree type = TREE_TYPE (slen);
2352 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2355 tree sptr = si && si->ptr ? si->ptr : src;
2357 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2358 NULL_TREE, slen))
2360 gimple_set_no_warning (stmt, true);
2361 set_no_warning = true;
2365 /* strcat (p, q) can be transformed into
2366 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2367 with length endptr - p if we need to compute the length
2368 later on. Don't do this transformation if we don't need
2369 it. */
2370 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2372 if (didx == 0)
2374 didx = new_stridx (dst);
2375 if (didx == 0)
2376 return;
2378 if (dsi == NULL)
2380 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2381 set_strinfo (didx, dsi);
2382 find_equal_ptrs (dst, didx);
2384 else
2386 dsi = unshare_strinfo (dsi);
2387 dsi->nonzero_chars = NULL_TREE;
2388 dsi->full_string_p = false;
2389 dsi->next = 0;
2390 dsi->endptr = NULL_TREE;
2392 dsi->writable = true;
2393 dsi->stmt = stmt;
2394 dsi->dont_invalidate = true;
2396 return;
2399 tree dstlen = dsi->nonzero_chars;
2400 endptr = dsi->endptr;
2402 dsi = unshare_strinfo (dsi);
2403 dsi->endptr = NULL_TREE;
2404 dsi->stmt = NULL;
2405 dsi->writable = true;
2407 if (srclen != NULL_TREE)
2409 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2410 TREE_TYPE (dsi->nonzero_chars),
2411 dsi->nonzero_chars, srclen);
2412 gcc_assert (dsi->full_string_p);
2413 adjust_related_strinfos (loc, dsi, srclen);
2414 dsi->dont_invalidate = true;
2416 else
2418 dsi->nonzero_chars = NULL;
2419 dsi->full_string_p = false;
2420 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2421 dsi->dont_invalidate = true;
2424 if (si != NULL)
2425 /* strcat src may not overlap dst, so src doesn't need to be
2426 invalidated either. */
2427 si->dont_invalidate = true;
2429 /* For now. Could remove the lhs from the call and add
2430 lhs = dst; afterwards. */
2431 if (lhs)
2432 return;
2434 fn = NULL_TREE;
2435 objsz = NULL_TREE;
2436 switch (bcode)
2438 case BUILT_IN_STRCAT:
2439 case BUILT_IN_STRCAT_CHKP:
2440 if (srclen != NULL_TREE)
2441 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2442 else
2443 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2444 break;
2445 case BUILT_IN_STRCAT_CHK:
2446 case BUILT_IN_STRCAT_CHK_CHKP:
2447 if (srclen != NULL_TREE)
2448 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2449 else
2450 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2451 objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2452 break;
2453 default:
2454 gcc_unreachable ();
2457 if (fn == NULL_TREE)
2458 return;
2460 if (dsi && dstlen)
2462 tree type = TREE_TYPE (dstlen);
2464 /* Compute the size of the source sequence, including the nul. */
2465 tree srcsize = srclen ? srclen : size_zero_node;
2466 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2468 tree sptr = si && si->ptr ? si->ptr : src;
2470 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2471 dstlen, srcsize))
2473 gimple_set_no_warning (stmt, true);
2474 set_no_warning = true;
2478 tree len = NULL_TREE;
2479 if (srclen != NULL_TREE)
2481 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2482 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2484 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2485 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2486 build_int_cst (type, 1));
2487 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2488 GSI_SAME_STMT);
2490 if (endptr)
2491 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2492 else
2493 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2494 TREE_TYPE (dst), unshare_expr (dst),
2495 fold_convert_loc (loc, sizetype,
2496 unshare_expr (dstlen)));
2497 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2498 GSI_SAME_STMT);
2499 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2501 fprintf (dump_file, "Optimizing: ");
2502 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2504 if (with_bounds)
2506 fn = chkp_maybe_create_clone (fn)->decl;
2507 if (srclen != NULL_TREE)
2508 success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE),
2509 dst,
2510 gimple_call_arg (stmt, 1),
2511 src,
2512 gimple_call_arg (stmt, 3),
2513 len, objsz);
2514 else
2515 success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE),
2516 dst,
2517 gimple_call_arg (stmt, 1),
2518 src,
2519 gimple_call_arg (stmt, 3),
2520 objsz);
2522 else
2523 if (srclen != NULL_TREE)
2524 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2525 dst, src, len, objsz);
2526 else
2527 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2528 dst, src, objsz);
2529 if (success)
2531 stmt = gsi_stmt (*gsi);
2532 gimple_call_set_with_bounds (stmt, with_bounds);
2533 update_stmt (stmt);
2534 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2536 fprintf (dump_file, "into: ");
2537 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2539 /* If srclen == NULL, note that current string length can be
2540 computed by transforming this strcpy into stpcpy. */
2541 if (srclen == NULL_TREE && dsi->dont_invalidate)
2542 dsi->stmt = stmt;
2543 adjust_last_stmt (dsi, stmt, true);
2544 if (srclen != NULL_TREE)
2546 laststmt.stmt = stmt;
2547 laststmt.len = srclen;
2548 laststmt.stridx = dsi->idx;
2551 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2552 fprintf (dump_file, "not possible.\n");
2554 if (set_no_warning)
2555 gimple_set_no_warning (stmt, true);
2558 /* Handle a call to malloc or calloc. */
2560 static void
2561 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2563 gimple *stmt = gsi_stmt (*gsi);
2564 tree lhs = gimple_call_lhs (stmt);
2565 if (lhs == NULL_TREE)
2566 return;
2568 gcc_assert (get_stridx (lhs) == 0);
2569 int idx = new_stridx (lhs);
2570 tree length = NULL_TREE;
2571 if (bcode == BUILT_IN_CALLOC)
2572 length = build_int_cst (size_type_node, 0);
2573 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2574 if (bcode == BUILT_IN_CALLOC)
2575 si->endptr = lhs;
2576 set_strinfo (idx, si);
2577 si->writable = true;
2578 si->stmt = stmt;
2579 si->dont_invalidate = true;
2582 /* Handle a call to memset.
2583 After a call to calloc, memset(,0,) is unnecessary.
2584 memset(malloc(n),0,n) is calloc(n,1). */
2586 static bool
2587 handle_builtin_memset (gimple_stmt_iterator *gsi)
2589 gimple *stmt2 = gsi_stmt (*gsi);
2590 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2591 return true;
2592 tree ptr = gimple_call_arg (stmt2, 0);
2593 int idx1 = get_stridx (ptr);
2594 if (idx1 <= 0)
2595 return true;
2596 strinfo *si1 = get_strinfo (idx1);
2597 if (!si1)
2598 return true;
2599 gimple *stmt1 = si1->stmt;
2600 if (!stmt1 || !is_gimple_call (stmt1))
2601 return true;
2602 tree callee1 = gimple_call_fndecl (stmt1);
2603 if (!valid_builtin_call (stmt1))
2604 return true;
2605 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2606 tree size = gimple_call_arg (stmt2, 2);
2607 if (code1 == BUILT_IN_CALLOC)
2608 /* Not touching stmt1 */ ;
2609 else if (code1 == BUILT_IN_MALLOC
2610 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2612 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2613 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2614 size, build_one_cst (size_type_node));
2615 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2616 si1->full_string_p = true;
2617 si1->stmt = gsi_stmt (gsi1);
2619 else
2620 return true;
2621 tree lhs = gimple_call_lhs (stmt2);
2622 unlink_stmt_vdef (stmt2);
2623 if (lhs)
2625 gimple *assign = gimple_build_assign (lhs, ptr);
2626 gsi_replace (gsi, assign, false);
2628 else
2630 gsi_remove (gsi, true);
2631 release_defs (stmt2);
2634 return false;
2637 /* Handle a call to memcmp. We try to handle small comparisons by
2638 converting them to load and compare, and replacing the call to memcmp
2639 with a __builtin_memcmp_eq call where possible. */
2641 static bool
2642 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2644 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2645 tree res = gimple_call_lhs (stmt2);
2646 tree arg1 = gimple_call_arg (stmt2, 0);
2647 tree arg2 = gimple_call_arg (stmt2, 1);
2648 tree len = gimple_call_arg (stmt2, 2);
2649 unsigned HOST_WIDE_INT leni;
2650 use_operand_p use_p;
2651 imm_use_iterator iter;
2653 if (!res)
2654 return true;
2656 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2658 gimple *ustmt = USE_STMT (use_p);
2660 if (is_gimple_debug (ustmt))
2661 continue;
2662 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2664 gassign *asgn = as_a <gassign *> (ustmt);
2665 tree_code code = gimple_assign_rhs_code (asgn);
2666 if ((code != EQ_EXPR && code != NE_EXPR)
2667 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2668 return true;
2670 else if (gimple_code (ustmt) == GIMPLE_COND)
2672 tree_code code = gimple_cond_code (ustmt);
2673 if ((code != EQ_EXPR && code != NE_EXPR)
2674 || !integer_zerop (gimple_cond_rhs (ustmt)))
2675 return true;
2677 else
2678 return true;
2681 if (tree_fits_uhwi_p (len)
2682 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2683 && pow2p_hwi (leni))
2685 leni *= CHAR_TYPE_SIZE;
2686 unsigned align1 = get_pointer_alignment (arg1);
2687 unsigned align2 = get_pointer_alignment (arg2);
2688 unsigned align = MIN (align1, align2);
2689 scalar_int_mode mode;
2690 if (int_mode_for_size (leni, 1).exists (&mode)
2691 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2693 location_t loc = gimple_location (stmt2);
2694 tree type, off;
2695 type = build_nonstandard_integer_type (leni, 1);
2696 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
2697 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2698 ptr_mode, true);
2699 off = build_int_cst (ptrtype, 0);
2700 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2701 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2702 tree tem1 = fold_const_aggregate_ref (arg1);
2703 if (tem1)
2704 arg1 = tem1;
2705 tree tem2 = fold_const_aggregate_ref (arg2);
2706 if (tem2)
2707 arg2 = tem2;
2708 res = fold_convert_loc (loc, TREE_TYPE (res),
2709 fold_build2_loc (loc, NE_EXPR,
2710 boolean_type_node,
2711 arg1, arg2));
2712 gimplify_and_update_call_from_tree (gsi, res);
2713 return false;
2717 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2718 return false;
2721 /* Handle a POINTER_PLUS_EXPR statement.
2722 For p = "abcd" + 2; compute associated length, or if
2723 p = q + off is pointing to a '\0' character of a string, call
2724 zero_length_string on it. */
2726 static void
2727 handle_pointer_plus (gimple_stmt_iterator *gsi)
2729 gimple *stmt = gsi_stmt (*gsi);
2730 tree lhs = gimple_assign_lhs (stmt), off;
2731 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2732 strinfo *si, *zsi;
2734 if (idx == 0)
2735 return;
2737 if (idx < 0)
2739 tree off = gimple_assign_rhs2 (stmt);
2740 if (tree_fits_uhwi_p (off)
2741 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2742 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2743 = ~(~idx - (int) tree_to_uhwi (off));
2744 return;
2747 si = get_strinfo (idx);
2748 if (si == NULL || si->nonzero_chars == NULL_TREE)
2749 return;
2751 off = gimple_assign_rhs2 (stmt);
2752 zsi = NULL;
2753 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2754 zsi = zero_length_string (lhs, si);
2755 else if (TREE_CODE (off) == SSA_NAME)
2757 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2758 if (gimple_assign_single_p (def_stmt)
2759 && si->full_string_p
2760 && operand_equal_p (si->nonzero_chars,
2761 gimple_assign_rhs1 (def_stmt), 0))
2762 zsi = zero_length_string (lhs, si);
2764 if (zsi != NULL
2765 && si->endptr != NULL_TREE
2766 && si->endptr != lhs
2767 && TREE_CODE (si->endptr) == SSA_NAME)
2769 enum tree_code rhs_code
2770 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2771 ? SSA_NAME : NOP_EXPR;
2772 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2773 gcc_assert (gsi_stmt (*gsi) == stmt);
2774 update_stmt (stmt);
2778 /* If RHS, either directly or indirectly, refers to a string of constant
2779 length, return it. Otherwise return a negative value. */
2781 static HOST_WIDE_INT
2782 get_string_cst_length (tree rhs)
2784 if (TREE_CODE (rhs) == MEM_REF
2785 && integer_zerop (TREE_OPERAND (rhs, 1)))
2787 rhs = TREE_OPERAND (rhs, 0);
2788 if (TREE_CODE (rhs) == ADDR_EXPR)
2790 tree rhs_addr = rhs;
2792 rhs = TREE_OPERAND (rhs, 0);
2793 if (TREE_CODE (rhs) != STRING_CST)
2795 int idx = get_stridx (rhs_addr);
2796 if (idx > 0)
2798 strinfo *si = get_strinfo (idx);
2799 if (si
2800 && si->full_string_p
2801 && tree_fits_shwi_p (si->nonzero_chars))
2802 return tree_to_shwi (si->nonzero_chars);
2808 if (TREE_CODE (rhs) == VAR_DECL
2809 && TREE_READONLY (rhs))
2810 rhs = DECL_INITIAL (rhs);
2812 if (rhs && TREE_CODE (rhs) == STRING_CST)
2813 return strlen (TREE_STRING_POINTER (rhs));
2815 return -1;
2818 /* Handle a single character store. */
2820 static bool
2821 handle_char_store (gimple_stmt_iterator *gsi)
2823 int idx = -1;
2824 strinfo *si = NULL;
2825 gimple *stmt = gsi_stmt (*gsi);
2826 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
2827 tree rhs = gimple_assign_rhs1 (stmt);
2828 unsigned HOST_WIDE_INT offset = 0;
2830 if (TREE_CODE (lhs) == MEM_REF
2831 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
2833 tree mem_offset = TREE_OPERAND (lhs, 1);
2834 if (tree_fits_uhwi_p (mem_offset))
2836 /* Get the strinfo for the base, and use it if it starts with at
2837 least OFFSET nonzero characters. This is trivially true if
2838 OFFSET is zero. */
2839 offset = tree_to_uhwi (mem_offset);
2840 idx = get_stridx (TREE_OPERAND (lhs, 0));
2841 if (idx > 0)
2842 si = get_strinfo (idx);
2843 if (offset == 0)
2844 ssaname = TREE_OPERAND (lhs, 0);
2845 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
2846 return true;
2849 else
2851 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
2852 if (idx > 0)
2853 si = get_strinfo (idx);
2856 bool storing_zero_p = initializer_zerop (rhs);
2857 bool storing_nonzero_p = (!storing_zero_p
2858 && TREE_CODE (rhs) == INTEGER_CST
2859 && integer_nonzerop (rhs));
2860 /* Set to the length of the string being assigned if known. */
2861 HOST_WIDE_INT rhslen;
2863 if (si != NULL)
2865 int cmp = compare_nonzero_chars (si, offset);
2866 gcc_assert (offset == 0 || cmp >= 0);
2867 if (storing_zero_p && cmp == 0 && si->full_string_p)
2869 /* When overwriting a '\0' with a '\0', the store can be removed
2870 if we know it has been stored in the current function. */
2871 if (!stmt_could_throw_p (stmt) && si->writable)
2873 unlink_stmt_vdef (stmt);
2874 release_defs (stmt);
2875 gsi_remove (gsi, true);
2876 return false;
2878 else
2880 si->writable = true;
2881 gsi_next (gsi);
2882 return false;
2885 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2886 and if we aren't storing '\0', we know that the length of the
2887 string and any other zero terminated string in memory remains
2888 the same. In that case we move to the next gimple statement and
2889 return to signal the caller that it shouldn't invalidate anything.
2891 This is benefical for cases like:
2893 char p[20];
2894 void foo (char *q)
2896 strcpy (p, "foobar");
2897 size_t len = strlen (p); // This can be optimized into 6
2898 size_t len2 = strlen (q); // This has to be computed
2899 p[0] = 'X';
2900 size_t len3 = strlen (p); // This can be optimized into 6
2901 size_t len4 = strlen (q); // This can be optimized into len2
2902 bar (len, len2, len3, len4);
2905 else if (storing_nonzero_p && cmp > 0)
2907 gsi_next (gsi);
2908 return false;
2910 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
2912 /* When storing_nonzero_p, we know that the string now starts
2913 with OFFSET + 1 nonzero characters, but don't know whether
2914 there's a following nul terminator.
2916 When storing_zero_p, we know that the string is now OFFSET
2917 characters long.
2919 Otherwise, we're storing an unknown value at offset OFFSET,
2920 so need to clip the nonzero_chars to OFFSET. */
2921 location_t loc = gimple_location (stmt);
2922 tree oldlen = si->nonzero_chars;
2923 if (cmp == 0 && si->full_string_p)
2924 /* We're overwriting the nul terminator with a nonzero or
2925 unknown character. If the previous stmt was a memcpy,
2926 its length may be decreased. */
2927 adjust_last_stmt (si, stmt, false);
2928 si = unshare_strinfo (si);
2929 if (storing_nonzero_p)
2930 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
2931 else
2932 si->nonzero_chars = build_int_cst (size_type_node, offset);
2933 si->full_string_p = storing_zero_p;
2934 if (storing_zero_p
2935 && ssaname
2936 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2937 si->endptr = ssaname;
2938 else
2939 si->endptr = NULL;
2940 si->next = 0;
2941 si->stmt = NULL;
2942 si->writable = true;
2943 si->dont_invalidate = true;
2944 if (oldlen)
2946 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
2947 si->nonzero_chars, oldlen);
2948 adjust_related_strinfos (loc, si, adj);
2950 else
2951 si->prev = 0;
2954 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
2956 if (ssaname)
2957 idx = new_stridx (ssaname);
2958 else
2959 idx = new_addr_stridx (lhs);
2960 if (idx != 0)
2962 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
2963 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
2964 si = new_strinfo (ptr, idx, len, storing_zero_p);
2965 set_strinfo (idx, si);
2966 if (storing_zero_p
2967 && ssaname
2968 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2969 si->endptr = ssaname;
2970 si->dont_invalidate = true;
2971 si->writable = true;
2974 else if (idx == 0
2975 && (rhslen = get_string_cst_length (gimple_assign_rhs1 (stmt))) >= 0
2976 && ssaname == NULL_TREE
2977 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
2979 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
2980 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
2982 int idx = new_addr_stridx (lhs);
2983 if (idx != 0)
2985 si = new_strinfo (build_fold_addr_expr (lhs), idx,
2986 build_int_cst (size_type_node, rhslen), true);
2987 set_strinfo (idx, si);
2988 si->dont_invalidate = true;
2993 if (si != NULL && offset == 0 && storing_zero_p)
2995 /* Allow adjust_last_stmt to remove it if the stored '\0'
2996 is immediately overwritten. */
2997 laststmt.stmt = stmt;
2998 laststmt.len = build_int_cst (size_type_node, 1);
2999 laststmt.stridx = si->idx;
3001 return true;
3004 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3006 static void
3007 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3009 if (TREE_CODE (rhs1) != SSA_NAME
3010 || TREE_CODE (rhs2) != SSA_NAME)
3011 return;
3013 gimple *call_stmt = NULL;
3014 for (int pass = 0; pass < 2; pass++)
3016 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3017 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3018 && has_single_use (rhs1)
3019 && gimple_call_arg (g, 0) == rhs2)
3021 call_stmt = g;
3022 break;
3024 std::swap (rhs1, rhs2);
3027 if (call_stmt)
3029 tree arg0 = gimple_call_arg (call_stmt, 0);
3031 if (arg0 == rhs2)
3033 tree arg1 = gimple_call_arg (call_stmt, 1);
3034 tree arg1_len = NULL_TREE;
3035 int idx = get_stridx (arg1);
3037 if (idx)
3039 if (idx < 0)
3040 arg1_len = build_int_cst (size_type_node, ~idx);
3041 else
3043 strinfo *si = get_strinfo (idx);
3044 if (si)
3045 arg1_len = get_string_length (si);
3049 if (arg1_len != NULL_TREE)
3051 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3052 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3054 if (!is_gimple_val (arg1_len))
3056 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3057 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3058 arg1_len);
3059 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3060 arg1_len = arg1_len_tmp;
3063 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3064 arg0, arg1, arg1_len);
3065 tree strncmp_lhs = make_ssa_name (integer_type_node);
3066 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3067 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3068 gsi_remove (&gsi, true);
3069 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3070 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3072 if (is_gimple_assign (stmt))
3074 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3076 tree cond = gimple_assign_rhs1 (stmt);
3077 TREE_OPERAND (cond, 0) = strncmp_lhs;
3078 TREE_OPERAND (cond, 1) = zero;
3080 else
3082 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3083 gimple_assign_set_rhs2 (stmt, zero);
3086 else
3088 gcond *cond = as_a<gcond *> (stmt);
3089 gimple_cond_set_lhs (cond, strncmp_lhs);
3090 gimple_cond_set_rhs (cond, zero);
3092 update_stmt (stmt);
3098 /* Attempt to check for validity of the performed access a single statement
3099 at *GSI using string length knowledge, and to optimize it.
3100 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3101 true. */
3103 static bool
3104 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
3106 gimple *stmt = gsi_stmt (*gsi);
3108 if (is_gimple_call (stmt))
3110 tree callee = gimple_call_fndecl (stmt);
3111 if (valid_builtin_call (stmt))
3112 switch (DECL_FUNCTION_CODE (callee))
3114 case BUILT_IN_STRLEN:
3115 case BUILT_IN_STRLEN_CHKP:
3116 handle_builtin_strlen (gsi);
3117 break;
3118 case BUILT_IN_STRCHR:
3119 case BUILT_IN_STRCHR_CHKP:
3120 handle_builtin_strchr (gsi);
3121 break;
3122 case BUILT_IN_STRCPY:
3123 case BUILT_IN_STRCPY_CHK:
3124 case BUILT_IN_STPCPY:
3125 case BUILT_IN_STPCPY_CHK:
3126 case BUILT_IN_STRCPY_CHKP:
3127 case BUILT_IN_STRCPY_CHK_CHKP:
3128 case BUILT_IN_STPCPY_CHKP:
3129 case BUILT_IN_STPCPY_CHK_CHKP:
3130 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3131 break;
3133 case BUILT_IN_STRNCAT:
3134 case BUILT_IN_STRNCAT_CHK:
3135 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3136 break;
3138 case BUILT_IN_STPNCPY:
3139 case BUILT_IN_STPNCPY_CHK:
3140 case BUILT_IN_STRNCPY:
3141 case BUILT_IN_STRNCPY_CHK:
3142 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3143 break;
3145 case BUILT_IN_MEMCPY:
3146 case BUILT_IN_MEMCPY_CHK:
3147 case BUILT_IN_MEMPCPY:
3148 case BUILT_IN_MEMPCPY_CHK:
3149 case BUILT_IN_MEMCPY_CHKP:
3150 case BUILT_IN_MEMCPY_CHK_CHKP:
3151 case BUILT_IN_MEMPCPY_CHKP:
3152 case BUILT_IN_MEMPCPY_CHK_CHKP:
3153 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3154 break;
3155 case BUILT_IN_STRCAT:
3156 case BUILT_IN_STRCAT_CHK:
3157 case BUILT_IN_STRCAT_CHKP:
3158 case BUILT_IN_STRCAT_CHK_CHKP:
3159 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3160 break;
3161 case BUILT_IN_MALLOC:
3162 case BUILT_IN_CALLOC:
3163 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3164 break;
3165 case BUILT_IN_MEMSET:
3166 if (!handle_builtin_memset (gsi))
3167 return false;
3168 break;
3169 case BUILT_IN_MEMCMP:
3170 if (!handle_builtin_memcmp (gsi))
3171 return false;
3172 break;
3173 default:
3174 break;
3177 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3179 tree lhs = gimple_assign_lhs (stmt);
3181 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3183 if (gimple_assign_single_p (stmt)
3184 || (gimple_assign_cast_p (stmt)
3185 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3187 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3188 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3190 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3191 handle_pointer_plus (gsi);
3193 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3195 enum tree_code code = gimple_assign_rhs_code (stmt);
3196 if (code == COND_EXPR)
3198 tree cond = gimple_assign_rhs1 (stmt);
3199 enum tree_code cond_code = TREE_CODE (cond);
3201 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3202 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3203 TREE_OPERAND (cond, 1), stmt);
3205 else if (code == EQ_EXPR || code == NE_EXPR)
3206 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3207 gimple_assign_rhs2 (stmt), stmt);
3208 else if (gimple_assign_load_p (stmt)
3209 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3210 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3211 && (TYPE_PRECISION (TREE_TYPE (lhs))
3212 == TYPE_PRECISION (char_type_node))
3213 && !gimple_has_volatile_ops (stmt))
3215 tree off = integer_zero_node;
3216 unsigned HOST_WIDE_INT coff = 0;
3217 int idx = 0;
3218 tree rhs1 = gimple_assign_rhs1 (stmt);
3219 if (code == MEM_REF)
3221 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3222 if (idx > 0)
3224 strinfo *si = get_strinfo (idx);
3225 if (si
3226 && si->nonzero_chars
3227 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3228 && (wi::to_widest (si->nonzero_chars)
3229 >= wi::to_widest (off)))
3230 off = TREE_OPERAND (rhs1, 1);
3231 else
3232 /* This case is not useful. See if get_addr_stridx
3233 returns something usable. */
3234 idx = 0;
3237 if (idx <= 0)
3238 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3239 if (idx > 0)
3241 strinfo *si = get_strinfo (idx);
3242 if (si
3243 && si->nonzero_chars
3244 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3246 widest_int w1 = wi::to_widest (si->nonzero_chars);
3247 widest_int w2 = wi::to_widest (off) + coff;
3248 if (w1 == w2
3249 && si->full_string_p)
3251 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3253 fprintf (dump_file, "Optimizing: ");
3254 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3257 /* Reading the final '\0' character. */
3258 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3259 gimple_set_vuse (stmt, NULL_TREE);
3260 gimple_assign_set_rhs_from_tree (gsi, zero);
3261 *cleanup_eh
3262 |= maybe_clean_or_replace_eh_stmt (stmt,
3263 gsi_stmt (*gsi));
3264 stmt = gsi_stmt (*gsi);
3265 update_stmt (stmt);
3267 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3269 fprintf (dump_file, "into: ");
3270 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3273 else if (w1 > w2)
3275 /* Reading a character before the final '\0'
3276 character. Just set the value range to ~[0, 0]
3277 if we don't have anything better. */
3278 wide_int min, max;
3279 tree type = TREE_TYPE (lhs);
3280 enum value_range_type vr
3281 = get_range_info (lhs, &min, &max);
3282 if (vr == VR_VARYING
3283 || (vr == VR_RANGE
3284 && min == wi::min_value (TYPE_PRECISION (type),
3285 TYPE_SIGN (type))
3286 && max == wi::max_value (TYPE_PRECISION (type),
3287 TYPE_SIGN (type))))
3288 set_range_info (lhs, VR_ANTI_RANGE,
3289 wi::zero (TYPE_PRECISION (type)),
3290 wi::zero (TYPE_PRECISION (type)));
3296 if (strlen_to_stridx)
3298 tree rhs1 = gimple_assign_rhs1 (stmt);
3299 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3300 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3303 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3305 tree type = TREE_TYPE (lhs);
3306 if (TREE_CODE (type) == ARRAY_TYPE)
3307 type = TREE_TYPE (type);
3308 if (TREE_CODE (type) == INTEGER_TYPE
3309 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3310 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3312 if (! handle_char_store (gsi))
3313 return false;
3317 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3319 enum tree_code code = gimple_cond_code (cond);
3320 if (code == EQ_EXPR || code == NE_EXPR)
3321 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3322 gimple_cond_rhs (stmt), stmt);
3325 if (gimple_vdef (stmt))
3326 maybe_invalidate (stmt);
3327 return true;
3330 /* Recursively call maybe_invalidate on stmts that might be executed
3331 in between dombb and current bb and that contain a vdef. Stop when
3332 *count stmts are inspected, or if the whole strinfo vector has
3333 been invalidated. */
3335 static void
3336 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3338 unsigned int i, n = gimple_phi_num_args (phi);
3340 for (i = 0; i < n; i++)
3342 tree vuse = gimple_phi_arg_def (phi, i);
3343 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3344 basic_block bb = gimple_bb (stmt);
3345 if (bb == NULL
3346 || bb == dombb
3347 || !bitmap_set_bit (visited, bb->index)
3348 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3349 continue;
3350 while (1)
3352 if (gimple_code (stmt) == GIMPLE_PHI)
3354 do_invalidate (dombb, stmt, visited, count);
3355 if (*count == 0)
3356 return;
3357 break;
3359 if (--*count == 0)
3360 return;
3361 if (!maybe_invalidate (stmt))
3363 *count = 0;
3364 return;
3366 vuse = gimple_vuse (stmt);
3367 stmt = SSA_NAME_DEF_STMT (vuse);
3368 if (gimple_bb (stmt) != bb)
3370 bb = gimple_bb (stmt);
3371 if (bb == NULL
3372 || bb == dombb
3373 || !bitmap_set_bit (visited, bb->index)
3374 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3375 break;
3381 class strlen_dom_walker : public dom_walker
3383 public:
3384 strlen_dom_walker (cdi_direction direction)
3385 : dom_walker (direction), m_cleanup_cfg (false)
3388 virtual edge before_dom_children (basic_block);
3389 virtual void after_dom_children (basic_block);
3391 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3392 execute function. */
3393 bool m_cleanup_cfg;
3396 /* Callback for walk_dominator_tree. Attempt to optimize various
3397 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3399 edge
3400 strlen_dom_walker::before_dom_children (basic_block bb)
3402 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3404 if (dombb == NULL)
3405 stridx_to_strinfo = NULL;
3406 else
3408 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3409 if (stridx_to_strinfo)
3411 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3412 gsi_next (&gsi))
3414 gphi *phi = gsi.phi ();
3415 if (virtual_operand_p (gimple_phi_result (phi)))
3417 bitmap visited = BITMAP_ALLOC (NULL);
3418 int count_vdef = 100;
3419 do_invalidate (dombb, phi, visited, &count_vdef);
3420 BITMAP_FREE (visited);
3421 if (count_vdef == 0)
3423 /* If there were too many vdefs in between immediate
3424 dominator and current bb, invalidate everything.
3425 If stridx_to_strinfo has been unshared, we need
3426 to free it, otherwise just set it to NULL. */
3427 if (!strinfo_shared ())
3429 unsigned int i;
3430 strinfo *si;
3432 for (i = 1;
3433 vec_safe_iterate (stridx_to_strinfo, i, &si);
3434 ++i)
3436 free_strinfo (si);
3437 (*stridx_to_strinfo)[i] = NULL;
3440 else
3441 stridx_to_strinfo = NULL;
3443 break;
3449 /* If all PHI arguments have the same string index, the PHI result
3450 has it as well. */
3451 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3452 gsi_next (&gsi))
3454 gphi *phi = gsi.phi ();
3455 tree result = gimple_phi_result (phi);
3456 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3458 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3459 if (idx != 0)
3461 unsigned int i, n = gimple_phi_num_args (phi);
3462 for (i = 1; i < n; i++)
3463 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3464 break;
3465 if (i == n)
3466 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3471 bool cleanup_eh = false;
3473 /* Attempt to optimize individual statements. */
3474 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3475 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
3476 gsi_next (&gsi);
3478 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
3479 m_cleanup_cfg = true;
3481 bb->aux = stridx_to_strinfo;
3482 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3483 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3484 return NULL;
3487 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3488 owned by the current bb, clear bb->aux. */
3490 void
3491 strlen_dom_walker::after_dom_children (basic_block bb)
3493 if (bb->aux)
3495 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3496 if (vec_safe_length (stridx_to_strinfo)
3497 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3499 unsigned int i;
3500 strinfo *si;
3502 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3503 free_strinfo (si);
3504 vec_free (stridx_to_strinfo);
3506 bb->aux = NULL;
3510 /* Main entry point. */
3512 namespace {
3514 const pass_data pass_data_strlen =
3516 GIMPLE_PASS, /* type */
3517 "strlen", /* name */
3518 OPTGROUP_NONE, /* optinfo_flags */
3519 TV_TREE_STRLEN, /* tv_id */
3520 ( PROP_cfg | PROP_ssa ), /* properties_required */
3521 0, /* properties_provided */
3522 0, /* properties_destroyed */
3523 0, /* todo_flags_start */
3524 0, /* todo_flags_finish */
3527 class pass_strlen : public gimple_opt_pass
3529 public:
3530 pass_strlen (gcc::context *ctxt)
3531 : gimple_opt_pass (pass_data_strlen, ctxt)
3534 /* opt_pass methods: */
3535 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3536 virtual unsigned int execute (function *);
3538 }; // class pass_strlen
3540 unsigned int
3541 pass_strlen::execute (function *fun)
3543 gcc_assert (!strlen_to_stridx);
3544 if (warn_stringop_overflow || warn_stringop_truncation)
3545 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3547 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3548 max_stridx = 1;
3550 calculate_dominance_info (CDI_DOMINATORS);
3552 /* String length optimization is implemented as a walk of the dominator
3553 tree and a forward walk of statements within each block. */
3554 strlen_dom_walker walker (CDI_DOMINATORS);
3555 walker.walk (fun->cfg->x_entry_block_ptr);
3557 ssa_ver_to_stridx.release ();
3558 strinfo_pool.release ();
3559 if (decl_to_stridxlist_htab)
3561 obstack_free (&stridx_obstack, NULL);
3562 delete decl_to_stridxlist_htab;
3563 decl_to_stridxlist_htab = NULL;
3565 laststmt.stmt = NULL;
3566 laststmt.len = NULL_TREE;
3567 laststmt.stridx = 0;
3569 if (strlen_to_stridx)
3571 strlen_to_stridx->empty ();
3572 delete strlen_to_stridx;
3573 strlen_to_stridx = NULL;
3576 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
3579 } // anon namespace
3581 gimple_opt_pass *
3582 make_pass_strlen (gcc::context *ctxt)
3584 return new pass_strlen (ctxt);