Fix ICE in lto_symtab_merge_symbols_1 (PR lto/88004).
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob669c315dce2390570b95de928ab8fac1d7467eda
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 "tree-ssa-strlen.h"
48 #include "params.h"
49 #include "tree-hash-traits.h"
50 #include "tree-object-size.h"
51 #include "builtins.h"
52 #include "target.h"
53 #include "diagnostic-core.h"
54 #include "diagnostic.h"
55 #include "intl.h"
56 #include "attribs.h"
57 #include "calls.h"
59 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
60 is an index into strinfo vector, negative value stands for
61 string length of a string literal (~strlen). */
62 static vec<int> ssa_ver_to_stridx;
64 /* Number of currently active string indexes plus one. */
65 static int max_stridx;
67 /* String information record. */
68 struct strinfo
70 /* Number of leading characters that are known to be nonzero. This is
71 also the length of the string if FULL_STRING_P.
73 The values in a list of related string pointers must be consistent;
74 that is, if strinfo B comes X bytes after strinfo A, it must be
75 the case that A->nonzero_chars == X + B->nonzero_chars. */
76 tree nonzero_chars;
77 /* Any of the corresponding pointers for querying alias oracle. */
78 tree ptr;
79 /* This is used for two things:
81 - To record the statement that should be used for delayed length
82 computations. We maintain the invariant that all related strinfos
83 have delayed lengths or none do.
85 - To record the malloc or calloc call that produced this result. */
86 gimple *stmt;
87 /* Pointer to '\0' if known, if NULL, it can be computed as
88 ptr + length. */
89 tree endptr;
90 /* Reference count. Any changes to strinfo entry possibly shared
91 with dominating basic blocks need unshare_strinfo first, except
92 for dont_invalidate which affects only the immediately next
93 maybe_invalidate. */
94 int refcount;
95 /* Copy of index. get_strinfo (si->idx) should return si; */
96 int idx;
97 /* These 3 fields are for chaining related string pointers together.
98 E.g. for
99 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
100 strcpy (c, d); e = c + dl;
101 strinfo(a) -> strinfo(c) -> strinfo(e)
102 All have ->first field equal to strinfo(a)->idx and are doubly
103 chained through prev/next fields. The later strinfos are required
104 to point into the same string with zero or more bytes after
105 the previous pointer and all bytes in between the two pointers
106 must be non-zero. Functions like strcpy or memcpy are supposed
107 to adjust all previous strinfo lengths, but not following strinfo
108 lengths (those are uncertain, usually invalidated during
109 maybe_invalidate, except when the alias oracle knows better).
110 Functions like strcat on the other side adjust the whole
111 related strinfo chain.
112 They are updated lazily, so to use the chain the same first fields
113 and si->prev->next == si->idx needs to be verified. */
114 int first;
115 int next;
116 int prev;
117 /* A flag whether the string is known to be written in the current
118 function. */
119 bool writable;
120 /* A flag for the next maybe_invalidate that this strinfo shouldn't
121 be invalidated. Always cleared by maybe_invalidate. */
122 bool dont_invalidate;
123 /* True if the string is known to be nul-terminated after NONZERO_CHARS
124 characters. False is useful when detecting strings that are built
125 up via successive memcpys. */
126 bool full_string_p;
129 /* Pool for allocating strinfo_struct entries. */
130 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
132 /* Vector mapping positive string indexes to strinfo, for the
133 current basic block. The first pointer in the vector is special,
134 it is either NULL, meaning the vector isn't shared, or it is
135 a basic block pointer to the owner basic_block if shared.
136 If some other bb wants to modify the vector, the vector needs
137 to be unshared first, and only the owner bb is supposed to free it. */
138 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
140 /* One OFFSET->IDX mapping. */
141 struct stridxlist
143 struct stridxlist *next;
144 HOST_WIDE_INT offset;
145 int idx;
148 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
149 struct decl_stridxlist_map
151 struct tree_map_base base;
152 struct stridxlist list;
155 /* Hash table for mapping decls to a chained list of offset -> idx
156 mappings. */
157 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
159 /* Hash table mapping strlen calls to stridx instances describing
160 the calls' arguments. Non-null only when warn_stringop_truncation
161 is non-zero. */
162 typedef std::pair<int, location_t> stridx_strlenloc;
163 static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
165 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
166 static struct obstack stridx_obstack;
168 /* Last memcpy statement if it could be adjusted if the trailing
169 '\0' written is immediately overwritten, or
170 *x = '\0' store that could be removed if it is immediately overwritten. */
171 struct laststmt_struct
173 gimple *stmt;
174 tree len;
175 int stridx;
176 } laststmt;
178 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
179 static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
181 /* Return:
183 - 1 if SI is known to start with more than OFF nonzero characters.
185 - 0 if SI is known to start with OFF nonzero characters,
186 but is not known to start with more.
188 - -1 if SI might not start with OFF nonzero characters. */
190 static inline int
191 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
193 if (si->nonzero_chars
194 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
195 return compare_tree_int (si->nonzero_chars, off);
196 else
197 return -1;
200 /* Return true if SI is known to be a zero-length string. */
202 static inline bool
203 zero_length_string_p (strinfo *si)
205 return si->full_string_p && integer_zerop (si->nonzero_chars);
208 /* Return strinfo vector entry IDX. */
210 static inline strinfo *
211 get_strinfo (int idx)
213 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
214 return NULL;
215 return (*stridx_to_strinfo)[idx];
218 /* Get the next strinfo in the chain after SI, or null if none. */
220 static inline strinfo *
221 get_next_strinfo (strinfo *si)
223 if (si->next == 0)
224 return NULL;
225 strinfo *nextsi = get_strinfo (si->next);
226 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
227 return NULL;
228 return nextsi;
231 /* Helper function for get_stridx. Return the strinfo index of the address
232 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
233 OK to return the index for some X <= &EXP and store &EXP - X in
234 *OFFSET_OUT. */
236 static int
237 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
239 HOST_WIDE_INT off;
240 struct stridxlist *list, *last = NULL;
241 tree base;
243 if (!decl_to_stridxlist_htab)
244 return 0;
246 poly_int64 poff;
247 base = get_addr_base_and_unit_offset (exp, &poff);
248 if (base == NULL || !DECL_P (base) || !poff.is_constant (&off))
249 return 0;
251 list = decl_to_stridxlist_htab->get (base);
252 if (list == NULL)
253 return 0;
257 if (list->offset == off)
259 if (offset_out)
260 *offset_out = 0;
261 return list->idx;
263 if (list->offset > off)
264 return 0;
265 last = list;
266 list = list->next;
268 while (list);
270 if ((offset_out || ptr) && last && last->idx > 0)
272 unsigned HOST_WIDE_INT rel_off
273 = (unsigned HOST_WIDE_INT) off - last->offset;
274 strinfo *si = get_strinfo (last->idx);
275 if (si && compare_nonzero_chars (si, rel_off) >= 0)
277 if (offset_out)
279 *offset_out = rel_off;
280 return last->idx;
282 else
283 return get_stridx_plus_constant (si, rel_off, ptr);
286 return 0;
289 /* Return string index for EXP. */
291 static int
292 get_stridx (tree exp)
294 if (TREE_CODE (exp) == SSA_NAME)
296 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
297 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
298 int i;
299 tree e = exp;
300 HOST_WIDE_INT off = 0;
301 for (i = 0; i < 5; i++)
303 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
304 if (!is_gimple_assign (def_stmt)
305 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
306 return 0;
307 tree rhs1 = gimple_assign_rhs1 (def_stmt);
308 tree rhs2 = gimple_assign_rhs2 (def_stmt);
309 if (TREE_CODE (rhs1) != SSA_NAME
310 || !tree_fits_shwi_p (rhs2))
311 return 0;
312 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
313 if (this_off < 0)
314 return 0;
315 off = (unsigned HOST_WIDE_INT) off + this_off;
316 if (off < 0)
317 return 0;
318 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
320 strinfo *si
321 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
322 if (si && compare_nonzero_chars (si, off) >= 0)
323 return get_stridx_plus_constant (si, off, exp);
325 e = rhs1;
327 return 0;
330 if (TREE_CODE (exp) == ADDR_EXPR)
332 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
333 if (idx != 0)
334 return idx;
337 const char *p = c_getstr (exp);
338 if (p)
339 return ~(int) strlen (p);
341 return 0;
344 /* Return true if strinfo vector is shared with the immediate dominator. */
346 static inline bool
347 strinfo_shared (void)
349 return vec_safe_length (stridx_to_strinfo)
350 && (*stridx_to_strinfo)[0] != NULL;
353 /* Unshare strinfo vector that is shared with the immediate dominator. */
355 static void
356 unshare_strinfo_vec (void)
358 strinfo *si;
359 unsigned int i = 0;
361 gcc_assert (strinfo_shared ());
362 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
363 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
364 if (si != NULL)
365 si->refcount++;
366 (*stridx_to_strinfo)[0] = NULL;
369 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
370 Return a pointer to the location where the string index can
371 be stored (if 0) or is stored, or NULL if this can't be tracked. */
373 static int *
374 addr_stridxptr (tree exp)
376 HOST_WIDE_INT off;
378 poly_int64 poff;
379 tree base = get_addr_base_and_unit_offset (exp, &poff);
380 if (base == NULL_TREE || !DECL_P (base) || !poff.is_constant (&off))
381 return NULL;
383 if (!decl_to_stridxlist_htab)
385 decl_to_stridxlist_htab
386 = new hash_map<tree_decl_hash, stridxlist> (64);
387 gcc_obstack_init (&stridx_obstack);
390 bool existed;
391 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
392 if (existed)
394 int i;
395 stridxlist *before = NULL;
396 for (i = 0; i < 32; i++)
398 if (list->offset == off)
399 return &list->idx;
400 if (list->offset > off && before == NULL)
401 before = list;
402 if (list->next == NULL)
403 break;
404 list = list->next;
406 if (i == 32)
407 return NULL;
408 if (before)
410 list = before;
411 before = XOBNEW (&stridx_obstack, struct stridxlist);
412 *before = *list;
413 list->next = before;
414 list->offset = off;
415 list->idx = 0;
416 return &list->idx;
418 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
419 list = list->next;
422 list->next = NULL;
423 list->offset = off;
424 list->idx = 0;
425 return &list->idx;
428 /* Create a new string index, or return 0 if reached limit. */
430 static int
431 new_stridx (tree exp)
433 int idx;
434 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
435 return 0;
436 if (TREE_CODE (exp) == SSA_NAME)
438 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
439 return 0;
440 idx = max_stridx++;
441 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
442 return idx;
444 if (TREE_CODE (exp) == ADDR_EXPR)
446 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
447 if (pidx != NULL)
449 gcc_assert (*pidx == 0);
450 *pidx = max_stridx++;
451 return *pidx;
454 return 0;
457 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
459 static int
460 new_addr_stridx (tree exp)
462 int *pidx;
463 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
464 return 0;
465 pidx = addr_stridxptr (exp);
466 if (pidx != NULL)
468 gcc_assert (*pidx == 0);
469 *pidx = max_stridx++;
470 return *pidx;
472 return 0;
475 /* Create a new strinfo. */
477 static strinfo *
478 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
480 strinfo *si = strinfo_pool.allocate ();
481 si->nonzero_chars = nonzero_chars;
482 si->ptr = ptr;
483 si->stmt = NULL;
484 si->endptr = NULL_TREE;
485 si->refcount = 1;
486 si->idx = idx;
487 si->first = 0;
488 si->prev = 0;
489 si->next = 0;
490 si->writable = false;
491 si->dont_invalidate = false;
492 si->full_string_p = full_string_p;
493 return si;
496 /* Decrease strinfo refcount and free it if not referenced anymore. */
498 static inline void
499 free_strinfo (strinfo *si)
501 if (si && --si->refcount == 0)
502 strinfo_pool.remove (si);
505 /* Set strinfo in the vector entry IDX to SI. */
507 static inline void
508 set_strinfo (int idx, strinfo *si)
510 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
511 unshare_strinfo_vec ();
512 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
513 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
514 (*stridx_to_strinfo)[idx] = si;
517 /* Return the first strinfo in the related strinfo chain
518 if all strinfos in between belong to the chain, otherwise NULL. */
520 static strinfo *
521 verify_related_strinfos (strinfo *origsi)
523 strinfo *si = origsi, *psi;
525 if (origsi->first == 0)
526 return NULL;
527 for (; si->prev; si = psi)
529 if (si->first != origsi->first)
530 return NULL;
531 psi = get_strinfo (si->prev);
532 if (psi == NULL)
533 return NULL;
534 if (psi->next != si->idx)
535 return NULL;
537 if (si->idx != si->first)
538 return NULL;
539 return si;
542 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
543 Use LOC for folding. */
545 static void
546 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
548 si->endptr = endptr;
549 si->stmt = NULL;
550 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
551 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
552 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
553 end_as_size, start_as_size);
554 si->full_string_p = true;
557 /* Return string length, or NULL if it can't be computed. */
559 static tree
560 get_string_length (strinfo *si)
562 if (si->nonzero_chars)
563 return si->full_string_p ? si->nonzero_chars : NULL;
565 if (si->stmt)
567 gimple *stmt = si->stmt, *lenstmt;
568 tree callee, lhs, fn, tem;
569 location_t loc;
570 gimple_stmt_iterator gsi;
572 gcc_assert (is_gimple_call (stmt));
573 callee = gimple_call_fndecl (stmt);
574 gcc_assert (callee && fndecl_built_in_p (callee, BUILT_IN_NORMAL));
575 lhs = gimple_call_lhs (stmt);
576 /* unshare_strinfo is intentionally not called here. The (delayed)
577 transformation of strcpy or strcat into stpcpy is done at the place
578 of the former strcpy/strcat call and so can affect all the strinfos
579 with the same stmt. If they were unshared before and transformation
580 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
581 just compute the right length. */
582 switch (DECL_FUNCTION_CODE (callee))
584 case BUILT_IN_STRCAT:
585 case BUILT_IN_STRCAT_CHK:
586 gsi = gsi_for_stmt (stmt);
587 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
588 gcc_assert (lhs == NULL_TREE);
589 tem = unshare_expr (gimple_call_arg (stmt, 0));
590 lenstmt = gimple_build_call (fn, 1, tem);
591 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
592 gimple_call_set_lhs (lenstmt, lhs);
593 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
594 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
595 tem = gimple_call_arg (stmt, 0);
596 if (!ptrofftype_p (TREE_TYPE (lhs)))
598 lhs = convert_to_ptrofftype (lhs);
599 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
600 true, GSI_SAME_STMT);
602 lenstmt = gimple_build_assign
603 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
604 POINTER_PLUS_EXPR,tem, lhs);
605 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
606 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
607 lhs = NULL_TREE;
608 /* FALLTHRU */
609 case BUILT_IN_STRCPY:
610 case BUILT_IN_STRCPY_CHK:
611 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
612 if (gimple_call_num_args (stmt) == 2)
613 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
614 else
615 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
616 gcc_assert (lhs == NULL_TREE);
617 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
619 fprintf (dump_file, "Optimizing: ");
620 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
622 gimple_call_set_fndecl (stmt, fn);
623 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
624 gimple_call_set_lhs (stmt, lhs);
625 update_stmt (stmt);
626 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
628 fprintf (dump_file, "into: ");
629 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
631 /* FALLTHRU */
632 case BUILT_IN_STPCPY:
633 case BUILT_IN_STPCPY_CHK:
634 gcc_assert (lhs != NULL_TREE);
635 loc = gimple_location (stmt);
636 set_endptr_and_length (loc, si, lhs);
637 for (strinfo *chainsi = verify_related_strinfos (si);
638 chainsi != NULL;
639 chainsi = get_next_strinfo (chainsi))
640 if (chainsi->nonzero_chars == NULL)
641 set_endptr_and_length (loc, chainsi, lhs);
642 break;
643 case BUILT_IN_MALLOC:
644 break;
645 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
646 default:
647 gcc_unreachable ();
648 break;
652 return si->nonzero_chars;
655 /* Invalidate string length information for strings whose length
656 might change due to stores in stmt. */
658 static bool
659 maybe_invalidate (gimple *stmt)
661 strinfo *si;
662 unsigned int i;
663 bool nonempty = false;
665 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
666 if (si != NULL)
668 if (!si->dont_invalidate)
670 ao_ref r;
671 /* Do not use si->nonzero_chars. */
672 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
673 if (stmt_may_clobber_ref_p_1 (stmt, &r))
675 set_strinfo (i, NULL);
676 free_strinfo (si);
677 continue;
680 si->dont_invalidate = false;
681 nonempty = true;
683 return nonempty;
686 /* Unshare strinfo record SI, if it has refcount > 1 or
687 if stridx_to_strinfo vector is shared with some other
688 bbs. */
690 static strinfo *
691 unshare_strinfo (strinfo *si)
693 strinfo *nsi;
695 if (si->refcount == 1 && !strinfo_shared ())
696 return si;
698 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
699 nsi->stmt = si->stmt;
700 nsi->endptr = si->endptr;
701 nsi->first = si->first;
702 nsi->prev = si->prev;
703 nsi->next = si->next;
704 nsi->writable = si->writable;
705 set_strinfo (si->idx, nsi);
706 free_strinfo (si);
707 return nsi;
710 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
711 strinfo if there is any. Return it's idx, or 0 if no strinfo has
712 been created. */
714 static int
715 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
716 tree ptr)
718 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
719 return 0;
721 if (compare_nonzero_chars (basesi, off) < 0
722 || !tree_fits_uhwi_p (basesi->nonzero_chars))
723 return 0;
725 unsigned HOST_WIDE_INT nonzero_chars
726 = tree_to_uhwi (basesi->nonzero_chars) - off;
727 strinfo *si = basesi, *chainsi;
728 if (si->first || si->prev || si->next)
729 si = verify_related_strinfos (basesi);
730 if (si == NULL
731 || si->nonzero_chars == NULL_TREE
732 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
733 return 0;
735 if (TREE_CODE (ptr) == SSA_NAME
736 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
737 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
739 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
740 for (chainsi = si; chainsi->next; chainsi = si)
742 si = get_next_strinfo (chainsi);
743 if (si == NULL
744 || si->nonzero_chars == NULL_TREE
745 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
746 break;
747 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
748 if (r != 1)
750 if (r == 0)
752 if (TREE_CODE (ptr) == SSA_NAME)
753 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
754 else
756 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
757 if (pidx != NULL && *pidx == 0)
758 *pidx = si->idx;
760 return si->idx;
762 break;
766 int idx = new_stridx (ptr);
767 if (idx == 0)
768 return 0;
769 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
770 basesi->full_string_p);
771 set_strinfo (idx, si);
772 if (strinfo *nextsi = get_strinfo (chainsi->next))
774 nextsi = unshare_strinfo (nextsi);
775 si->next = nextsi->idx;
776 nextsi->prev = idx;
778 chainsi = unshare_strinfo (chainsi);
779 if (chainsi->first == 0)
780 chainsi->first = chainsi->idx;
781 chainsi->next = idx;
782 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
783 chainsi->endptr = ptr;
784 si->endptr = chainsi->endptr;
785 si->prev = chainsi->idx;
786 si->first = chainsi->first;
787 si->writable = chainsi->writable;
788 return si->idx;
791 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
792 to a zero-length string and if possible chain it to a related strinfo
793 chain whose part is or might be CHAINSI. */
795 static strinfo *
796 zero_length_string (tree ptr, strinfo *chainsi)
798 strinfo *si;
799 int idx;
800 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
801 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
802 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
803 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
805 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
806 return NULL;
807 if (chainsi != NULL)
809 si = verify_related_strinfos (chainsi);
810 if (si)
814 /* We shouldn't mix delayed and non-delayed lengths. */
815 gcc_assert (si->full_string_p);
816 if (si->endptr == NULL_TREE)
818 si = unshare_strinfo (si);
819 si->endptr = ptr;
821 chainsi = si;
822 si = get_next_strinfo (si);
824 while (si != NULL);
825 if (zero_length_string_p (chainsi))
827 if (chainsi->next)
829 chainsi = unshare_strinfo (chainsi);
830 chainsi->next = 0;
832 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
833 return chainsi;
836 else
838 /* We shouldn't mix delayed and non-delayed lengths. */
839 gcc_assert (chainsi->full_string_p);
840 if (chainsi->first || chainsi->prev || chainsi->next)
842 chainsi = unshare_strinfo (chainsi);
843 chainsi->first = 0;
844 chainsi->prev = 0;
845 chainsi->next = 0;
849 idx = new_stridx (ptr);
850 if (idx == 0)
851 return NULL;
852 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
853 set_strinfo (idx, si);
854 si->endptr = ptr;
855 if (chainsi != NULL)
857 chainsi = unshare_strinfo (chainsi);
858 if (chainsi->first == 0)
859 chainsi->first = chainsi->idx;
860 chainsi->next = idx;
861 if (chainsi->endptr == NULL_TREE)
862 chainsi->endptr = ptr;
863 si->prev = chainsi->idx;
864 si->first = chainsi->first;
865 si->writable = chainsi->writable;
867 return si;
870 /* For strinfo ORIGSI whose length has been just updated, adjust other
871 related strinfos so that they match the new ORIGSI. This involves:
873 - adding ADJ to the nonzero_chars fields
874 - copying full_string_p from the new ORIGSI. */
876 static void
877 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
879 strinfo *si = verify_related_strinfos (origsi);
881 if (si == NULL)
882 return;
884 while (1)
886 strinfo *nsi;
888 if (si != origsi)
890 tree tem;
892 si = unshare_strinfo (si);
893 /* We shouldn't see delayed lengths here; the caller must have
894 calculated the old length in order to calculate the
895 adjustment. */
896 gcc_assert (si->nonzero_chars);
897 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
898 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
899 TREE_TYPE (si->nonzero_chars),
900 si->nonzero_chars, tem);
901 si->full_string_p = origsi->full_string_p;
903 si->endptr = NULL_TREE;
904 si->dont_invalidate = true;
906 nsi = get_next_strinfo (si);
907 if (nsi == NULL)
908 return;
909 si = nsi;
913 /* Find if there are other SSA_NAME pointers equal to PTR
914 for which we don't track their string lengths yet. If so, use
915 IDX for them. */
917 static void
918 find_equal_ptrs (tree ptr, int idx)
920 if (TREE_CODE (ptr) != SSA_NAME)
921 return;
922 while (1)
924 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
925 if (!is_gimple_assign (stmt))
926 return;
927 ptr = gimple_assign_rhs1 (stmt);
928 switch (gimple_assign_rhs_code (stmt))
930 case SSA_NAME:
931 break;
932 CASE_CONVERT:
933 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
934 return;
935 if (TREE_CODE (ptr) == SSA_NAME)
936 break;
937 if (TREE_CODE (ptr) != ADDR_EXPR)
938 return;
939 /* FALLTHRU */
940 case ADDR_EXPR:
942 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
943 if (pidx != NULL && *pidx == 0)
944 *pidx = idx;
945 return;
947 default:
948 return;
951 /* We might find an endptr created in this pass. Grow the
952 vector in that case. */
953 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
954 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
956 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
957 return;
958 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
962 /* Return true if STMT is a call to a builtin function with the right
963 arguments and attributes that should be considered for optimization
964 by this pass. */
966 static bool
967 valid_builtin_call (gimple *stmt)
969 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
970 return false;
972 tree callee = gimple_call_fndecl (stmt);
973 switch (DECL_FUNCTION_CODE (callee))
975 case BUILT_IN_MEMCMP:
976 case BUILT_IN_MEMCMP_EQ:
977 case BUILT_IN_STRCHR:
978 case BUILT_IN_STRLEN:
979 /* The above functions should be pure. Punt if they aren't. */
980 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
981 return false;
982 break;
984 case BUILT_IN_CALLOC:
985 case BUILT_IN_MALLOC:
986 case BUILT_IN_MEMCPY:
987 case BUILT_IN_MEMCPY_CHK:
988 case BUILT_IN_MEMPCPY:
989 case BUILT_IN_MEMPCPY_CHK:
990 case BUILT_IN_MEMSET:
991 case BUILT_IN_STPCPY:
992 case BUILT_IN_STPCPY_CHK:
993 case BUILT_IN_STRCAT:
994 case BUILT_IN_STRCAT_CHK:
995 case BUILT_IN_STRCPY:
996 case BUILT_IN_STRCPY_CHK:
997 /* The above functions should be neither const nor pure. Punt if they
998 aren't. */
999 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1000 return false;
1001 break;
1003 default:
1004 break;
1007 return true;
1010 /* If the last .MEM setter statement before STMT is
1011 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1012 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1013 just memcpy (x, y, strlen (y)). SI must be the zero length
1014 strinfo. */
1016 static void
1017 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1019 tree vuse, callee, len;
1020 struct laststmt_struct last = laststmt;
1021 strinfo *lastsi, *firstsi;
1022 unsigned len_arg_no = 2;
1024 laststmt.stmt = NULL;
1025 laststmt.len = NULL_TREE;
1026 laststmt.stridx = 0;
1028 if (last.stmt == NULL)
1029 return;
1031 vuse = gimple_vuse (stmt);
1032 if (vuse == NULL_TREE
1033 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1034 || !has_single_use (vuse))
1035 return;
1037 gcc_assert (last.stridx > 0);
1038 lastsi = get_strinfo (last.stridx);
1039 if (lastsi == NULL)
1040 return;
1042 if (lastsi != si)
1044 if (lastsi->first == 0 || lastsi->first != si->first)
1045 return;
1047 firstsi = verify_related_strinfos (si);
1048 if (firstsi == NULL)
1049 return;
1050 while (firstsi != lastsi)
1052 firstsi = get_next_strinfo (firstsi);
1053 if (firstsi == NULL)
1054 return;
1058 if (!is_strcat && !zero_length_string_p (si))
1059 return;
1061 if (is_gimple_assign (last.stmt))
1063 gimple_stmt_iterator gsi;
1065 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1066 return;
1067 if (stmt_could_throw_p (cfun, last.stmt))
1068 return;
1069 gsi = gsi_for_stmt (last.stmt);
1070 unlink_stmt_vdef (last.stmt);
1071 release_defs (last.stmt);
1072 gsi_remove (&gsi, true);
1073 return;
1076 if (!valid_builtin_call (last.stmt))
1077 return;
1079 callee = gimple_call_fndecl (last.stmt);
1080 switch (DECL_FUNCTION_CODE (callee))
1082 case BUILT_IN_MEMCPY:
1083 case BUILT_IN_MEMCPY_CHK:
1084 break;
1085 default:
1086 return;
1089 len = gimple_call_arg (last.stmt, len_arg_no);
1090 if (tree_fits_uhwi_p (len))
1092 if (!tree_fits_uhwi_p (last.len)
1093 || integer_zerop (len)
1094 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1095 return;
1096 /* Don't adjust the length if it is divisible by 4, it is more efficient
1097 to store the extra '\0' in that case. */
1098 if ((tree_to_uhwi (len) & 3) == 0)
1099 return;
1101 /* Don't fold away an out of bounds access, as this defeats proper
1102 warnings. */
1103 tree dst = gimple_call_arg (last.stmt, 0);
1104 tree size = compute_objsize (dst, 0);
1105 if (size && tree_int_cst_lt (size, len))
1106 return;
1108 else if (TREE_CODE (len) == SSA_NAME)
1110 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1111 if (!is_gimple_assign (def_stmt)
1112 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1113 || gimple_assign_rhs1 (def_stmt) != last.len
1114 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1115 return;
1117 else
1118 return;
1120 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1121 update_stmt (last.stmt);
1124 /* For an LHS that is an SSA_NAME and for strlen() or strnlen() argument
1125 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1126 a character array A[N] with unknown length bounded by N, and for
1127 strnlen(), by min (N, BOUND). */
1129 static tree
1130 maybe_set_strlen_range (tree lhs, tree src, tree bound)
1132 if (TREE_CODE (lhs) != SSA_NAME
1133 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
1134 return NULL_TREE;
1136 if (TREE_CODE (src) == SSA_NAME)
1138 gimple *def = SSA_NAME_DEF_STMT (src);
1139 if (is_gimple_assign (def)
1140 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1141 src = gimple_assign_rhs1 (def);
1144 wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1145 wide_int min = wi::zero (max.get_precision ());
1147 if (TREE_CODE (src) == ADDR_EXPR)
1149 /* The last array member of a struct can be bigger than its size
1150 suggests if it's treated as a poor-man's flexible array member. */
1151 src = TREE_OPERAND (src, 0);
1152 bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE;
1153 if (src_is_array
1154 && TREE_CODE (src) != MEM_REF
1155 && !array_at_struct_end_p (src))
1157 tree type = TREE_TYPE (src);
1158 if (tree size = TYPE_SIZE_UNIT (type))
1159 if (size && TREE_CODE (size) == INTEGER_CST)
1160 max = wi::to_wide (size);
1162 /* For strlen() the upper bound above is equal to
1163 the longest string that can be stored in the array
1164 (i.e., it accounts for the terminating nul. For
1165 strnlen() bump up the maximum by one since the array
1166 need not be nul-terminated. */
1167 if (!bound && max != 0)
1168 --max;
1170 else
1172 if (TREE_CODE (src) == COMPONENT_REF && !src_is_array)
1173 src = TREE_OPERAND (src, 1);
1174 if (DECL_P (src))
1176 /* Handle the unlikely case of strlen (&c) where c is some
1177 variable. */
1178 if (tree size = DECL_SIZE_UNIT (src))
1179 if (TREE_CODE (size) == INTEGER_CST)
1180 max = wi::to_wide (size);
1185 if (bound)
1187 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1188 is less than the size of the array set MAX to it. It it's
1189 greater than MAX and MAX is non-zero bump MAX down to account
1190 for the necessary terminating nul. Otherwise leave it alone. */
1191 if (TREE_CODE (bound) == INTEGER_CST)
1193 wide_int wibnd = wi::to_wide (bound);
1194 int cmp = wi::cmpu (wibnd, max);
1195 if (cmp < 0)
1196 max = wibnd;
1197 else if (cmp && wi::ne_p (max, min))
1198 --max;
1200 else if (TREE_CODE (bound) == SSA_NAME)
1202 wide_int minbound, maxbound;
1203 value_range_kind rng = get_range_info (bound, &minbound, &maxbound);
1204 if (rng == VR_RANGE)
1206 /* For a bound in a known range, adjust the range determined
1207 above as necessary. For a bound in some anti-range or
1208 in an unknown range, use the range determined above. */
1209 if (wi::ltu_p (minbound, min))
1210 min = minbound;
1211 if (wi::ltu_p (maxbound, max))
1212 max = maxbound;
1217 if (min == max)
1218 return wide_int_to_tree (size_type_node, min);
1220 set_range_info (lhs, VR_RANGE, min, max);
1221 return lhs;
1224 /* Handle a strlen call. If strlen of the argument is known, replace
1225 the strlen call with the known value, otherwise remember that strlen
1226 of the argument is stored in the lhs SSA_NAME. */
1228 static void
1229 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1231 gimple *stmt = gsi_stmt (*gsi);
1232 tree lhs = gimple_call_lhs (stmt);
1234 if (lhs == NULL_TREE)
1235 return;
1237 location_t loc = gimple_location (stmt);
1238 tree callee = gimple_call_fndecl (stmt);
1239 tree src = gimple_call_arg (stmt, 0);
1240 tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
1241 ? gimple_call_arg (stmt, 1) : NULL_TREE);
1242 int idx = get_stridx (src);
1243 if (idx)
1245 strinfo *si = NULL;
1246 tree rhs;
1248 if (idx < 0)
1249 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1250 else
1252 rhs = NULL_TREE;
1253 si = get_strinfo (idx);
1254 if (si != NULL)
1255 rhs = get_string_length (si);
1257 if (rhs != NULL_TREE)
1259 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1261 fprintf (dump_file, "Optimizing: ");
1262 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1264 rhs = unshare_expr (rhs);
1265 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1266 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1268 /* Set for strnlen() calls with a non-constant bound. */
1269 bool noncst_bound = false;
1270 if (bound)
1272 tree new_rhs
1273 = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
1275 noncst_bound = (TREE_CODE (new_rhs) != INTEGER_CST
1276 || tree_int_cst_lt (new_rhs, rhs));
1278 rhs = new_rhs;
1281 if (!update_call_from_tree (gsi, rhs))
1282 gimplify_and_update_call_from_tree (gsi, rhs);
1283 stmt = gsi_stmt (*gsi);
1284 update_stmt (stmt);
1285 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1287 fprintf (dump_file, "into: ");
1288 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1291 /* Avoid storing the length for calls to strnlen() with
1292 a non-constant bound. */
1293 if (noncst_bound)
1294 return;
1296 if (si != NULL
1297 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1298 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1299 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1301 si = unshare_strinfo (si);
1302 si->nonzero_chars = lhs;
1303 gcc_assert (si->full_string_p);
1306 if (strlen_to_stridx)
1307 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1309 return;
1312 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1313 return;
1315 if (idx == 0)
1316 idx = new_stridx (src);
1317 else
1319 strinfo *si = get_strinfo (idx);
1320 if (si != NULL)
1322 if (!si->full_string_p && !si->stmt)
1324 /* Until now we only had a lower bound on the string length.
1325 Install LHS as the actual length. */
1326 si = unshare_strinfo (si);
1327 tree old = si->nonzero_chars;
1328 si->nonzero_chars = lhs;
1329 si->full_string_p = true;
1330 if (TREE_CODE (old) == INTEGER_CST)
1332 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1333 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1334 TREE_TYPE (lhs), lhs, old);
1335 adjust_related_strinfos (loc, si, adj);
1337 else
1339 si->first = 0;
1340 si->prev = 0;
1341 si->next = 0;
1344 return;
1347 if (idx)
1349 if (!bound)
1351 /* Only store the new length information for calls to strlen(),
1352 not for those to strnlen(). */
1353 strinfo *si = new_strinfo (src, idx, lhs, true);
1354 set_strinfo (idx, si);
1355 find_equal_ptrs (src, idx);
1358 /* For SRC that is an array of N elements, set LHS's range
1359 to [0, min (N, BOUND)]. A constant return value means
1360 the range would have consisted of a single value. In
1361 that case, fold the result into the returned constant. */
1362 if (tree ret = maybe_set_strlen_range (lhs, src, bound))
1363 if (TREE_CODE (ret) == INTEGER_CST)
1365 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1367 fprintf (dump_file, "Optimizing: ");
1368 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1370 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
1371 ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
1372 if (!update_call_from_tree (gsi, ret))
1373 gimplify_and_update_call_from_tree (gsi, ret);
1374 stmt = gsi_stmt (*gsi);
1375 update_stmt (stmt);
1376 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1378 fprintf (dump_file, "into: ");
1379 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1383 if (strlen_to_stridx && !bound)
1384 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1388 /* Handle a strchr call. If strlen of the first argument is known, replace
1389 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1390 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1392 static void
1393 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1395 int idx;
1396 tree src;
1397 gimple *stmt = gsi_stmt (*gsi);
1398 tree lhs = gimple_call_lhs (stmt);
1400 if (lhs == NULL_TREE)
1401 return;
1403 if (!integer_zerop (gimple_call_arg (stmt, 1)))
1404 return;
1406 src = gimple_call_arg (stmt, 0);
1407 idx = get_stridx (src);
1408 if (idx)
1410 strinfo *si = NULL;
1411 tree rhs;
1413 if (idx < 0)
1414 rhs = build_int_cst (size_type_node, ~idx);
1415 else
1417 rhs = NULL_TREE;
1418 si = get_strinfo (idx);
1419 if (si != NULL)
1420 rhs = get_string_length (si);
1422 if (rhs != NULL_TREE)
1424 location_t loc = gimple_location (stmt);
1426 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1428 fprintf (dump_file, "Optimizing: ");
1429 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1431 if (si != NULL && si->endptr != NULL_TREE)
1433 rhs = unshare_expr (si->endptr);
1434 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1435 TREE_TYPE (rhs)))
1436 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1438 else
1440 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1441 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1442 TREE_TYPE (src), src, rhs);
1443 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1444 TREE_TYPE (rhs)))
1445 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1447 if (!update_call_from_tree (gsi, rhs))
1448 gimplify_and_update_call_from_tree (gsi, rhs);
1449 stmt = gsi_stmt (*gsi);
1450 update_stmt (stmt);
1451 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1453 fprintf (dump_file, "into: ");
1454 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1456 if (si != NULL
1457 && si->endptr == NULL_TREE
1458 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1460 si = unshare_strinfo (si);
1461 si->endptr = lhs;
1463 zero_length_string (lhs, si);
1464 return;
1467 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1468 return;
1469 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1471 if (idx == 0)
1472 idx = new_stridx (src);
1473 else if (get_strinfo (idx) != NULL)
1475 zero_length_string (lhs, NULL);
1476 return;
1478 if (idx)
1480 location_t loc = gimple_location (stmt);
1481 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1482 tree srcu = fold_convert_loc (loc, size_type_node, src);
1483 tree length = fold_build2_loc (loc, MINUS_EXPR,
1484 size_type_node, lhsu, srcu);
1485 strinfo *si = new_strinfo (src, idx, length, true);
1486 si->endptr = lhs;
1487 set_strinfo (idx, si);
1488 find_equal_ptrs (src, idx);
1489 zero_length_string (lhs, si);
1492 else
1493 zero_length_string (lhs, NULL);
1496 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1497 If strlen of the second argument is known, strlen of the first argument
1498 is the same after this call. Furthermore, attempt to convert it to
1499 memcpy. */
1501 static void
1502 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1504 int idx, didx;
1505 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1506 bool success;
1507 gimple *stmt = gsi_stmt (*gsi);
1508 strinfo *si, *dsi, *olddsi, *zsi;
1509 location_t loc;
1511 src = gimple_call_arg (stmt, 1);
1512 dst = gimple_call_arg (stmt, 0);
1513 lhs = gimple_call_lhs (stmt);
1514 idx = get_stridx (src);
1515 si = NULL;
1516 if (idx > 0)
1517 si = get_strinfo (idx);
1519 didx = get_stridx (dst);
1520 olddsi = NULL;
1521 oldlen = NULL_TREE;
1522 if (didx > 0)
1523 olddsi = get_strinfo (didx);
1524 else if (didx < 0)
1525 return;
1527 if (olddsi != NULL)
1528 adjust_last_stmt (olddsi, stmt, false);
1530 srclen = NULL_TREE;
1531 if (si != NULL)
1532 srclen = get_string_length (si);
1533 else if (idx < 0)
1534 srclen = build_int_cst (size_type_node, ~idx);
1536 loc = gimple_location (stmt);
1537 if (srclen == NULL_TREE)
1538 switch (bcode)
1540 case BUILT_IN_STRCPY:
1541 case BUILT_IN_STRCPY_CHK:
1542 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1543 return;
1544 break;
1545 case BUILT_IN_STPCPY:
1546 case BUILT_IN_STPCPY_CHK:
1547 if (lhs == NULL_TREE)
1548 return;
1549 else
1551 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1552 srclen = fold_convert_loc (loc, size_type_node, dst);
1553 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1554 lhsuint, srclen);
1556 break;
1557 default:
1558 gcc_unreachable ();
1561 if (didx == 0)
1563 didx = new_stridx (dst);
1564 if (didx == 0)
1565 return;
1567 if (olddsi != NULL)
1569 oldlen = olddsi->nonzero_chars;
1570 dsi = unshare_strinfo (olddsi);
1571 dsi->nonzero_chars = srclen;
1572 dsi->full_string_p = (srclen != NULL_TREE);
1573 /* Break the chain, so adjust_related_strinfo on later pointers in
1574 the chain won't adjust this one anymore. */
1575 dsi->next = 0;
1576 dsi->stmt = NULL;
1577 dsi->endptr = NULL_TREE;
1579 else
1581 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1582 set_strinfo (didx, dsi);
1583 find_equal_ptrs (dst, didx);
1585 dsi->writable = true;
1586 dsi->dont_invalidate = true;
1588 if (dsi->nonzero_chars == NULL_TREE)
1590 strinfo *chainsi;
1592 /* If string length of src is unknown, use delayed length
1593 computation. If string lenth of dst will be needed, it
1594 can be computed by transforming this strcpy call into
1595 stpcpy and subtracting dst from the return value. */
1597 /* Look for earlier strings whose length could be determined if
1598 this strcpy is turned into an stpcpy. */
1600 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1602 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1604 /* When setting a stmt for delayed length computation
1605 prevent all strinfos through dsi from being
1606 invalidated. */
1607 chainsi = unshare_strinfo (chainsi);
1608 chainsi->stmt = stmt;
1609 chainsi->nonzero_chars = NULL_TREE;
1610 chainsi->full_string_p = false;
1611 chainsi->endptr = NULL_TREE;
1612 chainsi->dont_invalidate = true;
1615 dsi->stmt = stmt;
1617 /* Try to detect overlap before returning. This catches cases
1618 like strcpy (d, d + n) where n is non-constant whose range
1619 is such that (n <= strlen (d) holds).
1621 OLDDSI->NONZERO_chars may have been reset by this point with
1622 oldlen holding it original value. */
1623 if (olddsi && oldlen)
1625 /* Add 1 for the terminating NUL. */
1626 tree type = TREE_TYPE (oldlen);
1627 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1628 build_int_cst (type, 1));
1629 check_bounds_or_overlap (stmt, olddsi->ptr, src, oldlen, NULL_TREE);
1632 return;
1635 if (olddsi != NULL)
1637 tree adj = NULL_TREE;
1638 if (oldlen == NULL_TREE)
1640 else if (integer_zerop (oldlen))
1641 adj = srclen;
1642 else if (TREE_CODE (oldlen) == INTEGER_CST
1643 || TREE_CODE (srclen) == INTEGER_CST)
1644 adj = fold_build2_loc (loc, MINUS_EXPR,
1645 TREE_TYPE (srclen), srclen,
1646 fold_convert_loc (loc, TREE_TYPE (srclen),
1647 oldlen));
1648 if (adj != NULL_TREE)
1649 adjust_related_strinfos (loc, dsi, adj);
1650 else
1651 dsi->prev = 0;
1653 /* strcpy src may not overlap dst, so src doesn't need to be
1654 invalidated either. */
1655 if (si != NULL)
1656 si->dont_invalidate = true;
1658 fn = NULL_TREE;
1659 zsi = NULL;
1660 switch (bcode)
1662 case BUILT_IN_STRCPY:
1663 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1664 if (lhs)
1665 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1666 break;
1667 case BUILT_IN_STRCPY_CHK:
1668 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1669 if (lhs)
1670 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1671 break;
1672 case BUILT_IN_STPCPY:
1673 /* This would need adjustment of the lhs (subtract one),
1674 or detection that the trailing '\0' doesn't need to be
1675 written, if it will be immediately overwritten.
1676 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1677 if (lhs)
1679 dsi->endptr = lhs;
1680 zsi = zero_length_string (lhs, dsi);
1682 break;
1683 case BUILT_IN_STPCPY_CHK:
1684 /* This would need adjustment of the lhs (subtract one),
1685 or detection that the trailing '\0' doesn't need to be
1686 written, if it will be immediately overwritten.
1687 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1688 if (lhs)
1690 dsi->endptr = lhs;
1691 zsi = zero_length_string (lhs, dsi);
1693 break;
1694 default:
1695 gcc_unreachable ();
1697 if (zsi != NULL)
1698 zsi->dont_invalidate = true;
1700 if (fn)
1702 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1703 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1705 else
1706 type = size_type_node;
1708 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1709 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1711 /* Set the no-warning bit on the transformed statement? */
1712 bool set_no_warning = false;
1714 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1715 if (si
1716 && !check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
1718 gimple_set_no_warning (stmt, true);
1719 set_no_warning = true;
1722 if (fn == NULL_TREE)
1723 return;
1725 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1726 GSI_SAME_STMT);
1727 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1729 fprintf (dump_file, "Optimizing: ");
1730 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1732 if (gimple_call_num_args (stmt) == 2)
1733 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1734 else
1735 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1736 gimple_call_arg (stmt, 2));
1737 if (success)
1739 stmt = gsi_stmt (*gsi);
1740 update_stmt (stmt);
1741 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1743 fprintf (dump_file, "into: ");
1744 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1746 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1747 laststmt.stmt = stmt;
1748 laststmt.len = srclen;
1749 laststmt.stridx = dsi->idx;
1751 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1752 fprintf (dump_file, "not possible.\n");
1754 if (set_no_warning)
1755 gimple_set_no_warning (stmt, true);
1758 /* Check the size argument to the built-in forms of stpncpy and strncpy
1759 for out-of-bounds offsets or overlapping access, and to see if the
1760 size argument is derived from a call to strlen() on the source argument,
1761 and if so, issue an appropriate warning. */
1763 static void
1764 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1766 /* Same as stxncpy(). */
1767 handle_builtin_stxncpy (bcode, gsi);
1770 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1771 way. LEN can either be an integer expression, or a pointer (to char).
1772 When it is the latter (such as in recursive calls to self) is is
1773 assumed to be the argument in some call to strlen() whose relationship
1774 to SRC is being ascertained. */
1776 bool
1777 is_strlen_related_p (tree src, tree len)
1779 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1780 && operand_equal_p (src, len, 0))
1781 return true;
1783 if (TREE_CODE (len) != SSA_NAME)
1784 return false;
1786 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1787 if (!def_stmt)
1788 return false;
1790 if (is_gimple_call (def_stmt))
1792 tree func = gimple_call_fndecl (def_stmt);
1793 if (!valid_builtin_call (def_stmt)
1794 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1795 return false;
1797 tree arg = gimple_call_arg (def_stmt, 0);
1798 return is_strlen_related_p (src, arg);
1801 if (!is_gimple_assign (def_stmt))
1802 return false;
1804 tree_code code = gimple_assign_rhs_code (def_stmt);
1805 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1806 tree rhstype = TREE_TYPE (rhs1);
1808 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1809 || (INTEGRAL_TYPE_P (rhstype)
1810 && (code == BIT_AND_EXPR
1811 || code == NOP_EXPR)))
1813 /* Pointer plus (an integer), and truncation are considered among
1814 the (potentially) related expressions to strlen. */
1815 return is_strlen_related_p (src, rhs1);
1818 if (tree rhs2 = gimple_assign_rhs2 (def_stmt))
1820 /* Integer subtraction is considered strlen-related when both
1821 arguments are integers and second one is strlen-related. */
1822 rhstype = TREE_TYPE (rhs2);
1823 if (INTEGRAL_TYPE_P (rhstype) && code == MINUS_EXPR)
1824 return is_strlen_related_p (src, rhs2);
1827 return false;
1830 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1831 in gimple-fold.c.
1832 Check to see if the specified bound is a) equal to the size of
1833 the destination DST and if so, b) if it's immediately followed by
1834 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1835 do nothing. Return true if diagnostic has been issued.
1837 The purpose is to diagnose calls to strncpy and stpncpy that do
1838 not nul-terminate the copy while allowing for the idiom where
1839 such a call is immediately followed by setting the last element
1840 to nul, as in:
1841 char a[32];
1842 strncpy (a, s, sizeof a);
1843 a[sizeof a - 1] = '\0';
1846 bool
1847 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1849 gimple *stmt = gsi_stmt (gsi);
1850 if (gimple_no_warning_p (stmt))
1851 return false;
1853 wide_int cntrange[2];
1855 if (TREE_CODE (cnt) == INTEGER_CST)
1856 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1857 else if (TREE_CODE (cnt) == SSA_NAME)
1859 enum value_range_kind rng = get_range_info (cnt, cntrange, cntrange + 1);
1860 if (rng == VR_RANGE)
1862 else if (rng == VR_ANTI_RANGE)
1864 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1866 if (wi::ltu_p (cntrange[1], maxobjsize))
1868 cntrange[0] = cntrange[1] + 1;
1869 cntrange[1] = maxobjsize;
1871 else
1873 cntrange[1] = cntrange[0] - 1;
1874 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1877 else
1878 return false;
1880 else
1881 return false;
1883 /* Negative value is the constant string length. If it's less than
1884 the lower bound there is no truncation. Avoid calling get_stridx()
1885 when ssa_ver_to_stridx is empty. That implies the caller isn't
1886 running under the control of this pass and ssa_ver_to_stridx hasn't
1887 been created yet. */
1888 int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
1889 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1890 return false;
1892 tree dst = gimple_call_arg (stmt, 0);
1893 tree dstdecl = dst;
1894 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1895 dstdecl = TREE_OPERAND (dstdecl, 0);
1897 tree ref = NULL_TREE;
1899 if (!sidx)
1901 /* If the source is a non-string return early to avoid warning
1902 for possible truncation (if the truncation is certain SIDX
1903 is non-zero). */
1904 tree srcdecl = gimple_call_arg (stmt, 1);
1905 if (TREE_CODE (srcdecl) == ADDR_EXPR)
1906 srcdecl = TREE_OPERAND (srcdecl, 0);
1907 if (get_attr_nonstring_decl (srcdecl, &ref))
1908 return false;
1911 /* Likewise, if the destination refers to a an array/pointer declared
1912 nonstring return early. */
1913 if (get_attr_nonstring_decl (dstdecl, &ref))
1914 return false;
1916 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1917 avoid the truncation warning. */
1918 gsi_next_nondebug (&gsi);
1919 gimple *next_stmt = gsi_stmt (gsi);
1920 if (!next_stmt)
1922 /* When there is no statement in the same basic block check
1923 the immediate successor block. */
1924 if (basic_block bb = gimple_bb (stmt))
1926 if (single_succ_p (bb))
1928 /* For simplicity, ignore blocks with multiple outgoing
1929 edges for now and only consider successor blocks along
1930 normal edges. */
1931 edge e = EDGE_SUCC (bb, 0);
1932 if (!(e->flags & EDGE_ABNORMAL))
1934 gsi = gsi_start_bb (e->dest);
1935 next_stmt = gsi_stmt (gsi);
1936 if (next_stmt && is_gimple_debug (next_stmt))
1938 gsi_next_nondebug (&gsi);
1939 next_stmt = gsi_stmt (gsi);
1946 if (next_stmt && is_gimple_assign (next_stmt))
1948 tree lhs = gimple_assign_lhs (next_stmt);
1949 tree_code code = TREE_CODE (lhs);
1950 if (code == ARRAY_REF || code == MEM_REF)
1951 lhs = TREE_OPERAND (lhs, 0);
1953 tree func = gimple_call_fndecl (stmt);
1954 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1956 tree ret = gimple_call_lhs (stmt);
1957 if (ret && operand_equal_p (ret, lhs, 0))
1958 return false;
1961 /* Determine the base address and offset of the reference,
1962 ignoring the innermost array index. */
1963 if (TREE_CODE (ref) == ARRAY_REF)
1964 ref = TREE_OPERAND (ref, 0);
1966 poly_int64 dstoff;
1967 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1969 poly_int64 lhsoff;
1970 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1971 if (lhsbase
1972 && dstbase
1973 && known_eq (dstoff, lhsoff)
1974 && operand_equal_p (dstbase, lhsbase, 0))
1975 return false;
1978 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1979 wide_int lenrange[2];
1980 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1982 lenrange[0] = (sisrc->nonzero_chars
1983 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1984 ? wi::to_wide (sisrc->nonzero_chars)
1985 : wi::zero (prec));
1986 lenrange[1] = lenrange[0];
1988 else if (sidx < 0)
1989 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1990 else
1992 tree range[2];
1993 get_range_strlen (src, range);
1994 if (range[0] != NULL_TREE
1995 && TREE_CODE (range[0]) == INTEGER_CST
1996 && range[1] != NULL_TREE
1997 && TREE_CODE (range[1]) == INTEGER_CST)
1999 lenrange[0] = wi::to_wide (range[0], prec);
2000 lenrange[1] = wi::to_wide (range[1], prec);
2002 else
2004 lenrange[0] = wi::shwi (0, prec);
2005 lenrange[1] = wi::shwi (-1, prec);
2009 location_t callloc = gimple_nonartificial_location (stmt);
2010 callloc = expansion_point_location_if_in_system_header (callloc);
2012 tree func = gimple_call_fndecl (stmt);
2014 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
2016 /* If the longest source string is shorter than the lower bound
2017 of the specified count the copy is definitely nul-terminated. */
2018 if (wi::ltu_p (lenrange[1], cntrange[0]))
2019 return false;
2021 if (wi::neg_p (lenrange[1]))
2023 /* The length of one of the strings is unknown but at least
2024 one has non-zero length and that length is stored in
2025 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2026 warning below. */
2027 lenrange[1] = lenrange[0];
2028 lenrange[0] = wi::shwi (0, prec);
2031 /* Set to true for strncat whose bound is derived from the length
2032 of the destination (the expected usage pattern). */
2033 bool cat_dstlen_bounded = false;
2034 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STRNCAT)
2035 cat_dstlen_bounded = is_strlen_related_p (dst, cnt);
2037 if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
2038 return warning_n (callloc, OPT_Wstringop_truncation,
2039 cntrange[0].to_uhwi (),
2040 "%G%qD output truncated before terminating "
2041 "nul copying %E byte from a string of the "
2042 "same length",
2043 "%G%qD output truncated before terminating nul "
2044 "copying %E bytes from a string of the same "
2045 "length",
2046 stmt, func, cnt);
2047 else if (!cat_dstlen_bounded)
2049 if (wi::geu_p (lenrange[0], cntrange[1]))
2051 /* The shortest string is longer than the upper bound of
2052 the count so the truncation is certain. */
2053 if (cntrange[0] == cntrange[1])
2054 return warning_n (callloc, OPT_Wstringop_truncation,
2055 cntrange[0].to_uhwi (),
2056 "%G%qD output truncated copying %E byte "
2057 "from a string of length %wu",
2058 "%G%qD output truncated copying %E bytes "
2059 "from a string of length %wu",
2060 stmt, func, cnt, lenrange[0].to_uhwi ());
2062 return warning_at (callloc, OPT_Wstringop_truncation,
2063 "%G%qD output truncated copying between %wu "
2064 "and %wu bytes from a string of length %wu",
2065 stmt, func, cntrange[0].to_uhwi (),
2066 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2068 else if (wi::geu_p (lenrange[1], cntrange[1]))
2070 /* The longest string is longer than the upper bound of
2071 the count so the truncation is possible. */
2072 if (cntrange[0] == cntrange[1])
2073 return warning_n (callloc, OPT_Wstringop_truncation,
2074 cntrange[0].to_uhwi (),
2075 "%G%qD output may be truncated copying %E "
2076 "byte from a string of length %wu",
2077 "%G%qD output may be truncated copying %E "
2078 "bytes from a string of length %wu",
2079 stmt, func, cnt, lenrange[1].to_uhwi ());
2081 return warning_at (callloc, OPT_Wstringop_truncation,
2082 "%G%qD output may be truncated copying between "
2083 "%wu and %wu bytes from a string of length %wu",
2084 stmt, func, cntrange[0].to_uhwi (),
2085 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
2089 if (!cat_dstlen_bounded
2090 && cntrange[0] != cntrange[1]
2091 && wi::leu_p (cntrange[0], lenrange[0])
2092 && wi::leu_p (cntrange[1], lenrange[0] + 1))
2094 /* If the source (including the terminating nul) is longer than
2095 the lower bound of the specified count but shorter than the
2096 upper bound the copy may (but need not) be truncated. */
2097 return warning_at (callloc, OPT_Wstringop_truncation,
2098 "%G%qD output may be truncated copying between "
2099 "%wu and %wu bytes from a string of length %wu",
2100 stmt, func, cntrange[0].to_uhwi (),
2101 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2105 if (tree dstsize = compute_objsize (dst, 1))
2107 /* The source length is uknown. Try to determine the destination
2108 size and see if it matches the specified bound. If not, bail.
2109 Otherwise go on to see if it should be diagnosed for possible
2110 truncation. */
2111 if (!dstsize)
2112 return false;
2114 if (wi::to_wide (dstsize) != cntrange[1])
2115 return false;
2117 if (cntrange[0] == cntrange[1])
2118 return warning_at (callloc, OPT_Wstringop_truncation,
2119 "%G%qD specified bound %E equals destination size",
2120 stmt, func, cnt);
2123 return false;
2126 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2127 out-of-bounds offsets or overlapping access, and to see if the size
2128 is derived from calling strlen() on the source argument, and if so,
2129 issue the appropriate warning. */
2131 static void
2132 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2134 if (!strlen_to_stridx)
2135 return;
2137 gimple *stmt = gsi_stmt (*gsi);
2139 tree dst = gimple_call_arg (stmt, 0);
2140 tree src = gimple_call_arg (stmt, 1);
2141 tree len = gimple_call_arg (stmt, 2);
2142 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2144 int didx = get_stridx (dst);
2145 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2147 /* Compute the size of the destination string including the NUL. */
2148 if (sidst->nonzero_chars)
2150 tree type = TREE_TYPE (sidst->nonzero_chars);
2151 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2152 build_int_cst (type, 1));
2154 dst = sidst->ptr;
2157 int sidx = get_stridx (src);
2158 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2159 if (sisrc)
2161 /* strncat() and strncpy() can modify the source string by writing
2162 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2163 clear. */
2165 /* Compute the size of the source string including the NUL. */
2166 if (sisrc->nonzero_chars)
2168 tree type = TREE_TYPE (sisrc->nonzero_chars);
2169 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2170 build_int_cst (type, 1));
2173 src = sisrc->ptr;
2175 else
2176 srcsize = NULL_TREE;
2178 if (!check_bounds_or_overlap (stmt, dst, src, dstsize, srcsize))
2180 gimple_set_no_warning (stmt, true);
2181 return;
2184 /* If the length argument was computed from strlen(S) for some string
2185 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2186 the location of the strlen() call (PSS->SECOND). */
2187 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2188 if (!pss || pss->first <= 0)
2190 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2191 gimple_set_no_warning (stmt, true);
2193 return;
2196 /* Retrieve the strinfo data for the string S that LEN was computed
2197 from as some function F of strlen (S) (i.e., LEN need not be equal
2198 to strlen(S)). */
2199 strinfo *silen = get_strinfo (pss->first);
2201 location_t callloc = gimple_nonartificial_location (stmt);
2202 callloc = expansion_point_location_if_in_system_header (callloc);
2204 tree func = gimple_call_fndecl (stmt);
2206 bool warned = false;
2208 /* When -Wstringop-truncation is set, try to determine truncation
2209 before diagnosing possible overflow. Truncation is implied by
2210 the LEN argument being equal to strlen(SRC), regardless of
2211 whether its value is known. Otherwise, issue the more generic
2212 -Wstringop-overflow which triggers for LEN arguments that in
2213 any meaningful way depend on strlen(SRC). */
2214 if (sisrc == silen
2215 && is_strlen_related_p (src, len)
2216 && warning_at (callloc, OPT_Wstringop_truncation,
2217 "%G%qD output truncated before terminating nul "
2218 "copying as many bytes from a string as its length",
2219 stmt, func))
2220 warned = true;
2221 else if (silen && is_strlen_related_p (src, silen->ptr))
2222 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2223 "%G%qD specified bound depends on the length "
2224 "of the source argument",
2225 stmt, func);
2226 if (warned)
2228 location_t strlenloc = pss->second;
2229 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2230 inform (strlenloc, "length computed here");
2234 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2235 If strlen of the second argument is known and length of the third argument
2236 is that plus one, strlen of the first argument is the same after this
2237 call. */
2239 static void
2240 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2242 int idx, didx;
2243 tree src, dst, len, lhs, oldlen, newlen;
2244 gimple *stmt = gsi_stmt (*gsi);
2245 strinfo *si, *dsi, *olddsi;
2247 len = gimple_call_arg (stmt, 2);
2248 src = gimple_call_arg (stmt, 1);
2249 dst = gimple_call_arg (stmt, 0);
2250 idx = get_stridx (src);
2251 if (idx == 0)
2252 return;
2254 didx = get_stridx (dst);
2255 olddsi = NULL;
2256 if (didx > 0)
2257 olddsi = get_strinfo (didx);
2258 else if (didx < 0)
2259 return;
2261 if (olddsi != NULL
2262 && tree_fits_uhwi_p (len)
2263 && !integer_zerop (len))
2264 adjust_last_stmt (olddsi, stmt, false);
2266 bool full_string_p;
2267 if (idx > 0)
2269 gimple *def_stmt;
2271 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2272 is known. */
2273 si = get_strinfo (idx);
2274 if (si == NULL || si->nonzero_chars == NULL_TREE)
2275 return;
2276 if (TREE_CODE (len) == INTEGER_CST
2277 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2279 if (tree_int_cst_le (len, si->nonzero_chars))
2281 /* Copying LEN nonzero characters, where LEN is constant. */
2282 newlen = len;
2283 full_string_p = false;
2285 else
2287 /* Copying the whole of the analyzed part of SI. */
2288 newlen = si->nonzero_chars;
2289 full_string_p = si->full_string_p;
2292 else
2294 if (!si->full_string_p)
2295 return;
2296 if (TREE_CODE (len) != SSA_NAME)
2297 return;
2298 def_stmt = SSA_NAME_DEF_STMT (len);
2299 if (!is_gimple_assign (def_stmt)
2300 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2301 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2302 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2303 return;
2304 /* Copying variable-length string SI (and no more). */
2305 newlen = si->nonzero_chars;
2306 full_string_p = true;
2309 else
2311 si = NULL;
2312 /* Handle memcpy (x, "abcd", 5) or
2313 memcpy (x, "abc\0uvw", 7). */
2314 if (!tree_fits_uhwi_p (len))
2315 return;
2317 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2318 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2319 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2320 full_string_p = clen > nonzero_chars;
2323 if (!full_string_p
2324 && olddsi
2325 && olddsi->nonzero_chars
2326 && TREE_CODE (olddsi->nonzero_chars) == INTEGER_CST
2327 && tree_int_cst_le (newlen, olddsi->nonzero_chars))
2329 /* The SRC substring being written strictly overlaps
2330 a subsequence of the existing string OLDDSI. */
2331 newlen = olddsi->nonzero_chars;
2332 full_string_p = olddsi->full_string_p;
2335 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2336 adjust_last_stmt (olddsi, stmt, false);
2338 if (didx == 0)
2340 didx = new_stridx (dst);
2341 if (didx == 0)
2342 return;
2344 oldlen = NULL_TREE;
2345 if (olddsi != NULL)
2347 dsi = unshare_strinfo (olddsi);
2348 oldlen = olddsi->nonzero_chars;
2349 dsi->nonzero_chars = newlen;
2350 dsi->full_string_p = full_string_p;
2351 /* Break the chain, so adjust_related_strinfo on later pointers in
2352 the chain won't adjust this one anymore. */
2353 dsi->next = 0;
2354 dsi->stmt = NULL;
2355 dsi->endptr = NULL_TREE;
2357 else
2359 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2360 set_strinfo (didx, dsi);
2361 find_equal_ptrs (dst, didx);
2363 dsi->writable = true;
2364 dsi->dont_invalidate = true;
2365 if (olddsi != NULL)
2367 tree adj = NULL_TREE;
2368 location_t loc = gimple_location (stmt);
2369 if (oldlen == NULL_TREE)
2371 else if (integer_zerop (oldlen))
2372 adj = newlen;
2373 else if (TREE_CODE (oldlen) == INTEGER_CST
2374 || TREE_CODE (newlen) == INTEGER_CST)
2375 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2376 fold_convert_loc (loc, TREE_TYPE (newlen),
2377 oldlen));
2378 if (adj != NULL_TREE)
2379 adjust_related_strinfos (loc, dsi, adj);
2380 else
2381 dsi->prev = 0;
2383 /* memcpy src may not overlap dst, so src doesn't need to be
2384 invalidated either. */
2385 if (si != NULL)
2386 si->dont_invalidate = true;
2388 if (full_string_p)
2390 lhs = gimple_call_lhs (stmt);
2391 switch (bcode)
2393 case BUILT_IN_MEMCPY:
2394 case BUILT_IN_MEMCPY_CHK:
2395 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2396 laststmt.stmt = stmt;
2397 laststmt.len = dsi->nonzero_chars;
2398 laststmt.stridx = dsi->idx;
2399 if (lhs)
2400 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2401 break;
2402 case BUILT_IN_MEMPCPY:
2403 case BUILT_IN_MEMPCPY_CHK:
2404 break;
2405 default:
2406 gcc_unreachable ();
2411 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2412 If strlen of the second argument is known, strlen of the first argument
2413 is increased by the length of the second argument. Furthermore, attempt
2414 to convert it to memcpy/strcpy if the length of the first argument
2415 is known. */
2417 static void
2418 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2420 int idx, didx;
2421 tree srclen, args, type, fn, objsz, endptr;
2422 bool success;
2423 gimple *stmt = gsi_stmt (*gsi);
2424 strinfo *si, *dsi;
2425 location_t loc = gimple_location (stmt);
2427 tree src = gimple_call_arg (stmt, 1);
2428 tree dst = gimple_call_arg (stmt, 0);
2430 /* Bail if the source is the same as destination. It will be diagnosed
2431 elsewhere. */
2432 if (operand_equal_p (src, dst, 0))
2433 return;
2435 tree lhs = gimple_call_lhs (stmt);
2437 didx = get_stridx (dst);
2438 if (didx < 0)
2439 return;
2441 dsi = NULL;
2442 if (didx > 0)
2443 dsi = get_strinfo (didx);
2445 srclen = NULL_TREE;
2446 si = NULL;
2447 idx = get_stridx (src);
2448 if (idx < 0)
2449 srclen = build_int_cst (size_type_node, ~idx);
2450 else if (idx > 0)
2452 si = get_strinfo (idx);
2453 if (si != NULL)
2454 srclen = get_string_length (si);
2457 /* Set the no-warning bit on the transformed statement? */
2458 bool set_no_warning = false;
2460 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2463 /* The concatenation always involves copying at least one byte
2464 (the terminating nul), even if the source string is empty.
2465 If the source is unknown assume it's one character long and
2466 used that as both sizes. */
2467 tree slen = srclen;
2468 if (slen)
2470 tree type = TREE_TYPE (slen);
2471 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2474 tree sptr = si && si->ptr ? si->ptr : src;
2476 if (!check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
2478 gimple_set_no_warning (stmt, true);
2479 set_no_warning = true;
2483 /* strcat (p, q) can be transformed into
2484 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2485 with length endptr - p if we need to compute the length
2486 later on. Don't do this transformation if we don't need
2487 it. */
2488 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2490 if (didx == 0)
2492 didx = new_stridx (dst);
2493 if (didx == 0)
2494 return;
2496 if (dsi == NULL)
2498 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2499 set_strinfo (didx, dsi);
2500 find_equal_ptrs (dst, didx);
2502 else
2504 dsi = unshare_strinfo (dsi);
2505 dsi->nonzero_chars = NULL_TREE;
2506 dsi->full_string_p = false;
2507 dsi->next = 0;
2508 dsi->endptr = NULL_TREE;
2510 dsi->writable = true;
2511 dsi->stmt = stmt;
2512 dsi->dont_invalidate = true;
2514 return;
2517 tree dstlen = dsi->nonzero_chars;
2518 endptr = dsi->endptr;
2520 dsi = unshare_strinfo (dsi);
2521 dsi->endptr = NULL_TREE;
2522 dsi->stmt = NULL;
2523 dsi->writable = true;
2525 if (srclen != NULL_TREE)
2527 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2528 TREE_TYPE (dsi->nonzero_chars),
2529 dsi->nonzero_chars, srclen);
2530 gcc_assert (dsi->full_string_p);
2531 adjust_related_strinfos (loc, dsi, srclen);
2532 dsi->dont_invalidate = true;
2534 else
2536 dsi->nonzero_chars = NULL;
2537 dsi->full_string_p = false;
2538 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2539 dsi->dont_invalidate = true;
2542 if (si != NULL)
2543 /* strcat src may not overlap dst, so src doesn't need to be
2544 invalidated either. */
2545 si->dont_invalidate = true;
2547 /* For now. Could remove the lhs from the call and add
2548 lhs = dst; afterwards. */
2549 if (lhs)
2550 return;
2552 fn = NULL_TREE;
2553 objsz = NULL_TREE;
2554 switch (bcode)
2556 case BUILT_IN_STRCAT:
2557 if (srclen != NULL_TREE)
2558 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2559 else
2560 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2561 break;
2562 case BUILT_IN_STRCAT_CHK:
2563 if (srclen != NULL_TREE)
2564 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2565 else
2566 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2567 objsz = gimple_call_arg (stmt, 2);
2568 break;
2569 default:
2570 gcc_unreachable ();
2573 if (fn == NULL_TREE)
2574 return;
2576 if (dsi && dstlen)
2578 tree type = TREE_TYPE (dstlen);
2580 /* Compute the size of the source sequence, including the nul. */
2581 tree srcsize = srclen ? srclen : size_zero_node;
2582 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2584 tree sptr = si && si->ptr ? si->ptr : src;
2586 if (!check_bounds_or_overlap (stmt, dst, sptr, dstlen, srcsize))
2588 gimple_set_no_warning (stmt, true);
2589 set_no_warning = true;
2593 tree len = NULL_TREE;
2594 if (srclen != NULL_TREE)
2596 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2597 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2599 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2600 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2601 build_int_cst (type, 1));
2602 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2603 GSI_SAME_STMT);
2605 if (endptr)
2606 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2607 else
2608 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dst), dst,
2609 fold_convert_loc (loc, sizetype,
2610 unshare_expr (dstlen)));
2611 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2612 GSI_SAME_STMT);
2613 if (objsz)
2615 objsz = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (objsz), objsz,
2616 fold_convert_loc (loc, TREE_TYPE (objsz),
2617 unshare_expr (dstlen)));
2618 objsz = force_gimple_operand_gsi (gsi, objsz, true, NULL_TREE, true,
2619 GSI_SAME_STMT);
2621 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2623 fprintf (dump_file, "Optimizing: ");
2624 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2626 if (srclen != NULL_TREE)
2627 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2628 dst, src, len, objsz);
2629 else
2630 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2631 dst, src, objsz);
2632 if (success)
2634 stmt = gsi_stmt (*gsi);
2635 update_stmt (stmt);
2636 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2638 fprintf (dump_file, "into: ");
2639 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2641 /* If srclen == NULL, note that current string length can be
2642 computed by transforming this strcpy into stpcpy. */
2643 if (srclen == NULL_TREE && dsi->dont_invalidate)
2644 dsi->stmt = stmt;
2645 adjust_last_stmt (dsi, stmt, true);
2646 if (srclen != NULL_TREE)
2648 laststmt.stmt = stmt;
2649 laststmt.len = srclen;
2650 laststmt.stridx = dsi->idx;
2653 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2654 fprintf (dump_file, "not possible.\n");
2656 if (set_no_warning)
2657 gimple_set_no_warning (stmt, true);
2660 /* Handle a call to malloc or calloc. */
2662 static void
2663 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2665 gimple *stmt = gsi_stmt (*gsi);
2666 tree lhs = gimple_call_lhs (stmt);
2667 if (lhs == NULL_TREE)
2668 return;
2670 gcc_assert (get_stridx (lhs) == 0);
2671 int idx = new_stridx (lhs);
2672 tree length = NULL_TREE;
2673 if (bcode == BUILT_IN_CALLOC)
2674 length = build_int_cst (size_type_node, 0);
2675 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2676 if (bcode == BUILT_IN_CALLOC)
2677 si->endptr = lhs;
2678 set_strinfo (idx, si);
2679 si->writable = true;
2680 si->stmt = stmt;
2681 si->dont_invalidate = true;
2684 /* Handle a call to memset.
2685 After a call to calloc, memset(,0,) is unnecessary.
2686 memset(malloc(n),0,n) is calloc(n,1).
2687 return true when the call is transfomred, false otherwise. */
2689 static bool
2690 handle_builtin_memset (gimple_stmt_iterator *gsi)
2692 gimple *stmt2 = gsi_stmt (*gsi);
2693 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2694 return false;
2695 tree ptr = gimple_call_arg (stmt2, 0);
2696 int idx1 = get_stridx (ptr);
2697 if (idx1 <= 0)
2698 return false;
2699 strinfo *si1 = get_strinfo (idx1);
2700 if (!si1)
2701 return false;
2702 gimple *stmt1 = si1->stmt;
2703 if (!stmt1 || !is_gimple_call (stmt1))
2704 return false;
2705 tree callee1 = gimple_call_fndecl (stmt1);
2706 if (!valid_builtin_call (stmt1))
2707 return false;
2708 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2709 tree size = gimple_call_arg (stmt2, 2);
2710 if (code1 == BUILT_IN_CALLOC)
2711 /* Not touching stmt1 */ ;
2712 else if (code1 == BUILT_IN_MALLOC
2713 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2715 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2716 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2717 size, build_one_cst (size_type_node));
2718 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2719 si1->full_string_p = true;
2720 si1->stmt = gsi_stmt (gsi1);
2722 else
2723 return false;
2724 tree lhs = gimple_call_lhs (stmt2);
2725 unlink_stmt_vdef (stmt2);
2726 if (lhs)
2728 gimple *assign = gimple_build_assign (lhs, ptr);
2729 gsi_replace (gsi, assign, false);
2731 else
2733 gsi_remove (gsi, true);
2734 release_defs (stmt2);
2737 return true;
2740 /* Handle a call to memcmp. We try to handle small comparisons by
2741 converting them to load and compare, and replacing the call to memcmp
2742 with a __builtin_memcmp_eq call where possible.
2743 return true when call is transformed, return false otherwise. */
2745 static bool
2746 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2748 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2749 tree res = gimple_call_lhs (stmt2);
2750 tree arg1 = gimple_call_arg (stmt2, 0);
2751 tree arg2 = gimple_call_arg (stmt2, 1);
2752 tree len = gimple_call_arg (stmt2, 2);
2753 unsigned HOST_WIDE_INT leni;
2754 use_operand_p use_p;
2755 imm_use_iterator iter;
2757 if (!res)
2758 return false;
2760 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2762 gimple *ustmt = USE_STMT (use_p);
2764 if (is_gimple_debug (ustmt))
2765 continue;
2766 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2768 gassign *asgn = as_a <gassign *> (ustmt);
2769 tree_code code = gimple_assign_rhs_code (asgn);
2770 if ((code != EQ_EXPR && code != NE_EXPR)
2771 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2772 return false;
2774 else if (gimple_code (ustmt) == GIMPLE_COND)
2776 tree_code code = gimple_cond_code (ustmt);
2777 if ((code != EQ_EXPR && code != NE_EXPR)
2778 || !integer_zerop (gimple_cond_rhs (ustmt)))
2779 return false;
2781 else
2782 return false;
2785 if (tree_fits_uhwi_p (len)
2786 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2787 && pow2p_hwi (leni))
2789 leni *= CHAR_TYPE_SIZE;
2790 unsigned align1 = get_pointer_alignment (arg1);
2791 unsigned align2 = get_pointer_alignment (arg2);
2792 unsigned align = MIN (align1, align2);
2793 scalar_int_mode mode;
2794 if (int_mode_for_size (leni, 1).exists (&mode)
2795 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2797 location_t loc = gimple_location (stmt2);
2798 tree type, off;
2799 type = build_nonstandard_integer_type (leni, 1);
2800 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
2801 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2802 ptr_mode, true);
2803 off = build_int_cst (ptrtype, 0);
2804 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2805 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2806 tree tem1 = fold_const_aggregate_ref (arg1);
2807 if (tem1)
2808 arg1 = tem1;
2809 tree tem2 = fold_const_aggregate_ref (arg2);
2810 if (tem2)
2811 arg2 = tem2;
2812 res = fold_convert_loc (loc, TREE_TYPE (res),
2813 fold_build2_loc (loc, NE_EXPR,
2814 boolean_type_node,
2815 arg1, arg2));
2816 gimplify_and_update_call_from_tree (gsi, res);
2817 return true;
2821 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2822 return true;
2825 /* Given an index to the strinfo vector, compute the string length for the
2826 corresponding string. Return -1 when unknown. */
2828 static HOST_WIDE_INT
2829 compute_string_length (int idx)
2831 HOST_WIDE_INT string_leni = -1;
2832 gcc_assert (idx != 0);
2834 if (idx < 0)
2835 return ~idx;
2837 strinfo *si = get_strinfo (idx);
2838 if (si)
2840 tree const_string_len = get_string_length (si);
2841 if (const_string_len && tree_fits_shwi_p (const_string_len))
2842 string_leni = tree_to_shwi (const_string_len);
2845 if (string_leni < 0)
2846 return -1;
2848 return string_leni;
2851 /* Determine the minimum size of the object referenced by DEST expression which
2852 must have a pointer type.
2853 Return the minimum size of the object if successful or NULL when the size
2854 cannot be determined. */
2855 static tree
2856 determine_min_objsize (tree dest)
2858 unsigned HOST_WIDE_INT size = 0;
2860 if (compute_builtin_object_size (dest, 2, &size))
2861 return build_int_cst (sizetype, size);
2863 /* Try to determine the size of the object through the RHS of the
2864 assign statement. */
2865 if (TREE_CODE (dest) == SSA_NAME)
2867 gimple *stmt = SSA_NAME_DEF_STMT (dest);
2868 if (!is_gimple_assign (stmt))
2869 return NULL_TREE;
2871 if (!gimple_assign_single_p (stmt)
2872 && !gimple_assign_unary_nop_p (stmt))
2873 return NULL_TREE;
2875 dest = gimple_assign_rhs1 (stmt);
2876 return determine_min_objsize (dest);
2879 /* Try to determine the size of the object from its type. */
2880 if (TREE_CODE (dest) != ADDR_EXPR)
2881 return NULL_TREE;
2883 tree type = TREE_TYPE (dest);
2884 if (TREE_CODE (type) == POINTER_TYPE)
2885 type = TREE_TYPE (type);
2887 type = TYPE_MAIN_VARIANT (type);
2889 /* We cannot determine the size of the array if it's a flexible array,
2890 which is declared at the end of a structure. */
2891 if (TREE_CODE (type) == ARRAY_TYPE
2892 && !array_at_struct_end_p (dest))
2894 tree size_t = TYPE_SIZE_UNIT (type);
2895 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2896 && !integer_zerop (size_t))
2897 return size_t;
2900 return NULL_TREE;
2903 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2904 equality test against zero:
2906 A. When the lengths of both arguments are constant and it's a strcmp:
2907 * if the lengths are NOT equal, we can safely fold the call
2908 to a non-zero value.
2909 * otherwise, do nothing now.
2911 B. When the length of one argument is constant, try to replace the call with
2912 a __builtin_str(n)cmp_eq call where possible, i.e:
2914 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2915 string with constant length , C is a constant.
2916 if (C <= strlen(STR) && sizeof_array(s) > C)
2918 replace this call with
2919 strncmp_eq (s, STR, C) (!)= 0
2921 if (C > strlen(STR)
2923 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2924 can handled by the following strcmp.
2927 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2928 string with constant length.
2929 if (sizeof_array(s) > strlen(STR))
2931 replace this call with
2932 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2935 Return true when the call is transformed, return false otherwise.
2938 static bool
2939 handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
2941 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
2942 tree res = gimple_call_lhs (stmt);
2943 use_operand_p use_p;
2944 imm_use_iterator iter;
2945 tree arg1 = gimple_call_arg (stmt, 0);
2946 tree arg2 = gimple_call_arg (stmt, 1);
2947 int idx1 = get_stridx (arg1);
2948 int idx2 = get_stridx (arg2);
2949 HOST_WIDE_INT length = -1;
2950 bool is_ncmp = false;
2952 if (!res)
2953 return false;
2955 /* When both arguments are unknown, do nothing. */
2956 if (idx1 == 0 && idx2 == 0)
2957 return false;
2959 /* Handle strncmp function. */
2960 if (gimple_call_num_args (stmt) == 3)
2962 tree len = gimple_call_arg (stmt, 2);
2963 if (tree_fits_shwi_p (len))
2964 length = tree_to_shwi (len);
2966 is_ncmp = true;
2969 /* For strncmp, if the length argument is NOT known, do nothing. */
2970 if (is_ncmp && length < 0)
2971 return false;
2973 /* When the result is ONLY used to do equality test against zero. */
2974 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2976 gimple *use_stmt = USE_STMT (use_p);
2978 if (is_gimple_debug (use_stmt))
2979 continue;
2980 if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
2982 tree_code code = gimple_assign_rhs_code (use_stmt);
2983 if (code == COND_EXPR)
2985 tree cond_expr = gimple_assign_rhs1 (use_stmt);
2986 if ((TREE_CODE (cond_expr) != EQ_EXPR
2987 && (TREE_CODE (cond_expr) != NE_EXPR))
2988 || !integer_zerop (TREE_OPERAND (cond_expr, 1)))
2989 return false;
2991 else if (code == EQ_EXPR || code == NE_EXPR)
2993 if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
2994 return false;
2996 else
2997 return false;
2999 else if (gimple_code (use_stmt) == GIMPLE_COND)
3001 tree_code code = gimple_cond_code (use_stmt);
3002 if ((code != EQ_EXPR && code != NE_EXPR)
3003 || !integer_zerop (gimple_cond_rhs (use_stmt)))
3004 return false;
3006 else
3007 return false;
3010 /* When the lengths of both arguments are known, and they are unequal, we can
3011 safely fold the call to a non-zero value for strcmp;
3012 othewise, do nothing now. */
3013 if (idx1 != 0 && idx2 != 0)
3015 HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
3016 HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
3018 if (!is_ncmp
3019 && const_string_leni1 != -1
3020 && const_string_leni2 != -1
3021 && const_string_leni1 != const_string_leni2)
3023 replace_call_with_value (gsi, integer_one_node);
3024 return true;
3026 return false;
3029 /* When the length of one argument is constant. */
3030 tree var_string = NULL_TREE;
3031 HOST_WIDE_INT const_string_leni = -1;
3033 if (idx1)
3035 const_string_leni = compute_string_length (idx1);
3036 var_string = arg2;
3038 else
3040 gcc_checking_assert (idx2);
3041 const_string_leni = compute_string_length (idx2);
3042 var_string = arg1;
3045 if (const_string_leni < 0)
3046 return false;
3048 unsigned HOST_WIDE_INT var_sizei = 0;
3049 /* try to determine the minimum size of the object pointed by var_string. */
3050 tree size = determine_min_objsize (var_string);
3052 if (!size)
3053 return false;
3055 if (tree_fits_uhwi_p (size))
3056 var_sizei = tree_to_uhwi (size);
3058 if (var_sizei == 0)
3059 return false;
3061 /* For strncmp, if length > const_string_leni , this call can be safely
3062 transformed to a strcmp. */
3063 if (is_ncmp && length > const_string_leni)
3064 is_ncmp = false;
3066 unsigned HOST_WIDE_INT final_length
3067 = is_ncmp ? length : const_string_leni + 1;
3069 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
3070 if (var_sizei > final_length)
3072 tree fn
3073 = (is_ncmp
3074 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
3075 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
3076 if (!fn)
3077 return false;
3078 tree const_string_len = build_int_cst (size_type_node, final_length);
3079 update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
3081 else
3082 return false;
3084 return true;
3087 /* Handle a POINTER_PLUS_EXPR statement.
3088 For p = "abcd" + 2; compute associated length, or if
3089 p = q + off is pointing to a '\0' character of a string, call
3090 zero_length_string on it. */
3092 static void
3093 handle_pointer_plus (gimple_stmt_iterator *gsi)
3095 gimple *stmt = gsi_stmt (*gsi);
3096 tree lhs = gimple_assign_lhs (stmt), off;
3097 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3098 strinfo *si, *zsi;
3100 if (idx == 0)
3101 return;
3103 if (idx < 0)
3105 tree off = gimple_assign_rhs2 (stmt);
3106 if (tree_fits_uhwi_p (off)
3107 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
3108 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
3109 = ~(~idx - (int) tree_to_uhwi (off));
3110 return;
3113 si = get_strinfo (idx);
3114 if (si == NULL || si->nonzero_chars == NULL_TREE)
3115 return;
3117 off = gimple_assign_rhs2 (stmt);
3118 zsi = NULL;
3119 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
3120 zsi = zero_length_string (lhs, si);
3121 else if (TREE_CODE (off) == SSA_NAME)
3123 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
3124 if (gimple_assign_single_p (def_stmt)
3125 && si->full_string_p
3126 && operand_equal_p (si->nonzero_chars,
3127 gimple_assign_rhs1 (def_stmt), 0))
3128 zsi = zero_length_string (lhs, si);
3130 if (zsi != NULL
3131 && si->endptr != NULL_TREE
3132 && si->endptr != lhs
3133 && TREE_CODE (si->endptr) == SSA_NAME)
3135 enum tree_code rhs_code
3136 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
3137 ? SSA_NAME : NOP_EXPR;
3138 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
3139 gcc_assert (gsi_stmt (*gsi) == stmt);
3140 update_stmt (stmt);
3144 /* If RHS, either directly or indirectly, refers to a string of constant
3145 length, return the length. Otherwise, if it refers to a character
3146 constant, return 1 if the constant is non-zero and 0 if it is nul.
3147 Otherwise, return a negative value. */
3149 static HOST_WIDE_INT
3150 get_min_string_length (tree rhs, bool *full_string_p)
3152 if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
3154 if (tree_expr_nonzero_p (rhs))
3156 *full_string_p = false;
3157 return 1;
3160 *full_string_p = true;
3161 return 0;
3164 if (TREE_CODE (rhs) == MEM_REF
3165 && integer_zerop (TREE_OPERAND (rhs, 1)))
3167 rhs = TREE_OPERAND (rhs, 0);
3168 if (TREE_CODE (rhs) == ADDR_EXPR)
3170 tree rhs_addr = rhs;
3172 rhs = TREE_OPERAND (rhs, 0);
3173 if (TREE_CODE (rhs) != STRING_CST)
3175 int idx = get_stridx (rhs_addr);
3176 if (idx > 0)
3178 strinfo *si = get_strinfo (idx);
3179 if (si
3180 && tree_fits_shwi_p (si->nonzero_chars))
3182 *full_string_p = si->full_string_p;
3183 return tree_to_shwi (si->nonzero_chars);
3190 if (TREE_CODE (rhs) == VAR_DECL
3191 && TREE_READONLY (rhs))
3192 rhs = DECL_INITIAL (rhs);
3194 if (rhs && TREE_CODE (rhs) == STRING_CST)
3196 *full_string_p = true;
3197 return strlen (TREE_STRING_POINTER (rhs));
3200 return -1;
3203 /* Handle a single or multiple character store either by single
3204 character assignment or by multi-character assignment from
3205 MEM_REF. */
3207 static bool
3208 handle_char_store (gimple_stmt_iterator *gsi)
3210 int idx = -1;
3211 strinfo *si = NULL;
3212 gimple *stmt = gsi_stmt (*gsi);
3213 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
3214 tree rhs = gimple_assign_rhs1 (stmt);
3215 unsigned HOST_WIDE_INT offset = 0;
3217 if (TREE_CODE (lhs) == MEM_REF
3218 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
3220 tree mem_offset = TREE_OPERAND (lhs, 1);
3221 if (tree_fits_uhwi_p (mem_offset))
3223 /* Get the strinfo for the base, and use it if it starts with at
3224 least OFFSET nonzero characters. This is trivially true if
3225 OFFSET is zero. */
3226 offset = tree_to_uhwi (mem_offset);
3227 idx = get_stridx (TREE_OPERAND (lhs, 0));
3228 if (idx > 0)
3229 si = get_strinfo (idx);
3230 if (offset == 0)
3231 ssaname = TREE_OPERAND (lhs, 0);
3232 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
3233 return true;
3236 else
3238 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
3239 if (idx > 0)
3240 si = get_strinfo (idx);
3243 /* STORING_NONZERO_P is true iff not all stored characters are zero.
3244 STORING_ALL_ZEROS_P is true iff all stored characters are zero.
3245 Both are false when it's impossible to determine which is true. */
3246 bool storing_nonzero_p;
3247 bool storing_all_zeros_p = initializer_zerop (rhs, &storing_nonzero_p);
3248 if (!storing_nonzero_p)
3249 storing_nonzero_p = tree_expr_nonzero_p (rhs);
3250 bool full_string_p = storing_all_zeros_p;
3252 /* Set to the length of the string being assigned if known. */
3253 HOST_WIDE_INT rhslen;
3255 if (si != NULL)
3257 int cmp = compare_nonzero_chars (si, offset);
3258 gcc_assert (offset == 0 || cmp >= 0);
3259 if (storing_all_zeros_p && cmp == 0 && si->full_string_p)
3261 /* When overwriting a '\0' with a '\0', the store can be removed
3262 if we know it has been stored in the current function. */
3263 if (!stmt_could_throw_p (cfun, stmt) && si->writable)
3265 unlink_stmt_vdef (stmt);
3266 release_defs (stmt);
3267 gsi_remove (gsi, true);
3268 return false;
3270 else
3272 si->writable = true;
3273 gsi_next (gsi);
3274 return false;
3277 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3278 and if we aren't storing '\0', we know that the length of the
3279 string and any other zero terminated string in memory remains
3280 the same. In that case we move to the next gimple statement and
3281 return to signal the caller that it shouldn't invalidate anything.
3283 This is benefical for cases like:
3285 char p[20];
3286 void foo (char *q)
3288 strcpy (p, "foobar");
3289 size_t len = strlen (p); // This can be optimized into 6
3290 size_t len2 = strlen (q); // This has to be computed
3291 p[0] = 'X';
3292 size_t len3 = strlen (p); // This can be optimized into 6
3293 size_t len4 = strlen (q); // This can be optimized into len2
3294 bar (len, len2, len3, len4);
3297 else if (storing_nonzero_p && cmp > 0)
3299 gsi_next (gsi);
3300 return false;
3302 else if (storing_all_zeros_p || storing_nonzero_p || (offset != 0 && cmp > 0))
3304 /* When STORING_NONZERO_P, we know that the string will start
3305 with at least OFFSET + 1 nonzero characters. If storing
3306 a single character, set si->NONZERO_CHARS to the result.
3307 If storing multiple characters, try to determine the number
3308 of leading non-zero characters and set si->NONZERO_CHARS to
3309 the result instead.
3311 When STORING_ALL_ZEROS_P, we know that the string is now
3312 OFFSET characters long.
3314 Otherwise, we're storing an unknown value at offset OFFSET,
3315 so need to clip the nonzero_chars to OFFSET. */
3316 bool full_string_p = storing_all_zeros_p;
3317 HOST_WIDE_INT len = 1;
3318 if (storing_nonzero_p)
3320 /* Try to get the minimum length of the string (or
3321 individual character) being stored. If it fails,
3322 STORING_NONZERO_P guarantees it's at least 1. */
3323 len = get_min_string_length (rhs, &full_string_p);
3324 if (len < 0)
3325 len = 1;
3328 location_t loc = gimple_location (stmt);
3329 tree oldlen = si->nonzero_chars;
3330 if (cmp == 0 && si->full_string_p)
3331 /* We're overwriting the nul terminator with a nonzero or
3332 unknown character. If the previous stmt was a memcpy,
3333 its length may be decreased. */
3334 adjust_last_stmt (si, stmt, false);
3335 si = unshare_strinfo (si);
3336 if (storing_nonzero_p)
3338 gcc_assert (len >= 0);
3339 si->nonzero_chars = build_int_cst (size_type_node, offset + len);
3341 else
3342 si->nonzero_chars = build_int_cst (size_type_node, offset);
3343 si->full_string_p = full_string_p;
3344 if (storing_all_zeros_p
3345 && ssaname
3346 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3347 si->endptr = ssaname;
3348 else
3349 si->endptr = NULL;
3350 si->next = 0;
3351 si->stmt = NULL;
3352 si->writable = true;
3353 si->dont_invalidate = true;
3354 if (oldlen)
3356 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
3357 si->nonzero_chars, oldlen);
3358 adjust_related_strinfos (loc, si, adj);
3360 else
3361 si->prev = 0;
3364 else if (idx == 0 && (storing_all_zeros_p || storing_nonzero_p))
3366 if (ssaname)
3367 idx = new_stridx (ssaname);
3368 else
3369 idx = new_addr_stridx (lhs);
3370 if (idx != 0)
3372 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
3373 HOST_WIDE_INT slen = (storing_all_zeros_p
3375 : (storing_nonzero_p
3376 ? get_min_string_length (rhs, &full_string_p)
3377 : -1));
3378 tree len = (slen <= 0
3379 ? size_zero_node
3380 : build_int_cst (size_type_node, slen));
3381 si = new_strinfo (ptr, idx, len, slen >= 0 && full_string_p);
3382 set_strinfo (idx, si);
3383 if (storing_all_zeros_p
3384 && ssaname
3385 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3386 si->endptr = ssaname;
3387 si->dont_invalidate = true;
3388 si->writable = true;
3391 else if (idx == 0
3392 && (rhslen = get_min_string_length (rhs, &full_string_p)) >= 0
3393 && ssaname == NULL_TREE
3394 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
3396 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
3397 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
3399 int idx = new_addr_stridx (lhs);
3400 if (idx != 0)
3402 si = new_strinfo (build_fold_addr_expr (lhs), idx,
3403 build_int_cst (size_type_node, rhslen),
3404 full_string_p);
3405 set_strinfo (idx, si);
3406 si->dont_invalidate = true;
3411 if (si != NULL && offset == 0 && storing_all_zeros_p)
3413 /* Allow adjust_last_stmt to remove it if the stored '\0'
3414 is immediately overwritten. */
3415 laststmt.stmt = stmt;
3416 laststmt.len = build_int_cst (size_type_node, 1);
3417 laststmt.stridx = si->idx;
3419 return true;
3422 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3424 static void
3425 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3427 if (TREE_CODE (rhs1) != SSA_NAME
3428 || TREE_CODE (rhs2) != SSA_NAME)
3429 return;
3431 gimple *call_stmt = NULL;
3432 for (int pass = 0; pass < 2; pass++)
3434 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3435 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3436 && has_single_use (rhs1)
3437 && gimple_call_arg (g, 0) == rhs2)
3439 call_stmt = g;
3440 break;
3442 std::swap (rhs1, rhs2);
3445 if (call_stmt)
3447 tree arg0 = gimple_call_arg (call_stmt, 0);
3449 if (arg0 == rhs2)
3451 tree arg1 = gimple_call_arg (call_stmt, 1);
3452 tree arg1_len = NULL_TREE;
3453 int idx = get_stridx (arg1);
3455 if (idx)
3457 if (idx < 0)
3458 arg1_len = build_int_cst (size_type_node, ~idx);
3459 else
3461 strinfo *si = get_strinfo (idx);
3462 if (si)
3463 arg1_len = get_string_length (si);
3467 if (arg1_len != NULL_TREE)
3469 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3470 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3472 if (!is_gimple_val (arg1_len))
3474 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3475 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3476 arg1_len);
3477 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3478 arg1_len = arg1_len_tmp;
3481 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3482 arg0, arg1, arg1_len);
3483 tree strncmp_lhs = make_ssa_name (integer_type_node);
3484 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3485 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3486 gsi_remove (&gsi, true);
3487 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3488 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3490 if (is_gimple_assign (stmt))
3492 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3494 tree cond = gimple_assign_rhs1 (stmt);
3495 TREE_OPERAND (cond, 0) = strncmp_lhs;
3496 TREE_OPERAND (cond, 1) = zero;
3498 else
3500 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3501 gimple_assign_set_rhs2 (stmt, zero);
3504 else
3506 gcond *cond = as_a<gcond *> (stmt);
3507 gimple_cond_set_lhs (cond, strncmp_lhs);
3508 gimple_cond_set_rhs (cond, zero);
3510 update_stmt (stmt);
3516 /* Attempt to check for validity of the performed access a single statement
3517 at *GSI using string length knowledge, and to optimize it.
3518 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3519 true. */
3521 static bool
3522 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
3524 gimple *stmt = gsi_stmt (*gsi);
3526 if (is_gimple_call (stmt))
3528 tree callee = gimple_call_fndecl (stmt);
3529 if (valid_builtin_call (stmt))
3530 switch (DECL_FUNCTION_CODE (callee))
3532 case BUILT_IN_STRLEN:
3533 case BUILT_IN_STRNLEN:
3534 handle_builtin_strlen (gsi);
3535 break;
3536 case BUILT_IN_STRCHR:
3537 handle_builtin_strchr (gsi);
3538 break;
3539 case BUILT_IN_STRCPY:
3540 case BUILT_IN_STRCPY_CHK:
3541 case BUILT_IN_STPCPY:
3542 case BUILT_IN_STPCPY_CHK:
3543 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3544 break;
3546 case BUILT_IN_STRNCAT:
3547 case BUILT_IN_STRNCAT_CHK:
3548 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3549 break;
3551 case BUILT_IN_STPNCPY:
3552 case BUILT_IN_STPNCPY_CHK:
3553 case BUILT_IN_STRNCPY:
3554 case BUILT_IN_STRNCPY_CHK:
3555 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3556 break;
3558 case BUILT_IN_MEMCPY:
3559 case BUILT_IN_MEMCPY_CHK:
3560 case BUILT_IN_MEMPCPY:
3561 case BUILT_IN_MEMPCPY_CHK:
3562 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3563 break;
3564 case BUILT_IN_STRCAT:
3565 case BUILT_IN_STRCAT_CHK:
3566 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3567 break;
3568 case BUILT_IN_MALLOC:
3569 case BUILT_IN_CALLOC:
3570 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3571 break;
3572 case BUILT_IN_MEMSET:
3573 if (handle_builtin_memset (gsi))
3574 return false;
3575 break;
3576 case BUILT_IN_MEMCMP:
3577 if (handle_builtin_memcmp (gsi))
3578 return false;
3579 break;
3580 case BUILT_IN_STRCMP:
3581 case BUILT_IN_STRNCMP:
3582 if (handle_builtin_string_cmp (gsi))
3583 return false;
3584 break;
3585 default:
3586 break;
3589 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3591 tree lhs = gimple_assign_lhs (stmt);
3593 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3595 if (gimple_assign_single_p (stmt)
3596 || (gimple_assign_cast_p (stmt)
3597 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3599 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3600 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3602 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3603 handle_pointer_plus (gsi);
3605 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3607 enum tree_code code = gimple_assign_rhs_code (stmt);
3608 if (code == COND_EXPR)
3610 tree cond = gimple_assign_rhs1 (stmt);
3611 enum tree_code cond_code = TREE_CODE (cond);
3613 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3614 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3615 TREE_OPERAND (cond, 1), stmt);
3617 else if (code == EQ_EXPR || code == NE_EXPR)
3618 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3619 gimple_assign_rhs2 (stmt), stmt);
3620 else if (gimple_assign_load_p (stmt)
3621 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3622 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3623 && (TYPE_PRECISION (TREE_TYPE (lhs))
3624 == TYPE_PRECISION (char_type_node))
3625 && !gimple_has_volatile_ops (stmt))
3627 tree off = integer_zero_node;
3628 unsigned HOST_WIDE_INT coff = 0;
3629 int idx = 0;
3630 tree rhs1 = gimple_assign_rhs1 (stmt);
3631 if (code == MEM_REF)
3633 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3634 if (idx > 0)
3636 strinfo *si = get_strinfo (idx);
3637 if (si
3638 && si->nonzero_chars
3639 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3640 && (wi::to_widest (si->nonzero_chars)
3641 >= wi::to_widest (off)))
3642 off = TREE_OPERAND (rhs1, 1);
3643 else
3644 /* This case is not useful. See if get_addr_stridx
3645 returns something usable. */
3646 idx = 0;
3649 if (idx <= 0)
3650 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3651 if (idx > 0)
3653 strinfo *si = get_strinfo (idx);
3654 if (si
3655 && si->nonzero_chars
3656 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3658 widest_int w1 = wi::to_widest (si->nonzero_chars);
3659 widest_int w2 = wi::to_widest (off) + coff;
3660 if (w1 == w2
3661 && si->full_string_p)
3663 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3665 fprintf (dump_file, "Optimizing: ");
3666 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3669 /* Reading the final '\0' character. */
3670 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3671 gimple_set_vuse (stmt, NULL_TREE);
3672 gimple_assign_set_rhs_from_tree (gsi, zero);
3673 *cleanup_eh
3674 |= maybe_clean_or_replace_eh_stmt (stmt,
3675 gsi_stmt (*gsi));
3676 stmt = gsi_stmt (*gsi);
3677 update_stmt (stmt);
3679 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3681 fprintf (dump_file, "into: ");
3682 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3685 else if (w1 > w2)
3687 /* Reading a character before the final '\0'
3688 character. Just set the value range to ~[0, 0]
3689 if we don't have anything better. */
3690 wide_int min, max;
3691 tree type = TREE_TYPE (lhs);
3692 enum value_range_kind vr
3693 = get_range_info (lhs, &min, &max);
3694 if (vr == VR_VARYING
3695 || (vr == VR_RANGE
3696 && min == wi::min_value (TYPE_PRECISION (type),
3697 TYPE_SIGN (type))
3698 && max == wi::max_value (TYPE_PRECISION (type),
3699 TYPE_SIGN (type))))
3700 set_range_info (lhs, VR_ANTI_RANGE,
3701 wi::zero (TYPE_PRECISION (type)),
3702 wi::zero (TYPE_PRECISION (type)));
3708 if (strlen_to_stridx)
3710 tree rhs1 = gimple_assign_rhs1 (stmt);
3711 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3712 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3715 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3717 tree type = TREE_TYPE (lhs);
3718 if (TREE_CODE (type) == ARRAY_TYPE)
3719 type = TREE_TYPE (type);
3720 if (TREE_CODE (type) == INTEGER_TYPE
3721 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3722 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3724 if (! handle_char_store (gsi))
3725 return false;
3729 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3731 enum tree_code code = gimple_cond_code (cond);
3732 if (code == EQ_EXPR || code == NE_EXPR)
3733 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3734 gimple_cond_rhs (stmt), stmt);
3737 if (gimple_vdef (stmt))
3738 maybe_invalidate (stmt);
3739 return true;
3742 /* Recursively call maybe_invalidate on stmts that might be executed
3743 in between dombb and current bb and that contain a vdef. Stop when
3744 *count stmts are inspected, or if the whole strinfo vector has
3745 been invalidated. */
3747 static void
3748 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3750 unsigned int i, n = gimple_phi_num_args (phi);
3752 for (i = 0; i < n; i++)
3754 tree vuse = gimple_phi_arg_def (phi, i);
3755 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3756 basic_block bb = gimple_bb (stmt);
3757 if (bb == NULL
3758 || bb == dombb
3759 || !bitmap_set_bit (visited, bb->index)
3760 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3761 continue;
3762 while (1)
3764 if (gimple_code (stmt) == GIMPLE_PHI)
3766 do_invalidate (dombb, stmt, visited, count);
3767 if (*count == 0)
3768 return;
3769 break;
3771 if (--*count == 0)
3772 return;
3773 if (!maybe_invalidate (stmt))
3775 *count = 0;
3776 return;
3778 vuse = gimple_vuse (stmt);
3779 stmt = SSA_NAME_DEF_STMT (vuse);
3780 if (gimple_bb (stmt) != bb)
3782 bb = gimple_bb (stmt);
3783 if (bb == NULL
3784 || bb == dombb
3785 || !bitmap_set_bit (visited, bb->index)
3786 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3787 break;
3793 class strlen_dom_walker : public dom_walker
3795 public:
3796 strlen_dom_walker (cdi_direction direction)
3797 : dom_walker (direction), m_cleanup_cfg (false)
3800 virtual edge before_dom_children (basic_block);
3801 virtual void after_dom_children (basic_block);
3803 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3804 execute function. */
3805 bool m_cleanup_cfg;
3808 /* Callback for walk_dominator_tree. Attempt to optimize various
3809 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3811 edge
3812 strlen_dom_walker::before_dom_children (basic_block bb)
3814 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3816 if (dombb == NULL)
3817 stridx_to_strinfo = NULL;
3818 else
3820 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3821 if (stridx_to_strinfo)
3823 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3824 gsi_next (&gsi))
3826 gphi *phi = gsi.phi ();
3827 if (virtual_operand_p (gimple_phi_result (phi)))
3829 bitmap visited = BITMAP_ALLOC (NULL);
3830 int count_vdef = 100;
3831 do_invalidate (dombb, phi, visited, &count_vdef);
3832 BITMAP_FREE (visited);
3833 if (count_vdef == 0)
3835 /* If there were too many vdefs in between immediate
3836 dominator and current bb, invalidate everything.
3837 If stridx_to_strinfo has been unshared, we need
3838 to free it, otherwise just set it to NULL. */
3839 if (!strinfo_shared ())
3841 unsigned int i;
3842 strinfo *si;
3844 for (i = 1;
3845 vec_safe_iterate (stridx_to_strinfo, i, &si);
3846 ++i)
3848 free_strinfo (si);
3849 (*stridx_to_strinfo)[i] = NULL;
3852 else
3853 stridx_to_strinfo = NULL;
3855 break;
3861 /* If all PHI arguments have the same string index, the PHI result
3862 has it as well. */
3863 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3864 gsi_next (&gsi))
3866 gphi *phi = gsi.phi ();
3867 tree result = gimple_phi_result (phi);
3868 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3870 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3871 if (idx != 0)
3873 unsigned int i, n = gimple_phi_num_args (phi);
3874 for (i = 1; i < n; i++)
3875 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3876 break;
3877 if (i == n)
3878 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3883 bool cleanup_eh = false;
3885 /* Attempt to optimize individual statements. */
3886 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3887 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
3888 gsi_next (&gsi);
3890 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
3891 m_cleanup_cfg = true;
3893 bb->aux = stridx_to_strinfo;
3894 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3895 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3896 return NULL;
3899 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3900 owned by the current bb, clear bb->aux. */
3902 void
3903 strlen_dom_walker::after_dom_children (basic_block bb)
3905 if (bb->aux)
3907 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3908 if (vec_safe_length (stridx_to_strinfo)
3909 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3911 unsigned int i;
3912 strinfo *si;
3914 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3915 free_strinfo (si);
3916 vec_free (stridx_to_strinfo);
3918 bb->aux = NULL;
3922 /* Main entry point. */
3924 namespace {
3926 const pass_data pass_data_strlen =
3928 GIMPLE_PASS, /* type */
3929 "strlen", /* name */
3930 OPTGROUP_NONE, /* optinfo_flags */
3931 TV_TREE_STRLEN, /* tv_id */
3932 ( PROP_cfg | PROP_ssa ), /* properties_required */
3933 0, /* properties_provided */
3934 0, /* properties_destroyed */
3935 0, /* todo_flags_start */
3936 0, /* todo_flags_finish */
3939 class pass_strlen : public gimple_opt_pass
3941 public:
3942 pass_strlen (gcc::context *ctxt)
3943 : gimple_opt_pass (pass_data_strlen, ctxt)
3946 /* opt_pass methods: */
3947 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3948 virtual unsigned int execute (function *);
3950 }; // class pass_strlen
3952 unsigned int
3953 pass_strlen::execute (function *fun)
3955 gcc_assert (!strlen_to_stridx);
3956 if (warn_stringop_overflow || warn_stringop_truncation)
3957 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3959 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3960 max_stridx = 1;
3962 calculate_dominance_info (CDI_DOMINATORS);
3964 /* String length optimization is implemented as a walk of the dominator
3965 tree and a forward walk of statements within each block. */
3966 strlen_dom_walker walker (CDI_DOMINATORS);
3967 walker.walk (fun->cfg->x_entry_block_ptr);
3969 ssa_ver_to_stridx.release ();
3970 strinfo_pool.release ();
3971 if (decl_to_stridxlist_htab)
3973 obstack_free (&stridx_obstack, NULL);
3974 delete decl_to_stridxlist_htab;
3975 decl_to_stridxlist_htab = NULL;
3977 laststmt.stmt = NULL;
3978 laststmt.len = NULL_TREE;
3979 laststmt.stridx = 0;
3981 if (strlen_to_stridx)
3983 strlen_to_stridx->empty ();
3984 delete strlen_to_stridx;
3985 strlen_to_stridx = NULL;
3988 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
3991 } // anon namespace
3993 gimple_opt_pass *
3994 make_pass_strlen (gcc::context *ctxt)
3996 return new pass_strlen (ctxt);