PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob8794cc240c8b5cb2beb124981f3a35ff9633ff72
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);
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 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
585 lhs = gimple_call_lhs (stmt);
586 /* unshare_strinfo is intentionally not called here. The (delayed)
587 transformation of strcpy or strcat into stpcpy is done at the place
588 of the former strcpy/strcat call and so can affect all the strinfos
589 with the same stmt. If they were unshared before and transformation
590 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
591 just compute the right length. */
592 switch (DECL_FUNCTION_CODE (callee))
594 case BUILT_IN_STRCAT:
595 case BUILT_IN_STRCAT_CHK:
596 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 else if (TREE_CODE (len) == SSA_NAME)
1113 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1114 if (!is_gimple_assign (def_stmt)
1115 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1116 || gimple_assign_rhs1 (def_stmt) != last.len
1117 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1118 return;
1120 else
1121 return;
1123 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1124 update_stmt (last.stmt);
1127 /* For an LHS that is an SSA_NAME and for strlen() argument SRC, set
1128 LHS range info to [0, N] if SRC refers to a character array A[N]
1129 with unknown length bounded by N. */
1131 static void
1132 maybe_set_strlen_range (tree lhs, tree src)
1134 if (TREE_CODE (lhs) != SSA_NAME)
1135 return;
1137 if (TREE_CODE (src) == SSA_NAME)
1139 gimple *def = SSA_NAME_DEF_STMT (src);
1140 if (is_gimple_assign (def)
1141 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1142 src = gimple_assign_rhs1 (def);
1145 if (TREE_CODE (src) != ADDR_EXPR)
1146 return;
1148 /* The last array member of a struct can be bigger than its size
1149 suggests if it's treated as a poor-man's flexible array member. */
1150 src = TREE_OPERAND (src, 0);
1151 if (TREE_CODE (TREE_TYPE (src)) != ARRAY_TYPE
1152 || array_at_struct_end_p (src))
1153 return;
1155 tree type = TREE_TYPE (src);
1156 if (tree dom = TYPE_DOMAIN (type))
1157 if (tree maxval = TYPE_MAX_VALUE (dom))
1159 wide_int max = wi::to_wide (maxval);
1160 wide_int min = wi::zero (max.get_precision ());
1161 set_range_info (lhs, VR_RANGE, min, max);
1165 /* Handle a strlen call. If strlen of the argument is known, replace
1166 the strlen call with the known value, otherwise remember that strlen
1167 of the argument is stored in the lhs SSA_NAME. */
1169 static void
1170 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1172 int idx;
1173 tree src;
1174 gimple *stmt = gsi_stmt (*gsi);
1175 tree lhs = gimple_call_lhs (stmt);
1177 if (lhs == NULL_TREE)
1178 return;
1180 src = gimple_call_arg (stmt, 0);
1181 idx = get_stridx (src);
1182 if (idx)
1184 strinfo *si = NULL;
1185 tree rhs;
1187 if (idx < 0)
1188 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1189 else
1191 rhs = NULL_TREE;
1192 si = get_strinfo (idx);
1193 if (si != NULL)
1194 rhs = get_string_length (si);
1196 if (rhs != NULL_TREE)
1198 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1200 fprintf (dump_file, "Optimizing: ");
1201 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1203 rhs = unshare_expr (rhs);
1204 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1205 rhs = fold_convert_loc (gimple_location (stmt),
1206 TREE_TYPE (lhs), rhs);
1207 if (!update_call_from_tree (gsi, rhs))
1208 gimplify_and_update_call_from_tree (gsi, rhs);
1209 stmt = gsi_stmt (*gsi);
1210 update_stmt (stmt);
1211 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1213 fprintf (dump_file, "into: ");
1214 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1216 if (si != NULL
1217 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1218 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1219 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1221 si = unshare_strinfo (si);
1222 si->nonzero_chars = lhs;
1223 gcc_assert (si->full_string_p);
1226 if (strlen_to_stridx)
1228 location_t loc = gimple_location (stmt);
1229 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1231 return;
1234 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1235 return;
1236 if (idx == 0)
1237 idx = new_stridx (src);
1238 else
1240 strinfo *si = get_strinfo (idx);
1241 if (si != NULL)
1243 if (!si->full_string_p && !si->stmt)
1245 /* Until now we only had a lower bound on the string length.
1246 Install LHS as the actual length. */
1247 si = unshare_strinfo (si);
1248 tree old = si->nonzero_chars;
1249 si->nonzero_chars = lhs;
1250 si->full_string_p = true;
1251 if (TREE_CODE (old) == INTEGER_CST)
1253 location_t loc = gimple_location (stmt);
1254 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1255 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1256 TREE_TYPE (lhs), lhs, old);
1257 adjust_related_strinfos (loc, si, adj);
1259 else
1261 si->first = 0;
1262 si->prev = 0;
1263 si->next = 0;
1266 return;
1269 if (idx)
1271 strinfo *si = new_strinfo (src, idx, lhs, true);
1272 set_strinfo (idx, si);
1273 find_equal_ptrs (src, idx);
1275 /* For SRC that is an array of N elements, set LHS's range
1276 to [0, N]. */
1277 maybe_set_strlen_range (lhs, src);
1279 if (strlen_to_stridx)
1281 location_t loc = gimple_location (stmt);
1282 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1287 /* Handle a strchr call. If strlen of the first argument is known, replace
1288 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1289 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1291 static void
1292 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1294 int idx;
1295 tree src;
1296 gimple *stmt = gsi_stmt (*gsi);
1297 tree lhs = gimple_call_lhs (stmt);
1299 if (lhs == NULL_TREE)
1300 return;
1302 if (!integer_zerop (gimple_call_arg (stmt, 1)))
1303 return;
1305 src = gimple_call_arg (stmt, 0);
1306 idx = get_stridx (src);
1307 if (idx)
1309 strinfo *si = NULL;
1310 tree rhs;
1312 if (idx < 0)
1313 rhs = build_int_cst (size_type_node, ~idx);
1314 else
1316 rhs = NULL_TREE;
1317 si = get_strinfo (idx);
1318 if (si != NULL)
1319 rhs = get_string_length (si);
1321 if (rhs != NULL_TREE)
1323 location_t loc = gimple_location (stmt);
1325 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1327 fprintf (dump_file, "Optimizing: ");
1328 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1330 if (si != NULL && si->endptr != NULL_TREE)
1332 rhs = unshare_expr (si->endptr);
1333 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1334 TREE_TYPE (rhs)))
1335 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1337 else
1339 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1340 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1341 TREE_TYPE (src), src, rhs);
1342 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1343 TREE_TYPE (rhs)))
1344 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1346 if (!update_call_from_tree (gsi, rhs))
1347 gimplify_and_update_call_from_tree (gsi, rhs);
1348 stmt = gsi_stmt (*gsi);
1349 update_stmt (stmt);
1350 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1352 fprintf (dump_file, "into: ");
1353 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1355 if (si != NULL
1356 && si->endptr == NULL_TREE
1357 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1359 si = unshare_strinfo (si);
1360 si->endptr = lhs;
1362 zero_length_string (lhs, si);
1363 return;
1366 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1367 return;
1368 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1370 if (idx == 0)
1371 idx = new_stridx (src);
1372 else if (get_strinfo (idx) != NULL)
1374 zero_length_string (lhs, NULL);
1375 return;
1377 if (idx)
1379 location_t loc = gimple_location (stmt);
1380 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1381 tree srcu = fold_convert_loc (loc, size_type_node, src);
1382 tree length = fold_build2_loc (loc, MINUS_EXPR,
1383 size_type_node, lhsu, srcu);
1384 strinfo *si = new_strinfo (src, idx, length, true);
1385 si->endptr = lhs;
1386 set_strinfo (idx, si);
1387 find_equal_ptrs (src, idx);
1388 zero_length_string (lhs, si);
1391 else
1392 zero_length_string (lhs, NULL);
1395 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1396 If strlen of the second argument is known, strlen of the first argument
1397 is the same after this call. Furthermore, attempt to convert it to
1398 memcpy. */
1400 static void
1401 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1403 int idx, didx;
1404 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1405 bool success;
1406 gimple *stmt = gsi_stmt (*gsi);
1407 strinfo *si, *dsi, *olddsi, *zsi;
1408 location_t loc;
1410 src = gimple_call_arg (stmt, 1);
1411 dst = gimple_call_arg (stmt, 0);
1412 lhs = gimple_call_lhs (stmt);
1413 idx = get_stridx (src);
1414 si = NULL;
1415 if (idx > 0)
1416 si = get_strinfo (idx);
1418 didx = get_stridx (dst);
1419 olddsi = NULL;
1420 oldlen = NULL_TREE;
1421 if (didx > 0)
1422 olddsi = get_strinfo (didx);
1423 else if (didx < 0)
1424 return;
1426 if (olddsi != NULL)
1427 adjust_last_stmt (olddsi, stmt, false);
1429 srclen = NULL_TREE;
1430 if (si != NULL)
1431 srclen = get_string_length (si);
1432 else if (idx < 0)
1433 srclen = build_int_cst (size_type_node, ~idx);
1435 loc = gimple_location (stmt);
1436 if (srclen == NULL_TREE)
1437 switch (bcode)
1439 case BUILT_IN_STRCPY:
1440 case BUILT_IN_STRCPY_CHK:
1441 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1442 return;
1443 break;
1444 case BUILT_IN_STPCPY:
1445 case BUILT_IN_STPCPY_CHK:
1446 if (lhs == NULL_TREE)
1447 return;
1448 else
1450 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1451 srclen = fold_convert_loc (loc, size_type_node, dst);
1452 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1453 lhsuint, srclen);
1455 break;
1456 default:
1457 gcc_unreachable ();
1460 if (didx == 0)
1462 didx = new_stridx (dst);
1463 if (didx == 0)
1464 return;
1466 if (olddsi != NULL)
1468 oldlen = olddsi->nonzero_chars;
1469 dsi = unshare_strinfo (olddsi);
1470 dsi->nonzero_chars = srclen;
1471 dsi->full_string_p = (srclen != NULL_TREE);
1472 /* Break the chain, so adjust_related_strinfo on later pointers in
1473 the chain won't adjust this one anymore. */
1474 dsi->next = 0;
1475 dsi->stmt = NULL;
1476 dsi->endptr = NULL_TREE;
1478 else
1480 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1481 set_strinfo (didx, dsi);
1482 find_equal_ptrs (dst, didx);
1484 dsi->writable = true;
1485 dsi->dont_invalidate = true;
1487 if (dsi->nonzero_chars == NULL_TREE)
1489 strinfo *chainsi;
1491 /* If string length of src is unknown, use delayed length
1492 computation. If string lenth of dst will be needed, it
1493 can be computed by transforming this strcpy call into
1494 stpcpy and subtracting dst from the return value. */
1496 /* Look for earlier strings whose length could be determined if
1497 this strcpy is turned into an stpcpy. */
1499 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1501 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1503 /* When setting a stmt for delayed length computation
1504 prevent all strinfos through dsi from being
1505 invalidated. */
1506 chainsi = unshare_strinfo (chainsi);
1507 chainsi->stmt = stmt;
1508 chainsi->nonzero_chars = NULL_TREE;
1509 chainsi->full_string_p = false;
1510 chainsi->endptr = NULL_TREE;
1511 chainsi->dont_invalidate = true;
1514 dsi->stmt = stmt;
1516 /* Try to detect overlap before returning. This catches cases
1517 like strcpy (d, d + n) where n is non-constant whose range
1518 is such that (n <= strlen (d) holds).
1520 OLDDSI->NONZERO_chars may have been reset by this point with
1521 oldlen holding it original value. */
1522 if (olddsi && oldlen)
1524 /* Add 1 for the terminating NUL. */
1525 tree type = TREE_TYPE (oldlen);
1526 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1527 build_int_cst (type, 1));
1528 check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
1529 oldlen, NULL_TREE);
1532 return;
1535 if (olddsi != NULL)
1537 tree adj = NULL_TREE;
1538 if (oldlen == NULL_TREE)
1540 else if (integer_zerop (oldlen))
1541 adj = srclen;
1542 else if (TREE_CODE (oldlen) == INTEGER_CST
1543 || TREE_CODE (srclen) == INTEGER_CST)
1544 adj = fold_build2_loc (loc, MINUS_EXPR,
1545 TREE_TYPE (srclen), srclen,
1546 fold_convert_loc (loc, TREE_TYPE (srclen),
1547 oldlen));
1548 if (adj != NULL_TREE)
1549 adjust_related_strinfos (loc, dsi, adj);
1550 else
1551 dsi->prev = 0;
1553 /* strcpy src may not overlap dst, so src doesn't need to be
1554 invalidated either. */
1555 if (si != NULL)
1556 si->dont_invalidate = true;
1558 fn = NULL_TREE;
1559 zsi = NULL;
1560 switch (bcode)
1562 case BUILT_IN_STRCPY:
1563 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1564 if (lhs)
1565 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1566 break;
1567 case BUILT_IN_STRCPY_CHK:
1568 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1569 if (lhs)
1570 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1571 break;
1572 case BUILT_IN_STPCPY:
1573 /* This would need adjustment of the lhs (subtract one),
1574 or detection that the trailing '\0' doesn't need to be
1575 written, if it will be immediately overwritten.
1576 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1577 if (lhs)
1579 dsi->endptr = lhs;
1580 zsi = zero_length_string (lhs, dsi);
1582 break;
1583 case BUILT_IN_STPCPY_CHK:
1584 /* This would need adjustment of the lhs (subtract one),
1585 or detection that the trailing '\0' doesn't need to be
1586 written, if it will be immediately overwritten.
1587 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1588 if (lhs)
1590 dsi->endptr = lhs;
1591 zsi = zero_length_string (lhs, dsi);
1593 break;
1594 default:
1595 gcc_unreachable ();
1597 if (zsi != NULL)
1598 zsi->dont_invalidate = true;
1600 if (fn)
1602 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1603 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1605 else
1606 type = size_type_node;
1608 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1609 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1611 /* Set the no-warning bit on the transformed statement? */
1612 bool set_no_warning = false;
1614 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1615 if (si
1616 && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
1617 NULL_TREE, len))
1619 gimple_set_no_warning (stmt, true);
1620 set_no_warning = true;
1623 if (fn == NULL_TREE)
1624 return;
1626 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1627 GSI_SAME_STMT);
1628 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1630 fprintf (dump_file, "Optimizing: ");
1631 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1633 if (gimple_call_num_args (stmt) == 2)
1634 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1635 else
1636 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1637 gimple_call_arg (stmt, 2));
1638 if (success)
1640 stmt = gsi_stmt (*gsi);
1641 update_stmt (stmt);
1642 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1644 fprintf (dump_file, "into: ");
1645 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1647 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1648 laststmt.stmt = stmt;
1649 laststmt.len = srclen;
1650 laststmt.stridx = dsi->idx;
1652 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1653 fprintf (dump_file, "not possible.\n");
1655 if (set_no_warning)
1656 gimple_set_no_warning (stmt, true);
1659 /* Check the size argument to the built-in forms of stpncpy and strncpy
1660 for out-of-bounds offsets or overlapping access, and to see if the
1661 size argument is derived from a call to strlen() on the source argument,
1662 and if so, issue an appropriate warning. */
1664 static void
1665 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1667 /* Same as stxncpy(). */
1668 handle_builtin_stxncpy (bcode, gsi);
1671 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1672 way. LEN can either be an integer expression, or a pointer (to char).
1673 When it is the latter (such as in recursive calls to self) is is
1674 assumed to be the argument in some call to strlen() whose relationship
1675 to SRC is being ascertained. */
1677 static bool
1678 is_strlen_related_p (tree src, tree len)
1680 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1681 && operand_equal_p (src, len, 0))
1682 return true;
1684 if (TREE_CODE (len) != SSA_NAME)
1685 return false;
1687 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1688 if (!def_stmt)
1689 return false;
1691 if (is_gimple_call (def_stmt))
1693 tree func = gimple_call_fndecl (def_stmt);
1694 if (!valid_builtin_call (def_stmt)
1695 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1696 return false;
1698 tree arg = gimple_call_arg (def_stmt, 0);
1699 return is_strlen_related_p (src, arg);
1702 if (!is_gimple_assign (def_stmt))
1703 return false;
1705 tree_code code = gimple_assign_rhs_code (def_stmt);
1706 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1707 tree rhstype = TREE_TYPE (rhs1);
1709 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1710 || (INTEGRAL_TYPE_P (rhstype)
1711 && (code == BIT_AND_EXPR
1712 || code == NOP_EXPR)))
1714 /* Pointer plus (an integer) and integer cast or truncation are
1715 considered among the (potentially) related expressions to strlen.
1716 Others are not. */
1717 return is_strlen_related_p (src, rhs1);
1720 return false;
1723 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1724 in gimple-fold.c.
1725 Check to see if the specified bound is a) equal to the size of
1726 the destination DST and if so, b) if it's immediately followed by
1727 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1728 do nothing. Return true if diagnostic has been issued.
1730 The purpose is to diagnose calls to strncpy and stpncpy that do
1731 not nul-terminate the copy while allowing for the idiom where
1732 such a call is immediately followed by setting the last element
1733 to nul, as in:
1734 char a[32];
1735 strncpy (a, s, sizeof a);
1736 a[sizeof a - 1] = '\0';
1739 bool
1740 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1742 gimple *stmt = gsi_stmt (gsi);
1743 if (gimple_no_warning_p (stmt))
1744 return false;
1746 wide_int cntrange[2];
1748 if (TREE_CODE (cnt) == INTEGER_CST)
1749 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1750 else if (TREE_CODE (cnt) == SSA_NAME)
1752 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1753 if (rng == VR_RANGE)
1755 else if (rng == VR_ANTI_RANGE)
1757 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1759 if (wi::ltu_p (cntrange[1], maxobjsize))
1761 cntrange[0] = cntrange[1] + 1;
1762 cntrange[1] = maxobjsize;
1764 else
1766 cntrange[1] = cntrange[0] - 1;
1767 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1770 else
1771 return false;
1773 else
1774 return false;
1776 /* Negative value is the constant string length. If it's less than
1777 the lower bound there is no truncation. Avoid calling get_stridx()
1778 when ssa_ver_to_stridx is empty. That implies the caller isn't
1779 running under the control of this pass and ssa_ver_to_stridx hasn't
1780 been created yet. */
1781 int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
1782 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1783 return false;
1785 tree dst = gimple_call_arg (stmt, 0);
1786 tree dstdecl = dst;
1787 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1788 dstdecl = TREE_OPERAND (dstdecl, 0);
1790 /* If the destination refers to a an array/pointer declared nonstring
1791 return early. */
1792 tree ref = NULL_TREE;
1793 if (get_attr_nonstring_decl (dstdecl, &ref))
1794 return false;
1796 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1797 avoid the truncation warning. */
1798 gsi_next_nondebug (&gsi);
1799 gimple *next_stmt = gsi_stmt (gsi);
1800 if (!next_stmt)
1802 /* When there is no statement in the same basic block check
1803 the immediate successor block. */
1804 if (basic_block bb = gimple_bb (stmt))
1806 if (single_succ_p (bb))
1808 /* For simplicity, ignore blocks with multiple outgoing
1809 edges for now and only consider successor blocks along
1810 normal edges. */
1811 edge e = EDGE_SUCC (bb, 0);
1812 if (!(e->flags & EDGE_ABNORMAL))
1814 gsi = gsi_start_bb (e->dest);
1815 next_stmt = gsi_stmt (gsi);
1816 if (next_stmt && is_gimple_debug (next_stmt))
1818 gsi_next_nondebug (&gsi);
1819 next_stmt = gsi_stmt (gsi);
1826 if (next_stmt && is_gimple_assign (next_stmt))
1828 tree lhs = gimple_assign_lhs (next_stmt);
1829 tree_code code = TREE_CODE (lhs);
1830 if (code == ARRAY_REF || code == MEM_REF)
1831 lhs = TREE_OPERAND (lhs, 0);
1833 tree func = gimple_call_fndecl (stmt);
1834 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1836 tree ret = gimple_call_lhs (stmt);
1837 if (ret && operand_equal_p (ret, lhs, 0))
1838 return false;
1841 /* Determine the base address and offset of the reference,
1842 ignoring the innermost array index. */
1843 if (TREE_CODE (ref) == ARRAY_REF)
1844 ref = TREE_OPERAND (ref, 0);
1846 poly_int64 dstoff;
1847 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1849 poly_int64 lhsoff;
1850 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1851 if (lhsbase
1852 && dstbase
1853 && known_eq (dstoff, lhsoff)
1854 && operand_equal_p (dstbase, lhsbase, 0))
1855 return false;
1858 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1859 wide_int lenrange[2];
1860 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1862 lenrange[0] = (sisrc->nonzero_chars
1863 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1864 ? wi::to_wide (sisrc->nonzero_chars)
1865 : wi::zero (prec));
1866 lenrange[1] = lenrange[0];
1868 else if (sidx < 0)
1869 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1870 else
1872 tree range[2];
1873 get_range_strlen (src, range);
1874 if (range[0] != NULL_TREE
1875 && TREE_CODE (range[0]) == INTEGER_CST
1876 && range[1] != NULL_TREE
1877 && TREE_CODE (range[1]) == INTEGER_CST)
1879 lenrange[0] = wi::to_wide (range[0], prec);
1880 lenrange[1] = wi::to_wide (range[1], prec);
1882 else
1884 lenrange[0] = wi::shwi (0, prec);
1885 lenrange[1] = wi::shwi (-1, prec);
1889 location_t callloc = gimple_nonartificial_location (stmt);
1890 callloc = expansion_point_location_if_in_system_header (callloc);
1892 tree func = gimple_call_fndecl (stmt);
1894 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1896 /* If the longest source string is shorter than the lower bound
1897 of the specified count the copy is definitely nul-terminated. */
1898 if (wi::ltu_p (lenrange[1], cntrange[0]))
1899 return false;
1901 if (wi::neg_p (lenrange[1]))
1903 /* The length of one of the strings is unknown but at least
1904 one has non-zero length and that length is stored in
1905 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1906 warning below. */
1907 lenrange[1] = lenrange[0];
1908 lenrange[0] = wi::shwi (0, prec);
1911 gcall *call = as_a <gcall *> (stmt);
1913 if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
1914 return warning_n (callloc, OPT_Wstringop_truncation,
1915 cntrange[0].to_uhwi (),
1916 "%G%qD output truncated before terminating "
1917 "nul copying %E byte from a string of the "
1918 "same length",
1919 "%G%qD output truncated before terminating nul "
1920 "copying %E bytes from a string of the same "
1921 "length",
1922 call, func, cnt);
1923 else if (wi::geu_p (lenrange[0], cntrange[1]))
1925 /* The shortest string is longer than the upper bound of
1926 the count so the truncation is certain. */
1927 if (cntrange[0] == cntrange[1])
1928 return warning_n (callloc, OPT_Wstringop_truncation,
1929 cntrange[0].to_uhwi (),
1930 "%G%qD output truncated copying %E byte "
1931 "from a string of length %wu",
1932 "%G%qD output truncated copying %E bytes "
1933 "from a string of length %wu",
1934 call, func, cnt, lenrange[0].to_uhwi ());
1936 return warning_at (callloc, OPT_Wstringop_truncation,
1937 "%G%qD output truncated copying between %wu "
1938 "and %wu bytes from a string of length %wu",
1939 call, func, cntrange[0].to_uhwi (),
1940 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1942 else if (wi::geu_p (lenrange[1], cntrange[1]))
1944 /* The longest string is longer than the upper bound of
1945 the count so the truncation is possible. */
1946 if (cntrange[0] == cntrange[1])
1947 return warning_n (callloc, OPT_Wstringop_truncation,
1948 cntrange[0].to_uhwi (),
1949 "%G%qD output may be truncated copying %E "
1950 "byte from a string of length %wu",
1951 "%G%qD output may be truncated copying %E "
1952 "bytes from a string of length %wu",
1953 call, func, cnt, lenrange[1].to_uhwi ());
1955 return warning_at (callloc, OPT_Wstringop_truncation,
1956 "%G%qD output may be truncated copying between %wu "
1957 "and %wu bytes from a string of length %wu",
1958 call, func, cntrange[0].to_uhwi (),
1959 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1962 if (cntrange[0] != cntrange[1]
1963 && wi::leu_p (cntrange[0], lenrange[0])
1964 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1966 /* If the source (including the terminating nul) is longer than
1967 the lower bound of the specified count but shorter than the
1968 upper bound the copy may (but need not) be truncated. */
1969 return warning_at (callloc, OPT_Wstringop_truncation,
1970 "%G%qD output may be truncated copying between "
1971 "%wu and %wu bytes from a string of length %wu",
1972 call, func, cntrange[0].to_uhwi (),
1973 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1977 if (tree dstsize = compute_objsize (dst, 1))
1979 /* The source length is uknown. Try to determine the destination
1980 size and see if it matches the specified bound. If not, bail.
1981 Otherwise go on to see if it should be diagnosed for possible
1982 truncation. */
1983 if (!dstsize)
1984 return false;
1986 if (wi::to_wide (dstsize) != cntrange[1])
1987 return false;
1989 if (cntrange[0] == cntrange[1])
1990 return warning_at (callloc, OPT_Wstringop_truncation,
1991 "%G%qD specified bound %E equals destination size",
1992 as_a <gcall *> (stmt), func, cnt);
1995 return false;
1998 /* Check the arguments to the built-in forms of stpncpy and strncpy for
1999 out-of-bounds offsets or overlapping access, and to see if the size
2000 is derived from calling strlen() on the source argument, and if so,
2001 issue the appropriate warning. */
2003 static void
2004 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2006 if (!strlen_to_stridx)
2007 return;
2009 gimple *stmt = gsi_stmt (*gsi);
2011 tree dst = gimple_call_arg (stmt, 0);
2012 tree src = gimple_call_arg (stmt, 1);
2013 tree len = gimple_call_arg (stmt, 2);
2014 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2016 int didx = get_stridx (dst);
2017 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2019 /* Compute the size of the destination string including the NUL. */
2020 if (sidst->nonzero_chars)
2022 tree type = TREE_TYPE (sidst->nonzero_chars);
2023 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2024 build_int_cst (type, 1));
2026 dst = sidst->ptr;
2029 int sidx = get_stridx (src);
2030 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2031 if (sisrc)
2033 /* strncat() and strncpy() can modify the source string by writing
2034 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2035 clear. */
2037 /* Compute the size of the source string including the NUL. */
2038 if (sisrc->nonzero_chars)
2040 tree type = TREE_TYPE (sisrc->nonzero_chars);
2041 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2042 build_int_cst (type, 1));
2045 src = sisrc->ptr;
2047 else
2048 srcsize = NULL_TREE;
2050 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
2051 dstsize, srcsize))
2053 gimple_set_no_warning (stmt, true);
2054 return;
2057 /* If the length argument was computed from strlen(S) for some string
2058 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2059 the location of the strlen() call (PSS->SECOND). */
2060 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2061 if (!pss || pss->first <= 0)
2063 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2064 gimple_set_no_warning (stmt, true);
2066 return;
2069 /* Retrieve the strinfo data for the string S that LEN was computed
2070 from as some function F of strlen (S) (i.e., LEN need not be equal
2071 to strlen(S)). */
2072 strinfo *silen = get_strinfo (pss->first);
2074 location_t callloc = gimple_nonartificial_location (stmt);
2075 callloc = expansion_point_location_if_in_system_header (callloc);
2077 tree func = gimple_call_fndecl (stmt);
2079 bool warned = false;
2081 /* When -Wstringop-truncation is set, try to determine truncation
2082 before diagnosing possible overflow. Truncation is implied by
2083 the LEN argument being equal to strlen(SRC), regardless of
2084 whether its value is known. Otherwise, issue the more generic
2085 -Wstringop-overflow which triggers for LEN arguments that in
2086 any meaningful way depend on strlen(SRC). */
2087 if (sisrc == silen
2088 && is_strlen_related_p (src, len)
2089 && warning_at (callloc, OPT_Wstringop_truncation,
2090 "%G%qD output truncated before terminating nul "
2091 "copying as many bytes from a string as its length",
2092 as_a <gcall *>(stmt), func))
2093 warned = true;
2094 else if (silen && is_strlen_related_p (src, silen->ptr))
2095 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2096 "%G%qD specified bound depends on the length "
2097 "of the source argument",
2098 as_a <gcall *>(stmt), func);
2099 if (warned)
2101 location_t strlenloc = pss->second;
2102 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2103 inform (strlenloc, "length computed here");
2107 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2108 If strlen of the second argument is known and length of the third argument
2109 is that plus one, strlen of the first argument is the same after this
2110 call. */
2112 static void
2113 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2115 int idx, didx;
2116 tree src, dst, len, lhs, oldlen, newlen;
2117 gimple *stmt = gsi_stmt (*gsi);
2118 strinfo *si, *dsi, *olddsi;
2120 len = gimple_call_arg (stmt, 2);
2121 src = gimple_call_arg (stmt, 1);
2122 dst = gimple_call_arg (stmt, 0);
2123 idx = get_stridx (src);
2124 if (idx == 0)
2125 return;
2127 didx = get_stridx (dst);
2128 olddsi = NULL;
2129 if (didx > 0)
2130 olddsi = get_strinfo (didx);
2131 else if (didx < 0)
2132 return;
2134 if (olddsi != NULL
2135 && tree_fits_uhwi_p (len)
2136 && !integer_zerop (len))
2137 adjust_last_stmt (olddsi, stmt, false);
2139 bool full_string_p;
2140 if (idx > 0)
2142 gimple *def_stmt;
2144 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2145 is known. */
2146 si = get_strinfo (idx);
2147 if (si == NULL || si->nonzero_chars == NULL_TREE)
2148 return;
2149 if (TREE_CODE (len) == INTEGER_CST
2150 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2152 if (tree_int_cst_le (len, si->nonzero_chars))
2154 /* Copying LEN nonzero characters, where LEN is constant. */
2155 newlen = len;
2156 full_string_p = false;
2158 else
2160 /* Copying the whole of the analyzed part of SI. */
2161 newlen = si->nonzero_chars;
2162 full_string_p = si->full_string_p;
2165 else
2167 if (!si->full_string_p)
2168 return;
2169 if (TREE_CODE (len) != SSA_NAME)
2170 return;
2171 def_stmt = SSA_NAME_DEF_STMT (len);
2172 if (!is_gimple_assign (def_stmt)
2173 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2174 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2175 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2176 return;
2177 /* Copying variable-length string SI (and no more). */
2178 newlen = si->nonzero_chars;
2179 full_string_p = true;
2182 else
2184 si = NULL;
2185 /* Handle memcpy (x, "abcd", 5) or
2186 memcpy (x, "abc\0uvw", 7). */
2187 if (!tree_fits_uhwi_p (len))
2188 return;
2190 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2191 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2192 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2193 full_string_p = clen > nonzero_chars;
2196 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2197 adjust_last_stmt (olddsi, stmt, false);
2199 if (didx == 0)
2201 didx = new_stridx (dst);
2202 if (didx == 0)
2203 return;
2205 oldlen = NULL_TREE;
2206 if (olddsi != NULL)
2208 dsi = unshare_strinfo (olddsi);
2209 oldlen = olddsi->nonzero_chars;
2210 dsi->nonzero_chars = newlen;
2211 dsi->full_string_p = full_string_p;
2212 /* Break the chain, so adjust_related_strinfo on later pointers in
2213 the chain won't adjust this one anymore. */
2214 dsi->next = 0;
2215 dsi->stmt = NULL;
2216 dsi->endptr = NULL_TREE;
2218 else
2220 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2221 set_strinfo (didx, dsi);
2222 find_equal_ptrs (dst, didx);
2224 dsi->writable = true;
2225 dsi->dont_invalidate = true;
2226 if (olddsi != NULL)
2228 tree adj = NULL_TREE;
2229 location_t loc = gimple_location (stmt);
2230 if (oldlen == NULL_TREE)
2232 else if (integer_zerop (oldlen))
2233 adj = newlen;
2234 else if (TREE_CODE (oldlen) == INTEGER_CST
2235 || TREE_CODE (newlen) == INTEGER_CST)
2236 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2237 fold_convert_loc (loc, TREE_TYPE (newlen),
2238 oldlen));
2239 if (adj != NULL_TREE)
2240 adjust_related_strinfos (loc, dsi, adj);
2241 else
2242 dsi->prev = 0;
2244 /* memcpy src may not overlap dst, so src doesn't need to be
2245 invalidated either. */
2246 if (si != NULL)
2247 si->dont_invalidate = true;
2249 if (full_string_p)
2251 lhs = gimple_call_lhs (stmt);
2252 switch (bcode)
2254 case BUILT_IN_MEMCPY:
2255 case BUILT_IN_MEMCPY_CHK:
2256 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2257 laststmt.stmt = stmt;
2258 laststmt.len = dsi->nonzero_chars;
2259 laststmt.stridx = dsi->idx;
2260 if (lhs)
2261 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2262 break;
2263 case BUILT_IN_MEMPCPY:
2264 case BUILT_IN_MEMPCPY_CHK:
2265 break;
2266 default:
2267 gcc_unreachable ();
2272 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2273 If strlen of the second argument is known, strlen of the first argument
2274 is increased by the length of the second argument. Furthermore, attempt
2275 to convert it to memcpy/strcpy if the length of the first argument
2276 is known. */
2278 static void
2279 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2281 int idx, didx;
2282 tree srclen, args, type, fn, objsz, endptr;
2283 bool success;
2284 gimple *stmt = gsi_stmt (*gsi);
2285 strinfo *si, *dsi;
2286 location_t loc = gimple_location (stmt);
2288 tree src = gimple_call_arg (stmt, 1);
2289 tree dst = gimple_call_arg (stmt, 0);
2291 /* Bail if the source is the same as destination. It will be diagnosed
2292 elsewhere. */
2293 if (operand_equal_p (src, dst, 0))
2294 return;
2296 tree lhs = gimple_call_lhs (stmt);
2298 didx = get_stridx (dst);
2299 if (didx < 0)
2300 return;
2302 dsi = NULL;
2303 if (didx > 0)
2304 dsi = get_strinfo (didx);
2306 srclen = NULL_TREE;
2307 si = NULL;
2308 idx = get_stridx (src);
2309 if (idx < 0)
2310 srclen = build_int_cst (size_type_node, ~idx);
2311 else if (idx > 0)
2313 si = get_strinfo (idx);
2314 if (si != NULL)
2315 srclen = get_string_length (si);
2318 /* Set the no-warning bit on the transformed statement? */
2319 bool set_no_warning = false;
2321 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2324 /* The concatenation always involves copying at least one byte
2325 (the terminating nul), even if the source string is empty.
2326 If the source is unknown assume it's one character long and
2327 used that as both sizes. */
2328 tree slen = srclen;
2329 if (slen)
2331 tree type = TREE_TYPE (slen);
2332 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2335 tree sptr = si && si->ptr ? si->ptr : src;
2337 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2338 NULL_TREE, slen))
2340 gimple_set_no_warning (stmt, true);
2341 set_no_warning = true;
2345 /* strcat (p, q) can be transformed into
2346 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2347 with length endptr - p if we need to compute the length
2348 later on. Don't do this transformation if we don't need
2349 it. */
2350 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2352 if (didx == 0)
2354 didx = new_stridx (dst);
2355 if (didx == 0)
2356 return;
2358 if (dsi == NULL)
2360 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2361 set_strinfo (didx, dsi);
2362 find_equal_ptrs (dst, didx);
2364 else
2366 dsi = unshare_strinfo (dsi);
2367 dsi->nonzero_chars = NULL_TREE;
2368 dsi->full_string_p = false;
2369 dsi->next = 0;
2370 dsi->endptr = NULL_TREE;
2372 dsi->writable = true;
2373 dsi->stmt = stmt;
2374 dsi->dont_invalidate = true;
2376 return;
2379 tree dstlen = dsi->nonzero_chars;
2380 endptr = dsi->endptr;
2382 dsi = unshare_strinfo (dsi);
2383 dsi->endptr = NULL_TREE;
2384 dsi->stmt = NULL;
2385 dsi->writable = true;
2387 if (srclen != NULL_TREE)
2389 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2390 TREE_TYPE (dsi->nonzero_chars),
2391 dsi->nonzero_chars, srclen);
2392 gcc_assert (dsi->full_string_p);
2393 adjust_related_strinfos (loc, dsi, srclen);
2394 dsi->dont_invalidate = true;
2396 else
2398 dsi->nonzero_chars = NULL;
2399 dsi->full_string_p = false;
2400 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2401 dsi->dont_invalidate = true;
2404 if (si != NULL)
2405 /* strcat src may not overlap dst, so src doesn't need to be
2406 invalidated either. */
2407 si->dont_invalidate = true;
2409 /* For now. Could remove the lhs from the call and add
2410 lhs = dst; afterwards. */
2411 if (lhs)
2412 return;
2414 fn = NULL_TREE;
2415 objsz = NULL_TREE;
2416 switch (bcode)
2418 case BUILT_IN_STRCAT:
2419 if (srclen != NULL_TREE)
2420 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2421 else
2422 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2423 break;
2424 case BUILT_IN_STRCAT_CHK:
2425 if (srclen != NULL_TREE)
2426 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2427 else
2428 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2429 objsz = gimple_call_arg (stmt, 2);
2430 break;
2431 default:
2432 gcc_unreachable ();
2435 if (fn == NULL_TREE)
2436 return;
2438 if (dsi && dstlen)
2440 tree type = TREE_TYPE (dstlen);
2442 /* Compute the size of the source sequence, including the nul. */
2443 tree srcsize = srclen ? srclen : size_zero_node;
2444 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2446 tree sptr = si && si->ptr ? si->ptr : src;
2448 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2449 dstlen, srcsize))
2451 gimple_set_no_warning (stmt, true);
2452 set_no_warning = true;
2456 tree len = NULL_TREE;
2457 if (srclen != NULL_TREE)
2459 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2460 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2462 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2463 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2464 build_int_cst (type, 1));
2465 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2466 GSI_SAME_STMT);
2468 if (endptr)
2469 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2470 else
2471 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2472 TREE_TYPE (dst), unshare_expr (dst),
2473 fold_convert_loc (loc, sizetype,
2474 unshare_expr (dstlen)));
2475 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2476 GSI_SAME_STMT);
2477 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2479 fprintf (dump_file, "Optimizing: ");
2480 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2482 if (srclen != NULL_TREE)
2483 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2484 dst, src, len, objsz);
2485 else
2486 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2487 dst, src, objsz);
2488 if (success)
2490 stmt = gsi_stmt (*gsi);
2491 update_stmt (stmt);
2492 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2494 fprintf (dump_file, "into: ");
2495 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2497 /* If srclen == NULL, note that current string length can be
2498 computed by transforming this strcpy into stpcpy. */
2499 if (srclen == NULL_TREE && dsi->dont_invalidate)
2500 dsi->stmt = stmt;
2501 adjust_last_stmt (dsi, stmt, true);
2502 if (srclen != NULL_TREE)
2504 laststmt.stmt = stmt;
2505 laststmt.len = srclen;
2506 laststmt.stridx = dsi->idx;
2509 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2510 fprintf (dump_file, "not possible.\n");
2512 if (set_no_warning)
2513 gimple_set_no_warning (stmt, true);
2516 /* Handle a call to malloc or calloc. */
2518 static void
2519 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2521 gimple *stmt = gsi_stmt (*gsi);
2522 tree lhs = gimple_call_lhs (stmt);
2523 if (lhs == NULL_TREE)
2524 return;
2526 gcc_assert (get_stridx (lhs) == 0);
2527 int idx = new_stridx (lhs);
2528 tree length = NULL_TREE;
2529 if (bcode == BUILT_IN_CALLOC)
2530 length = build_int_cst (size_type_node, 0);
2531 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2532 if (bcode == BUILT_IN_CALLOC)
2533 si->endptr = lhs;
2534 set_strinfo (idx, si);
2535 si->writable = true;
2536 si->stmt = stmt;
2537 si->dont_invalidate = true;
2540 /* Handle a call to memset.
2541 After a call to calloc, memset(,0,) is unnecessary.
2542 memset(malloc(n),0,n) is calloc(n,1).
2543 return true when the call is transfomred, false otherwise. */
2545 static bool
2546 handle_builtin_memset (gimple_stmt_iterator *gsi)
2548 gimple *stmt2 = gsi_stmt (*gsi);
2549 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2550 return false;
2551 tree ptr = gimple_call_arg (stmt2, 0);
2552 int idx1 = get_stridx (ptr);
2553 if (idx1 <= 0)
2554 return false;
2555 strinfo *si1 = get_strinfo (idx1);
2556 if (!si1)
2557 return false;
2558 gimple *stmt1 = si1->stmt;
2559 if (!stmt1 || !is_gimple_call (stmt1))
2560 return false;
2561 tree callee1 = gimple_call_fndecl (stmt1);
2562 if (!valid_builtin_call (stmt1))
2563 return false;
2564 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2565 tree size = gimple_call_arg (stmt2, 2);
2566 if (code1 == BUILT_IN_CALLOC)
2567 /* Not touching stmt1 */ ;
2568 else if (code1 == BUILT_IN_MALLOC
2569 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2571 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2572 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2573 size, build_one_cst (size_type_node));
2574 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2575 si1->full_string_p = true;
2576 si1->stmt = gsi_stmt (gsi1);
2578 else
2579 return false;
2580 tree lhs = gimple_call_lhs (stmt2);
2581 unlink_stmt_vdef (stmt2);
2582 if (lhs)
2584 gimple *assign = gimple_build_assign (lhs, ptr);
2585 gsi_replace (gsi, assign, false);
2587 else
2589 gsi_remove (gsi, true);
2590 release_defs (stmt2);
2593 return true;
2596 /* Handle a call to memcmp. We try to handle small comparisons by
2597 converting them to load and compare, and replacing the call to memcmp
2598 with a __builtin_memcmp_eq call where possible.
2599 return true when call is transformed, return false otherwise. */
2601 static bool
2602 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2604 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2605 tree res = gimple_call_lhs (stmt2);
2606 tree arg1 = gimple_call_arg (stmt2, 0);
2607 tree arg2 = gimple_call_arg (stmt2, 1);
2608 tree len = gimple_call_arg (stmt2, 2);
2609 unsigned HOST_WIDE_INT leni;
2610 use_operand_p use_p;
2611 imm_use_iterator iter;
2613 if (!res)
2614 return false;
2616 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2618 gimple *ustmt = USE_STMT (use_p);
2620 if (is_gimple_debug (ustmt))
2621 continue;
2622 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2624 gassign *asgn = as_a <gassign *> (ustmt);
2625 tree_code code = gimple_assign_rhs_code (asgn);
2626 if ((code != EQ_EXPR && code != NE_EXPR)
2627 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2628 return false;
2630 else if (gimple_code (ustmt) == GIMPLE_COND)
2632 tree_code code = gimple_cond_code (ustmt);
2633 if ((code != EQ_EXPR && code != NE_EXPR)
2634 || !integer_zerop (gimple_cond_rhs (ustmt)))
2635 return false;
2637 else
2638 return false;
2641 if (tree_fits_uhwi_p (len)
2642 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2643 && pow2p_hwi (leni))
2645 leni *= CHAR_TYPE_SIZE;
2646 unsigned align1 = get_pointer_alignment (arg1);
2647 unsigned align2 = get_pointer_alignment (arg2);
2648 unsigned align = MIN (align1, align2);
2649 scalar_int_mode mode;
2650 if (int_mode_for_size (leni, 1).exists (&mode)
2651 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2653 location_t loc = gimple_location (stmt2);
2654 tree type, off;
2655 type = build_nonstandard_integer_type (leni, 1);
2656 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
2657 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2658 ptr_mode, true);
2659 off = build_int_cst (ptrtype, 0);
2660 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2661 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2662 tree tem1 = fold_const_aggregate_ref (arg1);
2663 if (tem1)
2664 arg1 = tem1;
2665 tree tem2 = fold_const_aggregate_ref (arg2);
2666 if (tem2)
2667 arg2 = tem2;
2668 res = fold_convert_loc (loc, TREE_TYPE (res),
2669 fold_build2_loc (loc, NE_EXPR,
2670 boolean_type_node,
2671 arg1, arg2));
2672 gimplify_and_update_call_from_tree (gsi, res);
2673 return true;
2677 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2678 return true;
2681 /* Given an index to the strinfo vector, compute the string length for the
2682 corresponding string. Return -1 when unknown. */
2684 static HOST_WIDE_INT
2685 compute_string_length (int idx)
2687 HOST_WIDE_INT string_leni = -1;
2688 gcc_assert (idx != 0);
2690 if (idx < 0)
2691 return ~idx;
2693 strinfo *si = get_strinfo (idx);
2694 if (si)
2696 tree const_string_len = get_string_length (si);
2697 if (const_string_len && tree_fits_shwi_p (const_string_len))
2698 string_leni = tree_to_shwi (const_string_len);
2701 if (string_leni < 0)
2702 return -1;
2704 return string_leni;
2707 /* Determine the minimum size of the object referenced by DEST expression which
2708 must have a pointer type.
2709 Return the minimum size of the object if successful or NULL when the size
2710 cannot be determined. */
2711 static tree
2712 determine_min_objsize (tree dest)
2714 unsigned HOST_WIDE_INT size = 0;
2716 if (compute_builtin_object_size (dest, 2, &size))
2717 return build_int_cst (sizetype, size);
2719 /* Try to determine the size of the object through the RHS of the
2720 assign statement. */
2721 if (TREE_CODE (dest) == SSA_NAME)
2723 gimple *stmt = SSA_NAME_DEF_STMT (dest);
2724 if (!is_gimple_assign (stmt))
2725 return NULL_TREE;
2727 if (!gimple_assign_single_p (stmt)
2728 && !gimple_assign_unary_nop_p (stmt))
2729 return NULL_TREE;
2731 dest = gimple_assign_rhs1 (stmt);
2732 return determine_min_objsize (dest);
2735 /* Try to determine the size of the object from its type. */
2736 if (TREE_CODE (dest) != ADDR_EXPR)
2737 return NULL_TREE;
2739 tree type = TREE_TYPE (dest);
2740 if (TREE_CODE (type) == POINTER_TYPE)
2741 type = TREE_TYPE (type);
2743 type = TYPE_MAIN_VARIANT (type);
2745 /* We cannot determine the size of the array if it's a flexible array,
2746 which is declared at the end of a structure. */
2747 if (TREE_CODE (type) == ARRAY_TYPE
2748 && !array_at_struct_end_p (dest))
2750 tree size_t = TYPE_SIZE_UNIT (type);
2751 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2752 && !integer_zerop (size_t))
2753 return size_t;
2756 return NULL_TREE;
2759 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2760 equality test against zero:
2762 A. When the lengths of both arguments are constant and it's a strcmp:
2763 * if the lengths are NOT equal, we can safely fold the call
2764 to a non-zero value.
2765 * otherwise, do nothing now.
2767 B. When the length of one argument is constant, try to replace the call with
2768 a __builtin_str(n)cmp_eq call where possible, i.e:
2770 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2771 string with constant length , C is a constant.
2772 if (C <= strlen(STR) && sizeof_array(s) > C)
2774 replace this call with
2775 strncmp_eq (s, STR, C) (!)= 0
2777 if (C > strlen(STR)
2779 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2780 can handled by the following strcmp.
2783 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2784 string with constant length.
2785 if (sizeof_array(s) > strlen(STR))
2787 replace this call with
2788 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2791 Return true when the call is transformed, return false otherwise.
2794 static bool
2795 handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
2797 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
2798 tree res = gimple_call_lhs (stmt);
2799 use_operand_p use_p;
2800 imm_use_iterator iter;
2801 tree arg1 = gimple_call_arg (stmt, 0);
2802 tree arg2 = gimple_call_arg (stmt, 1);
2803 int idx1 = get_stridx (arg1);
2804 int idx2 = get_stridx (arg2);
2805 HOST_WIDE_INT length = -1;
2806 bool is_ncmp = false;
2808 if (!res)
2809 return false;
2811 /* When both arguments are unknown, do nothing. */
2812 if (idx1 == 0 && idx2 == 0)
2813 return false;
2815 /* Handle strncmp function. */
2816 if (gimple_call_num_args (stmt) == 3)
2818 tree len = gimple_call_arg (stmt, 2);
2819 if (tree_fits_shwi_p (len))
2820 length = tree_to_shwi (len);
2822 is_ncmp = true;
2825 /* For strncmp, if the length argument is NOT known, do nothing. */
2826 if (is_ncmp && length < 0)
2827 return false;
2829 /* When the result is ONLY used to do equality test against zero. */
2830 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2832 gimple *use_stmt = USE_STMT (use_p);
2834 if (is_gimple_debug (use_stmt))
2835 continue;
2836 if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
2838 tree_code code = gimple_assign_rhs_code (use_stmt);
2839 if (code == COND_EXPR)
2841 tree cond_expr = gimple_assign_rhs1 (use_stmt);
2842 if ((TREE_CODE (cond_expr) != EQ_EXPR
2843 && (TREE_CODE (cond_expr) != NE_EXPR))
2844 || !integer_zerop (TREE_OPERAND (cond_expr, 1)))
2845 return false;
2847 else if (code == EQ_EXPR || code == NE_EXPR)
2849 if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
2850 return false;
2852 else
2853 return false;
2855 else if (gimple_code (use_stmt) == GIMPLE_COND)
2857 tree_code code = gimple_cond_code (use_stmt);
2858 if ((code != EQ_EXPR && code != NE_EXPR)
2859 || !integer_zerop (gimple_cond_rhs (use_stmt)))
2860 return false;
2862 else
2863 return false;
2866 /* When the lengths of both arguments are known, and they are unequal, we can
2867 safely fold the call to a non-zero value for strcmp;
2868 othewise, do nothing now. */
2869 if (idx1 != 0 && idx2 != 0)
2871 HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
2872 HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
2874 if (!is_ncmp
2875 && const_string_leni1 != -1
2876 && const_string_leni2 != -1
2877 && const_string_leni1 != const_string_leni2)
2879 replace_call_with_value (gsi, integer_one_node);
2880 return true;
2882 return false;
2885 /* When the length of one argument is constant. */
2886 tree var_string = NULL_TREE;
2887 HOST_WIDE_INT const_string_leni = -1;
2889 if (idx1)
2891 const_string_leni = compute_string_length (idx1);
2892 var_string = arg2;
2894 else
2896 gcc_checking_assert (idx2);
2897 const_string_leni = compute_string_length (idx2);
2898 var_string = arg1;
2901 if (const_string_leni < 0)
2902 return false;
2904 unsigned HOST_WIDE_INT var_sizei = 0;
2905 /* try to determine the minimum size of the object pointed by var_string. */
2906 tree size = determine_min_objsize (var_string);
2908 if (!size)
2909 return false;
2911 if (tree_fits_uhwi_p (size))
2912 var_sizei = tree_to_uhwi (size);
2914 if (var_sizei == 0)
2915 return false;
2917 /* For strncmp, if length > const_string_leni , this call can be safely
2918 transformed to a strcmp. */
2919 if (is_ncmp && length > const_string_leni)
2920 is_ncmp = false;
2922 unsigned HOST_WIDE_INT final_length
2923 = is_ncmp ? length : const_string_leni + 1;
2925 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
2926 if (var_sizei > final_length)
2928 tree fn
2929 = (is_ncmp
2930 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
2931 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
2932 if (!fn)
2933 return false;
2934 tree const_string_len = build_int_cst (size_type_node, final_length);
2935 update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
2937 else
2938 return false;
2940 return true;
2943 /* Handle a POINTER_PLUS_EXPR statement.
2944 For p = "abcd" + 2; compute associated length, or if
2945 p = q + off is pointing to a '\0' character of a string, call
2946 zero_length_string on it. */
2948 static void
2949 handle_pointer_plus (gimple_stmt_iterator *gsi)
2951 gimple *stmt = gsi_stmt (*gsi);
2952 tree lhs = gimple_assign_lhs (stmt), off;
2953 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2954 strinfo *si, *zsi;
2956 if (idx == 0)
2957 return;
2959 if (idx < 0)
2961 tree off = gimple_assign_rhs2 (stmt);
2962 if (tree_fits_uhwi_p (off)
2963 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2964 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2965 = ~(~idx - (int) tree_to_uhwi (off));
2966 return;
2969 si = get_strinfo (idx);
2970 if (si == NULL || si->nonzero_chars == NULL_TREE)
2971 return;
2973 off = gimple_assign_rhs2 (stmt);
2974 zsi = NULL;
2975 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2976 zsi = zero_length_string (lhs, si);
2977 else if (TREE_CODE (off) == SSA_NAME)
2979 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2980 if (gimple_assign_single_p (def_stmt)
2981 && si->full_string_p
2982 && operand_equal_p (si->nonzero_chars,
2983 gimple_assign_rhs1 (def_stmt), 0))
2984 zsi = zero_length_string (lhs, si);
2986 if (zsi != NULL
2987 && si->endptr != NULL_TREE
2988 && si->endptr != lhs
2989 && TREE_CODE (si->endptr) == SSA_NAME)
2991 enum tree_code rhs_code
2992 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2993 ? SSA_NAME : NOP_EXPR;
2994 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2995 gcc_assert (gsi_stmt (*gsi) == stmt);
2996 update_stmt (stmt);
3000 /* If RHS, either directly or indirectly, refers to a string of constant
3001 length, return it. Otherwise return a negative value. */
3003 static HOST_WIDE_INT
3004 get_string_cst_length (tree rhs)
3006 if (TREE_CODE (rhs) == MEM_REF
3007 && integer_zerop (TREE_OPERAND (rhs, 1)))
3009 rhs = TREE_OPERAND (rhs, 0);
3010 if (TREE_CODE (rhs) == ADDR_EXPR)
3012 tree rhs_addr = rhs;
3014 rhs = TREE_OPERAND (rhs, 0);
3015 if (TREE_CODE (rhs) != STRING_CST)
3017 int idx = get_stridx (rhs_addr);
3018 if (idx > 0)
3020 strinfo *si = get_strinfo (idx);
3021 if (si
3022 && si->full_string_p
3023 && tree_fits_shwi_p (si->nonzero_chars))
3024 return tree_to_shwi (si->nonzero_chars);
3030 if (TREE_CODE (rhs) == VAR_DECL
3031 && TREE_READONLY (rhs))
3032 rhs = DECL_INITIAL (rhs);
3034 if (rhs && TREE_CODE (rhs) == STRING_CST)
3035 return strlen (TREE_STRING_POINTER (rhs));
3037 return -1;
3040 /* Handle a single character store. */
3042 static bool
3043 handle_char_store (gimple_stmt_iterator *gsi)
3045 int idx = -1;
3046 strinfo *si = NULL;
3047 gimple *stmt = gsi_stmt (*gsi);
3048 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
3049 tree rhs = gimple_assign_rhs1 (stmt);
3050 unsigned HOST_WIDE_INT offset = 0;
3052 if (TREE_CODE (lhs) == MEM_REF
3053 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
3055 tree mem_offset = TREE_OPERAND (lhs, 1);
3056 if (tree_fits_uhwi_p (mem_offset))
3058 /* Get the strinfo for the base, and use it if it starts with at
3059 least OFFSET nonzero characters. This is trivially true if
3060 OFFSET is zero. */
3061 offset = tree_to_uhwi (mem_offset);
3062 idx = get_stridx (TREE_OPERAND (lhs, 0));
3063 if (idx > 0)
3064 si = get_strinfo (idx);
3065 if (offset == 0)
3066 ssaname = TREE_OPERAND (lhs, 0);
3067 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
3068 return true;
3071 else
3073 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
3074 if (idx > 0)
3075 si = get_strinfo (idx);
3078 bool storing_zero_p = initializer_zerop (rhs);
3079 bool storing_nonzero_p = !storing_zero_p && tree_expr_nonzero_p (rhs);
3080 /* Set to the length of the string being assigned if known. */
3081 HOST_WIDE_INT rhslen;
3083 if (si != NULL)
3085 int cmp = compare_nonzero_chars (si, offset);
3086 gcc_assert (offset == 0 || cmp >= 0);
3087 if (storing_zero_p && cmp == 0 && si->full_string_p)
3089 /* When overwriting a '\0' with a '\0', the store can be removed
3090 if we know it has been stored in the current function. */
3091 if (!stmt_could_throw_p (stmt) && si->writable)
3093 unlink_stmt_vdef (stmt);
3094 release_defs (stmt);
3095 gsi_remove (gsi, true);
3096 return false;
3098 else
3100 si->writable = true;
3101 gsi_next (gsi);
3102 return false;
3105 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3106 and if we aren't storing '\0', we know that the length of the
3107 string and any other zero terminated string in memory remains
3108 the same. In that case we move to the next gimple statement and
3109 return to signal the caller that it shouldn't invalidate anything.
3111 This is benefical for cases like:
3113 char p[20];
3114 void foo (char *q)
3116 strcpy (p, "foobar");
3117 size_t len = strlen (p); // This can be optimized into 6
3118 size_t len2 = strlen (q); // This has to be computed
3119 p[0] = 'X';
3120 size_t len3 = strlen (p); // This can be optimized into 6
3121 size_t len4 = strlen (q); // This can be optimized into len2
3122 bar (len, len2, len3, len4);
3125 else if (storing_nonzero_p && cmp > 0)
3127 gsi_next (gsi);
3128 return false;
3130 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
3132 /* When storing_nonzero_p, we know that the string now starts
3133 with OFFSET + 1 nonzero characters, but don't know whether
3134 there's a following nul terminator.
3136 When storing_zero_p, we know that the string is now OFFSET
3137 characters long.
3139 Otherwise, we're storing an unknown value at offset OFFSET,
3140 so need to clip the nonzero_chars to OFFSET. */
3141 location_t loc = gimple_location (stmt);
3142 tree oldlen = si->nonzero_chars;
3143 if (cmp == 0 && si->full_string_p)
3144 /* We're overwriting the nul terminator with a nonzero or
3145 unknown character. If the previous stmt was a memcpy,
3146 its length may be decreased. */
3147 adjust_last_stmt (si, stmt, false);
3148 si = unshare_strinfo (si);
3149 if (storing_nonzero_p)
3150 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
3151 else
3152 si->nonzero_chars = build_int_cst (size_type_node, offset);
3153 si->full_string_p = storing_zero_p;
3154 if (storing_zero_p
3155 && ssaname
3156 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3157 si->endptr = ssaname;
3158 else
3159 si->endptr = NULL;
3160 si->next = 0;
3161 si->stmt = NULL;
3162 si->writable = true;
3163 si->dont_invalidate = true;
3164 if (oldlen)
3166 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
3167 si->nonzero_chars, oldlen);
3168 adjust_related_strinfos (loc, si, adj);
3170 else
3171 si->prev = 0;
3174 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
3176 if (ssaname)
3177 idx = new_stridx (ssaname);
3178 else
3179 idx = new_addr_stridx (lhs);
3180 if (idx != 0)
3182 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
3183 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
3184 si = new_strinfo (ptr, idx, len, storing_zero_p);
3185 set_strinfo (idx, si);
3186 if (storing_zero_p
3187 && ssaname
3188 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3189 si->endptr = ssaname;
3190 si->dont_invalidate = true;
3191 si->writable = true;
3194 else if (idx == 0
3195 && (rhslen = get_string_cst_length (gimple_assign_rhs1 (stmt))) >= 0
3196 && ssaname == NULL_TREE
3197 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
3199 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
3200 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
3202 int idx = new_addr_stridx (lhs);
3203 if (idx != 0)
3205 si = new_strinfo (build_fold_addr_expr (lhs), idx,
3206 build_int_cst (size_type_node, rhslen), true);
3207 set_strinfo (idx, si);
3208 si->dont_invalidate = true;
3213 if (si != NULL && offset == 0 && storing_zero_p)
3215 /* Allow adjust_last_stmt to remove it if the stored '\0'
3216 is immediately overwritten. */
3217 laststmt.stmt = stmt;
3218 laststmt.len = build_int_cst (size_type_node, 1);
3219 laststmt.stridx = si->idx;
3221 return true;
3224 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3226 static void
3227 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3229 if (TREE_CODE (rhs1) != SSA_NAME
3230 || TREE_CODE (rhs2) != SSA_NAME)
3231 return;
3233 gimple *call_stmt = NULL;
3234 for (int pass = 0; pass < 2; pass++)
3236 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3237 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3238 && has_single_use (rhs1)
3239 && gimple_call_arg (g, 0) == rhs2)
3241 call_stmt = g;
3242 break;
3244 std::swap (rhs1, rhs2);
3247 if (call_stmt)
3249 tree arg0 = gimple_call_arg (call_stmt, 0);
3251 if (arg0 == rhs2)
3253 tree arg1 = gimple_call_arg (call_stmt, 1);
3254 tree arg1_len = NULL_TREE;
3255 int idx = get_stridx (arg1);
3257 if (idx)
3259 if (idx < 0)
3260 arg1_len = build_int_cst (size_type_node, ~idx);
3261 else
3263 strinfo *si = get_strinfo (idx);
3264 if (si)
3265 arg1_len = get_string_length (si);
3269 if (arg1_len != NULL_TREE)
3271 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3272 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3274 if (!is_gimple_val (arg1_len))
3276 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3277 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3278 arg1_len);
3279 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3280 arg1_len = arg1_len_tmp;
3283 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3284 arg0, arg1, arg1_len);
3285 tree strncmp_lhs = make_ssa_name (integer_type_node);
3286 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3287 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3288 gsi_remove (&gsi, true);
3289 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3290 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3292 if (is_gimple_assign (stmt))
3294 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3296 tree cond = gimple_assign_rhs1 (stmt);
3297 TREE_OPERAND (cond, 0) = strncmp_lhs;
3298 TREE_OPERAND (cond, 1) = zero;
3300 else
3302 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3303 gimple_assign_set_rhs2 (stmt, zero);
3306 else
3308 gcond *cond = as_a<gcond *> (stmt);
3309 gimple_cond_set_lhs (cond, strncmp_lhs);
3310 gimple_cond_set_rhs (cond, zero);
3312 update_stmt (stmt);
3318 /* Attempt to check for validity of the performed access a single statement
3319 at *GSI using string length knowledge, and to optimize it.
3320 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3321 true. */
3323 static bool
3324 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
3326 gimple *stmt = gsi_stmt (*gsi);
3328 if (is_gimple_call (stmt))
3330 tree callee = gimple_call_fndecl (stmt);
3331 if (valid_builtin_call (stmt))
3332 switch (DECL_FUNCTION_CODE (callee))
3334 case BUILT_IN_STRLEN:
3335 handle_builtin_strlen (gsi);
3336 break;
3337 case BUILT_IN_STRCHR:
3338 handle_builtin_strchr (gsi);
3339 break;
3340 case BUILT_IN_STRCPY:
3341 case BUILT_IN_STRCPY_CHK:
3342 case BUILT_IN_STPCPY:
3343 case BUILT_IN_STPCPY_CHK:
3344 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3345 break;
3347 case BUILT_IN_STRNCAT:
3348 case BUILT_IN_STRNCAT_CHK:
3349 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3350 break;
3352 case BUILT_IN_STPNCPY:
3353 case BUILT_IN_STPNCPY_CHK:
3354 case BUILT_IN_STRNCPY:
3355 case BUILT_IN_STRNCPY_CHK:
3356 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3357 break;
3359 case BUILT_IN_MEMCPY:
3360 case BUILT_IN_MEMCPY_CHK:
3361 case BUILT_IN_MEMPCPY:
3362 case BUILT_IN_MEMPCPY_CHK:
3363 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3364 break;
3365 case BUILT_IN_STRCAT:
3366 case BUILT_IN_STRCAT_CHK:
3367 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3368 break;
3369 case BUILT_IN_MALLOC:
3370 case BUILT_IN_CALLOC:
3371 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3372 break;
3373 case BUILT_IN_MEMSET:
3374 if (handle_builtin_memset (gsi))
3375 return false;
3376 break;
3377 case BUILT_IN_MEMCMP:
3378 if (handle_builtin_memcmp (gsi))
3379 return false;
3380 break;
3381 case BUILT_IN_STRCMP:
3382 case BUILT_IN_STRNCMP:
3383 if (handle_builtin_string_cmp (gsi))
3384 return false;
3385 break;
3386 default:
3387 break;
3390 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3392 tree lhs = gimple_assign_lhs (stmt);
3394 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3396 if (gimple_assign_single_p (stmt)
3397 || (gimple_assign_cast_p (stmt)
3398 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3400 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3401 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3403 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3404 handle_pointer_plus (gsi);
3406 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3408 enum tree_code code = gimple_assign_rhs_code (stmt);
3409 if (code == COND_EXPR)
3411 tree cond = gimple_assign_rhs1 (stmt);
3412 enum tree_code cond_code = TREE_CODE (cond);
3414 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3415 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3416 TREE_OPERAND (cond, 1), stmt);
3418 else if (code == EQ_EXPR || code == NE_EXPR)
3419 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3420 gimple_assign_rhs2 (stmt), stmt);
3421 else if (gimple_assign_load_p (stmt)
3422 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3423 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3424 && (TYPE_PRECISION (TREE_TYPE (lhs))
3425 == TYPE_PRECISION (char_type_node))
3426 && !gimple_has_volatile_ops (stmt))
3428 tree off = integer_zero_node;
3429 unsigned HOST_WIDE_INT coff = 0;
3430 int idx = 0;
3431 tree rhs1 = gimple_assign_rhs1 (stmt);
3432 if (code == MEM_REF)
3434 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3435 if (idx > 0)
3437 strinfo *si = get_strinfo (idx);
3438 if (si
3439 && si->nonzero_chars
3440 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3441 && (wi::to_widest (si->nonzero_chars)
3442 >= wi::to_widest (off)))
3443 off = TREE_OPERAND (rhs1, 1);
3444 else
3445 /* This case is not useful. See if get_addr_stridx
3446 returns something usable. */
3447 idx = 0;
3450 if (idx <= 0)
3451 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3452 if (idx > 0)
3454 strinfo *si = get_strinfo (idx);
3455 if (si
3456 && si->nonzero_chars
3457 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3459 widest_int w1 = wi::to_widest (si->nonzero_chars);
3460 widest_int w2 = wi::to_widest (off) + coff;
3461 if (w1 == w2
3462 && si->full_string_p)
3464 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3466 fprintf (dump_file, "Optimizing: ");
3467 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3470 /* Reading the final '\0' character. */
3471 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3472 gimple_set_vuse (stmt, NULL_TREE);
3473 gimple_assign_set_rhs_from_tree (gsi, zero);
3474 *cleanup_eh
3475 |= maybe_clean_or_replace_eh_stmt (stmt,
3476 gsi_stmt (*gsi));
3477 stmt = gsi_stmt (*gsi);
3478 update_stmt (stmt);
3480 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3482 fprintf (dump_file, "into: ");
3483 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3486 else if (w1 > w2)
3488 /* Reading a character before the final '\0'
3489 character. Just set the value range to ~[0, 0]
3490 if we don't have anything better. */
3491 wide_int min, max;
3492 tree type = TREE_TYPE (lhs);
3493 enum value_range_type vr
3494 = get_range_info (lhs, &min, &max);
3495 if (vr == VR_VARYING
3496 || (vr == VR_RANGE
3497 && min == wi::min_value (TYPE_PRECISION (type),
3498 TYPE_SIGN (type))
3499 && max == wi::max_value (TYPE_PRECISION (type),
3500 TYPE_SIGN (type))))
3501 set_range_info (lhs, VR_ANTI_RANGE,
3502 wi::zero (TYPE_PRECISION (type)),
3503 wi::zero (TYPE_PRECISION (type)));
3509 if (strlen_to_stridx)
3511 tree rhs1 = gimple_assign_rhs1 (stmt);
3512 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3513 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3516 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3518 tree type = TREE_TYPE (lhs);
3519 if (TREE_CODE (type) == ARRAY_TYPE)
3520 type = TREE_TYPE (type);
3521 if (TREE_CODE (type) == INTEGER_TYPE
3522 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3523 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3525 if (! handle_char_store (gsi))
3526 return false;
3530 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3532 enum tree_code code = gimple_cond_code (cond);
3533 if (code == EQ_EXPR || code == NE_EXPR)
3534 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3535 gimple_cond_rhs (stmt), stmt);
3538 if (gimple_vdef (stmt))
3539 maybe_invalidate (stmt);
3540 return true;
3543 /* Recursively call maybe_invalidate on stmts that might be executed
3544 in between dombb and current bb and that contain a vdef. Stop when
3545 *count stmts are inspected, or if the whole strinfo vector has
3546 been invalidated. */
3548 static void
3549 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3551 unsigned int i, n = gimple_phi_num_args (phi);
3553 for (i = 0; i < n; i++)
3555 tree vuse = gimple_phi_arg_def (phi, i);
3556 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3557 basic_block bb = gimple_bb (stmt);
3558 if (bb == NULL
3559 || bb == dombb
3560 || !bitmap_set_bit (visited, bb->index)
3561 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3562 continue;
3563 while (1)
3565 if (gimple_code (stmt) == GIMPLE_PHI)
3567 do_invalidate (dombb, stmt, visited, count);
3568 if (*count == 0)
3569 return;
3570 break;
3572 if (--*count == 0)
3573 return;
3574 if (!maybe_invalidate (stmt))
3576 *count = 0;
3577 return;
3579 vuse = gimple_vuse (stmt);
3580 stmt = SSA_NAME_DEF_STMT (vuse);
3581 if (gimple_bb (stmt) != bb)
3583 bb = gimple_bb (stmt);
3584 if (bb == NULL
3585 || bb == dombb
3586 || !bitmap_set_bit (visited, bb->index)
3587 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3588 break;
3594 class strlen_dom_walker : public dom_walker
3596 public:
3597 strlen_dom_walker (cdi_direction direction)
3598 : dom_walker (direction), m_cleanup_cfg (false)
3601 virtual edge before_dom_children (basic_block);
3602 virtual void after_dom_children (basic_block);
3604 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3605 execute function. */
3606 bool m_cleanup_cfg;
3609 /* Callback for walk_dominator_tree. Attempt to optimize various
3610 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3612 edge
3613 strlen_dom_walker::before_dom_children (basic_block bb)
3615 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3617 if (dombb == NULL)
3618 stridx_to_strinfo = NULL;
3619 else
3621 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3622 if (stridx_to_strinfo)
3624 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3625 gsi_next (&gsi))
3627 gphi *phi = gsi.phi ();
3628 if (virtual_operand_p (gimple_phi_result (phi)))
3630 bitmap visited = BITMAP_ALLOC (NULL);
3631 int count_vdef = 100;
3632 do_invalidate (dombb, phi, visited, &count_vdef);
3633 BITMAP_FREE (visited);
3634 if (count_vdef == 0)
3636 /* If there were too many vdefs in between immediate
3637 dominator and current bb, invalidate everything.
3638 If stridx_to_strinfo has been unshared, we need
3639 to free it, otherwise just set it to NULL. */
3640 if (!strinfo_shared ())
3642 unsigned int i;
3643 strinfo *si;
3645 for (i = 1;
3646 vec_safe_iterate (stridx_to_strinfo, i, &si);
3647 ++i)
3649 free_strinfo (si);
3650 (*stridx_to_strinfo)[i] = NULL;
3653 else
3654 stridx_to_strinfo = NULL;
3656 break;
3662 /* If all PHI arguments have the same string index, the PHI result
3663 has it as well. */
3664 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3665 gsi_next (&gsi))
3667 gphi *phi = gsi.phi ();
3668 tree result = gimple_phi_result (phi);
3669 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3671 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3672 if (idx != 0)
3674 unsigned int i, n = gimple_phi_num_args (phi);
3675 for (i = 1; i < n; i++)
3676 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3677 break;
3678 if (i == n)
3679 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3684 bool cleanup_eh = false;
3686 /* Attempt to optimize individual statements. */
3687 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3688 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
3689 gsi_next (&gsi);
3691 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
3692 m_cleanup_cfg = true;
3694 bb->aux = stridx_to_strinfo;
3695 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3696 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3697 return NULL;
3700 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3701 owned by the current bb, clear bb->aux. */
3703 void
3704 strlen_dom_walker::after_dom_children (basic_block bb)
3706 if (bb->aux)
3708 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3709 if (vec_safe_length (stridx_to_strinfo)
3710 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3712 unsigned int i;
3713 strinfo *si;
3715 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3716 free_strinfo (si);
3717 vec_free (stridx_to_strinfo);
3719 bb->aux = NULL;
3723 /* Main entry point. */
3725 namespace {
3727 const pass_data pass_data_strlen =
3729 GIMPLE_PASS, /* type */
3730 "strlen", /* name */
3731 OPTGROUP_NONE, /* optinfo_flags */
3732 TV_TREE_STRLEN, /* tv_id */
3733 ( PROP_cfg | PROP_ssa ), /* properties_required */
3734 0, /* properties_provided */
3735 0, /* properties_destroyed */
3736 0, /* todo_flags_start */
3737 0, /* todo_flags_finish */
3740 class pass_strlen : public gimple_opt_pass
3742 public:
3743 pass_strlen (gcc::context *ctxt)
3744 : gimple_opt_pass (pass_data_strlen, ctxt)
3747 /* opt_pass methods: */
3748 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3749 virtual unsigned int execute (function *);
3751 }; // class pass_strlen
3753 unsigned int
3754 pass_strlen::execute (function *fun)
3756 gcc_assert (!strlen_to_stridx);
3757 if (warn_stringop_overflow || warn_stringop_truncation)
3758 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3760 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3761 max_stridx = 1;
3763 calculate_dominance_info (CDI_DOMINATORS);
3765 /* String length optimization is implemented as a walk of the dominator
3766 tree and a forward walk of statements within each block. */
3767 strlen_dom_walker walker (CDI_DOMINATORS);
3768 walker.walk (fun->cfg->x_entry_block_ptr);
3770 ssa_ver_to_stridx.release ();
3771 strinfo_pool.release ();
3772 if (decl_to_stridxlist_htab)
3774 obstack_free (&stridx_obstack, NULL);
3775 delete decl_to_stridxlist_htab;
3776 decl_to_stridxlist_htab = NULL;
3778 laststmt.stmt = NULL;
3779 laststmt.len = NULL_TREE;
3780 laststmt.stridx = 0;
3782 if (strlen_to_stridx)
3784 strlen_to_stridx->empty ();
3785 delete strlen_to_stridx;
3786 strlen_to_stridx = NULL;
3789 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
3792 } // anon namespace
3794 gimple_opt_pass *
3795 make_pass_strlen (gcc::context *ctxt)
3797 return new pass_strlen (ctxt);