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