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