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