PR ada/66205
[official-gcc.git] / gcc / tree-ssa-strlen.c
blob48b92417b57411d5f91e1ed751005d927ece4ea5
1 /* String length optimization
2 Copyright (C) 2011-2017 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 "fold-const.h"
34 #include "stor-layout.h"
35 #include "gimple-fold.h"
36 #include "tree-eh.h"
37 #include "gimplify.h"
38 #include "gimple-iterator.h"
39 #include "gimplify-me.h"
40 #include "expr.h"
41 #include "tree-dfa.h"
42 #include "domwalk.h"
43 #include "tree-ssa-alias.h"
44 #include "tree-ssa-propagate.h"
45 #include "params.h"
46 #include "ipa-chkp.h"
47 #include "tree-hash-traits.h"
48 #include "builtins.h"
49 #include "target.h"
50 #include "diagnostic-core.h"
51 #include "diagnostic.h"
52 #include "intl.h"
53 #include "attribs.h"
54 #include "calls.h"
56 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
57 is an index into strinfo vector, negative value stands for
58 string length of a string literal (~strlen). */
59 static vec<int> ssa_ver_to_stridx;
61 /* Number of currently active string indexes plus one. */
62 static int max_stridx;
64 /* String information record. */
65 struct strinfo
67 /* Number of leading characters that are known to be nonzero. This is
68 also the length of the string if FULL_STRING_P.
70 The values in a list of related string pointers must be consistent;
71 that is, if strinfo B comes X bytes after strinfo A, it must be
72 the case that A->nonzero_chars == X + B->nonzero_chars. */
73 tree nonzero_chars;
74 /* Any of the corresponding pointers for querying alias oracle. */
75 tree ptr;
76 /* This is used for two things:
78 - To record the statement that should be used for delayed length
79 computations. We maintain the invariant that all related strinfos
80 have delayed lengths or none do.
82 - To record the malloc or calloc call that produced this result. */
83 gimple *stmt;
84 /* Pointer to '\0' if known, if NULL, it can be computed as
85 ptr + length. */
86 tree endptr;
87 /* Reference count. Any changes to strinfo entry possibly shared
88 with dominating basic blocks need unshare_strinfo first, except
89 for dont_invalidate which affects only the immediately next
90 maybe_invalidate. */
91 int refcount;
92 /* Copy of index. get_strinfo (si->idx) should return si; */
93 int idx;
94 /* These 3 fields are for chaining related string pointers together.
95 E.g. for
96 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
97 strcpy (c, d); e = c + dl;
98 strinfo(a) -> strinfo(c) -> strinfo(e)
99 All have ->first field equal to strinfo(a)->idx and are doubly
100 chained through prev/next fields. The later strinfos are required
101 to point into the same string with zero or more bytes after
102 the previous pointer and all bytes in between the two pointers
103 must be non-zero. Functions like strcpy or memcpy are supposed
104 to adjust all previous strinfo lengths, but not following strinfo
105 lengths (those are uncertain, usually invalidated during
106 maybe_invalidate, except when the alias oracle knows better).
107 Functions like strcat on the other side adjust the whole
108 related strinfo chain.
109 They are updated lazily, so to use the chain the same first fields
110 and si->prev->next == si->idx needs to be verified. */
111 int first;
112 int next;
113 int prev;
114 /* A flag whether the string is known to be written in the current
115 function. */
116 bool writable;
117 /* A flag for the next maybe_invalidate that this strinfo shouldn't
118 be invalidated. Always cleared by maybe_invalidate. */
119 bool dont_invalidate;
120 /* True if the string is known to be nul-terminated after NONZERO_CHARS
121 characters. False is useful when detecting strings that are built
122 up via successive memcpys. */
123 bool full_string_p;
126 /* Pool for allocating strinfo_struct entries. */
127 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
129 /* Vector mapping positive string indexes to strinfo, for the
130 current basic block. The first pointer in the vector is special,
131 it is either NULL, meaning the vector isn't shared, or it is
132 a basic block pointer to the owner basic_block if shared.
133 If some other bb wants to modify the vector, the vector needs
134 to be unshared first, and only the owner bb is supposed to free it. */
135 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
137 /* One OFFSET->IDX mapping. */
138 struct stridxlist
140 struct stridxlist *next;
141 HOST_WIDE_INT offset;
142 int idx;
145 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
146 struct decl_stridxlist_map
148 struct tree_map_base base;
149 struct stridxlist list;
152 /* Hash table for mapping decls to a chained list of offset -> idx
153 mappings. */
154 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
156 /* Hash table mapping strlen calls to stridx instances describing
157 the calls' arguments. Non-null only when warn_stringop_truncation
158 is non-zero. */
159 typedef std::pair<int, location_t> stridx_strlenloc;
160 static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
162 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
163 static struct obstack stridx_obstack;
165 /* Last memcpy statement if it could be adjusted if the trailing
166 '\0' written is immediately overwritten, or
167 *x = '\0' store that could be removed if it is immediately overwritten. */
168 struct laststmt_struct
170 gimple *stmt;
171 tree len;
172 int stridx;
173 } laststmt;
175 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
177 /* Return:
179 - 1 if SI is known to start with more than OFF nonzero characters.
181 - 0 if SI is known to start with OFF nonzero characters,
182 but is not known to start with more.
184 - -1 if SI might not start with OFF nonzero characters. */
186 static inline int
187 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
189 if (si->nonzero_chars
190 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
191 return compare_tree_int (si->nonzero_chars, off);
192 else
193 return -1;
196 /* Return true if SI is known to be a zero-length string. */
198 static inline bool
199 zero_length_string_p (strinfo *si)
201 return si->full_string_p && integer_zerop (si->nonzero_chars);
204 /* Return strinfo vector entry IDX. */
206 static inline strinfo *
207 get_strinfo (int idx)
209 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
210 return NULL;
211 return (*stridx_to_strinfo)[idx];
214 /* Get the next strinfo in the chain after SI, or null if none. */
216 static inline strinfo *
217 get_next_strinfo (strinfo *si)
219 if (si->next == 0)
220 return NULL;
221 strinfo *nextsi = get_strinfo (si->next);
222 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
223 return NULL;
224 return nextsi;
227 /* Helper function for get_stridx. Return the strinfo index of the address
228 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
229 OK to return the index for some X <= &EXP and store &EXP - X in
230 *OFFSET_OUT. */
232 static int
233 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
235 HOST_WIDE_INT off;
236 struct stridxlist *list, *last = NULL;
237 tree base;
239 if (!decl_to_stridxlist_htab)
240 return 0;
242 base = get_addr_base_and_unit_offset (exp, &off);
243 if (base == NULL || !DECL_P (base))
244 return 0;
246 list = decl_to_stridxlist_htab->get (base);
247 if (list == NULL)
248 return 0;
252 if (list->offset == off)
254 if (offset_out)
255 *offset_out = 0;
256 return list->idx;
258 if (list->offset > off)
259 return 0;
260 last = list;
261 list = list->next;
263 while (list);
265 if ((offset_out || ptr) && last && last->idx > 0)
267 unsigned HOST_WIDE_INT rel_off
268 = (unsigned HOST_WIDE_INT) off - last->offset;
269 strinfo *si = get_strinfo (last->idx);
270 if (si && compare_nonzero_chars (si, rel_off) >= 0)
272 if (offset_out)
274 *offset_out = rel_off;
275 return last->idx;
277 else
278 return get_stridx_plus_constant (si, rel_off, ptr);
281 return 0;
284 /* Return string index for EXP. */
286 static int
287 get_stridx (tree exp)
289 tree s, o;
291 if (TREE_CODE (exp) == SSA_NAME)
293 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
294 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
295 int i;
296 tree e = exp;
297 HOST_WIDE_INT off = 0;
298 for (i = 0; i < 5; i++)
300 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
301 if (!is_gimple_assign (def_stmt)
302 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
303 return 0;
304 tree rhs1 = gimple_assign_rhs1 (def_stmt);
305 tree rhs2 = gimple_assign_rhs2 (def_stmt);
306 if (TREE_CODE (rhs1) != SSA_NAME
307 || !tree_fits_shwi_p (rhs2))
308 return 0;
309 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
310 if (this_off < 0)
311 return 0;
312 off = (unsigned HOST_WIDE_INT) off + this_off;
313 if (off < 0)
314 return 0;
315 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
317 strinfo *si
318 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
319 if (si && compare_nonzero_chars (si, off) >= 0)
320 return get_stridx_plus_constant (si, off, exp);
322 e = rhs1;
324 return 0;
327 if (TREE_CODE (exp) == ADDR_EXPR)
329 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
330 if (idx != 0)
331 return idx;
334 s = string_constant (exp, &o);
335 if (s != NULL_TREE
336 && (o == NULL_TREE || tree_fits_shwi_p (o))
337 && TREE_STRING_LENGTH (s) > 0)
339 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
340 const char *p = TREE_STRING_POINTER (s);
341 int max = TREE_STRING_LENGTH (s) - 1;
343 if (p[max] == '\0' && offset >= 0 && offset <= max)
344 return ~(int) strlen (p + offset);
346 return 0;
349 /* Return true if strinfo vector is shared with the immediate dominator. */
351 static inline bool
352 strinfo_shared (void)
354 return vec_safe_length (stridx_to_strinfo)
355 && (*stridx_to_strinfo)[0] != NULL;
358 /* Unshare strinfo vector that is shared with the immediate dominator. */
360 static void
361 unshare_strinfo_vec (void)
363 strinfo *si;
364 unsigned int i = 0;
366 gcc_assert (strinfo_shared ());
367 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
368 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
369 if (si != NULL)
370 si->refcount++;
371 (*stridx_to_strinfo)[0] = NULL;
374 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
375 Return a pointer to the location where the string index can
376 be stored (if 0) or is stored, or NULL if this can't be tracked. */
378 static int *
379 addr_stridxptr (tree exp)
381 HOST_WIDE_INT off;
383 tree base = get_addr_base_and_unit_offset (exp, &off);
384 if (base == NULL_TREE || !DECL_P (base))
385 return NULL;
387 if (!decl_to_stridxlist_htab)
389 decl_to_stridxlist_htab
390 = new hash_map<tree_decl_hash, stridxlist> (64);
391 gcc_obstack_init (&stridx_obstack);
394 bool existed;
395 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
396 if (existed)
398 int i;
399 stridxlist *before = NULL;
400 for (i = 0; i < 32; i++)
402 if (list->offset == off)
403 return &list->idx;
404 if (list->offset > off && before == NULL)
405 before = list;
406 if (list->next == NULL)
407 break;
408 list = list->next;
410 if (i == 32)
411 return NULL;
412 if (before)
414 list = before;
415 before = XOBNEW (&stridx_obstack, struct stridxlist);
416 *before = *list;
417 list->next = before;
418 list->offset = off;
419 list->idx = 0;
420 return &list->idx;
422 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
423 list = list->next;
426 list->next = NULL;
427 list->offset = off;
428 list->idx = 0;
429 return &list->idx;
432 /* Create a new string index, or return 0 if reached limit. */
434 static int
435 new_stridx (tree exp)
437 int idx;
438 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
439 return 0;
440 if (TREE_CODE (exp) == SSA_NAME)
442 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
443 return 0;
444 idx = max_stridx++;
445 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
446 return idx;
448 if (TREE_CODE (exp) == ADDR_EXPR)
450 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
451 if (pidx != NULL)
453 gcc_assert (*pidx == 0);
454 *pidx = max_stridx++;
455 return *pidx;
458 return 0;
461 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
463 static int
464 new_addr_stridx (tree exp)
466 int *pidx;
467 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
468 return 0;
469 pidx = addr_stridxptr (exp);
470 if (pidx != NULL)
472 gcc_assert (*pidx == 0);
473 *pidx = max_stridx++;
474 return *pidx;
476 return 0;
479 /* Create a new strinfo. */
481 static strinfo *
482 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
484 strinfo *si = strinfo_pool.allocate ();
485 si->nonzero_chars = nonzero_chars;
486 si->ptr = ptr;
487 si->stmt = NULL;
488 si->endptr = NULL_TREE;
489 si->refcount = 1;
490 si->idx = idx;
491 si->first = 0;
492 si->prev = 0;
493 si->next = 0;
494 si->writable = false;
495 si->dont_invalidate = false;
496 si->full_string_p = full_string_p;
497 return si;
500 /* Decrease strinfo refcount and free it if not referenced anymore. */
502 static inline void
503 free_strinfo (strinfo *si)
505 if (si && --si->refcount == 0)
506 strinfo_pool.remove (si);
509 /* Set strinfo in the vector entry IDX to SI. */
511 static inline void
512 set_strinfo (int idx, strinfo *si)
514 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
515 unshare_strinfo_vec ();
516 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
517 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
518 (*stridx_to_strinfo)[idx] = si;
521 /* Return the first strinfo in the related strinfo chain
522 if all strinfos in between belong to the chain, otherwise NULL. */
524 static strinfo *
525 verify_related_strinfos (strinfo *origsi)
527 strinfo *si = origsi, *psi;
529 if (origsi->first == 0)
530 return NULL;
531 for (; si->prev; si = psi)
533 if (si->first != origsi->first)
534 return NULL;
535 psi = get_strinfo (si->prev);
536 if (psi == NULL)
537 return NULL;
538 if (psi->next != si->idx)
539 return NULL;
541 if (si->idx != si->first)
542 return NULL;
543 return si;
546 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
547 Use LOC for folding. */
549 static void
550 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
552 si->endptr = endptr;
553 si->stmt = NULL;
554 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
555 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
556 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
557 end_as_size, start_as_size);
558 si->full_string_p = true;
561 /* Return string length, or NULL if it can't be computed. */
563 static tree
564 get_string_length (strinfo *si)
566 if (si->nonzero_chars)
567 return si->full_string_p ? si->nonzero_chars : NULL;
569 if (si->stmt)
571 gimple *stmt = si->stmt, *lenstmt;
572 bool with_bounds = gimple_call_with_bounds_p (stmt);
573 tree callee, lhs, fn, tem;
574 location_t loc;
575 gimple_stmt_iterator gsi;
577 gcc_assert (is_gimple_call (stmt));
578 callee = gimple_call_fndecl (stmt);
579 gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
580 lhs = gimple_call_lhs (stmt);
581 /* unshare_strinfo is intentionally not called here. The (delayed)
582 transformation of strcpy or strcat into stpcpy is done at the place
583 of the former strcpy/strcat call and so can affect all the strinfos
584 with the same stmt. If they were unshared before and transformation
585 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
586 just compute the right length. */
587 switch (DECL_FUNCTION_CODE (callee))
589 case BUILT_IN_STRCAT:
590 case BUILT_IN_STRCAT_CHK:
591 case BUILT_IN_STRCAT_CHKP:
592 case BUILT_IN_STRCAT_CHK_CHKP:
593 gsi = gsi_for_stmt (stmt);
594 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
595 gcc_assert (lhs == NULL_TREE);
596 tem = unshare_expr (gimple_call_arg (stmt, 0));
597 if (with_bounds)
599 lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl,
600 2, tem, gimple_call_arg (stmt, 1));
601 gimple_call_set_with_bounds (lenstmt, true);
603 else
604 lenstmt = gimple_build_call (fn, 1, tem);
605 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
606 gimple_call_set_lhs (lenstmt, lhs);
607 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
608 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
609 tem = gimple_call_arg (stmt, 0);
610 if (!ptrofftype_p (TREE_TYPE (lhs)))
612 lhs = convert_to_ptrofftype (lhs);
613 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
614 true, GSI_SAME_STMT);
616 lenstmt = gimple_build_assign
617 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
618 POINTER_PLUS_EXPR,tem, lhs);
619 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
620 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
621 lhs = NULL_TREE;
622 /* FALLTHRU */
623 case BUILT_IN_STRCPY:
624 case BUILT_IN_STRCPY_CHK:
625 case BUILT_IN_STRCPY_CHKP:
626 case BUILT_IN_STRCPY_CHK_CHKP:
627 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
628 if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2))
629 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
630 else
631 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
632 if (with_bounds)
633 fn = chkp_maybe_create_clone (fn)->decl;
634 gcc_assert (lhs == NULL_TREE);
635 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
637 fprintf (dump_file, "Optimizing: ");
638 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
640 gimple_call_set_fndecl (stmt, fn);
641 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
642 gimple_call_set_lhs (stmt, lhs);
643 update_stmt (stmt);
644 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
646 fprintf (dump_file, "into: ");
647 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
649 /* FALLTHRU */
650 case BUILT_IN_STPCPY:
651 case BUILT_IN_STPCPY_CHK:
652 case BUILT_IN_STPCPY_CHKP:
653 case BUILT_IN_STPCPY_CHK_CHKP:
654 gcc_assert (lhs != NULL_TREE);
655 loc = gimple_location (stmt);
656 set_endptr_and_length (loc, si, lhs);
657 for (strinfo *chainsi = verify_related_strinfos (si);
658 chainsi != NULL;
659 chainsi = get_next_strinfo (chainsi))
660 if (chainsi->nonzero_chars == NULL)
661 set_endptr_and_length (loc, chainsi, lhs);
662 break;
663 case BUILT_IN_MALLOC:
664 break;
665 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
666 default:
667 gcc_unreachable ();
668 break;
672 return si->nonzero_chars;
675 /* Invalidate string length information for strings whose length
676 might change due to stores in stmt. */
678 static bool
679 maybe_invalidate (gimple *stmt)
681 strinfo *si;
682 unsigned int i;
683 bool nonempty = false;
685 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
686 if (si != NULL)
688 if (!si->dont_invalidate)
690 ao_ref r;
691 /* Do not use si->nonzero_chars. */
692 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
693 if (stmt_may_clobber_ref_p_1 (stmt, &r))
695 set_strinfo (i, NULL);
696 free_strinfo (si);
697 continue;
700 si->dont_invalidate = false;
701 nonempty = true;
703 return nonempty;
706 /* Unshare strinfo record SI, if it has refcount > 1 or
707 if stridx_to_strinfo vector is shared with some other
708 bbs. */
710 static strinfo *
711 unshare_strinfo (strinfo *si)
713 strinfo *nsi;
715 if (si->refcount == 1 && !strinfo_shared ())
716 return si;
718 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
719 nsi->stmt = si->stmt;
720 nsi->endptr = si->endptr;
721 nsi->first = si->first;
722 nsi->prev = si->prev;
723 nsi->next = si->next;
724 nsi->writable = si->writable;
725 set_strinfo (si->idx, nsi);
726 free_strinfo (si);
727 return nsi;
730 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
731 strinfo if there is any. Return it's idx, or 0 if no strinfo has
732 been created. */
734 static int
735 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
736 tree ptr)
738 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
739 return 0;
741 if (compare_nonzero_chars (basesi, off) < 0
742 || !tree_fits_uhwi_p (basesi->nonzero_chars))
743 return 0;
745 unsigned HOST_WIDE_INT nonzero_chars
746 = tree_to_uhwi (basesi->nonzero_chars) - off;
747 strinfo *si = basesi, *chainsi;
748 if (si->first || si->prev || si->next)
749 si = verify_related_strinfos (basesi);
750 if (si == NULL
751 || si->nonzero_chars == NULL_TREE
752 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
753 return 0;
755 if (TREE_CODE (ptr) == SSA_NAME
756 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
757 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
759 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
760 for (chainsi = si; chainsi->next; chainsi = si)
762 si = get_next_strinfo (chainsi);
763 if (si == NULL
764 || si->nonzero_chars == NULL_TREE
765 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
766 break;
767 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
768 if (r != 1)
770 if (r == 0)
772 if (TREE_CODE (ptr) == SSA_NAME)
773 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
774 else
776 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
777 if (pidx != NULL && *pidx == 0)
778 *pidx = si->idx;
780 return si->idx;
782 break;
786 int idx = new_stridx (ptr);
787 if (idx == 0)
788 return 0;
789 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
790 basesi->full_string_p);
791 set_strinfo (idx, si);
792 if (chainsi->next)
794 strinfo *nextsi = unshare_strinfo (get_strinfo (chainsi->next));
795 si->next = nextsi->idx;
796 nextsi->prev = idx;
798 chainsi = unshare_strinfo (chainsi);
799 if (chainsi->first == 0)
800 chainsi->first = chainsi->idx;
801 chainsi->next = idx;
802 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
803 chainsi->endptr = ptr;
804 si->endptr = chainsi->endptr;
805 si->prev = chainsi->idx;
806 si->first = chainsi->first;
807 si->writable = chainsi->writable;
808 return si->idx;
811 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
812 to a zero-length string and if possible chain it to a related strinfo
813 chain whose part is or might be CHAINSI. */
815 static strinfo *
816 zero_length_string (tree ptr, strinfo *chainsi)
818 strinfo *si;
819 int idx;
820 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
821 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
822 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
823 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
825 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
826 return NULL;
827 if (chainsi != NULL)
829 si = verify_related_strinfos (chainsi);
830 if (si)
834 /* We shouldn't mix delayed and non-delayed lengths. */
835 gcc_assert (si->full_string_p);
836 if (si->endptr == NULL_TREE)
838 si = unshare_strinfo (si);
839 si->endptr = ptr;
841 chainsi = si;
842 si = get_next_strinfo (si);
844 while (si != NULL);
845 if (zero_length_string_p (chainsi))
847 if (chainsi->next)
849 chainsi = unshare_strinfo (chainsi);
850 chainsi->next = 0;
852 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
853 return chainsi;
856 else
858 /* We shouldn't mix delayed and non-delayed lengths. */
859 gcc_assert (chainsi->full_string_p);
860 if (chainsi->first || chainsi->prev || chainsi->next)
862 chainsi = unshare_strinfo (chainsi);
863 chainsi->first = 0;
864 chainsi->prev = 0;
865 chainsi->next = 0;
869 idx = new_stridx (ptr);
870 if (idx == 0)
871 return NULL;
872 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
873 set_strinfo (idx, si);
874 si->endptr = ptr;
875 if (chainsi != NULL)
877 chainsi = unshare_strinfo (chainsi);
878 if (chainsi->first == 0)
879 chainsi->first = chainsi->idx;
880 chainsi->next = idx;
881 if (chainsi->endptr == NULL_TREE)
882 chainsi->endptr = ptr;
883 si->prev = chainsi->idx;
884 si->first = chainsi->first;
885 si->writable = chainsi->writable;
887 return si;
890 /* For strinfo ORIGSI whose length has been just updated, adjust other
891 related strinfos so that they match the new ORIGSI. This involves:
893 - adding ADJ to the nonzero_chars fields
894 - copying full_string_p from the new ORIGSI. */
896 static void
897 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
899 strinfo *si = verify_related_strinfos (origsi);
901 if (si == NULL)
902 return;
904 while (1)
906 strinfo *nsi;
908 if (si != origsi)
910 tree tem;
912 si = unshare_strinfo (si);
913 /* We shouldn't see delayed lengths here; the caller must have
914 calculated the old length in order to calculate the
915 adjustment. */
916 gcc_assert (si->nonzero_chars);
917 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
918 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
919 TREE_TYPE (si->nonzero_chars),
920 si->nonzero_chars, tem);
921 si->full_string_p = origsi->full_string_p;
923 si->endptr = NULL_TREE;
924 si->dont_invalidate = true;
926 nsi = get_next_strinfo (si);
927 if (nsi == NULL)
928 return;
929 si = nsi;
933 /* Find if there are other SSA_NAME pointers equal to PTR
934 for which we don't track their string lengths yet. If so, use
935 IDX for them. */
937 static void
938 find_equal_ptrs (tree ptr, int idx)
940 if (TREE_CODE (ptr) != SSA_NAME)
941 return;
942 while (1)
944 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
945 if (!is_gimple_assign (stmt))
946 return;
947 ptr = gimple_assign_rhs1 (stmt);
948 switch (gimple_assign_rhs_code (stmt))
950 case SSA_NAME:
951 break;
952 CASE_CONVERT:
953 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
954 return;
955 if (TREE_CODE (ptr) == SSA_NAME)
956 break;
957 if (TREE_CODE (ptr) != ADDR_EXPR)
958 return;
959 /* FALLTHRU */
960 case ADDR_EXPR:
962 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
963 if (pidx != NULL && *pidx == 0)
964 *pidx = idx;
965 return;
967 default:
968 return;
971 /* We might find an endptr created in this pass. Grow the
972 vector in that case. */
973 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
974 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
976 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
977 return;
978 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
982 /* Return true if STMT is a call to a builtin function with the right
983 arguments and attributes that should be considered for optimization
984 by this pass. */
986 static bool
987 valid_builtin_call (gimple *stmt)
989 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
990 return false;
992 tree callee = gimple_call_fndecl (stmt);
993 switch (DECL_FUNCTION_CODE (callee))
995 case BUILT_IN_MEMCMP:
996 case BUILT_IN_MEMCMP_EQ:
997 case BUILT_IN_STRCHR:
998 case BUILT_IN_STRCHR_CHKP:
999 case BUILT_IN_STRLEN:
1000 case BUILT_IN_STRLEN_CHKP:
1001 /* The above functions should be pure. Punt if they aren't. */
1002 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
1003 return false;
1004 break;
1006 case BUILT_IN_CALLOC:
1007 case BUILT_IN_MALLOC:
1008 case BUILT_IN_MEMCPY:
1009 case BUILT_IN_MEMCPY_CHK:
1010 case BUILT_IN_MEMCPY_CHKP:
1011 case BUILT_IN_MEMCPY_CHK_CHKP:
1012 case BUILT_IN_MEMPCPY:
1013 case BUILT_IN_MEMPCPY_CHK:
1014 case BUILT_IN_MEMPCPY_CHKP:
1015 case BUILT_IN_MEMPCPY_CHK_CHKP:
1016 case BUILT_IN_MEMSET:
1017 case BUILT_IN_STPCPY:
1018 case BUILT_IN_STPCPY_CHK:
1019 case BUILT_IN_STPCPY_CHKP:
1020 case BUILT_IN_STPCPY_CHK_CHKP:
1021 case BUILT_IN_STRCAT:
1022 case BUILT_IN_STRCAT_CHK:
1023 case BUILT_IN_STRCAT_CHKP:
1024 case BUILT_IN_STRCAT_CHK_CHKP:
1025 case BUILT_IN_STRCPY:
1026 case BUILT_IN_STRCPY_CHK:
1027 case BUILT_IN_STRCPY_CHKP:
1028 case BUILT_IN_STRCPY_CHK_CHKP:
1029 /* The above functions should be neither const nor pure. Punt if they
1030 aren't. */
1031 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1032 return false;
1033 break;
1035 default:
1036 break;
1039 return true;
1042 /* If the last .MEM setter statement before STMT is
1043 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1044 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1045 just memcpy (x, y, strlen (y)). SI must be the zero length
1046 strinfo. */
1048 static void
1049 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1051 tree vuse, callee, len;
1052 struct laststmt_struct last = laststmt;
1053 strinfo *lastsi, *firstsi;
1054 unsigned len_arg_no = 2;
1056 laststmt.stmt = NULL;
1057 laststmt.len = NULL_TREE;
1058 laststmt.stridx = 0;
1060 if (last.stmt == NULL)
1061 return;
1063 vuse = gimple_vuse (stmt);
1064 if (vuse == NULL_TREE
1065 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1066 || !has_single_use (vuse))
1067 return;
1069 gcc_assert (last.stridx > 0);
1070 lastsi = get_strinfo (last.stridx);
1071 if (lastsi == NULL)
1072 return;
1074 if (lastsi != si)
1076 if (lastsi->first == 0 || lastsi->first != si->first)
1077 return;
1079 firstsi = verify_related_strinfos (si);
1080 if (firstsi == NULL)
1081 return;
1082 while (firstsi != lastsi)
1084 firstsi = get_next_strinfo (firstsi);
1085 if (firstsi == NULL)
1086 return;
1090 if (!is_strcat && !zero_length_string_p (si))
1091 return;
1093 if (is_gimple_assign (last.stmt))
1095 gimple_stmt_iterator gsi;
1097 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1098 return;
1099 if (stmt_could_throw_p (last.stmt))
1100 return;
1101 gsi = gsi_for_stmt (last.stmt);
1102 unlink_stmt_vdef (last.stmt);
1103 release_defs (last.stmt);
1104 gsi_remove (&gsi, true);
1105 return;
1108 if (!valid_builtin_call (last.stmt))
1109 return;
1111 callee = gimple_call_fndecl (last.stmt);
1112 switch (DECL_FUNCTION_CODE (callee))
1114 case BUILT_IN_MEMCPY:
1115 case BUILT_IN_MEMCPY_CHK:
1116 break;
1117 case BUILT_IN_MEMCPY_CHKP:
1118 case BUILT_IN_MEMCPY_CHK_CHKP:
1119 len_arg_no = 4;
1120 break;
1121 default:
1122 return;
1125 len = gimple_call_arg (last.stmt, len_arg_no);
1126 if (tree_fits_uhwi_p (len))
1128 if (!tree_fits_uhwi_p (last.len)
1129 || integer_zerop (len)
1130 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1131 return;
1132 /* Don't adjust the length if it is divisible by 4, it is more efficient
1133 to store the extra '\0' in that case. */
1134 if ((tree_to_uhwi (len) & 3) == 0)
1135 return;
1137 else if (TREE_CODE (len) == SSA_NAME)
1139 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1140 if (!is_gimple_assign (def_stmt)
1141 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1142 || gimple_assign_rhs1 (def_stmt) != last.len
1143 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1144 return;
1146 else
1147 return;
1149 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1150 update_stmt (last.stmt);
1153 /* Handle a strlen call. If strlen of the argument is known, replace
1154 the strlen call with the known value, otherwise remember that strlen
1155 of the argument is stored in the lhs SSA_NAME. */
1157 static void
1158 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1160 int idx;
1161 tree src;
1162 gimple *stmt = gsi_stmt (*gsi);
1163 tree lhs = gimple_call_lhs (stmt);
1165 if (lhs == NULL_TREE)
1166 return;
1168 src = gimple_call_arg (stmt, 0);
1169 idx = get_stridx (src);
1170 if (idx)
1172 strinfo *si = NULL;
1173 tree rhs;
1175 if (idx < 0)
1176 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1177 else
1179 rhs = NULL_TREE;
1180 si = get_strinfo (idx);
1181 if (si != NULL)
1182 rhs = get_string_length (si);
1184 if (rhs != NULL_TREE)
1186 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1188 fprintf (dump_file, "Optimizing: ");
1189 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1191 rhs = unshare_expr (rhs);
1192 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1193 rhs = fold_convert_loc (gimple_location (stmt),
1194 TREE_TYPE (lhs), rhs);
1195 if (!update_call_from_tree (gsi, rhs))
1196 gimplify_and_update_call_from_tree (gsi, rhs);
1197 stmt = gsi_stmt (*gsi);
1198 update_stmt (stmt);
1199 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1201 fprintf (dump_file, "into: ");
1202 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1204 if (si != NULL
1205 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1206 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1207 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1209 si = unshare_strinfo (si);
1210 si->nonzero_chars = lhs;
1211 gcc_assert (si->full_string_p);
1214 if (strlen_to_stridx)
1216 location_t loc = gimple_location (stmt);
1217 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1219 return;
1222 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1223 return;
1224 if (idx == 0)
1225 idx = new_stridx (src);
1226 else
1228 strinfo *si = get_strinfo (idx);
1229 if (si != NULL)
1231 if (!si->full_string_p && !si->stmt)
1233 /* Until now we only had a lower bound on the string length.
1234 Install LHS as the actual length. */
1235 si = unshare_strinfo (si);
1236 tree old = si->nonzero_chars;
1237 si->nonzero_chars = lhs;
1238 si->full_string_p = true;
1239 if (TREE_CODE (old) == INTEGER_CST)
1241 location_t loc = gimple_location (stmt);
1242 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1243 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1244 TREE_TYPE (lhs), lhs, old);
1245 adjust_related_strinfos (loc, si, adj);
1247 else
1249 si->first = 0;
1250 si->prev = 0;
1251 si->next = 0;
1254 return;
1257 if (idx)
1259 strinfo *si = new_strinfo (src, idx, lhs, true);
1260 set_strinfo (idx, si);
1261 find_equal_ptrs (src, idx);
1263 if (strlen_to_stridx)
1265 location_t loc = gimple_location (stmt);
1266 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1271 /* Handle a strchr call. If strlen of the first argument is known, replace
1272 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1273 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1275 static void
1276 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1278 int idx;
1279 tree src;
1280 gimple *stmt = gsi_stmt (*gsi);
1281 tree lhs = gimple_call_lhs (stmt);
1282 bool with_bounds = gimple_call_with_bounds_p (stmt);
1284 if (lhs == NULL_TREE)
1285 return;
1287 if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1)))
1288 return;
1290 src = gimple_call_arg (stmt, 0);
1291 idx = get_stridx (src);
1292 if (idx)
1294 strinfo *si = NULL;
1295 tree rhs;
1297 if (idx < 0)
1298 rhs = build_int_cst (size_type_node, ~idx);
1299 else
1301 rhs = NULL_TREE;
1302 si = get_strinfo (idx);
1303 if (si != NULL)
1304 rhs = get_string_length (si);
1306 if (rhs != NULL_TREE)
1308 location_t loc = gimple_location (stmt);
1310 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1312 fprintf (dump_file, "Optimizing: ");
1313 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1315 if (si != NULL && si->endptr != NULL_TREE)
1317 rhs = unshare_expr (si->endptr);
1318 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1319 TREE_TYPE (rhs)))
1320 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1322 else
1324 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1325 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1326 TREE_TYPE (src), src, rhs);
1327 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1328 TREE_TYPE (rhs)))
1329 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1331 if (!update_call_from_tree (gsi, rhs))
1332 gimplify_and_update_call_from_tree (gsi, rhs);
1333 stmt = gsi_stmt (*gsi);
1334 update_stmt (stmt);
1335 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1337 fprintf (dump_file, "into: ");
1338 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1340 if (si != NULL
1341 && si->endptr == NULL_TREE
1342 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1344 si = unshare_strinfo (si);
1345 si->endptr = lhs;
1347 zero_length_string (lhs, si);
1348 return;
1351 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1352 return;
1353 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1355 if (idx == 0)
1356 idx = new_stridx (src);
1357 else if (get_strinfo (idx) != NULL)
1359 zero_length_string (lhs, NULL);
1360 return;
1362 if (idx)
1364 location_t loc = gimple_location (stmt);
1365 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1366 tree srcu = fold_convert_loc (loc, size_type_node, src);
1367 tree length = fold_build2_loc (loc, MINUS_EXPR,
1368 size_type_node, lhsu, srcu);
1369 strinfo *si = new_strinfo (src, idx, length, true);
1370 si->endptr = lhs;
1371 set_strinfo (idx, si);
1372 find_equal_ptrs (src, idx);
1373 zero_length_string (lhs, si);
1376 else
1377 zero_length_string (lhs, NULL);
1380 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1381 If strlen of the second argument is known, strlen of the first argument
1382 is the same after this call. Furthermore, attempt to convert it to
1383 memcpy. */
1385 static void
1386 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1388 int idx, didx;
1389 tree src, dst, srclen, len, lhs, args, type, fn, oldlen;
1390 bool success;
1391 gimple *stmt = gsi_stmt (*gsi);
1392 strinfo *si, *dsi, *olddsi, *zsi;
1393 location_t loc;
1394 bool with_bounds = gimple_call_with_bounds_p (stmt);
1396 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1397 dst = gimple_call_arg (stmt, 0);
1398 lhs = gimple_call_lhs (stmt);
1399 idx = get_stridx (src);
1400 si = NULL;
1401 if (idx > 0)
1402 si = get_strinfo (idx);
1404 didx = get_stridx (dst);
1405 olddsi = NULL;
1406 oldlen = NULL_TREE;
1407 if (didx > 0)
1408 olddsi = get_strinfo (didx);
1409 else if (didx < 0)
1410 return;
1412 if (olddsi != NULL)
1413 adjust_last_stmt (olddsi, stmt, false);
1415 srclen = NULL_TREE;
1416 if (si != NULL)
1417 srclen = get_string_length (si);
1418 else if (idx < 0)
1419 srclen = build_int_cst (size_type_node, ~idx);
1421 loc = gimple_location (stmt);
1422 if (srclen == NULL_TREE)
1423 switch (bcode)
1425 case BUILT_IN_STRCPY:
1426 case BUILT_IN_STRCPY_CHK:
1427 case BUILT_IN_STRCPY_CHKP:
1428 case BUILT_IN_STRCPY_CHK_CHKP:
1429 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1430 return;
1431 break;
1432 case BUILT_IN_STPCPY:
1433 case BUILT_IN_STPCPY_CHK:
1434 case BUILT_IN_STPCPY_CHKP:
1435 case BUILT_IN_STPCPY_CHK_CHKP:
1436 if (lhs == NULL_TREE)
1437 return;
1438 else
1440 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1441 srclen = fold_convert_loc (loc, size_type_node, dst);
1442 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1443 lhsuint, srclen);
1445 break;
1446 default:
1447 gcc_unreachable ();
1450 if (didx == 0)
1452 didx = new_stridx (dst);
1453 if (didx == 0)
1454 return;
1456 if (olddsi != NULL)
1458 oldlen = olddsi->nonzero_chars;
1459 dsi = unshare_strinfo (olddsi);
1460 dsi->nonzero_chars = srclen;
1461 dsi->full_string_p = (srclen != NULL_TREE);
1462 /* Break the chain, so adjust_related_strinfo on later pointers in
1463 the chain won't adjust this one anymore. */
1464 dsi->next = 0;
1465 dsi->stmt = NULL;
1466 dsi->endptr = NULL_TREE;
1468 else
1470 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1471 set_strinfo (didx, dsi);
1472 find_equal_ptrs (dst, didx);
1474 dsi->writable = true;
1475 dsi->dont_invalidate = true;
1477 if (dsi->nonzero_chars == NULL_TREE)
1479 strinfo *chainsi;
1481 /* If string length of src is unknown, use delayed length
1482 computation. If string lenth of dst will be needed, it
1483 can be computed by transforming this strcpy call into
1484 stpcpy and subtracting dst from the return value. */
1486 /* Look for earlier strings whose length could be determined if
1487 this strcpy is turned into an stpcpy. */
1489 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1491 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1493 /* When setting a stmt for delayed length computation
1494 prevent all strinfos through dsi from being
1495 invalidated. */
1496 chainsi = unshare_strinfo (chainsi);
1497 chainsi->stmt = stmt;
1498 chainsi->nonzero_chars = NULL_TREE;
1499 chainsi->full_string_p = false;
1500 chainsi->endptr = NULL_TREE;
1501 chainsi->dont_invalidate = true;
1504 dsi->stmt = stmt;
1505 return;
1508 if (olddsi != NULL)
1510 tree adj = NULL_TREE;
1511 if (oldlen == NULL_TREE)
1513 else if (integer_zerop (oldlen))
1514 adj = srclen;
1515 else if (TREE_CODE (oldlen) == INTEGER_CST
1516 || TREE_CODE (srclen) == INTEGER_CST)
1517 adj = fold_build2_loc (loc, MINUS_EXPR,
1518 TREE_TYPE (srclen), srclen,
1519 fold_convert_loc (loc, TREE_TYPE (srclen),
1520 oldlen));
1521 if (adj != NULL_TREE)
1522 adjust_related_strinfos (loc, dsi, adj);
1523 else
1524 dsi->prev = 0;
1526 /* strcpy src may not overlap dst, so src doesn't need to be
1527 invalidated either. */
1528 if (si != NULL)
1529 si->dont_invalidate = true;
1531 fn = NULL_TREE;
1532 zsi = NULL;
1533 switch (bcode)
1535 case BUILT_IN_STRCPY:
1536 case BUILT_IN_STRCPY_CHKP:
1537 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1538 if (lhs)
1539 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1540 break;
1541 case BUILT_IN_STRCPY_CHK:
1542 case BUILT_IN_STRCPY_CHK_CHKP:
1543 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1544 if (lhs)
1545 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1546 break;
1547 case BUILT_IN_STPCPY:
1548 case BUILT_IN_STPCPY_CHKP:
1549 /* This would need adjustment of the lhs (subtract one),
1550 or detection that the trailing '\0' doesn't need to be
1551 written, if it will be immediately overwritten.
1552 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1553 if (lhs)
1555 dsi->endptr = lhs;
1556 zsi = zero_length_string (lhs, dsi);
1558 break;
1559 case BUILT_IN_STPCPY_CHK:
1560 case BUILT_IN_STPCPY_CHK_CHKP:
1561 /* This would need adjustment of the lhs (subtract one),
1562 or detection that the trailing '\0' doesn't need to be
1563 written, if it will be immediately overwritten.
1564 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1565 if (lhs)
1567 dsi->endptr = lhs;
1568 zsi = zero_length_string (lhs, dsi);
1570 break;
1571 default:
1572 gcc_unreachable ();
1574 if (zsi != NULL)
1575 zsi->dont_invalidate = true;
1577 if (fn == NULL_TREE)
1578 return;
1580 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1581 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1583 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1584 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1585 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1586 GSI_SAME_STMT);
1587 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1589 fprintf (dump_file, "Optimizing: ");
1590 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1592 if (with_bounds)
1594 fn = chkp_maybe_create_clone (fn)->decl;
1595 if (gimple_call_num_args (stmt) == 4)
1596 success = update_gimple_call (gsi, fn, 5, dst,
1597 gimple_call_arg (stmt, 1),
1598 src,
1599 gimple_call_arg (stmt, 3),
1600 len);
1601 else
1602 success = update_gimple_call (gsi, fn, 6, dst,
1603 gimple_call_arg (stmt, 1),
1604 src,
1605 gimple_call_arg (stmt, 3),
1606 len,
1607 gimple_call_arg (stmt, 4));
1609 else
1610 if (gimple_call_num_args (stmt) == 2)
1611 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1612 else
1613 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1614 gimple_call_arg (stmt, 2));
1615 if (success)
1617 stmt = gsi_stmt (*gsi);
1618 gimple_call_set_with_bounds (stmt, with_bounds);
1619 update_stmt (stmt);
1620 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1622 fprintf (dump_file, "into: ");
1623 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1625 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1626 laststmt.stmt = stmt;
1627 laststmt.len = srclen;
1628 laststmt.stridx = dsi->idx;
1630 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1631 fprintf (dump_file, "not possible.\n");
1634 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1635 way. LEN can either be an integer expression, or a pointer (to char).
1636 When it is the latter (such as in recursive calls to self) is is
1637 assumed to be the argument in some call to strlen() whose relationship
1638 to SRC is being ascertained. */
1640 static bool
1641 is_strlen_related_p (tree src, tree len)
1643 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1644 && operand_equal_p (src, len, 0))
1645 return true;
1647 if (TREE_CODE (len) != SSA_NAME)
1648 return false;
1650 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1651 if (!def_stmt)
1652 return false;
1654 if (is_gimple_call (def_stmt))
1656 tree func = gimple_call_fndecl (def_stmt);
1657 if (!valid_builtin_call (def_stmt)
1658 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1659 return false;
1661 tree arg = gimple_call_arg (def_stmt, 0);
1662 return is_strlen_related_p (src, arg);
1665 if (!is_gimple_assign (def_stmt))
1666 return false;
1668 tree_code code = gimple_assign_rhs_code (def_stmt);
1669 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1670 tree rhstype = TREE_TYPE (rhs1);
1672 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1673 || (INTEGRAL_TYPE_P (rhstype)
1674 && (code == BIT_AND_EXPR
1675 || code == NOP_EXPR)))
1677 /* Pointer plus (an integer) and integer cast or truncation are
1678 considered among the (potentially) related expressions to strlen.
1679 Others are not. */
1680 return is_strlen_related_p (src, rhs1);
1683 return false;
1686 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1687 bound is a) equal to the size of the destination DST and if so, b)
1688 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1689 and b) does not, warn. Otherwise, do nothing. Return true if
1690 diagnostic has been issued.
1692 The purpose is to diagnose calls to strncpy and stpncpy that do
1693 not nul-terminate the copy while allowing for the idiom where
1694 such a call is immediately followed by setting the last element
1695 to nul, as in:
1696 char a[32];
1697 strncpy (a, s, sizeof a);
1698 a[sizeof a - 1] = '\0';
1701 static bool
1702 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1704 gimple *stmt = gsi_stmt (gsi);
1706 wide_int cntrange[2];
1708 if (TREE_CODE (cnt) == INTEGER_CST)
1709 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1710 else if (TREE_CODE (cnt) == SSA_NAME)
1712 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1713 if (rng == VR_RANGE)
1715 else if (rng == VR_ANTI_RANGE)
1717 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1719 if (wi::ltu_p (cntrange[1], maxobjsize))
1721 cntrange[0] = cntrange[1] + 1;
1722 cntrange[1] = maxobjsize;
1724 else
1726 cntrange[1] = cntrange[0] - 1;
1727 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1730 else
1731 return false;
1733 else
1734 return false;
1736 /* Negative value is the constant string length. If it's less than
1737 the lower bound there is no truncation. */
1738 int sidx = get_stridx (src);
1739 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1740 return false;
1742 tree dst = gimple_call_arg (stmt, 0);
1743 tree dstdecl = dst;
1744 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1745 dstdecl = TREE_OPERAND (dstdecl, 0);
1747 /* If the destination refers to a an array/pointer declared nonstring
1748 return early. */
1749 tree ref = NULL_TREE;
1750 if (get_attr_nonstring_decl (dstdecl, &ref))
1751 return false;
1753 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1754 avoid the truncation warning. */
1755 gsi_next (&gsi);
1756 gimple *next_stmt = gsi_stmt (gsi);
1758 if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt))
1760 tree lhs = gimple_assign_lhs (next_stmt);
1761 tree_code code = TREE_CODE (lhs);
1762 if (code == ARRAY_REF || code == MEM_REF)
1763 lhs = TREE_OPERAND (lhs, 0);
1765 tree func = gimple_call_fndecl (stmt);
1766 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1768 tree ret = gimple_call_lhs (stmt);
1769 if (ret && operand_equal_p (ret, lhs, 0))
1770 return false;
1773 /* Determine the base address and offset of the reference,
1774 ignoring the innermost array index. */
1775 if (TREE_CODE (ref) == ARRAY_REF)
1776 ref = TREE_OPERAND (ref, 0);
1778 HOST_WIDE_INT dstoff;
1779 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1781 HOST_WIDE_INT lhsoff;
1782 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1783 if (lhsbase
1784 && dstoff == lhsoff
1785 && operand_equal_p (dstbase, lhsbase, 0))
1786 return false;
1789 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1790 wide_int lenrange[2];
1791 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1793 lenrange[0] = (sisrc->nonzero_chars
1794 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1795 ? wi::to_wide (sisrc->nonzero_chars)
1796 : wi::zero (prec));
1797 lenrange[1] = lenrange[0];
1799 else if (sidx < 0)
1800 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1801 else
1803 tree range[2];
1804 get_range_strlen (src, range);
1805 if (range[0])
1807 lenrange[0] = wi::to_wide (range[0], prec);
1808 lenrange[1] = wi::to_wide (range[1], prec);
1810 else
1812 lenrange[0] = wi::shwi (0, prec);
1813 lenrange[1] = wi::shwi (-1, prec);
1817 location_t callloc = gimple_location (stmt);
1818 tree func = gimple_call_fndecl (stmt);
1820 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1822 /* If the longest source string is shorter than the lower bound
1823 of the specified count the copy is definitely nul-terminated. */
1824 if (wi::ltu_p (lenrange[1], cntrange[0]))
1825 return false;
1827 if (wi::neg_p (lenrange[1]))
1829 /* The length of one of the strings is unknown but at least
1830 one has non-zero length and that length is stored in
1831 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1832 warning below. */
1833 lenrange[1] = lenrange[0];
1834 lenrange[0] = wi::shwi (0, prec);
1837 if (wi::geu_p (lenrange[0], cntrange[1]))
1839 /* The shortest string is longer than the upper bound of
1840 the count so the truncation is certain. */
1841 if (cntrange[0] == cntrange[1])
1842 return warning_at (callloc, OPT_Wstringop_truncation,
1843 integer_onep (cnt)
1844 ? G_("%qD output truncated copying %E byte "
1845 "from a string of length %wu")
1846 : G_("%qD output truncated copying %E bytes "
1847 "from a string of length %wu"),
1848 func, cnt, lenrange[0].to_uhwi ());
1850 return warning_at (callloc, OPT_Wstringop_truncation,
1851 "%qD output truncated copying between %wu "
1852 "and %wu bytes from a string of length %wu",
1853 func, cntrange[0].to_uhwi (),
1854 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1856 else if (wi::geu_p (lenrange[1], cntrange[1]))
1858 /* The longest string is longer than the upper bound of
1859 the count so the truncation is possible. */
1860 if (cntrange[0] == cntrange[1])
1861 return warning_at (callloc, OPT_Wstringop_truncation,
1862 integer_onep (cnt)
1863 ? G_("%qD output may be truncated copying %E "
1864 "byte from a string of length %wu")
1865 : G_("%qD output may be truncated copying %E "
1866 "bytes from a string of length %wu"),
1867 func, cnt, lenrange[1].to_uhwi ());
1869 return warning_at (callloc, OPT_Wstringop_truncation,
1870 "%qD output may be truncated copying between %wu "
1871 "and %wu bytes from a string of length %wu",
1872 func, cntrange[0].to_uhwi (),
1873 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1876 if (cntrange[0] != cntrange[1]
1877 && wi::leu_p (cntrange[0], lenrange[0])
1878 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1880 /* If the source (including the terminating nul) is longer than
1881 the lower bound of the specified count but shorter than the
1882 upper bound the copy may (but need not) be truncated. */
1883 return warning_at (callloc, OPT_Wstringop_truncation,
1884 "%qD output may be truncated copying between %wu "
1885 "and %wu bytes from a string of length %wu",
1886 func, cntrange[0].to_uhwi (),
1887 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1891 if (tree dstsize = compute_objsize (dst, 1))
1893 /* The source length is uknown. Try to determine the destination
1894 size and see if it matches the specified bound. If not, bail.
1895 Otherwise go on to see if it should be diagnosed for possible
1896 truncation. */
1897 if (!dstsize)
1898 return false;
1900 if (wi::to_wide (dstsize) != cntrange[1])
1901 return false;
1903 if (cntrange[0] == cntrange[1])
1904 return warning_at (callloc, OPT_Wstringop_truncation,
1905 "%qD specified bound %E equals destination size",
1906 func, cnt);
1909 return false;
1912 /* Check the size argument to the built-in forms of stpncpy and strncpy
1913 to see if it's derived from calling strlen() on the source argument
1914 and if so, issue a warning. */
1916 static void
1917 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
1919 if (!strlen_to_stridx)
1920 return;
1922 gimple *stmt = gsi_stmt (*gsi);
1924 bool with_bounds = gimple_call_with_bounds_p (stmt);
1926 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1927 tree len = gimple_call_arg (stmt, with_bounds ? 3 : 2);
1929 /* If the length argument was computed from strlen(S) for some string
1930 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
1931 the location of the strlen() call (PSS->SECOND). */
1932 stridx_strlenloc *pss = strlen_to_stridx->get (len);
1933 if (!pss || pss->first <= 0)
1935 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
1936 gimple_set_no_warning (stmt, true);
1938 return;
1941 int sidx = get_stridx (src);
1942 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
1944 /* Strncpy() et al. cannot modify the source string. Prevent the rest
1945 of the pass from invalidating the strinfo data. */
1946 if (sisrc)
1947 sisrc->dont_invalidate = true;
1949 /* Retrieve the strinfo data for the string S that LEN was computed
1950 from as some function F of strlen (S) (i.e., LEN need not be equal
1951 to strlen(S)). */
1952 strinfo *silen = get_strinfo (pss->first);
1954 location_t callloc = gimple_location (stmt);
1956 tree func = gimple_call_fndecl (stmt);
1958 bool warned = false;
1960 /* When -Wstringop-truncation is set, try to determine truncation
1961 before diagnosing possible overflow. Truncation is implied by
1962 the LEN argument being equal to strlen(SRC), regardless of
1963 whether its value is known. Otherwise, issue the more generic
1964 -Wstringop-overflow which triggers for LEN arguments that in
1965 any meaningful way depend on strlen(SRC). */
1966 if (sisrc == silen
1967 && is_strlen_related_p (src, len)
1968 && warning_at (callloc, OPT_Wstringop_truncation,
1969 "%qD output truncated before terminating nul "
1970 "copying as many bytes from a string as its length",
1971 func))
1972 warned = true;
1973 else if (silen && is_strlen_related_p (src, silen->ptr))
1974 warned = warning_at (callloc, OPT_Wstringop_overflow_,
1975 "%qD specified bound depends on the length "
1976 "of the source argument", func);
1977 if (warned)
1979 location_t strlenloc = pss->second;
1980 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
1981 inform (strlenloc, "length computed here");
1985 /* Check the size argument to the built-in forms of strncat to see if
1986 it's derived from calling strlen() on the source argument and if so,
1987 issue a warning. */
1989 static void
1990 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1992 /* Same as stxncpy(). */
1993 handle_builtin_stxncpy (bcode, gsi);
1996 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
1997 If strlen of the second argument is known and length of the third argument
1998 is that plus one, strlen of the first argument is the same after this
1999 call. */
2001 static void
2002 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2004 int idx, didx;
2005 tree src, dst, len, lhs, oldlen, newlen;
2006 gimple *stmt = gsi_stmt (*gsi);
2007 strinfo *si, *dsi, *olddsi;
2008 bool with_bounds = gimple_call_with_bounds_p (stmt);
2010 len = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2011 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2012 dst = gimple_call_arg (stmt, 0);
2013 idx = get_stridx (src);
2014 if (idx == 0)
2015 return;
2017 didx = get_stridx (dst);
2018 olddsi = NULL;
2019 if (didx > 0)
2020 olddsi = get_strinfo (didx);
2021 else if (didx < 0)
2022 return;
2024 if (olddsi != NULL
2025 && tree_fits_uhwi_p (len)
2026 && !integer_zerop (len))
2027 adjust_last_stmt (olddsi, stmt, false);
2029 bool full_string_p;
2030 if (idx > 0)
2032 gimple *def_stmt;
2034 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2035 is known. */
2036 si = get_strinfo (idx);
2037 if (si == NULL || si->nonzero_chars == NULL_TREE)
2038 return;
2039 if (TREE_CODE (len) == INTEGER_CST
2040 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2042 if (tree_int_cst_le (len, si->nonzero_chars))
2044 /* Copying LEN nonzero characters, where LEN is constant. */
2045 newlen = len;
2046 full_string_p = false;
2048 else
2050 /* Copying the whole of the analyzed part of SI. */
2051 newlen = si->nonzero_chars;
2052 full_string_p = si->full_string_p;
2055 else
2057 if (!si->full_string_p)
2058 return;
2059 if (TREE_CODE (len) != SSA_NAME)
2060 return;
2061 def_stmt = SSA_NAME_DEF_STMT (len);
2062 if (!is_gimple_assign (def_stmt)
2063 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2064 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2065 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2066 return;
2067 /* Copying variable-length string SI (and no more). */
2068 newlen = si->nonzero_chars;
2069 full_string_p = true;
2072 else
2074 si = NULL;
2075 /* Handle memcpy (x, "abcd", 5) or
2076 memcpy (x, "abc\0uvw", 7). */
2077 if (!tree_fits_uhwi_p (len))
2078 return;
2080 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2081 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2082 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2083 full_string_p = clen > nonzero_chars;
2086 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2087 adjust_last_stmt (olddsi, stmt, false);
2089 if (didx == 0)
2091 didx = new_stridx (dst);
2092 if (didx == 0)
2093 return;
2095 oldlen = NULL_TREE;
2096 if (olddsi != NULL)
2098 dsi = unshare_strinfo (olddsi);
2099 oldlen = olddsi->nonzero_chars;
2100 dsi->nonzero_chars = newlen;
2101 dsi->full_string_p = full_string_p;
2102 /* Break the chain, so adjust_related_strinfo on later pointers in
2103 the chain won't adjust this one anymore. */
2104 dsi->next = 0;
2105 dsi->stmt = NULL;
2106 dsi->endptr = NULL_TREE;
2108 else
2110 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2111 set_strinfo (didx, dsi);
2112 find_equal_ptrs (dst, didx);
2114 dsi->writable = true;
2115 dsi->dont_invalidate = true;
2116 if (olddsi != NULL)
2118 tree adj = NULL_TREE;
2119 location_t loc = gimple_location (stmt);
2120 if (oldlen == NULL_TREE)
2122 else if (integer_zerop (oldlen))
2123 adj = newlen;
2124 else if (TREE_CODE (oldlen) == INTEGER_CST
2125 || TREE_CODE (newlen) == INTEGER_CST)
2126 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2127 fold_convert_loc (loc, TREE_TYPE (newlen),
2128 oldlen));
2129 if (adj != NULL_TREE)
2130 adjust_related_strinfos (loc, dsi, adj);
2131 else
2132 dsi->prev = 0;
2134 /* memcpy src may not overlap dst, so src doesn't need to be
2135 invalidated either. */
2136 if (si != NULL)
2137 si->dont_invalidate = true;
2139 if (full_string_p)
2141 lhs = gimple_call_lhs (stmt);
2142 switch (bcode)
2144 case BUILT_IN_MEMCPY:
2145 case BUILT_IN_MEMCPY_CHK:
2146 case BUILT_IN_MEMCPY_CHKP:
2147 case BUILT_IN_MEMCPY_CHK_CHKP:
2148 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2149 laststmt.stmt = stmt;
2150 laststmt.len = dsi->nonzero_chars;
2151 laststmt.stridx = dsi->idx;
2152 if (lhs)
2153 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2154 break;
2155 case BUILT_IN_MEMPCPY:
2156 case BUILT_IN_MEMPCPY_CHK:
2157 case BUILT_IN_MEMPCPY_CHKP:
2158 case BUILT_IN_MEMPCPY_CHK_CHKP:
2159 break;
2160 default:
2161 gcc_unreachable ();
2166 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2167 If strlen of the second argument is known, strlen of the first argument
2168 is increased by the length of the second argument. Furthermore, attempt
2169 to convert it to memcpy/strcpy if the length of the first argument
2170 is known. */
2172 static void
2173 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2175 int idx, didx;
2176 tree src, dst, srclen, dstlen, len, lhs, args, type, fn, objsz, endptr;
2177 bool success;
2178 gimple *stmt = gsi_stmt (*gsi);
2179 strinfo *si, *dsi;
2180 location_t loc;
2181 bool with_bounds = gimple_call_with_bounds_p (stmt);
2183 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2184 dst = gimple_call_arg (stmt, 0);
2185 lhs = gimple_call_lhs (stmt);
2187 didx = get_stridx (dst);
2188 if (didx < 0)
2189 return;
2191 dsi = NULL;
2192 if (didx > 0)
2193 dsi = get_strinfo (didx);
2194 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2196 /* strcat (p, q) can be transformed into
2197 tmp = p + strlen (p); endptr = strpcpy (tmp, q);
2198 with length endptr - p if we need to compute the length
2199 later on. Don't do this transformation if we don't need
2200 it. */
2201 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2203 if (didx == 0)
2205 didx = new_stridx (dst);
2206 if (didx == 0)
2207 return;
2209 if (dsi == NULL)
2211 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2212 set_strinfo (didx, dsi);
2213 find_equal_ptrs (dst, didx);
2215 else
2217 dsi = unshare_strinfo (dsi);
2218 dsi->nonzero_chars = NULL_TREE;
2219 dsi->full_string_p = false;
2220 dsi->next = 0;
2221 dsi->endptr = NULL_TREE;
2223 dsi->writable = true;
2224 dsi->stmt = stmt;
2225 dsi->dont_invalidate = true;
2227 return;
2230 srclen = NULL_TREE;
2231 si = NULL;
2232 idx = get_stridx (src);
2233 if (idx < 0)
2234 srclen = build_int_cst (size_type_node, ~idx);
2235 else if (idx > 0)
2237 si = get_strinfo (idx);
2238 if (si != NULL)
2239 srclen = get_string_length (si);
2242 loc = gimple_location (stmt);
2243 dstlen = dsi->nonzero_chars;
2244 endptr = dsi->endptr;
2246 dsi = unshare_strinfo (dsi);
2247 dsi->endptr = NULL_TREE;
2248 dsi->stmt = NULL;
2249 dsi->writable = true;
2251 if (srclen != NULL_TREE)
2253 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2254 TREE_TYPE (dsi->nonzero_chars),
2255 dsi->nonzero_chars, srclen);
2256 gcc_assert (dsi->full_string_p);
2257 adjust_related_strinfos (loc, dsi, srclen);
2258 dsi->dont_invalidate = true;
2260 else
2262 dsi->nonzero_chars = NULL;
2263 dsi->full_string_p = false;
2264 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2265 dsi->dont_invalidate = true;
2268 if (si != NULL)
2269 /* strcat src may not overlap dst, so src doesn't need to be
2270 invalidated either. */
2271 si->dont_invalidate = true;
2273 /* For now. Could remove the lhs from the call and add
2274 lhs = dst; afterwards. */
2275 if (lhs)
2276 return;
2278 fn = NULL_TREE;
2279 objsz = NULL_TREE;
2280 switch (bcode)
2282 case BUILT_IN_STRCAT:
2283 case BUILT_IN_STRCAT_CHKP:
2284 if (srclen != NULL_TREE)
2285 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2286 else
2287 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2288 break;
2289 case BUILT_IN_STRCAT_CHK:
2290 case BUILT_IN_STRCAT_CHK_CHKP:
2291 if (srclen != NULL_TREE)
2292 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2293 else
2294 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2295 objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2296 break;
2297 default:
2298 gcc_unreachable ();
2301 if (fn == NULL_TREE)
2302 return;
2304 len = NULL_TREE;
2305 if (srclen != NULL_TREE)
2307 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2308 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2310 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2311 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2312 build_int_cst (type, 1));
2313 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2314 GSI_SAME_STMT);
2316 if (endptr)
2317 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2318 else
2319 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2320 TREE_TYPE (dst), unshare_expr (dst),
2321 fold_convert_loc (loc, sizetype,
2322 unshare_expr (dstlen)));
2323 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2324 GSI_SAME_STMT);
2325 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2327 fprintf (dump_file, "Optimizing: ");
2328 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2330 if (with_bounds)
2332 fn = chkp_maybe_create_clone (fn)->decl;
2333 if (srclen != NULL_TREE)
2334 success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE),
2335 dst,
2336 gimple_call_arg (stmt, 1),
2337 src,
2338 gimple_call_arg (stmt, 3),
2339 len, objsz);
2340 else
2341 success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE),
2342 dst,
2343 gimple_call_arg (stmt, 1),
2344 src,
2345 gimple_call_arg (stmt, 3),
2346 objsz);
2348 else
2349 if (srclen != NULL_TREE)
2350 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2351 dst, src, len, objsz);
2352 else
2353 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2354 dst, src, objsz);
2355 if (success)
2357 stmt = gsi_stmt (*gsi);
2358 gimple_call_set_with_bounds (stmt, with_bounds);
2359 update_stmt (stmt);
2360 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2362 fprintf (dump_file, "into: ");
2363 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2365 /* If srclen == NULL, note that current string length can be
2366 computed by transforming this strcpy into stpcpy. */
2367 if (srclen == NULL_TREE && dsi->dont_invalidate)
2368 dsi->stmt = stmt;
2369 adjust_last_stmt (dsi, stmt, true);
2370 if (srclen != NULL_TREE)
2372 laststmt.stmt = stmt;
2373 laststmt.len = srclen;
2374 laststmt.stridx = dsi->idx;
2377 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2378 fprintf (dump_file, "not possible.\n");
2381 /* Handle a call to malloc or calloc. */
2383 static void
2384 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2386 gimple *stmt = gsi_stmt (*gsi);
2387 tree lhs = gimple_call_lhs (stmt);
2388 if (lhs == NULL_TREE)
2389 return;
2391 gcc_assert (get_stridx (lhs) == 0);
2392 int idx = new_stridx (lhs);
2393 tree length = NULL_TREE;
2394 if (bcode == BUILT_IN_CALLOC)
2395 length = build_int_cst (size_type_node, 0);
2396 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2397 if (bcode == BUILT_IN_CALLOC)
2398 si->endptr = lhs;
2399 set_strinfo (idx, si);
2400 si->writable = true;
2401 si->stmt = stmt;
2402 si->dont_invalidate = true;
2405 /* Handle a call to memset.
2406 After a call to calloc, memset(,0,) is unnecessary.
2407 memset(malloc(n),0,n) is calloc(n,1). */
2409 static bool
2410 handle_builtin_memset (gimple_stmt_iterator *gsi)
2412 gimple *stmt2 = gsi_stmt (*gsi);
2413 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2414 return true;
2415 tree ptr = gimple_call_arg (stmt2, 0);
2416 int idx1 = get_stridx (ptr);
2417 if (idx1 <= 0)
2418 return true;
2419 strinfo *si1 = get_strinfo (idx1);
2420 if (!si1)
2421 return true;
2422 gimple *stmt1 = si1->stmt;
2423 if (!stmt1 || !is_gimple_call (stmt1))
2424 return true;
2425 tree callee1 = gimple_call_fndecl (stmt1);
2426 if (!valid_builtin_call (stmt1))
2427 return true;
2428 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2429 tree size = gimple_call_arg (stmt2, 2);
2430 if (code1 == BUILT_IN_CALLOC)
2431 /* Not touching stmt1 */ ;
2432 else if (code1 == BUILT_IN_MALLOC
2433 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2435 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2436 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2437 size, build_one_cst (size_type_node));
2438 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2439 si1->full_string_p = true;
2440 si1->stmt = gsi_stmt (gsi1);
2442 else
2443 return true;
2444 tree lhs = gimple_call_lhs (stmt2);
2445 unlink_stmt_vdef (stmt2);
2446 if (lhs)
2448 gimple *assign = gimple_build_assign (lhs, ptr);
2449 gsi_replace (gsi, assign, false);
2451 else
2453 gsi_remove (gsi, true);
2454 release_defs (stmt2);
2457 return false;
2460 /* Handle a call to memcmp. We try to handle small comparisons by
2461 converting them to load and compare, and replacing the call to memcmp
2462 with a __builtin_memcmp_eq call where possible. */
2464 static bool
2465 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2467 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2468 tree res = gimple_call_lhs (stmt2);
2469 tree arg1 = gimple_call_arg (stmt2, 0);
2470 tree arg2 = gimple_call_arg (stmt2, 1);
2471 tree len = gimple_call_arg (stmt2, 2);
2472 unsigned HOST_WIDE_INT leni;
2473 use_operand_p use_p;
2474 imm_use_iterator iter;
2476 if (!res)
2477 return true;
2479 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2481 gimple *ustmt = USE_STMT (use_p);
2483 if (is_gimple_debug (ustmt))
2484 continue;
2485 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2487 gassign *asgn = as_a <gassign *> (ustmt);
2488 tree_code code = gimple_assign_rhs_code (asgn);
2489 if ((code != EQ_EXPR && code != NE_EXPR)
2490 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2491 return true;
2493 else if (gimple_code (ustmt) == GIMPLE_COND)
2495 tree_code code = gimple_cond_code (ustmt);
2496 if ((code != EQ_EXPR && code != NE_EXPR)
2497 || !integer_zerop (gimple_cond_rhs (ustmt)))
2498 return true;
2500 else
2501 return true;
2504 if (tree_fits_uhwi_p (len)
2505 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2506 && pow2p_hwi (leni))
2508 leni *= CHAR_TYPE_SIZE;
2509 unsigned align1 = get_pointer_alignment (arg1);
2510 unsigned align2 = get_pointer_alignment (arg2);
2511 unsigned align = MIN (align1, align2);
2512 scalar_int_mode mode;
2513 if (int_mode_for_size (leni, 1).exists (&mode)
2514 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2516 location_t loc = gimple_location (stmt2);
2517 tree type, off;
2518 type = build_nonstandard_integer_type (leni, 1);
2519 gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type)) == leni);
2520 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2521 ptr_mode, true);
2522 off = build_int_cst (ptrtype, 0);
2523 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2524 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2525 tree tem1 = fold_const_aggregate_ref (arg1);
2526 if (tem1)
2527 arg1 = tem1;
2528 tree tem2 = fold_const_aggregate_ref (arg2);
2529 if (tem2)
2530 arg2 = tem2;
2531 res = fold_convert_loc (loc, TREE_TYPE (res),
2532 fold_build2_loc (loc, NE_EXPR,
2533 boolean_type_node,
2534 arg1, arg2));
2535 gimplify_and_update_call_from_tree (gsi, res);
2536 return false;
2540 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2541 return false;
2544 /* Handle a POINTER_PLUS_EXPR statement.
2545 For p = "abcd" + 2; compute associated length, or if
2546 p = q + off is pointing to a '\0' character of a string, call
2547 zero_length_string on it. */
2549 static void
2550 handle_pointer_plus (gimple_stmt_iterator *gsi)
2552 gimple *stmt = gsi_stmt (*gsi);
2553 tree lhs = gimple_assign_lhs (stmt), off;
2554 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2555 strinfo *si, *zsi;
2557 if (idx == 0)
2558 return;
2560 if (idx < 0)
2562 tree off = gimple_assign_rhs2 (stmt);
2563 if (tree_fits_uhwi_p (off)
2564 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2565 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2566 = ~(~idx - (int) tree_to_uhwi (off));
2567 return;
2570 si = get_strinfo (idx);
2571 if (si == NULL || si->nonzero_chars == NULL_TREE)
2572 return;
2574 off = gimple_assign_rhs2 (stmt);
2575 zsi = NULL;
2576 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2577 zsi = zero_length_string (lhs, si);
2578 else if (TREE_CODE (off) == SSA_NAME)
2580 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2581 if (gimple_assign_single_p (def_stmt)
2582 && si->full_string_p
2583 && operand_equal_p (si->nonzero_chars,
2584 gimple_assign_rhs1 (def_stmt), 0))
2585 zsi = zero_length_string (lhs, si);
2587 if (zsi != NULL
2588 && si->endptr != NULL_TREE
2589 && si->endptr != lhs
2590 && TREE_CODE (si->endptr) == SSA_NAME)
2592 enum tree_code rhs_code
2593 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2594 ? SSA_NAME : NOP_EXPR;
2595 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2596 gcc_assert (gsi_stmt (*gsi) == stmt);
2597 update_stmt (stmt);
2601 /* Handle a single character store. */
2603 static bool
2604 handle_char_store (gimple_stmt_iterator *gsi)
2606 int idx = -1;
2607 strinfo *si = NULL;
2608 gimple *stmt = gsi_stmt (*gsi);
2609 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
2610 tree rhs = gimple_assign_rhs1 (stmt);
2611 unsigned HOST_WIDE_INT offset = 0;
2613 if (TREE_CODE (lhs) == MEM_REF
2614 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
2616 tree mem_offset = TREE_OPERAND (lhs, 1);
2617 if (tree_fits_uhwi_p (mem_offset))
2619 /* Get the strinfo for the base, and use it if it starts with at
2620 least OFFSET nonzero characters. This is trivially true if
2621 OFFSET is zero. */
2622 offset = tree_to_uhwi (mem_offset);
2623 idx = get_stridx (TREE_OPERAND (lhs, 0));
2624 if (idx > 0)
2625 si = get_strinfo (idx);
2626 if (offset == 0)
2627 ssaname = TREE_OPERAND (lhs, 0);
2628 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
2629 return true;
2632 else
2634 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
2635 if (idx > 0)
2636 si = get_strinfo (idx);
2639 bool storing_zero_p = initializer_zerop (rhs);
2640 bool storing_nonzero_p = (!storing_zero_p
2641 && TREE_CODE (rhs) == INTEGER_CST
2642 && integer_nonzerop (rhs));
2644 if (si != NULL)
2646 int cmp = compare_nonzero_chars (si, offset);
2647 gcc_assert (offset == 0 || cmp >= 0);
2648 if (storing_zero_p && cmp == 0 && si->full_string_p)
2650 /* When overwriting a '\0' with a '\0', the store can be removed
2651 if we know it has been stored in the current function. */
2652 if (!stmt_could_throw_p (stmt) && si->writable)
2654 unlink_stmt_vdef (stmt);
2655 release_defs (stmt);
2656 gsi_remove (gsi, true);
2657 return false;
2659 else
2661 si->writable = true;
2662 gsi_next (gsi);
2663 return false;
2666 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2667 and if we aren't storing '\0', we know that the length of the
2668 string and any other zero terminated string in memory remains
2669 the same. In that case we move to the next gimple statement and
2670 return to signal the caller that it shouldn't invalidate anything.
2672 This is benefical for cases like:
2674 char p[20];
2675 void foo (char *q)
2677 strcpy (p, "foobar");
2678 size_t len = strlen (p); // This can be optimized into 6
2679 size_t len2 = strlen (q); // This has to be computed
2680 p[0] = 'X';
2681 size_t len3 = strlen (p); // This can be optimized into 6
2682 size_t len4 = strlen (q); // This can be optimized into len2
2683 bar (len, len2, len3, len4);
2686 else if (storing_nonzero_p && cmp > 0)
2688 gsi_next (gsi);
2689 return false;
2691 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
2693 /* When storing_nonzero_p, we know that the string now starts
2694 with OFFSET + 1 nonzero characters, but don't know whether
2695 there's a following nul terminator.
2697 When storing_zero_p, we know that the string is now OFFSET
2698 characters long.
2700 Otherwise, we're storing an unknown value at offset OFFSET,
2701 so need to clip the nonzero_chars to OFFSET. */
2702 location_t loc = gimple_location (stmt);
2703 tree oldlen = si->nonzero_chars;
2704 if (cmp == 0 && si->full_string_p)
2705 /* We're overwriting the nul terminator with a nonzero or
2706 unknown character. If the previous stmt was a memcpy,
2707 its length may be decreased. */
2708 adjust_last_stmt (si, stmt, false);
2709 si = unshare_strinfo (si);
2710 if (storing_nonzero_p)
2711 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
2712 else
2713 si->nonzero_chars = build_int_cst (size_type_node, offset);
2714 si->full_string_p = storing_zero_p;
2715 if (storing_zero_p
2716 && ssaname
2717 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2718 si->endptr = ssaname;
2719 else
2720 si->endptr = NULL;
2721 si->next = 0;
2722 si->stmt = NULL;
2723 si->writable = true;
2724 si->dont_invalidate = true;
2725 if (oldlen)
2727 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
2728 si->nonzero_chars, oldlen);
2729 adjust_related_strinfos (loc, si, adj);
2731 else
2732 si->prev = 0;
2735 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
2737 if (ssaname)
2738 idx = new_stridx (ssaname);
2739 else
2740 idx = new_addr_stridx (lhs);
2741 if (idx != 0)
2743 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
2744 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
2745 si = new_strinfo (ptr, idx, len, storing_zero_p);
2746 set_strinfo (idx, si);
2747 if (storing_zero_p
2748 && ssaname
2749 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2750 si->endptr = ssaname;
2751 si->dont_invalidate = true;
2752 si->writable = true;
2755 else if (idx == 0
2756 && TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST
2757 && ssaname == NULL_TREE
2758 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
2760 size_t l = strlen (TREE_STRING_POINTER (gimple_assign_rhs1 (stmt)));
2761 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
2762 if (a > 0 && (unsigned HOST_WIDE_INT) a > l)
2764 int idx = new_addr_stridx (lhs);
2765 if (idx != 0)
2767 si = new_strinfo (build_fold_addr_expr (lhs), idx,
2768 build_int_cst (size_type_node, l), true);
2769 set_strinfo (idx, si);
2770 si->dont_invalidate = true;
2775 if (si != NULL && offset == 0 && storing_zero_p)
2777 /* Allow adjust_last_stmt to remove it if the stored '\0'
2778 is immediately overwritten. */
2779 laststmt.stmt = stmt;
2780 laststmt.len = build_int_cst (size_type_node, 1);
2781 laststmt.stridx = si->idx;
2783 return true;
2786 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
2788 static void
2789 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
2791 if (TREE_CODE (rhs1) != SSA_NAME
2792 || TREE_CODE (rhs2) != SSA_NAME)
2793 return;
2795 gimple *call_stmt = NULL;
2796 for (int pass = 0; pass < 2; pass++)
2798 gimple *g = SSA_NAME_DEF_STMT (rhs1);
2799 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
2800 && has_single_use (rhs1)
2801 && gimple_call_arg (g, 0) == rhs2)
2803 call_stmt = g;
2804 break;
2806 std::swap (rhs1, rhs2);
2809 if (call_stmt)
2811 tree arg0 = gimple_call_arg (call_stmt, 0);
2813 if (arg0 == rhs2)
2815 tree arg1 = gimple_call_arg (call_stmt, 1);
2816 tree arg1_len = NULL_TREE;
2817 int idx = get_stridx (arg1);
2819 if (idx)
2821 if (idx < 0)
2822 arg1_len = build_int_cst (size_type_node, ~idx);
2823 else
2825 strinfo *si = get_strinfo (idx);
2826 if (si)
2827 arg1_len = get_string_length (si);
2831 if (arg1_len != NULL_TREE)
2833 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
2834 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
2835 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
2836 arg0, arg1, arg1_len);
2837 tree strncmp_lhs = make_ssa_name (integer_type_node);
2838 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
2839 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
2840 gsi_remove (&gsi, true);
2841 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
2842 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
2844 if (is_gimple_assign (stmt))
2846 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
2848 tree cond = gimple_assign_rhs1 (stmt);
2849 TREE_OPERAND (cond, 0) = strncmp_lhs;
2850 TREE_OPERAND (cond, 1) = zero;
2852 else
2854 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
2855 gimple_assign_set_rhs2 (stmt, zero);
2858 else
2860 gcond *cond = as_a<gcond *> (stmt);
2861 gimple_cond_set_lhs (cond, strncmp_lhs);
2862 gimple_cond_set_rhs (cond, zero);
2864 update_stmt (stmt);
2870 /* Attempt to optimize a single statement at *GSI using string length
2871 knowledge. */
2873 static bool
2874 strlen_optimize_stmt (gimple_stmt_iterator *gsi)
2876 gimple *stmt = gsi_stmt (*gsi);
2878 if (is_gimple_call (stmt))
2880 tree callee = gimple_call_fndecl (stmt);
2881 if (valid_builtin_call (stmt))
2882 switch (DECL_FUNCTION_CODE (callee))
2884 case BUILT_IN_STRLEN:
2885 case BUILT_IN_STRLEN_CHKP:
2886 handle_builtin_strlen (gsi);
2887 break;
2888 case BUILT_IN_STRCHR:
2889 case BUILT_IN_STRCHR_CHKP:
2890 handle_builtin_strchr (gsi);
2891 break;
2892 case BUILT_IN_STRCPY:
2893 case BUILT_IN_STRCPY_CHK:
2894 case BUILT_IN_STPCPY:
2895 case BUILT_IN_STPCPY_CHK:
2896 case BUILT_IN_STRCPY_CHKP:
2897 case BUILT_IN_STRCPY_CHK_CHKP:
2898 case BUILT_IN_STPCPY_CHKP:
2899 case BUILT_IN_STPCPY_CHK_CHKP:
2900 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
2901 break;
2903 case BUILT_IN_STRNCAT:
2904 case BUILT_IN_STRNCAT_CHK:
2905 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
2906 break;
2908 case BUILT_IN_STPNCPY:
2909 case BUILT_IN_STPNCPY_CHK:
2910 case BUILT_IN_STRNCPY:
2911 case BUILT_IN_STRNCPY_CHK:
2912 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
2913 break;
2915 case BUILT_IN_MEMCPY:
2916 case BUILT_IN_MEMCPY_CHK:
2917 case BUILT_IN_MEMPCPY:
2918 case BUILT_IN_MEMPCPY_CHK:
2919 case BUILT_IN_MEMCPY_CHKP:
2920 case BUILT_IN_MEMCPY_CHK_CHKP:
2921 case BUILT_IN_MEMPCPY_CHKP:
2922 case BUILT_IN_MEMPCPY_CHK_CHKP:
2923 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
2924 break;
2925 case BUILT_IN_STRCAT:
2926 case BUILT_IN_STRCAT_CHK:
2927 case BUILT_IN_STRCAT_CHKP:
2928 case BUILT_IN_STRCAT_CHK_CHKP:
2929 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
2930 break;
2931 case BUILT_IN_MALLOC:
2932 case BUILT_IN_CALLOC:
2933 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
2934 break;
2935 case BUILT_IN_MEMSET:
2936 if (!handle_builtin_memset (gsi))
2937 return false;
2938 break;
2939 case BUILT_IN_MEMCMP:
2940 if (!handle_builtin_memcmp (gsi))
2941 return false;
2942 break;
2943 default:
2944 break;
2947 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
2949 tree lhs = gimple_assign_lhs (stmt);
2951 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
2953 if (gimple_assign_single_p (stmt)
2954 || (gimple_assign_cast_p (stmt)
2955 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
2957 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2958 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
2960 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2961 handle_pointer_plus (gsi);
2963 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
2965 enum tree_code code = gimple_assign_rhs_code (stmt);
2966 if (code == COND_EXPR)
2968 tree cond = gimple_assign_rhs1 (stmt);
2969 enum tree_code cond_code = TREE_CODE (cond);
2971 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
2972 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
2973 TREE_OPERAND (cond, 1), stmt);
2975 else if (code == EQ_EXPR || code == NE_EXPR)
2976 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
2977 gimple_assign_rhs2 (stmt), stmt);
2979 if (strlen_to_stridx)
2981 tree rhs1 = gimple_assign_rhs1 (stmt);
2982 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
2983 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
2986 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
2988 tree type = TREE_TYPE (lhs);
2989 if (TREE_CODE (type) == ARRAY_TYPE)
2990 type = TREE_TYPE (type);
2991 if (TREE_CODE (type) == INTEGER_TYPE
2992 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
2993 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
2995 if (! handle_char_store (gsi))
2996 return false;
3000 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3002 enum tree_code code = gimple_cond_code (cond);
3003 if (code == EQ_EXPR || code == NE_EXPR)
3004 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3005 gimple_cond_rhs (stmt), stmt);
3008 if (gimple_vdef (stmt))
3009 maybe_invalidate (stmt);
3010 return true;
3013 /* Recursively call maybe_invalidate on stmts that might be executed
3014 in between dombb and current bb and that contain a vdef. Stop when
3015 *count stmts are inspected, or if the whole strinfo vector has
3016 been invalidated. */
3018 static void
3019 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3021 unsigned int i, n = gimple_phi_num_args (phi);
3023 for (i = 0; i < n; i++)
3025 tree vuse = gimple_phi_arg_def (phi, i);
3026 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3027 basic_block bb = gimple_bb (stmt);
3028 if (bb == NULL
3029 || bb == dombb
3030 || !bitmap_set_bit (visited, bb->index)
3031 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3032 continue;
3033 while (1)
3035 if (gimple_code (stmt) == GIMPLE_PHI)
3037 do_invalidate (dombb, stmt, visited, count);
3038 if (*count == 0)
3039 return;
3040 break;
3042 if (--*count == 0)
3043 return;
3044 if (!maybe_invalidate (stmt))
3046 *count = 0;
3047 return;
3049 vuse = gimple_vuse (stmt);
3050 stmt = SSA_NAME_DEF_STMT (vuse);
3051 if (gimple_bb (stmt) != bb)
3053 bb = gimple_bb (stmt);
3054 if (bb == NULL
3055 || bb == dombb
3056 || !bitmap_set_bit (visited, bb->index)
3057 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3058 break;
3064 class strlen_dom_walker : public dom_walker
3066 public:
3067 strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
3069 virtual edge before_dom_children (basic_block);
3070 virtual void after_dom_children (basic_block);
3073 /* Callback for walk_dominator_tree. Attempt to optimize various
3074 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3076 edge
3077 strlen_dom_walker::before_dom_children (basic_block bb)
3079 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3081 if (dombb == NULL)
3082 stridx_to_strinfo = NULL;
3083 else
3085 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3086 if (stridx_to_strinfo)
3088 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3089 gsi_next (&gsi))
3091 gphi *phi = gsi.phi ();
3092 if (virtual_operand_p (gimple_phi_result (phi)))
3094 bitmap visited = BITMAP_ALLOC (NULL);
3095 int count_vdef = 100;
3096 do_invalidate (dombb, phi, visited, &count_vdef);
3097 BITMAP_FREE (visited);
3098 if (count_vdef == 0)
3100 /* If there were too many vdefs in between immediate
3101 dominator and current bb, invalidate everything.
3102 If stridx_to_strinfo has been unshared, we need
3103 to free it, otherwise just set it to NULL. */
3104 if (!strinfo_shared ())
3106 unsigned int i;
3107 strinfo *si;
3109 for (i = 1;
3110 vec_safe_iterate (stridx_to_strinfo, i, &si);
3111 ++i)
3113 free_strinfo (si);
3114 (*stridx_to_strinfo)[i] = NULL;
3117 else
3118 stridx_to_strinfo = NULL;
3120 break;
3126 /* If all PHI arguments have the same string index, the PHI result
3127 has it as well. */
3128 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3129 gsi_next (&gsi))
3131 gphi *phi = gsi.phi ();
3132 tree result = gimple_phi_result (phi);
3133 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3135 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3136 if (idx != 0)
3138 unsigned int i, n = gimple_phi_num_args (phi);
3139 for (i = 1; i < n; i++)
3140 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3141 break;
3142 if (i == n)
3143 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3148 /* Attempt to optimize individual statements. */
3149 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3150 if (strlen_optimize_stmt (&gsi))
3151 gsi_next (&gsi);
3153 bb->aux = stridx_to_strinfo;
3154 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3155 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3156 return NULL;
3159 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3160 owned by the current bb, clear bb->aux. */
3162 void
3163 strlen_dom_walker::after_dom_children (basic_block bb)
3165 if (bb->aux)
3167 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3168 if (vec_safe_length (stridx_to_strinfo)
3169 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3171 unsigned int i;
3172 strinfo *si;
3174 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3175 free_strinfo (si);
3176 vec_free (stridx_to_strinfo);
3178 bb->aux = NULL;
3182 /* Main entry point. */
3184 namespace {
3186 const pass_data pass_data_strlen =
3188 GIMPLE_PASS, /* type */
3189 "strlen", /* name */
3190 OPTGROUP_NONE, /* optinfo_flags */
3191 TV_TREE_STRLEN, /* tv_id */
3192 ( PROP_cfg | PROP_ssa ), /* properties_required */
3193 0, /* properties_provided */
3194 0, /* properties_destroyed */
3195 0, /* todo_flags_start */
3196 0, /* todo_flags_finish */
3199 class pass_strlen : public gimple_opt_pass
3201 public:
3202 pass_strlen (gcc::context *ctxt)
3203 : gimple_opt_pass (pass_data_strlen, ctxt)
3206 /* opt_pass methods: */
3207 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3208 virtual unsigned int execute (function *);
3210 }; // class pass_strlen
3212 unsigned int
3213 pass_strlen::execute (function *fun)
3215 gcc_assert (!strlen_to_stridx);
3216 if (warn_stringop_overflow || warn_stringop_truncation)
3217 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3219 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3220 max_stridx = 1;
3222 calculate_dominance_info (CDI_DOMINATORS);
3224 /* String length optimization is implemented as a walk of the dominator
3225 tree and a forward walk of statements within each block. */
3226 strlen_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
3228 ssa_ver_to_stridx.release ();
3229 strinfo_pool.release ();
3230 if (decl_to_stridxlist_htab)
3232 obstack_free (&stridx_obstack, NULL);
3233 delete decl_to_stridxlist_htab;
3234 decl_to_stridxlist_htab = NULL;
3236 laststmt.stmt = NULL;
3237 laststmt.len = NULL_TREE;
3238 laststmt.stridx = 0;
3240 if (strlen_to_stridx)
3242 strlen_to_stridx->empty ();
3243 delete strlen_to_stridx;
3244 strlen_to_stridx = NULL;
3247 return 0;
3250 } // anon namespace
3252 gimple_opt_pass *
3253 make_pass_strlen (gcc::context *ctxt)
3255 return new pass_strlen (ctxt);