PR middle-end/85602 - -Wsizeof-pointer-memaccess for strncat with size of source
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob92545b9ce4d03af5d3fbe296b38b587048476291
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() or strnlen() argument
1128 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1129 a character array A[N] with unknown length bounded by N, and for
1130 strnlen(), by min (N, BOUND). */
1132 static tree
1133 maybe_set_strlen_range (tree lhs, tree src, tree bound)
1135 if (TREE_CODE (lhs) != SSA_NAME
1136 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
1137 return NULL_TREE;
1139 if (TREE_CODE (src) == SSA_NAME)
1141 gimple *def = SSA_NAME_DEF_STMT (src);
1142 if (is_gimple_assign (def)
1143 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1144 src = gimple_assign_rhs1 (def);
1147 wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1148 wide_int min = wi::zero (max.get_precision ());
1150 if (TREE_CODE (src) == ADDR_EXPR)
1152 /* The last array member of a struct can be bigger than its size
1153 suggests if it's treated as a poor-man's flexible array member. */
1154 src = TREE_OPERAND (src, 0);
1155 bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE;
1156 if (src_is_array && !array_at_struct_end_p (src))
1158 tree type = TREE_TYPE (src);
1159 if (tree dom = TYPE_DOMAIN (type))
1161 tree maxval = TYPE_MAX_VALUE (dom);
1162 if (maxval)
1163 max = wi::to_wide (maxval);
1164 else
1165 max = wi::zero (min.get_precision ());
1167 /* For strlen() the upper bound above is equal to
1168 the longest string that can be stored in the array
1169 (i.e., it accounts for the terminating nul. For
1170 strnlen() bump up the maximum by one since the array
1171 need not be nul-terminated. */
1172 if (bound)
1173 ++max;
1176 else
1178 if (TREE_CODE (src) == COMPONENT_REF && !src_is_array)
1179 src = TREE_OPERAND (src, 1);
1180 if (DECL_P (src))
1182 /* Handle the unlikely case of strlen (&c) where c is some
1183 variable. */
1184 if (tree size = DECL_SIZE_UNIT (src))
1185 if (TREE_CODE (size) == INTEGER_CST)
1186 max = wi::to_wide (size);
1191 if (bound)
1193 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1194 is less than the size of the array set MAX to it. It it's
1195 greater than MAX and MAX is non-zero bump MAX down to account
1196 for the necessary terminating nul. Otherwise leave it alone. */
1197 if (TREE_CODE (bound) == INTEGER_CST)
1199 wide_int wibnd = wi::to_wide (bound);
1200 int cmp = wi::cmpu (wibnd, max);
1201 if (cmp < 0)
1202 max = wibnd;
1203 else if (cmp && wi::ne_p (max, min))
1204 --max;
1206 else if (TREE_CODE (bound) == SSA_NAME)
1208 wide_int minbound, maxbound;
1209 value_range_type rng = get_range_info (bound, &minbound, &maxbound);
1210 if (rng == VR_RANGE)
1212 /* For a bound in a known range, adjust the range determined
1213 above as necessary. For a bound in some anti-range or
1214 in an unknown range, use the range determined above. */
1215 if (wi::ltu_p (minbound, min))
1216 min = minbound;
1217 if (wi::ltu_p (maxbound, max))
1218 max = maxbound;
1223 if (min == max)
1224 return wide_int_to_tree (size_type_node, min);
1226 set_range_info (lhs, VR_RANGE, min, max);
1227 return lhs;
1230 /* Handle a strlen call. If strlen of the argument is known, replace
1231 the strlen call with the known value, otherwise remember that strlen
1232 of the argument is stored in the lhs SSA_NAME. */
1234 static void
1235 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1237 gimple *stmt = gsi_stmt (*gsi);
1238 tree lhs = gimple_call_lhs (stmt);
1240 if (lhs == NULL_TREE)
1241 return;
1243 location_t loc = gimple_location (stmt);
1244 tree callee = gimple_call_fndecl (stmt);
1245 tree src = gimple_call_arg (stmt, 0);
1246 tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
1247 ? gimple_call_arg (stmt, 1) : NULL_TREE);
1248 int idx = get_stridx (src);
1249 if (idx)
1251 strinfo *si = NULL;
1252 tree rhs;
1254 if (idx < 0)
1255 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1256 else
1258 rhs = NULL_TREE;
1259 si = get_strinfo (idx);
1260 if (si != NULL)
1261 rhs = get_string_length (si);
1263 if (rhs != NULL_TREE)
1265 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1267 fprintf (dump_file, "Optimizing: ");
1268 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1270 rhs = unshare_expr (rhs);
1271 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1272 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1273 if (bound)
1274 rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
1275 if (!update_call_from_tree (gsi, rhs))
1276 gimplify_and_update_call_from_tree (gsi, rhs);
1277 stmt = gsi_stmt (*gsi);
1278 update_stmt (stmt);
1279 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1281 fprintf (dump_file, "into: ");
1282 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1284 if (si != NULL
1285 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1286 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1287 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1289 si = unshare_strinfo (si);
1290 si->nonzero_chars = lhs;
1291 gcc_assert (si->full_string_p);
1294 if (strlen_to_stridx)
1295 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1297 return;
1300 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1301 return;
1302 if (idx == 0)
1303 idx = new_stridx (src);
1304 else
1306 strinfo *si = get_strinfo (idx);
1307 if (si != NULL)
1309 if (!si->full_string_p && !si->stmt)
1311 /* Until now we only had a lower bound on the string length.
1312 Install LHS as the actual length. */
1313 si = unshare_strinfo (si);
1314 tree old = si->nonzero_chars;
1315 si->nonzero_chars = lhs;
1316 si->full_string_p = true;
1317 if (TREE_CODE (old) == INTEGER_CST)
1319 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1320 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1321 TREE_TYPE (lhs), lhs, old);
1322 adjust_related_strinfos (loc, si, adj);
1324 else
1326 si->first = 0;
1327 si->prev = 0;
1328 si->next = 0;
1331 return;
1334 if (idx)
1336 strinfo *si = new_strinfo (src, idx, lhs, true);
1337 set_strinfo (idx, si);
1338 find_equal_ptrs (src, idx);
1340 /* For SRC that is an array of N elements, set LHS's range
1341 to [0, min (N, BOUND)]. A constant return value means
1342 the range would have consisted of a single value. In
1343 that case, fold the result into the returned constant. */
1344 if (tree ret = maybe_set_strlen_range (lhs, src, bound))
1345 if (TREE_CODE (ret) == INTEGER_CST)
1347 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1349 fprintf (dump_file, "Optimizing: ");
1350 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1352 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
1353 ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
1354 if (!update_call_from_tree (gsi, ret))
1355 gimplify_and_update_call_from_tree (gsi, ret);
1356 stmt = gsi_stmt (*gsi);
1357 update_stmt (stmt);
1358 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1360 fprintf (dump_file, "into: ");
1361 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1365 if (strlen_to_stridx)
1366 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1370 /* Handle a strchr call. If strlen of the first argument is known, replace
1371 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1372 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1374 static void
1375 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1377 int idx;
1378 tree src;
1379 gimple *stmt = gsi_stmt (*gsi);
1380 tree lhs = gimple_call_lhs (stmt);
1382 if (lhs == NULL_TREE)
1383 return;
1385 if (!integer_zerop (gimple_call_arg (stmt, 1)))
1386 return;
1388 src = gimple_call_arg (stmt, 0);
1389 idx = get_stridx (src);
1390 if (idx)
1392 strinfo *si = NULL;
1393 tree rhs;
1395 if (idx < 0)
1396 rhs = build_int_cst (size_type_node, ~idx);
1397 else
1399 rhs = NULL_TREE;
1400 si = get_strinfo (idx);
1401 if (si != NULL)
1402 rhs = get_string_length (si);
1404 if (rhs != NULL_TREE)
1406 location_t loc = gimple_location (stmt);
1408 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1410 fprintf (dump_file, "Optimizing: ");
1411 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1413 if (si != NULL && si->endptr != NULL_TREE)
1415 rhs = unshare_expr (si->endptr);
1416 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1417 TREE_TYPE (rhs)))
1418 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1420 else
1422 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1423 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1424 TREE_TYPE (src), src, rhs);
1425 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1426 TREE_TYPE (rhs)))
1427 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1429 if (!update_call_from_tree (gsi, rhs))
1430 gimplify_and_update_call_from_tree (gsi, rhs);
1431 stmt = gsi_stmt (*gsi);
1432 update_stmt (stmt);
1433 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1435 fprintf (dump_file, "into: ");
1436 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1438 if (si != NULL
1439 && si->endptr == NULL_TREE
1440 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1442 si = unshare_strinfo (si);
1443 si->endptr = lhs;
1445 zero_length_string (lhs, si);
1446 return;
1449 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1450 return;
1451 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1453 if (idx == 0)
1454 idx = new_stridx (src);
1455 else if (get_strinfo (idx) != NULL)
1457 zero_length_string (lhs, NULL);
1458 return;
1460 if (idx)
1462 location_t loc = gimple_location (stmt);
1463 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1464 tree srcu = fold_convert_loc (loc, size_type_node, src);
1465 tree length = fold_build2_loc (loc, MINUS_EXPR,
1466 size_type_node, lhsu, srcu);
1467 strinfo *si = new_strinfo (src, idx, length, true);
1468 si->endptr = lhs;
1469 set_strinfo (idx, si);
1470 find_equal_ptrs (src, idx);
1471 zero_length_string (lhs, si);
1474 else
1475 zero_length_string (lhs, NULL);
1478 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1479 If strlen of the second argument is known, strlen of the first argument
1480 is the same after this call. Furthermore, attempt to convert it to
1481 memcpy. */
1483 static void
1484 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1486 int idx, didx;
1487 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1488 bool success;
1489 gimple *stmt = gsi_stmt (*gsi);
1490 strinfo *si, *dsi, *olddsi, *zsi;
1491 location_t loc;
1493 src = gimple_call_arg (stmt, 1);
1494 dst = gimple_call_arg (stmt, 0);
1495 lhs = gimple_call_lhs (stmt);
1496 idx = get_stridx (src);
1497 si = NULL;
1498 if (idx > 0)
1499 si = get_strinfo (idx);
1501 didx = get_stridx (dst);
1502 olddsi = NULL;
1503 oldlen = NULL_TREE;
1504 if (didx > 0)
1505 olddsi = get_strinfo (didx);
1506 else if (didx < 0)
1507 return;
1509 if (olddsi != NULL)
1510 adjust_last_stmt (olddsi, stmt, false);
1512 srclen = NULL_TREE;
1513 if (si != NULL)
1514 srclen = get_string_length (si);
1515 else if (idx < 0)
1516 srclen = build_int_cst (size_type_node, ~idx);
1518 loc = gimple_location (stmt);
1519 if (srclen == NULL_TREE)
1520 switch (bcode)
1522 case BUILT_IN_STRCPY:
1523 case BUILT_IN_STRCPY_CHK:
1524 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1525 return;
1526 break;
1527 case BUILT_IN_STPCPY:
1528 case BUILT_IN_STPCPY_CHK:
1529 if (lhs == NULL_TREE)
1530 return;
1531 else
1533 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1534 srclen = fold_convert_loc (loc, size_type_node, dst);
1535 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1536 lhsuint, srclen);
1538 break;
1539 default:
1540 gcc_unreachable ();
1543 if (didx == 0)
1545 didx = new_stridx (dst);
1546 if (didx == 0)
1547 return;
1549 if (olddsi != NULL)
1551 oldlen = olddsi->nonzero_chars;
1552 dsi = unshare_strinfo (olddsi);
1553 dsi->nonzero_chars = srclen;
1554 dsi->full_string_p = (srclen != NULL_TREE);
1555 /* Break the chain, so adjust_related_strinfo on later pointers in
1556 the chain won't adjust this one anymore. */
1557 dsi->next = 0;
1558 dsi->stmt = NULL;
1559 dsi->endptr = NULL_TREE;
1561 else
1563 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1564 set_strinfo (didx, dsi);
1565 find_equal_ptrs (dst, didx);
1567 dsi->writable = true;
1568 dsi->dont_invalidate = true;
1570 if (dsi->nonzero_chars == NULL_TREE)
1572 strinfo *chainsi;
1574 /* If string length of src is unknown, use delayed length
1575 computation. If string lenth of dst will be needed, it
1576 can be computed by transforming this strcpy call into
1577 stpcpy and subtracting dst from the return value. */
1579 /* Look for earlier strings whose length could be determined if
1580 this strcpy is turned into an stpcpy. */
1582 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1584 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1586 /* When setting a stmt for delayed length computation
1587 prevent all strinfos through dsi from being
1588 invalidated. */
1589 chainsi = unshare_strinfo (chainsi);
1590 chainsi->stmt = stmt;
1591 chainsi->nonzero_chars = NULL_TREE;
1592 chainsi->full_string_p = false;
1593 chainsi->endptr = NULL_TREE;
1594 chainsi->dont_invalidate = true;
1597 dsi->stmt = stmt;
1599 /* Try to detect overlap before returning. This catches cases
1600 like strcpy (d, d + n) where n is non-constant whose range
1601 is such that (n <= strlen (d) holds).
1603 OLDDSI->NONZERO_chars may have been reset by this point with
1604 oldlen holding it original value. */
1605 if (olddsi && oldlen)
1607 /* Add 1 for the terminating NUL. */
1608 tree type = TREE_TYPE (oldlen);
1609 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1610 build_int_cst (type, 1));
1611 check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
1612 oldlen, NULL_TREE);
1615 return;
1618 if (olddsi != NULL)
1620 tree adj = NULL_TREE;
1621 if (oldlen == NULL_TREE)
1623 else if (integer_zerop (oldlen))
1624 adj = srclen;
1625 else if (TREE_CODE (oldlen) == INTEGER_CST
1626 || TREE_CODE (srclen) == INTEGER_CST)
1627 adj = fold_build2_loc (loc, MINUS_EXPR,
1628 TREE_TYPE (srclen), srclen,
1629 fold_convert_loc (loc, TREE_TYPE (srclen),
1630 oldlen));
1631 if (adj != NULL_TREE)
1632 adjust_related_strinfos (loc, dsi, adj);
1633 else
1634 dsi->prev = 0;
1636 /* strcpy src may not overlap dst, so src doesn't need to be
1637 invalidated either. */
1638 if (si != NULL)
1639 si->dont_invalidate = true;
1641 fn = NULL_TREE;
1642 zsi = NULL;
1643 switch (bcode)
1645 case BUILT_IN_STRCPY:
1646 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1647 if (lhs)
1648 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1649 break;
1650 case BUILT_IN_STRCPY_CHK:
1651 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1652 if (lhs)
1653 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1654 break;
1655 case BUILT_IN_STPCPY:
1656 /* This would need adjustment of the lhs (subtract one),
1657 or detection that the trailing '\0' doesn't need to be
1658 written, if it will be immediately overwritten.
1659 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1660 if (lhs)
1662 dsi->endptr = lhs;
1663 zsi = zero_length_string (lhs, dsi);
1665 break;
1666 case BUILT_IN_STPCPY_CHK:
1667 /* This would need adjustment of the lhs (subtract one),
1668 or detection that the trailing '\0' doesn't need to be
1669 written, if it will be immediately overwritten.
1670 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1671 if (lhs)
1673 dsi->endptr = lhs;
1674 zsi = zero_length_string (lhs, dsi);
1676 break;
1677 default:
1678 gcc_unreachable ();
1680 if (zsi != NULL)
1681 zsi->dont_invalidate = true;
1683 if (fn)
1685 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1686 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1688 else
1689 type = size_type_node;
1691 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1692 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1694 /* Set the no-warning bit on the transformed statement? */
1695 bool set_no_warning = false;
1697 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1698 if (si
1699 && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
1700 NULL_TREE, len))
1702 gimple_set_no_warning (stmt, true);
1703 set_no_warning = true;
1706 if (fn == NULL_TREE)
1707 return;
1709 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1710 GSI_SAME_STMT);
1711 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1713 fprintf (dump_file, "Optimizing: ");
1714 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1716 if (gimple_call_num_args (stmt) == 2)
1717 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1718 else
1719 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1720 gimple_call_arg (stmt, 2));
1721 if (success)
1723 stmt = gsi_stmt (*gsi);
1724 update_stmt (stmt);
1725 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1727 fprintf (dump_file, "into: ");
1728 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1730 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1731 laststmt.stmt = stmt;
1732 laststmt.len = srclen;
1733 laststmt.stridx = dsi->idx;
1735 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1736 fprintf (dump_file, "not possible.\n");
1738 if (set_no_warning)
1739 gimple_set_no_warning (stmt, true);
1742 /* Check the size argument to the built-in forms of stpncpy and strncpy
1743 for out-of-bounds offsets or overlapping access, and to see if the
1744 size argument is derived from a call to strlen() on the source argument,
1745 and if so, issue an appropriate warning. */
1747 static void
1748 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1750 /* Same as stxncpy(). */
1751 handle_builtin_stxncpy (bcode, gsi);
1754 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1755 way. LEN can either be an integer expression, or a pointer (to char).
1756 When it is the latter (such as in recursive calls to self) is is
1757 assumed to be the argument in some call to strlen() whose relationship
1758 to SRC is being ascertained. */
1760 bool
1761 is_strlen_related_p (tree src, tree len)
1763 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1764 && operand_equal_p (src, len, 0))
1765 return true;
1767 if (TREE_CODE (len) != SSA_NAME)
1768 return false;
1770 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1771 if (!def_stmt)
1772 return false;
1774 if (is_gimple_call (def_stmt))
1776 tree func = gimple_call_fndecl (def_stmt);
1777 if (!valid_builtin_call (def_stmt)
1778 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1779 return false;
1781 tree arg = gimple_call_arg (def_stmt, 0);
1782 return is_strlen_related_p (src, arg);
1785 if (!is_gimple_assign (def_stmt))
1786 return false;
1788 tree_code code = gimple_assign_rhs_code (def_stmt);
1789 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1790 tree rhstype = TREE_TYPE (rhs1);
1792 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1793 || (INTEGRAL_TYPE_P (rhstype)
1794 && (code == BIT_AND_EXPR
1795 || code == NOP_EXPR)))
1797 /* Pointer plus (an integer), and truncation are considered among
1798 the (potentially) related expressions to strlen. */
1799 return is_strlen_related_p (src, rhs1);
1802 if (tree rhs2 = gimple_assign_rhs2 (def_stmt))
1804 /* Integer subtraction is considered strlen-related when both
1805 arguments are integers and second one is strlen-related. */
1806 rhstype = TREE_TYPE (rhs2);
1807 if (INTEGRAL_TYPE_P (rhstype) && code == MINUS_EXPR)
1808 return is_strlen_related_p (src, rhs2);
1811 return false;
1814 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1815 in gimple-fold.c.
1816 Check to see if the specified bound is a) equal to the size of
1817 the destination DST and if so, b) if it's immediately followed by
1818 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1819 do nothing. Return true if diagnostic has been issued.
1821 The purpose is to diagnose calls to strncpy and stpncpy that do
1822 not nul-terminate the copy while allowing for the idiom where
1823 such a call is immediately followed by setting the last element
1824 to nul, as in:
1825 char a[32];
1826 strncpy (a, s, sizeof a);
1827 a[sizeof a - 1] = '\0';
1830 bool
1831 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1833 gimple *stmt = gsi_stmt (gsi);
1834 if (gimple_no_warning_p (stmt))
1835 return false;
1837 wide_int cntrange[2];
1839 if (TREE_CODE (cnt) == INTEGER_CST)
1840 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1841 else if (TREE_CODE (cnt) == SSA_NAME)
1843 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1844 if (rng == VR_RANGE)
1846 else if (rng == VR_ANTI_RANGE)
1848 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1850 if (wi::ltu_p (cntrange[1], maxobjsize))
1852 cntrange[0] = cntrange[1] + 1;
1853 cntrange[1] = maxobjsize;
1855 else
1857 cntrange[1] = cntrange[0] - 1;
1858 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1861 else
1862 return false;
1864 else
1865 return false;
1867 /* Negative value is the constant string length. If it's less than
1868 the lower bound there is no truncation. Avoid calling get_stridx()
1869 when ssa_ver_to_stridx is empty. That implies the caller isn't
1870 running under the control of this pass and ssa_ver_to_stridx hasn't
1871 been created yet. */
1872 int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
1873 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1874 return false;
1876 tree dst = gimple_call_arg (stmt, 0);
1877 tree dstdecl = dst;
1878 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1879 dstdecl = TREE_OPERAND (dstdecl, 0);
1881 tree ref = NULL_TREE;
1883 if (!sidx)
1885 /* If the source is a non-string return early to avoid warning
1886 for possible truncation (if the truncation is certain SIDX
1887 is non-zero). */
1888 tree srcdecl = gimple_call_arg (stmt, 1);
1889 if (TREE_CODE (srcdecl) == ADDR_EXPR)
1890 srcdecl = TREE_OPERAND (srcdecl, 0);
1891 if (get_attr_nonstring_decl (srcdecl, &ref))
1892 return false;
1895 /* Likewise, if the destination refers to a an array/pointer declared
1896 nonstring return early. */
1897 if (get_attr_nonstring_decl (dstdecl, &ref))
1898 return false;
1900 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1901 avoid the truncation warning. */
1902 gsi_next_nondebug (&gsi);
1903 gimple *next_stmt = gsi_stmt (gsi);
1904 if (!next_stmt)
1906 /* When there is no statement in the same basic block check
1907 the immediate successor block. */
1908 if (basic_block bb = gimple_bb (stmt))
1910 if (single_succ_p (bb))
1912 /* For simplicity, ignore blocks with multiple outgoing
1913 edges for now and only consider successor blocks along
1914 normal edges. */
1915 edge e = EDGE_SUCC (bb, 0);
1916 if (!(e->flags & EDGE_ABNORMAL))
1918 gsi = gsi_start_bb (e->dest);
1919 next_stmt = gsi_stmt (gsi);
1920 if (next_stmt && is_gimple_debug (next_stmt))
1922 gsi_next_nondebug (&gsi);
1923 next_stmt = gsi_stmt (gsi);
1930 if (next_stmt && is_gimple_assign (next_stmt))
1932 tree lhs = gimple_assign_lhs (next_stmt);
1933 tree_code code = TREE_CODE (lhs);
1934 if (code == ARRAY_REF || code == MEM_REF)
1935 lhs = TREE_OPERAND (lhs, 0);
1937 tree func = gimple_call_fndecl (stmt);
1938 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1940 tree ret = gimple_call_lhs (stmt);
1941 if (ret && operand_equal_p (ret, lhs, 0))
1942 return false;
1945 /* Determine the base address and offset of the reference,
1946 ignoring the innermost array index. */
1947 if (TREE_CODE (ref) == ARRAY_REF)
1948 ref = TREE_OPERAND (ref, 0);
1950 poly_int64 dstoff;
1951 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1953 poly_int64 lhsoff;
1954 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1955 if (lhsbase
1956 && dstbase
1957 && known_eq (dstoff, lhsoff)
1958 && operand_equal_p (dstbase, lhsbase, 0))
1959 return false;
1962 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1963 wide_int lenrange[2];
1964 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1966 lenrange[0] = (sisrc->nonzero_chars
1967 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1968 ? wi::to_wide (sisrc->nonzero_chars)
1969 : wi::zero (prec));
1970 lenrange[1] = lenrange[0];
1972 else if (sidx < 0)
1973 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1974 else
1976 tree range[2];
1977 get_range_strlen (src, range);
1978 if (range[0] != NULL_TREE
1979 && TREE_CODE (range[0]) == INTEGER_CST
1980 && range[1] != NULL_TREE
1981 && TREE_CODE (range[1]) == INTEGER_CST)
1983 lenrange[0] = wi::to_wide (range[0], prec);
1984 lenrange[1] = wi::to_wide (range[1], prec);
1986 else
1988 lenrange[0] = wi::shwi (0, prec);
1989 lenrange[1] = wi::shwi (-1, prec);
1993 location_t callloc = gimple_nonartificial_location (stmt);
1994 callloc = expansion_point_location_if_in_system_header (callloc);
1996 tree func = gimple_call_fndecl (stmt);
1998 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
2000 /* If the longest source string is shorter than the lower bound
2001 of the specified count the copy is definitely nul-terminated. */
2002 if (wi::ltu_p (lenrange[1], cntrange[0]))
2003 return false;
2005 if (wi::neg_p (lenrange[1]))
2007 /* The length of one of the strings is unknown but at least
2008 one has non-zero length and that length is stored in
2009 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2010 warning below. */
2011 lenrange[1] = lenrange[0];
2012 lenrange[0] = wi::shwi (0, prec);
2015 gcall *call = as_a <gcall *> (stmt);
2017 if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
2018 return warning_n (callloc, OPT_Wstringop_truncation,
2019 cntrange[0].to_uhwi (),
2020 "%G%qD output truncated before terminating "
2021 "nul copying %E byte from a string of the "
2022 "same length",
2023 "%G%qD output truncated before terminating nul "
2024 "copying %E bytes from a string of the same "
2025 "length",
2026 call, func, cnt);
2027 else if (wi::geu_p (lenrange[0], cntrange[1]))
2029 /* The shortest string is longer than the upper bound of
2030 the count so the truncation is certain. */
2031 if (cntrange[0] == cntrange[1])
2032 return warning_n (callloc, OPT_Wstringop_truncation,
2033 cntrange[0].to_uhwi (),
2034 "%G%qD output truncated copying %E byte "
2035 "from a string of length %wu",
2036 "%G%qD output truncated copying %E bytes "
2037 "from a string of length %wu",
2038 call, func, cnt, lenrange[0].to_uhwi ());
2040 return warning_at (callloc, OPT_Wstringop_truncation,
2041 "%G%qD output truncated copying between %wu "
2042 "and %wu bytes from a string of length %wu",
2043 call, func, cntrange[0].to_uhwi (),
2044 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2046 else if (wi::geu_p (lenrange[1], cntrange[1]))
2048 /* The longest string is longer than the upper bound of
2049 the count so the truncation is possible. */
2050 if (cntrange[0] == cntrange[1])
2051 return warning_n (callloc, OPT_Wstringop_truncation,
2052 cntrange[0].to_uhwi (),
2053 "%G%qD output may be truncated copying %E "
2054 "byte from a string of length %wu",
2055 "%G%qD output may be truncated copying %E "
2056 "bytes from a string of length %wu",
2057 call, func, cnt, lenrange[1].to_uhwi ());
2059 return warning_at (callloc, OPT_Wstringop_truncation,
2060 "%G%qD output may be truncated copying between %wu "
2061 "and %wu bytes from a string of length %wu",
2062 call, func, cntrange[0].to_uhwi (),
2063 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
2066 if (cntrange[0] != cntrange[1]
2067 && wi::leu_p (cntrange[0], lenrange[0])
2068 && wi::leu_p (cntrange[1], lenrange[0] + 1))
2070 /* If the source (including the terminating nul) is longer than
2071 the lower bound of the specified count but shorter than the
2072 upper bound the copy may (but need not) be truncated. */
2073 return warning_at (callloc, OPT_Wstringop_truncation,
2074 "%G%qD output may be truncated copying between "
2075 "%wu and %wu bytes from a string of length %wu",
2076 call, func, cntrange[0].to_uhwi (),
2077 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2081 if (tree dstsize = compute_objsize (dst, 1))
2083 /* The source length is uknown. Try to determine the destination
2084 size and see if it matches the specified bound. If not, bail.
2085 Otherwise go on to see if it should be diagnosed for possible
2086 truncation. */
2087 if (!dstsize)
2088 return false;
2090 if (wi::to_wide (dstsize) != cntrange[1])
2091 return false;
2093 if (cntrange[0] == cntrange[1])
2094 return warning_at (callloc, OPT_Wstringop_truncation,
2095 "%G%qD specified bound %E equals destination size",
2096 as_a <gcall *> (stmt), func, cnt);
2099 return false;
2102 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2103 out-of-bounds offsets or overlapping access, and to see if the size
2104 is derived from calling strlen() on the source argument, and if so,
2105 issue the appropriate warning. */
2107 static void
2108 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2110 if (!strlen_to_stridx)
2111 return;
2113 gimple *stmt = gsi_stmt (*gsi);
2115 tree dst = gimple_call_arg (stmt, 0);
2116 tree src = gimple_call_arg (stmt, 1);
2117 tree len = gimple_call_arg (stmt, 2);
2118 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2120 int didx = get_stridx (dst);
2121 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2123 /* Compute the size of the destination string including the NUL. */
2124 if (sidst->nonzero_chars)
2126 tree type = TREE_TYPE (sidst->nonzero_chars);
2127 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2128 build_int_cst (type, 1));
2130 dst = sidst->ptr;
2133 int sidx = get_stridx (src);
2134 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2135 if (sisrc)
2137 /* strncat() and strncpy() can modify the source string by writing
2138 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2139 clear. */
2141 /* Compute the size of the source string including the NUL. */
2142 if (sisrc->nonzero_chars)
2144 tree type = TREE_TYPE (sisrc->nonzero_chars);
2145 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2146 build_int_cst (type, 1));
2149 src = sisrc->ptr;
2151 else
2152 srcsize = NULL_TREE;
2154 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
2155 dstsize, srcsize))
2157 gimple_set_no_warning (stmt, true);
2158 return;
2161 /* If the length argument was computed from strlen(S) for some string
2162 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2163 the location of the strlen() call (PSS->SECOND). */
2164 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2165 if (!pss || pss->first <= 0)
2167 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2168 gimple_set_no_warning (stmt, true);
2170 return;
2173 /* Retrieve the strinfo data for the string S that LEN was computed
2174 from as some function F of strlen (S) (i.e., LEN need not be equal
2175 to strlen(S)). */
2176 strinfo *silen = get_strinfo (pss->first);
2178 location_t callloc = gimple_nonartificial_location (stmt);
2179 callloc = expansion_point_location_if_in_system_header (callloc);
2181 tree func = gimple_call_fndecl (stmt);
2183 bool warned = false;
2185 /* When -Wstringop-truncation is set, try to determine truncation
2186 before diagnosing possible overflow. Truncation is implied by
2187 the LEN argument being equal to strlen(SRC), regardless of
2188 whether its value is known. Otherwise, issue the more generic
2189 -Wstringop-overflow which triggers for LEN arguments that in
2190 any meaningful way depend on strlen(SRC). */
2191 if (sisrc == silen
2192 && is_strlen_related_p (src, len)
2193 && warning_at (callloc, OPT_Wstringop_truncation,
2194 "%G%qD output truncated before terminating nul "
2195 "copying as many bytes from a string as its length",
2196 as_a <gcall *>(stmt), func))
2197 warned = true;
2198 else if (silen && is_strlen_related_p (src, silen->ptr))
2199 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2200 "%G%qD specified bound depends on the length "
2201 "of the source argument",
2202 as_a <gcall *>(stmt), func);
2203 if (warned)
2205 location_t strlenloc = pss->second;
2206 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2207 inform (strlenloc, "length computed here");
2211 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2212 If strlen of the second argument is known and length of the third argument
2213 is that plus one, strlen of the first argument is the same after this
2214 call. */
2216 static void
2217 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2219 int idx, didx;
2220 tree src, dst, len, lhs, oldlen, newlen;
2221 gimple *stmt = gsi_stmt (*gsi);
2222 strinfo *si, *dsi, *olddsi;
2224 len = gimple_call_arg (stmt, 2);
2225 src = gimple_call_arg (stmt, 1);
2226 dst = gimple_call_arg (stmt, 0);
2227 idx = get_stridx (src);
2228 if (idx == 0)
2229 return;
2231 didx = get_stridx (dst);
2232 olddsi = NULL;
2233 if (didx > 0)
2234 olddsi = get_strinfo (didx);
2235 else if (didx < 0)
2236 return;
2238 if (olddsi != NULL
2239 && tree_fits_uhwi_p (len)
2240 && !integer_zerop (len))
2241 adjust_last_stmt (olddsi, stmt, false);
2243 bool full_string_p;
2244 if (idx > 0)
2246 gimple *def_stmt;
2248 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2249 is known. */
2250 si = get_strinfo (idx);
2251 if (si == NULL || si->nonzero_chars == NULL_TREE)
2252 return;
2253 if (TREE_CODE (len) == INTEGER_CST
2254 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2256 if (tree_int_cst_le (len, si->nonzero_chars))
2258 /* Copying LEN nonzero characters, where LEN is constant. */
2259 newlen = len;
2260 full_string_p = false;
2262 else
2264 /* Copying the whole of the analyzed part of SI. */
2265 newlen = si->nonzero_chars;
2266 full_string_p = si->full_string_p;
2269 else
2271 if (!si->full_string_p)
2272 return;
2273 if (TREE_CODE (len) != SSA_NAME)
2274 return;
2275 def_stmt = SSA_NAME_DEF_STMT (len);
2276 if (!is_gimple_assign (def_stmt)
2277 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2278 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2279 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2280 return;
2281 /* Copying variable-length string SI (and no more). */
2282 newlen = si->nonzero_chars;
2283 full_string_p = true;
2286 else
2288 si = NULL;
2289 /* Handle memcpy (x, "abcd", 5) or
2290 memcpy (x, "abc\0uvw", 7). */
2291 if (!tree_fits_uhwi_p (len))
2292 return;
2294 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2295 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2296 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2297 full_string_p = clen > nonzero_chars;
2300 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2301 adjust_last_stmt (olddsi, stmt, false);
2303 if (didx == 0)
2305 didx = new_stridx (dst);
2306 if (didx == 0)
2307 return;
2309 oldlen = NULL_TREE;
2310 if (olddsi != NULL)
2312 dsi = unshare_strinfo (olddsi);
2313 oldlen = olddsi->nonzero_chars;
2314 dsi->nonzero_chars = newlen;
2315 dsi->full_string_p = full_string_p;
2316 /* Break the chain, so adjust_related_strinfo on later pointers in
2317 the chain won't adjust this one anymore. */
2318 dsi->next = 0;
2319 dsi->stmt = NULL;
2320 dsi->endptr = NULL_TREE;
2322 else
2324 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2325 set_strinfo (didx, dsi);
2326 find_equal_ptrs (dst, didx);
2328 dsi->writable = true;
2329 dsi->dont_invalidate = true;
2330 if (olddsi != NULL)
2332 tree adj = NULL_TREE;
2333 location_t loc = gimple_location (stmt);
2334 if (oldlen == NULL_TREE)
2336 else if (integer_zerop (oldlen))
2337 adj = newlen;
2338 else if (TREE_CODE (oldlen) == INTEGER_CST
2339 || TREE_CODE (newlen) == INTEGER_CST)
2340 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2341 fold_convert_loc (loc, TREE_TYPE (newlen),
2342 oldlen));
2343 if (adj != NULL_TREE)
2344 adjust_related_strinfos (loc, dsi, adj);
2345 else
2346 dsi->prev = 0;
2348 /* memcpy src may not overlap dst, so src doesn't need to be
2349 invalidated either. */
2350 if (si != NULL)
2351 si->dont_invalidate = true;
2353 if (full_string_p)
2355 lhs = gimple_call_lhs (stmt);
2356 switch (bcode)
2358 case BUILT_IN_MEMCPY:
2359 case BUILT_IN_MEMCPY_CHK:
2360 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2361 laststmt.stmt = stmt;
2362 laststmt.len = dsi->nonzero_chars;
2363 laststmt.stridx = dsi->idx;
2364 if (lhs)
2365 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2366 break;
2367 case BUILT_IN_MEMPCPY:
2368 case BUILT_IN_MEMPCPY_CHK:
2369 break;
2370 default:
2371 gcc_unreachable ();
2376 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2377 If strlen of the second argument is known, strlen of the first argument
2378 is increased by the length of the second argument. Furthermore, attempt
2379 to convert it to memcpy/strcpy if the length of the first argument
2380 is known. */
2382 static void
2383 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2385 int idx, didx;
2386 tree srclen, args, type, fn, objsz, endptr;
2387 bool success;
2388 gimple *stmt = gsi_stmt (*gsi);
2389 strinfo *si, *dsi;
2390 location_t loc = gimple_location (stmt);
2392 tree src = gimple_call_arg (stmt, 1);
2393 tree dst = gimple_call_arg (stmt, 0);
2395 /* Bail if the source is the same as destination. It will be diagnosed
2396 elsewhere. */
2397 if (operand_equal_p (src, dst, 0))
2398 return;
2400 tree lhs = gimple_call_lhs (stmt);
2402 didx = get_stridx (dst);
2403 if (didx < 0)
2404 return;
2406 dsi = NULL;
2407 if (didx > 0)
2408 dsi = get_strinfo (didx);
2410 srclen = NULL_TREE;
2411 si = NULL;
2412 idx = get_stridx (src);
2413 if (idx < 0)
2414 srclen = build_int_cst (size_type_node, ~idx);
2415 else if (idx > 0)
2417 si = get_strinfo (idx);
2418 if (si != NULL)
2419 srclen = get_string_length (si);
2422 /* Set the no-warning bit on the transformed statement? */
2423 bool set_no_warning = false;
2425 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2428 /* The concatenation always involves copying at least one byte
2429 (the terminating nul), even if the source string is empty.
2430 If the source is unknown assume it's one character long and
2431 used that as both sizes. */
2432 tree slen = srclen;
2433 if (slen)
2435 tree type = TREE_TYPE (slen);
2436 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2439 tree sptr = si && si->ptr ? si->ptr : src;
2441 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2442 NULL_TREE, slen))
2444 gimple_set_no_warning (stmt, true);
2445 set_no_warning = true;
2449 /* strcat (p, q) can be transformed into
2450 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2451 with length endptr - p if we need to compute the length
2452 later on. Don't do this transformation if we don't need
2453 it. */
2454 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2456 if (didx == 0)
2458 didx = new_stridx (dst);
2459 if (didx == 0)
2460 return;
2462 if (dsi == NULL)
2464 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2465 set_strinfo (didx, dsi);
2466 find_equal_ptrs (dst, didx);
2468 else
2470 dsi = unshare_strinfo (dsi);
2471 dsi->nonzero_chars = NULL_TREE;
2472 dsi->full_string_p = false;
2473 dsi->next = 0;
2474 dsi->endptr = NULL_TREE;
2476 dsi->writable = true;
2477 dsi->stmt = stmt;
2478 dsi->dont_invalidate = true;
2480 return;
2483 tree dstlen = dsi->nonzero_chars;
2484 endptr = dsi->endptr;
2486 dsi = unshare_strinfo (dsi);
2487 dsi->endptr = NULL_TREE;
2488 dsi->stmt = NULL;
2489 dsi->writable = true;
2491 if (srclen != NULL_TREE)
2493 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2494 TREE_TYPE (dsi->nonzero_chars),
2495 dsi->nonzero_chars, srclen);
2496 gcc_assert (dsi->full_string_p);
2497 adjust_related_strinfos (loc, dsi, srclen);
2498 dsi->dont_invalidate = true;
2500 else
2502 dsi->nonzero_chars = NULL;
2503 dsi->full_string_p = false;
2504 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2505 dsi->dont_invalidate = true;
2508 if (si != NULL)
2509 /* strcat src may not overlap dst, so src doesn't need to be
2510 invalidated either. */
2511 si->dont_invalidate = true;
2513 /* For now. Could remove the lhs from the call and add
2514 lhs = dst; afterwards. */
2515 if (lhs)
2516 return;
2518 fn = NULL_TREE;
2519 objsz = NULL_TREE;
2520 switch (bcode)
2522 case BUILT_IN_STRCAT:
2523 if (srclen != NULL_TREE)
2524 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2525 else
2526 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2527 break;
2528 case BUILT_IN_STRCAT_CHK:
2529 if (srclen != NULL_TREE)
2530 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2531 else
2532 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2533 objsz = gimple_call_arg (stmt, 2);
2534 break;
2535 default:
2536 gcc_unreachable ();
2539 if (fn == NULL_TREE)
2540 return;
2542 if (dsi && dstlen)
2544 tree type = TREE_TYPE (dstlen);
2546 /* Compute the size of the source sequence, including the nul. */
2547 tree srcsize = srclen ? srclen : size_zero_node;
2548 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2550 tree sptr = si && si->ptr ? si->ptr : src;
2552 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2553 dstlen, srcsize))
2555 gimple_set_no_warning (stmt, true);
2556 set_no_warning = true;
2560 tree len = NULL_TREE;
2561 if (srclen != NULL_TREE)
2563 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2564 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2566 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2567 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2568 build_int_cst (type, 1));
2569 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2570 GSI_SAME_STMT);
2572 if (endptr)
2573 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2574 else
2575 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2576 TREE_TYPE (dst), unshare_expr (dst),
2577 fold_convert_loc (loc, sizetype,
2578 unshare_expr (dstlen)));
2579 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2580 GSI_SAME_STMT);
2581 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2583 fprintf (dump_file, "Optimizing: ");
2584 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2586 if (srclen != NULL_TREE)
2587 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2588 dst, src, len, objsz);
2589 else
2590 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2591 dst, src, objsz);
2592 if (success)
2594 stmt = gsi_stmt (*gsi);
2595 update_stmt (stmt);
2596 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2598 fprintf (dump_file, "into: ");
2599 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2601 /* If srclen == NULL, note that current string length can be
2602 computed by transforming this strcpy into stpcpy. */
2603 if (srclen == NULL_TREE && dsi->dont_invalidate)
2604 dsi->stmt = stmt;
2605 adjust_last_stmt (dsi, stmt, true);
2606 if (srclen != NULL_TREE)
2608 laststmt.stmt = stmt;
2609 laststmt.len = srclen;
2610 laststmt.stridx = dsi->idx;
2613 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2614 fprintf (dump_file, "not possible.\n");
2616 if (set_no_warning)
2617 gimple_set_no_warning (stmt, true);
2620 /* Handle a call to malloc or calloc. */
2622 static void
2623 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2625 gimple *stmt = gsi_stmt (*gsi);
2626 tree lhs = gimple_call_lhs (stmt);
2627 if (lhs == NULL_TREE)
2628 return;
2630 gcc_assert (get_stridx (lhs) == 0);
2631 int idx = new_stridx (lhs);
2632 tree length = NULL_TREE;
2633 if (bcode == BUILT_IN_CALLOC)
2634 length = build_int_cst (size_type_node, 0);
2635 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2636 if (bcode == BUILT_IN_CALLOC)
2637 si->endptr = lhs;
2638 set_strinfo (idx, si);
2639 si->writable = true;
2640 si->stmt = stmt;
2641 si->dont_invalidate = true;
2644 /* Handle a call to memset.
2645 After a call to calloc, memset(,0,) is unnecessary.
2646 memset(malloc(n),0,n) is calloc(n,1).
2647 return true when the call is transfomred, false otherwise. */
2649 static bool
2650 handle_builtin_memset (gimple_stmt_iterator *gsi)
2652 gimple *stmt2 = gsi_stmt (*gsi);
2653 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2654 return false;
2655 tree ptr = gimple_call_arg (stmt2, 0);
2656 int idx1 = get_stridx (ptr);
2657 if (idx1 <= 0)
2658 return false;
2659 strinfo *si1 = get_strinfo (idx1);
2660 if (!si1)
2661 return false;
2662 gimple *stmt1 = si1->stmt;
2663 if (!stmt1 || !is_gimple_call (stmt1))
2664 return false;
2665 tree callee1 = gimple_call_fndecl (stmt1);
2666 if (!valid_builtin_call (stmt1))
2667 return false;
2668 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2669 tree size = gimple_call_arg (stmt2, 2);
2670 if (code1 == BUILT_IN_CALLOC)
2671 /* Not touching stmt1 */ ;
2672 else if (code1 == BUILT_IN_MALLOC
2673 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2675 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2676 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2677 size, build_one_cst (size_type_node));
2678 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2679 si1->full_string_p = true;
2680 si1->stmt = gsi_stmt (gsi1);
2682 else
2683 return false;
2684 tree lhs = gimple_call_lhs (stmt2);
2685 unlink_stmt_vdef (stmt2);
2686 if (lhs)
2688 gimple *assign = gimple_build_assign (lhs, ptr);
2689 gsi_replace (gsi, assign, false);
2691 else
2693 gsi_remove (gsi, true);
2694 release_defs (stmt2);
2697 return true;
2700 /* Handle a call to memcmp. We try to handle small comparisons by
2701 converting them to load and compare, and replacing the call to memcmp
2702 with a __builtin_memcmp_eq call where possible.
2703 return true when call is transformed, return false otherwise. */
2705 static bool
2706 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2708 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2709 tree res = gimple_call_lhs (stmt2);
2710 tree arg1 = gimple_call_arg (stmt2, 0);
2711 tree arg2 = gimple_call_arg (stmt2, 1);
2712 tree len = gimple_call_arg (stmt2, 2);
2713 unsigned HOST_WIDE_INT leni;
2714 use_operand_p use_p;
2715 imm_use_iterator iter;
2717 if (!res)
2718 return false;
2720 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2722 gimple *ustmt = USE_STMT (use_p);
2724 if (is_gimple_debug (ustmt))
2725 continue;
2726 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2728 gassign *asgn = as_a <gassign *> (ustmt);
2729 tree_code code = gimple_assign_rhs_code (asgn);
2730 if ((code != EQ_EXPR && code != NE_EXPR)
2731 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2732 return false;
2734 else if (gimple_code (ustmt) == GIMPLE_COND)
2736 tree_code code = gimple_cond_code (ustmt);
2737 if ((code != EQ_EXPR && code != NE_EXPR)
2738 || !integer_zerop (gimple_cond_rhs (ustmt)))
2739 return false;
2741 else
2742 return false;
2745 if (tree_fits_uhwi_p (len)
2746 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2747 && pow2p_hwi (leni))
2749 leni *= CHAR_TYPE_SIZE;
2750 unsigned align1 = get_pointer_alignment (arg1);
2751 unsigned align2 = get_pointer_alignment (arg2);
2752 unsigned align = MIN (align1, align2);
2753 scalar_int_mode mode;
2754 if (int_mode_for_size (leni, 1).exists (&mode)
2755 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2757 location_t loc = gimple_location (stmt2);
2758 tree type, off;
2759 type = build_nonstandard_integer_type (leni, 1);
2760 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
2761 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2762 ptr_mode, true);
2763 off = build_int_cst (ptrtype, 0);
2764 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2765 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2766 tree tem1 = fold_const_aggregate_ref (arg1);
2767 if (tem1)
2768 arg1 = tem1;
2769 tree tem2 = fold_const_aggregate_ref (arg2);
2770 if (tem2)
2771 arg2 = tem2;
2772 res = fold_convert_loc (loc, TREE_TYPE (res),
2773 fold_build2_loc (loc, NE_EXPR,
2774 boolean_type_node,
2775 arg1, arg2));
2776 gimplify_and_update_call_from_tree (gsi, res);
2777 return true;
2781 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2782 return true;
2785 /* Given an index to the strinfo vector, compute the string length for the
2786 corresponding string. Return -1 when unknown. */
2788 static HOST_WIDE_INT
2789 compute_string_length (int idx)
2791 HOST_WIDE_INT string_leni = -1;
2792 gcc_assert (idx != 0);
2794 if (idx < 0)
2795 return ~idx;
2797 strinfo *si = get_strinfo (idx);
2798 if (si)
2800 tree const_string_len = get_string_length (si);
2801 if (const_string_len && tree_fits_shwi_p (const_string_len))
2802 string_leni = tree_to_shwi (const_string_len);
2805 if (string_leni < 0)
2806 return -1;
2808 return string_leni;
2811 /* Determine the minimum size of the object referenced by DEST expression which
2812 must have a pointer type.
2813 Return the minimum size of the object if successful or NULL when the size
2814 cannot be determined. */
2815 static tree
2816 determine_min_objsize (tree dest)
2818 unsigned HOST_WIDE_INT size = 0;
2820 if (compute_builtin_object_size (dest, 2, &size))
2821 return build_int_cst (sizetype, size);
2823 /* Try to determine the size of the object through the RHS of the
2824 assign statement. */
2825 if (TREE_CODE (dest) == SSA_NAME)
2827 gimple *stmt = SSA_NAME_DEF_STMT (dest);
2828 if (!is_gimple_assign (stmt))
2829 return NULL_TREE;
2831 if (!gimple_assign_single_p (stmt)
2832 && !gimple_assign_unary_nop_p (stmt))
2833 return NULL_TREE;
2835 dest = gimple_assign_rhs1 (stmt);
2836 return determine_min_objsize (dest);
2839 /* Try to determine the size of the object from its type. */
2840 if (TREE_CODE (dest) != ADDR_EXPR)
2841 return NULL_TREE;
2843 tree type = TREE_TYPE (dest);
2844 if (TREE_CODE (type) == POINTER_TYPE)
2845 type = TREE_TYPE (type);
2847 type = TYPE_MAIN_VARIANT (type);
2849 /* We cannot determine the size of the array if it's a flexible array,
2850 which is declared at the end of a structure. */
2851 if (TREE_CODE (type) == ARRAY_TYPE
2852 && !array_at_struct_end_p (dest))
2854 tree size_t = TYPE_SIZE_UNIT (type);
2855 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2856 && !integer_zerop (size_t))
2857 return size_t;
2860 return NULL_TREE;
2863 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2864 equality test against zero:
2866 A. When the lengths of both arguments are constant and it's a strcmp:
2867 * if the lengths are NOT equal, we can safely fold the call
2868 to a non-zero value.
2869 * otherwise, do nothing now.
2871 B. When the length of one argument is constant, try to replace the call with
2872 a __builtin_str(n)cmp_eq call where possible, i.e:
2874 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2875 string with constant length , C is a constant.
2876 if (C <= strlen(STR) && sizeof_array(s) > C)
2878 replace this call with
2879 strncmp_eq (s, STR, C) (!)= 0
2881 if (C > strlen(STR)
2883 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2884 can handled by the following strcmp.
2887 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2888 string with constant length.
2889 if (sizeof_array(s) > strlen(STR))
2891 replace this call with
2892 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2895 Return true when the call is transformed, return false otherwise.
2898 static bool
2899 handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
2901 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
2902 tree res = gimple_call_lhs (stmt);
2903 use_operand_p use_p;
2904 imm_use_iterator iter;
2905 tree arg1 = gimple_call_arg (stmt, 0);
2906 tree arg2 = gimple_call_arg (stmt, 1);
2907 int idx1 = get_stridx (arg1);
2908 int idx2 = get_stridx (arg2);
2909 HOST_WIDE_INT length = -1;
2910 bool is_ncmp = false;
2912 if (!res)
2913 return false;
2915 /* When both arguments are unknown, do nothing. */
2916 if (idx1 == 0 && idx2 == 0)
2917 return false;
2919 /* Handle strncmp function. */
2920 if (gimple_call_num_args (stmt) == 3)
2922 tree len = gimple_call_arg (stmt, 2);
2923 if (tree_fits_shwi_p (len))
2924 length = tree_to_shwi (len);
2926 is_ncmp = true;
2929 /* For strncmp, if the length argument is NOT known, do nothing. */
2930 if (is_ncmp && length < 0)
2931 return false;
2933 /* When the result is ONLY used to do equality test against zero. */
2934 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2936 gimple *use_stmt = USE_STMT (use_p);
2938 if (is_gimple_debug (use_stmt))
2939 continue;
2940 if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
2942 tree_code code = gimple_assign_rhs_code (use_stmt);
2943 if (code == COND_EXPR)
2945 tree cond_expr = gimple_assign_rhs1 (use_stmt);
2946 if ((TREE_CODE (cond_expr) != EQ_EXPR
2947 && (TREE_CODE (cond_expr) != NE_EXPR))
2948 || !integer_zerop (TREE_OPERAND (cond_expr, 1)))
2949 return false;
2951 else if (code == EQ_EXPR || code == NE_EXPR)
2953 if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
2954 return false;
2956 else
2957 return false;
2959 else if (gimple_code (use_stmt) == GIMPLE_COND)
2961 tree_code code = gimple_cond_code (use_stmt);
2962 if ((code != EQ_EXPR && code != NE_EXPR)
2963 || !integer_zerop (gimple_cond_rhs (use_stmt)))
2964 return false;
2966 else
2967 return false;
2970 /* When the lengths of both arguments are known, and they are unequal, we can
2971 safely fold the call to a non-zero value for strcmp;
2972 othewise, do nothing now. */
2973 if (idx1 != 0 && idx2 != 0)
2975 HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
2976 HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
2978 if (!is_ncmp
2979 && const_string_leni1 != -1
2980 && const_string_leni2 != -1
2981 && const_string_leni1 != const_string_leni2)
2983 replace_call_with_value (gsi, integer_one_node);
2984 return true;
2986 return false;
2989 /* When the length of one argument is constant. */
2990 tree var_string = NULL_TREE;
2991 HOST_WIDE_INT const_string_leni = -1;
2993 if (idx1)
2995 const_string_leni = compute_string_length (idx1);
2996 var_string = arg2;
2998 else
3000 gcc_checking_assert (idx2);
3001 const_string_leni = compute_string_length (idx2);
3002 var_string = arg1;
3005 if (const_string_leni < 0)
3006 return false;
3008 unsigned HOST_WIDE_INT var_sizei = 0;
3009 /* try to determine the minimum size of the object pointed by var_string. */
3010 tree size = determine_min_objsize (var_string);
3012 if (!size)
3013 return false;
3015 if (tree_fits_uhwi_p (size))
3016 var_sizei = tree_to_uhwi (size);
3018 if (var_sizei == 0)
3019 return false;
3021 /* For strncmp, if length > const_string_leni , this call can be safely
3022 transformed to a strcmp. */
3023 if (is_ncmp && length > const_string_leni)
3024 is_ncmp = false;
3026 unsigned HOST_WIDE_INT final_length
3027 = is_ncmp ? length : const_string_leni + 1;
3029 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
3030 if (var_sizei > final_length)
3032 tree fn
3033 = (is_ncmp
3034 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
3035 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
3036 if (!fn)
3037 return false;
3038 tree const_string_len = build_int_cst (size_type_node, final_length);
3039 update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
3041 else
3042 return false;
3044 return true;
3047 /* Handle a POINTER_PLUS_EXPR statement.
3048 For p = "abcd" + 2; compute associated length, or if
3049 p = q + off is pointing to a '\0' character of a string, call
3050 zero_length_string on it. */
3052 static void
3053 handle_pointer_plus (gimple_stmt_iterator *gsi)
3055 gimple *stmt = gsi_stmt (*gsi);
3056 tree lhs = gimple_assign_lhs (stmt), off;
3057 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3058 strinfo *si, *zsi;
3060 if (idx == 0)
3061 return;
3063 if (idx < 0)
3065 tree off = gimple_assign_rhs2 (stmt);
3066 if (tree_fits_uhwi_p (off)
3067 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
3068 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
3069 = ~(~idx - (int) tree_to_uhwi (off));
3070 return;
3073 si = get_strinfo (idx);
3074 if (si == NULL || si->nonzero_chars == NULL_TREE)
3075 return;
3077 off = gimple_assign_rhs2 (stmt);
3078 zsi = NULL;
3079 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
3080 zsi = zero_length_string (lhs, si);
3081 else if (TREE_CODE (off) == SSA_NAME)
3083 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
3084 if (gimple_assign_single_p (def_stmt)
3085 && si->full_string_p
3086 && operand_equal_p (si->nonzero_chars,
3087 gimple_assign_rhs1 (def_stmt), 0))
3088 zsi = zero_length_string (lhs, si);
3090 if (zsi != NULL
3091 && si->endptr != NULL_TREE
3092 && si->endptr != lhs
3093 && TREE_CODE (si->endptr) == SSA_NAME)
3095 enum tree_code rhs_code
3096 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
3097 ? SSA_NAME : NOP_EXPR;
3098 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
3099 gcc_assert (gsi_stmt (*gsi) == stmt);
3100 update_stmt (stmt);
3104 /* If RHS, either directly or indirectly, refers to a string of constant
3105 length, return it. Otherwise return a negative value. */
3107 static HOST_WIDE_INT
3108 get_string_cst_length (tree rhs)
3110 if (TREE_CODE (rhs) == MEM_REF
3111 && integer_zerop (TREE_OPERAND (rhs, 1)))
3113 rhs = TREE_OPERAND (rhs, 0);
3114 if (TREE_CODE (rhs) == ADDR_EXPR)
3116 tree rhs_addr = rhs;
3118 rhs = TREE_OPERAND (rhs, 0);
3119 if (TREE_CODE (rhs) != STRING_CST)
3121 int idx = get_stridx (rhs_addr);
3122 if (idx > 0)
3124 strinfo *si = get_strinfo (idx);
3125 if (si
3126 && si->full_string_p
3127 && tree_fits_shwi_p (si->nonzero_chars))
3128 return tree_to_shwi (si->nonzero_chars);
3134 if (TREE_CODE (rhs) == VAR_DECL
3135 && TREE_READONLY (rhs))
3136 rhs = DECL_INITIAL (rhs);
3138 if (rhs && TREE_CODE (rhs) == STRING_CST)
3139 return strlen (TREE_STRING_POINTER (rhs));
3141 return -1;
3144 /* Handle a single character store. */
3146 static bool
3147 handle_char_store (gimple_stmt_iterator *gsi)
3149 int idx = -1;
3150 strinfo *si = NULL;
3151 gimple *stmt = gsi_stmt (*gsi);
3152 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
3153 tree rhs = gimple_assign_rhs1 (stmt);
3154 unsigned HOST_WIDE_INT offset = 0;
3156 if (TREE_CODE (lhs) == MEM_REF
3157 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
3159 tree mem_offset = TREE_OPERAND (lhs, 1);
3160 if (tree_fits_uhwi_p (mem_offset))
3162 /* Get the strinfo for the base, and use it if it starts with at
3163 least OFFSET nonzero characters. This is trivially true if
3164 OFFSET is zero. */
3165 offset = tree_to_uhwi (mem_offset);
3166 idx = get_stridx (TREE_OPERAND (lhs, 0));
3167 if (idx > 0)
3168 si = get_strinfo (idx);
3169 if (offset == 0)
3170 ssaname = TREE_OPERAND (lhs, 0);
3171 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
3172 return true;
3175 else
3177 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
3178 if (idx > 0)
3179 si = get_strinfo (idx);
3182 bool storing_zero_p = initializer_zerop (rhs);
3183 bool storing_nonzero_p = !storing_zero_p && tree_expr_nonzero_p (rhs);
3184 /* Set to the length of the string being assigned if known. */
3185 HOST_WIDE_INT rhslen;
3187 if (si != NULL)
3189 int cmp = compare_nonzero_chars (si, offset);
3190 gcc_assert (offset == 0 || cmp >= 0);
3191 if (storing_zero_p && cmp == 0 && si->full_string_p)
3193 /* When overwriting a '\0' with a '\0', the store can be removed
3194 if we know it has been stored in the current function. */
3195 if (!stmt_could_throw_p (stmt) && si->writable)
3197 unlink_stmt_vdef (stmt);
3198 release_defs (stmt);
3199 gsi_remove (gsi, true);
3200 return false;
3202 else
3204 si->writable = true;
3205 gsi_next (gsi);
3206 return false;
3209 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3210 and if we aren't storing '\0', we know that the length of the
3211 string and any other zero terminated string in memory remains
3212 the same. In that case we move to the next gimple statement and
3213 return to signal the caller that it shouldn't invalidate anything.
3215 This is benefical for cases like:
3217 char p[20];
3218 void foo (char *q)
3220 strcpy (p, "foobar");
3221 size_t len = strlen (p); // This can be optimized into 6
3222 size_t len2 = strlen (q); // This has to be computed
3223 p[0] = 'X';
3224 size_t len3 = strlen (p); // This can be optimized into 6
3225 size_t len4 = strlen (q); // This can be optimized into len2
3226 bar (len, len2, len3, len4);
3229 else if (storing_nonzero_p && cmp > 0)
3231 gsi_next (gsi);
3232 return false;
3234 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
3236 /* When storing_nonzero_p, we know that the string now starts
3237 with OFFSET + 1 nonzero characters, but don't know whether
3238 there's a following nul terminator.
3240 When storing_zero_p, we know that the string is now OFFSET
3241 characters long.
3243 Otherwise, we're storing an unknown value at offset OFFSET,
3244 so need to clip the nonzero_chars to OFFSET. */
3245 location_t loc = gimple_location (stmt);
3246 tree oldlen = si->nonzero_chars;
3247 if (cmp == 0 && si->full_string_p)
3248 /* We're overwriting the nul terminator with a nonzero or
3249 unknown character. If the previous stmt was a memcpy,
3250 its length may be decreased. */
3251 adjust_last_stmt (si, stmt, false);
3252 si = unshare_strinfo (si);
3253 if (storing_nonzero_p)
3254 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
3255 else
3256 si->nonzero_chars = build_int_cst (size_type_node, offset);
3257 si->full_string_p = storing_zero_p;
3258 if (storing_zero_p
3259 && ssaname
3260 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3261 si->endptr = ssaname;
3262 else
3263 si->endptr = NULL;
3264 si->next = 0;
3265 si->stmt = NULL;
3266 si->writable = true;
3267 si->dont_invalidate = true;
3268 if (oldlen)
3270 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
3271 si->nonzero_chars, oldlen);
3272 adjust_related_strinfos (loc, si, adj);
3274 else
3275 si->prev = 0;
3278 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
3280 if (ssaname)
3281 idx = new_stridx (ssaname);
3282 else
3283 idx = new_addr_stridx (lhs);
3284 if (idx != 0)
3286 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
3287 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
3288 si = new_strinfo (ptr, idx, len, storing_zero_p);
3289 set_strinfo (idx, si);
3290 if (storing_zero_p
3291 && ssaname
3292 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3293 si->endptr = ssaname;
3294 si->dont_invalidate = true;
3295 si->writable = true;
3298 else if (idx == 0
3299 && (rhslen = get_string_cst_length (gimple_assign_rhs1 (stmt))) >= 0
3300 && ssaname == NULL_TREE
3301 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
3303 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
3304 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
3306 int idx = new_addr_stridx (lhs);
3307 if (idx != 0)
3309 si = new_strinfo (build_fold_addr_expr (lhs), idx,
3310 build_int_cst (size_type_node, rhslen), true);
3311 set_strinfo (idx, si);
3312 si->dont_invalidate = true;
3317 if (si != NULL && offset == 0 && storing_zero_p)
3319 /* Allow adjust_last_stmt to remove it if the stored '\0'
3320 is immediately overwritten. */
3321 laststmt.stmt = stmt;
3322 laststmt.len = build_int_cst (size_type_node, 1);
3323 laststmt.stridx = si->idx;
3325 return true;
3328 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3330 static void
3331 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3333 if (TREE_CODE (rhs1) != SSA_NAME
3334 || TREE_CODE (rhs2) != SSA_NAME)
3335 return;
3337 gimple *call_stmt = NULL;
3338 for (int pass = 0; pass < 2; pass++)
3340 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3341 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3342 && has_single_use (rhs1)
3343 && gimple_call_arg (g, 0) == rhs2)
3345 call_stmt = g;
3346 break;
3348 std::swap (rhs1, rhs2);
3351 if (call_stmt)
3353 tree arg0 = gimple_call_arg (call_stmt, 0);
3355 if (arg0 == rhs2)
3357 tree arg1 = gimple_call_arg (call_stmt, 1);
3358 tree arg1_len = NULL_TREE;
3359 int idx = get_stridx (arg1);
3361 if (idx)
3363 if (idx < 0)
3364 arg1_len = build_int_cst (size_type_node, ~idx);
3365 else
3367 strinfo *si = get_strinfo (idx);
3368 if (si)
3369 arg1_len = get_string_length (si);
3373 if (arg1_len != NULL_TREE)
3375 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3376 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3378 if (!is_gimple_val (arg1_len))
3380 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3381 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3382 arg1_len);
3383 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3384 arg1_len = arg1_len_tmp;
3387 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3388 arg0, arg1, arg1_len);
3389 tree strncmp_lhs = make_ssa_name (integer_type_node);
3390 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3391 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3392 gsi_remove (&gsi, true);
3393 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3394 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3396 if (is_gimple_assign (stmt))
3398 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3400 tree cond = gimple_assign_rhs1 (stmt);
3401 TREE_OPERAND (cond, 0) = strncmp_lhs;
3402 TREE_OPERAND (cond, 1) = zero;
3404 else
3406 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3407 gimple_assign_set_rhs2 (stmt, zero);
3410 else
3412 gcond *cond = as_a<gcond *> (stmt);
3413 gimple_cond_set_lhs (cond, strncmp_lhs);
3414 gimple_cond_set_rhs (cond, zero);
3416 update_stmt (stmt);
3422 /* Attempt to check for validity of the performed access a single statement
3423 at *GSI using string length knowledge, and to optimize it.
3424 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3425 true. */
3427 static bool
3428 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
3430 gimple *stmt = gsi_stmt (*gsi);
3432 if (is_gimple_call (stmt))
3434 tree callee = gimple_call_fndecl (stmt);
3435 if (valid_builtin_call (stmt))
3436 switch (DECL_FUNCTION_CODE (callee))
3438 case BUILT_IN_STRLEN:
3439 case BUILT_IN_STRNLEN:
3440 handle_builtin_strlen (gsi);
3441 break;
3442 case BUILT_IN_STRCHR:
3443 handle_builtin_strchr (gsi);
3444 break;
3445 case BUILT_IN_STRCPY:
3446 case BUILT_IN_STRCPY_CHK:
3447 case BUILT_IN_STPCPY:
3448 case BUILT_IN_STPCPY_CHK:
3449 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3450 break;
3452 case BUILT_IN_STRNCAT:
3453 case BUILT_IN_STRNCAT_CHK:
3454 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3455 break;
3457 case BUILT_IN_STPNCPY:
3458 case BUILT_IN_STPNCPY_CHK:
3459 case BUILT_IN_STRNCPY:
3460 case BUILT_IN_STRNCPY_CHK:
3461 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3462 break;
3464 case BUILT_IN_MEMCPY:
3465 case BUILT_IN_MEMCPY_CHK:
3466 case BUILT_IN_MEMPCPY:
3467 case BUILT_IN_MEMPCPY_CHK:
3468 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3469 break;
3470 case BUILT_IN_STRCAT:
3471 case BUILT_IN_STRCAT_CHK:
3472 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3473 break;
3474 case BUILT_IN_MALLOC:
3475 case BUILT_IN_CALLOC:
3476 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3477 break;
3478 case BUILT_IN_MEMSET:
3479 if (handle_builtin_memset (gsi))
3480 return false;
3481 break;
3482 case BUILT_IN_MEMCMP:
3483 if (handle_builtin_memcmp (gsi))
3484 return false;
3485 break;
3486 case BUILT_IN_STRCMP:
3487 case BUILT_IN_STRNCMP:
3488 if (handle_builtin_string_cmp (gsi))
3489 return false;
3490 break;
3491 default:
3492 break;
3495 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3497 tree lhs = gimple_assign_lhs (stmt);
3499 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3501 if (gimple_assign_single_p (stmt)
3502 || (gimple_assign_cast_p (stmt)
3503 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3505 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3506 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3508 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3509 handle_pointer_plus (gsi);
3511 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3513 enum tree_code code = gimple_assign_rhs_code (stmt);
3514 if (code == COND_EXPR)
3516 tree cond = gimple_assign_rhs1 (stmt);
3517 enum tree_code cond_code = TREE_CODE (cond);
3519 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3520 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3521 TREE_OPERAND (cond, 1), stmt);
3523 else if (code == EQ_EXPR || code == NE_EXPR)
3524 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3525 gimple_assign_rhs2 (stmt), stmt);
3526 else if (gimple_assign_load_p (stmt)
3527 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3528 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3529 && (TYPE_PRECISION (TREE_TYPE (lhs))
3530 == TYPE_PRECISION (char_type_node))
3531 && !gimple_has_volatile_ops (stmt))
3533 tree off = integer_zero_node;
3534 unsigned HOST_WIDE_INT coff = 0;
3535 int idx = 0;
3536 tree rhs1 = gimple_assign_rhs1 (stmt);
3537 if (code == MEM_REF)
3539 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3540 if (idx > 0)
3542 strinfo *si = get_strinfo (idx);
3543 if (si
3544 && si->nonzero_chars
3545 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3546 && (wi::to_widest (si->nonzero_chars)
3547 >= wi::to_widest (off)))
3548 off = TREE_OPERAND (rhs1, 1);
3549 else
3550 /* This case is not useful. See if get_addr_stridx
3551 returns something usable. */
3552 idx = 0;
3555 if (idx <= 0)
3556 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3557 if (idx > 0)
3559 strinfo *si = get_strinfo (idx);
3560 if (si
3561 && si->nonzero_chars
3562 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3564 widest_int w1 = wi::to_widest (si->nonzero_chars);
3565 widest_int w2 = wi::to_widest (off) + coff;
3566 if (w1 == w2
3567 && si->full_string_p)
3569 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3571 fprintf (dump_file, "Optimizing: ");
3572 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3575 /* Reading the final '\0' character. */
3576 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3577 gimple_set_vuse (stmt, NULL_TREE);
3578 gimple_assign_set_rhs_from_tree (gsi, zero);
3579 *cleanup_eh
3580 |= maybe_clean_or_replace_eh_stmt (stmt,
3581 gsi_stmt (*gsi));
3582 stmt = gsi_stmt (*gsi);
3583 update_stmt (stmt);
3585 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3587 fprintf (dump_file, "into: ");
3588 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3591 else if (w1 > w2)
3593 /* Reading a character before the final '\0'
3594 character. Just set the value range to ~[0, 0]
3595 if we don't have anything better. */
3596 wide_int min, max;
3597 tree type = TREE_TYPE (lhs);
3598 enum value_range_type vr
3599 = get_range_info (lhs, &min, &max);
3600 if (vr == VR_VARYING
3601 || (vr == VR_RANGE
3602 && min == wi::min_value (TYPE_PRECISION (type),
3603 TYPE_SIGN (type))
3604 && max == wi::max_value (TYPE_PRECISION (type),
3605 TYPE_SIGN (type))))
3606 set_range_info (lhs, VR_ANTI_RANGE,
3607 wi::zero (TYPE_PRECISION (type)),
3608 wi::zero (TYPE_PRECISION (type)));
3614 if (strlen_to_stridx)
3616 tree rhs1 = gimple_assign_rhs1 (stmt);
3617 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3618 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3621 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3623 tree type = TREE_TYPE (lhs);
3624 if (TREE_CODE (type) == ARRAY_TYPE)
3625 type = TREE_TYPE (type);
3626 if (TREE_CODE (type) == INTEGER_TYPE
3627 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3628 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3630 if (! handle_char_store (gsi))
3631 return false;
3635 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3637 enum tree_code code = gimple_cond_code (cond);
3638 if (code == EQ_EXPR || code == NE_EXPR)
3639 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3640 gimple_cond_rhs (stmt), stmt);
3643 if (gimple_vdef (stmt))
3644 maybe_invalidate (stmt);
3645 return true;
3648 /* Recursively call maybe_invalidate on stmts that might be executed
3649 in between dombb and current bb and that contain a vdef. Stop when
3650 *count stmts are inspected, or if the whole strinfo vector has
3651 been invalidated. */
3653 static void
3654 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3656 unsigned int i, n = gimple_phi_num_args (phi);
3658 for (i = 0; i < n; i++)
3660 tree vuse = gimple_phi_arg_def (phi, i);
3661 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3662 basic_block bb = gimple_bb (stmt);
3663 if (bb == NULL
3664 || bb == dombb
3665 || !bitmap_set_bit (visited, bb->index)
3666 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3667 continue;
3668 while (1)
3670 if (gimple_code (stmt) == GIMPLE_PHI)
3672 do_invalidate (dombb, stmt, visited, count);
3673 if (*count == 0)
3674 return;
3675 break;
3677 if (--*count == 0)
3678 return;
3679 if (!maybe_invalidate (stmt))
3681 *count = 0;
3682 return;
3684 vuse = gimple_vuse (stmt);
3685 stmt = SSA_NAME_DEF_STMT (vuse);
3686 if (gimple_bb (stmt) != bb)
3688 bb = gimple_bb (stmt);
3689 if (bb == NULL
3690 || bb == dombb
3691 || !bitmap_set_bit (visited, bb->index)
3692 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3693 break;
3699 class strlen_dom_walker : public dom_walker
3701 public:
3702 strlen_dom_walker (cdi_direction direction)
3703 : dom_walker (direction), m_cleanup_cfg (false)
3706 virtual edge before_dom_children (basic_block);
3707 virtual void after_dom_children (basic_block);
3709 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3710 execute function. */
3711 bool m_cleanup_cfg;
3714 /* Callback for walk_dominator_tree. Attempt to optimize various
3715 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3717 edge
3718 strlen_dom_walker::before_dom_children (basic_block bb)
3720 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3722 if (dombb == NULL)
3723 stridx_to_strinfo = NULL;
3724 else
3726 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3727 if (stridx_to_strinfo)
3729 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3730 gsi_next (&gsi))
3732 gphi *phi = gsi.phi ();
3733 if (virtual_operand_p (gimple_phi_result (phi)))
3735 bitmap visited = BITMAP_ALLOC (NULL);
3736 int count_vdef = 100;
3737 do_invalidate (dombb, phi, visited, &count_vdef);
3738 BITMAP_FREE (visited);
3739 if (count_vdef == 0)
3741 /* If there were too many vdefs in between immediate
3742 dominator and current bb, invalidate everything.
3743 If stridx_to_strinfo has been unshared, we need
3744 to free it, otherwise just set it to NULL. */
3745 if (!strinfo_shared ())
3747 unsigned int i;
3748 strinfo *si;
3750 for (i = 1;
3751 vec_safe_iterate (stridx_to_strinfo, i, &si);
3752 ++i)
3754 free_strinfo (si);
3755 (*stridx_to_strinfo)[i] = NULL;
3758 else
3759 stridx_to_strinfo = NULL;
3761 break;
3767 /* If all PHI arguments have the same string index, the PHI result
3768 has it as well. */
3769 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3770 gsi_next (&gsi))
3772 gphi *phi = gsi.phi ();
3773 tree result = gimple_phi_result (phi);
3774 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3776 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3777 if (idx != 0)
3779 unsigned int i, n = gimple_phi_num_args (phi);
3780 for (i = 1; i < n; i++)
3781 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3782 break;
3783 if (i == n)
3784 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3789 bool cleanup_eh = false;
3791 /* Attempt to optimize individual statements. */
3792 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3793 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
3794 gsi_next (&gsi);
3796 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
3797 m_cleanup_cfg = true;
3799 bb->aux = stridx_to_strinfo;
3800 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3801 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3802 return NULL;
3805 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3806 owned by the current bb, clear bb->aux. */
3808 void
3809 strlen_dom_walker::after_dom_children (basic_block bb)
3811 if (bb->aux)
3813 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3814 if (vec_safe_length (stridx_to_strinfo)
3815 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3817 unsigned int i;
3818 strinfo *si;
3820 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3821 free_strinfo (si);
3822 vec_free (stridx_to_strinfo);
3824 bb->aux = NULL;
3828 /* Main entry point. */
3830 namespace {
3832 const pass_data pass_data_strlen =
3834 GIMPLE_PASS, /* type */
3835 "strlen", /* name */
3836 OPTGROUP_NONE, /* optinfo_flags */
3837 TV_TREE_STRLEN, /* tv_id */
3838 ( PROP_cfg | PROP_ssa ), /* properties_required */
3839 0, /* properties_provided */
3840 0, /* properties_destroyed */
3841 0, /* todo_flags_start */
3842 0, /* todo_flags_finish */
3845 class pass_strlen : public gimple_opt_pass
3847 public:
3848 pass_strlen (gcc::context *ctxt)
3849 : gimple_opt_pass (pass_data_strlen, ctxt)
3852 /* opt_pass methods: */
3853 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3854 virtual unsigned int execute (function *);
3856 }; // class pass_strlen
3858 unsigned int
3859 pass_strlen::execute (function *fun)
3861 gcc_assert (!strlen_to_stridx);
3862 if (warn_stringop_overflow || warn_stringop_truncation)
3863 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3865 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3866 max_stridx = 1;
3868 calculate_dominance_info (CDI_DOMINATORS);
3870 /* String length optimization is implemented as a walk of the dominator
3871 tree and a forward walk of statements within each block. */
3872 strlen_dom_walker walker (CDI_DOMINATORS);
3873 walker.walk (fun->cfg->x_entry_block_ptr);
3875 ssa_ver_to_stridx.release ();
3876 strinfo_pool.release ();
3877 if (decl_to_stridxlist_htab)
3879 obstack_free (&stridx_obstack, NULL);
3880 delete decl_to_stridxlist_htab;
3881 decl_to_stridxlist_htab = NULL;
3883 laststmt.stmt = NULL;
3884 laststmt.len = NULL_TREE;
3885 laststmt.stridx = 0;
3887 if (strlen_to_stridx)
3889 strlen_to_stridx->empty ();
3890 delete strlen_to_stridx;
3891 strlen_to_stridx = NULL;
3894 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
3897 } // anon namespace
3899 gimple_opt_pass *
3900 make_pass_strlen (gcc::context *ctxt)
3902 return new pass_strlen (ctxt);