1 /* String length optimization
2 Copyright (C) 2011-2017 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"
44 #include "tree-ssa-alias.h"
45 #include "tree-ssa-propagate.h"
48 #include "tree-hash-traits.h"
51 #include "diagnostic-core.h"
52 #include "diagnostic.h"
57 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
58 is an index into strinfo vector, negative value stands for
59 string length of a string literal (~strlen). */
60 static vec
<int> ssa_ver_to_stridx
;
62 /* Number of currently active string indexes plus one. */
63 static int max_stridx
;
65 /* String information record. */
68 /* Number of leading characters that are known to be nonzero. This is
69 also the length of the string if FULL_STRING_P.
71 The values in a list of related string pointers must be consistent;
72 that is, if strinfo B comes X bytes after strinfo A, it must be
73 the case that A->nonzero_chars == X + B->nonzero_chars. */
75 /* Any of the corresponding pointers for querying alias oracle. */
77 /* This is used for two things:
79 - To record the statement that should be used for delayed length
80 computations. We maintain the invariant that all related strinfos
81 have delayed lengths or none do.
83 - To record the malloc or calloc call that produced this result. */
85 /* Pointer to '\0' if known, if NULL, it can be computed as
88 /* Reference count. Any changes to strinfo entry possibly shared
89 with dominating basic blocks need unshare_strinfo first, except
90 for dont_invalidate which affects only the immediately next
93 /* Copy of index. get_strinfo (si->idx) should return si; */
95 /* These 3 fields are for chaining related string pointers together.
97 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
98 strcpy (c, d); e = c + dl;
99 strinfo(a) -> strinfo(c) -> strinfo(e)
100 All have ->first field equal to strinfo(a)->idx and are doubly
101 chained through prev/next fields. The later strinfos are required
102 to point into the same string with zero or more bytes after
103 the previous pointer and all bytes in between the two pointers
104 must be non-zero. Functions like strcpy or memcpy are supposed
105 to adjust all previous strinfo lengths, but not following strinfo
106 lengths (those are uncertain, usually invalidated during
107 maybe_invalidate, except when the alias oracle knows better).
108 Functions like strcat on the other side adjust the whole
109 related strinfo chain.
110 They are updated lazily, so to use the chain the same first fields
111 and si->prev->next == si->idx needs to be verified. */
115 /* A flag whether the string is known to be written in the current
118 /* A flag for the next maybe_invalidate that this strinfo shouldn't
119 be invalidated. Always cleared by maybe_invalidate. */
120 bool dont_invalidate
;
121 /* True if the string is known to be nul-terminated after NONZERO_CHARS
122 characters. False is useful when detecting strings that are built
123 up via successive memcpys. */
127 /* Pool for allocating strinfo_struct entries. */
128 static object_allocator
<strinfo
> strinfo_pool ("strinfo pool");
130 /* Vector mapping positive string indexes to strinfo, for the
131 current basic block. The first pointer in the vector is special,
132 it is either NULL, meaning the vector isn't shared, or it is
133 a basic block pointer to the owner basic_block if shared.
134 If some other bb wants to modify the vector, the vector needs
135 to be unshared first, and only the owner bb is supposed to free it. */
136 static vec
<strinfo
*, va_heap
, vl_embed
> *stridx_to_strinfo
;
138 /* One OFFSET->IDX mapping. */
141 struct stridxlist
*next
;
142 HOST_WIDE_INT offset
;
146 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
147 struct decl_stridxlist_map
149 struct tree_map_base base
;
150 struct stridxlist list
;
153 /* Hash table for mapping decls to a chained list of offset -> idx
155 static hash_map
<tree_decl_hash
, stridxlist
> *decl_to_stridxlist_htab
;
157 /* Hash table mapping strlen calls to stridx instances describing
158 the calls' arguments. Non-null only when warn_stringop_truncation
160 typedef std::pair
<int, location_t
> stridx_strlenloc
;
161 static hash_map
<tree
, stridx_strlenloc
> *strlen_to_stridx
;
163 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
164 static struct obstack stridx_obstack
;
166 /* Last memcpy statement if it could be adjusted if the trailing
167 '\0' written is immediately overwritten, or
168 *x = '\0' store that could be removed if it is immediately overwritten. */
169 struct laststmt_struct
176 static int get_stridx_plus_constant (strinfo
*, unsigned HOST_WIDE_INT
, tree
);
177 static void handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*);
181 - 1 if SI is known to start with more than OFF nonzero characters.
183 - 0 if SI is known to start with OFF nonzero characters,
184 but is not known to start with more.
186 - -1 if SI might not start with OFF nonzero characters. */
189 compare_nonzero_chars (strinfo
*si
, unsigned HOST_WIDE_INT off
)
191 if (si
->nonzero_chars
192 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
193 return compare_tree_int (si
->nonzero_chars
, off
);
198 /* Return true if SI is known to be a zero-length string. */
201 zero_length_string_p (strinfo
*si
)
203 return si
->full_string_p
&& integer_zerop (si
->nonzero_chars
);
206 /* Return strinfo vector entry IDX. */
208 static inline strinfo
*
209 get_strinfo (int idx
)
211 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
213 return (*stridx_to_strinfo
)[idx
];
216 /* Get the next strinfo in the chain after SI, or null if none. */
218 static inline strinfo
*
219 get_next_strinfo (strinfo
*si
)
223 strinfo
*nextsi
= get_strinfo (si
->next
);
224 if (nextsi
== NULL
|| nextsi
->first
!= si
->first
|| nextsi
->prev
!= si
->idx
)
229 /* Helper function for get_stridx. Return the strinfo index of the address
230 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
231 OK to return the index for some X <= &EXP and store &EXP - X in
235 get_addr_stridx (tree exp
, tree ptr
, unsigned HOST_WIDE_INT
*offset_out
)
238 struct stridxlist
*list
, *last
= NULL
;
241 if (!decl_to_stridxlist_htab
)
244 base
= get_addr_base_and_unit_offset (exp
, &off
);
245 if (base
== NULL
|| !DECL_P (base
))
248 list
= decl_to_stridxlist_htab
->get (base
);
254 if (list
->offset
== off
)
260 if (list
->offset
> off
)
267 if ((offset_out
|| ptr
) && last
&& last
->idx
> 0)
269 unsigned HOST_WIDE_INT rel_off
270 = (unsigned HOST_WIDE_INT
) off
- last
->offset
;
271 strinfo
*si
= get_strinfo (last
->idx
);
272 if (si
&& compare_nonzero_chars (si
, rel_off
) >= 0)
276 *offset_out
= rel_off
;
280 return get_stridx_plus_constant (si
, rel_off
, ptr
);
286 /* Return string index for EXP. */
289 get_stridx (tree exp
)
293 if (TREE_CODE (exp
) == SSA_NAME
)
295 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)])
296 return ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)];
299 HOST_WIDE_INT off
= 0;
300 for (i
= 0; i
< 5; i
++)
302 gimple
*def_stmt
= SSA_NAME_DEF_STMT (e
);
303 if (!is_gimple_assign (def_stmt
)
304 || gimple_assign_rhs_code (def_stmt
) != POINTER_PLUS_EXPR
)
306 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
307 tree rhs2
= gimple_assign_rhs2 (def_stmt
);
308 if (TREE_CODE (rhs1
) != SSA_NAME
309 || !tree_fits_shwi_p (rhs2
))
311 HOST_WIDE_INT this_off
= tree_to_shwi (rhs2
);
314 off
= (unsigned HOST_WIDE_INT
) off
+ this_off
;
317 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (rhs1
)])
320 = get_strinfo (ssa_ver_to_stridx
[SSA_NAME_VERSION (rhs1
)]);
321 if (si
&& compare_nonzero_chars (si
, off
) >= 0)
322 return get_stridx_plus_constant (si
, off
, exp
);
329 if (TREE_CODE (exp
) == ADDR_EXPR
)
331 int idx
= get_addr_stridx (TREE_OPERAND (exp
, 0), exp
, NULL
);
336 s
= string_constant (exp
, &o
);
338 && (o
== NULL_TREE
|| tree_fits_shwi_p (o
))
339 && TREE_STRING_LENGTH (s
) > 0)
341 HOST_WIDE_INT offset
= o
? tree_to_shwi (o
) : 0;
342 const char *p
= TREE_STRING_POINTER (s
);
343 int max
= TREE_STRING_LENGTH (s
) - 1;
345 if (p
[max
] == '\0' && offset
>= 0 && offset
<= max
)
346 return ~(int) strlen (p
+ offset
);
351 /* Return true if strinfo vector is shared with the immediate dominator. */
354 strinfo_shared (void)
356 return vec_safe_length (stridx_to_strinfo
)
357 && (*stridx_to_strinfo
)[0] != NULL
;
360 /* Unshare strinfo vector that is shared with the immediate dominator. */
363 unshare_strinfo_vec (void)
368 gcc_assert (strinfo_shared ());
369 stridx_to_strinfo
= vec_safe_copy (stridx_to_strinfo
);
370 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
373 (*stridx_to_strinfo
)[0] = NULL
;
376 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
377 Return a pointer to the location where the string index can
378 be stored (if 0) or is stored, or NULL if this can't be tracked. */
381 addr_stridxptr (tree exp
)
385 tree base
= get_addr_base_and_unit_offset (exp
, &off
);
386 if (base
== NULL_TREE
|| !DECL_P (base
))
389 if (!decl_to_stridxlist_htab
)
391 decl_to_stridxlist_htab
392 = new hash_map
<tree_decl_hash
, stridxlist
> (64);
393 gcc_obstack_init (&stridx_obstack
);
397 stridxlist
*list
= &decl_to_stridxlist_htab
->get_or_insert (base
, &existed
);
401 stridxlist
*before
= NULL
;
402 for (i
= 0; i
< 32; i
++)
404 if (list
->offset
== off
)
406 if (list
->offset
> off
&& before
== NULL
)
408 if (list
->next
== NULL
)
417 before
= XOBNEW (&stridx_obstack
, struct stridxlist
);
424 list
->next
= XOBNEW (&stridx_obstack
, struct stridxlist
);
434 /* Create a new string index, or return 0 if reached limit. */
437 new_stridx (tree exp
)
440 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
442 if (TREE_CODE (exp
) == SSA_NAME
)
444 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
))
447 ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)] = idx
;
450 if (TREE_CODE (exp
) == ADDR_EXPR
)
452 int *pidx
= addr_stridxptr (TREE_OPERAND (exp
, 0));
455 gcc_assert (*pidx
== 0);
456 *pidx
= max_stridx
++;
463 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
466 new_addr_stridx (tree exp
)
469 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
471 pidx
= addr_stridxptr (exp
);
474 gcc_assert (*pidx
== 0);
475 *pidx
= max_stridx
++;
481 /* Create a new strinfo. */
484 new_strinfo (tree ptr
, int idx
, tree nonzero_chars
, bool full_string_p
)
486 strinfo
*si
= strinfo_pool
.allocate ();
487 si
->nonzero_chars
= nonzero_chars
;
490 si
->endptr
= NULL_TREE
;
496 si
->writable
= false;
497 si
->dont_invalidate
= false;
498 si
->full_string_p
= full_string_p
;
502 /* Decrease strinfo refcount and free it if not referenced anymore. */
505 free_strinfo (strinfo
*si
)
507 if (si
&& --si
->refcount
== 0)
508 strinfo_pool
.remove (si
);
511 /* Set strinfo in the vector entry IDX to SI. */
514 set_strinfo (int idx
, strinfo
*si
)
516 if (vec_safe_length (stridx_to_strinfo
) && (*stridx_to_strinfo
)[0])
517 unshare_strinfo_vec ();
518 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
519 vec_safe_grow_cleared (stridx_to_strinfo
, idx
+ 1);
520 (*stridx_to_strinfo
)[idx
] = si
;
523 /* Return the first strinfo in the related strinfo chain
524 if all strinfos in between belong to the chain, otherwise NULL. */
527 verify_related_strinfos (strinfo
*origsi
)
529 strinfo
*si
= origsi
, *psi
;
531 if (origsi
->first
== 0)
533 for (; si
->prev
; si
= psi
)
535 if (si
->first
!= origsi
->first
)
537 psi
= get_strinfo (si
->prev
);
540 if (psi
->next
!= si
->idx
)
543 if (si
->idx
!= si
->first
)
548 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
549 Use LOC for folding. */
552 set_endptr_and_length (location_t loc
, strinfo
*si
, tree endptr
)
556 tree start_as_size
= fold_convert_loc (loc
, size_type_node
, si
->ptr
);
557 tree end_as_size
= fold_convert_loc (loc
, size_type_node
, endptr
);
558 si
->nonzero_chars
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
559 end_as_size
, start_as_size
);
560 si
->full_string_p
= true;
563 /* Return string length, or NULL if it can't be computed. */
566 get_string_length (strinfo
*si
)
568 if (si
->nonzero_chars
)
569 return si
->full_string_p
? si
->nonzero_chars
: NULL
;
573 gimple
*stmt
= si
->stmt
, *lenstmt
;
574 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
575 tree callee
, lhs
, fn
, tem
;
577 gimple_stmt_iterator gsi
;
579 gcc_assert (is_gimple_call (stmt
));
580 callee
= gimple_call_fndecl (stmt
);
581 gcc_assert (callee
&& DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
);
582 lhs
= gimple_call_lhs (stmt
);
583 /* unshare_strinfo is intentionally not called here. The (delayed)
584 transformation of strcpy or strcat into stpcpy is done at the place
585 of the former strcpy/strcat call and so can affect all the strinfos
586 with the same stmt. If they were unshared before and transformation
587 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
588 just compute the right length. */
589 switch (DECL_FUNCTION_CODE (callee
))
591 case BUILT_IN_STRCAT
:
592 case BUILT_IN_STRCAT_CHK
:
593 case BUILT_IN_STRCAT_CHKP
:
594 case BUILT_IN_STRCAT_CHK_CHKP
:
595 gsi
= gsi_for_stmt (stmt
);
596 fn
= builtin_decl_implicit (BUILT_IN_STRLEN
);
597 gcc_assert (lhs
== NULL_TREE
);
598 tem
= unshare_expr (gimple_call_arg (stmt
, 0));
601 lenstmt
= gimple_build_call (chkp_maybe_create_clone (fn
)->decl
,
602 2, tem
, gimple_call_arg (stmt
, 1));
603 gimple_call_set_with_bounds (lenstmt
, true);
606 lenstmt
= gimple_build_call (fn
, 1, tem
);
607 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), lenstmt
);
608 gimple_call_set_lhs (lenstmt
, lhs
);
609 gimple_set_vuse (lenstmt
, gimple_vuse (stmt
));
610 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
611 tem
= gimple_call_arg (stmt
, 0);
612 if (!ptrofftype_p (TREE_TYPE (lhs
)))
614 lhs
= convert_to_ptrofftype (lhs
);
615 lhs
= force_gimple_operand_gsi (&gsi
, lhs
, true, NULL_TREE
,
616 true, GSI_SAME_STMT
);
618 lenstmt
= gimple_build_assign
619 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt
, 0))),
620 POINTER_PLUS_EXPR
,tem
, lhs
);
621 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
622 gimple_call_set_arg (stmt
, 0, gimple_assign_lhs (lenstmt
));
625 case BUILT_IN_STRCPY
:
626 case BUILT_IN_STRCPY_CHK
:
627 case BUILT_IN_STRCPY_CHKP
:
628 case BUILT_IN_STRCPY_CHK_CHKP
:
629 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY
));
630 if (gimple_call_num_args (stmt
) == (with_bounds
? 4 : 2))
631 fn
= builtin_decl_implicit (BUILT_IN_STPCPY
);
633 fn
= builtin_decl_explicit (BUILT_IN_STPCPY_CHK
);
635 fn
= chkp_maybe_create_clone (fn
)->decl
;
636 gcc_assert (lhs
== NULL_TREE
);
637 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
639 fprintf (dump_file
, "Optimizing: ");
640 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
642 gimple_call_set_fndecl (stmt
, fn
);
643 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), stmt
);
644 gimple_call_set_lhs (stmt
, lhs
);
646 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
648 fprintf (dump_file
, "into: ");
649 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
652 case BUILT_IN_STPCPY
:
653 case BUILT_IN_STPCPY_CHK
:
654 case BUILT_IN_STPCPY_CHKP
:
655 case BUILT_IN_STPCPY_CHK_CHKP
:
656 gcc_assert (lhs
!= NULL_TREE
);
657 loc
= gimple_location (stmt
);
658 set_endptr_and_length (loc
, si
, lhs
);
659 for (strinfo
*chainsi
= verify_related_strinfos (si
);
661 chainsi
= get_next_strinfo (chainsi
))
662 if (chainsi
->nonzero_chars
== NULL
)
663 set_endptr_and_length (loc
, chainsi
, lhs
);
665 case BUILT_IN_MALLOC
:
667 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
674 return si
->nonzero_chars
;
677 /* Invalidate string length information for strings whose length
678 might change due to stores in stmt. */
681 maybe_invalidate (gimple
*stmt
)
685 bool nonempty
= false;
687 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
690 if (!si
->dont_invalidate
)
693 /* Do not use si->nonzero_chars. */
694 ao_ref_init_from_ptr_and_size (&r
, si
->ptr
, NULL_TREE
);
695 if (stmt_may_clobber_ref_p_1 (stmt
, &r
))
697 set_strinfo (i
, NULL
);
702 si
->dont_invalidate
= false;
708 /* Unshare strinfo record SI, if it has refcount > 1 or
709 if stridx_to_strinfo vector is shared with some other
713 unshare_strinfo (strinfo
*si
)
717 if (si
->refcount
== 1 && !strinfo_shared ())
720 nsi
= new_strinfo (si
->ptr
, si
->idx
, si
->nonzero_chars
, si
->full_string_p
);
721 nsi
->stmt
= si
->stmt
;
722 nsi
->endptr
= si
->endptr
;
723 nsi
->first
= si
->first
;
724 nsi
->prev
= si
->prev
;
725 nsi
->next
= si
->next
;
726 nsi
->writable
= si
->writable
;
727 set_strinfo (si
->idx
, nsi
);
732 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
733 strinfo if there is any. Return it's idx, or 0 if no strinfo has
737 get_stridx_plus_constant (strinfo
*basesi
, unsigned HOST_WIDE_INT off
,
740 if (TREE_CODE (ptr
) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
743 if (compare_nonzero_chars (basesi
, off
) < 0
744 || !tree_fits_uhwi_p (basesi
->nonzero_chars
))
747 unsigned HOST_WIDE_INT nonzero_chars
748 = tree_to_uhwi (basesi
->nonzero_chars
) - off
;
749 strinfo
*si
= basesi
, *chainsi
;
750 if (si
->first
|| si
->prev
|| si
->next
)
751 si
= verify_related_strinfos (basesi
);
753 || si
->nonzero_chars
== NULL_TREE
754 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
757 if (TREE_CODE (ptr
) == SSA_NAME
758 && ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
759 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
761 gcc_checking_assert (compare_tree_int (si
->nonzero_chars
, off
) != -1);
762 for (chainsi
= si
; chainsi
->next
; chainsi
= si
)
764 si
= get_next_strinfo (chainsi
);
766 || si
->nonzero_chars
== NULL_TREE
767 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
769 int r
= compare_tree_int (si
->nonzero_chars
, nonzero_chars
);
774 if (TREE_CODE (ptr
) == SSA_NAME
)
775 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = si
->idx
;
778 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
779 if (pidx
!= NULL
&& *pidx
== 0)
788 int idx
= new_stridx (ptr
);
791 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, nonzero_chars
),
792 basesi
->full_string_p
);
793 set_strinfo (idx
, si
);
796 strinfo
*nextsi
= unshare_strinfo (get_strinfo (chainsi
->next
));
797 si
->next
= nextsi
->idx
;
800 chainsi
= unshare_strinfo (chainsi
);
801 if (chainsi
->first
== 0)
802 chainsi
->first
= chainsi
->idx
;
804 if (chainsi
->endptr
== NULL_TREE
&& zero_length_string_p (si
))
805 chainsi
->endptr
= ptr
;
806 si
->endptr
= chainsi
->endptr
;
807 si
->prev
= chainsi
->idx
;
808 si
->first
= chainsi
->first
;
809 si
->writable
= chainsi
->writable
;
813 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
814 to a zero-length string and if possible chain it to a related strinfo
815 chain whose part is or might be CHAINSI. */
818 zero_length_string (tree ptr
, strinfo
*chainsi
)
822 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
823 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
824 gcc_checking_assert (TREE_CODE (ptr
) == SSA_NAME
825 && ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] == 0);
827 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
831 si
= verify_related_strinfos (chainsi
);
836 /* We shouldn't mix delayed and non-delayed lengths. */
837 gcc_assert (si
->full_string_p
);
838 if (si
->endptr
== NULL_TREE
)
840 si
= unshare_strinfo (si
);
844 si
= get_next_strinfo (si
);
847 if (zero_length_string_p (chainsi
))
851 chainsi
= unshare_strinfo (chainsi
);
854 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = chainsi
->idx
;
860 /* We shouldn't mix delayed and non-delayed lengths. */
861 gcc_assert (chainsi
->full_string_p
);
862 if (chainsi
->first
|| chainsi
->prev
|| chainsi
->next
)
864 chainsi
= unshare_strinfo (chainsi
);
871 idx
= new_stridx (ptr
);
874 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, 0), true);
875 set_strinfo (idx
, si
);
879 chainsi
= unshare_strinfo (chainsi
);
880 if (chainsi
->first
== 0)
881 chainsi
->first
= chainsi
->idx
;
883 if (chainsi
->endptr
== NULL_TREE
)
884 chainsi
->endptr
= ptr
;
885 si
->prev
= chainsi
->idx
;
886 si
->first
= chainsi
->first
;
887 si
->writable
= chainsi
->writable
;
892 /* For strinfo ORIGSI whose length has been just updated, adjust other
893 related strinfos so that they match the new ORIGSI. This involves:
895 - adding ADJ to the nonzero_chars fields
896 - copying full_string_p from the new ORIGSI. */
899 adjust_related_strinfos (location_t loc
, strinfo
*origsi
, tree adj
)
901 strinfo
*si
= verify_related_strinfos (origsi
);
914 si
= unshare_strinfo (si
);
915 /* We shouldn't see delayed lengths here; the caller must have
916 calculated the old length in order to calculate the
918 gcc_assert (si
->nonzero_chars
);
919 tem
= fold_convert_loc (loc
, TREE_TYPE (si
->nonzero_chars
), adj
);
920 si
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
921 TREE_TYPE (si
->nonzero_chars
),
922 si
->nonzero_chars
, tem
);
923 si
->full_string_p
= origsi
->full_string_p
;
925 si
->endptr
= NULL_TREE
;
926 si
->dont_invalidate
= true;
928 nsi
= get_next_strinfo (si
);
935 /* Find if there are other SSA_NAME pointers equal to PTR
936 for which we don't track their string lengths yet. If so, use
940 find_equal_ptrs (tree ptr
, int idx
)
942 if (TREE_CODE (ptr
) != SSA_NAME
)
946 gimple
*stmt
= SSA_NAME_DEF_STMT (ptr
);
947 if (!is_gimple_assign (stmt
))
949 ptr
= gimple_assign_rhs1 (stmt
);
950 switch (gimple_assign_rhs_code (stmt
))
955 if (!POINTER_TYPE_P (TREE_TYPE (ptr
)))
957 if (TREE_CODE (ptr
) == SSA_NAME
)
959 if (TREE_CODE (ptr
) != ADDR_EXPR
)
964 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
965 if (pidx
!= NULL
&& *pidx
== 0)
973 /* We might find an endptr created in this pass. Grow the
974 vector in that case. */
975 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
976 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
978 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] != 0)
980 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = idx
;
984 /* Return true if STMT is a call to a builtin function with the right
985 arguments and attributes that should be considered for optimization
989 valid_builtin_call (gimple
*stmt
)
991 if (!gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
994 tree callee
= gimple_call_fndecl (stmt
);
995 switch (DECL_FUNCTION_CODE (callee
))
997 case BUILT_IN_MEMCMP
:
998 case BUILT_IN_MEMCMP_EQ
:
999 case BUILT_IN_STRCHR
:
1000 case BUILT_IN_STRCHR_CHKP
:
1001 case BUILT_IN_STRLEN
:
1002 case BUILT_IN_STRLEN_CHKP
:
1003 /* The above functions should be pure. Punt if they aren't. */
1004 if (gimple_vdef (stmt
) || gimple_vuse (stmt
) == NULL_TREE
)
1008 case BUILT_IN_CALLOC
:
1009 case BUILT_IN_MALLOC
:
1010 case BUILT_IN_MEMCPY
:
1011 case BUILT_IN_MEMCPY_CHK
:
1012 case BUILT_IN_MEMCPY_CHKP
:
1013 case BUILT_IN_MEMCPY_CHK_CHKP
:
1014 case BUILT_IN_MEMPCPY
:
1015 case BUILT_IN_MEMPCPY_CHK
:
1016 case BUILT_IN_MEMPCPY_CHKP
:
1017 case BUILT_IN_MEMPCPY_CHK_CHKP
:
1018 case BUILT_IN_MEMSET
:
1019 case BUILT_IN_STPCPY
:
1020 case BUILT_IN_STPCPY_CHK
:
1021 case BUILT_IN_STPCPY_CHKP
:
1022 case BUILT_IN_STPCPY_CHK_CHKP
:
1023 case BUILT_IN_STRCAT
:
1024 case BUILT_IN_STRCAT_CHK
:
1025 case BUILT_IN_STRCAT_CHKP
:
1026 case BUILT_IN_STRCAT_CHK_CHKP
:
1027 case BUILT_IN_STRCPY
:
1028 case BUILT_IN_STRCPY_CHK
:
1029 case BUILT_IN_STRCPY_CHKP
:
1030 case BUILT_IN_STRCPY_CHK_CHKP
:
1031 /* The above functions should be neither const nor pure. Punt if they
1033 if (gimple_vdef (stmt
) == NULL_TREE
|| gimple_vuse (stmt
) == NULL_TREE
)
1044 /* If the last .MEM setter statement before STMT is
1045 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1046 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1047 just memcpy (x, y, strlen (y)). SI must be the zero length
1051 adjust_last_stmt (strinfo
*si
, gimple
*stmt
, bool is_strcat
)
1053 tree vuse
, callee
, len
;
1054 struct laststmt_struct last
= laststmt
;
1055 strinfo
*lastsi
, *firstsi
;
1056 unsigned len_arg_no
= 2;
1058 laststmt
.stmt
= NULL
;
1059 laststmt
.len
= NULL_TREE
;
1060 laststmt
.stridx
= 0;
1062 if (last
.stmt
== NULL
)
1065 vuse
= gimple_vuse (stmt
);
1066 if (vuse
== NULL_TREE
1067 || SSA_NAME_DEF_STMT (vuse
) != last
.stmt
1068 || !has_single_use (vuse
))
1071 gcc_assert (last
.stridx
> 0);
1072 lastsi
= get_strinfo (last
.stridx
);
1078 if (lastsi
->first
== 0 || lastsi
->first
!= si
->first
)
1081 firstsi
= verify_related_strinfos (si
);
1082 if (firstsi
== NULL
)
1084 while (firstsi
!= lastsi
)
1086 firstsi
= get_next_strinfo (firstsi
);
1087 if (firstsi
== NULL
)
1092 if (!is_strcat
&& !zero_length_string_p (si
))
1095 if (is_gimple_assign (last
.stmt
))
1097 gimple_stmt_iterator gsi
;
1099 if (!integer_zerop (gimple_assign_rhs1 (last
.stmt
)))
1101 if (stmt_could_throw_p (last
.stmt
))
1103 gsi
= gsi_for_stmt (last
.stmt
);
1104 unlink_stmt_vdef (last
.stmt
);
1105 release_defs (last
.stmt
);
1106 gsi_remove (&gsi
, true);
1110 if (!valid_builtin_call (last
.stmt
))
1113 callee
= gimple_call_fndecl (last
.stmt
);
1114 switch (DECL_FUNCTION_CODE (callee
))
1116 case BUILT_IN_MEMCPY
:
1117 case BUILT_IN_MEMCPY_CHK
:
1119 case BUILT_IN_MEMCPY_CHKP
:
1120 case BUILT_IN_MEMCPY_CHK_CHKP
:
1127 len
= gimple_call_arg (last
.stmt
, len_arg_no
);
1128 if (tree_fits_uhwi_p (len
))
1130 if (!tree_fits_uhwi_p (last
.len
)
1131 || integer_zerop (len
)
1132 || tree_to_uhwi (len
) != tree_to_uhwi (last
.len
) + 1)
1134 /* Don't adjust the length if it is divisible by 4, it is more efficient
1135 to store the extra '\0' in that case. */
1136 if ((tree_to_uhwi (len
) & 3) == 0)
1139 else if (TREE_CODE (len
) == SSA_NAME
)
1141 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1142 if (!is_gimple_assign (def_stmt
)
1143 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
1144 || gimple_assign_rhs1 (def_stmt
) != last
.len
1145 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
1151 gimple_call_set_arg (last
.stmt
, len_arg_no
, last
.len
);
1152 update_stmt (last
.stmt
);
1155 /* Handle a strlen call. If strlen of the argument is known, replace
1156 the strlen call with the known value, otherwise remember that strlen
1157 of the argument is stored in the lhs SSA_NAME. */
1160 handle_builtin_strlen (gimple_stmt_iterator
*gsi
)
1164 gimple
*stmt
= gsi_stmt (*gsi
);
1165 tree lhs
= gimple_call_lhs (stmt
);
1167 if (lhs
== NULL_TREE
)
1170 src
= gimple_call_arg (stmt
, 0);
1171 idx
= get_stridx (src
);
1178 rhs
= build_int_cst (TREE_TYPE (lhs
), ~idx
);
1182 si
= get_strinfo (idx
);
1184 rhs
= get_string_length (si
);
1186 if (rhs
!= NULL_TREE
)
1188 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1190 fprintf (dump_file
, "Optimizing: ");
1191 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1193 rhs
= unshare_expr (rhs
);
1194 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
1195 rhs
= fold_convert_loc (gimple_location (stmt
),
1196 TREE_TYPE (lhs
), rhs
);
1197 if (!update_call_from_tree (gsi
, rhs
))
1198 gimplify_and_update_call_from_tree (gsi
, rhs
);
1199 stmt
= gsi_stmt (*gsi
);
1201 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1203 fprintf (dump_file
, "into: ");
1204 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1207 && TREE_CODE (si
->nonzero_chars
) != SSA_NAME
1208 && TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
1209 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1211 si
= unshare_strinfo (si
);
1212 si
->nonzero_chars
= lhs
;
1213 gcc_assert (si
->full_string_p
);
1216 if (strlen_to_stridx
)
1218 location_t loc
= gimple_location (stmt
);
1219 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1224 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1227 idx
= new_stridx (src
);
1230 strinfo
*si
= get_strinfo (idx
);
1233 if (!si
->full_string_p
&& !si
->stmt
)
1235 /* Until now we only had a lower bound on the string length.
1236 Install LHS as the actual length. */
1237 si
= unshare_strinfo (si
);
1238 tree old
= si
->nonzero_chars
;
1239 si
->nonzero_chars
= lhs
;
1240 si
->full_string_p
= true;
1241 if (TREE_CODE (old
) == INTEGER_CST
)
1243 location_t loc
= gimple_location (stmt
);
1244 old
= fold_convert_loc (loc
, TREE_TYPE (lhs
), old
);
1245 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1246 TREE_TYPE (lhs
), lhs
, old
);
1247 adjust_related_strinfos (loc
, si
, adj
);
1261 strinfo
*si
= new_strinfo (src
, idx
, lhs
, true);
1262 set_strinfo (idx
, si
);
1263 find_equal_ptrs (src
, idx
);
1265 if (strlen_to_stridx
)
1267 location_t loc
= gimple_location (stmt
);
1268 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1273 /* Handle a strchr call. If strlen of the first argument is known, replace
1274 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1275 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1278 handle_builtin_strchr (gimple_stmt_iterator
*gsi
)
1282 gimple
*stmt
= gsi_stmt (*gsi
);
1283 tree lhs
= gimple_call_lhs (stmt
);
1284 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
1286 if (lhs
== NULL_TREE
)
1289 if (!integer_zerop (gimple_call_arg (stmt
, with_bounds
? 2 : 1)))
1292 src
= gimple_call_arg (stmt
, 0);
1293 idx
= get_stridx (src
);
1300 rhs
= build_int_cst (size_type_node
, ~idx
);
1304 si
= get_strinfo (idx
);
1306 rhs
= get_string_length (si
);
1308 if (rhs
!= NULL_TREE
)
1310 location_t loc
= gimple_location (stmt
);
1312 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1314 fprintf (dump_file
, "Optimizing: ");
1315 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1317 if (si
!= NULL
&& si
->endptr
!= NULL_TREE
)
1319 rhs
= unshare_expr (si
->endptr
);
1320 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1322 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1326 rhs
= fold_convert_loc (loc
, sizetype
, unshare_expr (rhs
));
1327 rhs
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
1328 TREE_TYPE (src
), src
, rhs
);
1329 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1331 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1333 if (!update_call_from_tree (gsi
, rhs
))
1334 gimplify_and_update_call_from_tree (gsi
, rhs
);
1335 stmt
= gsi_stmt (*gsi
);
1337 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1339 fprintf (dump_file
, "into: ");
1340 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1343 && si
->endptr
== NULL_TREE
1344 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1346 si
= unshare_strinfo (si
);
1349 zero_length_string (lhs
, si
);
1353 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1355 if (TREE_CODE (src
) != SSA_NAME
|| !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src
))
1358 idx
= new_stridx (src
);
1359 else if (get_strinfo (idx
) != NULL
)
1361 zero_length_string (lhs
, NULL
);
1366 location_t loc
= gimple_location (stmt
);
1367 tree lhsu
= fold_convert_loc (loc
, size_type_node
, lhs
);
1368 tree srcu
= fold_convert_loc (loc
, size_type_node
, src
);
1369 tree length
= fold_build2_loc (loc
, MINUS_EXPR
,
1370 size_type_node
, lhsu
, srcu
);
1371 strinfo
*si
= new_strinfo (src
, idx
, length
, true);
1373 set_strinfo (idx
, si
);
1374 find_equal_ptrs (src
, idx
);
1375 zero_length_string (lhs
, si
);
1379 zero_length_string (lhs
, NULL
);
1382 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1383 If strlen of the second argument is known, strlen of the first argument
1384 is the same after this call. Furthermore, attempt to convert it to
1388 handle_builtin_strcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1391 tree src
, dst
, srclen
, len
, lhs
, type
, fn
, oldlen
;
1393 gimple
*stmt
= gsi_stmt (*gsi
);
1394 strinfo
*si
, *dsi
, *olddsi
, *zsi
;
1396 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
1398 src
= gimple_call_arg (stmt
, with_bounds
? 2 : 1);
1399 dst
= gimple_call_arg (stmt
, 0);
1400 lhs
= gimple_call_lhs (stmt
);
1401 idx
= get_stridx (src
);
1404 si
= get_strinfo (idx
);
1406 didx
= get_stridx (dst
);
1410 olddsi
= get_strinfo (didx
);
1415 adjust_last_stmt (olddsi
, stmt
, false);
1419 srclen
= get_string_length (si
);
1421 srclen
= build_int_cst (size_type_node
, ~idx
);
1423 loc
= gimple_location (stmt
);
1424 if (srclen
== NULL_TREE
)
1427 case BUILT_IN_STRCPY
:
1428 case BUILT_IN_STRCPY_CHK
:
1429 case BUILT_IN_STRCPY_CHKP
:
1430 case BUILT_IN_STRCPY_CHK_CHKP
:
1431 if (lhs
!= NULL_TREE
|| !builtin_decl_implicit_p (BUILT_IN_STPCPY
))
1434 case BUILT_IN_STPCPY
:
1435 case BUILT_IN_STPCPY_CHK
:
1436 case BUILT_IN_STPCPY_CHKP
:
1437 case BUILT_IN_STPCPY_CHK_CHKP
:
1438 if (lhs
== NULL_TREE
)
1442 tree lhsuint
= fold_convert_loc (loc
, size_type_node
, lhs
);
1443 srclen
= fold_convert_loc (loc
, size_type_node
, dst
);
1444 srclen
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
1454 didx
= new_stridx (dst
);
1460 oldlen
= olddsi
->nonzero_chars
;
1461 dsi
= unshare_strinfo (olddsi
);
1462 dsi
->nonzero_chars
= srclen
;
1463 dsi
->full_string_p
= (srclen
!= NULL_TREE
);
1464 /* Break the chain, so adjust_related_strinfo on later pointers in
1465 the chain won't adjust this one anymore. */
1468 dsi
->endptr
= NULL_TREE
;
1472 dsi
= new_strinfo (dst
, didx
, srclen
, srclen
!= NULL_TREE
);
1473 set_strinfo (didx
, dsi
);
1474 find_equal_ptrs (dst
, didx
);
1476 dsi
->writable
= true;
1477 dsi
->dont_invalidate
= true;
1479 if (dsi
->nonzero_chars
== NULL_TREE
)
1483 /* If string length of src is unknown, use delayed length
1484 computation. If string lenth of dst will be needed, it
1485 can be computed by transforming this strcpy call into
1486 stpcpy and subtracting dst from the return value. */
1488 /* Look for earlier strings whose length could be determined if
1489 this strcpy is turned into an stpcpy. */
1491 if (dsi
->prev
!= 0 && (chainsi
= verify_related_strinfos (dsi
)) != NULL
)
1493 for (; chainsi
&& chainsi
!= dsi
; chainsi
= get_strinfo (chainsi
->next
))
1495 /* When setting a stmt for delayed length computation
1496 prevent all strinfos through dsi from being
1498 chainsi
= unshare_strinfo (chainsi
);
1499 chainsi
->stmt
= stmt
;
1500 chainsi
->nonzero_chars
= NULL_TREE
;
1501 chainsi
->full_string_p
= false;
1502 chainsi
->endptr
= NULL_TREE
;
1503 chainsi
->dont_invalidate
= true;
1508 /* Try to detect overlap before returning. This catches cases
1509 like strcpy (d, d + n) where n is non-constant whose range
1510 is such that (n <= strlen (d) holds).
1512 OLDDSI->NONZERO_chars may have been reset by this point with
1513 oldlen holding it original value. */
1514 if (olddsi
&& oldlen
)
1516 /* Add 1 for the terminating NUL. */
1517 tree type
= TREE_TYPE (oldlen
);
1518 oldlen
= fold_build2 (PLUS_EXPR
, type
, oldlen
,
1519 build_int_cst (type
, 1));
1520 check_bounds_or_overlap (as_a
<gcall
*>(stmt
), olddsi
->ptr
, src
,
1529 tree adj
= NULL_TREE
;
1530 if (oldlen
== NULL_TREE
)
1532 else if (integer_zerop (oldlen
))
1534 else if (TREE_CODE (oldlen
) == INTEGER_CST
1535 || TREE_CODE (srclen
) == INTEGER_CST
)
1536 adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1537 TREE_TYPE (srclen
), srclen
,
1538 fold_convert_loc (loc
, TREE_TYPE (srclen
),
1540 if (adj
!= NULL_TREE
)
1541 adjust_related_strinfos (loc
, dsi
, adj
);
1545 /* strcpy src may not overlap dst, so src doesn't need to be
1546 invalidated either. */
1548 si
->dont_invalidate
= true;
1554 case BUILT_IN_STRCPY
:
1555 case BUILT_IN_STRCPY_CHKP
:
1556 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
1558 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1560 case BUILT_IN_STRCPY_CHK
:
1561 case BUILT_IN_STRCPY_CHK_CHKP
:
1562 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
1564 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1566 case BUILT_IN_STPCPY
:
1567 case BUILT_IN_STPCPY_CHKP
:
1568 /* This would need adjustment of the lhs (subtract one),
1569 or detection that the trailing '\0' doesn't need to be
1570 written, if it will be immediately overwritten.
1571 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1575 zsi
= zero_length_string (lhs
, dsi
);
1578 case BUILT_IN_STPCPY_CHK
:
1579 case BUILT_IN_STPCPY_CHK_CHKP
:
1580 /* This would need adjustment of the lhs (subtract one),
1581 or detection that the trailing '\0' doesn't need to be
1582 written, if it will be immediately overwritten.
1583 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1587 zsi
= zero_length_string (lhs
, dsi
);
1594 zsi
->dont_invalidate
= true;
1598 tree args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1599 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
1602 type
= size_type_node
;
1604 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
1605 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
, build_int_cst (type
, 1));
1607 /* Set the no-warning bit on the transformed statement? */
1608 bool set_no_warning
= false;
1610 if (const strinfo
*chksi
= olddsi
? olddsi
: dsi
)
1612 && !check_bounds_or_overlap (as_a
<gcall
*>(stmt
), chksi
->ptr
, si
->ptr
,
1615 gimple_set_no_warning (stmt
, true);
1616 set_no_warning
= true;
1619 if (fn
== NULL_TREE
)
1622 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
1624 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1626 fprintf (dump_file
, "Optimizing: ");
1627 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1631 fn
= chkp_maybe_create_clone (fn
)->decl
;
1632 if (gimple_call_num_args (stmt
) == 4)
1633 success
= update_gimple_call (gsi
, fn
, 5, dst
,
1634 gimple_call_arg (stmt
, 1),
1636 gimple_call_arg (stmt
, 3),
1639 success
= update_gimple_call (gsi
, fn
, 6, dst
,
1640 gimple_call_arg (stmt
, 1),
1642 gimple_call_arg (stmt
, 3),
1644 gimple_call_arg (stmt
, 4));
1647 if (gimple_call_num_args (stmt
) == 2)
1648 success
= update_gimple_call (gsi
, fn
, 3, dst
, src
, len
);
1650 success
= update_gimple_call (gsi
, fn
, 4, dst
, src
, len
,
1651 gimple_call_arg (stmt
, 2));
1654 stmt
= gsi_stmt (*gsi
);
1655 gimple_call_set_with_bounds (stmt
, with_bounds
);
1657 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1659 fprintf (dump_file
, "into: ");
1660 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1662 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1663 laststmt
.stmt
= stmt
;
1664 laststmt
.len
= srclen
;
1665 laststmt
.stridx
= dsi
->idx
;
1667 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1668 fprintf (dump_file
, "not possible.\n");
1671 gimple_set_no_warning (stmt
, true);
1674 /* Check the size argument to the built-in forms of stpncpy and strncpy
1675 for out-of-bounds offsets or overlapping access, and to see if the
1676 size argument is derived from a call to strlen() on the source argument,
1677 and if so, issue an appropriate warning. */
1680 handle_builtin_strncat (built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1682 /* Same as stxncpy(). */
1683 handle_builtin_stxncpy (bcode
, gsi
);
1686 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1687 way. LEN can either be an integer expression, or a pointer (to char).
1688 When it is the latter (such as in recursive calls to self) is is
1689 assumed to be the argument in some call to strlen() whose relationship
1690 to SRC is being ascertained. */
1693 is_strlen_related_p (tree src
, tree len
)
1695 if (TREE_CODE (TREE_TYPE (len
)) == POINTER_TYPE
1696 && operand_equal_p (src
, len
, 0))
1699 if (TREE_CODE (len
) != SSA_NAME
)
1702 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1706 if (is_gimple_call (def_stmt
))
1708 tree func
= gimple_call_fndecl (def_stmt
);
1709 if (!valid_builtin_call (def_stmt
)
1710 || DECL_FUNCTION_CODE (func
) != BUILT_IN_STRLEN
)
1713 tree arg
= gimple_call_arg (def_stmt
, 0);
1714 return is_strlen_related_p (src
, arg
);
1717 if (!is_gimple_assign (def_stmt
))
1720 tree_code code
= gimple_assign_rhs_code (def_stmt
);
1721 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1722 tree rhstype
= TREE_TYPE (rhs1
);
1724 if ((TREE_CODE (rhstype
) == POINTER_TYPE
&& code
== POINTER_PLUS_EXPR
)
1725 || (INTEGRAL_TYPE_P (rhstype
)
1726 && (code
== BIT_AND_EXPR
1727 || code
== NOP_EXPR
)))
1729 /* Pointer plus (an integer) and integer cast or truncation are
1730 considered among the (potentially) related expressions to strlen.
1732 return is_strlen_related_p (src
, rhs1
);
1738 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1739 bound is a) equal to the size of the destination DST and if so, b)
1740 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1741 and b) does not, warn. Otherwise, do nothing. Return true if
1742 diagnostic has been issued.
1744 The purpose is to diagnose calls to strncpy and stpncpy that do
1745 not nul-terminate the copy while allowing for the idiom where
1746 such a call is immediately followed by setting the last element
1749 strncpy (a, s, sizeof a);
1750 a[sizeof a - 1] = '\0';
1754 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi
, tree src
, tree cnt
)
1756 gimple
*stmt
= gsi_stmt (gsi
);
1758 wide_int cntrange
[2];
1760 if (TREE_CODE (cnt
) == INTEGER_CST
)
1761 cntrange
[0] = cntrange
[1] = wi::to_wide (cnt
);
1762 else if (TREE_CODE (cnt
) == SSA_NAME
)
1764 enum value_range_type rng
= get_range_info (cnt
, cntrange
, cntrange
+ 1);
1765 if (rng
== VR_RANGE
)
1767 else if (rng
== VR_ANTI_RANGE
)
1769 wide_int maxobjsize
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
));
1771 if (wi::ltu_p (cntrange
[1], maxobjsize
))
1773 cntrange
[0] = cntrange
[1] + 1;
1774 cntrange
[1] = maxobjsize
;
1778 cntrange
[1] = cntrange
[0] - 1;
1779 cntrange
[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt
)));
1788 /* Negative value is the constant string length. If it's less than
1789 the lower bound there is no truncation. */
1790 int sidx
= get_stridx (src
);
1791 if (sidx
< 0 && wi::gtu_p (cntrange
[0], ~sidx
))
1794 tree dst
= gimple_call_arg (stmt
, 0);
1796 if (TREE_CODE (dstdecl
) == ADDR_EXPR
)
1797 dstdecl
= TREE_OPERAND (dstdecl
, 0);
1799 /* If the destination refers to a an array/pointer declared nonstring
1801 tree ref
= NULL_TREE
;
1802 if (get_attr_nonstring_decl (dstdecl
, &ref
))
1805 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1806 avoid the truncation warning. */
1808 gimple
*next_stmt
= gsi_stmt (gsi
);
1810 if (!gsi_end_p (gsi
) && is_gimple_assign (next_stmt
))
1812 tree lhs
= gimple_assign_lhs (next_stmt
);
1813 tree_code code
= TREE_CODE (lhs
);
1814 if (code
== ARRAY_REF
|| code
== MEM_REF
)
1815 lhs
= TREE_OPERAND (lhs
, 0);
1817 tree func
= gimple_call_fndecl (stmt
);
1818 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STPNCPY
)
1820 tree ret
= gimple_call_lhs (stmt
);
1821 if (ret
&& operand_equal_p (ret
, lhs
, 0))
1825 /* Determine the base address and offset of the reference,
1826 ignoring the innermost array index. */
1827 if (TREE_CODE (ref
) == ARRAY_REF
)
1828 ref
= TREE_OPERAND (ref
, 0);
1830 HOST_WIDE_INT dstoff
;
1831 tree dstbase
= get_addr_base_and_unit_offset (ref
, &dstoff
);
1833 HOST_WIDE_INT lhsoff
;
1834 tree lhsbase
= get_addr_base_and_unit_offset (lhs
, &lhsoff
);
1837 && operand_equal_p (dstbase
, lhsbase
, 0))
1841 int prec
= TYPE_PRECISION (TREE_TYPE (cnt
));
1842 wide_int lenrange
[2];
1843 if (strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
)
1845 lenrange
[0] = (sisrc
->nonzero_chars
1846 && TREE_CODE (sisrc
->nonzero_chars
) == INTEGER_CST
1847 ? wi::to_wide (sisrc
->nonzero_chars
)
1849 lenrange
[1] = lenrange
[0];
1852 lenrange
[0] = lenrange
[1] = wi::shwi (~sidx
, prec
);
1856 get_range_strlen (src
, range
);
1859 lenrange
[0] = wi::to_wide (range
[0], prec
);
1860 lenrange
[1] = wi::to_wide (range
[1], prec
);
1864 lenrange
[0] = wi::shwi (0, prec
);
1865 lenrange
[1] = wi::shwi (-1, prec
);
1869 location_t callloc
= gimple_location (stmt
);
1870 tree func
= gimple_call_fndecl (stmt
);
1872 if (lenrange
[0] != 0 || !wi::neg_p (lenrange
[1]))
1874 /* If the longest source string is shorter than the lower bound
1875 of the specified count the copy is definitely nul-terminated. */
1876 if (wi::ltu_p (lenrange
[1], cntrange
[0]))
1879 if (wi::neg_p (lenrange
[1]))
1881 /* The length of one of the strings is unknown but at least
1882 one has non-zero length and that length is stored in
1883 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1885 lenrange
[1] = lenrange
[0];
1886 lenrange
[0] = wi::shwi (0, prec
);
1889 if (wi::geu_p (lenrange
[0], cntrange
[1]))
1891 /* The shortest string is longer than the upper bound of
1892 the count so the truncation is certain. */
1893 if (cntrange
[0] == cntrange
[1])
1894 return warning_at (callloc
, OPT_Wstringop_truncation
,
1896 ? G_("%qD output truncated copying %E byte "
1897 "from a string of length %wu")
1898 : G_("%qD output truncated copying %E bytes "
1899 "from a string of length %wu"),
1900 func
, cnt
, lenrange
[0].to_uhwi ());
1902 return warning_at (callloc
, OPT_Wstringop_truncation
,
1903 "%qD output truncated copying between %wu "
1904 "and %wu bytes from a string of length %wu",
1905 func
, cntrange
[0].to_uhwi (),
1906 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
1908 else if (wi::geu_p (lenrange
[1], cntrange
[1]))
1910 /* The longest string is longer than the upper bound of
1911 the count so the truncation is possible. */
1912 if (cntrange
[0] == cntrange
[1])
1913 return warning_at (callloc
, OPT_Wstringop_truncation
,
1915 ? G_("%qD output may be truncated copying %E "
1916 "byte from a string of length %wu")
1917 : G_("%qD output may be truncated copying %E "
1918 "bytes from a string of length %wu"),
1919 func
, cnt
, lenrange
[1].to_uhwi ());
1921 return warning_at (callloc
, OPT_Wstringop_truncation
,
1922 "%qD output may be truncated copying between %wu "
1923 "and %wu bytes from a string of length %wu",
1924 func
, cntrange
[0].to_uhwi (),
1925 cntrange
[1].to_uhwi (), lenrange
[1].to_uhwi ());
1928 if (cntrange
[0] != cntrange
[1]
1929 && wi::leu_p (cntrange
[0], lenrange
[0])
1930 && wi::leu_p (cntrange
[1], lenrange
[0] + 1))
1932 /* If the source (including the terminating nul) is longer than
1933 the lower bound of the specified count but shorter than the
1934 upper bound the copy may (but need not) be truncated. */
1935 return warning_at (callloc
, OPT_Wstringop_truncation
,
1936 "%qD output may be truncated copying between %wu "
1937 "and %wu bytes from a string of length %wu",
1938 func
, cntrange
[0].to_uhwi (),
1939 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
1943 if (tree dstsize
= compute_objsize (dst
, 1))
1945 /* The source length is uknown. Try to determine the destination
1946 size and see if it matches the specified bound. If not, bail.
1947 Otherwise go on to see if it should be diagnosed for possible
1952 if (wi::to_wide (dstsize
) != cntrange
[1])
1955 if (cntrange
[0] == cntrange
[1])
1956 return warning_at (callloc
, OPT_Wstringop_truncation
,
1957 "%qD specified bound %E equals destination size",
1964 /* Check the arguments to the built-in forms of stpncpy and strncpy for
1965 out-of-bounds offsets or overlapping access, and to see if the size
1966 is derived from calling strlen() on the source argument, and if so,
1967 issue the appropriate warning. */
1970 handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*gsi
)
1972 if (!strlen_to_stridx
)
1975 gimple
*stmt
= gsi_stmt (*gsi
);
1977 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
1979 tree dst
= gimple_call_arg (stmt
, with_bounds
? 1 : 0);
1980 tree src
= gimple_call_arg (stmt
, with_bounds
? 2 : 1);
1981 tree len
= gimple_call_arg (stmt
, with_bounds
? 3 : 2);
1982 tree dstsize
= NULL_TREE
, srcsize
= NULL_TREE
;
1984 int didx
= get_stridx (dst
);
1985 if (strinfo
*sidst
= didx
> 0 ? get_strinfo (didx
) : NULL
)
1987 /* Compute the size of the destination string including the NUL. */
1988 if (sidst
->nonzero_chars
)
1990 tree type
= TREE_TYPE (sidst
->nonzero_chars
);
1991 dstsize
= fold_build2 (PLUS_EXPR
, type
, sidst
->nonzero_chars
,
1992 build_int_cst (type
, 1));
1997 int sidx
= get_stridx (src
);
1998 strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
;
2001 /* strncat() and strncpy() can modify the source string by writing
2002 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2005 /* Compute the size of the source string including the NUL. */
2006 if (sisrc
->nonzero_chars
)
2008 tree type
= TREE_TYPE (sisrc
->nonzero_chars
);
2009 srcsize
= fold_build2 (PLUS_EXPR
, type
, sisrc
->nonzero_chars
,
2010 build_int_cst (type
, 1));
2016 srcsize
= NULL_TREE
;
2018 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, src
,
2021 gimple_set_no_warning (stmt
, true);
2025 /* If the length argument was computed from strlen(S) for some string
2026 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2027 the location of the strlen() call (PSS->SECOND). */
2028 stridx_strlenloc
*pss
= strlen_to_stridx
->get (len
);
2029 if (!pss
|| pss
->first
<= 0)
2031 if (maybe_diag_stxncpy_trunc (*gsi
, src
, len
))
2032 gimple_set_no_warning (stmt
, true);
2037 /* Retrieve the strinfo data for the string S that LEN was computed
2038 from as some function F of strlen (S) (i.e., LEN need not be equal
2040 strinfo
*silen
= get_strinfo (pss
->first
);
2042 location_t callloc
= gimple_location (stmt
);
2044 tree func
= gimple_call_fndecl (stmt
);
2046 bool warned
= false;
2048 /* When -Wstringop-truncation is set, try to determine truncation
2049 before diagnosing possible overflow. Truncation is implied by
2050 the LEN argument being equal to strlen(SRC), regardless of
2051 whether its value is known. Otherwise, issue the more generic
2052 -Wstringop-overflow which triggers for LEN arguments that in
2053 any meaningful way depend on strlen(SRC). */
2055 && is_strlen_related_p (src
, len
)
2056 && warning_at (callloc
, OPT_Wstringop_truncation
,
2057 "%qD output truncated before terminating nul "
2058 "copying as many bytes from a string as its length",
2061 else if (silen
&& is_strlen_related_p (src
, silen
->ptr
))
2062 warned
= warning_at (callloc
, OPT_Wstringop_overflow_
,
2063 "%qD specified bound depends on the length "
2064 "of the source argument", func
);
2067 location_t strlenloc
= pss
->second
;
2068 if (strlenloc
!= UNKNOWN_LOCATION
&& strlenloc
!= callloc
)
2069 inform (strlenloc
, "length computed here");
2073 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2074 If strlen of the second argument is known and length of the third argument
2075 is that plus one, strlen of the first argument is the same after this
2079 handle_builtin_memcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2082 tree src
, dst
, len
, lhs
, oldlen
, newlen
;
2083 gimple
*stmt
= gsi_stmt (*gsi
);
2084 strinfo
*si
, *dsi
, *olddsi
;
2085 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
2087 len
= gimple_call_arg (stmt
, with_bounds
? 4 : 2);
2088 src
= gimple_call_arg (stmt
, with_bounds
? 2 : 1);
2089 dst
= gimple_call_arg (stmt
, 0);
2090 idx
= get_stridx (src
);
2094 didx
= get_stridx (dst
);
2097 olddsi
= get_strinfo (didx
);
2102 && tree_fits_uhwi_p (len
)
2103 && !integer_zerop (len
))
2104 adjust_last_stmt (olddsi
, stmt
, false);
2111 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2113 si
= get_strinfo (idx
);
2114 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2116 if (TREE_CODE (len
) == INTEGER_CST
2117 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
2119 if (tree_int_cst_le (len
, si
->nonzero_chars
))
2121 /* Copying LEN nonzero characters, where LEN is constant. */
2123 full_string_p
= false;
2127 /* Copying the whole of the analyzed part of SI. */
2128 newlen
= si
->nonzero_chars
;
2129 full_string_p
= si
->full_string_p
;
2134 if (!si
->full_string_p
)
2136 if (TREE_CODE (len
) != SSA_NAME
)
2138 def_stmt
= SSA_NAME_DEF_STMT (len
);
2139 if (!is_gimple_assign (def_stmt
)
2140 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
2141 || gimple_assign_rhs1 (def_stmt
) != si
->nonzero_chars
2142 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
2144 /* Copying variable-length string SI (and no more). */
2145 newlen
= si
->nonzero_chars
;
2146 full_string_p
= true;
2152 /* Handle memcpy (x, "abcd", 5) or
2153 memcpy (x, "abc\0uvw", 7). */
2154 if (!tree_fits_uhwi_p (len
))
2157 unsigned HOST_WIDE_INT clen
= tree_to_uhwi (len
);
2158 unsigned HOST_WIDE_INT nonzero_chars
= ~idx
;
2159 newlen
= build_int_cst (size_type_node
, MIN (nonzero_chars
, clen
));
2160 full_string_p
= clen
> nonzero_chars
;
2163 if (olddsi
!= NULL
&& TREE_CODE (len
) == SSA_NAME
)
2164 adjust_last_stmt (olddsi
, stmt
, false);
2168 didx
= new_stridx (dst
);
2175 dsi
= unshare_strinfo (olddsi
);
2176 oldlen
= olddsi
->nonzero_chars
;
2177 dsi
->nonzero_chars
= newlen
;
2178 dsi
->full_string_p
= full_string_p
;
2179 /* Break the chain, so adjust_related_strinfo on later pointers in
2180 the chain won't adjust this one anymore. */
2183 dsi
->endptr
= NULL_TREE
;
2187 dsi
= new_strinfo (dst
, didx
, newlen
, full_string_p
);
2188 set_strinfo (didx
, dsi
);
2189 find_equal_ptrs (dst
, didx
);
2191 dsi
->writable
= true;
2192 dsi
->dont_invalidate
= true;
2195 tree adj
= NULL_TREE
;
2196 location_t loc
= gimple_location (stmt
);
2197 if (oldlen
== NULL_TREE
)
2199 else if (integer_zerop (oldlen
))
2201 else if (TREE_CODE (oldlen
) == INTEGER_CST
2202 || TREE_CODE (newlen
) == INTEGER_CST
)
2203 adj
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (newlen
), newlen
,
2204 fold_convert_loc (loc
, TREE_TYPE (newlen
),
2206 if (adj
!= NULL_TREE
)
2207 adjust_related_strinfos (loc
, dsi
, adj
);
2211 /* memcpy src may not overlap dst, so src doesn't need to be
2212 invalidated either. */
2214 si
->dont_invalidate
= true;
2218 lhs
= gimple_call_lhs (stmt
);
2221 case BUILT_IN_MEMCPY
:
2222 case BUILT_IN_MEMCPY_CHK
:
2223 case BUILT_IN_MEMCPY_CHKP
:
2224 case BUILT_IN_MEMCPY_CHK_CHKP
:
2225 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2226 laststmt
.stmt
= stmt
;
2227 laststmt
.len
= dsi
->nonzero_chars
;
2228 laststmt
.stridx
= dsi
->idx
;
2230 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
2232 case BUILT_IN_MEMPCPY
:
2233 case BUILT_IN_MEMPCPY_CHK
:
2234 case BUILT_IN_MEMPCPY_CHKP
:
2235 case BUILT_IN_MEMPCPY_CHK_CHKP
:
2243 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2244 If strlen of the second argument is known, strlen of the first argument
2245 is increased by the length of the second argument. Furthermore, attempt
2246 to convert it to memcpy/strcpy if the length of the first argument
2250 handle_builtin_strcat (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2253 tree srclen
, args
, type
, fn
, objsz
, endptr
;
2255 gimple
*stmt
= gsi_stmt (*gsi
);
2257 location_t loc
= gimple_location (stmt
);
2258 bool with_bounds
= gimple_call_with_bounds_p (stmt
);
2260 tree src
= gimple_call_arg (stmt
, with_bounds
? 2 : 1);
2261 tree dst
= gimple_call_arg (stmt
, 0);
2263 /* Bail if the source is the same as destination. It will be diagnosed
2265 if (operand_equal_p (src
, dst
, 0))
2268 tree lhs
= gimple_call_lhs (stmt
);
2270 didx
= get_stridx (dst
);
2276 dsi
= get_strinfo (didx
);
2280 idx
= get_stridx (src
);
2282 srclen
= build_int_cst (size_type_node
, ~idx
);
2285 si
= get_strinfo (idx
);
2287 srclen
= get_string_length (si
);
2290 /* Set the no-warning bit on the transformed statement? */
2291 bool set_no_warning
= false;
2293 if (dsi
== NULL
|| get_string_length (dsi
) == NULL_TREE
)
2296 /* The concatenation always involves copying at least one byte
2297 (the terminating nul), even if the source string is empty.
2298 If the source is unknown assume it's one character long and
2299 used that as both sizes. */
2303 tree type
= TREE_TYPE (slen
);
2304 slen
= fold_build2 (PLUS_EXPR
, type
, slen
, build_int_cst (type
, 1));
2307 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2309 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2312 gimple_set_no_warning (stmt
, true);
2313 set_no_warning
= true;
2317 /* strcat (p, q) can be transformed into
2318 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2319 with length endptr - p if we need to compute the length
2320 later on. Don't do this transformation if we don't need
2322 if (builtin_decl_implicit_p (BUILT_IN_STPCPY
) && lhs
== NULL_TREE
)
2326 didx
= new_stridx (dst
);
2332 dsi
= new_strinfo (dst
, didx
, NULL_TREE
, false);
2333 set_strinfo (didx
, dsi
);
2334 find_equal_ptrs (dst
, didx
);
2338 dsi
= unshare_strinfo (dsi
);
2339 dsi
->nonzero_chars
= NULL_TREE
;
2340 dsi
->full_string_p
= false;
2342 dsi
->endptr
= NULL_TREE
;
2344 dsi
->writable
= true;
2346 dsi
->dont_invalidate
= true;
2351 tree dstlen
= dsi
->nonzero_chars
;
2352 endptr
= dsi
->endptr
;
2354 dsi
= unshare_strinfo (dsi
);
2355 dsi
->endptr
= NULL_TREE
;
2357 dsi
->writable
= true;
2359 if (srclen
!= NULL_TREE
)
2361 dsi
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
2362 TREE_TYPE (dsi
->nonzero_chars
),
2363 dsi
->nonzero_chars
, srclen
);
2364 gcc_assert (dsi
->full_string_p
);
2365 adjust_related_strinfos (loc
, dsi
, srclen
);
2366 dsi
->dont_invalidate
= true;
2370 dsi
->nonzero_chars
= NULL
;
2371 dsi
->full_string_p
= false;
2372 if (lhs
== NULL_TREE
&& builtin_decl_implicit_p (BUILT_IN_STPCPY
))
2373 dsi
->dont_invalidate
= true;
2377 /* strcat src may not overlap dst, so src doesn't need to be
2378 invalidated either. */
2379 si
->dont_invalidate
= true;
2381 /* For now. Could remove the lhs from the call and add
2382 lhs = dst; afterwards. */
2390 case BUILT_IN_STRCAT
:
2391 case BUILT_IN_STRCAT_CHKP
:
2392 if (srclen
!= NULL_TREE
)
2393 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
2395 fn
= builtin_decl_implicit (BUILT_IN_STRCPY
);
2397 case BUILT_IN_STRCAT_CHK
:
2398 case BUILT_IN_STRCAT_CHK_CHKP
:
2399 if (srclen
!= NULL_TREE
)
2400 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
2402 fn
= builtin_decl_explicit (BUILT_IN_STRCPY_CHK
);
2403 objsz
= gimple_call_arg (stmt
, with_bounds
? 4 : 2);
2409 if (fn
== NULL_TREE
)
2414 tree type
= TREE_TYPE (dstlen
);
2416 /* Compute the size of the source sequence, including the nul. */
2417 tree srcsize
= srclen
? srclen
: size_zero_node
;
2418 srcsize
= fold_build2 (PLUS_EXPR
, type
, srcsize
, build_int_cst (type
, 1));
2420 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2422 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2425 gimple_set_no_warning (stmt
, true);
2426 set_no_warning
= true;
2430 tree len
= NULL_TREE
;
2431 if (srclen
!= NULL_TREE
)
2433 args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2434 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
2436 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
2437 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
,
2438 build_int_cst (type
, 1));
2439 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
2443 dst
= fold_convert_loc (loc
, TREE_TYPE (dst
), unshare_expr (endptr
));
2445 dst
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
2446 TREE_TYPE (dst
), unshare_expr (dst
),
2447 fold_convert_loc (loc
, sizetype
,
2448 unshare_expr (dstlen
)));
2449 dst
= force_gimple_operand_gsi (gsi
, dst
, true, NULL_TREE
, true,
2451 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2453 fprintf (dump_file
, "Optimizing: ");
2454 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2458 fn
= chkp_maybe_create_clone (fn
)->decl
;
2459 if (srclen
!= NULL_TREE
)
2460 success
= update_gimple_call (gsi
, fn
, 5 + (objsz
!= NULL_TREE
),
2462 gimple_call_arg (stmt
, 1),
2464 gimple_call_arg (stmt
, 3),
2467 success
= update_gimple_call (gsi
, fn
, 4 + (objsz
!= NULL_TREE
),
2469 gimple_call_arg (stmt
, 1),
2471 gimple_call_arg (stmt
, 3),
2475 if (srclen
!= NULL_TREE
)
2476 success
= update_gimple_call (gsi
, fn
, 3 + (objsz
!= NULL_TREE
),
2477 dst
, src
, len
, objsz
);
2479 success
= update_gimple_call (gsi
, fn
, 2 + (objsz
!= NULL_TREE
),
2483 stmt
= gsi_stmt (*gsi
);
2484 gimple_call_set_with_bounds (stmt
, with_bounds
);
2486 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2488 fprintf (dump_file
, "into: ");
2489 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2491 /* If srclen == NULL, note that current string length can be
2492 computed by transforming this strcpy into stpcpy. */
2493 if (srclen
== NULL_TREE
&& dsi
->dont_invalidate
)
2495 adjust_last_stmt (dsi
, stmt
, true);
2496 if (srclen
!= NULL_TREE
)
2498 laststmt
.stmt
= stmt
;
2499 laststmt
.len
= srclen
;
2500 laststmt
.stridx
= dsi
->idx
;
2503 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2504 fprintf (dump_file
, "not possible.\n");
2507 gimple_set_no_warning (stmt
, true);
2510 /* Handle a call to malloc or calloc. */
2513 handle_builtin_malloc (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2515 gimple
*stmt
= gsi_stmt (*gsi
);
2516 tree lhs
= gimple_call_lhs (stmt
);
2517 if (lhs
== NULL_TREE
)
2520 gcc_assert (get_stridx (lhs
) == 0);
2521 int idx
= new_stridx (lhs
);
2522 tree length
= NULL_TREE
;
2523 if (bcode
== BUILT_IN_CALLOC
)
2524 length
= build_int_cst (size_type_node
, 0);
2525 strinfo
*si
= new_strinfo (lhs
, idx
, length
, length
!= NULL_TREE
);
2526 if (bcode
== BUILT_IN_CALLOC
)
2528 set_strinfo (idx
, si
);
2529 si
->writable
= true;
2531 si
->dont_invalidate
= true;
2534 /* Handle a call to memset.
2535 After a call to calloc, memset(,0,) is unnecessary.
2536 memset(malloc(n),0,n) is calloc(n,1). */
2539 handle_builtin_memset (gimple_stmt_iterator
*gsi
)
2541 gimple
*stmt2
= gsi_stmt (*gsi
);
2542 if (!integer_zerop (gimple_call_arg (stmt2
, 1)))
2544 tree ptr
= gimple_call_arg (stmt2
, 0);
2545 int idx1
= get_stridx (ptr
);
2548 strinfo
*si1
= get_strinfo (idx1
);
2551 gimple
*stmt1
= si1
->stmt
;
2552 if (!stmt1
|| !is_gimple_call (stmt1
))
2554 tree callee1
= gimple_call_fndecl (stmt1
);
2555 if (!valid_builtin_call (stmt1
))
2557 enum built_in_function code1
= DECL_FUNCTION_CODE (callee1
);
2558 tree size
= gimple_call_arg (stmt2
, 2);
2559 if (code1
== BUILT_IN_CALLOC
)
2560 /* Not touching stmt1 */ ;
2561 else if (code1
== BUILT_IN_MALLOC
2562 && operand_equal_p (gimple_call_arg (stmt1
, 0), size
, 0))
2564 gimple_stmt_iterator gsi1
= gsi_for_stmt (stmt1
);
2565 update_gimple_call (&gsi1
, builtin_decl_implicit (BUILT_IN_CALLOC
), 2,
2566 size
, build_one_cst (size_type_node
));
2567 si1
->nonzero_chars
= build_int_cst (size_type_node
, 0);
2568 si1
->full_string_p
= true;
2569 si1
->stmt
= gsi_stmt (gsi1
);
2573 tree lhs
= gimple_call_lhs (stmt2
);
2574 unlink_stmt_vdef (stmt2
);
2577 gimple
*assign
= gimple_build_assign (lhs
, ptr
);
2578 gsi_replace (gsi
, assign
, false);
2582 gsi_remove (gsi
, true);
2583 release_defs (stmt2
);
2589 /* Handle a call to memcmp. We try to handle small comparisons by
2590 converting them to load and compare, and replacing the call to memcmp
2591 with a __builtin_memcmp_eq call where possible. */
2594 handle_builtin_memcmp (gimple_stmt_iterator
*gsi
)
2596 gcall
*stmt2
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2597 tree res
= gimple_call_lhs (stmt2
);
2598 tree arg1
= gimple_call_arg (stmt2
, 0);
2599 tree arg2
= gimple_call_arg (stmt2
, 1);
2600 tree len
= gimple_call_arg (stmt2
, 2);
2601 unsigned HOST_WIDE_INT leni
;
2602 use_operand_p use_p
;
2603 imm_use_iterator iter
;
2608 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2610 gimple
*ustmt
= USE_STMT (use_p
);
2612 if (is_gimple_debug (ustmt
))
2614 if (gimple_code (ustmt
) == GIMPLE_ASSIGN
)
2616 gassign
*asgn
= as_a
<gassign
*> (ustmt
);
2617 tree_code code
= gimple_assign_rhs_code (asgn
);
2618 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2619 || !integer_zerop (gimple_assign_rhs2 (asgn
)))
2622 else if (gimple_code (ustmt
) == GIMPLE_COND
)
2624 tree_code code
= gimple_cond_code (ustmt
);
2625 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2626 || !integer_zerop (gimple_cond_rhs (ustmt
)))
2633 if (tree_fits_uhwi_p (len
)
2634 && (leni
= tree_to_uhwi (len
)) <= GET_MODE_SIZE (word_mode
)
2635 && pow2p_hwi (leni
))
2637 leni
*= CHAR_TYPE_SIZE
;
2638 unsigned align1
= get_pointer_alignment (arg1
);
2639 unsigned align2
= get_pointer_alignment (arg2
);
2640 unsigned align
= MIN (align1
, align2
);
2641 scalar_int_mode mode
;
2642 if (int_mode_for_size (leni
, 1).exists (&mode
)
2643 && (align
>= leni
|| !targetm
.slow_unaligned_access (mode
, align
)))
2645 location_t loc
= gimple_location (stmt2
);
2647 type
= build_nonstandard_integer_type (leni
, 1);
2648 gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type
)) == leni
);
2649 tree ptrtype
= build_pointer_type_for_mode (char_type_node
,
2651 off
= build_int_cst (ptrtype
, 0);
2652 arg1
= build2_loc (loc
, MEM_REF
, type
, arg1
, off
);
2653 arg2
= build2_loc (loc
, MEM_REF
, type
, arg2
, off
);
2654 tree tem1
= fold_const_aggregate_ref (arg1
);
2657 tree tem2
= fold_const_aggregate_ref (arg2
);
2660 res
= fold_convert_loc (loc
, TREE_TYPE (res
),
2661 fold_build2_loc (loc
, NE_EXPR
,
2664 gimplify_and_update_call_from_tree (gsi
, res
);
2669 gimple_call_set_fndecl (stmt2
, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ
));
2673 /* Handle a POINTER_PLUS_EXPR statement.
2674 For p = "abcd" + 2; compute associated length, or if
2675 p = q + off is pointing to a '\0' character of a string, call
2676 zero_length_string on it. */
2679 handle_pointer_plus (gimple_stmt_iterator
*gsi
)
2681 gimple
*stmt
= gsi_stmt (*gsi
);
2682 tree lhs
= gimple_assign_lhs (stmt
), off
;
2683 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
2691 tree off
= gimple_assign_rhs2 (stmt
);
2692 if (tree_fits_uhwi_p (off
)
2693 && tree_to_uhwi (off
) <= (unsigned HOST_WIDE_INT
) ~idx
)
2694 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)]
2695 = ~(~idx
- (int) tree_to_uhwi (off
));
2699 si
= get_strinfo (idx
);
2700 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2703 off
= gimple_assign_rhs2 (stmt
);
2705 if (si
->full_string_p
&& operand_equal_p (si
->nonzero_chars
, off
, 0))
2706 zsi
= zero_length_string (lhs
, si
);
2707 else if (TREE_CODE (off
) == SSA_NAME
)
2709 gimple
*def_stmt
= SSA_NAME_DEF_STMT (off
);
2710 if (gimple_assign_single_p (def_stmt
)
2711 && si
->full_string_p
2712 && operand_equal_p (si
->nonzero_chars
,
2713 gimple_assign_rhs1 (def_stmt
), 0))
2714 zsi
= zero_length_string (lhs
, si
);
2717 && si
->endptr
!= NULL_TREE
2718 && si
->endptr
!= lhs
2719 && TREE_CODE (si
->endptr
) == SSA_NAME
)
2721 enum tree_code rhs_code
2722 = useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (si
->endptr
))
2723 ? SSA_NAME
: NOP_EXPR
;
2724 gimple_assign_set_rhs_with_ops (gsi
, rhs_code
, si
->endptr
);
2725 gcc_assert (gsi_stmt (*gsi
) == stmt
);
2730 /* Handle a single character store. */
2733 handle_char_store (gimple_stmt_iterator
*gsi
)
2737 gimple
*stmt
= gsi_stmt (*gsi
);
2738 tree ssaname
= NULL_TREE
, lhs
= gimple_assign_lhs (stmt
);
2739 tree rhs
= gimple_assign_rhs1 (stmt
);
2740 unsigned HOST_WIDE_INT offset
= 0;
2742 if (TREE_CODE (lhs
) == MEM_REF
2743 && TREE_CODE (TREE_OPERAND (lhs
, 0)) == SSA_NAME
)
2745 tree mem_offset
= TREE_OPERAND (lhs
, 1);
2746 if (tree_fits_uhwi_p (mem_offset
))
2748 /* Get the strinfo for the base, and use it if it starts with at
2749 least OFFSET nonzero characters. This is trivially true if
2751 offset
= tree_to_uhwi (mem_offset
);
2752 idx
= get_stridx (TREE_OPERAND (lhs
, 0));
2754 si
= get_strinfo (idx
);
2756 ssaname
= TREE_OPERAND (lhs
, 0);
2757 else if (si
== NULL
|| compare_nonzero_chars (si
, offset
) < 0)
2763 idx
= get_addr_stridx (lhs
, NULL_TREE
, &offset
);
2765 si
= get_strinfo (idx
);
2768 bool storing_zero_p
= initializer_zerop (rhs
);
2769 bool storing_nonzero_p
= (!storing_zero_p
2770 && TREE_CODE (rhs
) == INTEGER_CST
2771 && integer_nonzerop (rhs
));
2775 int cmp
= compare_nonzero_chars (si
, offset
);
2776 gcc_assert (offset
== 0 || cmp
>= 0);
2777 if (storing_zero_p
&& cmp
== 0 && si
->full_string_p
)
2779 /* When overwriting a '\0' with a '\0', the store can be removed
2780 if we know it has been stored in the current function. */
2781 if (!stmt_could_throw_p (stmt
) && si
->writable
)
2783 unlink_stmt_vdef (stmt
);
2784 release_defs (stmt
);
2785 gsi_remove (gsi
, true);
2790 si
->writable
= true;
2795 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2796 and if we aren't storing '\0', we know that the length of the
2797 string and any other zero terminated string in memory remains
2798 the same. In that case we move to the next gimple statement and
2799 return to signal the caller that it shouldn't invalidate anything.
2801 This is benefical for cases like:
2806 strcpy (p, "foobar");
2807 size_t len = strlen (p); // This can be optimized into 6
2808 size_t len2 = strlen (q); // This has to be computed
2810 size_t len3 = strlen (p); // This can be optimized into 6
2811 size_t len4 = strlen (q); // This can be optimized into len2
2812 bar (len, len2, len3, len4);
2815 else if (storing_nonzero_p
&& cmp
> 0)
2820 else if (storing_zero_p
|| storing_nonzero_p
|| (offset
!= 0 && cmp
> 0))
2822 /* When storing_nonzero_p, we know that the string now starts
2823 with OFFSET + 1 nonzero characters, but don't know whether
2824 there's a following nul terminator.
2826 When storing_zero_p, we know that the string is now OFFSET
2829 Otherwise, we're storing an unknown value at offset OFFSET,
2830 so need to clip the nonzero_chars to OFFSET. */
2831 location_t loc
= gimple_location (stmt
);
2832 tree oldlen
= si
->nonzero_chars
;
2833 if (cmp
== 0 && si
->full_string_p
)
2834 /* We're overwriting the nul terminator with a nonzero or
2835 unknown character. If the previous stmt was a memcpy,
2836 its length may be decreased. */
2837 adjust_last_stmt (si
, stmt
, false);
2838 si
= unshare_strinfo (si
);
2839 if (storing_nonzero_p
)
2840 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
+ 1);
2842 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
);
2843 si
->full_string_p
= storing_zero_p
;
2846 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
2847 si
->endptr
= ssaname
;
2852 si
->writable
= true;
2853 si
->dont_invalidate
= true;
2856 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
2857 si
->nonzero_chars
, oldlen
);
2858 adjust_related_strinfos (loc
, si
, adj
);
2864 else if (idx
== 0 && (storing_zero_p
|| storing_nonzero_p
))
2867 idx
= new_stridx (ssaname
);
2869 idx
= new_addr_stridx (lhs
);
2872 tree ptr
= (ssaname
? ssaname
: build_fold_addr_expr (lhs
));
2873 tree len
= storing_nonzero_p
? size_one_node
: size_zero_node
;
2874 si
= new_strinfo (ptr
, idx
, len
, storing_zero_p
);
2875 set_strinfo (idx
, si
);
2878 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
2879 si
->endptr
= ssaname
;
2880 si
->dont_invalidate
= true;
2881 si
->writable
= true;
2885 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == STRING_CST
2886 && ssaname
== NULL_TREE
2887 && TREE_CODE (TREE_TYPE (lhs
)) == ARRAY_TYPE
)
2889 size_t l
= strlen (TREE_STRING_POINTER (gimple_assign_rhs1 (stmt
)));
2890 HOST_WIDE_INT a
= int_size_in_bytes (TREE_TYPE (lhs
));
2891 if (a
> 0 && (unsigned HOST_WIDE_INT
) a
> l
)
2893 int idx
= new_addr_stridx (lhs
);
2896 si
= new_strinfo (build_fold_addr_expr (lhs
), idx
,
2897 build_int_cst (size_type_node
, l
), true);
2898 set_strinfo (idx
, si
);
2899 si
->dont_invalidate
= true;
2904 if (si
!= NULL
&& offset
== 0 && storing_zero_p
)
2906 /* Allow adjust_last_stmt to remove it if the stored '\0'
2907 is immediately overwritten. */
2908 laststmt
.stmt
= stmt
;
2909 laststmt
.len
= build_int_cst (size_type_node
, 1);
2910 laststmt
.stridx
= si
->idx
;
2915 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
2918 fold_strstr_to_strncmp (tree rhs1
, tree rhs2
, gimple
*stmt
)
2920 if (TREE_CODE (rhs1
) != SSA_NAME
2921 || TREE_CODE (rhs2
) != SSA_NAME
)
2924 gimple
*call_stmt
= NULL
;
2925 for (int pass
= 0; pass
< 2; pass
++)
2927 gimple
*g
= SSA_NAME_DEF_STMT (rhs1
);
2928 if (gimple_call_builtin_p (g
, BUILT_IN_STRSTR
)
2929 && has_single_use (rhs1
)
2930 && gimple_call_arg (g
, 0) == rhs2
)
2935 std::swap (rhs1
, rhs2
);
2940 tree arg0
= gimple_call_arg (call_stmt
, 0);
2944 tree arg1
= gimple_call_arg (call_stmt
, 1);
2945 tree arg1_len
= NULL_TREE
;
2946 int idx
= get_stridx (arg1
);
2951 arg1_len
= build_int_cst (size_type_node
, ~idx
);
2954 strinfo
*si
= get_strinfo (idx
);
2956 arg1_len
= get_string_length (si
);
2960 if (arg1_len
!= NULL_TREE
)
2962 gimple_stmt_iterator gsi
= gsi_for_stmt (call_stmt
);
2963 tree strncmp_decl
= builtin_decl_explicit (BUILT_IN_STRNCMP
);
2964 gcall
*strncmp_call
= gimple_build_call (strncmp_decl
, 3,
2965 arg0
, arg1
, arg1_len
);
2966 tree strncmp_lhs
= make_ssa_name (integer_type_node
);
2967 gimple_set_vuse (strncmp_call
, gimple_vuse (call_stmt
));
2968 gimple_call_set_lhs (strncmp_call
, strncmp_lhs
);
2969 gsi_remove (&gsi
, true);
2970 gsi_insert_before (&gsi
, strncmp_call
, GSI_SAME_STMT
);
2971 tree zero
= build_zero_cst (TREE_TYPE (strncmp_lhs
));
2973 if (is_gimple_assign (stmt
))
2975 if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
2977 tree cond
= gimple_assign_rhs1 (stmt
);
2978 TREE_OPERAND (cond
, 0) = strncmp_lhs
;
2979 TREE_OPERAND (cond
, 1) = zero
;
2983 gimple_assign_set_rhs1 (stmt
, strncmp_lhs
);
2984 gimple_assign_set_rhs2 (stmt
, zero
);
2989 gcond
*cond
= as_a
<gcond
*> (stmt
);
2990 gimple_cond_set_lhs (cond
, strncmp_lhs
);
2991 gimple_cond_set_rhs (cond
, zero
);
2999 /* Attempt to check for validity of the performed access a single statement
3000 at *GSI using string length knowledge, and to optimize it. */
3003 strlen_check_and_optimize_stmt (gimple_stmt_iterator
*gsi
)
3005 gimple
*stmt
= gsi_stmt (*gsi
);
3007 if (is_gimple_call (stmt
))
3009 tree callee
= gimple_call_fndecl (stmt
);
3010 if (valid_builtin_call (stmt
))
3011 switch (DECL_FUNCTION_CODE (callee
))
3013 case BUILT_IN_STRLEN
:
3014 case BUILT_IN_STRLEN_CHKP
:
3015 handle_builtin_strlen (gsi
);
3017 case BUILT_IN_STRCHR
:
3018 case BUILT_IN_STRCHR_CHKP
:
3019 handle_builtin_strchr (gsi
);
3021 case BUILT_IN_STRCPY
:
3022 case BUILT_IN_STRCPY_CHK
:
3023 case BUILT_IN_STPCPY
:
3024 case BUILT_IN_STPCPY_CHK
:
3025 case BUILT_IN_STRCPY_CHKP
:
3026 case BUILT_IN_STRCPY_CHK_CHKP
:
3027 case BUILT_IN_STPCPY_CHKP
:
3028 case BUILT_IN_STPCPY_CHK_CHKP
:
3029 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3032 case BUILT_IN_STRNCAT
:
3033 case BUILT_IN_STRNCAT_CHK
:
3034 handle_builtin_strncat (DECL_FUNCTION_CODE (callee
), gsi
);
3037 case BUILT_IN_STPNCPY
:
3038 case BUILT_IN_STPNCPY_CHK
:
3039 case BUILT_IN_STRNCPY
:
3040 case BUILT_IN_STRNCPY_CHK
:
3041 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee
), gsi
);
3044 case BUILT_IN_MEMCPY
:
3045 case BUILT_IN_MEMCPY_CHK
:
3046 case BUILT_IN_MEMPCPY
:
3047 case BUILT_IN_MEMPCPY_CHK
:
3048 case BUILT_IN_MEMCPY_CHKP
:
3049 case BUILT_IN_MEMCPY_CHK_CHKP
:
3050 case BUILT_IN_MEMPCPY_CHKP
:
3051 case BUILT_IN_MEMPCPY_CHK_CHKP
:
3052 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3054 case BUILT_IN_STRCAT
:
3055 case BUILT_IN_STRCAT_CHK
:
3056 case BUILT_IN_STRCAT_CHKP
:
3057 case BUILT_IN_STRCAT_CHK_CHKP
:
3058 handle_builtin_strcat (DECL_FUNCTION_CODE (callee
), gsi
);
3060 case BUILT_IN_MALLOC
:
3061 case BUILT_IN_CALLOC
:
3062 handle_builtin_malloc (DECL_FUNCTION_CODE (callee
), gsi
);
3064 case BUILT_IN_MEMSET
:
3065 if (!handle_builtin_memset (gsi
))
3068 case BUILT_IN_MEMCMP
:
3069 if (!handle_builtin_memcmp (gsi
))
3076 else if (is_gimple_assign (stmt
) && !gimple_clobber_p (stmt
))
3078 tree lhs
= gimple_assign_lhs (stmt
);
3080 if (TREE_CODE (lhs
) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (lhs
)))
3082 if (gimple_assign_single_p (stmt
)
3083 || (gimple_assign_cast_p (stmt
)
3084 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt
)))))
3086 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3087 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = idx
;
3089 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
3090 handle_pointer_plus (gsi
);
3092 else if (TREE_CODE (lhs
) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
3094 enum tree_code code
= gimple_assign_rhs_code (stmt
);
3095 if (code
== COND_EXPR
)
3097 tree cond
= gimple_assign_rhs1 (stmt
);
3098 enum tree_code cond_code
= TREE_CODE (cond
);
3100 if (cond_code
== EQ_EXPR
|| cond_code
== NE_EXPR
)
3101 fold_strstr_to_strncmp (TREE_OPERAND (cond
, 0),
3102 TREE_OPERAND (cond
, 1), stmt
);
3104 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3105 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt
),
3106 gimple_assign_rhs2 (stmt
), stmt
);
3108 if (strlen_to_stridx
)
3110 tree rhs1
= gimple_assign_rhs1 (stmt
);
3111 if (stridx_strlenloc
*ps
= strlen_to_stridx
->get (rhs1
))
3112 strlen_to_stridx
->put (lhs
, stridx_strlenloc (*ps
));
3115 else if (TREE_CODE (lhs
) != SSA_NAME
&& !TREE_SIDE_EFFECTS (lhs
))
3117 tree type
= TREE_TYPE (lhs
);
3118 if (TREE_CODE (type
) == ARRAY_TYPE
)
3119 type
= TREE_TYPE (type
);
3120 if (TREE_CODE (type
) == INTEGER_TYPE
3121 && TYPE_MODE (type
) == TYPE_MODE (char_type_node
)
3122 && TYPE_PRECISION (type
) == TYPE_PRECISION (char_type_node
))
3124 if (! handle_char_store (gsi
))
3129 else if (gcond
*cond
= dyn_cast
<gcond
*> (stmt
))
3131 enum tree_code code
= gimple_cond_code (cond
);
3132 if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3133 fold_strstr_to_strncmp (gimple_cond_lhs (stmt
),
3134 gimple_cond_rhs (stmt
), stmt
);
3137 if (gimple_vdef (stmt
))
3138 maybe_invalidate (stmt
);
3142 /* Recursively call maybe_invalidate on stmts that might be executed
3143 in between dombb and current bb and that contain a vdef. Stop when
3144 *count stmts are inspected, or if the whole strinfo vector has
3145 been invalidated. */
3148 do_invalidate (basic_block dombb
, gimple
*phi
, bitmap visited
, int *count
)
3150 unsigned int i
, n
= gimple_phi_num_args (phi
);
3152 for (i
= 0; i
< n
; i
++)
3154 tree vuse
= gimple_phi_arg_def (phi
, i
);
3155 gimple
*stmt
= SSA_NAME_DEF_STMT (vuse
);
3156 basic_block bb
= gimple_bb (stmt
);
3159 || !bitmap_set_bit (visited
, bb
->index
)
3160 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3164 if (gimple_code (stmt
) == GIMPLE_PHI
)
3166 do_invalidate (dombb
, stmt
, visited
, count
);
3173 if (!maybe_invalidate (stmt
))
3178 vuse
= gimple_vuse (stmt
);
3179 stmt
= SSA_NAME_DEF_STMT (vuse
);
3180 if (gimple_bb (stmt
) != bb
)
3182 bb
= gimple_bb (stmt
);
3185 || !bitmap_set_bit (visited
, bb
->index
)
3186 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3193 class strlen_dom_walker
: public dom_walker
3196 strlen_dom_walker (cdi_direction direction
) : dom_walker (direction
) {}
3198 virtual edge
before_dom_children (basic_block
);
3199 virtual void after_dom_children (basic_block
);
3202 /* Callback for walk_dominator_tree. Attempt to optimize various
3203 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3206 strlen_dom_walker::before_dom_children (basic_block bb
)
3208 basic_block dombb
= get_immediate_dominator (CDI_DOMINATORS
, bb
);
3211 stridx_to_strinfo
= NULL
;
3214 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) dombb
->aux
);
3215 if (stridx_to_strinfo
)
3217 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3220 gphi
*phi
= gsi
.phi ();
3221 if (virtual_operand_p (gimple_phi_result (phi
)))
3223 bitmap visited
= BITMAP_ALLOC (NULL
);
3224 int count_vdef
= 100;
3225 do_invalidate (dombb
, phi
, visited
, &count_vdef
);
3226 BITMAP_FREE (visited
);
3227 if (count_vdef
== 0)
3229 /* If there were too many vdefs in between immediate
3230 dominator and current bb, invalidate everything.
3231 If stridx_to_strinfo has been unshared, we need
3232 to free it, otherwise just set it to NULL. */
3233 if (!strinfo_shared ())
3239 vec_safe_iterate (stridx_to_strinfo
, i
, &si
);
3243 (*stridx_to_strinfo
)[i
] = NULL
;
3247 stridx_to_strinfo
= NULL
;
3255 /* If all PHI arguments have the same string index, the PHI result
3257 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3260 gphi
*phi
= gsi
.phi ();
3261 tree result
= gimple_phi_result (phi
);
3262 if (!virtual_operand_p (result
) && POINTER_TYPE_P (TREE_TYPE (result
)))
3264 int idx
= get_stridx (gimple_phi_arg_def (phi
, 0));
3267 unsigned int i
, n
= gimple_phi_num_args (phi
);
3268 for (i
= 1; i
< n
; i
++)
3269 if (idx
!= get_stridx (gimple_phi_arg_def (phi
, i
)))
3272 ssa_ver_to_stridx
[SSA_NAME_VERSION (result
)] = idx
;
3277 /* Attempt to optimize individual statements. */
3278 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); )
3279 if (strlen_check_and_optimize_stmt (&gsi
))
3282 bb
->aux
= stridx_to_strinfo
;
3283 if (vec_safe_length (stridx_to_strinfo
) && !strinfo_shared ())
3284 (*stridx_to_strinfo
)[0] = (strinfo
*) bb
;
3288 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3289 owned by the current bb, clear bb->aux. */
3292 strlen_dom_walker::after_dom_children (basic_block bb
)
3296 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) bb
->aux
);
3297 if (vec_safe_length (stridx_to_strinfo
)
3298 && (*stridx_to_strinfo
)[0] == (strinfo
*) bb
)
3303 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
3305 vec_free (stridx_to_strinfo
);
3311 /* Main entry point. */
3315 const pass_data pass_data_strlen
=
3317 GIMPLE_PASS
, /* type */
3318 "strlen", /* name */
3319 OPTGROUP_NONE
, /* optinfo_flags */
3320 TV_TREE_STRLEN
, /* tv_id */
3321 ( PROP_cfg
| PROP_ssa
), /* properties_required */
3322 0, /* properties_provided */
3323 0, /* properties_destroyed */
3324 0, /* todo_flags_start */
3325 0, /* todo_flags_finish */
3328 class pass_strlen
: public gimple_opt_pass
3331 pass_strlen (gcc::context
*ctxt
)
3332 : gimple_opt_pass (pass_data_strlen
, ctxt
)
3335 /* opt_pass methods: */
3336 virtual bool gate (function
*) { return flag_optimize_strlen
!= 0; }
3337 virtual unsigned int execute (function
*);
3339 }; // class pass_strlen
3342 pass_strlen::execute (function
*fun
)
3344 gcc_assert (!strlen_to_stridx
);
3345 if (warn_stringop_overflow
|| warn_stringop_truncation
)
3346 strlen_to_stridx
= new hash_map
<tree
, stridx_strlenloc
> ();
3348 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
3351 calculate_dominance_info (CDI_DOMINATORS
);
3353 /* String length optimization is implemented as a walk of the dominator
3354 tree and a forward walk of statements within each block. */
3355 strlen_dom_walker (CDI_DOMINATORS
).walk (fun
->cfg
->x_entry_block_ptr
);
3357 ssa_ver_to_stridx
.release ();
3358 strinfo_pool
.release ();
3359 if (decl_to_stridxlist_htab
)
3361 obstack_free (&stridx_obstack
, NULL
);
3362 delete decl_to_stridxlist_htab
;
3363 decl_to_stridxlist_htab
= NULL
;
3365 laststmt
.stmt
= NULL
;
3366 laststmt
.len
= NULL_TREE
;
3367 laststmt
.stridx
= 0;
3369 if (strlen_to_stridx
)
3371 strlen_to_stridx
->empty ();
3372 delete strlen_to_stridx
;
3373 strlen_to_stridx
= NULL
;
3382 make_pass_strlen (gcc::context
*ctxt
)
3384 return new pass_strlen (ctxt
);