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