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