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