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