]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-strlen.c
[Darwin, specs] Tidy some more linker options.
[thirdparty/gcc.git] / gcc / tree-ssa-strlen.c
CommitLineData
8b57bfeb 1/* String length optimization
a5544970 2 Copyright (C) 2011-2019 Free Software Foundation, Inc.
8b57bfeb
JJ
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
c7131fb2 24#include "backend.h"
957060b5 25#include "rtl.h"
4d648807 26#include "tree.h"
c7131fb2 27#include "gimple.h"
957060b5
AM
28#include "alloc-pool.h"
29#include "tree-pass.h"
c7131fb2 30#include "ssa.h"
957060b5
AM
31#include "cgraph.h"
32#include "gimple-pretty-print.h"
cc8bea0a 33#include "gimple-ssa-warn-restrict.h"
40e23961 34#include "fold-const.h"
d8a2d370 35#include "stor-layout.h"
2fb9a547
AM
36#include "gimple-fold.h"
37#include "tree-eh.h"
45b0be94 38#include "gimplify.h"
5be5c238 39#include "gimple-iterator.h"
18f429e2 40#include "gimplify-me.h"
d8a2d370 41#include "expr.h"
fa9544ab 42#include "tree-cfg.h"
442b4905 43#include "tree-dfa.h"
8b57bfeb 44#include "domwalk.h"
025d57f0 45#include "tree-ssa-alias.h"
8b57bfeb 46#include "tree-ssa-propagate.h"
5d0d5d68 47#include "tree-ssa-strlen.h"
8b57bfeb 48#include "params.h"
910ee068 49#include "tree-hash-traits.h"
8b0b334a 50#include "tree-object-size.h"
36b85e43 51#include "builtins.h"
e0bd6c9f 52#include "target.h"
025d57f0
MS
53#include "diagnostic-core.h"
54#include "diagnostic.h"
55#include "intl.h"
56#include "attribs.h"
6a33d0ff 57#include "calls.h"
8b57bfeb
JJ
58
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). */
9771b263 62static vec<int> ssa_ver_to_stridx;
8b57bfeb
JJ
63
64/* Number of currently active string indexes plus one. */
65static int max_stridx;
66
67/* String information record. */
526ceb68 68struct strinfo
8b57bfeb 69{
e3f9a279
RS
70 /* Number of leading characters that are known to be nonzero. This is
71 also the length of the string if FULL_STRING_P.
72
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;
8b57bfeb
JJ
77 /* Any of the corresponding pointers for querying alias oracle. */
78 tree ptr;
862088aa
RS
79 /* This is used for two things:
80
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.
84
85 - To record the malloc or calloc call that produced this result. */
355fe088 86 gimple *stmt;
8b57bfeb
JJ
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;
e3f9a279
RS
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;
526ceb68 127};
8b57bfeb
JJ
128
129/* Pool for allocating strinfo_struct entries. */
526ceb68 130static object_allocator<strinfo> strinfo_pool ("strinfo pool");
8b57bfeb
JJ
131
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. */
526ceb68 138static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
8b57bfeb
JJ
139
140/* One OFFSET->IDX mapping. */
141struct stridxlist
142{
143 struct stridxlist *next;
144 HOST_WIDE_INT offset;
145 int idx;
146};
147
148/* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
149struct decl_stridxlist_map
150{
151 struct tree_map_base base;
152 struct stridxlist list;
153};
154
155/* Hash table for mapping decls to a chained list of offset -> idx
156 mappings. */
fb5c464a 157static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
8b57bfeb 158
9bc83f27
JJ
159/* Hash table mapping strlen (or strnlen with constant bound and return
160 smaller than bound) calls to stridx instances describing
6a33d0ff
MS
161 the calls' arguments. Non-null only when warn_stringop_truncation
162 is non-zero. */
025d57f0 163typedef std::pair<int, location_t> stridx_strlenloc;
6a33d0ff 164static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
025d57f0 165
8b57bfeb
JJ
166/* Obstack for struct stridxlist and struct decl_stridxlist_map. */
167static struct obstack stridx_obstack;
168
169/* Last memcpy statement if it could be adjusted if the trailing
170 '\0' written is immediately overwritten, or
171 *x = '\0' store that could be removed if it is immediately overwritten. */
172struct laststmt_struct
173{
355fe088 174 gimple *stmt;
8b57bfeb
JJ
175 tree len;
176 int stridx;
177} laststmt;
178
e3f9a279 179static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
cc8bea0a 180static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
e3f9a279
RS
181
182/* Return:
183
184 - 1 if SI is known to start with more than OFF nonzero characters.
185
186 - 0 if SI is known to start with OFF nonzero characters,
187 but is not known to start with more.
188
189 - -1 if SI might not start with OFF nonzero characters. */
190
191static inline int
192compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
193{
194 if (si->nonzero_chars
195 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
196 return compare_tree_int (si->nonzero_chars, off);
197 else
198 return -1;
199}
200
201/* Return true if SI is known to be a zero-length string. */
202
203static inline bool
204zero_length_string_p (strinfo *si)
205{
206 return si->full_string_p && integer_zerop (si->nonzero_chars);
207}
204a913b
JJ
208
209/* Return strinfo vector entry IDX. */
210
526ceb68 211static inline strinfo *
204a913b
JJ
212get_strinfo (int idx)
213{
214 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
215 return NULL;
216 return (*stridx_to_strinfo)[idx];
217}
218
bde63fde
RS
219/* Get the next strinfo in the chain after SI, or null if none. */
220
221static inline strinfo *
222get_next_strinfo (strinfo *si)
223{
224 if (si->next == 0)
225 return NULL;
226 strinfo *nextsi = get_strinfo (si->next);
227 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
228 return NULL;
229 return nextsi;
230}
231
e3f9a279
RS
232/* Helper function for get_stridx. Return the strinfo index of the address
233 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
234 OK to return the index for some X <= &EXP and store &EXP - X in
235 *OFFSET_OUT. */
8b57bfeb
JJ
236
237static int
e3f9a279 238get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
8b57bfeb
JJ
239{
240 HOST_WIDE_INT off;
5f3cd7c3 241 struct stridxlist *list, *last = NULL;
8b57bfeb
JJ
242 tree base;
243
c203e8a7 244 if (!decl_to_stridxlist_htab)
8b57bfeb
JJ
245 return 0;
246
a90c8804
RS
247 poly_int64 poff;
248 base = get_addr_base_and_unit_offset (exp, &poff);
249 if (base == NULL || !DECL_P (base) || !poff.is_constant (&off))
8b57bfeb
JJ
250 return 0;
251
1eb68d2d
TS
252 list = decl_to_stridxlist_htab->get (base);
253 if (list == NULL)
8b57bfeb
JJ
254 return 0;
255
8b57bfeb
JJ
256 do
257 {
258 if (list->offset == off)
e3f9a279
RS
259 {
260 if (offset_out)
261 *offset_out = 0;
262 return list->idx;
263 }
5f3cd7c3
JJ
264 if (list->offset > off)
265 return 0;
266 last = list;
8b57bfeb
JJ
267 list = list->next;
268 }
269 while (list);
5f3cd7c3 270
e3f9a279 271 if ((offset_out || ptr) && last && last->idx > 0)
5f3cd7c3 272 {
e3f9a279
RS
273 unsigned HOST_WIDE_INT rel_off
274 = (unsigned HOST_WIDE_INT) off - last->offset;
5f3cd7c3 275 strinfo *si = get_strinfo (last->idx);
e3f9a279
RS
276 if (si && compare_nonzero_chars (si, rel_off) >= 0)
277 {
278 if (offset_out)
279 {
280 *offset_out = rel_off;
281 return last->idx;
282 }
283 else
284 return get_stridx_plus_constant (si, rel_off, ptr);
285 }
5f3cd7c3 286 }
8b57bfeb
JJ
287 return 0;
288}
289
290/* Return string index for EXP. */
291
292static int
293get_stridx (tree exp)
294{
8b57bfeb 295 if (TREE_CODE (exp) == SSA_NAME)
204a913b
JJ
296 {
297 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
298 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
7802a8ec 299
204a913b 300 tree e = exp;
7802a8ec
MS
301 HOST_WIDE_INT offset = 0;
302 /* Follow a chain of at most 5 assignments. */
303 for (int i = 0; i < 5; i++)
204a913b 304 {
355fe088 305 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
7802a8ec
MS
306 if (!is_gimple_assign (def_stmt))
307 return 0;
308
309 tree_code rhs_code = gimple_assign_rhs_code (def_stmt);
310 tree ptr, off;
311
312 if (rhs_code == ADDR_EXPR)
313 {
314 /* Handle indices/offsets into VLAs which are implemented
315 as pointers to arrays. */
316 ptr = gimple_assign_rhs1 (def_stmt);
317 ptr = TREE_OPERAND (ptr, 0);
318
319 /* Handle also VLAs of types larger than char. */
320 if (tree eltsize = TYPE_SIZE_UNIT (TREE_TYPE (ptr)))
321 {
322 if (TREE_CODE (ptr) == ARRAY_REF)
323 {
324 off = TREE_OPERAND (ptr, 1);
7802a8ec 325 ptr = TREE_OPERAND (ptr, 0);
bc09939d
MS
326 if (!integer_onep (eltsize))
327 {
328 /* Scale the array index by the size of the element
329 type in the rare case that it's greater than
330 the typical 1 for char, making sure both operands
331 have the same type. */
332 eltsize = fold_convert (ssizetype, eltsize);
333 off = fold_convert (ssizetype, off);
334 off = fold_build2 (MULT_EXPR, ssizetype, off, eltsize);
335 }
7802a8ec
MS
336 }
337 else
338 off = integer_zero_node;
339 }
340 else
341 return 0;
342
343 if (TREE_CODE (ptr) != MEM_REF)
344 return 0;
345
346 /* Add the MEM_REF byte offset. */
347 tree mem_off = TREE_OPERAND (ptr, 1);
348 off = fold_build2 (PLUS_EXPR, TREE_TYPE (off), off, mem_off);
349 ptr = TREE_OPERAND (ptr, 0);
350 }
351 else if (rhs_code == POINTER_PLUS_EXPR)
352 {
353 ptr = gimple_assign_rhs1 (def_stmt);
354 off = gimple_assign_rhs2 (def_stmt);
355 }
356 else
204a913b 357 return 0;
7802a8ec
MS
358
359 if (TREE_CODE (ptr) != SSA_NAME
360 || !tree_fits_shwi_p (off))
204a913b 361 return 0;
7802a8ec 362 HOST_WIDE_INT this_off = tree_to_shwi (off);
204a913b
JJ
363 if (this_off < 0)
364 return 0;
7802a8ec
MS
365 offset = (unsigned HOST_WIDE_INT) offset + this_off;
366 if (offset < 0)
204a913b 367 return 0;
7802a8ec 368 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)])
204a913b 369 {
526ceb68 370 strinfo *si
7802a8ec
MS
371 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)]);
372 if (si && compare_nonzero_chars (si, offset) >= 0)
373 return get_stridx_plus_constant (si, offset, exp);
204a913b 374 }
7802a8ec 375 e = ptr;
204a913b
JJ
376 }
377 return 0;
378 }
8b57bfeb
JJ
379
380 if (TREE_CODE (exp) == ADDR_EXPR)
381 {
e3f9a279 382 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
8b57bfeb
JJ
383 if (idx != 0)
384 return idx;
385 }
386
6ab24ea8
MS
387 const char *p = c_getstr (exp);
388 if (p)
389 return ~(int) strlen (p);
b3c3685a 390
8b57bfeb
JJ
391 return 0;
392}
393
394/* Return true if strinfo vector is shared with the immediate dominator. */
395
396static inline bool
397strinfo_shared (void)
398{
9771b263
DN
399 return vec_safe_length (stridx_to_strinfo)
400 && (*stridx_to_strinfo)[0] != NULL;
8b57bfeb
JJ
401}
402
403/* Unshare strinfo vector that is shared with the immediate dominator. */
404
405static void
406unshare_strinfo_vec (void)
407{
526ceb68 408 strinfo *si;
8b57bfeb
JJ
409 unsigned int i = 0;
410
411 gcc_assert (strinfo_shared ());
9771b263
DN
412 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
413 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
8b57bfeb
JJ
414 if (si != NULL)
415 si->refcount++;
9771b263 416 (*stridx_to_strinfo)[0] = NULL;
8b57bfeb
JJ
417}
418
419/* Attempt to create a string index for exp, ADDR_EXPR's operand.
420 Return a pointer to the location where the string index can
421 be stored (if 0) or is stored, or NULL if this can't be tracked. */
422
423static int *
424addr_stridxptr (tree exp)
425{
8b57bfeb
JJ
426 HOST_WIDE_INT off;
427
a90c8804
RS
428 poly_int64 poff;
429 tree base = get_addr_base_and_unit_offset (exp, &poff);
430 if (base == NULL_TREE || !DECL_P (base) || !poff.is_constant (&off))
8b57bfeb
JJ
431 return NULL;
432
c203e8a7 433 if (!decl_to_stridxlist_htab)
8b57bfeb 434 {
1eb68d2d 435 decl_to_stridxlist_htab
fb5c464a 436 = new hash_map<tree_decl_hash, stridxlist> (64);
8b57bfeb
JJ
437 gcc_obstack_init (&stridx_obstack);
438 }
1eb68d2d
TS
439
440 bool existed;
441 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
442 if (existed)
8b57bfeb
JJ
443 {
444 int i;
5f3cd7c3
JJ
445 stridxlist *before = NULL;
446 for (i = 0; i < 32; i++)
8b57bfeb
JJ
447 {
448 if (list->offset == off)
449 return &list->idx;
5f3cd7c3
JJ
450 if (list->offset > off && before == NULL)
451 before = list;
8b57bfeb
JJ
452 if (list->next == NULL)
453 break;
5f3cd7c3 454 list = list->next;
8b57bfeb 455 }
5f3cd7c3 456 if (i == 32)
8b57bfeb 457 return NULL;
5f3cd7c3
JJ
458 if (before)
459 {
460 list = before;
461 before = XOBNEW (&stridx_obstack, struct stridxlist);
462 *before = *list;
463 list->next = before;
464 list->offset = off;
465 list->idx = 0;
466 return &list->idx;
467 }
8b57bfeb
JJ
468 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
469 list = list->next;
470 }
1eb68d2d 471
8b57bfeb
JJ
472 list->next = NULL;
473 list->offset = off;
474 list->idx = 0;
475 return &list->idx;
476}
477
478/* Create a new string index, or return 0 if reached limit. */
479
480static int
481new_stridx (tree exp)
482{
483 int idx;
484 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
485 return 0;
486 if (TREE_CODE (exp) == SSA_NAME)
487 {
488 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
489 return 0;
490 idx = max_stridx++;
9771b263 491 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
8b57bfeb
JJ
492 return idx;
493 }
494 if (TREE_CODE (exp) == ADDR_EXPR)
495 {
496 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
497 if (pidx != NULL)
498 {
499 gcc_assert (*pidx == 0);
500 *pidx = max_stridx++;
501 return *pidx;
502 }
503 }
504 return 0;
505}
506
507/* Like new_stridx, but for ADDR_EXPR's operand instead. */
508
509static int
510new_addr_stridx (tree exp)
511{
512 int *pidx;
513 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
514 return 0;
515 pidx = addr_stridxptr (exp);
516 if (pidx != NULL)
517 {
518 gcc_assert (*pidx == 0);
519 *pidx = max_stridx++;
520 return *pidx;
521 }
522 return 0;
523}
524
525/* Create a new strinfo. */
526
526ceb68 527static strinfo *
e3f9a279 528new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
8b57bfeb 529{
526ceb68 530 strinfo *si = strinfo_pool.allocate ();
e3f9a279 531 si->nonzero_chars = nonzero_chars;
8b57bfeb
JJ
532 si->ptr = ptr;
533 si->stmt = NULL;
534 si->endptr = NULL_TREE;
535 si->refcount = 1;
536 si->idx = idx;
537 si->first = 0;
538 si->prev = 0;
539 si->next = 0;
540 si->writable = false;
541 si->dont_invalidate = false;
e3f9a279 542 si->full_string_p = full_string_p;
8b57bfeb
JJ
543 return si;
544}
545
546/* Decrease strinfo refcount and free it if not referenced anymore. */
547
548static inline void
526ceb68 549free_strinfo (strinfo *si)
8b57bfeb
JJ
550{
551 if (si && --si->refcount == 0)
33e7d32e 552 strinfo_pool.remove (si);
8b57bfeb
JJ
553}
554
8b57bfeb
JJ
555/* Set strinfo in the vector entry IDX to SI. */
556
557static inline void
526ceb68 558set_strinfo (int idx, strinfo *si)
8b57bfeb 559{
9771b263 560 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
8b57bfeb 561 unshare_strinfo_vec ();
9771b263
DN
562 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
563 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
564 (*stridx_to_strinfo)[idx] = si;
8b57bfeb
JJ
565}
566
862088aa
RS
567/* Return the first strinfo in the related strinfo chain
568 if all strinfos in between belong to the chain, otherwise NULL. */
569
570static strinfo *
571verify_related_strinfos (strinfo *origsi)
572{
573 strinfo *si = origsi, *psi;
574
575 if (origsi->first == 0)
576 return NULL;
577 for (; si->prev; si = psi)
578 {
579 if (si->first != origsi->first)
580 return NULL;
581 psi = get_strinfo (si->prev);
582 if (psi == NULL)
583 return NULL;
584 if (psi->next != si->idx)
585 return NULL;
586 }
587 if (si->idx != si->first)
588 return NULL;
589 return si;
590}
591
592/* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
593 Use LOC for folding. */
594
595static void
596set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
597{
598 si->endptr = endptr;
599 si->stmt = NULL;
600 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
601 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
e3f9a279
RS
602 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
603 end_as_size, start_as_size);
604 si->full_string_p = true;
862088aa
RS
605}
606
8b57bfeb
JJ
607/* Return string length, or NULL if it can't be computed. */
608
609static tree
526ceb68 610get_string_length (strinfo *si)
8b57bfeb 611{
e3f9a279
RS
612 if (si->nonzero_chars)
613 return si->full_string_p ? si->nonzero_chars : NULL;
8b57bfeb
JJ
614
615 if (si->stmt)
616 {
355fe088 617 gimple *stmt = si->stmt, *lenstmt;
83d5977e 618 tree callee, lhs, fn, tem;
8b57bfeb
JJ
619 location_t loc;
620 gimple_stmt_iterator gsi;
621
622 gcc_assert (is_gimple_call (stmt));
623 callee = gimple_call_fndecl (stmt);
3d78e008 624 gcc_assert (callee && fndecl_built_in_p (callee, BUILT_IN_NORMAL));
8b57bfeb 625 lhs = gimple_call_lhs (stmt);
8b57bfeb
JJ
626 /* unshare_strinfo is intentionally not called here. The (delayed)
627 transformation of strcpy or strcat into stpcpy is done at the place
628 of the former strcpy/strcat call and so can affect all the strinfos
629 with the same stmt. If they were unshared before and transformation
630 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
631 just compute the right length. */
632 switch (DECL_FUNCTION_CODE (callee))
633 {
634 case BUILT_IN_STRCAT:
635 case BUILT_IN_STRCAT_CHK:
636 gsi = gsi_for_stmt (stmt);
e79983f4 637 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
8b57bfeb 638 gcc_assert (lhs == NULL_TREE);
8b57bfeb 639 tem = unshare_expr (gimple_call_arg (stmt, 0));
31db0fe0 640 lenstmt = gimple_build_call (fn, 1, tem);
83d5977e 641 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
8b57bfeb
JJ
642 gimple_call_set_lhs (lenstmt, lhs);
643 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
644 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
8b57bfeb 645 tem = gimple_call_arg (stmt, 0);
33960e2e
TG
646 if (!ptrofftype_p (TREE_TYPE (lhs)))
647 {
648 lhs = convert_to_ptrofftype (lhs);
649 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
650 true, GSI_SAME_STMT);
651 }
0d0e4a03
JJ
652 lenstmt = gimple_build_assign
653 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
654 POINTER_PLUS_EXPR,tem, lhs);
8b57bfeb
JJ
655 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
656 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
657 lhs = NULL_TREE;
658 /* FALLTHRU */
659 case BUILT_IN_STRCPY:
2dcab30b 660 case BUILT_IN_STRCPY_CHK:
1e762c6a 661 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
2dcab30b
ML
662 if (gimple_call_num_args (stmt) == 2)
663 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
664 else
665 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
8b57bfeb
JJ
666 gcc_assert (lhs == NULL_TREE);
667 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
668 {
669 fprintf (dump_file, "Optimizing: ");
670 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
671 }
672 gimple_call_set_fndecl (stmt, fn);
83d5977e 673 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
8b57bfeb
JJ
674 gimple_call_set_lhs (stmt, lhs);
675 update_stmt (stmt);
676 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
677 {
678 fprintf (dump_file, "into: ");
679 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
680 }
681 /* FALLTHRU */
682 case BUILT_IN_STPCPY:
683 case BUILT_IN_STPCPY_CHK:
684 gcc_assert (lhs != NULL_TREE);
685 loc = gimple_location (stmt);
862088aa
RS
686 set_endptr_and_length (loc, si, lhs);
687 for (strinfo *chainsi = verify_related_strinfos (si);
688 chainsi != NULL;
689 chainsi = get_next_strinfo (chainsi))
e3f9a279 690 if (chainsi->nonzero_chars == NULL)
862088aa 691 set_endptr_and_length (loc, chainsi, lhs);
8b57bfeb 692 break;
24314386
MG
693 case BUILT_IN_MALLOC:
694 break;
e3f9a279 695 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
8b57bfeb
JJ
696 default:
697 gcc_unreachable ();
698 break;
699 }
700 }
701
e3f9a279 702 return si->nonzero_chars;
8b57bfeb
JJ
703}
704
705/* Invalidate string length information for strings whose length
706 might change due to stores in stmt. */
707
708static bool
355fe088 709maybe_invalidate (gimple *stmt)
8b57bfeb 710{
526ceb68 711 strinfo *si;
8b57bfeb
JJ
712 unsigned int i;
713 bool nonempty = false;
714
9771b263 715 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
8b57bfeb
JJ
716 if (si != NULL)
717 {
718 if (!si->dont_invalidate)
719 {
720 ao_ref r;
e3f9a279 721 /* Do not use si->nonzero_chars. */
8b57bfeb
JJ
722 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
723 if (stmt_may_clobber_ref_p_1 (stmt, &r))
724 {
725 set_strinfo (i, NULL);
726 free_strinfo (si);
727 continue;
728 }
729 }
730 si->dont_invalidate = false;
731 nonempty = true;
732 }
733 return nonempty;
734}
735
204a913b 736/* Unshare strinfo record SI, if it has refcount > 1 or
8b57bfeb
JJ
737 if stridx_to_strinfo vector is shared with some other
738 bbs. */
739
526ceb68
TS
740static strinfo *
741unshare_strinfo (strinfo *si)
8b57bfeb 742{
526ceb68 743 strinfo *nsi;
8b57bfeb
JJ
744
745 if (si->refcount == 1 && !strinfo_shared ())
746 return si;
747
e3f9a279 748 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
8b57bfeb
JJ
749 nsi->stmt = si->stmt;
750 nsi->endptr = si->endptr;
751 nsi->first = si->first;
752 nsi->prev = si->prev;
753 nsi->next = si->next;
754 nsi->writable = si->writable;
755 set_strinfo (si->idx, nsi);
756 free_strinfo (si);
757 return nsi;
758}
759
204a913b
JJ
760/* Attempt to create a new strinfo for BASESI + OFF, or find existing
761 strinfo if there is any. Return it's idx, or 0 if no strinfo has
762 been created. */
763
764static int
e3f9a279
RS
765get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
766 tree ptr)
204a913b 767{
5f3cd7c3 768 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
204a913b
JJ
769 return 0;
770
e3f9a279
RS
771 if (compare_nonzero_chars (basesi, off) < 0
772 || !tree_fits_uhwi_p (basesi->nonzero_chars))
204a913b
JJ
773 return 0;
774
e3f9a279
RS
775 unsigned HOST_WIDE_INT nonzero_chars
776 = tree_to_uhwi (basesi->nonzero_chars) - off;
526ceb68 777 strinfo *si = basesi, *chainsi;
204a913b
JJ
778 if (si->first || si->prev || si->next)
779 si = verify_related_strinfos (basesi);
780 if (si == NULL
e3f9a279
RS
781 || si->nonzero_chars == NULL_TREE
782 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
204a913b
JJ
783 return 0;
784
5f3cd7c3
JJ
785 if (TREE_CODE (ptr) == SSA_NAME
786 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
204a913b
JJ
787 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
788
e3f9a279 789 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
204a913b
JJ
790 for (chainsi = si; chainsi->next; chainsi = si)
791 {
bde63fde 792 si = get_next_strinfo (chainsi);
204a913b 793 if (si == NULL
e3f9a279
RS
794 || si->nonzero_chars == NULL_TREE
795 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
204a913b 796 break;
e3f9a279 797 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
204a913b
JJ
798 if (r != 1)
799 {
800 if (r == 0)
801 {
55a0f21a
JJ
802 if (TREE_CODE (ptr) == SSA_NAME)
803 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
804 else
805 {
806 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
807 if (pidx != NULL && *pidx == 0)
808 *pidx = si->idx;
809 }
204a913b
JJ
810 return si->idx;
811 }
812 break;
813 }
814 }
815
816 int idx = new_stridx (ptr);
817 if (idx == 0)
818 return 0;
e3f9a279
RS
819 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
820 basesi->full_string_p);
204a913b 821 set_strinfo (idx, si);
9c8c7338 822 if (strinfo *nextsi = get_strinfo (chainsi->next))
204a913b 823 {
9c8c7338 824 nextsi = unshare_strinfo (nextsi);
204a913b
JJ
825 si->next = nextsi->idx;
826 nextsi->prev = idx;
827 }
828 chainsi = unshare_strinfo (chainsi);
829 if (chainsi->first == 0)
830 chainsi->first = chainsi->idx;
831 chainsi->next = idx;
e3f9a279 832 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
204a913b
JJ
833 chainsi->endptr = ptr;
834 si->endptr = chainsi->endptr;
835 si->prev = chainsi->idx;
836 si->first = chainsi->first;
837 si->writable = chainsi->writable;
838 return si->idx;
839}
840
8b57bfeb
JJ
841/* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
842 to a zero-length string and if possible chain it to a related strinfo
843 chain whose part is or might be CHAINSI. */
844
526ceb68
TS
845static strinfo *
846zero_length_string (tree ptr, strinfo *chainsi)
8b57bfeb 847{
526ceb68 848 strinfo *si;
8b57bfeb 849 int idx;
204a913b
JJ
850 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
851 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
8b57bfeb 852 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
204a913b 853 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
8b57bfeb
JJ
854
855 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
856 return NULL;
857 if (chainsi != NULL)
858 {
859 si = verify_related_strinfos (chainsi);
860 if (si)
861 {
bde63fde 862 do
8b57bfeb 863 {
862088aa 864 /* We shouldn't mix delayed and non-delayed lengths. */
e3f9a279 865 gcc_assert (si->full_string_p);
bde63fde 866 if (si->endptr == NULL_TREE)
8b57bfeb 867 {
bde63fde
RS
868 si = unshare_strinfo (si);
869 si->endptr = ptr;
8b57bfeb 870 }
bde63fde
RS
871 chainsi = si;
872 si = get_next_strinfo (si);
8b57bfeb 873 }
bde63fde 874 while (si != NULL);
e3f9a279 875 if (zero_length_string_p (chainsi))
8b57bfeb
JJ
876 {
877 if (chainsi->next)
878 {
879 chainsi = unshare_strinfo (chainsi);
880 chainsi->next = 0;
881 }
9771b263 882 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
8b57bfeb
JJ
883 return chainsi;
884 }
885 }
862088aa 886 else
8b57bfeb 887 {
862088aa 888 /* We shouldn't mix delayed and non-delayed lengths. */
e3f9a279 889 gcc_assert (chainsi->full_string_p);
862088aa
RS
890 if (chainsi->first || chainsi->prev || chainsi->next)
891 {
892 chainsi = unshare_strinfo (chainsi);
893 chainsi->first = 0;
894 chainsi->prev = 0;
895 chainsi->next = 0;
896 }
8b57bfeb
JJ
897 }
898 }
899 idx = new_stridx (ptr);
900 if (idx == 0)
901 return NULL;
e3f9a279 902 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
8b57bfeb
JJ
903 set_strinfo (idx, si);
904 si->endptr = ptr;
905 if (chainsi != NULL)
906 {
907 chainsi = unshare_strinfo (chainsi);
908 if (chainsi->first == 0)
909 chainsi->first = chainsi->idx;
910 chainsi->next = idx;
93a90db6
AK
911 if (chainsi->endptr == NULL_TREE)
912 chainsi->endptr = ptr;
8b57bfeb
JJ
913 si->prev = chainsi->idx;
914 si->first = chainsi->first;
915 si->writable = chainsi->writable;
916 }
917 return si;
918}
919
e3f9a279
RS
920/* For strinfo ORIGSI whose length has been just updated, adjust other
921 related strinfos so that they match the new ORIGSI. This involves:
922
923 - adding ADJ to the nonzero_chars fields
924 - copying full_string_p from the new ORIGSI. */
8b57bfeb
JJ
925
926static void
526ceb68 927adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
8b57bfeb 928{
526ceb68 929 strinfo *si = verify_related_strinfos (origsi);
8b57bfeb
JJ
930
931 if (si == NULL)
932 return;
933
934 while (1)
935 {
526ceb68 936 strinfo *nsi;
8b57bfeb
JJ
937
938 if (si != origsi)
939 {
940 tree tem;
941
942 si = unshare_strinfo (si);
21722777
MS
943 /* We shouldn't see delayed lengths here; the caller must
944 have calculated the old length in order to calculate
945 the adjustment. */
e3f9a279
RS
946 gcc_assert (si->nonzero_chars);
947 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
948 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
949 TREE_TYPE (si->nonzero_chars),
950 si->nonzero_chars, tem);
951 si->full_string_p = origsi->full_string_p;
93a90db6 952
8b57bfeb
JJ
953 si->endptr = NULL_TREE;
954 si->dont_invalidate = true;
955 }
bde63fde
RS
956 nsi = get_next_strinfo (si);
957 if (nsi == NULL)
8b57bfeb
JJ
958 return;
959 si = nsi;
960 }
961}
962
963/* Find if there are other SSA_NAME pointers equal to PTR
964 for which we don't track their string lengths yet. If so, use
965 IDX for them. */
966
967static void
968find_equal_ptrs (tree ptr, int idx)
969{
970 if (TREE_CODE (ptr) != SSA_NAME)
971 return;
972 while (1)
973 {
355fe088 974 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
8b57bfeb
JJ
975 if (!is_gimple_assign (stmt))
976 return;
977 ptr = gimple_assign_rhs1 (stmt);
978 switch (gimple_assign_rhs_code (stmt))
979 {
980 case SSA_NAME:
981 break;
97246d78
JJ
982 CASE_CONVERT:
983 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
984 return;
985 if (TREE_CODE (ptr) == SSA_NAME)
986 break;
987 if (TREE_CODE (ptr) != ADDR_EXPR)
988 return;
989 /* FALLTHRU */
8b57bfeb
JJ
990 case ADDR_EXPR:
991 {
992 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
993 if (pidx != NULL && *pidx == 0)
994 *pidx = idx;
995 return;
996 }
8b57bfeb
JJ
997 default:
998 return;
999 }
1000
1001 /* We might find an endptr created in this pass. Grow the
1002 vector in that case. */
9771b263
DN
1003 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
1004 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
8b57bfeb 1005
9771b263 1006 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
8b57bfeb 1007 return;
9771b263 1008 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
8b57bfeb
JJ
1009 }
1010}
1011
0ad84f34
JJ
1012/* Return true if STMT is a call to a builtin function with the right
1013 arguments and attributes that should be considered for optimization
1014 by this pass. */
1015
1016static bool
1017valid_builtin_call (gimple *stmt)
1018{
1019 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
1020 return false;
1021
1022 tree callee = gimple_call_fndecl (stmt);
f54e63df
JJ
1023 tree decl = builtin_decl_explicit (DECL_FUNCTION_CODE (callee));
1024 if (decl
1025 && decl != callee
1026 && !gimple_builtin_call_types_compatible_p (stmt, decl))
1027 return false;
1028
0ad84f34
JJ
1029 switch (DECL_FUNCTION_CODE (callee))
1030 {
1031 case BUILT_IN_MEMCMP:
1032 case BUILT_IN_MEMCMP_EQ:
f54e63df
JJ
1033 case BUILT_IN_STRCMP:
1034 case BUILT_IN_STRNCMP:
0ad84f34 1035 case BUILT_IN_STRCHR:
0ad84f34 1036 case BUILT_IN_STRLEN:
f54e63df 1037 case BUILT_IN_STRNLEN:
0ad84f34
JJ
1038 /* The above functions should be pure. Punt if they aren't. */
1039 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
1040 return false;
1041 break;
1042
1043 case BUILT_IN_CALLOC:
1044 case BUILT_IN_MALLOC:
1045 case BUILT_IN_MEMCPY:
1046 case BUILT_IN_MEMCPY_CHK:
0ad84f34
JJ
1047 case BUILT_IN_MEMPCPY:
1048 case BUILT_IN_MEMPCPY_CHK:
0ad84f34
JJ
1049 case BUILT_IN_MEMSET:
1050 case BUILT_IN_STPCPY:
1051 case BUILT_IN_STPCPY_CHK:
f54e63df
JJ
1052 case BUILT_IN_STPNCPY:
1053 case BUILT_IN_STPNCPY_CHK:
0ad84f34
JJ
1054 case BUILT_IN_STRCAT:
1055 case BUILT_IN_STRCAT_CHK:
0ad84f34
JJ
1056 case BUILT_IN_STRCPY:
1057 case BUILT_IN_STRCPY_CHK:
f54e63df
JJ
1058 case BUILT_IN_STRNCAT:
1059 case BUILT_IN_STRNCAT_CHK:
1060 case BUILT_IN_STRNCPY:
1061 case BUILT_IN_STRNCPY_CHK:
0ad84f34
JJ
1062 /* The above functions should be neither const nor pure. Punt if they
1063 aren't. */
1064 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1065 return false;
1066 break;
1067
1068 default:
1069 break;
1070 }
1071
1072 return true;
1073}
1074
8b57bfeb
JJ
1075/* If the last .MEM setter statement before STMT is
1076 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1077 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1078 just memcpy (x, y, strlen (y)). SI must be the zero length
1079 strinfo. */
1080
1081static void
526ceb68 1082adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
8b57bfeb
JJ
1083{
1084 tree vuse, callee, len;
1085 struct laststmt_struct last = laststmt;
526ceb68 1086 strinfo *lastsi, *firstsi;
f5fc4a04 1087 unsigned len_arg_no = 2;
8b57bfeb
JJ
1088
1089 laststmt.stmt = NULL;
1090 laststmt.len = NULL_TREE;
1091 laststmt.stridx = 0;
1092
1093 if (last.stmt == NULL)
1094 return;
1095
1096 vuse = gimple_vuse (stmt);
1097 if (vuse == NULL_TREE
1098 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1099 || !has_single_use (vuse))
1100 return;
1101
1102 gcc_assert (last.stridx > 0);
1103 lastsi = get_strinfo (last.stridx);
1104 if (lastsi == NULL)
1105 return;
1106
1107 if (lastsi != si)
1108 {
1109 if (lastsi->first == 0 || lastsi->first != si->first)
1110 return;
1111
1112 firstsi = verify_related_strinfos (si);
1113 if (firstsi == NULL)
1114 return;
1115 while (firstsi != lastsi)
1116 {
bde63fde
RS
1117 firstsi = get_next_strinfo (firstsi);
1118 if (firstsi == NULL)
8b57bfeb 1119 return;
8b57bfeb
JJ
1120 }
1121 }
1122
e3f9a279
RS
1123 if (!is_strcat && !zero_length_string_p (si))
1124 return;
8b57bfeb
JJ
1125
1126 if (is_gimple_assign (last.stmt))
1127 {
1128 gimple_stmt_iterator gsi;
1129
1130 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1131 return;
36bbc05d 1132 if (stmt_could_throw_p (cfun, last.stmt))
8b57bfeb
JJ
1133 return;
1134 gsi = gsi_for_stmt (last.stmt);
1135 unlink_stmt_vdef (last.stmt);
1136 release_defs (last.stmt);
1137 gsi_remove (&gsi, true);
1138 return;
1139 }
1140
0ad84f34 1141 if (!valid_builtin_call (last.stmt))
8b57bfeb
JJ
1142 return;
1143
3626621a 1144 callee = gimple_call_fndecl (last.stmt);
8b57bfeb
JJ
1145 switch (DECL_FUNCTION_CODE (callee))
1146 {
1147 case BUILT_IN_MEMCPY:
1148 case BUILT_IN_MEMCPY_CHK:
1149 break;
1150 default:
1151 return;
1152 }
1153
f5fc4a04 1154 len = gimple_call_arg (last.stmt, len_arg_no);
cc269bb6 1155 if (tree_fits_uhwi_p (len))
8b57bfeb 1156 {
cc269bb6 1157 if (!tree_fits_uhwi_p (last.len)
8b57bfeb 1158 || integer_zerop (len)
7d362f6c 1159 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
8b57bfeb
JJ
1160 return;
1161 /* Don't adjust the length if it is divisible by 4, it is more efficient
1162 to store the extra '\0' in that case. */
7d362f6c 1163 if ((tree_to_uhwi (len) & 3) == 0)
8b57bfeb 1164 return;
7d4ae1fb
BE
1165
1166 /* Don't fold away an out of bounds access, as this defeats proper
1167 warnings. */
1168 tree dst = gimple_call_arg (last.stmt, 0);
1169 tree size = compute_objsize (dst, 0);
1170 if (size && tree_int_cst_lt (size, len))
1171 return;
8b57bfeb
JJ
1172 }
1173 else if (TREE_CODE (len) == SSA_NAME)
1174 {
355fe088 1175 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
8b57bfeb
JJ
1176 if (!is_gimple_assign (def_stmt)
1177 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1178 || gimple_assign_rhs1 (def_stmt) != last.len
1179 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1180 return;
1181 }
1182 else
1183 return;
1184
f5fc4a04 1185 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
8b57bfeb
JJ
1186 update_stmt (last.stmt);
1187}
1188
d4bf6975
MS
1189/* For an LHS that is an SSA_NAME that is the result of a strlen()
1190 call, or when BOUND is non-null, of a strnlen() call, set LHS
1191 range info to [0, min (MAX, BOUND)] when the range includes more
1192 than one value and return LHS. Otherwise, when the range
1193 [MIN, MAX] is such that MIN == MAX, return the tree representation
1194 of (MIN). The latter allows callers to fold suitable strnlen() calls
1195 to constants. */
1196
1197tree
1198set_strlen_range (tree lhs, wide_int max, tree bound /* = NULL_TREE */)
06199618 1199{
a7bf6c08
MS
1200 if (TREE_CODE (lhs) != SSA_NAME
1201 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
781ff3d8 1202 return NULL_TREE;
06199618 1203
781ff3d8 1204 wide_int min = wi::zero (max.get_precision ());
06199618 1205
781ff3d8
MS
1206 if (bound)
1207 {
1208 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1209 is less than the size of the array set MAX to it. It it's
1210 greater than MAX and MAX is non-zero bump MAX down to account
1211 for the necessary terminating nul. Otherwise leave it alone. */
1212 if (TREE_CODE (bound) == INTEGER_CST)
1213 {
1214 wide_int wibnd = wi::to_wide (bound);
1215 int cmp = wi::cmpu (wibnd, max);
1216 if (cmp < 0)
1217 max = wibnd;
1218 else if (cmp && wi::ne_p (max, min))
1219 --max;
1220 }
1221 else if (TREE_CODE (bound) == SSA_NAME)
1222 {
1223 wide_int minbound, maxbound;
54994253 1224 value_range_kind rng = get_range_info (bound, &minbound, &maxbound);
781ff3d8
MS
1225 if (rng == VR_RANGE)
1226 {
1227 /* For a bound in a known range, adjust the range determined
1228 above as necessary. For a bound in some anti-range or
d4bf6975 1229 in an unknown range, use the range determined by callers. */
781ff3d8
MS
1230 if (wi::ltu_p (minbound, min))
1231 min = minbound;
1232 if (wi::ltu_p (maxbound, max))
1233 max = maxbound;
1234 }
1235 }
1236 }
1237
1238 if (min == max)
1239 return wide_int_to_tree (size_type_node, min);
1240
1241 set_range_info (lhs, VR_RANGE, min, max);
1242 return lhs;
06199618
MS
1243}
1244
d4bf6975
MS
1245/* For an LHS that is an SSA_NAME and for strlen() or strnlen() argument
1246 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1247 a character array A[N] with unknown length bounded by N, and for
1248 strnlen(), by min (N, BOUND). */
1249
1250static tree
1251maybe_set_strlen_range (tree lhs, tree src, tree bound)
1252{
1253 if (TREE_CODE (lhs) != SSA_NAME
1254 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
1255 return NULL_TREE;
1256
1257 if (TREE_CODE (src) == SSA_NAME)
1258 {
1259 gimple *def = SSA_NAME_DEF_STMT (src);
1260 if (is_gimple_assign (def)
1261 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1262 src = gimple_assign_rhs1 (def);
1263 }
1264
1265 /* The longest string is PTRDIFF_MAX - 1 bytes including the final
1266 NUL so that the difference between a pointer to just past it and
1267 one to its beginning is positive. */
1268 wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)) - 2;
1269
1270 if (TREE_CODE (src) == ADDR_EXPR)
1271 {
1272 /* The last array member of a struct can be bigger than its size
1273 suggests if it's treated as a poor-man's flexible array member. */
1274 src = TREE_OPERAND (src, 0);
1275 if (TREE_CODE (src) != MEM_REF
1276 && !array_at_struct_end_p (src))
1277 {
1278 tree type = TREE_TYPE (src);
1279 tree size = TYPE_SIZE_UNIT (type);
1280 if (size
1281 && TREE_CODE (size) == INTEGER_CST
1282 && !integer_zerop (size))
1283 {
1284 /* Even though such uses of strlen would be undefined,
1285 avoid relying on arrays of arrays in case some genius
1286 decides to call strlen on an unterminated array element
1287 that's followed by a terminated one. Likewise, avoid
1288 assuming that a struct array member is necessarily
1289 nul-terminated (the nul may be in the member that
1290 follows). In those cases, assume that the length
1291 of the string stored in such an array is bounded
1292 by the size of the enclosing object if one can be
1293 determined. */
1294 tree base = get_base_address (src);
1295 if (VAR_P (base))
1296 {
1297 if (tree size = DECL_SIZE_UNIT (base))
1298 if (size
1299 && TREE_CODE (size) == INTEGER_CST
1300 && TREE_CODE (TREE_TYPE (base)) != POINTER_TYPE)
1301 max = wi::to_wide (size);
1302 }
1303 }
1304
1305 /* For strlen() the upper bound above is equal to
1306 the longest string that can be stored in the array
1307 (i.e., it accounts for the terminating nul. For
1308 strnlen() bump up the maximum by one since the array
1309 need not be nul-terminated. */
1310 if (!bound && max != 0)
1311 --max;
1312 }
1313 }
1314
1315 return set_strlen_range (lhs, max, bound);
1316}
1317
8b57bfeb
JJ
1318/* Handle a strlen call. If strlen of the argument is known, replace
1319 the strlen call with the known value, otherwise remember that strlen
1320 of the argument is stored in the lhs SSA_NAME. */
1321
1322static void
1323handle_builtin_strlen (gimple_stmt_iterator *gsi)
1324{
355fe088 1325 gimple *stmt = gsi_stmt (*gsi);
8b57bfeb
JJ
1326 tree lhs = gimple_call_lhs (stmt);
1327
1328 if (lhs == NULL_TREE)
1329 return;
1330
781ff3d8
MS
1331 location_t loc = gimple_location (stmt);
1332 tree callee = gimple_call_fndecl (stmt);
1333 tree src = gimple_call_arg (stmt, 0);
1334 tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
1335 ? gimple_call_arg (stmt, 1) : NULL_TREE);
1336 int idx = get_stridx (src);
9bc83f27 1337 if (idx || (bound && integer_zerop (bound)))
8b57bfeb 1338 {
526ceb68 1339 strinfo *si = NULL;
8b57bfeb
JJ
1340 tree rhs;
1341
1342 if (idx < 0)
1343 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
9bc83f27
JJ
1344 else if (idx == 0)
1345 rhs = bound;
8b57bfeb
JJ
1346 else
1347 {
1348 rhs = NULL_TREE;
1349 si = get_strinfo (idx);
1350 if (si != NULL)
9bc83f27
JJ
1351 {
1352 rhs = get_string_length (si);
1353 /* For strnlen, if bound is constant, even if si is not known
1354 to be zero terminated, if we know at least bound bytes are
1355 not zero, the return value will be bound. */
1356 if (rhs == NULL_TREE
1357 && bound != NULL_TREE
1358 && TREE_CODE (bound) == INTEGER_CST
1359 && si->nonzero_chars != NULL_TREE
1360 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
1361 && tree_int_cst_le (bound, si->nonzero_chars))
1362 rhs = bound;
1363 }
8b57bfeb
JJ
1364 }
1365 if (rhs != NULL_TREE)
1366 {
1367 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1368 {
1369 fprintf (dump_file, "Optimizing: ");
1370 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1371 }
1372 rhs = unshare_expr (rhs);
1373 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
781ff3d8 1374 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
b36bc89e 1375
781ff3d8 1376 if (bound)
9bc83f27 1377 rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
b36bc89e 1378
8b57bfeb
JJ
1379 if (!update_call_from_tree (gsi, rhs))
1380 gimplify_and_update_call_from_tree (gsi, rhs);
1381 stmt = gsi_stmt (*gsi);
1382 update_stmt (stmt);
1383 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1384 {
1385 fprintf (dump_file, "into: ");
1386 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1387 }
b36bc89e 1388
8b57bfeb 1389 if (si != NULL
9bc83f27
JJ
1390 /* Don't update anything for strnlen. */
1391 && bound == NULL_TREE
e3f9a279
RS
1392 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1393 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
8b57bfeb
JJ
1394 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1395 {
1396 si = unshare_strinfo (si);
e3f9a279
RS
1397 si->nonzero_chars = lhs;
1398 gcc_assert (si->full_string_p);
8b57bfeb 1399 }
025d57f0 1400
9bc83f27
JJ
1401 if (strlen_to_stridx
1402 && (bound == NULL_TREE
1403 /* For strnlen record this only if the call is proven
1404 to return the same value as strlen would. */
1405 || (TREE_CODE (bound) == INTEGER_CST
1406 && TREE_CODE (rhs) == INTEGER_CST
1407 && tree_int_cst_lt (rhs, bound))))
781ff3d8
MS
1408 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1409
8b57bfeb
JJ
1410 return;
1411 }
1412 }
1413 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1414 return;
b36bc89e 1415
8b57bfeb
JJ
1416 if (idx == 0)
1417 idx = new_stridx (src);
e3f9a279
RS
1418 else
1419 {
1420 strinfo *si = get_strinfo (idx);
1421 if (si != NULL)
1422 {
1423 if (!si->full_string_p && !si->stmt)
1424 {
1425 /* Until now we only had a lower bound on the string length.
1426 Install LHS as the actual length. */
1427 si = unshare_strinfo (si);
1aad7106 1428 tree old = si->nonzero_chars;
e3f9a279
RS
1429 si->nonzero_chars = lhs;
1430 si->full_string_p = true;
1aad7106
RS
1431 if (TREE_CODE (old) == INTEGER_CST)
1432 {
1aad7106
RS
1433 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1434 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1435 TREE_TYPE (lhs), lhs, old);
1436 adjust_related_strinfos (loc, si, adj);
1437 }
1438 else
1439 {
1440 si->first = 0;
1441 si->prev = 0;
1442 si->next = 0;
1443 }
e3f9a279
RS
1444 }
1445 return;
1446 }
1447 }
8b57bfeb
JJ
1448 if (idx)
1449 {
b36bc89e
MS
1450 if (!bound)
1451 {
1452 /* Only store the new length information for calls to strlen(),
1453 not for those to strnlen(). */
1454 strinfo *si = new_strinfo (src, idx, lhs, true);
1455 set_strinfo (idx, si);
1456 find_equal_ptrs (src, idx);
1457 }
025d57f0 1458
06199618 1459 /* For SRC that is an array of N elements, set LHS's range
781ff3d8
MS
1460 to [0, min (N, BOUND)]. A constant return value means
1461 the range would have consisted of a single value. In
1462 that case, fold the result into the returned constant. */
1463 if (tree ret = maybe_set_strlen_range (lhs, src, bound))
1464 if (TREE_CODE (ret) == INTEGER_CST)
1465 {
1466 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1467 {
1468 fprintf (dump_file, "Optimizing: ");
1469 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1470 }
1471 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
1472 ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
1473 if (!update_call_from_tree (gsi, ret))
1474 gimplify_and_update_call_from_tree (gsi, ret);
1475 stmt = gsi_stmt (*gsi);
1476 update_stmt (stmt);
1477 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1478 {
1479 fprintf (dump_file, "into: ");
1480 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1481 }
1482 }
06199618 1483
b36bc89e 1484 if (strlen_to_stridx && !bound)
781ff3d8 1485 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
8b57bfeb
JJ
1486 }
1487}
1488
1489/* Handle a strchr call. If strlen of the first argument is known, replace
1490 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1491 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1492
1493static void
1494handle_builtin_strchr (gimple_stmt_iterator *gsi)
1495{
1496 int idx;
1497 tree src;
355fe088 1498 gimple *stmt = gsi_stmt (*gsi);
8b57bfeb
JJ
1499 tree lhs = gimple_call_lhs (stmt);
1500
1501 if (lhs == NULL_TREE)
1502 return;
1503
31db0fe0 1504 if (!integer_zerop (gimple_call_arg (stmt, 1)))
8b57bfeb
JJ
1505 return;
1506
1507 src = gimple_call_arg (stmt, 0);
1508 idx = get_stridx (src);
1509 if (idx)
1510 {
526ceb68 1511 strinfo *si = NULL;
8b57bfeb
JJ
1512 tree rhs;
1513
1514 if (idx < 0)
1515 rhs = build_int_cst (size_type_node, ~idx);
1516 else
1517 {
1518 rhs = NULL_TREE;
1519 si = get_strinfo (idx);
1520 if (si != NULL)
1521 rhs = get_string_length (si);
1522 }
1523 if (rhs != NULL_TREE)
1524 {
1525 location_t loc = gimple_location (stmt);
1526
1527 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1528 {
1529 fprintf (dump_file, "Optimizing: ");
1530 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1531 }
1532 if (si != NULL && si->endptr != NULL_TREE)
1533 {
1534 rhs = unshare_expr (si->endptr);
1535 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1536 TREE_TYPE (rhs)))
1537 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1538 }
1539 else
1540 {
1541 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1542 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1543 TREE_TYPE (src), src, rhs);
1544 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1545 TREE_TYPE (rhs)))
1546 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1547 }
1548 if (!update_call_from_tree (gsi, rhs))
1549 gimplify_and_update_call_from_tree (gsi, rhs);
1550 stmt = gsi_stmt (*gsi);
1551 update_stmt (stmt);
1552 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1553 {
1554 fprintf (dump_file, "into: ");
1555 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1556 }
1557 if (si != NULL
1558 && si->endptr == NULL_TREE
1559 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1560 {
1561 si = unshare_strinfo (si);
1562 si->endptr = lhs;
1563 }
1564 zero_length_string (lhs, si);
1565 return;
1566 }
1567 }
1568 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1569 return;
1570 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1571 {
1572 if (idx == 0)
1573 idx = new_stridx (src);
1574 else if (get_strinfo (idx) != NULL)
1575 {
1576 zero_length_string (lhs, NULL);
1577 return;
1578 }
1579 if (idx)
1580 {
1581 location_t loc = gimple_location (stmt);
1582 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1583 tree srcu = fold_convert_loc (loc, size_type_node, src);
1584 tree length = fold_build2_loc (loc, MINUS_EXPR,
1585 size_type_node, lhsu, srcu);
e3f9a279 1586 strinfo *si = new_strinfo (src, idx, length, true);
8b57bfeb
JJ
1587 si->endptr = lhs;
1588 set_strinfo (idx, si);
1589 find_equal_ptrs (src, idx);
1590 zero_length_string (lhs, si);
1591 }
1592 }
1593 else
1594 zero_length_string (lhs, NULL);
1595}
1596
1597/* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1598 If strlen of the second argument is known, strlen of the first argument
1599 is the same after this call. Furthermore, attempt to convert it to
1600 memcpy. */
1601
1602static void
1603handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1604{
1605 int idx, didx;
cc8bea0a 1606 tree src, dst, srclen, len, lhs, type, fn, oldlen;
8b57bfeb 1607 bool success;
355fe088 1608 gimple *stmt = gsi_stmt (*gsi);
526ceb68 1609 strinfo *si, *dsi, *olddsi, *zsi;
8b57bfeb
JJ
1610 location_t loc;
1611
31db0fe0 1612 src = gimple_call_arg (stmt, 1);
8b57bfeb
JJ
1613 dst = gimple_call_arg (stmt, 0);
1614 lhs = gimple_call_lhs (stmt);
1615 idx = get_stridx (src);
1616 si = NULL;
1617 if (idx > 0)
1618 si = get_strinfo (idx);
1619
1620 didx = get_stridx (dst);
1621 olddsi = NULL;
1622 oldlen = NULL_TREE;
1623 if (didx > 0)
1624 olddsi = get_strinfo (didx);
1625 else if (didx < 0)
1626 return;
1627
1628 if (olddsi != NULL)
1629 adjust_last_stmt (olddsi, stmt, false);
1630
1631 srclen = NULL_TREE;
1632 if (si != NULL)
1633 srclen = get_string_length (si);
1634 else if (idx < 0)
1635 srclen = build_int_cst (size_type_node, ~idx);
1636
1637 loc = gimple_location (stmt);
1638 if (srclen == NULL_TREE)
1639 switch (bcode)
1640 {
1641 case BUILT_IN_STRCPY:
1642 case BUILT_IN_STRCPY_CHK:
e79983f4 1643 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
8b57bfeb
JJ
1644 return;
1645 break;
1646 case BUILT_IN_STPCPY:
1647 case BUILT_IN_STPCPY_CHK:
1648 if (lhs == NULL_TREE)
1649 return;
1650 else
1651 {
1652 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1653 srclen = fold_convert_loc (loc, size_type_node, dst);
1654 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1655 lhsuint, srclen);
1656 }
1657 break;
1658 default:
1659 gcc_unreachable ();
1660 }
1661
1662 if (didx == 0)
1663 {
1664 didx = new_stridx (dst);
1665 if (didx == 0)
1666 return;
1667 }
1668 if (olddsi != NULL)
1669 {
e3f9a279 1670 oldlen = olddsi->nonzero_chars;
8b57bfeb 1671 dsi = unshare_strinfo (olddsi);
e3f9a279
RS
1672 dsi->nonzero_chars = srclen;
1673 dsi->full_string_p = (srclen != NULL_TREE);
8b57bfeb
JJ
1674 /* Break the chain, so adjust_related_strinfo on later pointers in
1675 the chain won't adjust this one anymore. */
1676 dsi->next = 0;
1677 dsi->stmt = NULL;
1678 dsi->endptr = NULL_TREE;
1679 }
1680 else
1681 {
e3f9a279 1682 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
8b57bfeb
JJ
1683 set_strinfo (didx, dsi);
1684 find_equal_ptrs (dst, didx);
1685 }
1686 dsi->writable = true;
1687 dsi->dont_invalidate = true;
1688
e3f9a279 1689 if (dsi->nonzero_chars == NULL_TREE)
8b57bfeb 1690 {
526ceb68 1691 strinfo *chainsi;
93a90db6 1692
8b57bfeb
JJ
1693 /* If string length of src is unknown, use delayed length
1694 computation. If string lenth of dst will be needed, it
1695 can be computed by transforming this strcpy call into
1696 stpcpy and subtracting dst from the return value. */
93a90db6
AK
1697
1698 /* Look for earlier strings whose length could be determined if
1699 this strcpy is turned into an stpcpy. */
1700
1701 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1702 {
1703 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1704 {
1705 /* When setting a stmt for delayed length computation
1706 prevent all strinfos through dsi from being
1707 invalidated. */
1708 chainsi = unshare_strinfo (chainsi);
1709 chainsi->stmt = stmt;
e3f9a279
RS
1710 chainsi->nonzero_chars = NULL_TREE;
1711 chainsi->full_string_p = false;
93a90db6
AK
1712 chainsi->endptr = NULL_TREE;
1713 chainsi->dont_invalidate = true;
1714 }
1715 }
8b57bfeb 1716 dsi->stmt = stmt;
cc8bea0a
MS
1717
1718 /* Try to detect overlap before returning. This catches cases
1719 like strcpy (d, d + n) where n is non-constant whose range
1720 is such that (n <= strlen (d) holds).
1721
1722 OLDDSI->NONZERO_chars may have been reset by this point with
1723 oldlen holding it original value. */
1724 if (olddsi && oldlen)
1725 {
1726 /* Add 1 for the terminating NUL. */
1727 tree type = TREE_TYPE (oldlen);
1728 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1729 build_int_cst (type, 1));
8a45b051 1730 check_bounds_or_overlap (stmt, olddsi->ptr, src, oldlen, NULL_TREE);
cc8bea0a
MS
1731 }
1732
8b57bfeb
JJ
1733 return;
1734 }
1735
1736 if (olddsi != NULL)
1737 {
1738 tree adj = NULL_TREE;
1739 if (oldlen == NULL_TREE)
1740 ;
1741 else if (integer_zerop (oldlen))
1742 adj = srclen;
1743 else if (TREE_CODE (oldlen) == INTEGER_CST
1744 || TREE_CODE (srclen) == INTEGER_CST)
1745 adj = fold_build2_loc (loc, MINUS_EXPR,
1746 TREE_TYPE (srclen), srclen,
1747 fold_convert_loc (loc, TREE_TYPE (srclen),
1748 oldlen));
1749 if (adj != NULL_TREE)
1750 adjust_related_strinfos (loc, dsi, adj);
1751 else
1752 dsi->prev = 0;
1753 }
1754 /* strcpy src may not overlap dst, so src doesn't need to be
1755 invalidated either. */
1756 if (si != NULL)
1757 si->dont_invalidate = true;
1758
1759 fn = NULL_TREE;
1760 zsi = NULL;
1761 switch (bcode)
1762 {
1763 case BUILT_IN_STRCPY:
e79983f4 1764 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
8b57bfeb 1765 if (lhs)
9771b263 1766 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
8b57bfeb
JJ
1767 break;
1768 case BUILT_IN_STRCPY_CHK:
e79983f4 1769 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
8b57bfeb 1770 if (lhs)
9771b263 1771 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
8b57bfeb
JJ
1772 break;
1773 case BUILT_IN_STPCPY:
1774 /* This would need adjustment of the lhs (subtract one),
1775 or detection that the trailing '\0' doesn't need to be
1776 written, if it will be immediately overwritten.
e79983f4 1777 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
8b57bfeb
JJ
1778 if (lhs)
1779 {
1780 dsi->endptr = lhs;
1781 zsi = zero_length_string (lhs, dsi);
1782 }
1783 break;
1784 case BUILT_IN_STPCPY_CHK:
1785 /* This would need adjustment of the lhs (subtract one),
1786 or detection that the trailing '\0' doesn't need to be
1787 written, if it will be immediately overwritten.
e79983f4 1788 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
8b57bfeb
JJ
1789 if (lhs)
1790 {
1791 dsi->endptr = lhs;
1792 zsi = zero_length_string (lhs, dsi);
1793 }
1794 break;
1795 default:
1796 gcc_unreachable ();
1797 }
1798 if (zsi != NULL)
1799 zsi->dont_invalidate = true;
1800
cc8bea0a
MS
1801 if (fn)
1802 {
1803 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1804 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1805 }
1806 else
1807 type = size_type_node;
8b57bfeb
JJ
1808
1809 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1810 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
cc8bea0a
MS
1811
1812 /* Set the no-warning bit on the transformed statement? */
1813 bool set_no_warning = false;
1814
1815 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1816 if (si
213694e5 1817 && check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
cc8bea0a
MS
1818 {
1819 gimple_set_no_warning (stmt, true);
1820 set_no_warning = true;
1821 }
1822
1823 if (fn == NULL_TREE)
1824 return;
1825
8b57bfeb
JJ
1826 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1827 GSI_SAME_STMT);
1828 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1829 {
1830 fprintf (dump_file, "Optimizing: ");
1831 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1832 }
31db0fe0
ML
1833 if (gimple_call_num_args (stmt) == 2)
1834 success = update_gimple_call (gsi, fn, 3, dst, src, len);
8b57bfeb 1835 else
31db0fe0
ML
1836 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1837 gimple_call_arg (stmt, 2));
8b57bfeb
JJ
1838 if (success)
1839 {
1840 stmt = gsi_stmt (*gsi);
1841 update_stmt (stmt);
1842 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1843 {
1844 fprintf (dump_file, "into: ");
1845 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1846 }
1847 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1848 laststmt.stmt = stmt;
1849 laststmt.len = srclen;
1850 laststmt.stridx = dsi->idx;
1851 }
1852 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1853 fprintf (dump_file, "not possible.\n");
cc8bea0a
MS
1854
1855 if (set_no_warning)
1856 gimple_set_no_warning (stmt, true);
1857}
1858
1859/* Check the size argument to the built-in forms of stpncpy and strncpy
1860 for out-of-bounds offsets or overlapping access, and to see if the
1861 size argument is derived from a call to strlen() on the source argument,
1862 and if so, issue an appropriate warning. */
1863
1864static void
1865handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1866{
1867 /* Same as stxncpy(). */
1868 handle_builtin_stxncpy (bcode, gsi);
8b57bfeb
JJ
1869}
1870
025d57f0
MS
1871/* Return true if LEN depends on a call to strlen(SRC) in an interesting
1872 way. LEN can either be an integer expression, or a pointer (to char).
1873 When it is the latter (such as in recursive calls to self) is is
1874 assumed to be the argument in some call to strlen() whose relationship
1875 to SRC is being ascertained. */
1876
4252ccd7 1877bool
025d57f0
MS
1878is_strlen_related_p (tree src, tree len)
1879{
1880 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1881 && operand_equal_p (src, len, 0))
1882 return true;
1883
1884 if (TREE_CODE (len) != SSA_NAME)
1885 return false;
1886
1887 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1888 if (!def_stmt)
1889 return false;
1890
1891 if (is_gimple_call (def_stmt))
1892 {
1893 tree func = gimple_call_fndecl (def_stmt);
1894 if (!valid_builtin_call (def_stmt)
1895 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1896 return false;
1897
1898 tree arg = gimple_call_arg (def_stmt, 0);
1899 return is_strlen_related_p (src, arg);
1900 }
1901
1902 if (!is_gimple_assign (def_stmt))
1903 return false;
1904
1905 tree_code code = gimple_assign_rhs_code (def_stmt);
1906 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1907 tree rhstype = TREE_TYPE (rhs1);
1908
1909 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1910 || (INTEGRAL_TYPE_P (rhstype)
1911 && (code == BIT_AND_EXPR
1912 || code == NOP_EXPR)))
1913 {
4252ccd7
MS
1914 /* Pointer plus (an integer), and truncation are considered among
1915 the (potentially) related expressions to strlen. */
025d57f0
MS
1916 return is_strlen_related_p (src, rhs1);
1917 }
1918
4252ccd7
MS
1919 if (tree rhs2 = gimple_assign_rhs2 (def_stmt))
1920 {
1921 /* Integer subtraction is considered strlen-related when both
1922 arguments are integers and second one is strlen-related. */
1923 rhstype = TREE_TYPE (rhs2);
1924 if (INTEGRAL_TYPE_P (rhstype) && code == MINUS_EXPR)
1925 return is_strlen_related_p (src, rhs2);
1926 }
1927
025d57f0
MS
1928 return false;
1929}
1930
5d0d5d68
MS
1931/* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1932 in gimple-fold.c.
1933 Check to see if the specified bound is a) equal to the size of
1934 the destination DST and if so, b) if it's immediately followed by
1935 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1936 do nothing. Return true if diagnostic has been issued.
025d57f0
MS
1937
1938 The purpose is to diagnose calls to strncpy and stpncpy that do
1939 not nul-terminate the copy while allowing for the idiom where
1940 such a call is immediately followed by setting the last element
1941 to nul, as in:
1942 char a[32];
1943 strncpy (a, s, sizeof a);
1944 a[sizeof a - 1] = '\0';
1945*/
1946
5d0d5d68 1947bool
025d57f0
MS
1948maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1949{
025d57f0 1950 gimple *stmt = gsi_stmt (gsi);
e9b9fa4c
MS
1951 if (gimple_no_warning_p (stmt))
1952 return false;
025d57f0
MS
1953
1954 wide_int cntrange[2];
1955
1956 if (TREE_CODE (cnt) == INTEGER_CST)
1957 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1958 else if (TREE_CODE (cnt) == SSA_NAME)
1959 {
54994253 1960 enum value_range_kind rng = get_range_info (cnt, cntrange, cntrange + 1);
025d57f0
MS
1961 if (rng == VR_RANGE)
1962 ;
1963 else if (rng == VR_ANTI_RANGE)
1964 {
1965 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1966
1967 if (wi::ltu_p (cntrange[1], maxobjsize))
1968 {
1969 cntrange[0] = cntrange[1] + 1;
1970 cntrange[1] = maxobjsize;
1971 }
1972 else
1973 {
1974 cntrange[1] = cntrange[0] - 1;
1975 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1976 }
1977 }
1978 else
1979 return false;
1980 }
1981 else
1982 return false;
1983
1984 /* Negative value is the constant string length. If it's less than
5d0d5d68
MS
1985 the lower bound there is no truncation. Avoid calling get_stridx()
1986 when ssa_ver_to_stridx is empty. That implies the caller isn't
1987 running under the control of this pass and ssa_ver_to_stridx hasn't
1988 been created yet. */
1989 int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
025d57f0
MS
1990 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1991 return false;
1992
1993 tree dst = gimple_call_arg (stmt, 0);
025d57f0
MS
1994 tree dstdecl = dst;
1995 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1996 dstdecl = TREE_OPERAND (dstdecl, 0);
1997
6a33d0ff 1998 tree ref = NULL_TREE;
4252ccd7
MS
1999
2000 if (!sidx)
2001 {
2002 /* If the source is a non-string return early to avoid warning
2003 for possible truncation (if the truncation is certain SIDX
2004 is non-zero). */
2005 tree srcdecl = gimple_call_arg (stmt, 1);
2006 if (TREE_CODE (srcdecl) == ADDR_EXPR)
2007 srcdecl = TREE_OPERAND (srcdecl, 0);
2008 if (get_attr_nonstring_decl (srcdecl, &ref))
2009 return false;
2010 }
2011
2012 /* Likewise, if the destination refers to a an array/pointer declared
2013 nonstring return early. */
6a33d0ff
MS
2014 if (get_attr_nonstring_decl (dstdecl, &ref))
2015 return false;
025d57f0
MS
2016
2017 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
2018 avoid the truncation warning. */
b25e5572 2019 gsi_next_nondebug (&gsi);
025d57f0 2020 gimple *next_stmt = gsi_stmt (gsi);
a76acaed
MS
2021 if (!next_stmt)
2022 {
2023 /* When there is no statement in the same basic block check
2024 the immediate successor block. */
2025 if (basic_block bb = gimple_bb (stmt))
2026 {
2027 if (single_succ_p (bb))
2028 {
2029 /* For simplicity, ignore blocks with multiple outgoing
2030 edges for now and only consider successor blocks along
2031 normal edges. */
2032 edge e = EDGE_SUCC (bb, 0);
2033 if (!(e->flags & EDGE_ABNORMAL))
2034 {
2035 gsi = gsi_start_bb (e->dest);
2036 next_stmt = gsi_stmt (gsi);
2037 if (next_stmt && is_gimple_debug (next_stmt))
2038 {
2039 gsi_next_nondebug (&gsi);
2040 next_stmt = gsi_stmt (gsi);
2041 }
2042 }
2043 }
2044 }
2045 }
025d57f0 2046
a76acaed 2047 if (next_stmt && is_gimple_assign (next_stmt))
025d57f0 2048 {
025d57f0 2049 tree lhs = gimple_assign_lhs (next_stmt);
6a33d0ff
MS
2050 tree_code code = TREE_CODE (lhs);
2051 if (code == ARRAY_REF || code == MEM_REF)
2052 lhs = TREE_OPERAND (lhs, 0);
2053
2054 tree func = gimple_call_fndecl (stmt);
2055 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
2056 {
2057 tree ret = gimple_call_lhs (stmt);
2058 if (ret && operand_equal_p (ret, lhs, 0))
2059 return false;
2060 }
2061
2062 /* Determine the base address and offset of the reference,
2063 ignoring the innermost array index. */
2064 if (TREE_CODE (ref) == ARRAY_REF)
2065 ref = TREE_OPERAND (ref, 0);
2066
a90c8804 2067 poly_int64 dstoff;
6a33d0ff
MS
2068 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
2069
a90c8804 2070 poly_int64 lhsoff;
6a33d0ff
MS
2071 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
2072 if (lhsbase
44e60df3 2073 && dstbase
a90c8804 2074 && known_eq (dstoff, lhsoff)
6a33d0ff 2075 && operand_equal_p (dstbase, lhsbase, 0))
025d57f0
MS
2076 return false;
2077 }
2078
2079 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
2080 wide_int lenrange[2];
2081 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
2082 {
2083 lenrange[0] = (sisrc->nonzero_chars
2084 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
2085 ? wi::to_wide (sisrc->nonzero_chars)
2086 : wi::zero (prec));
2087 lenrange[1] = lenrange[0];
2088 }
2089 else if (sidx < 0)
2090 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
2091 else
2092 {
5d6655eb
MS
2093 c_strlen_data lendata = { };
2094 get_range_strlen (src, &lendata, /* eltsize = */1);
2095 if (TREE_CODE (lendata.minlen) == INTEGER_CST
2096 && TREE_CODE (lendata.maxbound) == INTEGER_CST)
025d57f0 2097 {
5d6655eb
MS
2098 /* When LENDATA.MAXLEN is unknown, reset LENDATA.MINLEN
2099 which stores the length of the shortest known string. */
2100 if (integer_all_onesp (lendata.maxlen))
2101 lenrange[0] = wi::shwi (0, prec);
2102 else
2103 lenrange[0] = wi::to_wide (lendata.minlen, prec);
2104 lenrange[1] = wi::to_wide (lendata.maxbound, prec);
025d57f0
MS
2105 }
2106 else
2107 {
2108 lenrange[0] = wi::shwi (0, prec);
2109 lenrange[1] = wi::shwi (-1, prec);
2110 }
2111 }
2112
e3329a78
MS
2113 location_t callloc = gimple_nonartificial_location (stmt);
2114 callloc = expansion_point_location_if_in_system_header (callloc);
2115
025d57f0
MS
2116 tree func = gimple_call_fndecl (stmt);
2117
2118 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
2119 {
2120 /* If the longest source string is shorter than the lower bound
2121 of the specified count the copy is definitely nul-terminated. */
2122 if (wi::ltu_p (lenrange[1], cntrange[0]))
2123 return false;
2124
2125 if (wi::neg_p (lenrange[1]))
2126 {
2127 /* The length of one of the strings is unknown but at least
2128 one has non-zero length and that length is stored in
2129 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2130 warning below. */
2131 lenrange[1] = lenrange[0];
2132 lenrange[0] = wi::shwi (0, prec);
2133 }
2134
eec5f615
MS
2135 /* Set to true for strncat whose bound is derived from the length
2136 of the destination (the expected usage pattern). */
2137 bool cat_dstlen_bounded = false;
2138 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STRNCAT)
2139 cat_dstlen_bounded = is_strlen_related_p (dst, cnt);
2140
5d0d5d68 2141 if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
1c89478a
MS
2142 return warning_n (callloc, OPT_Wstringop_truncation,
2143 cntrange[0].to_uhwi (),
2144 "%G%qD output truncated before terminating "
2145 "nul copying %E byte from a string of the "
2146 "same length",
2147 "%G%qD output truncated before terminating nul "
2148 "copying %E bytes from a string of the same "
2149 "length",
8a45b051 2150 stmt, func, cnt);
eec5f615 2151 else if (!cat_dstlen_bounded)
025d57f0 2152 {
eec5f615
MS
2153 if (wi::geu_p (lenrange[0], cntrange[1]))
2154 {
2155 /* The shortest string is longer than the upper bound of
2156 the count so the truncation is certain. */
2157 if (cntrange[0] == cntrange[1])
2158 return warning_n (callloc, OPT_Wstringop_truncation,
2159 cntrange[0].to_uhwi (),
2160 "%G%qD output truncated copying %E byte "
2161 "from a string of length %wu",
2162 "%G%qD output truncated copying %E bytes "
2163 "from a string of length %wu",
8a45b051 2164 stmt, func, cnt, lenrange[0].to_uhwi ());
eec5f615
MS
2165
2166 return warning_at (callloc, OPT_Wstringop_truncation,
2167 "%G%qD output truncated copying between %wu "
2168 "and %wu bytes from a string of length %wu",
8a45b051 2169 stmt, func, cntrange[0].to_uhwi (),
eec5f615
MS
2170 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2171 }
2172 else if (wi::geu_p (lenrange[1], cntrange[1]))
2173 {
2174 /* The longest string is longer than the upper bound of
2175 the count so the truncation is possible. */
2176 if (cntrange[0] == cntrange[1])
2177 return warning_n (callloc, OPT_Wstringop_truncation,
2178 cntrange[0].to_uhwi (),
2179 "%G%qD output may be truncated copying %E "
2180 "byte from a string of length %wu",
2181 "%G%qD output may be truncated copying %E "
2182 "bytes from a string of length %wu",
8a45b051 2183 stmt, func, cnt, lenrange[1].to_uhwi ());
eec5f615
MS
2184
2185 return warning_at (callloc, OPT_Wstringop_truncation,
2186 "%G%qD output may be truncated copying between "
2187 "%wu and %wu bytes from a string of length %wu",
8a45b051 2188 stmt, func, cntrange[0].to_uhwi (),
eec5f615
MS
2189 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
2190 }
025d57f0
MS
2191 }
2192
eec5f615
MS
2193 if (!cat_dstlen_bounded
2194 && cntrange[0] != cntrange[1]
025d57f0
MS
2195 && wi::leu_p (cntrange[0], lenrange[0])
2196 && wi::leu_p (cntrange[1], lenrange[0] + 1))
2197 {
2198 /* If the source (including the terminating nul) is longer than
2199 the lower bound of the specified count but shorter than the
2200 upper bound the copy may (but need not) be truncated. */
2201 return warning_at (callloc, OPT_Wstringop_truncation,
5d0d5d68
MS
2202 "%G%qD output may be truncated copying between "
2203 "%wu and %wu bytes from a string of length %wu",
8a45b051 2204 stmt, func, cntrange[0].to_uhwi (),
025d57f0
MS
2205 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
2206 }
2207 }
2208
2209 if (tree dstsize = compute_objsize (dst, 1))
2210 {
2211 /* The source length is uknown. Try to determine the destination
2212 size and see if it matches the specified bound. If not, bail.
2213 Otherwise go on to see if it should be diagnosed for possible
2214 truncation. */
2215 if (!dstsize)
2216 return false;
2217
2218 if (wi::to_wide (dstsize) != cntrange[1])
2219 return false;
2220
3a03bffd
MS
2221 /* Avoid warning for strncpy(a, b, N) calls where the following
2222 equalities hold:
2223 N == sizeof a && N == sizeof b */
2224 if (tree srcsize = compute_objsize (src, 1))
2225 if (wi::to_wide (srcsize) == cntrange[1])
2226 return false;
2227
025d57f0
MS
2228 if (cntrange[0] == cntrange[1])
2229 return warning_at (callloc, OPT_Wstringop_truncation,
5d0d5d68 2230 "%G%qD specified bound %E equals destination size",
8a45b051 2231 stmt, func, cnt);
025d57f0
MS
2232 }
2233
2234 return false;
2235}
2236
cc8bea0a
MS
2237/* Check the arguments to the built-in forms of stpncpy and strncpy for
2238 out-of-bounds offsets or overlapping access, and to see if the size
2239 is derived from calling strlen() on the source argument, and if so,
2240 issue the appropriate warning. */
025d57f0
MS
2241
2242static void
2243handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2244{
6a33d0ff
MS
2245 if (!strlen_to_stridx)
2246 return;
2247
025d57f0
MS
2248 gimple *stmt = gsi_stmt (*gsi);
2249
31db0fe0
ML
2250 tree dst = gimple_call_arg (stmt, 0);
2251 tree src = gimple_call_arg (stmt, 1);
2252 tree len = gimple_call_arg (stmt, 2);
cc8bea0a
MS
2253 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2254
2255 int didx = get_stridx (dst);
2256 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2257 {
e3ba46bd
MS
2258 /* Compute the size of the destination string including the nul
2259 if it is known to be nul-terminated. */
cc8bea0a
MS
2260 if (sidst->nonzero_chars)
2261 {
e0748030 2262 if (sidst->full_string_p)
e3ba46bd
MS
2263 {
2264 /* String is known to be nul-terminated. */
2265 tree type = TREE_TYPE (sidst->nonzero_chars);
2266 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2267 build_int_cst (type, 1));
2268 }
2269 else
2270 dstsize = sidst->nonzero_chars;
cc8bea0a 2271 }
e3ba46bd 2272
cc8bea0a
MS
2273 dst = sidst->ptr;
2274 }
2275
2276 int sidx = get_stridx (src);
2277 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2278 if (sisrc)
2279 {
2280 /* strncat() and strncpy() can modify the source string by writing
2281 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2282 clear. */
2283
e3ba46bd
MS
2284 /* Compute the size of the source string including the terminating
2285 nul if its known to be nul-terminated. */
cc8bea0a
MS
2286 if (sisrc->nonzero_chars)
2287 {
e0748030 2288 if (sisrc->full_string_p)
e3ba46bd
MS
2289 {
2290 tree type = TREE_TYPE (sisrc->nonzero_chars);
2291 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2292 build_int_cst (type, 1));
2293 }
2294 else
2295 srcsize = sisrc->nonzero_chars;
cc8bea0a
MS
2296 }
2297
2298 src = sisrc->ptr;
2299 }
2300 else
2301 srcsize = NULL_TREE;
2302
213694e5 2303 if (check_bounds_or_overlap (stmt, dst, src, dstsize, srcsize))
cc8bea0a
MS
2304 {
2305 gimple_set_no_warning (stmt, true);
2306 return;
2307 }
025d57f0
MS
2308
2309 /* If the length argument was computed from strlen(S) for some string
2310 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2311 the location of the strlen() call (PSS->SECOND). */
6a33d0ff 2312 stridx_strlenloc *pss = strlen_to_stridx->get (len);
025d57f0
MS
2313 if (!pss || pss->first <= 0)
2314 {
2315 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2316 gimple_set_no_warning (stmt, true);
2317
2318 return;
2319 }
2320
025d57f0
MS
2321 /* Retrieve the strinfo data for the string S that LEN was computed
2322 from as some function F of strlen (S) (i.e., LEN need not be equal
2323 to strlen(S)). */
2324 strinfo *silen = get_strinfo (pss->first);
2325
e3329a78
MS
2326 location_t callloc = gimple_nonartificial_location (stmt);
2327 callloc = expansion_point_location_if_in_system_header (callloc);
025d57f0
MS
2328
2329 tree func = gimple_call_fndecl (stmt);
2330
2331 bool warned = false;
2332
2333 /* When -Wstringop-truncation is set, try to determine truncation
2334 before diagnosing possible overflow. Truncation is implied by
2335 the LEN argument being equal to strlen(SRC), regardless of
2336 whether its value is known. Otherwise, issue the more generic
2337 -Wstringop-overflow which triggers for LEN arguments that in
2338 any meaningful way depend on strlen(SRC). */
6a33d0ff
MS
2339 if (sisrc == silen
2340 && is_strlen_related_p (src, len)
2341 && warning_at (callloc, OPT_Wstringop_truncation,
5d0d5d68 2342 "%G%qD output truncated before terminating nul "
6a33d0ff 2343 "copying as many bytes from a string as its length",
8a45b051 2344 stmt, func))
6a33d0ff 2345 warned = true;
025d57f0
MS
2346 else if (silen && is_strlen_related_p (src, silen->ptr))
2347 warned = warning_at (callloc, OPT_Wstringop_overflow_,
5d0d5d68
MS
2348 "%G%qD specified bound depends on the length "
2349 "of the source argument",
8a45b051 2350 stmt, func);
025d57f0
MS
2351 if (warned)
2352 {
2353 location_t strlenloc = pss->second;
2354 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2355 inform (strlenloc, "length computed here");
2356 }
2357}
2358
8b57bfeb
JJ
2359/* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2360 If strlen of the second argument is known and length of the third argument
2361 is that plus one, strlen of the first argument is the same after this
2362 call. */
2363
2364static void
2365handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2366{
2367 int idx, didx;
2368 tree src, dst, len, lhs, oldlen, newlen;
355fe088 2369 gimple *stmt = gsi_stmt (*gsi);
526ceb68 2370 strinfo *si, *dsi, *olddsi;
8b57bfeb 2371
31db0fe0
ML
2372 len = gimple_call_arg (stmt, 2);
2373 src = gimple_call_arg (stmt, 1);
8b57bfeb
JJ
2374 dst = gimple_call_arg (stmt, 0);
2375 idx = get_stridx (src);
2376 if (idx == 0)
2377 return;
2378
2379 didx = get_stridx (dst);
2380 olddsi = NULL;
2381 if (didx > 0)
2382 olddsi = get_strinfo (didx);
2383 else if (didx < 0)
2384 return;
2385
2386 if (olddsi != NULL
cc269bb6 2387 && tree_fits_uhwi_p (len)
8b57bfeb
JJ
2388 && !integer_zerop (len))
2389 adjust_last_stmt (olddsi, stmt, false);
2390
e3f9a279 2391 bool full_string_p;
8b57bfeb
JJ
2392 if (idx > 0)
2393 {
355fe088 2394 gimple *def_stmt;
8b57bfeb 2395
e3f9a279
RS
2396 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2397 is known. */
8b57bfeb 2398 si = get_strinfo (idx);
e3f9a279 2399 if (si == NULL || si->nonzero_chars == NULL_TREE)
8b57bfeb 2400 return;
e3f9a279
RS
2401 if (TREE_CODE (len) == INTEGER_CST
2402 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2403 {
2404 if (tree_int_cst_le (len, si->nonzero_chars))
2405 {
2406 /* Copying LEN nonzero characters, where LEN is constant. */
2407 newlen = len;
2408 full_string_p = false;
2409 }
2410 else
2411 {
2412 /* Copying the whole of the analyzed part of SI. */
2413 newlen = si->nonzero_chars;
2414 full_string_p = si->full_string_p;
2415 }
2416 }
2417 else
2418 {
2419 if (!si->full_string_p)
2420 return;
2421 if (TREE_CODE (len) != SSA_NAME)
2422 return;
2423 def_stmt = SSA_NAME_DEF_STMT (len);
2424 if (!is_gimple_assign (def_stmt)
2425 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2426 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2427 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2428 return;
2429 /* Copying variable-length string SI (and no more). */
2430 newlen = si->nonzero_chars;
2431 full_string_p = true;
2432 }
8b57bfeb
JJ
2433 }
2434 else
2435 {
2436 si = NULL;
2437 /* Handle memcpy (x, "abcd", 5) or
2438 memcpy (x, "abc\0uvw", 7). */
e3f9a279 2439 if (!tree_fits_uhwi_p (len))
8b57bfeb 2440 return;
e3f9a279
RS
2441
2442 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2443 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2444 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2445 full_string_p = clen > nonzero_chars;
8b57bfeb
JJ
2446 }
2447
aca8570e
MS
2448 if (!full_string_p
2449 && olddsi
2450 && olddsi->nonzero_chars
2451 && TREE_CODE (olddsi->nonzero_chars) == INTEGER_CST
2452 && tree_int_cst_le (newlen, olddsi->nonzero_chars))
2453 {
2454 /* The SRC substring being written strictly overlaps
2455 a subsequence of the existing string OLDDSI. */
2456 newlen = olddsi->nonzero_chars;
2457 full_string_p = olddsi->full_string_p;
2458 }
2459
8b57bfeb
JJ
2460 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2461 adjust_last_stmt (olddsi, stmt, false);
2462
2463 if (didx == 0)
2464 {
2465 didx = new_stridx (dst);
2466 if (didx == 0)
2467 return;
2468 }
8b57bfeb
JJ
2469 oldlen = NULL_TREE;
2470 if (olddsi != NULL)
2471 {
2472 dsi = unshare_strinfo (olddsi);
e3f9a279
RS
2473 oldlen = olddsi->nonzero_chars;
2474 dsi->nonzero_chars = newlen;
2475 dsi->full_string_p = full_string_p;
8b57bfeb
JJ
2476 /* Break the chain, so adjust_related_strinfo on later pointers in
2477 the chain won't adjust this one anymore. */
2478 dsi->next = 0;
2479 dsi->stmt = NULL;
2480 dsi->endptr = NULL_TREE;
2481 }
2482 else
2483 {
e3f9a279 2484 dsi = new_strinfo (dst, didx, newlen, full_string_p);
8b57bfeb
JJ
2485 set_strinfo (didx, dsi);
2486 find_equal_ptrs (dst, didx);
2487 }
2488 dsi->writable = true;
2489 dsi->dont_invalidate = true;
2490 if (olddsi != NULL)
2491 {
2492 tree adj = NULL_TREE;
2493 location_t loc = gimple_location (stmt);
2494 if (oldlen == NULL_TREE)
2495 ;
2496 else if (integer_zerop (oldlen))
e3f9a279 2497 adj = newlen;
8b57bfeb 2498 else if (TREE_CODE (oldlen) == INTEGER_CST
e3f9a279
RS
2499 || TREE_CODE (newlen) == INTEGER_CST)
2500 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2501 fold_convert_loc (loc, TREE_TYPE (newlen),
8b57bfeb
JJ
2502 oldlen));
2503 if (adj != NULL_TREE)
2504 adjust_related_strinfos (loc, dsi, adj);
2505 else
2506 dsi->prev = 0;
2507 }
2508 /* memcpy src may not overlap dst, so src doesn't need to be
2509 invalidated either. */
2510 if (si != NULL)
2511 si->dont_invalidate = true;
2512
e3f9a279 2513 if (full_string_p)
8b57bfeb 2514 {
e3f9a279
RS
2515 lhs = gimple_call_lhs (stmt);
2516 switch (bcode)
2517 {
2518 case BUILT_IN_MEMCPY:
2519 case BUILT_IN_MEMCPY_CHK:
e3f9a279
RS
2520 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2521 laststmt.stmt = stmt;
2522 laststmt.len = dsi->nonzero_chars;
2523 laststmt.stridx = dsi->idx;
2524 if (lhs)
2525 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2526 break;
2527 case BUILT_IN_MEMPCPY:
2528 case BUILT_IN_MEMPCPY_CHK:
e3f9a279
RS
2529 break;
2530 default:
2531 gcc_unreachable ();
2532 }
8b57bfeb
JJ
2533 }
2534}
2535
2536/* Handle a strcat-like ({strcat,__strcat_chk}) call.
2537 If strlen of the second argument is known, strlen of the first argument
2538 is increased by the length of the second argument. Furthermore, attempt
2539 to convert it to memcpy/strcpy if the length of the first argument
2540 is known. */
2541
2542static void
2543handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2544{
2545 int idx, didx;
cc8bea0a 2546 tree srclen, args, type, fn, objsz, endptr;
8b57bfeb 2547 bool success;
355fe088 2548 gimple *stmt = gsi_stmt (*gsi);
526ceb68 2549 strinfo *si, *dsi;
cc8bea0a 2550 location_t loc = gimple_location (stmt);
8b57bfeb 2551
31db0fe0 2552 tree src = gimple_call_arg (stmt, 1);
cc8bea0a
MS
2553 tree dst = gimple_call_arg (stmt, 0);
2554
2555 /* Bail if the source is the same as destination. It will be diagnosed
2556 elsewhere. */
2557 if (operand_equal_p (src, dst, 0))
2558 return;
2559
2560 tree lhs = gimple_call_lhs (stmt);
8b57bfeb
JJ
2561
2562 didx = get_stridx (dst);
2563 if (didx < 0)
2564 return;
2565
2566 dsi = NULL;
2567 if (didx > 0)
2568 dsi = get_strinfo (didx);
cc8bea0a
MS
2569
2570 srclen = NULL_TREE;
2571 si = NULL;
2572 idx = get_stridx (src);
2573 if (idx < 0)
2574 srclen = build_int_cst (size_type_node, ~idx);
2575 else if (idx > 0)
2576 {
2577 si = get_strinfo (idx);
2578 if (si != NULL)
2579 srclen = get_string_length (si);
2580 }
2581
2582 /* Set the no-warning bit on the transformed statement? */
2583 bool set_no_warning = false;
2584
8b57bfeb
JJ
2585 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2586 {
cc8bea0a
MS
2587 {
2588 /* The concatenation always involves copying at least one byte
2589 (the terminating nul), even if the source string is empty.
2590 If the source is unknown assume it's one character long and
2591 used that as both sizes. */
2592 tree slen = srclen;
2593 if (slen)
2594 {
2595 tree type = TREE_TYPE (slen);
2596 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2597 }
2598
2599 tree sptr = si && si->ptr ? si->ptr : src;
2600
213694e5 2601 if (check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
cc8bea0a
MS
2602 {
2603 gimple_set_no_warning (stmt, true);
2604 set_no_warning = true;
2605 }
2606 }
2607
8b57bfeb 2608 /* strcat (p, q) can be transformed into
cc8bea0a 2609 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
8b57bfeb
JJ
2610 with length endptr - p if we need to compute the length
2611 later on. Don't do this transformation if we don't need
2612 it. */
e79983f4 2613 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
8b57bfeb
JJ
2614 {
2615 if (didx == 0)
2616 {
2617 didx = new_stridx (dst);
2618 if (didx == 0)
2619 return;
2620 }
2621 if (dsi == NULL)
2622 {
e3f9a279 2623 dsi = new_strinfo (dst, didx, NULL_TREE, false);
8b57bfeb
JJ
2624 set_strinfo (didx, dsi);
2625 find_equal_ptrs (dst, didx);
2626 }
2627 else
2628 {
2629 dsi = unshare_strinfo (dsi);
e3f9a279
RS
2630 dsi->nonzero_chars = NULL_TREE;
2631 dsi->full_string_p = false;
8b57bfeb
JJ
2632 dsi->next = 0;
2633 dsi->endptr = NULL_TREE;
2634 }
2635 dsi->writable = true;
2636 dsi->stmt = stmt;
2637 dsi->dont_invalidate = true;
2638 }
2639 return;
2640 }
2641
cc8bea0a 2642 tree dstlen = dsi->nonzero_chars;
8b57bfeb
JJ
2643 endptr = dsi->endptr;
2644
2645 dsi = unshare_strinfo (dsi);
2646 dsi->endptr = NULL_TREE;
2647 dsi->stmt = NULL;
2648 dsi->writable = true;
2649
2650 if (srclen != NULL_TREE)
2651 {
e3f9a279
RS
2652 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2653 TREE_TYPE (dsi->nonzero_chars),
2654 dsi->nonzero_chars, srclen);
2655 gcc_assert (dsi->full_string_p);
8b57bfeb
JJ
2656 adjust_related_strinfos (loc, dsi, srclen);
2657 dsi->dont_invalidate = true;
2658 }
2659 else
2660 {
e3f9a279
RS
2661 dsi->nonzero_chars = NULL;
2662 dsi->full_string_p = false;
e79983f4 2663 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
8b57bfeb
JJ
2664 dsi->dont_invalidate = true;
2665 }
2666
2667 if (si != NULL)
2668 /* strcat src may not overlap dst, so src doesn't need to be
2669 invalidated either. */
2670 si->dont_invalidate = true;
2671
2672 /* For now. Could remove the lhs from the call and add
2673 lhs = dst; afterwards. */
2674 if (lhs)
2675 return;
2676
2677 fn = NULL_TREE;
2678 objsz = NULL_TREE;
2679 switch (bcode)
2680 {
2681 case BUILT_IN_STRCAT:
2682 if (srclen != NULL_TREE)
e79983f4 2683 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
8b57bfeb 2684 else
e79983f4 2685 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
8b57bfeb
JJ
2686 break;
2687 case BUILT_IN_STRCAT_CHK:
2688 if (srclen != NULL_TREE)
e79983f4 2689 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
8b57bfeb 2690 else
e79983f4 2691 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
31db0fe0 2692 objsz = gimple_call_arg (stmt, 2);
8b57bfeb
JJ
2693 break;
2694 default:
2695 gcc_unreachable ();
2696 }
2697
2698 if (fn == NULL_TREE)
2699 return;
2700
cc8bea0a
MS
2701 if (dsi && dstlen)
2702 {
2703 tree type = TREE_TYPE (dstlen);
2704
2705 /* Compute the size of the source sequence, including the nul. */
2706 tree srcsize = srclen ? srclen : size_zero_node;
2707 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2708
2709 tree sptr = si && si->ptr ? si->ptr : src;
2710
213694e5 2711 if (check_bounds_or_overlap (stmt, dst, sptr, dstlen, srcsize))
cc8bea0a
MS
2712 {
2713 gimple_set_no_warning (stmt, true);
2714 set_no_warning = true;
2715 }
2716 }
2717
2718 tree len = NULL_TREE;
8b57bfeb
JJ
2719 if (srclen != NULL_TREE)
2720 {
2721 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2722 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2723
2724 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2725 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2726 build_int_cst (type, 1));
2727 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2728 GSI_SAME_STMT);
2729 }
2730 if (endptr)
2731 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2732 else
770fe3a3 2733 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dst), dst,
8b57bfeb
JJ
2734 fold_convert_loc (loc, sizetype,
2735 unshare_expr (dstlen)));
2736 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2737 GSI_SAME_STMT);
770fe3a3
BE
2738 if (objsz)
2739 {
2740 objsz = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (objsz), objsz,
2741 fold_convert_loc (loc, TREE_TYPE (objsz),
2742 unshare_expr (dstlen)));
2743 objsz = force_gimple_operand_gsi (gsi, objsz, true, NULL_TREE, true,
2744 GSI_SAME_STMT);
2745 }
8b57bfeb
JJ
2746 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2747 {
2748 fprintf (dump_file, "Optimizing: ");
2749 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2750 }
31db0fe0
ML
2751 if (srclen != NULL_TREE)
2752 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2753 dst, src, len, objsz);
8b57bfeb 2754 else
31db0fe0
ML
2755 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2756 dst, src, objsz);
8b57bfeb
JJ
2757 if (success)
2758 {
2759 stmt = gsi_stmt (*gsi);
2760 update_stmt (stmt);
2761 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2762 {
2763 fprintf (dump_file, "into: ");
2764 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2765 }
2766 /* If srclen == NULL, note that current string length can be
2767 computed by transforming this strcpy into stpcpy. */
2768 if (srclen == NULL_TREE && dsi->dont_invalidate)
2769 dsi->stmt = stmt;
2770 adjust_last_stmt (dsi, stmt, true);
2771 if (srclen != NULL_TREE)
2772 {
2773 laststmt.stmt = stmt;
2774 laststmt.len = srclen;
2775 laststmt.stridx = dsi->idx;
2776 }
2777 }
2778 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2779 fprintf (dump_file, "not possible.\n");
cc8bea0a
MS
2780
2781 if (set_no_warning)
2782 gimple_set_no_warning (stmt, true);
8b57bfeb
JJ
2783}
2784
24314386
MG
2785/* Handle a call to malloc or calloc. */
2786
2787static void
2788handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2789{
355fe088 2790 gimple *stmt = gsi_stmt (*gsi);
24314386 2791 tree lhs = gimple_call_lhs (stmt);
a71dcca8
ML
2792 if (lhs == NULL_TREE)
2793 return;
2794
24314386
MG
2795 gcc_assert (get_stridx (lhs) == 0);
2796 int idx = new_stridx (lhs);
2797 tree length = NULL_TREE;
2798 if (bcode == BUILT_IN_CALLOC)
2799 length = build_int_cst (size_type_node, 0);
e3f9a279 2800 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
24314386
MG
2801 if (bcode == BUILT_IN_CALLOC)
2802 si->endptr = lhs;
2803 set_strinfo (idx, si);
2804 si->writable = true;
2805 si->stmt = stmt;
2806 si->dont_invalidate = true;
2807}
2808
2809/* Handle a call to memset.
2810 After a call to calloc, memset(,0,) is unnecessary.
21722777 2811 memset(malloc(n),0,n) is calloc(n,1).
8b0b334a 2812 return true when the call is transfomred, false otherwise. */
24314386
MG
2813
2814static bool
2815handle_builtin_memset (gimple_stmt_iterator *gsi)
2816{
355fe088 2817 gimple *stmt2 = gsi_stmt (*gsi);
24314386 2818 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
8b0b334a 2819 return false;
24314386
MG
2820 tree ptr = gimple_call_arg (stmt2, 0);
2821 int idx1 = get_stridx (ptr);
2822 if (idx1 <= 0)
8b0b334a 2823 return false;
526ceb68 2824 strinfo *si1 = get_strinfo (idx1);
24314386 2825 if (!si1)
8b0b334a 2826 return false;
355fe088 2827 gimple *stmt1 = si1->stmt;
24314386 2828 if (!stmt1 || !is_gimple_call (stmt1))
8b0b334a 2829 return false;
24314386 2830 tree callee1 = gimple_call_fndecl (stmt1);
0ad84f34 2831 if (!valid_builtin_call (stmt1))
8b0b334a 2832 return false;
24314386
MG
2833 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2834 tree size = gimple_call_arg (stmt2, 2);
2835 if (code1 == BUILT_IN_CALLOC)
2836 /* Not touching stmt1 */ ;
2837 else if (code1 == BUILT_IN_MALLOC
2838 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2839 {
2840 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2841 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2842 size, build_one_cst (size_type_node));
e3f9a279
RS
2843 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2844 si1->full_string_p = true;
20cb2258 2845 si1->stmt = gsi_stmt (gsi1);
24314386
MG
2846 }
2847 else
8b0b334a 2848 return false;
24314386
MG
2849 tree lhs = gimple_call_lhs (stmt2);
2850 unlink_stmt_vdef (stmt2);
2851 if (lhs)
2852 {
355fe088 2853 gimple *assign = gimple_build_assign (lhs, ptr);
24314386
MG
2854 gsi_replace (gsi, assign, false);
2855 }
2856 else
2857 {
2858 gsi_remove (gsi, true);
2859 release_defs (stmt2);
2860 }
2861
8b0b334a 2862 return true;
24314386
MG
2863}
2864
36b85e43
BS
2865/* Handle a call to memcmp. We try to handle small comparisons by
2866 converting them to load and compare, and replacing the call to memcmp
21722777 2867 with a __builtin_memcmp_eq call where possible.
8b0b334a 2868 return true when call is transformed, return false otherwise. */
36b85e43
BS
2869
2870static bool
2871handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2872{
2873 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2874 tree res = gimple_call_lhs (stmt2);
2875 tree arg1 = gimple_call_arg (stmt2, 0);
2876 tree arg2 = gimple_call_arg (stmt2, 1);
2877 tree len = gimple_call_arg (stmt2, 2);
2878 unsigned HOST_WIDE_INT leni;
2879 use_operand_p use_p;
2880 imm_use_iterator iter;
2881
2882 if (!res)
8b0b334a 2883 return false;
36b85e43
BS
2884
2885 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2886 {
2887 gimple *ustmt = USE_STMT (use_p);
2888
73d73b48
BS
2889 if (is_gimple_debug (ustmt))
2890 continue;
36b85e43
BS
2891 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2892 {
2893 gassign *asgn = as_a <gassign *> (ustmt);
2894 tree_code code = gimple_assign_rhs_code (asgn);
2895 if ((code != EQ_EXPR && code != NE_EXPR)
2896 || !integer_zerop (gimple_assign_rhs2 (asgn)))
8b0b334a 2897 return false;
36b85e43
BS
2898 }
2899 else if (gimple_code (ustmt) == GIMPLE_COND)
2900 {
2901 tree_code code = gimple_cond_code (ustmt);
2902 if ((code != EQ_EXPR && code != NE_EXPR)
2903 || !integer_zerop (gimple_cond_rhs (ustmt)))
8b0b334a 2904 return false;
36b85e43
BS
2905 }
2906 else
8b0b334a 2907 return false;
36b85e43
BS
2908 }
2909
2910 if (tree_fits_uhwi_p (len)
2911 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
146ec50f 2912 && pow2p_hwi (leni))
36b85e43
BS
2913 {
2914 leni *= CHAR_TYPE_SIZE;
2915 unsigned align1 = get_pointer_alignment (arg1);
2916 unsigned align2 = get_pointer_alignment (arg2);
2917 unsigned align = MIN (align1, align2);
fffbab82
RS
2918 scalar_int_mode mode;
2919 if (int_mode_for_size (leni, 1).exists (&mode)
e0bd6c9f 2920 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
36b85e43
BS
2921 {
2922 location_t loc = gimple_location (stmt2);
2923 tree type, off;
2924 type = build_nonstandard_integer_type (leni, 1);
73a699ae 2925 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
36b85e43
BS
2926 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2927 ptr_mode, true);
2928 off = build_int_cst (ptrtype, 0);
2929 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2930 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2931 tree tem1 = fold_const_aggregate_ref (arg1);
2932 if (tem1)
2933 arg1 = tem1;
2934 tree tem2 = fold_const_aggregate_ref (arg2);
2935 if (tem2)
2936 arg2 = tem2;
2937 res = fold_convert_loc (loc, TREE_TYPE (res),
2938 fold_build2_loc (loc, NE_EXPR,
2939 boolean_type_node,
2940 arg1, arg2));
2941 gimplify_and_update_call_from_tree (gsi, res);
8b0b334a 2942 return true;
36b85e43
BS
2943 }
2944 }
2945
2946 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
8b0b334a
QZ
2947 return true;
2948}
2949
21722777
MS
2950/* Given an index to the strinfo vector, compute the string length
2951 for the corresponding string. Return -1 when unknown. */
2952
2953static HOST_WIDE_INT
8b0b334a
QZ
2954compute_string_length (int idx)
2955{
21722777 2956 HOST_WIDE_INT string_leni = -1;
8b0b334a
QZ
2957 gcc_assert (idx != 0);
2958
2959 if (idx < 0)
2960 return ~idx;
2961
2962 strinfo *si = get_strinfo (idx);
2963 if (si)
2964 {
2965 tree const_string_len = get_string_length (si);
2966 if (const_string_len && tree_fits_shwi_p (const_string_len))
2967 string_leni = tree_to_shwi (const_string_len);
2968 }
2969
2970 if (string_leni < 0)
2971 return -1;
2972
2973 return string_leni;
2974}
2975
21722777
MS
2976/* Determine the minimum size of the object referenced by DEST expression
2977 which must have a pointer type.
2978 Return the minimum size of the object if successful or NULL when the size
8b0b334a
QZ
2979 cannot be determined. */
2980static tree
2981determine_min_objsize (tree dest)
2982{
2983 unsigned HOST_WIDE_INT size = 0;
2984
2985 if (compute_builtin_object_size (dest, 2, &size))
2986 return build_int_cst (sizetype, size);
2987
21722777
MS
2988 /* Try to determine the size of the object through the RHS
2989 of the assign statement. */
8b0b334a
QZ
2990 if (TREE_CODE (dest) == SSA_NAME)
2991 {
2992 gimple *stmt = SSA_NAME_DEF_STMT (dest);
2993 if (!is_gimple_assign (stmt))
2994 return NULL_TREE;
2995
2996 if (!gimple_assign_single_p (stmt)
2997 && !gimple_assign_unary_nop_p (stmt))
2998 return NULL_TREE;
2999
3000 dest = gimple_assign_rhs1 (stmt);
3001 return determine_min_objsize (dest);
3002 }
3003
3004 /* Try to determine the size of the object from its type. */
3005 if (TREE_CODE (dest) != ADDR_EXPR)
3006 return NULL_TREE;
3007
3008 tree type = TREE_TYPE (dest);
3009 if (TREE_CODE (type) == POINTER_TYPE)
3010 type = TREE_TYPE (type);
3011
3012 type = TYPE_MAIN_VARIANT (type);
3013
21722777 3014 /* We cannot determine the size of the array if it's a flexible array,
8b0b334a
QZ
3015 which is declared at the end of a structure. */
3016 if (TREE_CODE (type) == ARRAY_TYPE
3017 && !array_at_struct_end_p (dest))
3018 {
3019 tree size_t = TYPE_SIZE_UNIT (type);
21722777 3020 if (size_t && TREE_CODE (size_t) == INTEGER_CST
8b0b334a
QZ
3021 && !integer_zerop (size_t))
3022 return size_t;
3023 }
3024
3025 return NULL_TREE;
3026}
3027
21722777 3028/* Handle a call to strcmp or strncmp. When the result is ONLY used to do
8b0b334a
QZ
3029 equality test against zero:
3030
3031 A. When the lengths of both arguments are constant and it's a strcmp:
3032 * if the lengths are NOT equal, we can safely fold the call
3033 to a non-zero value.
3034 * otherwise, do nothing now.
8b0b334a 3035
21722777
MS
3036 B. When the length of one argument is constant, try to replace the call
3037 with a __builtin_str(n)cmp_eq call where possible, i.e:
3038
3039 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR
3040 is a string with constant length , C is a constant.
8b0b334a
QZ
3041 if (C <= strlen(STR) && sizeof_array(s) > C)
3042 {
3043 replace this call with
3044 strncmp_eq (s, STR, C) (!)= 0
3045 }
3046 if (C > strlen(STR)
3047 {
3048 it can be safely treated as a call to strcmp (s, STR) (!)= 0
3049 can handled by the following strcmp.
3050 }
3051
21722777
MS
3052 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR
3053 is a string with constant length.
8b0b334a
QZ
3054 if (sizeof_array(s) > strlen(STR))
3055 {
3056 replace this call with
3057 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
3058 }
3059
21722777
MS
3060 Return true when the call is transformed, return false otherwise.
3061 */
8b0b334a
QZ
3062
3063static bool
3064handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
3065{
3066 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
3067 tree res = gimple_call_lhs (stmt);
3068 use_operand_p use_p;
3069 imm_use_iterator iter;
3070 tree arg1 = gimple_call_arg (stmt, 0);
3071 tree arg2 = gimple_call_arg (stmt, 1);
3072 int idx1 = get_stridx (arg1);
3073 int idx2 = get_stridx (arg2);
3074 HOST_WIDE_INT length = -1;
3075 bool is_ncmp = false;
3076
3077 if (!res)
3078 return false;
3079
3080 /* When both arguments are unknown, do nothing. */
3081 if (idx1 == 0 && idx2 == 0)
3082 return false;
3083
3084 /* Handle strncmp function. */
3085 if (gimple_call_num_args (stmt) == 3)
3086 {
3087 tree len = gimple_call_arg (stmt, 2);
3088 if (tree_fits_shwi_p (len))
3089 length = tree_to_shwi (len);
3090
3091 is_ncmp = true;
3092 }
3093
3094 /* For strncmp, if the length argument is NOT known, do nothing. */
3095 if (is_ncmp && length < 0)
3096 return false;
3097
3098 /* When the result is ONLY used to do equality test against zero. */
21722777
MS
3099 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
3100 {
8b0b334a
QZ
3101 gimple *use_stmt = USE_STMT (use_p);
3102
3103 if (is_gimple_debug (use_stmt))
3104 continue;
3105 if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
21722777 3106 {
8b0b334a 3107 tree_code code = gimple_assign_rhs_code (use_stmt);
21722777 3108 if (code == COND_EXPR)
8b0b334a
QZ
3109 {
3110 tree cond_expr = gimple_assign_rhs1 (use_stmt);
21722777 3111 if ((TREE_CODE (cond_expr) != EQ_EXPR
8b0b334a
QZ
3112 && (TREE_CODE (cond_expr) != NE_EXPR))
3113 || !integer_zerop (TREE_OPERAND (cond_expr, 1)))
3114 return false;
3115 }
3116 else if (code == EQ_EXPR || code == NE_EXPR)
3117 {
3118 if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
3119 return false;
3120 }
21722777 3121 else
8b0b334a
QZ
3122 return false;
3123 }
3124 else if (gimple_code (use_stmt) == GIMPLE_COND)
3125 {
3126 tree_code code = gimple_cond_code (use_stmt);
3127 if ((code != EQ_EXPR && code != NE_EXPR)
3128 || !integer_zerop (gimple_cond_rhs (use_stmt)))
3129 return false;
3130 }
3131 else
3132 return false;
3133 }
21722777
MS
3134
3135 /* When the lengths of both arguments are known, and they are unequal,
3136 we can safely fold the call to a non-zero value for strcmp;
8b0b334a
QZ
3137 othewise, do nothing now. */
3138 if (idx1 != 0 && idx2 != 0)
3139 {
3140 HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
3141 HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
3142
21722777 3143 if (!is_ncmp
8b0b334a
QZ
3144 && const_string_leni1 != -1
3145 && const_string_leni2 != -1
21722777 3146 && const_string_leni1 != const_string_leni2)
8b0b334a 3147 {
21722777 3148 replace_call_with_value (gsi, integer_one_node);
8b0b334a
QZ
3149 return true;
3150 }
3151 return false;
3152 }
3153
3154 /* When the length of one argument is constant. */
3155 tree var_string = NULL_TREE;
3156 HOST_WIDE_INT const_string_leni = -1;
21722777 3157
8b0b334a
QZ
3158 if (idx1)
3159 {
3160 const_string_leni = compute_string_length (idx1);
3161 var_string = arg2;
21722777
MS
3162 }
3163 else
8b0b334a
QZ
3164 {
3165 gcc_checking_assert (idx2);
3166 const_string_leni = compute_string_length (idx2);
3167 var_string = arg1;
21722777 3168 }
8b0b334a 3169
21722777 3170 if (const_string_leni < 0)
8b0b334a 3171 return false;
21722777 3172
8b0b334a
QZ
3173 unsigned HOST_WIDE_INT var_sizei = 0;
3174 /* try to determine the minimum size of the object pointed by var_string. */
3175 tree size = determine_min_objsize (var_string);
3176
3177 if (!size)
3178 return false;
21722777 3179
8b0b334a
QZ
3180 if (tree_fits_uhwi_p (size))
3181 var_sizei = tree_to_uhwi (size);
3182
3183 if (var_sizei == 0)
3184 return false;
3185
21722777 3186 /* For strncmp, if length > const_string_leni , this call can be safely
8b0b334a
QZ
3187 transformed to a strcmp. */
3188 if (is_ncmp && length > const_string_leni)
3189 is_ncmp = false;
3190
21722777 3191 unsigned HOST_WIDE_INT final_length
8b0b334a
QZ
3192 = is_ncmp ? length : const_string_leni + 1;
3193
3194 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
21722777 3195 if (var_sizei > final_length)
8b0b334a 3196 {
21722777
MS
3197 tree fn
3198 = (is_ncmp
3199 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
8b0b334a
QZ
3200 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
3201 if (!fn)
3202 return false;
21722777 3203 tree const_string_len = build_int_cst (size_type_node, final_length);
8b0b334a
QZ
3204 update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
3205 }
21722777 3206 else
8b0b334a
QZ
3207 return false;
3208
3209 return true;
36b85e43
BS
3210}
3211
8b57bfeb
JJ
3212/* Handle a POINTER_PLUS_EXPR statement.
3213 For p = "abcd" + 2; compute associated length, or if
3214 p = q + off is pointing to a '\0' character of a string, call
3215 zero_length_string on it. */
3216
3217static void
3218handle_pointer_plus (gimple_stmt_iterator *gsi)
3219{
355fe088 3220 gimple *stmt = gsi_stmt (*gsi);
8b57bfeb
JJ
3221 tree lhs = gimple_assign_lhs (stmt), off;
3222 int idx = get_stridx (gimple_assign_rhs1 (stmt));
526ceb68 3223 strinfo *si, *zsi;
8b57bfeb
JJ
3224
3225 if (idx == 0)
3226 return;
3227
3228 if (idx < 0)
3229 {
3230 tree off = gimple_assign_rhs2 (stmt);
cc269bb6 3231 if (tree_fits_uhwi_p (off)
7d362f6c 3232 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
9771b263 3233 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
ae7e9ddd 3234 = ~(~idx - (int) tree_to_uhwi (off));
8b57bfeb
JJ
3235 return;
3236 }
3237
3238 si = get_strinfo (idx);
e3f9a279 3239 if (si == NULL || si->nonzero_chars == NULL_TREE)
8b57bfeb
JJ
3240 return;
3241
3242 off = gimple_assign_rhs2 (stmt);
3243 zsi = NULL;
e3f9a279 3244 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
8b57bfeb
JJ
3245 zsi = zero_length_string (lhs, si);
3246 else if (TREE_CODE (off) == SSA_NAME)
3247 {
355fe088 3248 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
8b57bfeb 3249 if (gimple_assign_single_p (def_stmt)
e3f9a279
RS
3250 && si->full_string_p
3251 && operand_equal_p (si->nonzero_chars,
3252 gimple_assign_rhs1 (def_stmt), 0))
8b57bfeb
JJ
3253 zsi = zero_length_string (lhs, si);
3254 }
3255 if (zsi != NULL
3256 && si->endptr != NULL_TREE
3257 && si->endptr != lhs
3258 && TREE_CODE (si->endptr) == SSA_NAME)
3259 {
3260 enum tree_code rhs_code
3261 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
3262 ? SSA_NAME : NOP_EXPR;
00d66391 3263 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
8b57bfeb
JJ
3264 gcc_assert (gsi_stmt (*gsi) == stmt);
3265 update_stmt (stmt);
3266 }
3267}
3268
a011292a 3269/* If RHS, either directly or indirectly, refers to a string of constant
aca8570e
MS
3270 length, return the length. Otherwise, if it refers to a character
3271 constant, return 1 if the constant is non-zero and 0 if it is nul.
3272 Otherwise, return a negative value. */
a011292a
MS
3273
3274static HOST_WIDE_INT
aca8570e 3275get_min_string_length (tree rhs, bool *full_string_p)
65f2d1ee 3276{
e4bbeea2 3277 if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
aca8570e
MS
3278 {
3279 if (tree_expr_nonzero_p (rhs))
3280 {
3281 *full_string_p = false;
3282 return 1;
3283 }
3284
3285 *full_string_p = true;
3286 return 0;
3287 }
3288
65f2d1ee
PK
3289 if (TREE_CODE (rhs) == MEM_REF
3290 && integer_zerop (TREE_OPERAND (rhs, 1)))
3291 {
a011292a 3292 rhs = TREE_OPERAND (rhs, 0);
65f2d1ee 3293 if (TREE_CODE (rhs) == ADDR_EXPR)
05ef3173 3294 {
a011292a
MS
3295 tree rhs_addr = rhs;
3296
05ef3173
MS
3297 rhs = TREE_OPERAND (rhs, 0);
3298 if (TREE_CODE (rhs) != STRING_CST)
3299 {
3300 int idx = get_stridx (rhs_addr);
3301 if (idx > 0)
3302 {
3303 strinfo *si = get_strinfo (idx);
a011292a 3304 if (si
a011292a 3305 && tree_fits_shwi_p (si->nonzero_chars))
aca8570e
MS
3306 {
3307 *full_string_p = si->full_string_p;
3308 return tree_to_shwi (si->nonzero_chars);
3309 }
05ef3173
MS
3310 }
3311 }
3312 }
3313 }
3314
3315 if (TREE_CODE (rhs) == VAR_DECL
3316 && TREE_READONLY (rhs))
3317 rhs = DECL_INITIAL (rhs);
3318
3319 if (rhs && TREE_CODE (rhs) == STRING_CST)
aca8570e 3320 {
e17fa93e
JJ
3321 HOST_WIDE_INT len = strlen (TREE_STRING_POINTER (rhs));
3322 *full_string_p = len < TREE_STRING_LENGTH (rhs);
3323 return len;
aca8570e 3324 }
65f2d1ee 3325
05ef3173 3326 return -1;
65f2d1ee
PK
3327}
3328
aca8570e
MS
3329/* Handle a single or multiple character store either by single
3330 character assignment or by multi-character assignment from
3331 MEM_REF. */
8b57bfeb
JJ
3332
3333static bool
3334handle_char_store (gimple_stmt_iterator *gsi)
3335{
3336 int idx = -1;
526ceb68 3337 strinfo *si = NULL;
355fe088 3338 gimple *stmt = gsi_stmt (*gsi);
8b57bfeb 3339 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
e3f9a279
RS
3340 tree rhs = gimple_assign_rhs1 (stmt);
3341 unsigned HOST_WIDE_INT offset = 0;
8b57bfeb
JJ
3342
3343 if (TREE_CODE (lhs) == MEM_REF
3344 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
3345 {
e3f9a279
RS
3346 tree mem_offset = TREE_OPERAND (lhs, 1);
3347 if (tree_fits_uhwi_p (mem_offset))
8b57bfeb 3348 {
e3f9a279
RS
3349 /* Get the strinfo for the base, and use it if it starts with at
3350 least OFFSET nonzero characters. This is trivially true if
3351 OFFSET is zero. */
3352 offset = tree_to_uhwi (mem_offset);
3353 idx = get_stridx (TREE_OPERAND (lhs, 0));
3354 if (idx > 0)
3355 si = get_strinfo (idx);
3356 if (offset == 0)
3357 ssaname = TREE_OPERAND (lhs, 0);
3358 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
3359 return true;
8b57bfeb
JJ
3360 }
3361 }
3362 else
e3f9a279
RS
3363 {
3364 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
3365 if (idx > 0)
3366 si = get_strinfo (idx);
3367 }
8b57bfeb 3368
aca8570e
MS
3369 /* STORING_NONZERO_P is true iff not all stored characters are zero.
3370 STORING_ALL_ZEROS_P is true iff all stored characters are zero.
3371 Both are false when it's impossible to determine which is true. */
3372 bool storing_nonzero_p;
3373 bool storing_all_zeros_p = initializer_zerop (rhs, &storing_nonzero_p);
3374 if (!storing_nonzero_p)
3375 storing_nonzero_p = tree_expr_nonzero_p (rhs);
3376 bool full_string_p = storing_all_zeros_p;
3377
a011292a
MS
3378 /* Set to the length of the string being assigned if known. */
3379 HOST_WIDE_INT rhslen;
e3f9a279
RS
3380
3381 if (si != NULL)
8b57bfeb 3382 {
e3f9a279
RS
3383 int cmp = compare_nonzero_chars (si, offset);
3384 gcc_assert (offset == 0 || cmp >= 0);
aca8570e 3385 if (storing_all_zeros_p && cmp == 0 && si->full_string_p)
8b57bfeb 3386 {
e3f9a279
RS
3387 /* When overwriting a '\0' with a '\0', the store can be removed
3388 if we know it has been stored in the current function. */
36bbc05d 3389 if (!stmt_could_throw_p (cfun, stmt) && si->writable)
8b57bfeb 3390 {
e3f9a279
RS
3391 unlink_stmt_vdef (stmt);
3392 release_defs (stmt);
3393 gsi_remove (gsi, true);
3394 return false;
8b57bfeb
JJ
3395 }
3396 else
e3f9a279
RS
3397 {
3398 si->writable = true;
3399 gsi_next (gsi);
3400 return false;
3401 }
8b57bfeb 3402 }
e3f9a279 3403 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
5b115c1f
MP
3404 and if we aren't storing '\0', we know that the length of the
3405 string and any other zero terminated string in memory remains
3406 the same. In that case we move to the next gimple statement and
21722777 3407 return to signal the caller that it shouldn't invalidate anything.
5b115c1f
MP
3408
3409 This is benefical for cases like:
3410
3411 char p[20];
3412 void foo (char *q)
3413 {
3414 strcpy (p, "foobar");
3415 size_t len = strlen (p); // This can be optimized into 6
3416 size_t len2 = strlen (q); // This has to be computed
3417 p[0] = 'X';
3418 size_t len3 = strlen (p); // This can be optimized into 6
3419 size_t len4 = strlen (q); // This can be optimized into len2
3420 bar (len, len2, len3, len4);
3421 }
21722777 3422 */
e3f9a279 3423 else if (storing_nonzero_p && cmp > 0)
5b115c1f
MP
3424 {
3425 gsi_next (gsi);
3426 return false;
3427 }
21722777
MS
3428 else if (storing_all_zeros_p
3429 || storing_nonzero_p
3430 || (offset != 0 && cmp > 0))
e3f9a279 3431 {
aca8570e
MS
3432 /* When STORING_NONZERO_P, we know that the string will start
3433 with at least OFFSET + 1 nonzero characters. If storing
3434 a single character, set si->NONZERO_CHARS to the result.
3435 If storing multiple characters, try to determine the number
3436 of leading non-zero characters and set si->NONZERO_CHARS to
3437 the result instead.
e3f9a279 3438
aca8570e
MS
3439 When STORING_ALL_ZEROS_P, we know that the string is now
3440 OFFSET characters long.
e3f9a279
RS
3441
3442 Otherwise, we're storing an unknown value at offset OFFSET,
3443 so need to clip the nonzero_chars to OFFSET. */
aca8570e 3444 bool full_string_p = storing_all_zeros_p;
e4bbeea2
MS
3445 HOST_WIDE_INT len = 1;
3446 if (storing_nonzero_p)
3447 {
3448 /* Try to get the minimum length of the string (or
3449 individual character) being stored. If it fails,
3450 STORING_NONZERO_P guarantees it's at least 1. */
3451 len = get_min_string_length (rhs, &full_string_p);
3452 if (len < 0)
3453 len = 1;
3454 }
aca8570e 3455
e3f9a279
RS
3456 location_t loc = gimple_location (stmt);
3457 tree oldlen = si->nonzero_chars;
3458 if (cmp == 0 && si->full_string_p)
3459 /* We're overwriting the nul terminator with a nonzero or
3460 unknown character. If the previous stmt was a memcpy,
3461 its length may be decreased. */
3462 adjust_last_stmt (si, stmt, false);
3463 si = unshare_strinfo (si);
3464 if (storing_nonzero_p)
aca8570e
MS
3465 {
3466 gcc_assert (len >= 0);
3467 si->nonzero_chars = build_int_cst (size_type_node, offset + len);
3468 }
e3f9a279
RS
3469 else
3470 si->nonzero_chars = build_int_cst (size_type_node, offset);
aca8570e
MS
3471 si->full_string_p = full_string_p;
3472 if (storing_all_zeros_p
e3f9a279
RS
3473 && ssaname
3474 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3475 si->endptr = ssaname;
3476 else
3477 si->endptr = NULL;
3478 si->next = 0;
3479 si->stmt = NULL;
3480 si->writable = true;
3481 si->dont_invalidate = true;
3482 if (oldlen)
3483 {
3484 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
3485 si->nonzero_chars, oldlen);
3486 adjust_related_strinfos (loc, si, adj);
3487 }
3488 else
3489 si->prev = 0;
3490 }
8b57bfeb 3491 }
aca8570e 3492 else if (idx == 0 && (storing_all_zeros_p || storing_nonzero_p))
8b57bfeb
JJ
3493 {
3494 if (ssaname)
e3f9a279 3495 idx = new_stridx (ssaname);
8b57bfeb 3496 else
e3f9a279
RS
3497 idx = new_addr_stridx (lhs);
3498 if (idx != 0)
8b57bfeb 3499 {
e3f9a279 3500 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
aca8570e
MS
3501 HOST_WIDE_INT slen = (storing_all_zeros_p
3502 ? 0
3503 : (storing_nonzero_p
3504 ? get_min_string_length (rhs, &full_string_p)
3505 : -1));
3506 tree len = (slen <= 0
3507 ? size_zero_node
3508 : build_int_cst (size_type_node, slen));
3509 si = new_strinfo (ptr, idx, len, slen >= 0 && full_string_p);
e3f9a279 3510 set_strinfo (idx, si);
aca8570e 3511 if (storing_all_zeros_p
e3f9a279
RS
3512 && ssaname
3513 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
3514 si->endptr = ssaname;
3515 si->dont_invalidate = true;
3516 si->writable = true;
8b57bfeb 3517 }
8b57bfeb 3518 }
198fe1bf 3519 else if (idx == 0
aca8570e 3520 && (rhslen = get_min_string_length (rhs, &full_string_p)) >= 0
198fe1bf
JJ
3521 && ssaname == NULL_TREE
3522 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
3523 {
198fe1bf 3524 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
05ef3173 3525 if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
198fe1bf
JJ
3526 {
3527 int idx = new_addr_stridx (lhs);
3528 if (idx != 0)
3529 {
3530 si = new_strinfo (build_fold_addr_expr (lhs), idx,
aca8570e
MS
3531 build_int_cst (size_type_node, rhslen),
3532 full_string_p);
198fe1bf
JJ
3533 set_strinfo (idx, si);
3534 si->dont_invalidate = true;
3535 }
3536 }
3537 }
8b57bfeb 3538
aca8570e 3539 if (si != NULL && offset == 0 && storing_all_zeros_p)
8b57bfeb
JJ
3540 {
3541 /* Allow adjust_last_stmt to remove it if the stored '\0'
3542 is immediately overwritten. */
3543 laststmt.stmt = stmt;
3544 laststmt.len = build_int_cst (size_type_node, 1);
3545 laststmt.stridx = si->idx;
3546 }
3547 return true;
3548}
3549
f368600f 3550/* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3b1970cb
PK
3551
3552static void
f368600f 3553fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
3b1970cb
PK
3554{
3555 if (TREE_CODE (rhs1) != SSA_NAME
3556 || TREE_CODE (rhs2) != SSA_NAME)
3557 return;
3558
3559 gimple *call_stmt = NULL;
3560 for (int pass = 0; pass < 2; pass++)
3561 {
3562 gimple *g = SSA_NAME_DEF_STMT (rhs1);
3563 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
3564 && has_single_use (rhs1)
3565 && gimple_call_arg (g, 0) == rhs2)
3566 {
3567 call_stmt = g;
3568 break;
3569 }
3570 std::swap (rhs1, rhs2);
3571 }
3572
3573 if (call_stmt)
3574 {
3575 tree arg0 = gimple_call_arg (call_stmt, 0);
3576
3577 if (arg0 == rhs2)
3578 {
3579 tree arg1 = gimple_call_arg (call_stmt, 1);
3580 tree arg1_len = NULL_TREE;
3581 int idx = get_stridx (arg1);
3582
3583 if (idx)
3584 {
3585 if (idx < 0)
3586 arg1_len = build_int_cst (size_type_node, ~idx);
3587 else
3588 {
3589 strinfo *si = get_strinfo (idx);
3590 if (si)
3591 arg1_len = get_string_length (si);
3592 }
3593 }
3594
3595 if (arg1_len != NULL_TREE)
3596 {
3597 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
f368600f 3598 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
96863f32
ML
3599
3600 if (!is_gimple_val (arg1_len))
3601 {
3602 tree arg1_len_tmp = make_ssa_name (TREE_TYPE (arg1_len));
3603 gassign *arg1_stmt = gimple_build_assign (arg1_len_tmp,
3604 arg1_len);
3605 gsi_insert_before (&gsi, arg1_stmt, GSI_SAME_STMT);
3606 arg1_len = arg1_len_tmp;
3607 }
3608
f368600f 3609 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3b1970cb 3610 arg0, arg1, arg1_len);
f368600f
ML
3611 tree strncmp_lhs = make_ssa_name (integer_type_node);
3612 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3613 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3b1970cb 3614 gsi_remove (&gsi, true);
f368600f
ML
3615 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3616 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3b1970cb
PK
3617
3618 if (is_gimple_assign (stmt))
3619 {
3620 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3621 {
3622 tree cond = gimple_assign_rhs1 (stmt);
f368600f 3623 TREE_OPERAND (cond, 0) = strncmp_lhs;
3b1970cb
PK
3624 TREE_OPERAND (cond, 1) = zero;
3625 }
3626 else
3627 {
f368600f 3628 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3b1970cb
PK
3629 gimple_assign_set_rhs2 (stmt, zero);
3630 }
3631 }
3632 else
3633 {
3634 gcond *cond = as_a<gcond *> (stmt);
f368600f 3635 gimple_cond_set_lhs (cond, strncmp_lhs);
3b1970cb
PK
3636 gimple_cond_set_rhs (cond, zero);
3637 }
3638 update_stmt (stmt);
3639 }
3640 }
3641 }
3642}
3643
cc8bea0a 3644/* Attempt to check for validity of the performed access a single statement
fa9544ab
ML
3645 at *GSI using string length knowledge, and to optimize it.
3646 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3647 true. */
8b57bfeb
JJ
3648
3649static bool
fa9544ab 3650strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh)
8b57bfeb 3651{
355fe088 3652 gimple *stmt = gsi_stmt (*gsi);
8b57bfeb
JJ
3653
3654 if (is_gimple_call (stmt))
3655 {
3656 tree callee = gimple_call_fndecl (stmt);
0ad84f34 3657 if (valid_builtin_call (stmt))
8b57bfeb
JJ
3658 switch (DECL_FUNCTION_CODE (callee))
3659 {
3660 case BUILT_IN_STRLEN:
781ff3d8 3661 case BUILT_IN_STRNLEN:
8b57bfeb
JJ
3662 handle_builtin_strlen (gsi);
3663 break;
3664 case BUILT_IN_STRCHR:
3665 handle_builtin_strchr (gsi);
3666 break;
3667 case BUILT_IN_STRCPY:
3668 case BUILT_IN_STRCPY_CHK:
3669 case BUILT_IN_STPCPY:
3670 case BUILT_IN_STPCPY_CHK:
3671 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3672 break;
025d57f0
MS
3673
3674 case BUILT_IN_STRNCAT:
3675 case BUILT_IN_STRNCAT_CHK:
3676 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3677 break;
3678
3679 case BUILT_IN_STPNCPY:
3680 case BUILT_IN_STPNCPY_CHK:
3681 case BUILT_IN_STRNCPY:
3682 case BUILT_IN_STRNCPY_CHK:
3683 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3684 break;
3685
8b57bfeb
JJ
3686 case BUILT_IN_MEMCPY:
3687 case BUILT_IN_MEMCPY_CHK:
3688 case BUILT_IN_MEMPCPY:
3689 case BUILT_IN_MEMPCPY_CHK:
3690 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3691 break;
3692 case BUILT_IN_STRCAT:
3693 case BUILT_IN_STRCAT_CHK:
3694 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3695 break;
24314386
MG
3696 case BUILT_IN_MALLOC:
3697 case BUILT_IN_CALLOC:
3698 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3699 break;
3700 case BUILT_IN_MEMSET:
8b0b334a 3701 if (handle_builtin_memset (gsi))
24314386
MG
3702 return false;
3703 break;
36b85e43 3704 case BUILT_IN_MEMCMP:
8b0b334a
QZ
3705 if (handle_builtin_memcmp (gsi))
3706 return false;
3707 break;
3708 case BUILT_IN_STRCMP:
3709 case BUILT_IN_STRNCMP:
3710 if (handle_builtin_string_cmp (gsi))
36b85e43
BS
3711 return false;
3712 break;
8b57bfeb
JJ
3713 default:
3714 break;
3715 }
3716 }
5004bd00 3717 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
8b57bfeb
JJ
3718 {
3719 tree lhs = gimple_assign_lhs (stmt);
3720
3721 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3722 {
3723 if (gimple_assign_single_p (stmt)
3724 || (gimple_assign_cast_p (stmt)
3725 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3726 {
3727 int idx = get_stridx (gimple_assign_rhs1 (stmt));
9771b263 3728 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
8b57bfeb
JJ
3729 }
3730 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3731 handle_pointer_plus (gsi);
3732 }
3b1970cb
PK
3733 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3734 {
3735 enum tree_code code = gimple_assign_rhs_code (stmt);
3736 if (code == COND_EXPR)
3737 {
3738 tree cond = gimple_assign_rhs1 (stmt);
3739 enum tree_code cond_code = TREE_CODE (cond);
3740
3741 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
f368600f
ML
3742 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3743 TREE_OPERAND (cond, 1), stmt);
3b1970cb
PK
3744 }
3745 else if (code == EQ_EXPR || code == NE_EXPR)
f368600f
ML
3746 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3747 gimple_assign_rhs2 (stmt), stmt);
f744bfec
JJ
3748 else if (gimple_assign_load_p (stmt)
3749 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3750 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3751 && (TYPE_PRECISION (TREE_TYPE (lhs))
3752 == TYPE_PRECISION (char_type_node))
3753 && !gimple_has_volatile_ops (stmt))
3754 {
3755 tree off = integer_zero_node;
3756 unsigned HOST_WIDE_INT coff = 0;
ad2a970f 3757 int idx = 0;
f744bfec
JJ
3758 tree rhs1 = gimple_assign_rhs1 (stmt);
3759 if (code == MEM_REF)
3760 {
3761 idx = get_stridx (TREE_OPERAND (rhs1, 0));
ad2a970f
JJ
3762 if (idx > 0)
3763 {
3764 strinfo *si = get_strinfo (idx);
3765 if (si
3766 && si->nonzero_chars
3767 && TREE_CODE (si->nonzero_chars) == INTEGER_CST
3768 && (wi::to_widest (si->nonzero_chars)
3769 >= wi::to_widest (off)))
3770 off = TREE_OPERAND (rhs1, 1);
3771 else
3772 /* This case is not useful. See if get_addr_stridx
3773 returns something usable. */
3774 idx = 0;
3775 }
f744bfec 3776 }
ad2a970f 3777 if (idx <= 0)
f744bfec
JJ
3778 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3779 if (idx > 0)
3780 {
3781 strinfo *si = get_strinfo (idx);
3782 if (si
3783 && si->nonzero_chars
3784 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3785 {
3786 widest_int w1 = wi::to_widest (si->nonzero_chars);
3787 widest_int w2 = wi::to_widest (off) + coff;
3788 if (w1 == w2
3789 && si->full_string_p)
3790 {
fa9544ab
ML
3791 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3792 {
3793 fprintf (dump_file, "Optimizing: ");
3794 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3795 }
3796
f744bfec
JJ
3797 /* Reading the final '\0' character. */
3798 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3799 gimple_set_vuse (stmt, NULL_TREE);
3800 gimple_assign_set_rhs_from_tree (gsi, zero);
fa9544ab
ML
3801 *cleanup_eh
3802 |= maybe_clean_or_replace_eh_stmt (stmt,
3803 gsi_stmt (*gsi));
3804 stmt = gsi_stmt (*gsi);
3805 update_stmt (stmt);
3806
3807 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
3808 {
3809 fprintf (dump_file, "into: ");
3810 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3811 }
f744bfec
JJ
3812 }
3813 else if (w1 > w2)
3814 {
3815 /* Reading a character before the final '\0'
3816 character. Just set the value range to ~[0, 0]
3817 if we don't have anything better. */
3818 wide_int min, max;
3819 tree type = TREE_TYPE (lhs);
54994253 3820 enum value_range_kind vr
f744bfec
JJ
3821 = get_range_info (lhs, &min, &max);
3822 if (vr == VR_VARYING
3823 || (vr == VR_RANGE
3824 && min == wi::min_value (TYPE_PRECISION (type),
3825 TYPE_SIGN (type))
3826 && max == wi::max_value (TYPE_PRECISION (type),
3827 TYPE_SIGN (type))))
3828 set_range_info (lhs, VR_ANTI_RANGE,
3829 wi::zero (TYPE_PRECISION (type)),
3830 wi::zero (TYPE_PRECISION (type)));
3831 }
3832 }
3833 }
3834 }
025d57f0 3835
6a33d0ff
MS
3836 if (strlen_to_stridx)
3837 {
3838 tree rhs1 = gimple_assign_rhs1 (stmt);
3839 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3840 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3841 }
3b1970cb
PK
3842 }
3843 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
8b57bfeb
JJ
3844 {
3845 tree type = TREE_TYPE (lhs);
3846 if (TREE_CODE (type) == ARRAY_TYPE)
3847 type = TREE_TYPE (type);
3848 if (TREE_CODE (type) == INTEGER_TYPE
3849 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3850 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3851 {
3852 if (! handle_char_store (gsi))
3853 return false;
3854 }
3855 }
3856 }
3b1970cb
PK
3857 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3858 {
3859 enum tree_code code = gimple_cond_code (cond);
3860 if (code == EQ_EXPR || code == NE_EXPR)
f368600f
ML
3861 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3862 gimple_cond_rhs (stmt), stmt);
3b1970cb 3863 }
8b57bfeb
JJ
3864
3865 if (gimple_vdef (stmt))
3866 maybe_invalidate (stmt);
3867 return true;
3868}
3869
3870/* Recursively call maybe_invalidate on stmts that might be executed
3871 in between dombb and current bb and that contain a vdef. Stop when
3872 *count stmts are inspected, or if the whole strinfo vector has
3873 been invalidated. */
3874
3875static void
355fe088 3876do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
8b57bfeb
JJ
3877{
3878 unsigned int i, n = gimple_phi_num_args (phi);
3879
3880 for (i = 0; i < n; i++)
3881 {
3882 tree vuse = gimple_phi_arg_def (phi, i);
355fe088 3883 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
8b57bfeb
JJ
3884 basic_block bb = gimple_bb (stmt);
3885 if (bb == NULL
3886 || bb == dombb
3887 || !bitmap_set_bit (visited, bb->index)
3888 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3889 continue;
3890 while (1)
3891 {
3892 if (gimple_code (stmt) == GIMPLE_PHI)
3893 {
3894 do_invalidate (dombb, stmt, visited, count);
3895 if (*count == 0)
3896 return;
3897 break;
3898 }
3899 if (--*count == 0)
3900 return;
3901 if (!maybe_invalidate (stmt))
3902 {
3903 *count = 0;
3904 return;
3905 }
3906 vuse = gimple_vuse (stmt);
3907 stmt = SSA_NAME_DEF_STMT (vuse);
3908 if (gimple_bb (stmt) != bb)
3909 {
3910 bb = gimple_bb (stmt);
3911 if (bb == NULL
3912 || bb == dombb
3913 || !bitmap_set_bit (visited, bb->index)
3914 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3915 break;
3916 }
3917 }
3918 }
3919}
3920
4d9192b5
TS
3921class strlen_dom_walker : public dom_walker
3922{
3923public:
fa9544ab
ML
3924 strlen_dom_walker (cdi_direction direction)
3925 : dom_walker (direction), m_cleanup_cfg (false)
3926 {}
4d9192b5 3927
3daacdcd 3928 virtual edge before_dom_children (basic_block);
4d9192b5 3929 virtual void after_dom_children (basic_block);
fa9544ab
ML
3930
3931 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3932 execute function. */
3933 bool m_cleanup_cfg;
4d9192b5
TS
3934};
3935
8b57bfeb 3936/* Callback for walk_dominator_tree. Attempt to optimize various
c7880c8c 3937 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
8b57bfeb 3938
3daacdcd 3939edge
4d9192b5 3940strlen_dom_walker::before_dom_children (basic_block bb)
8b57bfeb 3941{
8b57bfeb
JJ
3942 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3943
3944 if (dombb == NULL)
3945 stridx_to_strinfo = NULL;
3946 else
3947 {
526ceb68 3948 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
8b57bfeb
JJ
3949 if (stridx_to_strinfo)
3950 {
538dd0b7
DM
3951 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3952 gsi_next (&gsi))
8b57bfeb 3953 {
538dd0b7 3954 gphi *phi = gsi.phi ();
ea057359 3955 if (virtual_operand_p (gimple_phi_result (phi)))
8b57bfeb
JJ
3956 {
3957 bitmap visited = BITMAP_ALLOC (NULL);
3958 int count_vdef = 100;
3959 do_invalidate (dombb, phi, visited, &count_vdef);
3960 BITMAP_FREE (visited);
8b29fd4e
JJ
3961 if (count_vdef == 0)
3962 {
3963 /* If there were too many vdefs in between immediate
3964 dominator and current bb, invalidate everything.
3965 If stridx_to_strinfo has been unshared, we need
3966 to free it, otherwise just set it to NULL. */
3967 if (!strinfo_shared ())
3968 {
3969 unsigned int i;
526ceb68 3970 strinfo *si;
8b29fd4e
JJ
3971
3972 for (i = 1;
3973 vec_safe_iterate (stridx_to_strinfo, i, &si);
3974 ++i)
3975 {
3976 free_strinfo (si);
3977 (*stridx_to_strinfo)[i] = NULL;
3978 }
3979 }
3980 else
3981 stridx_to_strinfo = NULL;
3982 }
8b57bfeb
JJ
3983 break;
3984 }
3985 }
3986 }
3987 }
3988
3989 /* If all PHI arguments have the same string index, the PHI result
3990 has it as well. */
538dd0b7
DM
3991 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3992 gsi_next (&gsi))
8b57bfeb 3993 {
538dd0b7 3994 gphi *phi = gsi.phi ();
8b57bfeb 3995 tree result = gimple_phi_result (phi);
ea057359 3996 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
8b57bfeb
JJ
3997 {
3998 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3999 if (idx != 0)
4000 {
4001 unsigned int i, n = gimple_phi_num_args (phi);
4002 for (i = 1; i < n; i++)
4003 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
4004 break;
4005 if (i == n)
9771b263 4006 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
8b57bfeb
JJ
4007 }
4008 }
4009 }
4010
fa9544ab
ML
4011 bool cleanup_eh = false;
4012
8b57bfeb 4013 /* Attempt to optimize individual statements. */
538dd0b7 4014 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
fa9544ab 4015 if (strlen_check_and_optimize_stmt (&gsi, &cleanup_eh))
8b57bfeb
JJ
4016 gsi_next (&gsi);
4017
fa9544ab
ML
4018 if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
4019 m_cleanup_cfg = true;
4020
8b57bfeb 4021 bb->aux = stridx_to_strinfo;
9771b263 4022 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
526ceb68 4023 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3daacdcd 4024 return NULL;
8b57bfeb
JJ
4025}
4026
4027/* Callback for walk_dominator_tree. Free strinfo vector if it is
4028 owned by the current bb, clear bb->aux. */
4029
4d9192b5
TS
4030void
4031strlen_dom_walker::after_dom_children (basic_block bb)
8b57bfeb
JJ
4032{
4033 if (bb->aux)
4034 {
526ceb68 4035 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
9771b263 4036 if (vec_safe_length (stridx_to_strinfo)
526ceb68 4037 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
8b57bfeb
JJ
4038 {
4039 unsigned int i;
526ceb68 4040 strinfo *si;
8b57bfeb 4041
9771b263 4042 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
8b57bfeb 4043 free_strinfo (si);
9771b263 4044 vec_free (stridx_to_strinfo);
8b57bfeb
JJ
4045 }
4046 bb->aux = NULL;
4047 }
4048}
4049
4050/* Main entry point. */
4051
27a4cd48
DM
4052namespace {
4053
4054const pass_data pass_data_strlen =
8b57bfeb 4055{
27a4cd48
DM
4056 GIMPLE_PASS, /* type */
4057 "strlen", /* name */
4058 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
4059 TV_TREE_STRLEN, /* tv_id */
4060 ( PROP_cfg | PROP_ssa ), /* properties_required */
4061 0, /* properties_provided */
4062 0, /* properties_destroyed */
4063 0, /* todo_flags_start */
3bea341f 4064 0, /* todo_flags_finish */
8b57bfeb 4065};
27a4cd48
DM
4066
4067class pass_strlen : public gimple_opt_pass
4068{
4069public:
c3284718
RS
4070 pass_strlen (gcc::context *ctxt)
4071 : gimple_opt_pass (pass_data_strlen, ctxt)
27a4cd48
DM
4072 {}
4073
4074 /* opt_pass methods: */
1a3d085c 4075 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
be55bfe6 4076 virtual unsigned int execute (function *);
27a4cd48
DM
4077
4078}; // class pass_strlen
4079
be55bfe6
TS
4080unsigned int
4081pass_strlen::execute (function *fun)
4082{
6a33d0ff
MS
4083 gcc_assert (!strlen_to_stridx);
4084 if (warn_stringop_overflow || warn_stringop_truncation)
4085 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
4086
be55bfe6
TS
4087 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
4088 max_stridx = 1;
be55bfe6
TS
4089
4090 calculate_dominance_info (CDI_DOMINATORS);
4091
4092 /* String length optimization is implemented as a walk of the dominator
4093 tree and a forward walk of statements within each block. */
fa9544ab
ML
4094 strlen_dom_walker walker (CDI_DOMINATORS);
4095 walker.walk (fun->cfg->x_entry_block_ptr);
be55bfe6
TS
4096
4097 ssa_ver_to_stridx.release ();
33e7d32e 4098 strinfo_pool.release ();
c203e8a7 4099 if (decl_to_stridxlist_htab)
be55bfe6
TS
4100 {
4101 obstack_free (&stridx_obstack, NULL);
c203e8a7
TS
4102 delete decl_to_stridxlist_htab;
4103 decl_to_stridxlist_htab = NULL;
be55bfe6
TS
4104 }
4105 laststmt.stmt = NULL;
4106 laststmt.len = NULL_TREE;
4107 laststmt.stridx = 0;
4108
6a33d0ff
MS
4109 if (strlen_to_stridx)
4110 {
4111 strlen_to_stridx->empty ();
4112 delete strlen_to_stridx;
4113 strlen_to_stridx = NULL;
4114 }
025d57f0 4115
fa9544ab 4116 return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
be55bfe6
TS
4117}
4118
27a4cd48
DM
4119} // anon namespace
4120
4121gimple_opt_pass *
4122make_pass_strlen (gcc::context *ctxt)
4123{
4124 return new pass_strlen (ctxt);
4125}