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