1 /* String length optimization
2 Copyright (C) 2011-2019 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "alloc-pool.h"
29 #include "tree-pass.h"
32 #include "gimple-pretty-print.h"
33 #include "gimple-ssa-warn-restrict.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
36 #include "gimple-fold.h"
39 #include "gimple-iterator.h"
40 #include "gimplify-me.h"
45 #include "tree-ssa-alias.h"
46 #include "tree-ssa-propagate.h"
47 #include "tree-ssa-strlen.h"
49 #include "tree-hash-traits.h"
50 #include "tree-object-size.h"
53 #include "diagnostic-core.h"
54 #include "diagnostic.h"
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). */
62 static vec
<int> ssa_ver_to_stridx
;
64 /* Number of currently active string indexes plus one. */
65 static int max_stridx
;
67 /* String information record. */
70 /* Number of leading characters that are known to be nonzero. This is
71 also the length of the string if FULL_STRING_P.
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. */
77 /* Any of the corresponding pointers for querying alias oracle. */
79 /* This is used for two things:
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.
85 - To record the malloc or calloc call that produced this result. */
87 /* Pointer to '\0' if known, if NULL, it can be computed as
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
95 /* Copy of index. get_strinfo (si->idx) should return si; */
97 /* These 3 fields are for chaining related string pointers together.
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. */
117 /* A flag whether the string is known to be written in the current
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
;
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. */
129 /* Pool for allocating strinfo_struct entries. */
130 static object_allocator
<strinfo
> strinfo_pool ("strinfo pool");
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. */
138 static vec
<strinfo
*, va_heap
, vl_embed
> *stridx_to_strinfo
;
140 /* One OFFSET->IDX mapping. */
143 struct stridxlist
*next
;
144 HOST_WIDE_INT offset
;
148 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
149 struct decl_stridxlist_map
151 struct tree_map_base base
;
152 struct stridxlist list
;
155 /* Hash table for mapping decls to a chained list of offset -> idx
157 static hash_map
<tree_decl_hash
, stridxlist
> *decl_to_stridxlist_htab
;
159 /* Hash table mapping strlen (or strnlen with constant bound and return
160 smaller than bound) calls to stridx instances describing
161 the calls' arguments. Non-null only when warn_stringop_truncation
163 typedef std::pair
<int, location_t
> stridx_strlenloc
;
164 static hash_map
<tree
, stridx_strlenloc
> *strlen_to_stridx
;
166 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
167 static struct obstack stridx_obstack
;
169 /* Last memcpy statement if it could be adjusted if the trailing
170 '\0' written is immediately overwritten, or
171 *x = '\0' store that could be removed if it is immediately overwritten. */
172 struct laststmt_struct
179 static int get_stridx_plus_constant (strinfo
*, unsigned HOST_WIDE_INT
, tree
);
180 static void handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*);
184 - 1 if SI is known to start with more than OFF nonzero characters.
186 - 0 if SI is known to start with OFF nonzero characters,
187 but is not known to start with more.
189 - -1 if SI might not start with OFF nonzero characters. */
192 compare_nonzero_chars (strinfo
*si
, unsigned HOST_WIDE_INT off
)
194 if (si
->nonzero_chars
195 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
196 return compare_tree_int (si
->nonzero_chars
, off
);
201 /* Return true if SI is known to be a zero-length string. */
204 zero_length_string_p (strinfo
*si
)
206 return si
->full_string_p
&& integer_zerop (si
->nonzero_chars
);
209 /* Return strinfo vector entry IDX. */
211 static inline strinfo
*
212 get_strinfo (int idx
)
214 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
216 return (*stridx_to_strinfo
)[idx
];
219 /* Get the next strinfo in the chain after SI, or null if none. */
221 static inline strinfo
*
222 get_next_strinfo (strinfo
*si
)
226 strinfo
*nextsi
= get_strinfo (si
->next
);
227 if (nextsi
== NULL
|| nextsi
->first
!= si
->first
|| nextsi
->prev
!= si
->idx
)
232 /* Helper function for get_stridx. Return the strinfo index of the address
233 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
234 OK to return the index for some X <= &EXP and store &EXP - X in
238 get_addr_stridx (tree exp
, tree ptr
, unsigned HOST_WIDE_INT
*offset_out
)
241 struct stridxlist
*list
, *last
= NULL
;
244 if (!decl_to_stridxlist_htab
)
248 base
= get_addr_base_and_unit_offset (exp
, &poff
);
249 if (base
== NULL
|| !DECL_P (base
) || !poff
.is_constant (&off
))
252 list
= decl_to_stridxlist_htab
->get (base
);
258 if (list
->offset
== off
)
264 if (list
->offset
> off
)
271 if ((offset_out
|| ptr
) && last
&& last
->idx
> 0)
273 unsigned HOST_WIDE_INT rel_off
274 = (unsigned HOST_WIDE_INT
) off
- last
->offset
;
275 strinfo
*si
= get_strinfo (last
->idx
);
276 if (si
&& compare_nonzero_chars (si
, rel_off
) >= 0)
280 *offset_out
= rel_off
;
284 return get_stridx_plus_constant (si
, rel_off
, ptr
);
290 /* Return string index for EXP. */
293 get_stridx (tree exp
)
295 if (TREE_CODE (exp
) == SSA_NAME
)
297 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)])
298 return ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)];
301 HOST_WIDE_INT offset
= 0;
302 /* Follow a chain of at most 5 assignments. */
303 for (int i
= 0; i
< 5; i
++)
305 gimple
*def_stmt
= SSA_NAME_DEF_STMT (e
);
306 if (!is_gimple_assign (def_stmt
))
309 tree_code rhs_code
= gimple_assign_rhs_code (def_stmt
);
312 if (rhs_code
== ADDR_EXPR
)
314 /* Handle indices/offsets into VLAs which are implemented
315 as pointers to arrays. */
316 ptr
= gimple_assign_rhs1 (def_stmt
);
317 ptr
= TREE_OPERAND (ptr
, 0);
319 /* Handle also VLAs of types larger than char. */
320 if (tree eltsize
= TYPE_SIZE_UNIT (TREE_TYPE (ptr
)))
322 if (TREE_CODE (ptr
) == ARRAY_REF
)
324 off
= TREE_OPERAND (ptr
, 1);
325 ptr
= TREE_OPERAND (ptr
, 0);
326 if (!integer_onep (eltsize
))
328 /* Scale the array index by the size of the element
329 type in the rare case that it's greater than
330 the typical 1 for char, making sure both operands
331 have the same type. */
332 eltsize
= fold_convert (ssizetype
, eltsize
);
333 off
= fold_convert (ssizetype
, off
);
334 off
= fold_build2 (MULT_EXPR
, ssizetype
, off
, eltsize
);
338 off
= integer_zero_node
;
343 if (TREE_CODE (ptr
) != MEM_REF
)
346 /* Add the MEM_REF byte offset. */
347 tree mem_off
= TREE_OPERAND (ptr
, 1);
348 off
= fold_build2 (PLUS_EXPR
, TREE_TYPE (off
), off
, mem_off
);
349 ptr
= TREE_OPERAND (ptr
, 0);
351 else if (rhs_code
== POINTER_PLUS_EXPR
)
353 ptr
= gimple_assign_rhs1 (def_stmt
);
354 off
= gimple_assign_rhs2 (def_stmt
);
359 if (TREE_CODE (ptr
) != SSA_NAME
360 || !tree_fits_shwi_p (off
))
362 HOST_WIDE_INT this_off
= tree_to_shwi (off
);
365 offset
= (unsigned HOST_WIDE_INT
) offset
+ this_off
;
368 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)])
371 = get_strinfo (ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)]);
372 if (si
&& compare_nonzero_chars (si
, offset
) >= 0)
373 return get_stridx_plus_constant (si
, offset
, exp
);
380 if (TREE_CODE (exp
) == ADDR_EXPR
)
382 int idx
= get_addr_stridx (TREE_OPERAND (exp
, 0), exp
, NULL
);
387 const char *p
= c_getstr (exp
);
389 return ~(int) strlen (p
);
394 /* Return true if strinfo vector is shared with the immediate dominator. */
397 strinfo_shared (void)
399 return vec_safe_length (stridx_to_strinfo
)
400 && (*stridx_to_strinfo
)[0] != NULL
;
403 /* Unshare strinfo vector that is shared with the immediate dominator. */
406 unshare_strinfo_vec (void)
411 gcc_assert (strinfo_shared ());
412 stridx_to_strinfo
= vec_safe_copy (stridx_to_strinfo
);
413 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
416 (*stridx_to_strinfo
)[0] = NULL
;
419 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
420 Return a pointer to the location where the string index can
421 be stored (if 0) or is stored, or NULL if this can't be tracked. */
424 addr_stridxptr (tree exp
)
429 tree base
= get_addr_base_and_unit_offset (exp
, &poff
);
430 if (base
== NULL_TREE
|| !DECL_P (base
) || !poff
.is_constant (&off
))
433 if (!decl_to_stridxlist_htab
)
435 decl_to_stridxlist_htab
436 = new hash_map
<tree_decl_hash
, stridxlist
> (64);
437 gcc_obstack_init (&stridx_obstack
);
441 stridxlist
*list
= &decl_to_stridxlist_htab
->get_or_insert (base
, &existed
);
445 stridxlist
*before
= NULL
;
446 for (i
= 0; i
< 32; i
++)
448 if (list
->offset
== off
)
450 if (list
->offset
> off
&& before
== NULL
)
452 if (list
->next
== NULL
)
461 before
= XOBNEW (&stridx_obstack
, struct stridxlist
);
468 list
->next
= XOBNEW (&stridx_obstack
, struct stridxlist
);
478 /* Create a new string index, or return 0 if reached limit. */
481 new_stridx (tree exp
)
484 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
486 if (TREE_CODE (exp
) == SSA_NAME
)
488 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
))
491 ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)] = idx
;
494 if (TREE_CODE (exp
) == ADDR_EXPR
)
496 int *pidx
= addr_stridxptr (TREE_OPERAND (exp
, 0));
499 gcc_assert (*pidx
== 0);
500 *pidx
= max_stridx
++;
507 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
510 new_addr_stridx (tree exp
)
513 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
515 pidx
= addr_stridxptr (exp
);
518 gcc_assert (*pidx
== 0);
519 *pidx
= max_stridx
++;
525 /* Create a new strinfo. */
528 new_strinfo (tree ptr
, int idx
, tree nonzero_chars
, bool full_string_p
)
530 strinfo
*si
= strinfo_pool
.allocate ();
531 si
->nonzero_chars
= nonzero_chars
;
534 si
->endptr
= NULL_TREE
;
540 si
->writable
= false;
541 si
->dont_invalidate
= false;
542 si
->full_string_p
= full_string_p
;
546 /* Decrease strinfo refcount and free it if not referenced anymore. */
549 free_strinfo (strinfo
*si
)
551 if (si
&& --si
->refcount
== 0)
552 strinfo_pool
.remove (si
);
555 /* Set strinfo in the vector entry IDX to SI. */
558 set_strinfo (int idx
, strinfo
*si
)
560 if (vec_safe_length (stridx_to_strinfo
) && (*stridx_to_strinfo
)[0])
561 unshare_strinfo_vec ();
562 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
563 vec_safe_grow_cleared (stridx_to_strinfo
, idx
+ 1);
564 (*stridx_to_strinfo
)[idx
] = si
;
567 /* Return the first strinfo in the related strinfo chain
568 if all strinfos in between belong to the chain, otherwise NULL. */
571 verify_related_strinfos (strinfo
*origsi
)
573 strinfo
*si
= origsi
, *psi
;
575 if (origsi
->first
== 0)
577 for (; si
->prev
; si
= psi
)
579 if (si
->first
!= origsi
->first
)
581 psi
= get_strinfo (si
->prev
);
584 if (psi
->next
!= si
->idx
)
587 if (si
->idx
!= si
->first
)
592 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
593 Use LOC for folding. */
596 set_endptr_and_length (location_t loc
, strinfo
*si
, tree endptr
)
600 tree start_as_size
= fold_convert_loc (loc
, size_type_node
, si
->ptr
);
601 tree end_as_size
= fold_convert_loc (loc
, size_type_node
, endptr
);
602 si
->nonzero_chars
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
603 end_as_size
, start_as_size
);
604 si
->full_string_p
= true;
607 /* Return string length, or NULL if it can't be computed. */
610 get_string_length (strinfo
*si
)
612 if (si
->nonzero_chars
)
613 return si
->full_string_p
? si
->nonzero_chars
: NULL
;
617 gimple
*stmt
= si
->stmt
, *lenstmt
;
618 tree callee
, lhs
, fn
, tem
;
620 gimple_stmt_iterator gsi
;
622 gcc_assert (is_gimple_call (stmt
));
623 callee
= gimple_call_fndecl (stmt
);
624 gcc_assert (callee
&& fndecl_built_in_p (callee
, BUILT_IN_NORMAL
));
625 lhs
= gimple_call_lhs (stmt
);
626 /* unshare_strinfo is intentionally not called here. The (delayed)
627 transformation of strcpy or strcat into stpcpy is done at the place
628 of the former strcpy/strcat call and so can affect all the strinfos
629 with the same stmt. If they were unshared before and transformation
630 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
631 just compute the right length. */
632 switch (DECL_FUNCTION_CODE (callee
))
634 case BUILT_IN_STRCAT
:
635 case BUILT_IN_STRCAT_CHK
:
636 gsi
= gsi_for_stmt (stmt
);
637 fn
= builtin_decl_implicit (BUILT_IN_STRLEN
);
638 gcc_assert (lhs
== NULL_TREE
);
639 tem
= unshare_expr (gimple_call_arg (stmt
, 0));
640 lenstmt
= gimple_build_call (fn
, 1, tem
);
641 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), lenstmt
);
642 gimple_call_set_lhs (lenstmt
, lhs
);
643 gimple_set_vuse (lenstmt
, gimple_vuse (stmt
));
644 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
645 tem
= gimple_call_arg (stmt
, 0);
646 if (!ptrofftype_p (TREE_TYPE (lhs
)))
648 lhs
= convert_to_ptrofftype (lhs
);
649 lhs
= force_gimple_operand_gsi (&gsi
, lhs
, true, NULL_TREE
,
650 true, GSI_SAME_STMT
);
652 lenstmt
= gimple_build_assign
653 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt
, 0))),
654 POINTER_PLUS_EXPR
,tem
, lhs
);
655 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
656 gimple_call_set_arg (stmt
, 0, gimple_assign_lhs (lenstmt
));
659 case BUILT_IN_STRCPY
:
660 case BUILT_IN_STRCPY_CHK
:
661 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY
));
662 if (gimple_call_num_args (stmt
) == 2)
663 fn
= builtin_decl_implicit (BUILT_IN_STPCPY
);
665 fn
= builtin_decl_explicit (BUILT_IN_STPCPY_CHK
);
666 gcc_assert (lhs
== NULL_TREE
);
667 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
669 fprintf (dump_file
, "Optimizing: ");
670 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
672 gimple_call_set_fndecl (stmt
, fn
);
673 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), stmt
);
674 gimple_call_set_lhs (stmt
, lhs
);
676 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
678 fprintf (dump_file
, "into: ");
679 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
682 case BUILT_IN_STPCPY
:
683 case BUILT_IN_STPCPY_CHK
:
684 gcc_assert (lhs
!= NULL_TREE
);
685 loc
= gimple_location (stmt
);
686 set_endptr_and_length (loc
, si
, lhs
);
687 for (strinfo
*chainsi
= verify_related_strinfos (si
);
689 chainsi
= get_next_strinfo (chainsi
))
690 if (chainsi
->nonzero_chars
== NULL
)
691 set_endptr_and_length (loc
, chainsi
, lhs
);
693 case BUILT_IN_MALLOC
:
695 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
702 return si
->nonzero_chars
;
705 /* Invalidate string length information for strings whose length
706 might change due to stores in stmt. */
709 maybe_invalidate (gimple
*stmt
)
713 bool nonempty
= false;
715 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
718 if (!si
->dont_invalidate
)
721 /* Do not use si->nonzero_chars. */
722 ao_ref_init_from_ptr_and_size (&r
, si
->ptr
, NULL_TREE
);
723 if (stmt_may_clobber_ref_p_1 (stmt
, &r
))
725 set_strinfo (i
, NULL
);
730 si
->dont_invalidate
= false;
736 /* Unshare strinfo record SI, if it has refcount > 1 or
737 if stridx_to_strinfo vector is shared with some other
741 unshare_strinfo (strinfo
*si
)
745 if (si
->refcount
== 1 && !strinfo_shared ())
748 nsi
= new_strinfo (si
->ptr
, si
->idx
, si
->nonzero_chars
, si
->full_string_p
);
749 nsi
->stmt
= si
->stmt
;
750 nsi
->endptr
= si
->endptr
;
751 nsi
->first
= si
->first
;
752 nsi
->prev
= si
->prev
;
753 nsi
->next
= si
->next
;
754 nsi
->writable
= si
->writable
;
755 set_strinfo (si
->idx
, nsi
);
760 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
761 strinfo if there is any. Return it's idx, or 0 if no strinfo has
765 get_stridx_plus_constant (strinfo
*basesi
, unsigned HOST_WIDE_INT off
,
768 if (TREE_CODE (ptr
) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
771 if (compare_nonzero_chars (basesi
, off
) < 0
772 || !tree_fits_uhwi_p (basesi
->nonzero_chars
))
775 unsigned HOST_WIDE_INT nonzero_chars
776 = tree_to_uhwi (basesi
->nonzero_chars
) - off
;
777 strinfo
*si
= basesi
, *chainsi
;
778 if (si
->first
|| si
->prev
|| si
->next
)
779 si
= verify_related_strinfos (basesi
);
781 || si
->nonzero_chars
== NULL_TREE
782 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
785 if (TREE_CODE (ptr
) == SSA_NAME
786 && ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
787 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
789 gcc_checking_assert (compare_tree_int (si
->nonzero_chars
, off
) != -1);
790 for (chainsi
= si
; chainsi
->next
; chainsi
= si
)
792 si
= get_next_strinfo (chainsi
);
794 || si
->nonzero_chars
== NULL_TREE
795 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
797 int r
= compare_tree_int (si
->nonzero_chars
, nonzero_chars
);
802 if (TREE_CODE (ptr
) == SSA_NAME
)
803 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = si
->idx
;
806 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
807 if (pidx
!= NULL
&& *pidx
== 0)
816 int idx
= new_stridx (ptr
);
819 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, nonzero_chars
),
820 basesi
->full_string_p
);
821 set_strinfo (idx
, si
);
822 if (strinfo
*nextsi
= get_strinfo (chainsi
->next
))
824 nextsi
= unshare_strinfo (nextsi
);
825 si
->next
= nextsi
->idx
;
828 chainsi
= unshare_strinfo (chainsi
);
829 if (chainsi
->first
== 0)
830 chainsi
->first
= chainsi
->idx
;
832 if (chainsi
->endptr
== NULL_TREE
&& zero_length_string_p (si
))
833 chainsi
->endptr
= ptr
;
834 si
->endptr
= chainsi
->endptr
;
835 si
->prev
= chainsi
->idx
;
836 si
->first
= chainsi
->first
;
837 si
->writable
= chainsi
->writable
;
841 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
842 to a zero-length string and if possible chain it to a related strinfo
843 chain whose part is or might be CHAINSI. */
846 zero_length_string (tree ptr
, strinfo
*chainsi
)
850 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
851 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
852 gcc_checking_assert (TREE_CODE (ptr
) == SSA_NAME
853 && ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] == 0);
855 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
859 si
= verify_related_strinfos (chainsi
);
864 /* We shouldn't mix delayed and non-delayed lengths. */
865 gcc_assert (si
->full_string_p
);
866 if (si
->endptr
== NULL_TREE
)
868 si
= unshare_strinfo (si
);
872 si
= get_next_strinfo (si
);
875 if (zero_length_string_p (chainsi
))
879 chainsi
= unshare_strinfo (chainsi
);
882 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = chainsi
->idx
;
888 /* We shouldn't mix delayed and non-delayed lengths. */
889 gcc_assert (chainsi
->full_string_p
);
890 if (chainsi
->first
|| chainsi
->prev
|| chainsi
->next
)
892 chainsi
= unshare_strinfo (chainsi
);
899 idx
= new_stridx (ptr
);
902 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, 0), true);
903 set_strinfo (idx
, si
);
907 chainsi
= unshare_strinfo (chainsi
);
908 if (chainsi
->first
== 0)
909 chainsi
->first
= chainsi
->idx
;
911 if (chainsi
->endptr
== NULL_TREE
)
912 chainsi
->endptr
= ptr
;
913 si
->prev
= chainsi
->idx
;
914 si
->first
= chainsi
->first
;
915 si
->writable
= chainsi
->writable
;
920 /* For strinfo ORIGSI whose length has been just updated, adjust other
921 related strinfos so that they match the new ORIGSI. This involves:
923 - adding ADJ to the nonzero_chars fields
924 - copying full_string_p from the new ORIGSI. */
927 adjust_related_strinfos (location_t loc
, strinfo
*origsi
, tree adj
)
929 strinfo
*si
= verify_related_strinfos (origsi
);
942 si
= unshare_strinfo (si
);
943 /* We shouldn't see delayed lengths here; the caller must
944 have calculated the old length in order to calculate
946 gcc_assert (si
->nonzero_chars
);
947 tem
= fold_convert_loc (loc
, TREE_TYPE (si
->nonzero_chars
), adj
);
948 si
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
949 TREE_TYPE (si
->nonzero_chars
),
950 si
->nonzero_chars
, tem
);
951 si
->full_string_p
= origsi
->full_string_p
;
953 si
->endptr
= NULL_TREE
;
954 si
->dont_invalidate
= true;
956 nsi
= get_next_strinfo (si
);
963 /* Find if there are other SSA_NAME pointers equal to PTR
964 for which we don't track their string lengths yet. If so, use
968 find_equal_ptrs (tree ptr
, int idx
)
970 if (TREE_CODE (ptr
) != SSA_NAME
)
974 gimple
*stmt
= SSA_NAME_DEF_STMT (ptr
);
975 if (!is_gimple_assign (stmt
))
977 ptr
= gimple_assign_rhs1 (stmt
);
978 switch (gimple_assign_rhs_code (stmt
))
983 if (!POINTER_TYPE_P (TREE_TYPE (ptr
)))
985 if (TREE_CODE (ptr
) == SSA_NAME
)
987 if (TREE_CODE (ptr
) != ADDR_EXPR
)
992 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
993 if (pidx
!= NULL
&& *pidx
== 0)
1001 /* We might find an endptr created in this pass. Grow the
1002 vector in that case. */
1003 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
1004 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
1006 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] != 0)
1008 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = idx
;
1012 /* Return true if STMT is a call to a builtin function with the right
1013 arguments and attributes that should be considered for optimization
1017 valid_builtin_call (gimple
*stmt
)
1019 if (!gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
1022 tree callee
= gimple_call_fndecl (stmt
);
1023 tree decl
= builtin_decl_explicit (DECL_FUNCTION_CODE (callee
));
1026 && !gimple_builtin_call_types_compatible_p (stmt
, decl
))
1029 switch (DECL_FUNCTION_CODE (callee
))
1031 case BUILT_IN_MEMCMP
:
1032 case BUILT_IN_MEMCMP_EQ
:
1033 case BUILT_IN_STRCMP
:
1034 case BUILT_IN_STRNCMP
:
1035 case BUILT_IN_STRCHR
:
1036 case BUILT_IN_STRLEN
:
1037 case BUILT_IN_STRNLEN
:
1038 /* The above functions should be pure. Punt if they aren't. */
1039 if (gimple_vdef (stmt
) || gimple_vuse (stmt
) == NULL_TREE
)
1043 case BUILT_IN_CALLOC
:
1044 case BUILT_IN_MALLOC
:
1045 case BUILT_IN_MEMCPY
:
1046 case BUILT_IN_MEMCPY_CHK
:
1047 case BUILT_IN_MEMPCPY
:
1048 case BUILT_IN_MEMPCPY_CHK
:
1049 case BUILT_IN_MEMSET
:
1050 case BUILT_IN_STPCPY
:
1051 case BUILT_IN_STPCPY_CHK
:
1052 case BUILT_IN_STPNCPY
:
1053 case BUILT_IN_STPNCPY_CHK
:
1054 case BUILT_IN_STRCAT
:
1055 case BUILT_IN_STRCAT_CHK
:
1056 case BUILT_IN_STRCPY
:
1057 case BUILT_IN_STRCPY_CHK
:
1058 case BUILT_IN_STRNCAT
:
1059 case BUILT_IN_STRNCAT_CHK
:
1060 case BUILT_IN_STRNCPY
:
1061 case BUILT_IN_STRNCPY_CHK
:
1062 /* The above functions should be neither const nor pure. Punt if they
1064 if (gimple_vdef (stmt
) == NULL_TREE
|| gimple_vuse (stmt
) == NULL_TREE
)
1075 /* If the last .MEM setter statement before STMT is
1076 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1077 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1078 just memcpy (x, y, strlen (y)). SI must be the zero length
1082 adjust_last_stmt (strinfo
*si
, gimple
*stmt
, bool is_strcat
)
1084 tree vuse
, callee
, len
;
1085 struct laststmt_struct last
= laststmt
;
1086 strinfo
*lastsi
, *firstsi
;
1087 unsigned len_arg_no
= 2;
1089 laststmt
.stmt
= NULL
;
1090 laststmt
.len
= NULL_TREE
;
1091 laststmt
.stridx
= 0;
1093 if (last
.stmt
== NULL
)
1096 vuse
= gimple_vuse (stmt
);
1097 if (vuse
== NULL_TREE
1098 || SSA_NAME_DEF_STMT (vuse
) != last
.stmt
1099 || !has_single_use (vuse
))
1102 gcc_assert (last
.stridx
> 0);
1103 lastsi
= get_strinfo (last
.stridx
);
1109 if (lastsi
->first
== 0 || lastsi
->first
!= si
->first
)
1112 firstsi
= verify_related_strinfos (si
);
1113 if (firstsi
== NULL
)
1115 while (firstsi
!= lastsi
)
1117 firstsi
= get_next_strinfo (firstsi
);
1118 if (firstsi
== NULL
)
1123 if (!is_strcat
&& !zero_length_string_p (si
))
1126 if (is_gimple_assign (last
.stmt
))
1128 gimple_stmt_iterator gsi
;
1130 if (!integer_zerop (gimple_assign_rhs1 (last
.stmt
)))
1132 if (stmt_could_throw_p (cfun
, last
.stmt
))
1134 gsi
= gsi_for_stmt (last
.stmt
);
1135 unlink_stmt_vdef (last
.stmt
);
1136 release_defs (last
.stmt
);
1137 gsi_remove (&gsi
, true);
1141 if (!valid_builtin_call (last
.stmt
))
1144 callee
= gimple_call_fndecl (last
.stmt
);
1145 switch (DECL_FUNCTION_CODE (callee
))
1147 case BUILT_IN_MEMCPY
:
1148 case BUILT_IN_MEMCPY_CHK
:
1154 len
= gimple_call_arg (last
.stmt
, len_arg_no
);
1155 if (tree_fits_uhwi_p (len
))
1157 if (!tree_fits_uhwi_p (last
.len
)
1158 || integer_zerop (len
)
1159 || tree_to_uhwi (len
) != tree_to_uhwi (last
.len
) + 1)
1161 /* Don't adjust the length if it is divisible by 4, it is more efficient
1162 to store the extra '\0' in that case. */
1163 if ((tree_to_uhwi (len
) & 3) == 0)
1166 /* Don't fold away an out of bounds access, as this defeats proper
1168 tree dst
= gimple_call_arg (last
.stmt
, 0);
1169 tree size
= compute_objsize (dst
, 0);
1170 if (size
&& tree_int_cst_lt (size
, len
))
1173 else if (TREE_CODE (len
) == SSA_NAME
)
1175 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1176 if (!is_gimple_assign (def_stmt
)
1177 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
1178 || gimple_assign_rhs1 (def_stmt
) != last
.len
1179 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
1185 gimple_call_set_arg (last
.stmt
, len_arg_no
, last
.len
);
1186 update_stmt (last
.stmt
);
1189 /* For an LHS that is an SSA_NAME that is the result of a strlen()
1190 call, or when BOUND is non-null, of a strnlen() call, set LHS
1191 range info to [0, min (MAX, BOUND)] when the range includes more
1192 than one value and return LHS. Otherwise, when the range
1193 [MIN, MAX] is such that MIN == MAX, return the tree representation
1194 of (MIN). The latter allows callers to fold suitable strnlen() calls
1198 set_strlen_range (tree lhs
, wide_int max
, tree bound
/* = NULL_TREE */)
1200 if (TREE_CODE (lhs
) != SSA_NAME
1201 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
1204 wide_int min
= wi::zero (max
.get_precision ());
1208 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1209 is less than the size of the array set MAX to it. It it's
1210 greater than MAX and MAX is non-zero bump MAX down to account
1211 for the necessary terminating nul. Otherwise leave it alone. */
1212 if (TREE_CODE (bound
) == INTEGER_CST
)
1214 wide_int wibnd
= wi::to_wide (bound
);
1215 int cmp
= wi::cmpu (wibnd
, max
);
1218 else if (cmp
&& wi::ne_p (max
, min
))
1221 else if (TREE_CODE (bound
) == SSA_NAME
)
1223 wide_int minbound
, maxbound
;
1224 value_range_kind rng
= get_range_info (bound
, &minbound
, &maxbound
);
1225 if (rng
== VR_RANGE
)
1227 /* For a bound in a known range, adjust the range determined
1228 above as necessary. For a bound in some anti-range or
1229 in an unknown range, use the range determined by callers. */
1230 if (wi::ltu_p (minbound
, min
))
1232 if (wi::ltu_p (maxbound
, max
))
1239 return wide_int_to_tree (size_type_node
, min
);
1241 set_range_info (lhs
, VR_RANGE
, min
, max
);
1245 /* For an LHS that is an SSA_NAME and for strlen() or strnlen() argument
1246 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1247 a character array A[N] with unknown length bounded by N, and for
1248 strnlen(), by min (N, BOUND). */
1251 maybe_set_strlen_range (tree lhs
, tree src
, tree bound
)
1253 if (TREE_CODE (lhs
) != SSA_NAME
1254 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
1257 if (TREE_CODE (src
) == SSA_NAME
)
1259 gimple
*def
= SSA_NAME_DEF_STMT (src
);
1260 if (is_gimple_assign (def
)
1261 && gimple_assign_rhs_code (def
) == ADDR_EXPR
)
1262 src
= gimple_assign_rhs1 (def
);
1265 /* The longest string is PTRDIFF_MAX - 1 bytes including the final
1266 NUL so that the difference between a pointer to just past it and
1267 one to its beginning is positive. */
1268 wide_int max
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
)) - 2;
1270 if (TREE_CODE (src
) == ADDR_EXPR
)
1272 /* The last array member of a struct can be bigger than its size
1273 suggests if it's treated as a poor-man's flexible array member. */
1274 src
= TREE_OPERAND (src
, 0);
1275 if (TREE_CODE (src
) != MEM_REF
1276 && !array_at_struct_end_p (src
))
1278 tree type
= TREE_TYPE (src
);
1279 tree size
= TYPE_SIZE_UNIT (type
);
1281 && TREE_CODE (size
) == INTEGER_CST
1282 && !integer_zerop (size
))
1284 /* Even though such uses of strlen would be undefined,
1285 avoid relying on arrays of arrays in case some genius
1286 decides to call strlen on an unterminated array element
1287 that's followed by a terminated one. Likewise, avoid
1288 assuming that a struct array member is necessarily
1289 nul-terminated (the nul may be in the member that
1290 follows). In those cases, assume that the length
1291 of the string stored in such an array is bounded
1292 by the size of the enclosing object if one can be
1294 tree base
= get_base_address (src
);
1297 if (tree size
= DECL_SIZE_UNIT (base
))
1299 && TREE_CODE (size
) == INTEGER_CST
1300 && TREE_CODE (TREE_TYPE (base
)) != POINTER_TYPE
)
1301 max
= wi::to_wide (size
);
1305 /* For strlen() the upper bound above is equal to
1306 the longest string that can be stored in the array
1307 (i.e., it accounts for the terminating nul. For
1308 strnlen() bump up the maximum by one since the array
1309 need not be nul-terminated. */
1310 if (!bound
&& max
!= 0)
1315 return set_strlen_range (lhs
, max
, bound
);
1318 /* Handle a strlen call. If strlen of the argument is known, replace
1319 the strlen call with the known value, otherwise remember that strlen
1320 of the argument is stored in the lhs SSA_NAME. */
1323 handle_builtin_strlen (gimple_stmt_iterator
*gsi
)
1325 gimple
*stmt
= gsi_stmt (*gsi
);
1326 tree lhs
= gimple_call_lhs (stmt
);
1328 if (lhs
== NULL_TREE
)
1331 location_t loc
= gimple_location (stmt
);
1332 tree callee
= gimple_call_fndecl (stmt
);
1333 tree src
= gimple_call_arg (stmt
, 0);
1334 tree bound
= (DECL_FUNCTION_CODE (callee
) == BUILT_IN_STRNLEN
1335 ? gimple_call_arg (stmt
, 1) : NULL_TREE
);
1336 int idx
= get_stridx (src
);
1337 if (idx
|| (bound
&& integer_zerop (bound
)))
1343 rhs
= build_int_cst (TREE_TYPE (lhs
), ~idx
);
1349 si
= get_strinfo (idx
);
1352 rhs
= get_string_length (si
);
1353 /* For strnlen, if bound is constant, even if si is not known
1354 to be zero terminated, if we know at least bound bytes are
1355 not zero, the return value will be bound. */
1356 if (rhs
== NULL_TREE
1357 && bound
!= NULL_TREE
1358 && TREE_CODE (bound
) == INTEGER_CST
1359 && si
->nonzero_chars
!= NULL_TREE
1360 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
1361 && tree_int_cst_le (bound
, si
->nonzero_chars
))
1365 if (rhs
!= NULL_TREE
)
1367 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1369 fprintf (dump_file
, "Optimizing: ");
1370 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1372 rhs
= unshare_expr (rhs
);
1373 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
1374 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1377 rhs
= fold_build2_loc (loc
, MIN_EXPR
, TREE_TYPE (rhs
), rhs
, bound
);
1379 if (!update_call_from_tree (gsi
, rhs
))
1380 gimplify_and_update_call_from_tree (gsi
, rhs
);
1381 stmt
= gsi_stmt (*gsi
);
1383 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1385 fprintf (dump_file
, "into: ");
1386 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1390 /* Don't update anything for strnlen. */
1391 && bound
== NULL_TREE
1392 && TREE_CODE (si
->nonzero_chars
) != SSA_NAME
1393 && TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
1394 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1396 si
= unshare_strinfo (si
);
1397 si
->nonzero_chars
= lhs
;
1398 gcc_assert (si
->full_string_p
);
1401 if (strlen_to_stridx
1402 && (bound
== NULL_TREE
1403 /* For strnlen record this only if the call is proven
1404 to return the same value as strlen would. */
1405 || (TREE_CODE (bound
) == INTEGER_CST
1406 && TREE_CODE (rhs
) == INTEGER_CST
1407 && tree_int_cst_lt (rhs
, bound
))))
1408 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1413 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1417 idx
= new_stridx (src
);
1420 strinfo
*si
= get_strinfo (idx
);
1423 if (!si
->full_string_p
&& !si
->stmt
)
1425 /* Until now we only had a lower bound on the string length.
1426 Install LHS as the actual length. */
1427 si
= unshare_strinfo (si
);
1428 tree old
= si
->nonzero_chars
;
1429 si
->nonzero_chars
= lhs
;
1430 si
->full_string_p
= true;
1431 if (TREE_CODE (old
) == INTEGER_CST
)
1433 old
= fold_convert_loc (loc
, TREE_TYPE (lhs
), old
);
1434 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1435 TREE_TYPE (lhs
), lhs
, old
);
1436 adjust_related_strinfos (loc
, si
, adj
);
1452 /* Only store the new length information for calls to strlen(),
1453 not for those to strnlen(). */
1454 strinfo
*si
= new_strinfo (src
, idx
, lhs
, true);
1455 set_strinfo (idx
, si
);
1456 find_equal_ptrs (src
, idx
);
1459 /* For SRC that is an array of N elements, set LHS's range
1460 to [0, min (N, BOUND)]. A constant return value means
1461 the range would have consisted of a single value. In
1462 that case, fold the result into the returned constant. */
1463 if (tree ret
= maybe_set_strlen_range (lhs
, src
, bound
))
1464 if (TREE_CODE (ret
) == INTEGER_CST
)
1466 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1468 fprintf (dump_file
, "Optimizing: ");
1469 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1471 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (ret
)))
1472 ret
= fold_convert_loc (loc
, TREE_TYPE (lhs
), ret
);
1473 if (!update_call_from_tree (gsi
, ret
))
1474 gimplify_and_update_call_from_tree (gsi
, ret
);
1475 stmt
= gsi_stmt (*gsi
);
1477 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1479 fprintf (dump_file
, "into: ");
1480 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1484 if (strlen_to_stridx
&& !bound
)
1485 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1489 /* Handle a strchr call. If strlen of the first argument is known, replace
1490 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1491 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1494 handle_builtin_strchr (gimple_stmt_iterator
*gsi
)
1498 gimple
*stmt
= gsi_stmt (*gsi
);
1499 tree lhs
= gimple_call_lhs (stmt
);
1501 if (lhs
== NULL_TREE
)
1504 if (!integer_zerop (gimple_call_arg (stmt
, 1)))
1507 src
= gimple_call_arg (stmt
, 0);
1508 idx
= get_stridx (src
);
1515 rhs
= build_int_cst (size_type_node
, ~idx
);
1519 si
= get_strinfo (idx
);
1521 rhs
= get_string_length (si
);
1523 if (rhs
!= NULL_TREE
)
1525 location_t loc
= gimple_location (stmt
);
1527 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1529 fprintf (dump_file
, "Optimizing: ");
1530 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1532 if (si
!= NULL
&& si
->endptr
!= NULL_TREE
)
1534 rhs
= unshare_expr (si
->endptr
);
1535 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1537 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1541 rhs
= fold_convert_loc (loc
, sizetype
, unshare_expr (rhs
));
1542 rhs
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
1543 TREE_TYPE (src
), src
, rhs
);
1544 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1546 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1548 if (!update_call_from_tree (gsi
, rhs
))
1549 gimplify_and_update_call_from_tree (gsi
, rhs
);
1550 stmt
= gsi_stmt (*gsi
);
1552 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1554 fprintf (dump_file
, "into: ");
1555 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1558 && si
->endptr
== NULL_TREE
1559 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1561 si
= unshare_strinfo (si
);
1564 zero_length_string (lhs
, si
);
1568 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1570 if (TREE_CODE (src
) != SSA_NAME
|| !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src
))
1573 idx
= new_stridx (src
);
1574 else if (get_strinfo (idx
) != NULL
)
1576 zero_length_string (lhs
, NULL
);
1581 location_t loc
= gimple_location (stmt
);
1582 tree lhsu
= fold_convert_loc (loc
, size_type_node
, lhs
);
1583 tree srcu
= fold_convert_loc (loc
, size_type_node
, src
);
1584 tree length
= fold_build2_loc (loc
, MINUS_EXPR
,
1585 size_type_node
, lhsu
, srcu
);
1586 strinfo
*si
= new_strinfo (src
, idx
, length
, true);
1588 set_strinfo (idx
, si
);
1589 find_equal_ptrs (src
, idx
);
1590 zero_length_string (lhs
, si
);
1594 zero_length_string (lhs
, NULL
);
1597 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1598 If strlen of the second argument is known, strlen of the first argument
1599 is the same after this call. Furthermore, attempt to convert it to
1603 handle_builtin_strcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1606 tree src
, dst
, srclen
, len
, lhs
, type
, fn
, oldlen
;
1608 gimple
*stmt
= gsi_stmt (*gsi
);
1609 strinfo
*si
, *dsi
, *olddsi
, *zsi
;
1612 src
= gimple_call_arg (stmt
, 1);
1613 dst
= gimple_call_arg (stmt
, 0);
1614 lhs
= gimple_call_lhs (stmt
);
1615 idx
= get_stridx (src
);
1618 si
= get_strinfo (idx
);
1620 didx
= get_stridx (dst
);
1624 olddsi
= get_strinfo (didx
);
1629 adjust_last_stmt (olddsi
, stmt
, false);
1633 srclen
= get_string_length (si
);
1635 srclen
= build_int_cst (size_type_node
, ~idx
);
1637 loc
= gimple_location (stmt
);
1638 if (srclen
== NULL_TREE
)
1641 case BUILT_IN_STRCPY
:
1642 case BUILT_IN_STRCPY_CHK
:
1643 if (lhs
!= NULL_TREE
|| !builtin_decl_implicit_p (BUILT_IN_STPCPY
))
1646 case BUILT_IN_STPCPY
:
1647 case BUILT_IN_STPCPY_CHK
:
1648 if (lhs
== NULL_TREE
)
1652 tree lhsuint
= fold_convert_loc (loc
, size_type_node
, lhs
);
1653 srclen
= fold_convert_loc (loc
, size_type_node
, dst
);
1654 srclen
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
1664 didx
= new_stridx (dst
);
1670 oldlen
= olddsi
->nonzero_chars
;
1671 dsi
= unshare_strinfo (olddsi
);
1672 dsi
->nonzero_chars
= srclen
;
1673 dsi
->full_string_p
= (srclen
!= NULL_TREE
);
1674 /* Break the chain, so adjust_related_strinfo on later pointers in
1675 the chain won't adjust this one anymore. */
1678 dsi
->endptr
= NULL_TREE
;
1682 dsi
= new_strinfo (dst
, didx
, srclen
, srclen
!= NULL_TREE
);
1683 set_strinfo (didx
, dsi
);
1684 find_equal_ptrs (dst
, didx
);
1686 dsi
->writable
= true;
1687 dsi
->dont_invalidate
= true;
1689 if (dsi
->nonzero_chars
== NULL_TREE
)
1693 /* If string length of src is unknown, use delayed length
1694 computation. If string lenth of dst will be needed, it
1695 can be computed by transforming this strcpy call into
1696 stpcpy and subtracting dst from the return value. */
1698 /* Look for earlier strings whose length could be determined if
1699 this strcpy is turned into an stpcpy. */
1701 if (dsi
->prev
!= 0 && (chainsi
= verify_related_strinfos (dsi
)) != NULL
)
1703 for (; chainsi
&& chainsi
!= dsi
; chainsi
= get_strinfo (chainsi
->next
))
1705 /* When setting a stmt for delayed length computation
1706 prevent all strinfos through dsi from being
1708 chainsi
= unshare_strinfo (chainsi
);
1709 chainsi
->stmt
= stmt
;
1710 chainsi
->nonzero_chars
= NULL_TREE
;
1711 chainsi
->full_string_p
= false;
1712 chainsi
->endptr
= NULL_TREE
;
1713 chainsi
->dont_invalidate
= true;
1718 /* Try to detect overlap before returning. This catches cases
1719 like strcpy (d, d + n) where n is non-constant whose range
1720 is such that (n <= strlen (d) holds).
1722 OLDDSI->NONZERO_chars may have been reset by this point with
1723 oldlen holding it original value. */
1724 if (olddsi
&& oldlen
)
1726 /* Add 1 for the terminating NUL. */
1727 tree type
= TREE_TYPE (oldlen
);
1728 oldlen
= fold_build2 (PLUS_EXPR
, type
, oldlen
,
1729 build_int_cst (type
, 1));
1730 check_bounds_or_overlap (stmt
, olddsi
->ptr
, src
, oldlen
, NULL_TREE
);
1738 tree adj
= NULL_TREE
;
1739 if (oldlen
== NULL_TREE
)
1741 else if (integer_zerop (oldlen
))
1743 else if (TREE_CODE (oldlen
) == INTEGER_CST
1744 || TREE_CODE (srclen
) == INTEGER_CST
)
1745 adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1746 TREE_TYPE (srclen
), srclen
,
1747 fold_convert_loc (loc
, TREE_TYPE (srclen
),
1749 if (adj
!= NULL_TREE
)
1750 adjust_related_strinfos (loc
, dsi
, adj
);
1754 /* strcpy src may not overlap dst, so src doesn't need to be
1755 invalidated either. */
1757 si
->dont_invalidate
= true;
1763 case BUILT_IN_STRCPY
:
1764 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
1766 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1768 case BUILT_IN_STRCPY_CHK
:
1769 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
1771 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1773 case BUILT_IN_STPCPY
:
1774 /* This would need adjustment of the lhs (subtract one),
1775 or detection that the trailing '\0' doesn't need to be
1776 written, if it will be immediately overwritten.
1777 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1781 zsi
= zero_length_string (lhs
, dsi
);
1784 case BUILT_IN_STPCPY_CHK
:
1785 /* This would need adjustment of the lhs (subtract one),
1786 or detection that the trailing '\0' doesn't need to be
1787 written, if it will be immediately overwritten.
1788 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1792 zsi
= zero_length_string (lhs
, dsi
);
1799 zsi
->dont_invalidate
= true;
1803 tree args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1804 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
1807 type
= size_type_node
;
1809 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
1810 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
, build_int_cst (type
, 1));
1812 /* Set the no-warning bit on the transformed statement? */
1813 bool set_no_warning
= false;
1815 if (const strinfo
*chksi
= olddsi
? olddsi
: dsi
)
1817 && check_bounds_or_overlap (stmt
, chksi
->ptr
, si
->ptr
, NULL_TREE
, len
))
1819 gimple_set_no_warning (stmt
, true);
1820 set_no_warning
= true;
1823 if (fn
== NULL_TREE
)
1826 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
1828 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1830 fprintf (dump_file
, "Optimizing: ");
1831 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1833 if (gimple_call_num_args (stmt
) == 2)
1834 success
= update_gimple_call (gsi
, fn
, 3, dst
, src
, len
);
1836 success
= update_gimple_call (gsi
, fn
, 4, dst
, src
, len
,
1837 gimple_call_arg (stmt
, 2));
1840 stmt
= gsi_stmt (*gsi
);
1842 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1844 fprintf (dump_file
, "into: ");
1845 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1847 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1848 laststmt
.stmt
= stmt
;
1849 laststmt
.len
= srclen
;
1850 laststmt
.stridx
= dsi
->idx
;
1852 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1853 fprintf (dump_file
, "not possible.\n");
1856 gimple_set_no_warning (stmt
, true);
1859 /* Check the size argument to the built-in forms of stpncpy and strncpy
1860 for out-of-bounds offsets or overlapping access, and to see if the
1861 size argument is derived from a call to strlen() on the source argument,
1862 and if so, issue an appropriate warning. */
1865 handle_builtin_strncat (built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1867 /* Same as stxncpy(). */
1868 handle_builtin_stxncpy (bcode
, gsi
);
1871 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1872 way. LEN can either be an integer expression, or a pointer (to char).
1873 When it is the latter (such as in recursive calls to self) is is
1874 assumed to be the argument in some call to strlen() whose relationship
1875 to SRC is being ascertained. */
1878 is_strlen_related_p (tree src
, tree len
)
1880 if (TREE_CODE (TREE_TYPE (len
)) == POINTER_TYPE
1881 && operand_equal_p (src
, len
, 0))
1884 if (TREE_CODE (len
) != SSA_NAME
)
1887 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1891 if (is_gimple_call (def_stmt
))
1893 tree func
= gimple_call_fndecl (def_stmt
);
1894 if (!valid_builtin_call (def_stmt
)
1895 || DECL_FUNCTION_CODE (func
) != BUILT_IN_STRLEN
)
1898 tree arg
= gimple_call_arg (def_stmt
, 0);
1899 return is_strlen_related_p (src
, arg
);
1902 if (!is_gimple_assign (def_stmt
))
1905 tree_code code
= gimple_assign_rhs_code (def_stmt
);
1906 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1907 tree rhstype
= TREE_TYPE (rhs1
);
1909 if ((TREE_CODE (rhstype
) == POINTER_TYPE
&& code
== POINTER_PLUS_EXPR
)
1910 || (INTEGRAL_TYPE_P (rhstype
)
1911 && (code
== BIT_AND_EXPR
1912 || code
== NOP_EXPR
)))
1914 /* Pointer plus (an integer), and truncation are considered among
1915 the (potentially) related expressions to strlen. */
1916 return is_strlen_related_p (src
, rhs1
);
1919 if (tree rhs2
= gimple_assign_rhs2 (def_stmt
))
1921 /* Integer subtraction is considered strlen-related when both
1922 arguments are integers and second one is strlen-related. */
1923 rhstype
= TREE_TYPE (rhs2
);
1924 if (INTEGRAL_TYPE_P (rhstype
) && code
== MINUS_EXPR
)
1925 return is_strlen_related_p (src
, rhs2
);
1931 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1933 Check to see if the specified bound is a) equal to the size of
1934 the destination DST and if so, b) if it's immediately followed by
1935 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1936 do nothing. Return true if diagnostic has been issued.
1938 The purpose is to diagnose calls to strncpy and stpncpy that do
1939 not nul-terminate the copy while allowing for the idiom where
1940 such a call is immediately followed by setting the last element
1943 strncpy (a, s, sizeof a);
1944 a[sizeof a - 1] = '\0';
1948 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi
, tree src
, tree cnt
)
1950 gimple
*stmt
= gsi_stmt (gsi
);
1951 if (gimple_no_warning_p (stmt
))
1954 wide_int cntrange
[2];
1956 if (TREE_CODE (cnt
) == INTEGER_CST
)
1957 cntrange
[0] = cntrange
[1] = wi::to_wide (cnt
);
1958 else if (TREE_CODE (cnt
) == SSA_NAME
)
1960 enum value_range_kind rng
= get_range_info (cnt
, cntrange
, cntrange
+ 1);
1961 if (rng
== VR_RANGE
)
1963 else if (rng
== VR_ANTI_RANGE
)
1965 wide_int maxobjsize
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
));
1967 if (wi::ltu_p (cntrange
[1], maxobjsize
))
1969 cntrange
[0] = cntrange
[1] + 1;
1970 cntrange
[1] = maxobjsize
;
1974 cntrange
[1] = cntrange
[0] - 1;
1975 cntrange
[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt
)));
1984 /* Negative value is the constant string length. If it's less than
1985 the lower bound there is no truncation. Avoid calling get_stridx()
1986 when ssa_ver_to_stridx is empty. That implies the caller isn't
1987 running under the control of this pass and ssa_ver_to_stridx hasn't
1988 been created yet. */
1989 int sidx
= ssa_ver_to_stridx
.length () ? get_stridx (src
) : 0;
1990 if (sidx
< 0 && wi::gtu_p (cntrange
[0], ~sidx
))
1993 tree dst
= gimple_call_arg (stmt
, 0);
1995 if (TREE_CODE (dstdecl
) == ADDR_EXPR
)
1996 dstdecl
= TREE_OPERAND (dstdecl
, 0);
1998 tree ref
= NULL_TREE
;
2002 /* If the source is a non-string return early to avoid warning
2003 for possible truncation (if the truncation is certain SIDX
2005 tree srcdecl
= gimple_call_arg (stmt
, 1);
2006 if (TREE_CODE (srcdecl
) == ADDR_EXPR
)
2007 srcdecl
= TREE_OPERAND (srcdecl
, 0);
2008 if (get_attr_nonstring_decl (srcdecl
, &ref
))
2012 /* Likewise, if the destination refers to a an array/pointer declared
2013 nonstring return early. */
2014 if (get_attr_nonstring_decl (dstdecl
, &ref
))
2017 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
2018 avoid the truncation warning. */
2019 gsi_next_nondebug (&gsi
);
2020 gimple
*next_stmt
= gsi_stmt (gsi
);
2023 /* When there is no statement in the same basic block check
2024 the immediate successor block. */
2025 if (basic_block bb
= gimple_bb (stmt
))
2027 if (single_succ_p (bb
))
2029 /* For simplicity, ignore blocks with multiple outgoing
2030 edges for now and only consider successor blocks along
2032 edge e
= EDGE_SUCC (bb
, 0);
2033 if (!(e
->flags
& EDGE_ABNORMAL
))
2035 gsi
= gsi_start_bb (e
->dest
);
2036 next_stmt
= gsi_stmt (gsi
);
2037 if (next_stmt
&& is_gimple_debug (next_stmt
))
2039 gsi_next_nondebug (&gsi
);
2040 next_stmt
= gsi_stmt (gsi
);
2047 if (next_stmt
&& is_gimple_assign (next_stmt
))
2049 tree lhs
= gimple_assign_lhs (next_stmt
);
2050 tree_code code
= TREE_CODE (lhs
);
2051 if (code
== ARRAY_REF
|| code
== MEM_REF
)
2052 lhs
= TREE_OPERAND (lhs
, 0);
2054 tree func
= gimple_call_fndecl (stmt
);
2055 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STPNCPY
)
2057 tree ret
= gimple_call_lhs (stmt
);
2058 if (ret
&& operand_equal_p (ret
, lhs
, 0))
2062 /* Determine the base address and offset of the reference,
2063 ignoring the innermost array index. */
2064 if (TREE_CODE (ref
) == ARRAY_REF
)
2065 ref
= TREE_OPERAND (ref
, 0);
2068 tree dstbase
= get_addr_base_and_unit_offset (ref
, &dstoff
);
2071 tree lhsbase
= get_addr_base_and_unit_offset (lhs
, &lhsoff
);
2074 && known_eq (dstoff
, lhsoff
)
2075 && operand_equal_p (dstbase
, lhsbase
, 0))
2079 int prec
= TYPE_PRECISION (TREE_TYPE (cnt
));
2080 wide_int lenrange
[2];
2081 if (strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
)
2083 lenrange
[0] = (sisrc
->nonzero_chars
2084 && TREE_CODE (sisrc
->nonzero_chars
) == INTEGER_CST
2085 ? wi::to_wide (sisrc
->nonzero_chars
)
2087 lenrange
[1] = lenrange
[0];
2090 lenrange
[0] = lenrange
[1] = wi::shwi (~sidx
, prec
);
2093 c_strlen_data lendata
= { };
2094 get_range_strlen (src
, &lendata
, /* eltsize = */1);
2095 if (TREE_CODE (lendata
.minlen
) == INTEGER_CST
2096 && TREE_CODE (lendata
.maxbound
) == INTEGER_CST
)
2098 /* When LENDATA.MAXLEN is unknown, reset LENDATA.MINLEN
2099 which stores the length of the shortest known string. */
2100 if (integer_all_onesp (lendata
.maxlen
))
2101 lenrange
[0] = wi::shwi (0, prec
);
2103 lenrange
[0] = wi::to_wide (lendata
.minlen
, prec
);
2104 lenrange
[1] = wi::to_wide (lendata
.maxbound
, prec
);
2108 lenrange
[0] = wi::shwi (0, prec
);
2109 lenrange
[1] = wi::shwi (-1, prec
);
2113 location_t callloc
= gimple_nonartificial_location (stmt
);
2114 callloc
= expansion_point_location_if_in_system_header (callloc
);
2116 tree func
= gimple_call_fndecl (stmt
);
2118 if (lenrange
[0] != 0 || !wi::neg_p (lenrange
[1]))
2120 /* If the longest source string is shorter than the lower bound
2121 of the specified count the copy is definitely nul-terminated. */
2122 if (wi::ltu_p (lenrange
[1], cntrange
[0]))
2125 if (wi::neg_p (lenrange
[1]))
2127 /* The length of one of the strings is unknown but at least
2128 one has non-zero length and that length is stored in
2129 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2131 lenrange
[1] = lenrange
[0];
2132 lenrange
[0] = wi::shwi (0, prec
);
2135 /* Set to true for strncat whose bound is derived from the length
2136 of the destination (the expected usage pattern). */
2137 bool cat_dstlen_bounded
= false;
2138 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STRNCAT
)
2139 cat_dstlen_bounded
= is_strlen_related_p (dst
, cnt
);
2141 if (lenrange
[0] == cntrange
[1] && cntrange
[0] == cntrange
[1])
2142 return warning_n (callloc
, OPT_Wstringop_truncation
,
2143 cntrange
[0].to_uhwi (),
2144 "%G%qD output truncated before terminating "
2145 "nul copying %E byte from a string of the "
2147 "%G%qD output truncated before terminating nul "
2148 "copying %E bytes from a string of the same "
2151 else if (!cat_dstlen_bounded
)
2153 if (wi::geu_p (lenrange
[0], cntrange
[1]))
2155 /* The shortest string is longer than the upper bound of
2156 the count so the truncation is certain. */
2157 if (cntrange
[0] == cntrange
[1])
2158 return warning_n (callloc
, OPT_Wstringop_truncation
,
2159 cntrange
[0].to_uhwi (),
2160 "%G%qD output truncated copying %E byte "
2161 "from a string of length %wu",
2162 "%G%qD output truncated copying %E bytes "
2163 "from a string of length %wu",
2164 stmt
, func
, cnt
, lenrange
[0].to_uhwi ());
2166 return warning_at (callloc
, OPT_Wstringop_truncation
,
2167 "%G%qD output truncated copying between %wu "
2168 "and %wu bytes from a string of length %wu",
2169 stmt
, func
, cntrange
[0].to_uhwi (),
2170 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
2172 else if (wi::geu_p (lenrange
[1], cntrange
[1]))
2174 /* The longest string is longer than the upper bound of
2175 the count so the truncation is possible. */
2176 if (cntrange
[0] == cntrange
[1])
2177 return warning_n (callloc
, OPT_Wstringop_truncation
,
2178 cntrange
[0].to_uhwi (),
2179 "%G%qD output may be truncated copying %E "
2180 "byte from a string of length %wu",
2181 "%G%qD output may be truncated copying %E "
2182 "bytes from a string of length %wu",
2183 stmt
, func
, cnt
, lenrange
[1].to_uhwi ());
2185 return warning_at (callloc
, OPT_Wstringop_truncation
,
2186 "%G%qD output may be truncated copying between "
2187 "%wu and %wu bytes from a string of length %wu",
2188 stmt
, func
, cntrange
[0].to_uhwi (),
2189 cntrange
[1].to_uhwi (), lenrange
[1].to_uhwi ());
2193 if (!cat_dstlen_bounded
2194 && cntrange
[0] != cntrange
[1]
2195 && wi::leu_p (cntrange
[0], lenrange
[0])
2196 && wi::leu_p (cntrange
[1], lenrange
[0] + 1))
2198 /* If the source (including the terminating nul) is longer than
2199 the lower bound of the specified count but shorter than the
2200 upper bound the copy may (but need not) be truncated. */
2201 return warning_at (callloc
, OPT_Wstringop_truncation
,
2202 "%G%qD output may be truncated copying between "
2203 "%wu and %wu bytes from a string of length %wu",
2204 stmt
, func
, cntrange
[0].to_uhwi (),
2205 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
2209 if (tree dstsize
= compute_objsize (dst
, 1))
2211 /* The source length is uknown. Try to determine the destination
2212 size and see if it matches the specified bound. If not, bail.
2213 Otherwise go on to see if it should be diagnosed for possible
2218 if (wi::to_wide (dstsize
) != cntrange
[1])
2221 /* Avoid warning for strncpy(a, b, N) calls where the following
2223 N == sizeof a && N == sizeof b */
2224 if (tree srcsize
= compute_objsize (src
, 1))
2225 if (wi::to_wide (srcsize
) == cntrange
[1])
2228 if (cntrange
[0] == cntrange
[1])
2229 return warning_at (callloc
, OPT_Wstringop_truncation
,
2230 "%G%qD specified bound %E equals destination size",
2237 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2238 out-of-bounds offsets or overlapping access, and to see if the size
2239 is derived from calling strlen() on the source argument, and if so,
2240 issue the appropriate warning. */
2243 handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*gsi
)
2245 if (!strlen_to_stridx
)
2248 gimple
*stmt
= gsi_stmt (*gsi
);
2250 tree dst
= gimple_call_arg (stmt
, 0);
2251 tree src
= gimple_call_arg (stmt
, 1);
2252 tree len
= gimple_call_arg (stmt
, 2);
2253 tree dstsize
= NULL_TREE
, srcsize
= NULL_TREE
;
2255 int didx
= get_stridx (dst
);
2256 if (strinfo
*sidst
= didx
> 0 ? get_strinfo (didx
) : NULL
)
2258 /* Compute the size of the destination string including the nul
2259 if it is known to be nul-terminated. */
2260 if (sidst
->nonzero_chars
)
2262 if (sidst
->full_string_p
)
2264 /* String is known to be nul-terminated. */
2265 tree type
= TREE_TYPE (sidst
->nonzero_chars
);
2266 dstsize
= fold_build2 (PLUS_EXPR
, type
, sidst
->nonzero_chars
,
2267 build_int_cst (type
, 1));
2270 dstsize
= sidst
->nonzero_chars
;
2276 int sidx
= get_stridx (src
);
2277 strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
;
2280 /* strncat() and strncpy() can modify the source string by writing
2281 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2284 /* Compute the size of the source string including the terminating
2285 nul if its known to be nul-terminated. */
2286 if (sisrc
->nonzero_chars
)
2288 if (sisrc
->full_string_p
)
2290 tree type
= TREE_TYPE (sisrc
->nonzero_chars
);
2291 srcsize
= fold_build2 (PLUS_EXPR
, type
, sisrc
->nonzero_chars
,
2292 build_int_cst (type
, 1));
2295 srcsize
= sisrc
->nonzero_chars
;
2301 srcsize
= NULL_TREE
;
2303 if (check_bounds_or_overlap (stmt
, dst
, src
, dstsize
, srcsize
))
2305 gimple_set_no_warning (stmt
, true);
2309 /* If the length argument was computed from strlen(S) for some string
2310 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2311 the location of the strlen() call (PSS->SECOND). */
2312 stridx_strlenloc
*pss
= strlen_to_stridx
->get (len
);
2313 if (!pss
|| pss
->first
<= 0)
2315 if (maybe_diag_stxncpy_trunc (*gsi
, src
, len
))
2316 gimple_set_no_warning (stmt
, true);
2321 /* Retrieve the strinfo data for the string S that LEN was computed
2322 from as some function F of strlen (S) (i.e., LEN need not be equal
2324 strinfo
*silen
= get_strinfo (pss
->first
);
2326 location_t callloc
= gimple_nonartificial_location (stmt
);
2327 callloc
= expansion_point_location_if_in_system_header (callloc
);
2329 tree func
= gimple_call_fndecl (stmt
);
2331 bool warned
= false;
2333 /* When -Wstringop-truncation is set, try to determine truncation
2334 before diagnosing possible overflow. Truncation is implied by
2335 the LEN argument being equal to strlen(SRC), regardless of
2336 whether its value is known. Otherwise, issue the more generic
2337 -Wstringop-overflow which triggers for LEN arguments that in
2338 any meaningful way depend on strlen(SRC). */
2340 && is_strlen_related_p (src
, len
)
2341 && warning_at (callloc
, OPT_Wstringop_truncation
,
2342 "%G%qD output truncated before terminating nul "
2343 "copying as many bytes from a string as its length",
2346 else if (silen
&& is_strlen_related_p (src
, silen
->ptr
))
2347 warned
= warning_at (callloc
, OPT_Wstringop_overflow_
,
2348 "%G%qD specified bound depends on the length "
2349 "of the source argument",
2353 location_t strlenloc
= pss
->second
;
2354 if (strlenloc
!= UNKNOWN_LOCATION
&& strlenloc
!= callloc
)
2355 inform (strlenloc
, "length computed here");
2359 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2360 If strlen of the second argument is known and length of the third argument
2361 is that plus one, strlen of the first argument is the same after this
2365 handle_builtin_memcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2368 tree src
, dst
, len
, lhs
, oldlen
, newlen
;
2369 gimple
*stmt
= gsi_stmt (*gsi
);
2370 strinfo
*si
, *dsi
, *olddsi
;
2372 len
= gimple_call_arg (stmt
, 2);
2373 src
= gimple_call_arg (stmt
, 1);
2374 dst
= gimple_call_arg (stmt
, 0);
2375 idx
= get_stridx (src
);
2379 didx
= get_stridx (dst
);
2382 olddsi
= get_strinfo (didx
);
2387 && tree_fits_uhwi_p (len
)
2388 && !integer_zerop (len
))
2389 adjust_last_stmt (olddsi
, stmt
, false);
2396 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2398 si
= get_strinfo (idx
);
2399 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2401 if (TREE_CODE (len
) == INTEGER_CST
2402 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
2404 if (tree_int_cst_le (len
, si
->nonzero_chars
))
2406 /* Copying LEN nonzero characters, where LEN is constant. */
2408 full_string_p
= false;
2412 /* Copying the whole of the analyzed part of SI. */
2413 newlen
= si
->nonzero_chars
;
2414 full_string_p
= si
->full_string_p
;
2419 if (!si
->full_string_p
)
2421 if (TREE_CODE (len
) != SSA_NAME
)
2423 def_stmt
= SSA_NAME_DEF_STMT (len
);
2424 if (!is_gimple_assign (def_stmt
)
2425 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
2426 || gimple_assign_rhs1 (def_stmt
) != si
->nonzero_chars
2427 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
2429 /* Copying variable-length string SI (and no more). */
2430 newlen
= si
->nonzero_chars
;
2431 full_string_p
= true;
2437 /* Handle memcpy (x, "abcd", 5) or
2438 memcpy (x, "abc\0uvw", 7). */
2439 if (!tree_fits_uhwi_p (len
))
2442 unsigned HOST_WIDE_INT clen
= tree_to_uhwi (len
);
2443 unsigned HOST_WIDE_INT nonzero_chars
= ~idx
;
2444 newlen
= build_int_cst (size_type_node
, MIN (nonzero_chars
, clen
));
2445 full_string_p
= clen
> nonzero_chars
;
2450 && olddsi
->nonzero_chars
2451 && TREE_CODE (olddsi
->nonzero_chars
) == INTEGER_CST
2452 && tree_int_cst_le (newlen
, olddsi
->nonzero_chars
))
2454 /* The SRC substring being written strictly overlaps
2455 a subsequence of the existing string OLDDSI. */
2456 newlen
= olddsi
->nonzero_chars
;
2457 full_string_p
= olddsi
->full_string_p
;
2460 if (olddsi
!= NULL
&& TREE_CODE (len
) == SSA_NAME
)
2461 adjust_last_stmt (olddsi
, stmt
, false);
2465 didx
= new_stridx (dst
);
2472 dsi
= unshare_strinfo (olddsi
);
2473 oldlen
= olddsi
->nonzero_chars
;
2474 dsi
->nonzero_chars
= newlen
;
2475 dsi
->full_string_p
= full_string_p
;
2476 /* Break the chain, so adjust_related_strinfo on later pointers in
2477 the chain won't adjust this one anymore. */
2480 dsi
->endptr
= NULL_TREE
;
2484 dsi
= new_strinfo (dst
, didx
, newlen
, full_string_p
);
2485 set_strinfo (didx
, dsi
);
2486 find_equal_ptrs (dst
, didx
);
2488 dsi
->writable
= true;
2489 dsi
->dont_invalidate
= true;
2492 tree adj
= NULL_TREE
;
2493 location_t loc
= gimple_location (stmt
);
2494 if (oldlen
== NULL_TREE
)
2496 else if (integer_zerop (oldlen
))
2498 else if (TREE_CODE (oldlen
) == INTEGER_CST
2499 || TREE_CODE (newlen
) == INTEGER_CST
)
2500 adj
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (newlen
), newlen
,
2501 fold_convert_loc (loc
, TREE_TYPE (newlen
),
2503 if (adj
!= NULL_TREE
)
2504 adjust_related_strinfos (loc
, dsi
, adj
);
2508 /* memcpy src may not overlap dst, so src doesn't need to be
2509 invalidated either. */
2511 si
->dont_invalidate
= true;
2515 lhs
= gimple_call_lhs (stmt
);
2518 case BUILT_IN_MEMCPY
:
2519 case BUILT_IN_MEMCPY_CHK
:
2520 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2521 laststmt
.stmt
= stmt
;
2522 laststmt
.len
= dsi
->nonzero_chars
;
2523 laststmt
.stridx
= dsi
->idx
;
2525 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
2527 case BUILT_IN_MEMPCPY
:
2528 case BUILT_IN_MEMPCPY_CHK
:
2536 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2537 If strlen of the second argument is known, strlen of the first argument
2538 is increased by the length of the second argument. Furthermore, attempt
2539 to convert it to memcpy/strcpy if the length of the first argument
2543 handle_builtin_strcat (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2546 tree srclen
, args
, type
, fn
, objsz
, endptr
;
2548 gimple
*stmt
= gsi_stmt (*gsi
);
2550 location_t loc
= gimple_location (stmt
);
2552 tree src
= gimple_call_arg (stmt
, 1);
2553 tree dst
= gimple_call_arg (stmt
, 0);
2555 /* Bail if the source is the same as destination. It will be diagnosed
2557 if (operand_equal_p (src
, dst
, 0))
2560 tree lhs
= gimple_call_lhs (stmt
);
2562 didx
= get_stridx (dst
);
2568 dsi
= get_strinfo (didx
);
2572 idx
= get_stridx (src
);
2574 srclen
= build_int_cst (size_type_node
, ~idx
);
2577 si
= get_strinfo (idx
);
2579 srclen
= get_string_length (si
);
2582 /* Set the no-warning bit on the transformed statement? */
2583 bool set_no_warning
= false;
2585 if (dsi
== NULL
|| get_string_length (dsi
) == NULL_TREE
)
2588 /* The concatenation always involves copying at least one byte
2589 (the terminating nul), even if the source string is empty.
2590 If the source is unknown assume it's one character long and
2591 used that as both sizes. */
2595 tree type
= TREE_TYPE (slen
);
2596 slen
= fold_build2 (PLUS_EXPR
, type
, slen
, build_int_cst (type
, 1));
2599 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2601 if (check_bounds_or_overlap (stmt
, dst
, sptr
, NULL_TREE
, slen
))
2603 gimple_set_no_warning (stmt
, true);
2604 set_no_warning
= true;
2608 /* strcat (p, q) can be transformed into
2609 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2610 with length endptr - p if we need to compute the length
2611 later on. Don't do this transformation if we don't need
2613 if (builtin_decl_implicit_p (BUILT_IN_STPCPY
) && lhs
== NULL_TREE
)
2617 didx
= new_stridx (dst
);
2623 dsi
= new_strinfo (dst
, didx
, NULL_TREE
, false);
2624 set_strinfo (didx
, dsi
);
2625 find_equal_ptrs (dst
, didx
);
2629 dsi
= unshare_strinfo (dsi
);
2630 dsi
->nonzero_chars
= NULL_TREE
;
2631 dsi
->full_string_p
= false;
2633 dsi
->endptr
= NULL_TREE
;
2635 dsi
->writable
= true;
2637 dsi
->dont_invalidate
= true;
2642 tree dstlen
= dsi
->nonzero_chars
;
2643 endptr
= dsi
->endptr
;
2645 dsi
= unshare_strinfo (dsi
);
2646 dsi
->endptr
= NULL_TREE
;
2648 dsi
->writable
= true;
2650 if (srclen
!= NULL_TREE
)
2652 dsi
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
2653 TREE_TYPE (dsi
->nonzero_chars
),
2654 dsi
->nonzero_chars
, srclen
);
2655 gcc_assert (dsi
->full_string_p
);
2656 adjust_related_strinfos (loc
, dsi
, srclen
);
2657 dsi
->dont_invalidate
= true;
2661 dsi
->nonzero_chars
= NULL
;
2662 dsi
->full_string_p
= false;
2663 if (lhs
== NULL_TREE
&& builtin_decl_implicit_p (BUILT_IN_STPCPY
))
2664 dsi
->dont_invalidate
= true;
2668 /* strcat src may not overlap dst, so src doesn't need to be
2669 invalidated either. */
2670 si
->dont_invalidate
= true;
2672 /* For now. Could remove the lhs from the call and add
2673 lhs = dst; afterwards. */
2681 case BUILT_IN_STRCAT
:
2682 if (srclen
!= NULL_TREE
)
2683 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
2685 fn
= builtin_decl_implicit (BUILT_IN_STRCPY
);
2687 case BUILT_IN_STRCAT_CHK
:
2688 if (srclen
!= NULL_TREE
)
2689 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
2691 fn
= builtin_decl_explicit (BUILT_IN_STRCPY_CHK
);
2692 objsz
= gimple_call_arg (stmt
, 2);
2698 if (fn
== NULL_TREE
)
2703 tree type
= TREE_TYPE (dstlen
);
2705 /* Compute the size of the source sequence, including the nul. */
2706 tree srcsize
= srclen
? srclen
: size_zero_node
;
2707 srcsize
= fold_build2 (PLUS_EXPR
, type
, srcsize
, build_int_cst (type
, 1));
2709 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2711 if (check_bounds_or_overlap (stmt
, dst
, sptr
, dstlen
, srcsize
))
2713 gimple_set_no_warning (stmt
, true);
2714 set_no_warning
= true;
2718 tree len
= NULL_TREE
;
2719 if (srclen
!= NULL_TREE
)
2721 args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2722 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
2724 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
2725 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
,
2726 build_int_cst (type
, 1));
2727 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
2731 dst
= fold_convert_loc (loc
, TREE_TYPE (dst
), unshare_expr (endptr
));
2733 dst
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
, TREE_TYPE (dst
), dst
,
2734 fold_convert_loc (loc
, sizetype
,
2735 unshare_expr (dstlen
)));
2736 dst
= force_gimple_operand_gsi (gsi
, dst
, true, NULL_TREE
, true,
2740 objsz
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (objsz
), objsz
,
2741 fold_convert_loc (loc
, TREE_TYPE (objsz
),
2742 unshare_expr (dstlen
)));
2743 objsz
= force_gimple_operand_gsi (gsi
, objsz
, true, NULL_TREE
, true,
2746 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2748 fprintf (dump_file
, "Optimizing: ");
2749 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2751 if (srclen
!= NULL_TREE
)
2752 success
= update_gimple_call (gsi
, fn
, 3 + (objsz
!= NULL_TREE
),
2753 dst
, src
, len
, objsz
);
2755 success
= update_gimple_call (gsi
, fn
, 2 + (objsz
!= NULL_TREE
),
2759 stmt
= gsi_stmt (*gsi
);
2761 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2763 fprintf (dump_file
, "into: ");
2764 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2766 /* If srclen == NULL, note that current string length can be
2767 computed by transforming this strcpy into stpcpy. */
2768 if (srclen
== NULL_TREE
&& dsi
->dont_invalidate
)
2770 adjust_last_stmt (dsi
, stmt
, true);
2771 if (srclen
!= NULL_TREE
)
2773 laststmt
.stmt
= stmt
;
2774 laststmt
.len
= srclen
;
2775 laststmt
.stridx
= dsi
->idx
;
2778 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2779 fprintf (dump_file
, "not possible.\n");
2782 gimple_set_no_warning (stmt
, true);
2785 /* Handle a call to malloc or calloc. */
2788 handle_builtin_malloc (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2790 gimple
*stmt
= gsi_stmt (*gsi
);
2791 tree lhs
= gimple_call_lhs (stmt
);
2792 if (lhs
== NULL_TREE
)
2795 gcc_assert (get_stridx (lhs
) == 0);
2796 int idx
= new_stridx (lhs
);
2797 tree length
= NULL_TREE
;
2798 if (bcode
== BUILT_IN_CALLOC
)
2799 length
= build_int_cst (size_type_node
, 0);
2800 strinfo
*si
= new_strinfo (lhs
, idx
, length
, length
!= NULL_TREE
);
2801 if (bcode
== BUILT_IN_CALLOC
)
2803 set_strinfo (idx
, si
);
2804 si
->writable
= true;
2806 si
->dont_invalidate
= true;
2809 /* Handle a call to memset.
2810 After a call to calloc, memset(,0,) is unnecessary.
2811 memset(malloc(n),0,n) is calloc(n,1).
2812 return true when the call is transfomred, false otherwise. */
2815 handle_builtin_memset (gimple_stmt_iterator
*gsi
)
2817 gimple
*stmt2
= gsi_stmt (*gsi
);
2818 if (!integer_zerop (gimple_call_arg (stmt2
, 1)))
2820 tree ptr
= gimple_call_arg (stmt2
, 0);
2821 int idx1
= get_stridx (ptr
);
2824 strinfo
*si1
= get_strinfo (idx1
);
2827 gimple
*stmt1
= si1
->stmt
;
2828 if (!stmt1
|| !is_gimple_call (stmt1
))
2830 tree callee1
= gimple_call_fndecl (stmt1
);
2831 if (!valid_builtin_call (stmt1
))
2833 enum built_in_function code1
= DECL_FUNCTION_CODE (callee1
);
2834 tree size
= gimple_call_arg (stmt2
, 2);
2835 if (code1
== BUILT_IN_CALLOC
)
2836 /* Not touching stmt1 */ ;
2837 else if (code1
== BUILT_IN_MALLOC
2838 && operand_equal_p (gimple_call_arg (stmt1
, 0), size
, 0))
2840 gimple_stmt_iterator gsi1
= gsi_for_stmt (stmt1
);
2841 update_gimple_call (&gsi1
, builtin_decl_implicit (BUILT_IN_CALLOC
), 2,
2842 size
, build_one_cst (size_type_node
));
2843 si1
->nonzero_chars
= build_int_cst (size_type_node
, 0);
2844 si1
->full_string_p
= true;
2845 si1
->stmt
= gsi_stmt (gsi1
);
2849 tree lhs
= gimple_call_lhs (stmt2
);
2850 unlink_stmt_vdef (stmt2
);
2853 gimple
*assign
= gimple_build_assign (lhs
, ptr
);
2854 gsi_replace (gsi
, assign
, false);
2858 gsi_remove (gsi
, true);
2859 release_defs (stmt2
);
2865 /* Handle a call to memcmp. We try to handle small comparisons by
2866 converting them to load and compare, and replacing the call to memcmp
2867 with a __builtin_memcmp_eq call where possible.
2868 return true when call is transformed, return false otherwise. */
2871 handle_builtin_memcmp (gimple_stmt_iterator
*gsi
)
2873 gcall
*stmt2
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2874 tree res
= gimple_call_lhs (stmt2
);
2875 tree arg1
= gimple_call_arg (stmt2
, 0);
2876 tree arg2
= gimple_call_arg (stmt2
, 1);
2877 tree len
= gimple_call_arg (stmt2
, 2);
2878 unsigned HOST_WIDE_INT leni
;
2879 use_operand_p use_p
;
2880 imm_use_iterator iter
;
2885 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2887 gimple
*ustmt
= USE_STMT (use_p
);
2889 if (is_gimple_debug (ustmt
))
2891 if (gimple_code (ustmt
) == GIMPLE_ASSIGN
)
2893 gassign
*asgn
= as_a
<gassign
*> (ustmt
);
2894 tree_code code
= gimple_assign_rhs_code (asgn
);
2895 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2896 || !integer_zerop (gimple_assign_rhs2 (asgn
)))
2899 else if (gimple_code (ustmt
) == GIMPLE_COND
)
2901 tree_code code
= gimple_cond_code (ustmt
);
2902 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2903 || !integer_zerop (gimple_cond_rhs (ustmt
)))
2910 if (tree_fits_uhwi_p (len
)
2911 && (leni
= tree_to_uhwi (len
)) <= GET_MODE_SIZE (word_mode
)
2912 && pow2p_hwi (leni
))
2914 leni
*= CHAR_TYPE_SIZE
;
2915 unsigned align1
= get_pointer_alignment (arg1
);
2916 unsigned align2
= get_pointer_alignment (arg2
);
2917 unsigned align
= MIN (align1
, align2
);
2918 scalar_int_mode mode
;
2919 if (int_mode_for_size (leni
, 1).exists (&mode
)
2920 && (align
>= leni
|| !targetm
.slow_unaligned_access (mode
, align
)))
2922 location_t loc
= gimple_location (stmt2
);
2924 type
= build_nonstandard_integer_type (leni
, 1);
2925 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type
)), leni
));
2926 tree ptrtype
= build_pointer_type_for_mode (char_type_node
,
2928 off
= build_int_cst (ptrtype
, 0);
2929 arg1
= build2_loc (loc
, MEM_REF
, type
, arg1
, off
);
2930 arg2
= build2_loc (loc
, MEM_REF
, type
, arg2
, off
);
2931 tree tem1
= fold_const_aggregate_ref (arg1
);
2934 tree tem2
= fold_const_aggregate_ref (arg2
);
2937 res
= fold_convert_loc (loc
, TREE_TYPE (res
),
2938 fold_build2_loc (loc
, NE_EXPR
,
2941 gimplify_and_update_call_from_tree (gsi
, res
);
2946 gimple_call_set_fndecl (stmt2
, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ
));
2950 /* If IDX1 and IDX2 refer to strings A and B of unequal lengths, return
2951 the result of 0 == strncmp (A, B, N) (which is the same as strcmp for
2952 sufficiently large N). Otherwise return false. */
2955 strxcmp_unequal (int idx1
, int idx2
, unsigned HOST_WIDE_INT n
)
2957 unsigned HOST_WIDE_INT len1
;
2958 unsigned HOST_WIDE_INT len2
;
2968 else if (strinfo
*si
= get_strinfo (idx1
))
2970 if (tree_fits_uhwi_p (si
->nonzero_chars
))
2972 len1
= tree_to_uhwi (si
->nonzero_chars
);
2973 nulterm1
= si
->full_string_p
;
2986 else if (strinfo
*si
= get_strinfo (idx2
))
2988 if (tree_fits_uhwi_p (si
->nonzero_chars
))
2990 len2
= tree_to_uhwi (si
->nonzero_chars
);
2991 nulterm2
= si
->full_string_p
;
2999 /* N is set to UHWI_MAX for strcmp and less to strncmp. Adjust
3000 the length of each string to consider to be no more than N. */
3006 if ((len1
< len2
&& nulterm1
)
3007 || (len2
< len1
&& nulterm2
))
3008 /* The string lengths are definitely unequal and the result can
3009 be folded to one (since it's used for comparison with zero). */
3012 /* The string lengths may be equal or unequal. Even when equal and
3013 both strings nul-terminated, without the string contents there's
3014 no way to determine whether they are equal. */
3018 /* Given an index to the strinfo vector, compute the string length
3019 for the corresponding string. Return -1 when unknown. */
3021 static HOST_WIDE_INT
3022 compute_string_length (int idx
)
3024 HOST_WIDE_INT string_leni
= -1;
3025 gcc_assert (idx
!= 0);
3030 strinfo
*si
= get_strinfo (idx
);
3033 tree const_string_len
= get_string_length (si
);
3034 if (const_string_len
&& tree_fits_shwi_p (const_string_len
))
3035 string_leni
= tree_to_shwi (const_string_len
);
3038 if (string_leni
< 0)
3044 /* Determine the minimum size of the object referenced by DEST expression
3045 which must have a pointer type.
3046 Return the minimum size of the object if successful or NULL when the size
3047 cannot be determined. */
3049 determine_min_objsize (tree dest
)
3051 unsigned HOST_WIDE_INT size
= 0;
3053 if (compute_builtin_object_size (dest
, 2, &size
))
3054 return build_int_cst (sizetype
, size
);
3056 /* Try to determine the size of the object through the RHS
3057 of the assign statement. */
3058 if (TREE_CODE (dest
) == SSA_NAME
)
3060 gimple
*stmt
= SSA_NAME_DEF_STMT (dest
);
3061 if (!is_gimple_assign (stmt
))
3064 if (!gimple_assign_single_p (stmt
)
3065 && !gimple_assign_unary_nop_p (stmt
))
3068 dest
= gimple_assign_rhs1 (stmt
);
3069 return determine_min_objsize (dest
);
3072 /* Try to determine the size of the object from its type. */
3073 if (TREE_CODE (dest
) != ADDR_EXPR
)
3076 tree type
= TREE_TYPE (dest
);
3077 if (TREE_CODE (type
) == POINTER_TYPE
)
3078 type
= TREE_TYPE (type
);
3080 type
= TYPE_MAIN_VARIANT (type
);
3082 /* We cannot determine the size of the array if it's a flexible array,
3083 which is declared at the end of a structure. */
3084 if (TREE_CODE (type
) == ARRAY_TYPE
3085 && !array_at_struct_end_p (dest
))
3087 tree
size_t = TYPE_SIZE_UNIT (type
);
3088 if (size_t && TREE_CODE (size_t) == INTEGER_CST
3089 && !integer_zerop (size_t))
3096 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
3097 equality test against zero:
3099 A. When the lengths of both arguments are constant and it's a strcmp:
3100 * if the lengths are NOT equal, we can safely fold the call
3101 to a non-zero value.
3102 * otherwise, do nothing now.
3104 B. When the length of one argument is constant, try to replace the call
3105 with a __builtin_str(n)cmp_eq call where possible, i.e:
3107 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR
3108 is a string with constant length , C is a constant.
3109 if (C <= strlen(STR) && sizeof_array(s) > C)
3111 replace this call with
3112 strncmp_eq (s, STR, C) (!)= 0
3116 it can be safely treated as a call to strcmp (s, STR) (!)= 0
3117 can handled by the following strcmp.
3120 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR
3121 is a string with constant length.
3122 if (sizeof_array(s) > strlen(STR))
3124 replace this call with
3125 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
3128 Return true when the call is transformed, return false otherwise.
3132 handle_builtin_string_cmp (gimple_stmt_iterator
*gsi
)
3134 gcall
*stmt
= as_a
<gcall
*> (gsi_stmt (*gsi
));
3135 tree res
= gimple_call_lhs (stmt
);
3136 use_operand_p use_p
;
3137 imm_use_iterator iter
;
3138 tree arg1
= gimple_call_arg (stmt
, 0);
3139 tree arg2
= gimple_call_arg (stmt
, 1);
3140 int idx1
= get_stridx (arg1
);
3141 int idx2
= get_stridx (arg2
);
3142 HOST_WIDE_INT length
= -1;
3143 bool is_ncmp
= false;
3148 /* When both arguments are unknown, do nothing. */
3149 if (idx1
== 0 && idx2
== 0)
3152 /* Handle strncmp function. */
3153 if (gimple_call_num_args (stmt
) == 3)
3155 tree len
= gimple_call_arg (stmt
, 2);
3156 if (tree_fits_shwi_p (len
))
3157 length
= tree_to_shwi (len
);
3162 /* For strncmp, if the length argument is NOT known, do nothing. */
3163 if (is_ncmp
&& length
< 0)
3166 /* When the result is ONLY used to do equality test against zero. */
3167 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
3169 gimple
*use_stmt
= USE_STMT (use_p
);
3171 if (is_gimple_debug (use_stmt
))
3173 if (gimple_code (use_stmt
) == GIMPLE_ASSIGN
)
3175 tree_code code
= gimple_assign_rhs_code (use_stmt
);
3176 if (code
== COND_EXPR
)
3178 tree cond_expr
= gimple_assign_rhs1 (use_stmt
);
3179 if ((TREE_CODE (cond_expr
) != EQ_EXPR
3180 && (TREE_CODE (cond_expr
) != NE_EXPR
))
3181 || !integer_zerop (TREE_OPERAND (cond_expr
, 1)))
3184 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3186 if (!integer_zerop (gimple_assign_rhs2 (use_stmt
)))
3192 else if (gimple_code (use_stmt
) == GIMPLE_COND
)
3194 tree_code code
= gimple_cond_code (use_stmt
);
3195 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
3196 || !integer_zerop (gimple_cond_rhs (use_stmt
)))
3203 /* When the lengths of the arguments are known to be unequal
3204 we can safely fold the call to a non-zero value for strcmp;
3205 otherwise, do nothing now. */
3206 if (idx1
!= 0 && idx2
!= 0)
3208 if (strxcmp_unequal (idx1
, idx2
, length
))
3210 replace_call_with_value (gsi
, integer_one_node
);
3216 /* When the length of one argument is constant. */
3217 tree var_string
= NULL_TREE
;
3218 HOST_WIDE_INT const_string_leni
= -1;
3222 const_string_leni
= compute_string_length (idx1
);
3227 gcc_checking_assert (idx2
);
3228 const_string_leni
= compute_string_length (idx2
);
3232 if (const_string_leni
< 0)
3235 unsigned HOST_WIDE_INT var_sizei
= 0;
3236 /* try to determine the minimum size of the object pointed by var_string. */
3237 tree size
= determine_min_objsize (var_string
);
3242 if (tree_fits_uhwi_p (size
))
3243 var_sizei
= tree_to_uhwi (size
);
3248 /* For strncmp, if length > const_string_leni , this call can be safely
3249 transformed to a strcmp. */
3250 if (is_ncmp
&& length
> const_string_leni
)
3253 unsigned HOST_WIDE_INT final_length
3254 = is_ncmp
? length
: const_string_leni
+ 1;
3256 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
3257 if (var_sizei
> final_length
)
3261 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ
)
3262 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ
));
3265 tree const_string_len
= build_int_cst (size_type_node
, final_length
);
3266 update_gimple_call (gsi
, fn
, 3, arg1
, arg2
, const_string_len
);
3274 /* Handle a POINTER_PLUS_EXPR statement.
3275 For p = "abcd" + 2; compute associated length, or if
3276 p = q + off is pointing to a '\0' character of a string, call
3277 zero_length_string on it. */
3280 handle_pointer_plus (gimple_stmt_iterator
*gsi
)
3282 gimple
*stmt
= gsi_stmt (*gsi
);
3283 tree lhs
= gimple_assign_lhs (stmt
), off
;
3284 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3292 tree off
= gimple_assign_rhs2 (stmt
);
3293 if (tree_fits_uhwi_p (off
)
3294 && tree_to_uhwi (off
) <= (unsigned HOST_WIDE_INT
) ~idx
)
3295 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)]
3296 = ~(~idx
- (int) tree_to_uhwi (off
));
3300 si
= get_strinfo (idx
);
3301 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
3304 off
= gimple_assign_rhs2 (stmt
);
3306 if (si
->full_string_p
&& operand_equal_p (si
->nonzero_chars
, off
, 0))
3307 zsi
= zero_length_string (lhs
, si
);
3308 else if (TREE_CODE (off
) == SSA_NAME
)
3310 gimple
*def_stmt
= SSA_NAME_DEF_STMT (off
);
3311 if (gimple_assign_single_p (def_stmt
)
3312 && si
->full_string_p
3313 && operand_equal_p (si
->nonzero_chars
,
3314 gimple_assign_rhs1 (def_stmt
), 0))
3315 zsi
= zero_length_string (lhs
, si
);
3318 && si
->endptr
!= NULL_TREE
3319 && si
->endptr
!= lhs
3320 && TREE_CODE (si
->endptr
) == SSA_NAME
)
3322 enum tree_code rhs_code
3323 = useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (si
->endptr
))
3324 ? SSA_NAME
: NOP_EXPR
;
3325 gimple_assign_set_rhs_with_ops (gsi
, rhs_code
, si
->endptr
);
3326 gcc_assert (gsi_stmt (*gsi
) == stmt
);
3331 /* If RHS, either directly or indirectly, refers to a string of constant
3332 length, return the length. Otherwise, if it refers to a character
3333 constant, return 1 if the constant is non-zero and 0 if it is nul.
3334 Otherwise, return a negative value. */
3336 static HOST_WIDE_INT
3337 get_min_string_length (tree rhs
, bool *full_string_p
)
3339 if (INTEGRAL_TYPE_P (TREE_TYPE (rhs
)))
3341 if (tree_expr_nonzero_p (rhs
))
3343 *full_string_p
= false;
3347 *full_string_p
= true;
3351 if (TREE_CODE (rhs
) == MEM_REF
3352 && integer_zerop (TREE_OPERAND (rhs
, 1)))
3354 rhs
= TREE_OPERAND (rhs
, 0);
3355 if (TREE_CODE (rhs
) == ADDR_EXPR
)
3357 tree rhs_addr
= rhs
;
3359 rhs
= TREE_OPERAND (rhs
, 0);
3360 if (TREE_CODE (rhs
) != STRING_CST
)
3362 int idx
= get_stridx (rhs_addr
);
3365 strinfo
*si
= get_strinfo (idx
);
3367 && tree_fits_shwi_p (si
->nonzero_chars
))
3369 *full_string_p
= si
->full_string_p
;
3370 return tree_to_shwi (si
->nonzero_chars
);
3377 if (TREE_CODE (rhs
) == VAR_DECL
3378 && TREE_READONLY (rhs
))
3379 rhs
= DECL_INITIAL (rhs
);
3381 if (rhs
&& TREE_CODE (rhs
) == STRING_CST
)
3383 HOST_WIDE_INT len
= strlen (TREE_STRING_POINTER (rhs
));
3384 *full_string_p
= len
< TREE_STRING_LENGTH (rhs
);
3391 /* Handle a single or multiple character store either by single
3392 character assignment or by multi-character assignment from
3396 handle_char_store (gimple_stmt_iterator
*gsi
)
3400 gimple
*stmt
= gsi_stmt (*gsi
);
3401 tree ssaname
= NULL_TREE
, lhs
= gimple_assign_lhs (stmt
);
3402 tree rhs
= gimple_assign_rhs1 (stmt
);
3403 unsigned HOST_WIDE_INT offset
= 0;
3405 if (TREE_CODE (lhs
) == MEM_REF
3406 && TREE_CODE (TREE_OPERAND (lhs
, 0)) == SSA_NAME
)
3408 tree mem_offset
= TREE_OPERAND (lhs
, 1);
3409 if (tree_fits_uhwi_p (mem_offset
))
3411 /* Get the strinfo for the base, and use it if it starts with at
3412 least OFFSET nonzero characters. This is trivially true if
3414 offset
= tree_to_uhwi (mem_offset
);
3415 idx
= get_stridx (TREE_OPERAND (lhs
, 0));
3417 si
= get_strinfo (idx
);
3419 ssaname
= TREE_OPERAND (lhs
, 0);
3420 else if (si
== NULL
|| compare_nonzero_chars (si
, offset
) < 0)
3426 idx
= get_addr_stridx (lhs
, NULL_TREE
, &offset
);
3428 si
= get_strinfo (idx
);
3431 /* STORING_NONZERO_P is true iff not all stored characters are zero.
3432 STORING_ALL_ZEROS_P is true iff all stored characters are zero.
3433 Both are false when it's impossible to determine which is true. */
3434 bool storing_nonzero_p
;
3435 bool storing_all_zeros_p
= initializer_zerop (rhs
, &storing_nonzero_p
);
3436 if (!storing_nonzero_p
)
3437 storing_nonzero_p
= tree_expr_nonzero_p (rhs
);
3438 bool full_string_p
= storing_all_zeros_p
;
3440 /* Set to the length of the string being assigned if known. */
3441 HOST_WIDE_INT rhslen
;
3445 int cmp
= compare_nonzero_chars (si
, offset
);
3446 gcc_assert (offset
== 0 || cmp
>= 0);
3447 if (storing_all_zeros_p
&& cmp
== 0 && si
->full_string_p
)
3449 /* When overwriting a '\0' with a '\0', the store can be removed
3450 if we know it has been stored in the current function. */
3451 if (!stmt_could_throw_p (cfun
, stmt
) && si
->writable
)
3453 unlink_stmt_vdef (stmt
);
3454 release_defs (stmt
);
3455 gsi_remove (gsi
, true);
3460 si
->writable
= true;
3465 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3466 and if we aren't storing '\0', we know that the length of the
3467 string and any other zero terminated string in memory remains
3468 the same. In that case we move to the next gimple statement and
3469 return to signal the caller that it shouldn't invalidate anything.
3471 This is benefical for cases like:
3476 strcpy (p, "foobar");
3477 size_t len = strlen (p); // This can be optimized into 6
3478 size_t len2 = strlen (q); // This has to be computed
3480 size_t len3 = strlen (p); // This can be optimized into 6
3481 size_t len4 = strlen (q); // This can be optimized into len2
3482 bar (len, len2, len3, len4);
3485 else if (storing_nonzero_p
&& cmp
> 0)
3490 else if (storing_all_zeros_p
3491 || storing_nonzero_p
3492 || (offset
!= 0 && cmp
> 0))
3494 /* When STORING_NONZERO_P, we know that the string will start
3495 with at least OFFSET + 1 nonzero characters. If storing
3496 a single character, set si->NONZERO_CHARS to the result.
3497 If storing multiple characters, try to determine the number
3498 of leading non-zero characters and set si->NONZERO_CHARS to
3501 When STORING_ALL_ZEROS_P, we know that the string is now
3502 OFFSET characters long.
3504 Otherwise, we're storing an unknown value at offset OFFSET,
3505 so need to clip the nonzero_chars to OFFSET. */
3506 bool full_string_p
= storing_all_zeros_p
;
3507 HOST_WIDE_INT len
= 1;
3508 if (storing_nonzero_p
)
3510 /* Try to get the minimum length of the string (or
3511 individual character) being stored. If it fails,
3512 STORING_NONZERO_P guarantees it's at least 1. */
3513 len
= get_min_string_length (rhs
, &full_string_p
);
3518 location_t loc
= gimple_location (stmt
);
3519 tree oldlen
= si
->nonzero_chars
;
3520 if (cmp
== 0 && si
->full_string_p
)
3521 /* We're overwriting the nul terminator with a nonzero or
3522 unknown character. If the previous stmt was a memcpy,
3523 its length may be decreased. */
3524 adjust_last_stmt (si
, stmt
, false);
3525 si
= unshare_strinfo (si
);
3526 if (storing_nonzero_p
)
3528 gcc_assert (len
>= 0);
3529 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
+ len
);
3532 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
);
3533 si
->full_string_p
= full_string_p
;
3534 if (storing_all_zeros_p
3536 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3537 si
->endptr
= ssaname
;
3542 si
->writable
= true;
3543 si
->dont_invalidate
= true;
3546 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
3547 si
->nonzero_chars
, oldlen
);
3548 adjust_related_strinfos (loc
, si
, adj
);
3554 else if (idx
== 0 && (storing_all_zeros_p
|| storing_nonzero_p
))
3557 idx
= new_stridx (ssaname
);
3559 idx
= new_addr_stridx (lhs
);
3562 tree ptr
= (ssaname
? ssaname
: build_fold_addr_expr (lhs
));
3563 HOST_WIDE_INT slen
= (storing_all_zeros_p
3565 : (storing_nonzero_p
3566 ? get_min_string_length (rhs
, &full_string_p
)
3568 tree len
= (slen
<= 0
3570 : build_int_cst (size_type_node
, slen
));
3571 si
= new_strinfo (ptr
, idx
, len
, slen
>= 0 && full_string_p
);
3572 set_strinfo (idx
, si
);
3573 if (storing_all_zeros_p
3575 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3576 si
->endptr
= ssaname
;
3577 si
->dont_invalidate
= true;
3578 si
->writable
= true;
3582 && (rhslen
= get_min_string_length (rhs
, &full_string_p
)) >= 0
3583 && ssaname
== NULL_TREE
3584 && TREE_CODE (TREE_TYPE (lhs
)) == ARRAY_TYPE
)
3586 HOST_WIDE_INT a
= int_size_in_bytes (TREE_TYPE (lhs
));
3587 if (a
> 0 && (unsigned HOST_WIDE_INT
) a
> (unsigned HOST_WIDE_INT
) rhslen
)
3589 int idx
= new_addr_stridx (lhs
);
3592 si
= new_strinfo (build_fold_addr_expr (lhs
), idx
,
3593 build_int_cst (size_type_node
, rhslen
),
3595 set_strinfo (idx
, si
);
3596 si
->dont_invalidate
= true;
3601 if (si
!= NULL
&& offset
== 0 && storing_all_zeros_p
)
3603 /* Allow adjust_last_stmt to remove it if the stored '\0'
3604 is immediately overwritten. */
3605 laststmt
.stmt
= stmt
;
3606 laststmt
.len
= build_int_cst (size_type_node
, 1);
3607 laststmt
.stridx
= si
->idx
;
3612 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3615 fold_strstr_to_strncmp (tree rhs1
, tree rhs2
, gimple
*stmt
)
3617 if (TREE_CODE (rhs1
) != SSA_NAME
3618 || TREE_CODE (rhs2
) != SSA_NAME
)
3621 gimple
*call_stmt
= NULL
;
3622 for (int pass
= 0; pass
< 2; pass
++)
3624 gimple
*g
= SSA_NAME_DEF_STMT (rhs1
);
3625 if (gimple_call_builtin_p (g
, BUILT_IN_STRSTR
)
3626 && has_single_use (rhs1
)
3627 && gimple_call_arg (g
, 0) == rhs2
)
3632 std::swap (rhs1
, rhs2
);
3637 tree arg0
= gimple_call_arg (call_stmt
, 0);
3641 tree arg1
= gimple_call_arg (call_stmt
, 1);
3642 tree arg1_len
= NULL_TREE
;
3643 int idx
= get_stridx (arg1
);
3648 arg1_len
= build_int_cst (size_type_node
, ~idx
);
3651 strinfo
*si
= get_strinfo (idx
);
3653 arg1_len
= get_string_length (si
);
3657 if (arg1_len
!= NULL_TREE
)
3659 gimple_stmt_iterator gsi
= gsi_for_stmt (call_stmt
);
3660 tree strncmp_decl
= builtin_decl_explicit (BUILT_IN_STRNCMP
);
3662 if (!is_gimple_val (arg1_len
))
3664 tree arg1_len_tmp
= make_ssa_name (TREE_TYPE (arg1_len
));
3665 gassign
*arg1_stmt
= gimple_build_assign (arg1_len_tmp
,
3667 gsi_insert_before (&gsi
, arg1_stmt
, GSI_SAME_STMT
);
3668 arg1_len
= arg1_len_tmp
;
3671 gcall
*strncmp_call
= gimple_build_call (strncmp_decl
, 3,
3672 arg0
, arg1
, arg1_len
);
3673 tree strncmp_lhs
= make_ssa_name (integer_type_node
);
3674 gimple_set_vuse (strncmp_call
, gimple_vuse (call_stmt
));
3675 gimple_call_set_lhs (strncmp_call
, strncmp_lhs
);
3676 gsi_remove (&gsi
, true);
3677 gsi_insert_before (&gsi
, strncmp_call
, GSI_SAME_STMT
);
3678 tree zero
= build_zero_cst (TREE_TYPE (strncmp_lhs
));
3680 if (is_gimple_assign (stmt
))
3682 if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
3684 tree cond
= gimple_assign_rhs1 (stmt
);
3685 TREE_OPERAND (cond
, 0) = strncmp_lhs
;
3686 TREE_OPERAND (cond
, 1) = zero
;
3690 gimple_assign_set_rhs1 (stmt
, strncmp_lhs
);
3691 gimple_assign_set_rhs2 (stmt
, zero
);
3696 gcond
*cond
= as_a
<gcond
*> (stmt
);
3697 gimple_cond_set_lhs (cond
, strncmp_lhs
);
3698 gimple_cond_set_rhs (cond
, zero
);
3706 /* Attempt to check for validity of the performed access a single statement
3707 at *GSI using string length knowledge, and to optimize it.
3708 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3712 strlen_check_and_optimize_stmt (gimple_stmt_iterator
*gsi
, bool *cleanup_eh
)
3714 gimple
*stmt
= gsi_stmt (*gsi
);
3716 if (is_gimple_call (stmt
))
3718 tree callee
= gimple_call_fndecl (stmt
);
3719 if (valid_builtin_call (stmt
))
3720 switch (DECL_FUNCTION_CODE (callee
))
3722 case BUILT_IN_STRLEN
:
3723 case BUILT_IN_STRNLEN
:
3724 handle_builtin_strlen (gsi
);
3726 case BUILT_IN_STRCHR
:
3727 handle_builtin_strchr (gsi
);
3729 case BUILT_IN_STRCPY
:
3730 case BUILT_IN_STRCPY_CHK
:
3731 case BUILT_IN_STPCPY
:
3732 case BUILT_IN_STPCPY_CHK
:
3733 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3736 case BUILT_IN_STRNCAT
:
3737 case BUILT_IN_STRNCAT_CHK
:
3738 handle_builtin_strncat (DECL_FUNCTION_CODE (callee
), gsi
);
3741 case BUILT_IN_STPNCPY
:
3742 case BUILT_IN_STPNCPY_CHK
:
3743 case BUILT_IN_STRNCPY
:
3744 case BUILT_IN_STRNCPY_CHK
:
3745 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee
), gsi
);
3748 case BUILT_IN_MEMCPY
:
3749 case BUILT_IN_MEMCPY_CHK
:
3750 case BUILT_IN_MEMPCPY
:
3751 case BUILT_IN_MEMPCPY_CHK
:
3752 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3754 case BUILT_IN_STRCAT
:
3755 case BUILT_IN_STRCAT_CHK
:
3756 handle_builtin_strcat (DECL_FUNCTION_CODE (callee
), gsi
);
3758 case BUILT_IN_MALLOC
:
3759 case BUILT_IN_CALLOC
:
3760 handle_builtin_malloc (DECL_FUNCTION_CODE (callee
), gsi
);
3762 case BUILT_IN_MEMSET
:
3763 if (handle_builtin_memset (gsi
))
3766 case BUILT_IN_MEMCMP
:
3767 if (handle_builtin_memcmp (gsi
))
3770 case BUILT_IN_STRCMP
:
3771 case BUILT_IN_STRNCMP
:
3772 if (handle_builtin_string_cmp (gsi
))
3779 else if (is_gimple_assign (stmt
) && !gimple_clobber_p (stmt
))
3781 tree lhs
= gimple_assign_lhs (stmt
);
3783 if (TREE_CODE (lhs
) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (lhs
)))
3785 if (gimple_assign_single_p (stmt
)
3786 || (gimple_assign_cast_p (stmt
)
3787 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt
)))))
3789 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3790 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = idx
;
3792 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
3793 handle_pointer_plus (gsi
);
3795 else if (TREE_CODE (lhs
) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
3797 enum tree_code code
= gimple_assign_rhs_code (stmt
);
3798 if (code
== COND_EXPR
)
3800 tree cond
= gimple_assign_rhs1 (stmt
);
3801 enum tree_code cond_code
= TREE_CODE (cond
);
3803 if (cond_code
== EQ_EXPR
|| cond_code
== NE_EXPR
)
3804 fold_strstr_to_strncmp (TREE_OPERAND (cond
, 0),
3805 TREE_OPERAND (cond
, 1), stmt
);
3807 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3808 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt
),
3809 gimple_assign_rhs2 (stmt
), stmt
);
3810 else if (gimple_assign_load_p (stmt
)
3811 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
3812 && TYPE_MODE (TREE_TYPE (lhs
)) == TYPE_MODE (char_type_node
)
3813 && (TYPE_PRECISION (TREE_TYPE (lhs
))
3814 == TYPE_PRECISION (char_type_node
))
3815 && !gimple_has_volatile_ops (stmt
))
3817 tree off
= integer_zero_node
;
3818 unsigned HOST_WIDE_INT coff
= 0;
3820 tree rhs1
= gimple_assign_rhs1 (stmt
);
3821 if (code
== MEM_REF
)
3823 idx
= get_stridx (TREE_OPERAND (rhs1
, 0));
3826 strinfo
*si
= get_strinfo (idx
);
3828 && si
->nonzero_chars
3829 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
3830 && (wi::to_widest (si
->nonzero_chars
)
3831 >= wi::to_widest (off
)))
3832 off
= TREE_OPERAND (rhs1
, 1);
3834 /* This case is not useful. See if get_addr_stridx
3835 returns something usable. */
3840 idx
= get_addr_stridx (rhs1
, NULL_TREE
, &coff
);
3843 strinfo
*si
= get_strinfo (idx
);
3845 && si
->nonzero_chars
3846 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
3848 widest_int w1
= wi::to_widest (si
->nonzero_chars
);
3849 widest_int w2
= wi::to_widest (off
) + coff
;
3851 && si
->full_string_p
)
3853 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3855 fprintf (dump_file
, "Optimizing: ");
3856 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3859 /* Reading the final '\0' character. */
3860 tree zero
= build_int_cst (TREE_TYPE (lhs
), 0);
3861 gimple_set_vuse (stmt
, NULL_TREE
);
3862 gimple_assign_set_rhs_from_tree (gsi
, zero
);
3864 |= maybe_clean_or_replace_eh_stmt (stmt
,
3866 stmt
= gsi_stmt (*gsi
);
3869 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3871 fprintf (dump_file
, "into: ");
3872 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3877 /* Reading a character before the final '\0'
3878 character. Just set the value range to ~[0, 0]
3879 if we don't have anything better. */
3881 tree type
= TREE_TYPE (lhs
);
3882 enum value_range_kind vr
3883 = get_range_info (lhs
, &min
, &max
);
3884 if (vr
== VR_VARYING
3886 && min
== wi::min_value (TYPE_PRECISION (type
),
3888 && max
== wi::max_value (TYPE_PRECISION (type
),
3890 set_range_info (lhs
, VR_ANTI_RANGE
,
3891 wi::zero (TYPE_PRECISION (type
)),
3892 wi::zero (TYPE_PRECISION (type
)));
3898 if (strlen_to_stridx
)
3900 tree rhs1
= gimple_assign_rhs1 (stmt
);
3901 if (stridx_strlenloc
*ps
= strlen_to_stridx
->get (rhs1
))
3902 strlen_to_stridx
->put (lhs
, stridx_strlenloc (*ps
));
3905 else if (TREE_CODE (lhs
) != SSA_NAME
&& !TREE_SIDE_EFFECTS (lhs
))
3907 tree type
= TREE_TYPE (lhs
);
3908 if (TREE_CODE (type
) == ARRAY_TYPE
)
3909 type
= TREE_TYPE (type
);
3910 if (TREE_CODE (type
) == INTEGER_TYPE
3911 && TYPE_MODE (type
) == TYPE_MODE (char_type_node
)
3912 && TYPE_PRECISION (type
) == TYPE_PRECISION (char_type_node
))
3914 if (! handle_char_store (gsi
))
3919 else if (gcond
*cond
= dyn_cast
<gcond
*> (stmt
))
3921 enum tree_code code
= gimple_cond_code (cond
);
3922 if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3923 fold_strstr_to_strncmp (gimple_cond_lhs (stmt
),
3924 gimple_cond_rhs (stmt
), stmt
);
3927 if (gimple_vdef (stmt
))
3928 maybe_invalidate (stmt
);
3932 /* Recursively call maybe_invalidate on stmts that might be executed
3933 in between dombb and current bb and that contain a vdef. Stop when
3934 *count stmts are inspected, or if the whole strinfo vector has
3935 been invalidated. */
3938 do_invalidate (basic_block dombb
, gimple
*phi
, bitmap visited
, int *count
)
3940 unsigned int i
, n
= gimple_phi_num_args (phi
);
3942 for (i
= 0; i
< n
; i
++)
3944 tree vuse
= gimple_phi_arg_def (phi
, i
);
3945 gimple
*stmt
= SSA_NAME_DEF_STMT (vuse
);
3946 basic_block bb
= gimple_bb (stmt
);
3949 || !bitmap_set_bit (visited
, bb
->index
)
3950 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3954 if (gimple_code (stmt
) == GIMPLE_PHI
)
3956 do_invalidate (dombb
, stmt
, visited
, count
);
3963 if (!maybe_invalidate (stmt
))
3968 vuse
= gimple_vuse (stmt
);
3969 stmt
= SSA_NAME_DEF_STMT (vuse
);
3970 if (gimple_bb (stmt
) != bb
)
3972 bb
= gimple_bb (stmt
);
3975 || !bitmap_set_bit (visited
, bb
->index
)
3976 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3983 class strlen_dom_walker
: public dom_walker
3986 strlen_dom_walker (cdi_direction direction
)
3987 : dom_walker (direction
), m_cleanup_cfg (false)
3990 virtual edge
before_dom_children (basic_block
);
3991 virtual void after_dom_children (basic_block
);
3993 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3994 execute function. */
3998 /* Callback for walk_dominator_tree. Attempt to optimize various
3999 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
4002 strlen_dom_walker::before_dom_children (basic_block bb
)
4004 basic_block dombb
= get_immediate_dominator (CDI_DOMINATORS
, bb
);
4007 stridx_to_strinfo
= NULL
;
4010 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) dombb
->aux
);
4011 if (stridx_to_strinfo
)
4013 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
4016 gphi
*phi
= gsi
.phi ();
4017 if (virtual_operand_p (gimple_phi_result (phi
)))
4019 bitmap visited
= BITMAP_ALLOC (NULL
);
4020 int count_vdef
= 100;
4021 do_invalidate (dombb
, phi
, visited
, &count_vdef
);
4022 BITMAP_FREE (visited
);
4023 if (count_vdef
== 0)
4025 /* If there were too many vdefs in between immediate
4026 dominator and current bb, invalidate everything.
4027 If stridx_to_strinfo has been unshared, we need
4028 to free it, otherwise just set it to NULL. */
4029 if (!strinfo_shared ())
4035 vec_safe_iterate (stridx_to_strinfo
, i
, &si
);
4039 (*stridx_to_strinfo
)[i
] = NULL
;
4043 stridx_to_strinfo
= NULL
;
4051 /* If all PHI arguments have the same string index, the PHI result
4053 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
4056 gphi
*phi
= gsi
.phi ();
4057 tree result
= gimple_phi_result (phi
);
4058 if (!virtual_operand_p (result
) && POINTER_TYPE_P (TREE_TYPE (result
)))
4060 int idx
= get_stridx (gimple_phi_arg_def (phi
, 0));
4063 unsigned int i
, n
= gimple_phi_num_args (phi
);
4064 for (i
= 1; i
< n
; i
++)
4065 if (idx
!= get_stridx (gimple_phi_arg_def (phi
, i
)))
4068 ssa_ver_to_stridx
[SSA_NAME_VERSION (result
)] = idx
;
4073 bool cleanup_eh
= false;
4075 /* Attempt to optimize individual statements. */
4076 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); )
4077 if (strlen_check_and_optimize_stmt (&gsi
, &cleanup_eh
))
4080 if (cleanup_eh
&& gimple_purge_dead_eh_edges (bb
))
4081 m_cleanup_cfg
= true;
4083 bb
->aux
= stridx_to_strinfo
;
4084 if (vec_safe_length (stridx_to_strinfo
) && !strinfo_shared ())
4085 (*stridx_to_strinfo
)[0] = (strinfo
*) bb
;
4089 /* Callback for walk_dominator_tree. Free strinfo vector if it is
4090 owned by the current bb, clear bb->aux. */
4093 strlen_dom_walker::after_dom_children (basic_block bb
)
4097 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) bb
->aux
);
4098 if (vec_safe_length (stridx_to_strinfo
)
4099 && (*stridx_to_strinfo
)[0] == (strinfo
*) bb
)
4104 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
4106 vec_free (stridx_to_strinfo
);
4112 /* Main entry point. */
4116 const pass_data pass_data_strlen
=
4118 GIMPLE_PASS
, /* type */
4119 "strlen", /* name */
4120 OPTGROUP_NONE
, /* optinfo_flags */
4121 TV_TREE_STRLEN
, /* tv_id */
4122 ( PROP_cfg
| PROP_ssa
), /* properties_required */
4123 0, /* properties_provided */
4124 0, /* properties_destroyed */
4125 0, /* todo_flags_start */
4126 0, /* todo_flags_finish */
4129 class pass_strlen
: public gimple_opt_pass
4132 pass_strlen (gcc::context
*ctxt
)
4133 : gimple_opt_pass (pass_data_strlen
, ctxt
)
4136 /* opt_pass methods: */
4137 virtual bool gate (function
*) { return flag_optimize_strlen
!= 0; }
4138 virtual unsigned int execute (function
*);
4140 }; // class pass_strlen
4143 pass_strlen::execute (function
*fun
)
4145 gcc_assert (!strlen_to_stridx
);
4146 if (warn_stringop_overflow
|| warn_stringop_truncation
)
4147 strlen_to_stridx
= new hash_map
<tree
, stridx_strlenloc
> ();
4149 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
4152 calculate_dominance_info (CDI_DOMINATORS
);
4154 /* String length optimization is implemented as a walk of the dominator
4155 tree and a forward walk of statements within each block. */
4156 strlen_dom_walker
walker (CDI_DOMINATORS
);
4157 walker
.walk (fun
->cfg
->x_entry_block_ptr
);
4159 ssa_ver_to_stridx
.release ();
4160 strinfo_pool
.release ();
4161 if (decl_to_stridxlist_htab
)
4163 obstack_free (&stridx_obstack
, NULL
);
4164 delete decl_to_stridxlist_htab
;
4165 decl_to_stridxlist_htab
= NULL
;
4167 laststmt
.stmt
= NULL
;
4168 laststmt
.len
= NULL_TREE
;
4169 laststmt
.stridx
= 0;
4171 if (strlen_to_stridx
)
4173 strlen_to_stridx
->empty ();
4174 delete strlen_to_stridx
;
4175 strlen_to_stridx
= NULL
;
4178 return walker
.m_cleanup_cfg
? TODO_cleanup_cfg
: 0;
4184 make_pass_strlen (gcc::context
*ctxt
)
4186 return new pass_strlen (ctxt
);