Daily bump.
[official-gcc.git] / gcc / tree-ssa-strlen.c
blobd625b940c1fd151096b45f130533ef7503a8c3e0
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 tree s, o;
296 if (TREE_CODE (exp) == SSA_NAME)
298 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
299 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
300 int i;
301 tree e = exp;
302 HOST_WIDE_INT off = 0;
303 for (i = 0; i < 5; i++)
305 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
306 if (!is_gimple_assign (def_stmt)
307 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
308 return 0;
309 tree rhs1 = gimple_assign_rhs1 (def_stmt);
310 tree rhs2 = gimple_assign_rhs2 (def_stmt);
311 if (TREE_CODE (rhs1) != SSA_NAME
312 || !tree_fits_shwi_p (rhs2))
313 return 0;
314 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
315 if (this_off < 0)
316 return 0;
317 off = (unsigned HOST_WIDE_INT) off + this_off;
318 if (off < 0)
319 return 0;
320 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
322 strinfo *si
323 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
324 if (si && compare_nonzero_chars (si, off) >= 0)
325 return get_stridx_plus_constant (si, off, exp);
327 e = rhs1;
329 return 0;
332 if (TREE_CODE (exp) == ADDR_EXPR)
334 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
335 if (idx != 0)
336 return idx;
339 s = string_constant (exp, &o, NULL, NULL);
340 if (s != NULL_TREE
341 && (o == NULL_TREE || tree_fits_shwi_p (o))
342 && TREE_STRING_LENGTH (s) > 0)
344 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
345 const char *p = TREE_STRING_POINTER (s);
346 int max = TREE_STRING_LENGTH (s) - 1;
348 if (p[max] == '\0' && offset >= 0 && offset <= max)
349 return ~(int) strlen (p + offset);
351 return 0;
354 /* Return true if strinfo vector is shared with the immediate dominator. */
356 static inline bool
357 strinfo_shared (void)
359 return vec_safe_length (stridx_to_strinfo)
360 && (*stridx_to_strinfo)[0] != NULL;
363 /* Unshare strinfo vector that is shared with the immediate dominator. */
365 static void
366 unshare_strinfo_vec (void)
368 strinfo *si;
369 unsigned int i = 0;
371 gcc_assert (strinfo_shared ());
372 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
373 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
374 if (si != NULL)
375 si->refcount++;
376 (*stridx_to_strinfo)[0] = NULL;
379 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
380 Return a pointer to the location where the string index can
381 be stored (if 0) or is stored, or NULL if this can't be tracked. */
383 static int *
384 addr_stridxptr (tree exp)
386 HOST_WIDE_INT off;
388 poly_int64 poff;
389 tree base = get_addr_base_and_unit_offset (exp, &poff);
390 if (base == NULL_TREE || !DECL_P (base) || !poff.is_constant (&off))
391 return NULL;
393 if (!decl_to_stridxlist_htab)
395 decl_to_stridxlist_htab
396 = new hash_map<tree_decl_hash, stridxlist> (64);
397 gcc_obstack_init (&stridx_obstack);
400 bool existed;
401 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
402 if (existed)
404 int i;
405 stridxlist *before = NULL;
406 for (i = 0; i < 32; i++)
408 if (list->offset == off)
409 return &list->idx;
410 if (list->offset > off && before == NULL)
411 before = list;
412 if (list->next == NULL)
413 break;
414 list = list->next;
416 if (i == 32)
417 return NULL;
418 if (before)
420 list = before;
421 before = XOBNEW (&stridx_obstack, struct stridxlist);
422 *before = *list;
423 list->next = before;
424 list->offset = off;
425 list->idx = 0;
426 return &list->idx;
428 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
429 list = list->next;
432 list->next = NULL;
433 list->offset = off;
434 list->idx = 0;
435 return &list->idx;
438 /* Create a new string index, or return 0 if reached limit. */
440 static int
441 new_stridx (tree exp)
443 int idx;
444 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
445 return 0;
446 if (TREE_CODE (exp) == SSA_NAME)
448 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
449 return 0;
450 idx = max_stridx++;
451 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
452 return idx;
454 if (TREE_CODE (exp) == ADDR_EXPR)
456 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
457 if (pidx != NULL)
459 gcc_assert (*pidx == 0);
460 *pidx = max_stridx++;
461 return *pidx;
464 return 0;
467 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
469 static int
470 new_addr_stridx (tree exp)
472 int *pidx;
473 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
474 return 0;
475 pidx = addr_stridxptr (exp);
476 if (pidx != NULL)
478 gcc_assert (*pidx == 0);
479 *pidx = max_stridx++;
480 return *pidx;
482 return 0;
485 /* Create a new strinfo. */
487 static strinfo *
488 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
490 strinfo *si = strinfo_pool.allocate ();
491 si->nonzero_chars = nonzero_chars;
492 si->ptr = ptr;
493 si->stmt = NULL;
494 si->endptr = NULL_TREE;
495 si->refcount = 1;
496 si->idx = idx;
497 si->first = 0;
498 si->prev = 0;
499 si->next = 0;
500 si->writable = false;
501 si->dont_invalidate = false;
502 si->full_string_p = full_string_p;
503 return si;
506 /* Decrease strinfo refcount and free it if not referenced anymore. */
508 static inline void
509 free_strinfo (strinfo *si)
511 if (si && --si->refcount == 0)
512 strinfo_pool.remove (si);
515 /* Set strinfo in the vector entry IDX to SI. */
517 static inline void
518 set_strinfo (int idx, strinfo *si)
520 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
521 unshare_strinfo_vec ();
522 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
523 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
524 (*stridx_to_strinfo)[idx] = si;
527 /* Return the first strinfo in the related strinfo chain
528 if all strinfos in between belong to the chain, otherwise NULL. */
530 static strinfo *
531 verify_related_strinfos (strinfo *origsi)
533 strinfo *si = origsi, *psi;
535 if (origsi->first == 0)
536 return NULL;
537 for (; si->prev; si = psi)
539 if (si->first != origsi->first)
540 return NULL;
541 psi = get_strinfo (si->prev);
542 if (psi == NULL)
543 return NULL;
544 if (psi->next != si->idx)
545 return NULL;
547 if (si->idx != si->first)
548 return NULL;
549 return si;
552 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
553 Use LOC for folding. */
555 static void
556 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
558 si->endptr = endptr;
559 si->stmt = NULL;
560 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
561 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
562 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
563 end_as_size, start_as_size);
564 si->full_string_p = true;
567 /* Return string length, or NULL if it can't be computed. */
569 static tree
570 get_string_length (strinfo *si)
572 if (si->nonzero_chars)
573 return si->full_string_p ? si->nonzero_chars : NULL;
575 if (si->stmt)
577 gimple *stmt = si->stmt, *lenstmt;
578 tree callee, lhs, fn, tem;
579 location_t loc;
580 gimple_stmt_iterator gsi;
582 gcc_assert (is_gimple_call (stmt));
583 callee = gimple_call_fndecl (stmt);
584 gcc_assert (callee && fndecl_built_in_p (callee, BUILT_IN_NORMAL));
585 lhs = gimple_call_lhs (stmt);
586 /* unshare_strinfo is intentionally not called here. The (delayed)
587 transformation of strcpy or strcat into stpcpy is done at the place
588 of the former strcpy/strcat call and so can affect all the strinfos
589 with the same stmt. If they were unshared before and transformation
590 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
591 just compute the right length. */
592 switch (DECL_FUNCTION_CODE (callee))
594 case BUILT_IN_STRCAT:
595 case BUILT_IN_STRCAT_CHK:
596 gsi = gsi_for_stmt (stmt);
597 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
598 gcc_assert (lhs == NULL_TREE);
599 tem = unshare_expr (gimple_call_arg (stmt, 0));
600 lenstmt = gimple_build_call (fn, 1, tem);
601 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
602 gimple_call_set_lhs (lenstmt, lhs);
603 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
604 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
605 tem = gimple_call_arg (stmt, 0);
606 if (!ptrofftype_p (TREE_TYPE (lhs)))
608 lhs = convert_to_ptrofftype (lhs);
609 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
610 true, GSI_SAME_STMT);
612 lenstmt = gimple_build_assign
613 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
614 POINTER_PLUS_EXPR,tem, lhs);
615 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
616 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
617 lhs = NULL_TREE;
618 /* FALLTHRU */
619 case BUILT_IN_STRCPY:
620 case BUILT_IN_STRCPY_CHK:
621 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
622 if (gimple_call_num_args (stmt) == 2)
623 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
624 else
625 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
626 gcc_assert (lhs == NULL_TREE);
627 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
629 fprintf (dump_file, "Optimizing: ");
630 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
632 gimple_call_set_fndecl (stmt, fn);
633 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
634 gimple_call_set_lhs (stmt, lhs);
635 update_stmt (stmt);
636 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
638 fprintf (dump_file, "into: ");
639 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
641 /* FALLTHRU */
642 case BUILT_IN_STPCPY:
643 case BUILT_IN_STPCPY_CHK:
644 gcc_assert (lhs != NULL_TREE);
645 loc = gimple_location (stmt);
646 set_endptr_and_length (loc, si, lhs);
647 for (strinfo *chainsi = verify_related_strinfos (si);
648 chainsi != NULL;
649 chainsi = get_next_strinfo (chainsi))
650 if (chainsi->nonzero_chars == NULL)
651 set_endptr_and_length (loc, chainsi, lhs);
652 break;
653 case BUILT_IN_MALLOC:
654 break;
655 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
656 default:
657 gcc_unreachable ();
658 break;
662 return si->nonzero_chars;
665 /* Invalidate string length information for strings whose length
666 might change due to stores in stmt. */
668 static bool
669 maybe_invalidate (gimple *stmt)
671 strinfo *si;
672 unsigned int i;
673 bool nonempty = false;
675 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
676 if (si != NULL)
678 if (!si->dont_invalidate)
680 ao_ref r;
681 /* Do not use si->nonzero_chars. */
682 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
683 if (stmt_may_clobber_ref_p_1 (stmt, &r))
685 set_strinfo (i, NULL);
686 free_strinfo (si);
687 continue;
690 si->dont_invalidate = false;
691 nonempty = true;
693 return nonempty;
696 /* Unshare strinfo record SI, if it has refcount > 1 or
697 if stridx_to_strinfo vector is shared with some other
698 bbs. */
700 static strinfo *
701 unshare_strinfo (strinfo *si)
703 strinfo *nsi;
705 if (si->refcount == 1 && !strinfo_shared ())
706 return si;
708 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
709 nsi->stmt = si->stmt;
710 nsi->endptr = si->endptr;
711 nsi->first = si->first;
712 nsi->prev = si->prev;
713 nsi->next = si->next;
714 nsi->writable = si->writable;
715 set_strinfo (si->idx, nsi);
716 free_strinfo (si);
717 return nsi;
720 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
721 strinfo if there is any. Return it's idx, or 0 if no strinfo has
722 been created. */
724 static int
725 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
726 tree ptr)
728 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
729 return 0;
731 if (compare_nonzero_chars (basesi, off) < 0
732 || !tree_fits_uhwi_p (basesi->nonzero_chars))
733 return 0;
735 unsigned HOST_WIDE_INT nonzero_chars
736 = tree_to_uhwi (basesi->nonzero_chars) - off;
737 strinfo *si = basesi, *chainsi;
738 if (si->first || si->prev || si->next)
739 si = verify_related_strinfos (basesi);
740 if (si == NULL
741 || si->nonzero_chars == NULL_TREE
742 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
743 return 0;
745 if (TREE_CODE (ptr) == SSA_NAME
746 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
747 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
749 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
750 for (chainsi = si; chainsi->next; chainsi = si)
752 si = get_next_strinfo (chainsi);
753 if (si == NULL
754 || si->nonzero_chars == NULL_TREE
755 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
756 break;
757 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
758 if (r != 1)
760 if (r == 0)
762 if (TREE_CODE (ptr) == SSA_NAME)
763 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
764 else
766 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
767 if (pidx != NULL && *pidx == 0)
768 *pidx = si->idx;
770 return si->idx;
772 break;
776 int idx = new_stridx (ptr);
777 if (idx == 0)
778 return 0;
779 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
780 basesi->full_string_p);
781 set_strinfo (idx, si);
782 if (strinfo *nextsi = get_strinfo (chainsi->next))
784 nextsi = unshare_strinfo (nextsi);
785 si->next = nextsi->idx;
786 nextsi->prev = idx;
788 chainsi = unshare_strinfo (chainsi);
789 if (chainsi->first == 0)
790 chainsi->first = chainsi->idx;
791 chainsi->next = idx;
792 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
793 chainsi->endptr = ptr;
794 si->endptr = chainsi->endptr;
795 si->prev = chainsi->idx;
796 si->first = chainsi->first;
797 si->writable = chainsi->writable;
798 return si->idx;
801 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
802 to a zero-length string and if possible chain it to a related strinfo
803 chain whose part is or might be CHAINSI. */
805 static strinfo *
806 zero_length_string (tree ptr, strinfo *chainsi)
808 strinfo *si;
809 int idx;
810 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
811 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
812 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
813 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
815 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
816 return NULL;
817 if (chainsi != NULL)
819 si = verify_related_strinfos (chainsi);
820 if (si)
824 /* We shouldn't mix delayed and non-delayed lengths. */
825 gcc_assert (si->full_string_p);
826 if (si->endptr == NULL_TREE)
828 si = unshare_strinfo (si);
829 si->endptr = ptr;
831 chainsi = si;
832 si = get_next_strinfo (si);
834 while (si != NULL);
835 if (zero_length_string_p (chainsi))
837 if (chainsi->next)
839 chainsi = unshare_strinfo (chainsi);
840 chainsi->next = 0;
842 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
843 return chainsi;
846 else
848 /* We shouldn't mix delayed and non-delayed lengths. */
849 gcc_assert (chainsi->full_string_p);
850 if (chainsi->first || chainsi->prev || chainsi->next)
852 chainsi = unshare_strinfo (chainsi);
853 chainsi->first = 0;
854 chainsi->prev = 0;
855 chainsi->next = 0;
859 idx = new_stridx (ptr);
860 if (idx == 0)
861 return NULL;
862 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
863 set_strinfo (idx, si);
864 si->endptr = ptr;
865 if (chainsi != NULL)
867 chainsi = unshare_strinfo (chainsi);
868 if (chainsi->first == 0)
869 chainsi->first = chainsi->idx;
870 chainsi->next = idx;
871 if (chainsi->endptr == NULL_TREE)
872 chainsi->endptr = ptr;
873 si->prev = chainsi->idx;
874 si->first = chainsi->first;
875 si->writable = chainsi->writable;
877 return si;
880 /* For strinfo ORIGSI whose length has been just updated, adjust other
881 related strinfos so that they match the new ORIGSI. This involves:
883 - adding ADJ to the nonzero_chars fields
884 - copying full_string_p from the new ORIGSI. */
886 static void
887 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
889 strinfo *si = verify_related_strinfos (origsi);
891 if (si == NULL)
892 return;
894 while (1)
896 strinfo *nsi;
898 if (si != origsi)
900 tree tem;
902 si = unshare_strinfo (si);
903 /* We shouldn't see delayed lengths here; the caller must have
904 calculated the old length in order to calculate the
905 adjustment. */
906 gcc_assert (si->nonzero_chars);
907 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
908 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
909 TREE_TYPE (si->nonzero_chars),
910 si->nonzero_chars, tem);
911 si->full_string_p = origsi->full_string_p;
913 si->endptr = NULL_TREE;
914 si->dont_invalidate = true;
916 nsi = get_next_strinfo (si);
917 if (nsi == NULL)
918 return;
919 si = nsi;
923 /* Find if there are other SSA_NAME pointers equal to PTR
924 for which we don't track their string lengths yet. If so, use
925 IDX for them. */
927 static void
928 find_equal_ptrs (tree ptr, int idx)
930 if (TREE_CODE (ptr) != SSA_NAME)
931 return;
932 while (1)
934 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
935 if (!is_gimple_assign (stmt))
936 return;
937 ptr = gimple_assign_rhs1 (stmt);
938 switch (gimple_assign_rhs_code (stmt))
940 case SSA_NAME:
941 break;
942 CASE_CONVERT:
943 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
944 return;
945 if (TREE_CODE (ptr) == SSA_NAME)
946 break;
947 if (TREE_CODE (ptr) != ADDR_EXPR)
948 return;
949 /* FALLTHRU */
950 case ADDR_EXPR:
952 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
953 if (pidx != NULL && *pidx == 0)
954 *pidx = idx;
955 return;
957 default:
958 return;
961 /* We might find an endptr created in this pass. Grow the
962 vector in that case. */
963 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
964 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
966 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
967 return;
968 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
972 /* Return true if STMT is a call to a builtin function with the right
973 arguments and attributes that should be considered for optimization
974 by this pass. */
976 static bool
977 valid_builtin_call (gimple *stmt)
979 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
980 return false;
982 tree callee = gimple_call_fndecl (stmt);
983 switch (DECL_FUNCTION_CODE (callee))
985 case BUILT_IN_MEMCMP:
986 case BUILT_IN_MEMCMP_EQ:
987 case BUILT_IN_STRCHR:
988 case BUILT_IN_STRLEN:
989 /* The above functions should be pure. Punt if they aren't. */
990 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
991 return false;
992 break;
994 case BUILT_IN_CALLOC:
995 case BUILT_IN_MALLOC:
996 case BUILT_IN_MEMCPY:
997 case BUILT_IN_MEMCPY_CHK:
998 case BUILT_IN_MEMPCPY:
999 case BUILT_IN_MEMPCPY_CHK:
1000 case BUILT_IN_MEMSET:
1001 case BUILT_IN_STPCPY:
1002 case BUILT_IN_STPCPY_CHK:
1003 case BUILT_IN_STRCAT:
1004 case BUILT_IN_STRCAT_CHK:
1005 case BUILT_IN_STRCPY:
1006 case BUILT_IN_STRCPY_CHK:
1007 /* The above functions should be neither const nor pure. Punt if they
1008 aren't. */
1009 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1010 return false;
1011 break;
1013 default:
1014 break;
1017 return true;
1020 /* If the last .MEM setter statement before STMT is
1021 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1022 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1023 just memcpy (x, y, strlen (y)). SI must be the zero length
1024 strinfo. */
1026 static void
1027 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1029 tree vuse, callee, len;
1030 struct laststmt_struct last = laststmt;
1031 strinfo *lastsi, *firstsi;
1032 unsigned len_arg_no = 2;
1034 laststmt.stmt = NULL;
1035 laststmt.len = NULL_TREE;
1036 laststmt.stridx = 0;
1038 if (last.stmt == NULL)
1039 return;
1041 vuse = gimple_vuse (stmt);
1042 if (vuse == NULL_TREE
1043 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1044 || !has_single_use (vuse))
1045 return;
1047 gcc_assert (last.stridx > 0);
1048 lastsi = get_strinfo (last.stridx);
1049 if (lastsi == NULL)
1050 return;
1052 if (lastsi != si)
1054 if (lastsi->first == 0 || lastsi->first != si->first)
1055 return;
1057 firstsi = verify_related_strinfos (si);
1058 if (firstsi == NULL)
1059 return;
1060 while (firstsi != lastsi)
1062 firstsi = get_next_strinfo (firstsi);
1063 if (firstsi == NULL)
1064 return;
1068 if (!is_strcat && !zero_length_string_p (si))
1069 return;
1071 if (is_gimple_assign (last.stmt))
1073 gimple_stmt_iterator gsi;
1075 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1076 return;
1077 if (stmt_could_throw_p (last.stmt))
1078 return;
1079 gsi = gsi_for_stmt (last.stmt);
1080 unlink_stmt_vdef (last.stmt);
1081 release_defs (last.stmt);
1082 gsi_remove (&gsi, true);
1083 return;
1086 if (!valid_builtin_call (last.stmt))
1087 return;
1089 callee = gimple_call_fndecl (last.stmt);
1090 switch (DECL_FUNCTION_CODE (callee))
1092 case BUILT_IN_MEMCPY:
1093 case BUILT_IN_MEMCPY_CHK:
1094 break;
1095 default:
1096 return;
1099 len = gimple_call_arg (last.stmt, len_arg_no);
1100 if (tree_fits_uhwi_p (len))
1102 if (!tree_fits_uhwi_p (last.len)
1103 || integer_zerop (len)
1104 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1105 return;
1106 /* Don't adjust the length if it is divisible by 4, it is more efficient
1107 to store the extra '\0' in that case. */
1108 if ((tree_to_uhwi (len) & 3) == 0)
1109 return;
1111 /* Don't fold away an out of bounds access, as this defeats proper
1112 warnings. */
1113 tree dst = gimple_call_arg (last.stmt, 0);
1114 tree size = compute_objsize (dst, 0);
1115 if (size && tree_int_cst_lt (size, len))
1116 return;
1118 else if (TREE_CODE (len) == SSA_NAME)
1120 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1121 if (!is_gimple_assign (def_stmt)
1122 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1123 || gimple_assign_rhs1 (def_stmt) != last.len
1124 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1125 return;
1127 else
1128 return;
1130 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1131 update_stmt (last.stmt);
1134 /* For an LHS that is an SSA_NAME and for strlen() or strnlen() argument
1135 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1136 a character array A[N] with unknown length bounded by N, and for
1137 strnlen(), by min (N, BOUND). */
1139 static tree
1140 maybe_set_strlen_range (tree lhs, tree src, tree bound)
1142 if (TREE_CODE (lhs) != SSA_NAME
1143 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
1144 return NULL_TREE;
1146 if (TREE_CODE (src) == SSA_NAME)
1148 gimple *def = SSA_NAME_DEF_STMT (src);
1149 if (is_gimple_assign (def)
1150 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1151 src = gimple_assign_rhs1 (def);
1154 wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1155 wide_int min = wi::zero (max.get_precision ());
1157 if (TREE_CODE (src) == ADDR_EXPR)
1159 /* The last array member of a struct can be bigger than its size
1160 suggests if it's treated as a poor-man's flexible array member. */
1161 src = TREE_OPERAND (src, 0);
1162 bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE;
1163 if (src_is_array
1164 && TREE_CODE (src) != MEM_REF
1165 && !array_at_struct_end_p (src))
1167 tree type = TREE_TYPE (src);
1168 if (tree size = TYPE_SIZE_UNIT (type))
1169 if (size && TREE_CODE (size) == INTEGER_CST)
1170 max = wi::to_wide (size);
1172 /* For strlen() the upper bound above is equal to
1173 the longest string that can be stored in the array
1174 (i.e., it accounts for the terminating nul. For
1175 strnlen() bump up the maximum by one since the array
1176 need not be nul-terminated. */
1177 if (!bound && max != 0)
1178 --max;
1180 else
1182 if (TREE_CODE (src) == COMPONENT_REF && !src_is_array)
1183 src = TREE_OPERAND (src, 1);
1184 if (DECL_P (src))
1186 /* Handle the unlikely case of strlen (&c) where c is some
1187 variable. */
1188 if (tree size = DECL_SIZE_UNIT (src))
1189 if (TREE_CODE (size) == INTEGER_CST)
1190 max = wi::to_wide (size);
1195 if (bound)
1197 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1198 is less than the size of the array set MAX to it. It it's
1199 greater than MAX and MAX is non-zero bump MAX down to account
1200 for the necessary terminating nul. Otherwise leave it alone. */
1201 if (TREE_CODE (bound) == INTEGER_CST)
1203 wide_int wibnd = wi::to_wide (bound);
1204 int cmp = wi::cmpu (wibnd, max);
1205 if (cmp < 0)
1206 max = wibnd;
1207 else if (cmp && wi::ne_p (max, min))
1208 --max;
1210 else if (TREE_CODE (bound) == SSA_NAME)
1212 wide_int minbound, maxbound;
1213 value_range_type rng = get_range_info (bound, &minbound, &maxbound);
1214 if (rng == VR_RANGE)
1216 /* For a bound in a known range, adjust the range determined
1217 above as necessary. For a bound in some anti-range or
1218 in an unknown range, use the range determined above. */
1219 if (wi::ltu_p (minbound, min))
1220 min = minbound;
1221 if (wi::ltu_p (maxbound, max))
1222 max = maxbound;
1227 if (min == max)
1228 return wide_int_to_tree (size_type_node, min);
1230 set_range_info (lhs, VR_RANGE, min, max);
1231 return lhs;
1234 /* Handle a strlen call. If strlen of the argument is known, replace
1235 the strlen call with the known value, otherwise remember that strlen
1236 of the argument is stored in the lhs SSA_NAME. */
1238 static void
1239 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1241 gimple *stmt = gsi_stmt (*gsi);
1242 tree lhs = gimple_call_lhs (stmt);
1244 if (lhs == NULL_TREE)
1245 return;
1247 location_t loc = gimple_location (stmt);
1248 tree callee = gimple_call_fndecl (stmt);
1249 tree src = gimple_call_arg (stmt, 0);
1250 tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
1251 ? gimple_call_arg (stmt, 1) : NULL_TREE);
1252 int idx = get_stridx (src);
1253 if (idx)
1255 strinfo *si = NULL;
1256 tree rhs;
1258 if (idx < 0)
1259 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1260 else
1262 rhs = NULL_TREE;
1263 si = get_strinfo (idx);
1264 if (si != NULL)
1265 rhs = get_string_length (si);
1267 if (rhs != NULL_TREE)
1269 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1271 fprintf (dump_file, "Optimizing: ");
1272 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1274 rhs = unshare_expr (rhs);
1275 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1276 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1278 /* Set for strnlen() calls with a non-constant bound. */
1279 bool noncst_bound = false;
1280 if (bound)
1282 tree new_rhs
1283 = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
1285 noncst_bound = (TREE_CODE (new_rhs) != INTEGER_CST
1286 || tree_int_cst_lt (new_rhs, rhs));
1288 rhs = new_rhs;
1291 if (!update_call_from_tree (gsi, rhs))
1292 gimplify_and_update_call_from_tree (gsi, rhs);
1293 stmt = gsi_stmt (*gsi);
1294 update_stmt (stmt);
1295 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1297 fprintf (dump_file, "into: ");
1298 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1301 /* Avoid storing the length for calls to strnlen() with
1302 a non-constant bound. */
1303 if (noncst_bound)
1304 return;
1306 if (si != NULL
1307 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1308 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1309 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1311 si = unshare_strinfo (si);
1312 si->nonzero_chars = lhs;
1313 gcc_assert (si->full_string_p);
1316 if (strlen_to_stridx)
1317 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1319 return;
1322 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1323 return;
1325 if (idx == 0)
1326 idx = new_stridx (src);
1327 else
1329 strinfo *si = get_strinfo (idx);
1330 if (si != NULL)
1332 if (!si->full_string_p && !si->stmt)
1334 /* Until now we only had a lower bound on the string length.
1335 Install LHS as the actual length. */
1336 si = unshare_strinfo (si);
1337 tree old = si->nonzero_chars;
1338 si->nonzero_chars = lhs;
1339 si->full_string_p = true;
1340 if (TREE_CODE (old) == INTEGER_CST)
1342 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1343 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1344 TREE_TYPE (lhs), lhs, old);
1345 adjust_related_strinfos (loc, si, adj);
1347 else
1349 si->first = 0;
1350 si->prev = 0;
1351 si->next = 0;
1354 return;
1357 if (idx)
1359 if (!bound)
1361 /* Only store the new length information for calls to strlen(),
1362 not for those to strnlen(). */
1363 strinfo *si = new_strinfo (src, idx, lhs, true);
1364 set_strinfo (idx, si);
1365 find_equal_ptrs (src, idx);
1368 /* For SRC that is an array of N elements, set LHS's range
1369 to [0, min (N, BOUND)]. A constant return value means
1370 the range would have consisted of a single value. In
1371 that case, fold the result into the returned constant. */
1372 if (tree ret = maybe_set_strlen_range (lhs, src, bound))
1373 if (TREE_CODE (ret) == INTEGER_CST)
1375 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1377 fprintf (dump_file, "Optimizing: ");
1378 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1380 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
1381 ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
1382 if (!update_call_from_tree (gsi, ret))
1383 gimplify_and_update_call_from_tree (gsi, ret);
1384 stmt = gsi_stmt (*gsi);
1385 update_stmt (stmt);
1386 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1388 fprintf (dump_file, "into: ");
1389 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1393 if (strlen_to_stridx && !bound)
1394 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1398 /* Handle a strchr call. If strlen of the first argument is known, replace
1399 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1400 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1402 static void
1403 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1405 int idx;
1406 tree src;
1407 gimple *stmt = gsi_stmt (*gsi);
1408 tree lhs = gimple_call_lhs (stmt);
1410 if (lhs == NULL_TREE)
1411 return;
1413 if (!integer_zerop (gimple_call_arg (stmt, 1)))
1414 return;
1416 src = gimple_call_arg (stmt, 0);
1417 idx = get_stridx (src);
1418 if (idx)
1420 strinfo *si = NULL;
1421 tree rhs;
1423 if (idx < 0)
1424 rhs = build_int_cst (size_type_node, ~idx);
1425 else
1427 rhs = NULL_TREE;
1428 si = get_strinfo (idx);
1429 if (si != NULL)
1430 rhs = get_string_length (si);
1432 if (rhs != NULL_TREE)
1434 location_t loc = gimple_location (stmt);
1436 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1438 fprintf (dump_file, "Optimizing: ");
1439 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1441 if (si != NULL && si->endptr != NULL_TREE)
1443 rhs = unshare_expr (si->endptr);
1444 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1445 TREE_TYPE (rhs)))
1446 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1448 else
1450 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1451 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1452 TREE_TYPE (src), src, rhs);
1453 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1454 TREE_TYPE (rhs)))
1455 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1457 if (!update_call_from_tree (gsi, rhs))
1458 gimplify_and_update_call_from_tree (gsi, rhs);
1459 stmt = gsi_stmt (*gsi);
1460 update_stmt (stmt);
1461 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1463 fprintf (dump_file, "into: ");
1464 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1466 if (si != NULL
1467 && si->endptr == NULL_TREE
1468 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1470 si = unshare_strinfo (si);
1471 si->endptr = lhs;
1473 zero_length_string (lhs, si);
1474 return;
1477 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1478 return;
1479 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1481 if (idx == 0)
1482 idx = new_stridx (src);
1483 else if (get_strinfo (idx) != NULL)
1485 zero_length_string (lhs, NULL);
1486 return;
1488 if (idx)
1490 location_t loc = gimple_location (stmt);
1491 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1492 tree srcu = fold_convert_loc (loc, size_type_node, src);
1493 tree length = fold_build2_loc (loc, MINUS_EXPR,
1494 size_type_node, lhsu, srcu);
1495 strinfo *si = new_strinfo (src, idx, length, true);
1496 si->endptr = lhs;
1497 set_strinfo (idx, si);
1498 find_equal_ptrs (src, idx);
1499 zero_length_string (lhs, si);
1502 else
1503 zero_length_string (lhs, NULL);
1506 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1507 If strlen of the second argument is known, strlen of the first argument
1508 is the same after this call. Furthermore, attempt to convert it to
1509 memcpy. */
1511 static void
1512 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1514 int idx, didx;
1515 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1516 bool success;
1517 gimple *stmt = gsi_stmt (*gsi);
1518 strinfo *si, *dsi, *olddsi, *zsi;
1519 location_t loc;
1521 src = gimple_call_arg (stmt, 1);
1522 dst = gimple_call_arg (stmt, 0);
1523 lhs = gimple_call_lhs (stmt);
1524 idx = get_stridx (src);
1525 si = NULL;
1526 if (idx > 0)
1527 si = get_strinfo (idx);
1529 didx = get_stridx (dst);
1530 olddsi = NULL;
1531 oldlen = NULL_TREE;
1532 if (didx > 0)
1533 olddsi = get_strinfo (didx);
1534 else if (didx < 0)
1535 return;
1537 if (olddsi != NULL)
1538 adjust_last_stmt (olddsi, stmt, false);
1540 srclen = NULL_TREE;
1541 if (si != NULL)
1542 srclen = get_string_length (si);
1543 else if (idx < 0)
1544 srclen = build_int_cst (size_type_node, ~idx);
1546 loc = gimple_location (stmt);
1547 if (srclen == NULL_TREE)
1548 switch (bcode)
1550 case BUILT_IN_STRCPY:
1551 case BUILT_IN_STRCPY_CHK:
1552 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1553 return;
1554 break;
1555 case BUILT_IN_STPCPY:
1556 case BUILT_IN_STPCPY_CHK:
1557 if (lhs == NULL_TREE)
1558 return;
1559 else
1561 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1562 srclen = fold_convert_loc (loc, size_type_node, dst);
1563 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1564 lhsuint, srclen);
1566 break;
1567 default:
1568 gcc_unreachable ();
1571 if (didx == 0)
1573 didx = new_stridx (dst);
1574 if (didx == 0)
1575 return;
1577 if (olddsi != NULL)
1579 oldlen = olddsi->nonzero_chars;
1580 dsi = unshare_strinfo (olddsi);
1581 dsi->nonzero_chars = srclen;
1582 dsi->full_string_p = (srclen != NULL_TREE);
1583 /* Break the chain, so adjust_related_strinfo on later pointers in
1584 the chain won't adjust this one anymore. */
1585 dsi->next = 0;
1586 dsi->stmt = NULL;
1587 dsi->endptr = NULL_TREE;
1589 else
1591 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1592 set_strinfo (didx, dsi);
1593 find_equal_ptrs (dst, didx);
1595 dsi->writable = true;
1596 dsi->dont_invalidate = true;
1598 if (dsi->nonzero_chars == NULL_TREE)
1600 strinfo *chainsi;
1602 /* If string length of src is unknown, use delayed length
1603 computation. If string lenth of dst will be needed, it
1604 can be computed by transforming this strcpy call into
1605 stpcpy and subtracting dst from the return value. */
1607 /* Look for earlier strings whose length could be determined if
1608 this strcpy is turned into an stpcpy. */
1610 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1612 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1614 /* When setting a stmt for delayed length computation
1615 prevent all strinfos through dsi from being
1616 invalidated. */
1617 chainsi = unshare_strinfo (chainsi);
1618 chainsi->stmt = stmt;
1619 chainsi->nonzero_chars = NULL_TREE;
1620 chainsi->full_string_p = false;
1621 chainsi->endptr = NULL_TREE;
1622 chainsi->dont_invalidate = true;
1625 dsi->stmt = stmt;
1627 /* Try to detect overlap before returning. This catches cases
1628 like strcpy (d, d + n) where n is non-constant whose range
1629 is such that (n <= strlen (d) holds).
1631 OLDDSI->NONZERO_chars may have been reset by this point with
1632 oldlen holding it original value. */
1633 if (olddsi && oldlen)
1635 /* Add 1 for the terminating NUL. */
1636 tree type = TREE_TYPE (oldlen);
1637 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1638 build_int_cst (type, 1));
1639 check_bounds_or_overlap (stmt, olddsi->ptr, src, oldlen, NULL_TREE);
1642 return;
1645 if (olddsi != NULL)
1647 tree adj = NULL_TREE;
1648 if (oldlen == NULL_TREE)
1650 else if (integer_zerop (oldlen))
1651 adj = srclen;
1652 else if (TREE_CODE (oldlen) == INTEGER_CST
1653 || TREE_CODE (srclen) == INTEGER_CST)
1654 adj = fold_build2_loc (loc, MINUS_EXPR,
1655 TREE_TYPE (srclen), srclen,
1656 fold_convert_loc (loc, TREE_TYPE (srclen),
1657 oldlen));
1658 if (adj != NULL_TREE)
1659 adjust_related_strinfos (loc, dsi, adj);
1660 else
1661 dsi->prev = 0;
1663 /* strcpy src may not overlap dst, so src doesn't need to be
1664 invalidated either. */
1665 if (si != NULL)
1666 si->dont_invalidate = true;
1668 fn = NULL_TREE;
1669 zsi = NULL;
1670 switch (bcode)
1672 case BUILT_IN_STRCPY:
1673 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1674 if (lhs)
1675 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1676 break;
1677 case BUILT_IN_STRCPY_CHK:
1678 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1679 if (lhs)
1680 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1681 break;
1682 case BUILT_IN_STPCPY:
1683 /* This would need adjustment of the lhs (subtract one),
1684 or detection that the trailing '\0' doesn't need to be
1685 written, if it will be immediately overwritten.
1686 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1687 if (lhs)
1689 dsi->endptr = lhs;
1690 zsi = zero_length_string (lhs, dsi);
1692 break;
1693 case BUILT_IN_STPCPY_CHK:
1694 /* This would need adjustment of the lhs (subtract one),
1695 or detection that the trailing '\0' doesn't need to be
1696 written, if it will be immediately overwritten.
1697 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1698 if (lhs)
1700 dsi->endptr = lhs;
1701 zsi = zero_length_string (lhs, dsi);
1703 break;
1704 default:
1705 gcc_unreachable ();
1707 if (zsi != NULL)
1708 zsi->dont_invalidate = true;
1710 if (fn)
1712 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1713 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1715 else
1716 type = size_type_node;
1718 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1719 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1721 /* Set the no-warning bit on the transformed statement? */
1722 bool set_no_warning = false;
1724 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1725 if (si
1726 && !check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
1728 gimple_set_no_warning (stmt, true);
1729 set_no_warning = true;
1732 if (fn == NULL_TREE)
1733 return;
1735 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1736 GSI_SAME_STMT);
1737 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1739 fprintf (dump_file, "Optimizing: ");
1740 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1742 if (gimple_call_num_args (stmt) == 2)
1743 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1744 else
1745 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1746 gimple_call_arg (stmt, 2));
1747 if (success)
1749 stmt = gsi_stmt (*gsi);
1750 update_stmt (stmt);
1751 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1753 fprintf (dump_file, "into: ");
1754 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1756 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1757 laststmt.stmt = stmt;
1758 laststmt.len = srclen;
1759 laststmt.stridx = dsi->idx;
1761 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1762 fprintf (dump_file, "not possible.\n");
1764 if (set_no_warning)
1765 gimple_set_no_warning (stmt, true);
1768 /* Check the size argument to the built-in forms of stpncpy and strncpy
1769 for out-of-bounds offsets or overlapping access, and to see if the
1770 size argument is derived from a call to strlen() on the source argument,
1771 and if so, issue an appropriate warning. */
1773 static void
1774 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1776 /* Same as stxncpy(). */
1777 handle_builtin_stxncpy (bcode, gsi);
1780 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1781 way. LEN can either be an integer expression, or a pointer (to char).
1782 When it is the latter (such as in recursive calls to self) is is
1783 assumed to be the argument in some call to strlen() whose relationship
1784 to SRC is being ascertained. */
1786 bool
1787 is_strlen_related_p (tree src, tree len)
1789 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1790 && operand_equal_p (src, len, 0))
1791 return true;
1793 if (TREE_CODE (len) != SSA_NAME)
1794 return false;
1796 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1797 if (!def_stmt)
1798 return false;
1800 if (is_gimple_call (def_stmt))
1802 tree func = gimple_call_fndecl (def_stmt);
1803 if (!valid_builtin_call (def_stmt)
1804 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1805 return false;
1807 tree arg = gimple_call_arg (def_stmt, 0);
1808 return is_strlen_related_p (src, arg);
1811 if (!is_gimple_assign (def_stmt))
1812 return false;
1814 tree_code code = gimple_assign_rhs_code (def_stmt);
1815 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1816 tree rhstype = TREE_TYPE (rhs1);
1818 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1819 || (INTEGRAL_TYPE_P (rhstype)
1820 && (code == BIT_AND_EXPR
1821 || code == NOP_EXPR)))
1823 /* Pointer plus (an integer), and truncation are considered among
1824 the (potentially) related expressions to strlen. */
1825 return is_strlen_related_p (src, rhs1);
1828 if (tree rhs2 = gimple_assign_rhs2 (def_stmt))
1830 /* Integer subtraction is considered strlen-related when both
1831 arguments are integers and second one is strlen-related. */
1832 rhstype = TREE_TYPE (rhs2);
1833 if (INTEGRAL_TYPE_P (rhstype) && code == MINUS_EXPR)
1834 return is_strlen_related_p (src, rhs2);
1837 return false;
1840 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1841 in gimple-fold.c.
1842 Check to see if the specified bound is a) equal to the size of
1843 the destination DST and if so, b) if it's immediately followed by
1844 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1845 do nothing. Return true if diagnostic has been issued.
1847 The purpose is to diagnose calls to strncpy and stpncpy that do
1848 not nul-terminate the copy while allowing for the idiom where
1849 such a call is immediately followed by setting the last element
1850 to nul, as in:
1851 char a[32];
1852 strncpy (a, s, sizeof a);
1853 a[sizeof a - 1] = '\0';
1856 bool
1857 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1859 gimple *stmt = gsi_stmt (gsi);
1860 if (gimple_no_warning_p (stmt))
1861 return false;
1863 wide_int cntrange[2];
1865 if (TREE_CODE (cnt) == INTEGER_CST)
1866 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1867 else if (TREE_CODE (cnt) == SSA_NAME)
1869 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1870 if (rng == VR_RANGE)
1872 else if (rng == VR_ANTI_RANGE)
1874 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1876 if (wi::ltu_p (cntrange[1], maxobjsize))
1878 cntrange[0] = cntrange[1] + 1;
1879 cntrange[1] = maxobjsize;
1881 else
1883 cntrange[1] = cntrange[0] - 1;
1884 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1887 else
1888 return false;
1890 else
1891 return false;
1893 /* Negative value is the constant string length. If it's less than
1894 the lower bound there is no truncation. Avoid calling get_stridx()
1895 when ssa_ver_to_stridx is empty. That implies the caller isn't
1896 running under the control of this pass and ssa_ver_to_stridx hasn't
1897 been created yet. */
1898 int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
1899 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1900 return false;
1902 tree dst = gimple_call_arg (stmt, 0);
1903 tree dstdecl = dst;
1904 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1905 dstdecl = TREE_OPERAND (dstdecl, 0);
1907 tree ref = NULL_TREE;
1909 if (!sidx)
1911 /* If the source is a non-string return early to avoid warning
1912 for possible truncation (if the truncation is certain SIDX
1913 is non-zero). */
1914 tree srcdecl = gimple_call_arg (stmt, 1);
1915 if (TREE_CODE (srcdecl) == ADDR_EXPR)
1916 srcdecl = TREE_OPERAND (srcdecl, 0);
1917 if (get_attr_nonstring_decl (srcdecl, &ref))
1918 return false;
1921 /* Likewise, if the destination refers to a an array/pointer declared
1922 nonstring return early. */
1923 if (get_attr_nonstring_decl (dstdecl, &ref))
1924 return false;
1926 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1927 avoid the truncation warning. */
1928 gsi_next_nondebug (&gsi);
1929 gimple *next_stmt = gsi_stmt (gsi);
1930 if (!next_stmt)
1932 /* When there is no statement in the same basic block check
1933 the immediate successor block. */
1934 if (basic_block bb = gimple_bb (stmt))
1936 if (single_succ_p (bb))
1938 /* For simplicity, ignore blocks with multiple outgoing
1939 edges for now and only consider successor blocks along
1940 normal edges. */
1941 edge e = EDGE_SUCC (bb, 0);
1942 if (!(e->flags & EDGE_ABNORMAL))
1944 gsi = gsi_start_bb (e->dest);
1945 next_stmt = gsi_stmt (gsi);
1946 if (next_stmt && is_gimple_debug (next_stmt))
1948 gsi_next_nondebug (&gsi);
1949 next_stmt = gsi_stmt (gsi);
1956 if (next_stmt && is_gimple_assign (next_stmt))
1958 tree lhs = gimple_assign_lhs (next_stmt);
1959 tree_code code = TREE_CODE (lhs);
1960 if (code == ARRAY_REF || code == MEM_REF)
1961 lhs = TREE_OPERAND (lhs, 0);
1963 tree func = gimple_call_fndecl (stmt);
1964 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1966 tree ret = gimple_call_lhs (stmt);
1967 if (ret && operand_equal_p (ret, lhs, 0))
1968 return false;
1971 /* Determine the base address and offset of the reference,
1972 ignoring the innermost array index. */
1973 if (TREE_CODE (ref) == ARRAY_REF)
1974 ref = TREE_OPERAND (ref, 0);
1976 poly_int64 dstoff;
1977 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1979 poly_int64 lhsoff;
1980 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1981 if (lhsbase
1982 && dstbase
1983 && known_eq (dstoff, lhsoff)
1984 && operand_equal_p (dstbase, lhsbase, 0))
1985 return false;
1988 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1989 wide_int lenrange[2];
1990 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1992 lenrange[0] = (sisrc->nonzero_chars
1993 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1994 ? wi::to_wide (sisrc->nonzero_chars)
1995 : wi::zero (prec));
1996 lenrange[1] = lenrange[0];
1998 else if (sidx < 0)
1999 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
2000 else
2002 tree range[2];
2003 get_range_strlen (src, range);
2004 if (range[0] != NULL_TREE
2005 && TREE_CODE (range[0]) == INTEGER_CST
2006 && range[1] != NULL_TREE
2007 && TREE_CODE (range[1]) == INTEGER_CST)
2009 lenrange[0] = wi::to_wide (range[0], prec);
2010 lenrange[1] = wi::to_wide (range[1], prec);
2012 else
2014 lenrange[0] = wi::shwi (0, prec);
2015 lenrange[1] = wi::shwi (-1, prec);
2019 location_t callloc = gimple_nonartificial_location (stmt);
2020 callloc = expansion_point_location_if_in_system_header (callloc);
2022 tree func = gimple_call_fndecl (stmt);
2024 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
2026 /* If the longest source string is shorter than the lower bound
2027 of the specified count the copy is definitely nul-terminated. */
2028 if (wi::ltu_p (lenrange[1], cntrange[0]))
2029 return false;
2031 if (wi::neg_p (lenrange[1]))
2033 /* The length of one of the strings is unknown but at least
2034 one has non-zero length and that length is stored in
2035 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2036 warning below. */
2037 lenrange[1] = lenrange[0];
2038 lenrange[0] = wi::shwi (0, prec);
2041 /* Set to true for strncat whose bound is derived from the length
2042 of the destination (the expected usage pattern). */
2043 bool cat_dstlen_bounded = false;
2044 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STRNCAT)
2045 cat_dstlen_bounded = is_strlen_related_p (dst, cnt);
2047 if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
2048 return warning_n (callloc, OPT_Wstringop_truncation,
2049 cntrange[0].to_uhwi (),
2050 "%G%qD output truncated before terminating "
2051 "nul copying %E byte from a string of the "
2052 "same length",
2053 "%G%qD output truncated before terminating nul "
2054 "copying %E bytes from a string of the same "
2055 "length",
2056 stmt, func, cnt);
2057 else if (!cat_dstlen_bounded)
2059 if (wi::geu_p (lenrange[0], cntrange[1]))
2061 /* The shortest string is longer than the upper bound of
2062 the count so the truncation is certain. */
2063 if (cntrange[0] == cntrange[1])
2064 return warning_n (callloc, OPT_Wstringop_truncation,
2065 cntrange[0].to_uhwi (),
2066 "%G%qD output truncated copying %E byte "
2067 "from a string of length %wu",
2068 "%G%qD output truncated copying %E bytes "
2069 "from a string of length %wu",
2070 stmt, func, cnt, lenrange[0].to_uhwi ());
2072 return warning_at (callloc, OPT_Wstringop_truncation,
2073 "%G%qD output truncated copying between %wu "
2074 "and %wu bytes from a string of length %wu",
2075 stmt, func, cntrange[0].to_uhwi (),
2076 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2078 else if (wi::geu_p (lenrange[1], cntrange[1]))
2080 /* The longest string is longer than the upper bound of
2081 the count so the truncation is possible. */
2082 if (cntrange[0] == cntrange[1])
2083 return warning_n (callloc, OPT_Wstringop_truncation,
2084 cntrange[0].to_uhwi (),
2085 "%G%qD output may be truncated copying %E "
2086 "byte from a string of length %wu",
2087 "%G%qD output may be truncated copying %E "
2088 "bytes from a string of length %wu",
2089 stmt, func, cnt, lenrange[1].to_uhwi ());
2091 return warning_at (callloc, OPT_Wstringop_truncation,
2092 "%G%qD output may be truncated copying between "
2093 "%wu and %wu bytes from a string of length %wu",
2094 stmt, func, cntrange[0].to_uhwi (),
2095 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
2099 if (!cat_dstlen_bounded
2100 && cntrange[0] != cntrange[1]
2101 && wi::leu_p (cntrange[0], lenrange[0])
2102 && wi::leu_p (cntrange[1], lenrange[0] + 1))
2104 /* If the source (including the terminating nul) is longer than
2105 the lower bound of the specified count but shorter than the
2106 upper bound the copy may (but need not) be truncated. */
2107 return warning_at (callloc, OPT_Wstringop_truncation,
2108 "%G%qD output may be truncated copying between "
2109 "%wu and %wu bytes from a string of length %wu",
2110 stmt, func, cntrange[0].to_uhwi (),
2111 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2115 if (tree dstsize = compute_objsize (dst, 1))
2117 /* The source length is uknown. Try to determine the destination
2118 size and see if it matches the specified bound. If not, bail.
2119 Otherwise go on to see if it should be diagnosed for possible
2120 truncation. */
2121 if (!dstsize)
2122 return false;
2124 if (wi::to_wide (dstsize) != cntrange[1])
2125 return false;
2127 if (cntrange[0] == cntrange[1])
2128 return warning_at (callloc, OPT_Wstringop_truncation,
2129 "%G%qD specified bound %E equals destination size",
2130 stmt, func, cnt);
2133 return false;
2136 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2137 out-of-bounds offsets or overlapping access, and to see if the size
2138 is derived from calling strlen() on the source argument, and if so,
2139 issue the appropriate warning. */
2141 static void
2142 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2144 if (!strlen_to_stridx)
2145 return;
2147 gimple *stmt = gsi_stmt (*gsi);
2149 tree dst = gimple_call_arg (stmt, 0);
2150 tree src = gimple_call_arg (stmt, 1);
2151 tree len = gimple_call_arg (stmt, 2);
2152 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2154 int didx = get_stridx (dst);
2155 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2157 /* Compute the size of the destination string including the NUL. */
2158 if (sidst->nonzero_chars)
2160 tree type = TREE_TYPE (sidst->nonzero_chars);
2161 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2162 build_int_cst (type, 1));
2164 dst = sidst->ptr;
2167 int sidx = get_stridx (src);
2168 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2169 if (sisrc)
2171 /* strncat() and strncpy() can modify the source string by writing
2172 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2173 clear. */
2175 /* Compute the size of the source string including the NUL. */
2176 if (sisrc->nonzero_chars)
2178 tree type = TREE_TYPE (sisrc->nonzero_chars);
2179 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2180 build_int_cst (type, 1));
2183 src = sisrc->ptr;
2185 else
2186 srcsize = NULL_TREE;
2188 if (!check_bounds_or_overlap (stmt, dst, src, dstsize, srcsize))
2190 gimple_set_no_warning (stmt, true);
2191 return;
2194 /* If the length argument was computed from strlen(S) for some string
2195 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2196 the location of the strlen() call (PSS->SECOND). */
2197 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2198 if (!pss || pss->first <= 0)
2200 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2201 gimple_set_no_warning (stmt, true);
2203 return;
2206 /* Retrieve the strinfo data for the string S that LEN was computed
2207 from as some function F of strlen (S) (i.e., LEN need not be equal
2208 to strlen(S)). */
2209 strinfo *silen = get_strinfo (pss->first);
2211 location_t callloc = gimple_nonartificial_location (stmt);
2212 callloc = expansion_point_location_if_in_system_header (callloc);
2214 tree func = gimple_call_fndecl (stmt);
2216 bool warned = false;
2218 /* When -Wstringop-truncation is set, try to determine truncation
2219 before diagnosing possible overflow. Truncation is implied by
2220 the LEN argument being equal to strlen(SRC), regardless of
2221 whether its value is known. Otherwise, issue the more generic
2222 -Wstringop-overflow which triggers for LEN arguments that in
2223 any meaningful way depend on strlen(SRC). */
2224 if (sisrc == silen
2225 && is_strlen_related_p (src, len)
2226 && warning_at (callloc, OPT_Wstringop_truncation,
2227 "%G%qD output truncated before terminating nul "
2228 "copying as many bytes from a string as its length",
2229 stmt, func))
2230 warned = true;
2231 else if (silen && is_strlen_related_p (src, silen->ptr))
2232 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2233 "%G%qD specified bound depends on the length "
2234 "of the source argument",
2235 stmt, func);
2236 if (warned)
2238 location_t strlenloc = pss->second;
2239 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2240 inform (strlenloc, "length computed here");
2244 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2245 If strlen of the second argument is known and length of the third argument
2246 is that plus one, strlen of the first argument is the same after this
2247 call. */
2249 static void
2250 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2252 int idx, didx;
2253 tree src, dst, len, lhs, oldlen, newlen;
2254 gimple *stmt = gsi_stmt (*gsi);
2255 strinfo *si, *dsi, *olddsi;
2257 len = gimple_call_arg (stmt, 2);
2258 src = gimple_call_arg (stmt, 1);
2259 dst = gimple_call_arg (stmt, 0);
2260 idx = get_stridx (src);
2261 if (idx == 0)
2262 return;
2264 didx = get_stridx (dst);
2265 olddsi = NULL;
2266 if (didx > 0)
2267 olddsi = get_strinfo (didx);
2268 else if (didx < 0)
2269 return;
2271 if (olddsi != NULL
2272 && tree_fits_uhwi_p (len)
2273 && !integer_zerop (len))
2274 adjust_last_stmt (olddsi, stmt, false);
2276 bool full_string_p;
2277 if (idx > 0)
2279 gimple *def_stmt;
2281 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2282 is known. */
2283 si = get_strinfo (idx);
2284 if (si == NULL || si->nonzero_chars == NULL_TREE)
2285 return;
2286 if (TREE_CODE (len) == INTEGER_CST
2287 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2289 if (tree_int_cst_le (len, si->nonzero_chars))
2291 /* Copying LEN nonzero characters, where LEN is constant. */
2292 newlen = len;
2293 full_string_p = false;
2295 else
2297 /* Copying the whole of the analyzed part of SI. */
2298 newlen = si->nonzero_chars;
2299 full_string_p = si->full_string_p;
2302 else
2304 if (!si->full_string_p)
2305 return;
2306 if (TREE_CODE (len) != SSA_NAME)
2307 return;
2308 def_stmt = SSA_NAME_DEF_STMT (len);
2309 if (!is_gimple_assign (def_stmt)
2310 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2311 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2312 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2313 return;
2314 /* Copying variable-length string SI (and no more). */
2315 newlen = si->nonzero_chars;
2316 full_string_p = true;
2319 else
2321 si = NULL;
2322 /* Handle memcpy (x, "abcd", 5) or
2323 memcpy (x, "abc\0uvw", 7). */
2324 if (!tree_fits_uhwi_p (len))
2325 return;
2327 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2328 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2329 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2330 full_string_p = clen > nonzero_chars;
2333 if (!full_string_p
2334 && olddsi
2335 && olddsi->nonzero_chars
2336 && TREE_CODE (olddsi->nonzero_chars) == INTEGER_CST
2337 && tree_int_cst_le (newlen, olddsi->nonzero_chars))
2339 /* The SRC substring being written strictly overlaps
2340 a subsequence of the existing string OLDDSI. */
2341 newlen = olddsi->nonzero_chars;
2342 full_string_p = olddsi->full_string_p;
2345 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2346 adjust_last_stmt (olddsi, stmt, false);
2348 if (didx == 0)
2350 didx = new_stridx (dst);
2351 if (didx == 0)
2352 return;
2354 oldlen = NULL_TREE;
2355 if (olddsi != NULL)
2357 dsi = unshare_strinfo (olddsi);
2358 oldlen = olddsi->nonzero_chars;
2359 dsi->nonzero_chars = newlen;
2360 dsi->full_string_p = full_string_p;
2361 /* Break the chain, so adjust_related_strinfo on later pointers in
2362 the chain won't adjust this one anymore. */
2363 dsi->next = 0;
2364 dsi->stmt = NULL;
2365 dsi->endptr = NULL_TREE;
2367 else
2369 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2370 set_strinfo (didx, dsi);
2371 find_equal_ptrs (dst, didx);
2373 dsi->writable = true;
2374 dsi->dont_invalidate = true;
2375 if (olddsi != NULL)
2377 tree adj = NULL_TREE;
2378 location_t loc = gimple_location (stmt);
2379 if (oldlen == NULL_TREE)
2381 else if (integer_zerop (oldlen))
2382 adj = newlen;
2383 else if (TREE_CODE (oldlen) == INTEGER_CST
2384 || TREE_CODE (newlen) == INTEGER_CST)
2385 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2386 fold_convert_loc (loc, TREE_TYPE (newlen),
2387 oldlen));
2388 if (adj != NULL_TREE)
2389 adjust_related_strinfos (loc, dsi, adj);
2390 else
2391 dsi->prev = 0;
2393 /* memcpy src may not overlap dst, so src doesn't need to be
2394 invalidated either. */
2395 if (si != NULL)
2396 si->dont_invalidate = true;
2398 if (full_string_p)
2400 lhs = gimple_call_lhs (stmt);
2401 switch (bcode)
2403 case BUILT_IN_MEMCPY:
2404 case BUILT_IN_MEMCPY_CHK:
2405 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2406 laststmt.stmt = stmt;
2407 laststmt.len = dsi->nonzero_chars;
2408 laststmt.stridx = dsi->idx;
2409 if (lhs)
2410 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2411 break;
2412 case BUILT_IN_MEMPCPY:
2413 case BUILT_IN_MEMPCPY_CHK:
2414 break;
2415 default:
2416 gcc_unreachable ();
2421 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2422 If strlen of the second argument is known, strlen of the first argument
2423 is increased by the length of the second argument. Furthermore, attempt
2424 to convert it to memcpy/strcpy if the length of the first argument
2425 is known. */
2427 static void
2428 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2430 int idx, didx;
2431 tree srclen, args, type, fn, objsz, endptr;
2432 bool success;
2433 gimple *stmt = gsi_stmt (*gsi);
2434 strinfo *si, *dsi;
2435 location_t loc = gimple_location (stmt);
2437 tree src = gimple_call_arg (stmt, 1);
2438 tree dst = gimple_call_arg (stmt, 0);
2440 /* Bail if the source is the same as destination. It will be diagnosed
2441 elsewhere. */
2442 if (operand_equal_p (src, dst, 0))
2443 return;
2445 tree lhs = gimple_call_lhs (stmt);
2447 didx = get_stridx (dst);
2448 if (didx < 0)
2449 return;
2451 dsi = NULL;
2452 if (didx > 0)
2453 dsi = get_strinfo (didx);
2455 srclen = NULL_TREE;
2456 si = NULL;
2457 idx = get_stridx (src);
2458 if (idx < 0)
2459 srclen = build_int_cst (size_type_node, ~idx);
2460 else if (idx > 0)
2462 si = get_strinfo (idx);
2463 if (si != NULL)
2464 srclen = get_string_length (si);
2467 /* Set the no-warning bit on the transformed statement? */
2468 bool set_no_warning = false;
2470 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2473 /* The concatenation always involves copying at least one byte
2474 (the terminating nul), even if the source string is empty.
2475 If the source is unknown assume it's one character long and
2476 used that as both sizes. */
2477 tree slen = srclen;
2478 if (slen)
2480 tree type = TREE_TYPE (slen);
2481 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2484 tree sptr = si && si->ptr ? si->ptr : src;
2486 if (!check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
2488 gimple_set_no_warning (stmt, true);
2489 set_no_warning = true;
2493 /* strcat (p, q) can be transformed into
2494 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2495 with length endptr - p if we need to compute the length
2496 later on. Don't do this transformation if we don't need
2497 it. */
2498 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2500 if (didx == 0)
2502 didx = new_stridx (dst);
2503 if (didx == 0)
2504 return;
2506 if (dsi == NULL)
2508 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2509 set_strinfo (didx, dsi);
2510 find_equal_ptrs (dst, didx);
2512 else
2514 dsi = unshare_strinfo (dsi);
2515 dsi->nonzero_chars = NULL_TREE;
2516 dsi->full_string_p = false;
2517 dsi->next = 0;
2518 dsi->endptr = NULL_TREE;
2520 dsi->writable = true;
2521 dsi->stmt = stmt;
2522 dsi->dont_invalidate = true;
2524 return;
2527 tree dstlen = dsi->nonzero_chars;
2528 endptr = dsi->endptr;
2530 dsi = unshare_strinfo (dsi);
2531 dsi->endptr = NULL_TREE;
2532 dsi->stmt = NULL;
2533 dsi->writable = true;
2535 if (srclen != NULL_TREE)
2537 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2538 TREE_TYPE (dsi->nonzero_chars),
2539 dsi->nonzero_chars, srclen);
2540 gcc_assert (dsi->full_string_p);
2541 adjust_related_strinfos (loc, dsi, srclen);
2542 dsi->dont_invalidate = true;
2544 else
2546 dsi->nonzero_chars = NULL;
2547 dsi->full_string_p = false;
2548 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2549 dsi->dont_invalidate = true;
2552 if (si != NULL)
2553 /* strcat src may not overlap dst, so src doesn't need to be
2554 invalidated either. */
2555 si->dont_invalidate = true;
2557 /* For now. Could remove the lhs from the call and add
2558 lhs = dst; afterwards. */
2559 if (lhs)
2560 return;
2562 fn = NULL_TREE;
2563 objsz = NULL_TREE;
2564 switch (bcode)
2566 case BUILT_IN_STRCAT:
2567 if (srclen != NULL_TREE)
2568 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2569 else
2570 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2571 break;
2572 case BUILT_IN_STRCAT_CHK:
2573 if (srclen != NULL_TREE)
2574 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2575 else
2576 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2577 objsz = gimple_call_arg (stmt, 2);
2578 break;
2579 default:
2580 gcc_unreachable ();
2583 if (fn == NULL_TREE)
2584 return;
2586 if (dsi && dstlen)
2588 tree type = TREE_TYPE (dstlen);
2590 /* Compute the size of the source sequence, including the nul. */
2591 tree srcsize = srclen ? srclen : size_zero_node;
2592 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2594 tree sptr = si && si->ptr ? si->ptr : src;
2596 if (!check_bounds_or_overlap (stmt, dst, sptr, dstlen, srcsize))
2598 gimple_set_no_warning (stmt, true);
2599 set_no_warning = true;
2603 tree len = NULL_TREE;
2604 if (srclen != NULL_TREE)
2606 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2607 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2609 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2610 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2611 build_int_cst (type, 1));
2612 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2613 GSI_SAME_STMT);
2615 if (endptr)
2616 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2617 else
2618 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2619 TREE_TYPE (dst), unshare_expr (dst),
2620 fold_convert_loc (loc, sizetype,
2621 unshare_expr (dstlen)));
2622 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2623 GSI_SAME_STMT);
2624 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2626 fprintf (dump_file, "Optimizing: ");
2627 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2629 if (srclen != NULL_TREE)
2630 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2631 dst, src, len, objsz);
2632 else
2633 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2634 dst, src, objsz);
2635 if (success)
2637 stmt = gsi_stmt (*gsi);
2638 update_stmt (stmt);
2639 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2641 fprintf (dump_file, "into: ");
2642 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2644 /* If srclen == NULL, note that current string length can be
2645 computed by transforming this strcpy into stpcpy. */
2646 if (srclen == NULL_TREE && dsi->dont_invalidate)
2647 dsi->stmt = stmt;
2648 adjust_last_stmt (dsi, stmt, true);
2649 if (srclen != NULL_TREE)
2651 laststmt.stmt = stmt;
2652 laststmt.len = srclen;
2653 laststmt.stridx = dsi->idx;
2656 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2657 fprintf (dump_file, "not possible.\n");
2659 if (set_no_warning)
2660 gimple_set_no_warning (stmt, true);
2663 /* Handle a call to malloc or calloc. */
2665 static void
2666 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2668 gimple *stmt = gsi_stmt (*gsi);
2669 tree lhs = gimple_call_lhs (stmt);
2670 if (lhs == NULL_TREE)
2671 return;
2673 gcc_assert (get_stridx (lhs) == 0);
2674 int idx = new_stridx (lhs);
2675 tree length = NULL_TREE;
2676 if (bcode == BUILT_IN_CALLOC)
2677 length = build_int_cst (size_type_node, 0);
2678 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2679 if (bcode == BUILT_IN_CALLOC)
2680 si->endptr = lhs;
2681 set_strinfo (idx, si);
2682 si->writable = true;
2683 si->stmt = stmt;
2684 si->dont_invalidate = true;
2687 /* Handle a call to memset.
2688 After a call to calloc, memset(,0,) is unnecessary.
2689 memset(malloc(n),0,n) is calloc(n,1).
2690 return true when the call is transfomred, false otherwise. */
2692 static bool
2693 handle_builtin_memset (gimple_stmt_iterator *gsi)
2695 gimple *stmt2 = gsi_stmt (*gsi);
2696 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2697 return false;
2698 tree ptr = gimple_call_arg (stmt2, 0);
2699 int idx1 = get_stridx (ptr);
2700 if (idx1 <= 0)
2701 return false;
2702 strinfo *si1 = get_strinfo (idx1);
2703 if (!si1)
2704 return false;
2705 gimple *stmt1 = si1->stmt;
2706 if (!stmt1 || !is_gimple_call (stmt1))
2707 return false;
2708 tree callee1 = gimple_call_fndecl (stmt1);
2709 if (!valid_builtin_call (stmt1))
2710 return false;
2711 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2712 tree size = gimple_call_arg (stmt2, 2);
2713 if (code1 == BUILT_IN_CALLOC)
2714 /* Not touching stmt1 */ ;
2715 else if (code1 == BUILT_IN_MALLOC
2716 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2718 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2719 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2720 size, build_one_cst (size_type_node));
2721 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2722 si1->full_string_p = true;
2723 si1->stmt = gsi_stmt (gsi1);
2725 else
2726 return false;
2727 tree lhs = gimple_call_lhs (stmt2);
2728 unlink_stmt_vdef (stmt2);
2729 if (lhs)
2731 gimple *assign = gimple_build_assign (lhs, ptr);
2732 gsi_replace (gsi, assign, false);
2734 else
2736 gsi_remove (gsi, true);
2737 release_defs (stmt2);
2740 return true;
2743 /* Handle a call to memcmp. We try to handle small comparisons by
2744 converting them to load and compare, and replacing the call to memcmp
2745 with a __builtin_memcmp_eq call where possible.
2746 return true when call is transformed, return false otherwise. */
2748 static bool
2749 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2751 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2752 tree res = gimple_call_lhs (stmt2);
2753 tree arg1 = gimple_call_arg (stmt2, 0);
2754 tree arg2 = gimple_call_arg (stmt2, 1);
2755 tree len = gimple_call_arg (stmt2, 2);
2756 unsigned HOST_WIDE_INT leni;
2757 use_operand_p use_p;
2758 imm_use_iterator iter;
2760 if (!res)
2761 return false;
2763 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2765 gimple *ustmt = USE_STMT (use_p);
2767 if (is_gimple_debug (ustmt))
2768 continue;
2769 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2771 gassign *asgn = as_a <gassign *> (ustmt);
2772 tree_code code = gimple_assign_rhs_code (asgn);
2773 if ((code != EQ_EXPR && code != NE_EXPR)
2774 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2775 return false;
2777 else if (gimple_code (ustmt) == GIMPLE_COND)
2779 tree_code code = gimple_cond_code (ustmt);
2780 if ((code != EQ_EXPR && code != NE_EXPR)
2781 || !integer_zerop (gimple_cond_rhs (ustmt)))
2782 return false;
2784 else
2785 return false;
2788 if (tree_fits_uhwi_p (len)
2789 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2790 && pow2p_hwi (leni))
2792 leni *= CHAR_TYPE_SIZE;
2793 unsigned align1 = get_pointer_alignment (arg1);
2794 unsigned align2 = get_pointer_alignment (arg2);
2795 unsigned align = MIN (align1, align2);
2796 scalar_int_mode mode;
2797 if (int_mode_for_size (leni, 1).exists (&mode)
2798 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2800 location_t loc = gimple_location (stmt2);
2801 tree type, off;
2802 type = build_nonstandard_integer_type (leni, 1);
2803 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
2804 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2805 ptr_mode, true);
2806 off = build_int_cst (ptrtype, 0);
2807 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2808 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2809 tree tem1 = fold_const_aggregate_ref (arg1);
2810 if (tem1)
2811 arg1 = tem1;
2812 tree tem2 = fold_const_aggregate_ref (arg2);
2813 if (tem2)
2814 arg2 = tem2;
2815 res = fold_convert_loc (loc, TREE_TYPE (res),
2816 fold_build2_loc (loc, NE_EXPR,
2817 boolean_type_node,
2818 arg1, arg2));
2819 gimplify_and_update_call_from_tree (gsi, res);
2820 return true;
2824 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2825 return true;
2828 /* Given an index to the strinfo vector, compute the string length for the
2829 corresponding string. Return -1 when unknown. */
2831 static HOST_WIDE_INT
2832 compute_string_length (int idx)
2834 HOST_WIDE_INT string_leni = -1;
2835 gcc_assert (idx != 0);
2837 if (idx < 0)
2838 return ~idx;
2840 strinfo *si = get_strinfo (idx);
2841 if (si)
2843 tree const_string_len = get_string_length (si);
2844 if (const_string_len && tree_fits_shwi_p (const_string_len))
2845 string_leni = tree_to_shwi (const_string_len);
2848 if (string_leni < 0)
2849 return -1;
2851 return string_leni;
2854 /* Determine the minimum size of the object referenced by DEST expression which
2855 must have a pointer type.
2856 Return the minimum size of the object if successful or NULL when the size
2857 cannot be determined. */
2858 static tree
2859 determine_min_objsize (tree dest)
2861 unsigned HOST_WIDE_INT size = 0;
2863 if (compute_builtin_object_size (dest, 2, &size))
2864 return build_int_cst (sizetype, size);
2866 /* Try to determine the size of the object through the RHS of the
2867 assign statement. */
2868 if (TREE_CODE (dest) == SSA_NAME)
2870 gimple *stmt = SSA_NAME_DEF_STMT (dest);
2871 if (!is_gimple_assign (stmt))
2872 return NULL_TREE;
2874 if (!gimple_assign_single_p (stmt)
2875 && !gimple_assign_unary_nop_p (stmt))
2876 return NULL_TREE;
2878 dest = gimple_assign_rhs1 (stmt);
2879 return determine_min_objsize (dest);
2882 /* Try to determine the size of the object from its type. */
2883 if (TREE_CODE (dest) != ADDR_EXPR)
2884 return NULL_TREE;
2886 tree type = TREE_TYPE (dest);
2887 if (TREE_CODE (type) == POINTER_TYPE)
2888 type = TREE_TYPE (type);
2890 type = TYPE_MAIN_VARIANT (type);
2892 /* We cannot determine the size of the array if it's a flexible array,
2893 which is declared at the end of a structure. */
2894 if (TREE_CODE (type) == ARRAY_TYPE
2895 && !array_at_struct_end_p (dest))
2897 tree size_t = TYPE_SIZE_UNIT (type);
2898 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2899 && !integer_zerop (size_t))
2900 return size_t;
2903 return NULL_TREE;
2906 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2907 equality test against zero:
2909 A. When the lengths of both arguments are constant and it's a strcmp:
2910 * if the lengths are NOT equal, we can safely fold the call
2911 to a non-zero value.
2912 * otherwise, do nothing now.
2914 B. When the length of one argument is constant, try to replace the call with
2915 a __builtin_str(n)cmp_eq call where possible, i.e:
2917 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2918 string with constant length , C is a constant.
2919 if (C <= strlen(STR) && sizeof_array(s) > C)
2921 replace this call with
2922 strncmp_eq (s, STR, C) (!)= 0
2924 if (C > strlen(STR)
2926 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2927 can handled by the following strcmp.
2930 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2931 string with constant length.
2932 if (sizeof_array(s) > strlen(STR))
2934 replace this call with
2935 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2938 Return true when the call is transformed, return false otherwise.
2941 static bool
2942 handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
2944 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
2945 tree res = gimple_call_lhs (stmt);
2946 use_operand_p use_p;
2947 imm_use_iterator iter;
2948 tree arg1 = gimple_call_arg (stmt, 0);
2949 tree arg2 = gimple_call_arg (stmt, 1);
2950 int idx1 = get_stridx (arg1);
2951 int idx2 = get_stridx (arg2);
2952 HOST_WIDE_INT length = -1;
2953 bool is_ncmp = false;
2955 if (!res)
2956 return false;
2958 /* When both arguments are unknown, do nothing. */
2959 if (idx1 == 0 && idx2 == 0)
2960 return false;
2962 /* Handle strncmp function. */
2963 if (gimple_call_num_args (stmt) == 3)
2965 tree len = gimple_call_arg (stmt, 2);
2966 if (tree_fits_shwi_p (len))
2967 length = tree_to_shwi (len);
2969 is_ncmp = true;
2972 /* For strncmp, if the length argument is NOT known, do nothing. */
2973 if (is_ncmp && length < 0)
2974 return false;
2976 /* When the result is ONLY used to do equality test against zero. */
2977 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2979 gimple *use_stmt = USE_STMT (use_p);
2981 if (is_gimple_debug (use_stmt))
2982 continue;
2983 if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
2985 tree_code code = gimple_assign_rhs_code (use_stmt);
2986 if (code == COND_EXPR)
2988 tree cond_expr = gimple_assign_rhs1 (use_stmt);
2989 if ((TREE_CODE (cond_expr) != EQ_EXPR
2990 && (TREE_CODE (cond_expr) != NE_EXPR))
2991 || !integer_zerop (TREE_OPERAND (cond_expr, 1)))
2992 return false;
2994 else if (code == EQ_EXPR || code == NE_EXPR)
2996 if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
2997 return false;
2999 else
3000 return false;
3002 else if (gimple_code (use_stmt) == GIMPLE_COND)
3004 tree_code code = gimple_cond_code (use_stmt);
3005 if ((code != EQ_EXPR && code != NE_EXPR)
3006 || !integer_zerop (gimple_cond_rhs (use_stmt)))
3007 return false;
3009 else
3010 return false;
3013 /* When the lengths of both arguments are known, and they are unequal, we can
3014 safely fold the call to a non-zero value for strcmp;
3015 othewise, do nothing now. */
3016 if (idx1 != 0 && idx2 != 0)
3018 HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
3019 HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
3021 if (!is_ncmp
3022 && const_string_leni1 != -1
3023 && const_string_leni2 != -1
3024 && const_string_leni1 != const_string_leni2)
3026 replace_call_with_value (gsi, integer_one_node);
3027 return true;
3029 return false;
3032 /* When the length of one argument is constant. */
3033 tree var_string = NULL_TREE;
3034 HOST_WIDE_INT const_string_leni = -1;
3036 if (idx1)
3038 const_string_leni = compute_string_length (idx1);
3039 var_string = arg2;
3041 else
3043 gcc_checking_assert (idx2);
3044 const_string_leni = compute_string_length (idx2);
3045 var_string = arg1;
3048 if (const_string_leni < 0)
3049 return false;
3051 unsigned HOST_WIDE_INT var_sizei = 0;
3052 /* try to determine the minimum size of the object pointed by var_string. */
3053 tree size = determine_min_objsize (var_string);
3055 if (!size)
3056 return false;
3058 if (tree_fits_uhwi_p (size))
3059 var_sizei = tree_to_uhwi (size);
3061 if (var_sizei == 0)
3062 return false;
3064 /* For strncmp, if length > const_string_leni , this call can be safely
3065 transformed to a strcmp. */
3066 if (is_ncmp && length > const_string_leni)
3067 is_ncmp = false;
3069 unsigned HOST_WIDE_INT final_length
3070 = is_ncmp ? length : const_string_leni + 1;
3072 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
3073 if (var_sizei > final_length)
3075 tree fn
3076 = (is_ncmp
3077 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
3078 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
3079 if (!fn)
3080 return false;
3081 tree const_string_len = build_int_cst (size_type_node, final_length);
3082 update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
3084 else
3085 return false;
3087 return true;
3090 /* Handle a POINTER_PLUS_EXPR statement.
3091 For p = "abcd" + 2; compute associated length, or if
3092 p = q + off is pointing to a '\0' character of a string, call
3093 zero_length_string on it. */
3095 static void
3096 handle_pointer_plus (gimple_stmt_iterator *gsi)
3098 gimple *stmt = gsi_stmt (*gsi);
3099 tree lhs = gimple_assign_lhs (stmt), off;
3100 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3101 strinfo *si, *zsi;
3103 if (idx == 0)
3104 return;
3106 if (idx < 0)
3108 tree off = gimple_assign_rhs2 (stmt);
3109 if (tree_fits_uhwi_p (off)
3110 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
3111 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
3112 = ~(~idx - (int) tree_to_uhwi (off));
3113 return;
3116 si = get_strinfo (idx);
3117 if (si == NULL || si->nonzero_chars == NULL_TREE)
3118 return;
3120 off = gimple_assign_rhs2 (stmt);
3121 zsi = NULL;
3122 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
3123 zsi = zero_length_string (lhs, si);
3124 else if (TREE_CODE (off) == SSA_NAME)
3126 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
3127 if (gimple_assign_single_p (def_stmt)
3128 && si->full_string_p
3129 && operand_equal_p (si->nonzero_chars,
3130 gimple_assign_rhs1 (def_stmt), 0))
3131 zsi = zero_length_string (lhs, si);
3133 if (zsi != NULL
3134 && si->endptr != NULL_TREE
3135 && si->endptr != lhs
3136 && TREE_CODE (si->endptr) == SSA_NAME)
3138 enum tree_code rhs_code
3139 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
3140 ? SSA_NAME : NOP_EXPR;
3141 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
3142 gcc_assert (gsi_stmt (*gsi) == stmt);
3143 update_stmt (stmt);
3147 /* If RHS, either directly or indirectly, refers to a string of constant
3148 length, return the length. Otherwise, if it refers to a character
3149 constant, return 1 if the constant is non-zero and 0 if it is nul.
3150 Otherwise, return a negative value. */
3152 static HOST_WIDE_INT
3153 get_min_string_length (tree rhs, bool *full_string_p)
3155 if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
3157 if (tree_expr_nonzero_p (rhs))
3159 *full_string_p = false;
3160 return 1;
3163 *full_string_p = true;
3164 return 0;
3167 if (TREE_CODE (rhs) == MEM_REF
3168 && integer_zerop (TREE_OPERAND (rhs, 1)))
3170 rhs = TREE_OPERAND (rhs, 0);
3171 if (TREE_CODE (rhs) == ADDR_EXPR)
3173 tree rhs_addr = rhs;
3175 rhs = TREE_OPERAND (rhs, 0);
3176 if (TREE_CODE (rhs) != STRING_CST)
3178 int idx = get_stridx (rhs_addr);
3179 if (idx > 0)
3181 strinfo *si = get_strinfo (idx);
3182 if (si
3183 && tree_fits_shwi_p (si->nonzero_chars))
3185 *full_string_p = si->full_string_p;
3186 return tree_to_shwi (si->nonzero_chars);
3193 if (TREE_CODE (rhs) == VAR_DECL
3194 && TREE_READONLY (rhs))
3195 rhs = DECL_INITIAL (rhs);
3197 if (rhs && TREE_CODE (rhs) == STRING_CST)
3199 *full_string_p = true;
3200 return strlen (TREE_STRING_POINTER (rhs));
3203 return -1;
3206 /* Handle a single or multiple character store either by single
3207 character assignment or by multi-character assignment from
3208 MEM_REF. */
3210 static bool
3211 handle_char_store (gimple_stmt_iterator *gsi)
3213 int idx = -1;
3214 strinfo *si = NULL;
3215 gimple *stmt = gsi_stmt (*gsi);
3216 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
3217 tree rhs = gimple_assign_rhs1 (stmt);
3218 unsigned HOST_WIDE_INT offset = 0;
3220 if (TREE_CODE (lhs) == MEM_REF
3221 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
3223 tree mem_offset = TREE_OPERAND (lhs, 1);
3224 if (tree_fits_uhwi_p (mem_offset))
3226 /* Get the strinfo for the base, and use it if it starts with at
3227 least OFFSET nonzero characters. This is trivially true if
3228 OFFSET is zero. */
3229 offset = tree_to_uhwi (mem_offset);
3230 idx = get_stridx (TREE_OPERAND (lhs, 0));
3231 if (idx > 0)
3232 si = get_strinfo (idx);
3233 if (offset == 0)
3234 ssaname = TREE_OPERAND (lhs, 0);
3235 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
3236 return true;
3239 else
3241 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
3242 if (idx > 0)
3243 si = get_strinfo (idx);
3246 /* STORING_NONZERO_P is true iff not all stored characters are zero.
3247 STORING_ALL_ZEROS_P is true iff all stored characters are zero.
3248 Both are false when it's impossible to determine which is true. */
3249 bool storing_nonzero_p;
3250 bool storing_all_zeros_p = initializer_zerop (rhs, &storing_nonzero_p);
3251 if (!storing_nonzero_p)
3252 storing_nonzero_p = tree_expr_nonzero_p (rhs);
3253 bool full_string_p = storing_all_zeros_p;
3255 /* Set to the length of the string being assigned if known. */
3256 HOST_WIDE_INT rhslen;
3258 if (si != NULL)
3260 int cmp = compare_nonzero_chars (si, offset);
3261 gcc_assert (offset == 0 || cmp >= 0);
3262 if (storing_all_zeros_p && cmp == 0 && si->full_string_p)
3264 /* When overwriting a '\0' with a '\0', the store can be removed
3265 if we know it has been stored in the current function. */
3266 if (!stmt_could_throw_p (stmt) && si->writable)
3268 unlink_stmt_vdef (stmt);
3269 release_defs (stmt);
3270 gsi_remove (gsi, true);
3271 return false;
3273 else
3275 si->writable = true;
3276 gsi_next (gsi);
3277 return false;
3280 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3281 and if we aren't storing '\0', we know that the length of the
3282 string and any other zero terminated string in memory remains
3283 the same. In that case we move to the next gimple statement and
3284 return to signal the caller that it shouldn't invalidate anything.
3286 This is benefical for cases like:
3288 char p[20];
3289 void foo (char *q)
3291 strcpy (p, "foobar");
3292 size_t len = strlen (p); // This can be optimized into 6
3293 size_t len2 = strlen (q); // This has to be computed
3294 p[0] = 'X';
3295 size_t len3 = strlen (p); // This can be optimized into 6
3296 size_t len4 = strlen (q); // This can be optimized into len2
3297 bar (len, len2, len3, len4);
3300 else if (storing_nonzero_p && cmp > 0)
3302 gsi_next (gsi);
3303 return false;
3305 else if (storing_all_zeros_p || storing_nonzero_p || (offset != 0 && cmp > 0))
3307 /* When STORING_NONZERO_P, we know that the string will start
3308 with at least OFFSET + 1 nonzero characters. If storing
3309 a single character, set si->NONZERO_CHARS to the result.
3310 If storing multiple characters, try to determine the number
3311 of leading non-zero characters and set si->NONZERO_CHARS to
3312 the result instead.
3314 When STORING_ALL_ZEROS_P, we know that the string is now
3315 OFFSET characters long.
3317 Otherwise, we're storing an unknown value at offset OFFSET,
3318 so need to clip the nonzero_chars to OFFSET. */
3319 bool full_string_p = storing_all_zeros_p;
3320 HOST_WIDE_INT len = 1;
3321 if (storing_nonzero_p)
3323 /* Try to get the minimum length of the string (or
3324 individual character) being stored. If it fails,
3325 STORING_NONZERO_P guarantees it's at least 1. */
3326 len = get_min_string_length (rhs, &full_string_p);
3327 if (len < 0)
3328 len = 1;
3331 location_t loc = gimple_location (stmt);
3332 tree oldlen = si->nonzero_chars;
3333 if (cmp == 0 && si->full_string_p)
3334 /* We're overwriting the nul terminator with a nonzero or
3335 unknown character. If the previous stmt was a memcpy,
3336 its length may be decreased. */
3337 adjust_last_stmt (si, stmt, false);
3338 si = unshare_strinfo (si);
3339 if (storing_nonzero_p)
3341 gcc_assert (len >= 0);
3342 si->nonzero_chars = build_int_cst (size_type_node, offset + len);
3344 else
3345 si->nonzero_chars = build_int_cst (size_type_node, offset);
3346 si->full_string_p = full_string_p;
3347 if (storing_all_zeros_p
3348 && ssaname
3349 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3350 si->endptr = ssaname;
3351 else
3352 si->endptr = NULL;
3353 si->next = 0;
3354 si->stmt = NULL;
3355 si->writable = true;
3356 si->dont_invalidate = true;
3357 if (oldlen)
3359 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
3360 si->nonzero_chars, oldlen);
3361 adjust_related_strinfos (loc, si, adj);
3363 else
3364 si->prev = 0;
3367 else if (idx == 0 && (storing_all_zeros_p || storing_nonzero_p))
3369 if (ssaname)
3370 idx = new_stridx (ssaname);
3371 else
3372 idx = new_addr_stridx (lhs);
3373 if (idx != 0)
3375 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
3376 HOST_WIDE_INT slen = (storing_all_zeros_p
3378 : (storing_nonzero_p
3379 ? get_min_string_length (rhs, &full_string_p)
3380 : -1));
3381 tree len = (slen <= 0
3382 ? size_zero_node
3383 : build_int_cst (size_type_node, slen));
3384 si = new_strinfo (ptr, idx, len, slen >= 0 && full_string_p);
3385 set_strinfo (idx, si);
3386 if (storing_all_zeros_p
3387 && ssaname
3388 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3389 si->endptr = ssaname;
3390 si->dont_invalidate = true;
3391 si->writable = true;
3394 else if (idx == 0
3395 && (rhslen = get_min_string_length (rhs, &full_string_p)) >= 0
3396 && ssaname == NULL_TREE
3397 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
3399 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
3400 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
3402 int idx = new_addr_stridx (lhs);
3403 if (idx != 0)
3405 si = new_strinfo (build_fold_addr_expr (lhs), idx,
3406 build_int_cst (size_type_node, rhslen),
3407 full_string_p);
3408 set_strinfo (idx, si);
3409 si->dont_invalidate = true;
3414 if (si != NULL && offset == 0 && storing_all_zeros_p)
3416 /* Allow adjust_last_stmt to remove it if the stored '\0'
3417 is immediately overwritten. */
3418 laststmt.stmt = stmt;
3419 laststmt.len = build_int_cst (size_type_node, 1);
3420 laststmt.stridx = si->idx;
3422 return true;
3425 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3427 static void
3428 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3430 if (TREE_CODE (rhs1) != SSA_NAME
3431 || TREE_CODE (rhs2) != SSA_NAME)
3432 return;
3434 gimple *call_stmt = NULL;
3435 for (int pass = 0; pass < 2; pass++)
3437 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3438 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3439 && has_single_use (rhs1)
3440 && gimple_call_arg (g, 0) == rhs2)
3442 call_stmt = g;
3443 break;
3445 std::swap (rhs1, rhs2);
3448 if (call_stmt)
3450 tree arg0 = gimple_call_arg (call_stmt, 0);
3452 if (arg0 == rhs2)
3454 tree arg1 = gimple_call_arg (call_stmt, 1);
3455 tree arg1_len = NULL_TREE;
3456 int idx = get_stridx (arg1);
3458 if (idx)
3460 if (idx < 0)
3461 arg1_len = build_int_cst (size_type_node, ~idx);
3462 else
3464 strinfo *si = get_strinfo (idx);
3465 if (si)
3466 arg1_len = get_string_length (si);
3470 if (arg1_len != NULL_TREE)
3472 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3473 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3475 if (!is_gimple_val (arg1_len))
3477 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3478 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3479 arg1_len);
3480 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3481 arg1_len = arg1_len_tmp;
3484 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3485 arg0, arg1, arg1_len);
3486 tree strncmp_lhs = make_ssa_name (integer_type_node);
3487 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3488 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3489 gsi_remove (&gsi, true);
3490 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3491 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3493 if (is_gimple_assign (stmt))
3495 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3497 tree cond = gimple_assign_rhs1 (stmt);
3498 TREE_OPERAND (cond, 0) = strncmp_lhs;
3499 TREE_OPERAND (cond, 1) = zero;
3501 else
3503 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3504 gimple_assign_set_rhs2 (stmt, zero);
3507 else
3509 gcond *cond = as_a<gcond *> (stmt);
3510 gimple_cond_set_lhs (cond, strncmp_lhs);
3511 gimple_cond_set_rhs (cond, zero);
3513 update_stmt (stmt);
3519 /* Attempt to check for validity of the performed access a single statement
3520 at *GSI using string length knowledge, and to optimize it.
3521 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3522 true. */
3524 static bool
3525 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
3527 gimple *stmt = gsi_stmt (*gsi);
3529 if (is_gimple_call (stmt))
3531 tree callee = gimple_call_fndecl (stmt);
3532 if (valid_builtin_call (stmt))
3533 switch (DECL_FUNCTION_CODE (callee))
3535 case BUILT_IN_STRLEN:
3536 case BUILT_IN_STRNLEN:
3537 handle_builtin_strlen (gsi);
3538 break;
3539 case BUILT_IN_STRCHR:
3540 handle_builtin_strchr (gsi);
3541 break;
3542 case BUILT_IN_STRCPY:
3543 case BUILT_IN_STRCPY_CHK:
3544 case BUILT_IN_STPCPY:
3545 case BUILT_IN_STPCPY_CHK:
3546 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3547 break;
3549 case BUILT_IN_STRNCAT:
3550 case BUILT_IN_STRNCAT_CHK:
3551 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3552 break;
3554 case BUILT_IN_STPNCPY:
3555 case BUILT_IN_STPNCPY_CHK:
3556 case BUILT_IN_STRNCPY:
3557 case BUILT_IN_STRNCPY_CHK:
3558 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3559 break;
3561 case BUILT_IN_MEMCPY:
3562 case BUILT_IN_MEMCPY_CHK:
3563 case BUILT_IN_MEMPCPY:
3564 case BUILT_IN_MEMPCPY_CHK:
3565 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3566 break;
3567 case BUILT_IN_STRCAT:
3568 case BUILT_IN_STRCAT_CHK:
3569 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3570 break;
3571 case BUILT_IN_MALLOC:
3572 case BUILT_IN_CALLOC:
3573 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3574 break;
3575 case BUILT_IN_MEMSET:
3576 if (handle_builtin_memset (gsi))
3577 return false;
3578 break;
3579 case BUILT_IN_MEMCMP:
3580 if (handle_builtin_memcmp (gsi))
3581 return false;
3582 break;
3583 case BUILT_IN_STRCMP:
3584 case BUILT_IN_STRNCMP:
3585 if (handle_builtin_string_cmp (gsi))
3586 return false;
3587 break;
3588 default:
3589 break;
3592 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3594 tree lhs = gimple_assign_lhs (stmt);
3596 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3598 if (gimple_assign_single_p (stmt)
3599 || (gimple_assign_cast_p (stmt)
3600 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3602 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3603 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3605 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3606 handle_pointer_plus (gsi);
3608 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3610 enum tree_code code = gimple_assign_rhs_code (stmt);
3611 if (code == COND_EXPR)
3613 tree cond = gimple_assign_rhs1 (stmt);
3614 enum tree_code cond_code = TREE_CODE (cond);
3616 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3617 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3618 TREE_OPERAND (cond, 1), stmt);
3620 else if (code == EQ_EXPR || code == NE_EXPR)
3621 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3622 gimple_assign_rhs2 (stmt), stmt);
3623 else if (gimple_assign_load_p (stmt)
3624 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3625 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3626 && (TYPE_PRECISION (TREE_TYPE (lhs))
3627 == TYPE_PRECISION (char_type_node))
3628 && !gimple_has_volatile_ops (stmt))
3630 tree off = integer_zero_node;
3631 unsigned HOST_WIDE_INT coff = 0;
3632 int idx = 0;
3633 tree rhs1 = gimple_assign_rhs1 (stmt);
3634 if (code == MEM_REF)
3636 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3637 if (idx > 0)
3639 strinfo *si = get_strinfo (idx);
3640 if (si
3641 && si->nonzero_chars
3642 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3643 && (wi::to_widest (si->nonzero_chars)
3644 >= wi::to_widest (off)))
3645 off = TREE_OPERAND (rhs1, 1);
3646 else
3647 /* This case is not useful. See if get_addr_stridx
3648 returns something usable. */
3649 idx = 0;
3652 if (idx <= 0)
3653 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3654 if (idx > 0)
3656 strinfo *si = get_strinfo (idx);
3657 if (si
3658 && si->nonzero_chars
3659 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3661 widest_int w1 = wi::to_widest (si->nonzero_chars);
3662 widest_int w2 = wi::to_widest (off) + coff;
3663 if (w1 == w2
3664 && si->full_string_p)
3666 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3668 fprintf (dump_file, "Optimizing: ");
3669 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3672 /* Reading the final '\0' character. */
3673 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3674 gimple_set_vuse (stmt, NULL_TREE);
3675 gimple_assign_set_rhs_from_tree (gsi, zero);
3676 *cleanup_eh
3677 |= maybe_clean_or_replace_eh_stmt (stmt,
3678 gsi_stmt (*gsi));
3679 stmt = gsi_stmt (*gsi);
3680 update_stmt (stmt);
3682 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3684 fprintf (dump_file, "into: ");
3685 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3688 else if (w1 > w2)
3690 /* Reading a character before the final '\0'
3691 character. Just set the value range to ~[0, 0]
3692 if we don't have anything better. */
3693 wide_int min, max;
3694 tree type = TREE_TYPE (lhs);
3695 enum value_range_type vr
3696 = get_range_info (lhs, &min, &max);
3697 if (vr == VR_VARYING
3698 || (vr == VR_RANGE
3699 && min == wi::min_value (TYPE_PRECISION (type),
3700 TYPE_SIGN (type))
3701 && max == wi::max_value (TYPE_PRECISION (type),
3702 TYPE_SIGN (type))))
3703 set_range_info (lhs, VR_ANTI_RANGE,
3704 wi::zero (TYPE_PRECISION (type)),
3705 wi::zero (TYPE_PRECISION (type)));
3711 if (strlen_to_stridx)
3713 tree rhs1 = gimple_assign_rhs1 (stmt);
3714 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3715 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3718 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3720 tree type = TREE_TYPE (lhs);
3721 if (TREE_CODE (type) == ARRAY_TYPE)
3722 type = TREE_TYPE (type);
3723 if (TREE_CODE (type) == INTEGER_TYPE
3724 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3725 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3727 if (! handle_char_store (gsi))
3728 return false;
3732 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3734 enum tree_code code = gimple_cond_code (cond);
3735 if (code == EQ_EXPR || code == NE_EXPR)
3736 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3737 gimple_cond_rhs (stmt), stmt);
3740 if (gimple_vdef (stmt))
3741 maybe_invalidate (stmt);
3742 return true;
3745 /* Recursively call maybe_invalidate on stmts that might be executed
3746 in between dombb and current bb and that contain a vdef. Stop when
3747 *count stmts are inspected, or if the whole strinfo vector has
3748 been invalidated. */
3750 static void
3751 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3753 unsigned int i, n = gimple_phi_num_args (phi);
3755 for (i = 0; i < n; i++)
3757 tree vuse = gimple_phi_arg_def (phi, i);
3758 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3759 basic_block bb = gimple_bb (stmt);
3760 if (bb == NULL
3761 || bb == dombb
3762 || !bitmap_set_bit (visited, bb->index)
3763 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3764 continue;
3765 while (1)
3767 if (gimple_code (stmt) == GIMPLE_PHI)
3769 do_invalidate (dombb, stmt, visited, count);
3770 if (*count == 0)
3771 return;
3772 break;
3774 if (--*count == 0)
3775 return;
3776 if (!maybe_invalidate (stmt))
3778 *count = 0;
3779 return;
3781 vuse = gimple_vuse (stmt);
3782 stmt = SSA_NAME_DEF_STMT (vuse);
3783 if (gimple_bb (stmt) != bb)
3785 bb = gimple_bb (stmt);
3786 if (bb == NULL
3787 || bb == dombb
3788 || !bitmap_set_bit (visited, bb->index)
3789 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3790 break;
3796 class strlen_dom_walker : public dom_walker
3798 public:
3799 strlen_dom_walker (cdi_direction direction)
3800 : dom_walker (direction), m_cleanup_cfg (false)
3803 virtual edge before_dom_children (basic_block);
3804 virtual void after_dom_children (basic_block);
3806 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3807 execute function. */
3808 bool m_cleanup_cfg;
3811 /* Callback for walk_dominator_tree. Attempt to optimize various
3812 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3814 edge
3815 strlen_dom_walker::before_dom_children (basic_block bb)
3817 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3819 if (dombb == NULL)
3820 stridx_to_strinfo = NULL;
3821 else
3823 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3824 if (stridx_to_strinfo)
3826 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3827 gsi_next (&gsi))
3829 gphi *phi = gsi.phi ();
3830 if (virtual_operand_p (gimple_phi_result (phi)))
3832 bitmap visited = BITMAP_ALLOC (NULL);
3833 int count_vdef = 100;
3834 do_invalidate (dombb, phi, visited, &count_vdef);
3835 BITMAP_FREE (visited);
3836 if (count_vdef == 0)
3838 /* If there were too many vdefs in between immediate
3839 dominator and current bb, invalidate everything.
3840 If stridx_to_strinfo has been unshared, we need
3841 to free it, otherwise just set it to NULL. */
3842 if (!strinfo_shared ())
3844 unsigned int i;
3845 strinfo *si;
3847 for (i = 1;
3848 vec_safe_iterate (stridx_to_strinfo, i, &si);
3849 ++i)
3851 free_strinfo (si);
3852 (*stridx_to_strinfo)[i] = NULL;
3855 else
3856 stridx_to_strinfo = NULL;
3858 break;
3864 /* If all PHI arguments have the same string index, the PHI result
3865 has it as well. */
3866 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3867 gsi_next (&gsi))
3869 gphi *phi = gsi.phi ();
3870 tree result = gimple_phi_result (phi);
3871 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3873 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3874 if (idx != 0)
3876 unsigned int i, n = gimple_phi_num_args (phi);
3877 for (i = 1; i < n; i++)
3878 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3879 break;
3880 if (i == n)
3881 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3886 bool cleanup_eh = false;
3888 /* Attempt to optimize individual statements. */
3889 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3890 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
3891 gsi_next (&gsi);
3893 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
3894 m_cleanup_cfg = true;
3896 bb->aux = stridx_to_strinfo;
3897 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3898 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3899 return NULL;
3902 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3903 owned by the current bb, clear bb->aux. */
3905 void
3906 strlen_dom_walker::after_dom_children (basic_block bb)
3908 if (bb->aux)
3910 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3911 if (vec_safe_length (stridx_to_strinfo)
3912 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3914 unsigned int i;
3915 strinfo *si;
3917 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3918 free_strinfo (si);
3919 vec_free (stridx_to_strinfo);
3921 bb->aux = NULL;
3925 /* Main entry point. */
3927 namespace {
3929 const pass_data pass_data_strlen =
3931 GIMPLE_PASS, /* type */
3932 "strlen", /* name */
3933 OPTGROUP_NONE, /* optinfo_flags */
3934 TV_TREE_STRLEN, /* tv_id */
3935 ( PROP_cfg | PROP_ssa ), /* properties_required */
3936 0, /* properties_provided */
3937 0, /* properties_destroyed */
3938 0, /* todo_flags_start */
3939 0, /* todo_flags_finish */
3942 class pass_strlen : public gimple_opt_pass
3944 public:
3945 pass_strlen (gcc::context *ctxt)
3946 : gimple_opt_pass (pass_data_strlen, ctxt)
3949 /* opt_pass methods: */
3950 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3951 virtual unsigned int execute (function *);
3953 }; // class pass_strlen
3955 unsigned int
3956 pass_strlen::execute (function *fun)
3958 gcc_assert (!strlen_to_stridx);
3959 if (warn_stringop_overflow || warn_stringop_truncation)
3960 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3962 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3963 max_stridx = 1;
3965 calculate_dominance_info (CDI_DOMINATORS);
3967 /* String length optimization is implemented as a walk of the dominator
3968 tree and a forward walk of statements within each block. */
3969 strlen_dom_walker walker (CDI_DOMINATORS);
3970 walker.walk (fun->cfg->x_entry_block_ptr);
3972 ssa_ver_to_stridx.release ();
3973 strinfo_pool.release ();
3974 if (decl_to_stridxlist_htab)
3976 obstack_free (&stridx_obstack, NULL);
3977 delete decl_to_stridxlist_htab;
3978 decl_to_stridxlist_htab = NULL;
3980 laststmt.stmt = NULL;
3981 laststmt.len = NULL_TREE;
3982 laststmt.stridx = 0;
3984 if (strlen_to_stridx)
3986 strlen_to_stridx->empty ();
3987 delete strlen_to_stridx;
3988 strlen_to_stridx = NULL;
3991 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
3994 } // anon namespace
3996 gimple_opt_pass *
3997 make_pass_strlen (gcc::context *ctxt)
3999 return new pass_strlen (ctxt);