1 /* String length optimization
2 Copyright (C) 2011-2018 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 calls to stridx instances describing
160 the calls' arguments. Non-null only when warn_stringop_truncation
162 typedef std::pair
<int, location_t
> stridx_strlenloc
;
163 static hash_map
<tree
, stridx_strlenloc
> *strlen_to_stridx
;
165 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
166 static struct obstack stridx_obstack
;
168 /* Last memcpy statement if it could be adjusted if the trailing
169 '\0' written is immediately overwritten, or
170 *x = '\0' store that could be removed if it is immediately overwritten. */
171 struct laststmt_struct
178 static int get_stridx_plus_constant (strinfo
*, unsigned HOST_WIDE_INT
, tree
);
179 static void handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*);
183 - 1 if SI is known to start with more than OFF nonzero characters.
185 - 0 if SI is known to start with OFF nonzero characters,
186 but is not known to start with more.
188 - -1 if SI might not start with OFF nonzero characters. */
191 compare_nonzero_chars (strinfo
*si
, unsigned HOST_WIDE_INT off
)
193 if (si
->nonzero_chars
194 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
195 return compare_tree_int (si
->nonzero_chars
, off
);
200 /* Return true if SI is known to be a zero-length string. */
203 zero_length_string_p (strinfo
*si
)
205 return si
->full_string_p
&& integer_zerop (si
->nonzero_chars
);
208 /* Return strinfo vector entry IDX. */
210 static inline strinfo
*
211 get_strinfo (int idx
)
213 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
215 return (*stridx_to_strinfo
)[idx
];
218 /* Get the next strinfo in the chain after SI, or null if none. */
220 static inline strinfo
*
221 get_next_strinfo (strinfo
*si
)
225 strinfo
*nextsi
= get_strinfo (si
->next
);
226 if (nextsi
== NULL
|| nextsi
->first
!= si
->first
|| nextsi
->prev
!= si
->idx
)
231 /* Helper function for get_stridx. Return the strinfo index of the address
232 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
233 OK to return the index for some X <= &EXP and store &EXP - X in
237 get_addr_stridx (tree exp
, tree ptr
, unsigned HOST_WIDE_INT
*offset_out
)
240 struct stridxlist
*list
, *last
= NULL
;
243 if (!decl_to_stridxlist_htab
)
247 base
= get_addr_base_and_unit_offset (exp
, &poff
);
248 if (base
== NULL
|| !DECL_P (base
) || !poff
.is_constant (&off
))
251 list
= decl_to_stridxlist_htab
->get (base
);
257 if (list
->offset
== off
)
263 if (list
->offset
> off
)
270 if ((offset_out
|| ptr
) && last
&& last
->idx
> 0)
272 unsigned HOST_WIDE_INT rel_off
273 = (unsigned HOST_WIDE_INT
) off
- last
->offset
;
274 strinfo
*si
= get_strinfo (last
->idx
);
275 if (si
&& compare_nonzero_chars (si
, rel_off
) >= 0)
279 *offset_out
= rel_off
;
283 return get_stridx_plus_constant (si
, rel_off
, ptr
);
289 /* Return string index for EXP. */
292 get_stridx (tree exp
)
296 if (TREE_CODE (exp
) == SSA_NAME
)
298 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)])
299 return ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)];
302 HOST_WIDE_INT off
= 0;
303 for (i
= 0; i
< 5; i
++)
305 gimple
*def_stmt
= SSA_NAME_DEF_STMT (e
);
306 if (!is_gimple_assign (def_stmt
)
307 || gimple_assign_rhs_code (def_stmt
) != POINTER_PLUS_EXPR
)
309 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
310 tree rhs2
= gimple_assign_rhs2 (def_stmt
);
311 if (TREE_CODE (rhs1
) != SSA_NAME
312 || !tree_fits_shwi_p (rhs2
))
314 HOST_WIDE_INT this_off
= tree_to_shwi (rhs2
);
317 off
= (unsigned HOST_WIDE_INT
) off
+ this_off
;
320 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (rhs1
)])
323 = get_strinfo (ssa_ver_to_stridx
[SSA_NAME_VERSION (rhs1
)]);
324 if (si
&& compare_nonzero_chars (si
, off
) >= 0)
325 return get_stridx_plus_constant (si
, off
, exp
);
332 if (TREE_CODE (exp
) == ADDR_EXPR
)
334 int idx
= get_addr_stridx (TREE_OPERAND (exp
, 0), exp
, NULL
);
339 s
= string_constant (exp
, &o
);
341 && (o
== NULL_TREE
|| tree_fits_shwi_p (o
))
342 && TREE_STRING_LENGTH (s
) > 0)
344 HOST_WIDE_INT offset
= o
? tree_to_shwi (o
) : 0;
345 const char *p
= TREE_STRING_POINTER (s
);
346 int max
= TREE_STRING_LENGTH (s
) - 1;
348 if (p
[max
] == '\0' && offset
>= 0 && offset
<= max
)
349 return ~(int) strlen (p
+ offset
);
354 /* Return true if strinfo vector is shared with the immediate dominator. */
357 strinfo_shared (void)
359 return vec_safe_length (stridx_to_strinfo
)
360 && (*stridx_to_strinfo
)[0] != NULL
;
363 /* Unshare strinfo vector that is shared with the immediate dominator. */
366 unshare_strinfo_vec (void)
371 gcc_assert (strinfo_shared ());
372 stridx_to_strinfo
= vec_safe_copy (stridx_to_strinfo
);
373 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
376 (*stridx_to_strinfo
)[0] = NULL
;
379 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
380 Return a pointer to the location where the string index can
381 be stored (if 0) or is stored, or NULL if this can't be tracked. */
384 addr_stridxptr (tree exp
)
389 tree base
= get_addr_base_and_unit_offset (exp
, &poff
);
390 if (base
== NULL_TREE
|| !DECL_P (base
) || !poff
.is_constant (&off
))
393 if (!decl_to_stridxlist_htab
)
395 decl_to_stridxlist_htab
396 = new hash_map
<tree_decl_hash
, stridxlist
> (64);
397 gcc_obstack_init (&stridx_obstack
);
401 stridxlist
*list
= &decl_to_stridxlist_htab
->get_or_insert (base
, &existed
);
405 stridxlist
*before
= NULL
;
406 for (i
= 0; i
< 32; i
++)
408 if (list
->offset
== off
)
410 if (list
->offset
> off
&& before
== NULL
)
412 if (list
->next
== NULL
)
421 before
= XOBNEW (&stridx_obstack
, struct stridxlist
);
428 list
->next
= XOBNEW (&stridx_obstack
, struct stridxlist
);
438 /* Create a new string index, or return 0 if reached limit. */
441 new_stridx (tree exp
)
444 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
446 if (TREE_CODE (exp
) == SSA_NAME
)
448 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
))
451 ssa_ver_to_stridx
[SSA_NAME_VERSION (exp
)] = idx
;
454 if (TREE_CODE (exp
) == ADDR_EXPR
)
456 int *pidx
= addr_stridxptr (TREE_OPERAND (exp
, 0));
459 gcc_assert (*pidx
== 0);
460 *pidx
= max_stridx
++;
467 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
470 new_addr_stridx (tree exp
)
473 if (max_stridx
>= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS
))
475 pidx
= addr_stridxptr (exp
);
478 gcc_assert (*pidx
== 0);
479 *pidx
= max_stridx
++;
485 /* Create a new strinfo. */
488 new_strinfo (tree ptr
, int idx
, tree nonzero_chars
, bool full_string_p
)
490 strinfo
*si
= strinfo_pool
.allocate ();
491 si
->nonzero_chars
= nonzero_chars
;
494 si
->endptr
= NULL_TREE
;
500 si
->writable
= false;
501 si
->dont_invalidate
= false;
502 si
->full_string_p
= full_string_p
;
506 /* Decrease strinfo refcount and free it if not referenced anymore. */
509 free_strinfo (strinfo
*si
)
511 if (si
&& --si
->refcount
== 0)
512 strinfo_pool
.remove (si
);
515 /* Set strinfo in the vector entry IDX to SI. */
518 set_strinfo (int idx
, strinfo
*si
)
520 if (vec_safe_length (stridx_to_strinfo
) && (*stridx_to_strinfo
)[0])
521 unshare_strinfo_vec ();
522 if (vec_safe_length (stridx_to_strinfo
) <= (unsigned int) idx
)
523 vec_safe_grow_cleared (stridx_to_strinfo
, idx
+ 1);
524 (*stridx_to_strinfo
)[idx
] = si
;
527 /* Return the first strinfo in the related strinfo chain
528 if all strinfos in between belong to the chain, otherwise NULL. */
531 verify_related_strinfos (strinfo
*origsi
)
533 strinfo
*si
= origsi
, *psi
;
535 if (origsi
->first
== 0)
537 for (; si
->prev
; si
= psi
)
539 if (si
->first
!= origsi
->first
)
541 psi
= get_strinfo (si
->prev
);
544 if (psi
->next
!= si
->idx
)
547 if (si
->idx
!= si
->first
)
552 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
553 Use LOC for folding. */
556 set_endptr_and_length (location_t loc
, strinfo
*si
, tree endptr
)
560 tree start_as_size
= fold_convert_loc (loc
, size_type_node
, si
->ptr
);
561 tree end_as_size
= fold_convert_loc (loc
, size_type_node
, endptr
);
562 si
->nonzero_chars
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
563 end_as_size
, start_as_size
);
564 si
->full_string_p
= true;
567 /* Return string length, or NULL if it can't be computed. */
570 get_string_length (strinfo
*si
)
572 if (si
->nonzero_chars
)
573 return si
->full_string_p
? si
->nonzero_chars
: NULL
;
577 gimple
*stmt
= si
->stmt
, *lenstmt
;
578 tree callee
, lhs
, fn
, tem
;
580 gimple_stmt_iterator gsi
;
582 gcc_assert (is_gimple_call (stmt
));
583 callee
= gimple_call_fndecl (stmt
);
584 gcc_assert (callee
&& DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
);
585 lhs
= gimple_call_lhs (stmt
);
586 /* unshare_strinfo is intentionally not called here. The (delayed)
587 transformation of strcpy or strcat into stpcpy is done at the place
588 of the former strcpy/strcat call and so can affect all the strinfos
589 with the same stmt. If they were unshared before and transformation
590 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
591 just compute the right length. */
592 switch (DECL_FUNCTION_CODE (callee
))
594 case BUILT_IN_STRCAT
:
595 case BUILT_IN_STRCAT_CHK
:
596 gsi
= gsi_for_stmt (stmt
);
597 fn
= builtin_decl_implicit (BUILT_IN_STRLEN
);
598 gcc_assert (lhs
== NULL_TREE
);
599 tem
= unshare_expr (gimple_call_arg (stmt
, 0));
600 lenstmt
= gimple_build_call (fn
, 1, tem
);
601 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), lenstmt
);
602 gimple_call_set_lhs (lenstmt
, lhs
);
603 gimple_set_vuse (lenstmt
, gimple_vuse (stmt
));
604 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
605 tem
= gimple_call_arg (stmt
, 0);
606 if (!ptrofftype_p (TREE_TYPE (lhs
)))
608 lhs
= convert_to_ptrofftype (lhs
);
609 lhs
= force_gimple_operand_gsi (&gsi
, lhs
, true, NULL_TREE
,
610 true, GSI_SAME_STMT
);
612 lenstmt
= gimple_build_assign
613 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt
, 0))),
614 POINTER_PLUS_EXPR
,tem
, lhs
);
615 gsi_insert_before (&gsi
, lenstmt
, GSI_SAME_STMT
);
616 gimple_call_set_arg (stmt
, 0, gimple_assign_lhs (lenstmt
));
619 case BUILT_IN_STRCPY
:
620 case BUILT_IN_STRCPY_CHK
:
621 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY
));
622 if (gimple_call_num_args (stmt
) == 2)
623 fn
= builtin_decl_implicit (BUILT_IN_STPCPY
);
625 fn
= builtin_decl_explicit (BUILT_IN_STPCPY_CHK
);
626 gcc_assert (lhs
== NULL_TREE
);
627 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
629 fprintf (dump_file
, "Optimizing: ");
630 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
632 gimple_call_set_fndecl (stmt
, fn
);
633 lhs
= make_ssa_name (TREE_TYPE (TREE_TYPE (fn
)), stmt
);
634 gimple_call_set_lhs (stmt
, lhs
);
636 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
638 fprintf (dump_file
, "into: ");
639 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
642 case BUILT_IN_STPCPY
:
643 case BUILT_IN_STPCPY_CHK
:
644 gcc_assert (lhs
!= NULL_TREE
);
645 loc
= gimple_location (stmt
);
646 set_endptr_and_length (loc
, si
, lhs
);
647 for (strinfo
*chainsi
= verify_related_strinfos (si
);
649 chainsi
= get_next_strinfo (chainsi
))
650 if (chainsi
->nonzero_chars
== NULL
)
651 set_endptr_and_length (loc
, chainsi
, lhs
);
653 case BUILT_IN_MALLOC
:
655 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
662 return si
->nonzero_chars
;
665 /* Invalidate string length information for strings whose length
666 might change due to stores in stmt. */
669 maybe_invalidate (gimple
*stmt
)
673 bool nonempty
= false;
675 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
678 if (!si
->dont_invalidate
)
681 /* Do not use si->nonzero_chars. */
682 ao_ref_init_from_ptr_and_size (&r
, si
->ptr
, NULL_TREE
);
683 if (stmt_may_clobber_ref_p_1 (stmt
, &r
))
685 set_strinfo (i
, NULL
);
690 si
->dont_invalidate
= false;
696 /* Unshare strinfo record SI, if it has refcount > 1 or
697 if stridx_to_strinfo vector is shared with some other
701 unshare_strinfo (strinfo
*si
)
705 if (si
->refcount
== 1 && !strinfo_shared ())
708 nsi
= new_strinfo (si
->ptr
, si
->idx
, si
->nonzero_chars
, si
->full_string_p
);
709 nsi
->stmt
= si
->stmt
;
710 nsi
->endptr
= si
->endptr
;
711 nsi
->first
= si
->first
;
712 nsi
->prev
= si
->prev
;
713 nsi
->next
= si
->next
;
714 nsi
->writable
= si
->writable
;
715 set_strinfo (si
->idx
, nsi
);
720 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
721 strinfo if there is any. Return it's idx, or 0 if no strinfo has
725 get_stridx_plus_constant (strinfo
*basesi
, unsigned HOST_WIDE_INT off
,
728 if (TREE_CODE (ptr
) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
731 if (compare_nonzero_chars (basesi
, off
) < 0
732 || !tree_fits_uhwi_p (basesi
->nonzero_chars
))
735 unsigned HOST_WIDE_INT nonzero_chars
736 = tree_to_uhwi (basesi
->nonzero_chars
) - off
;
737 strinfo
*si
= basesi
, *chainsi
;
738 if (si
->first
|| si
->prev
|| si
->next
)
739 si
= verify_related_strinfos (basesi
);
741 || si
->nonzero_chars
== NULL_TREE
742 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
745 if (TREE_CODE (ptr
) == SSA_NAME
746 && ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
747 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
749 gcc_checking_assert (compare_tree_int (si
->nonzero_chars
, off
) != -1);
750 for (chainsi
= si
; chainsi
->next
; chainsi
= si
)
752 si
= get_next_strinfo (chainsi
);
754 || si
->nonzero_chars
== NULL_TREE
755 || TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
)
757 int r
= compare_tree_int (si
->nonzero_chars
, nonzero_chars
);
762 if (TREE_CODE (ptr
) == SSA_NAME
)
763 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = si
->idx
;
766 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
767 if (pidx
!= NULL
&& *pidx
== 0)
776 int idx
= new_stridx (ptr
);
779 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, nonzero_chars
),
780 basesi
->full_string_p
);
781 set_strinfo (idx
, si
);
782 if (strinfo
*nextsi
= get_strinfo (chainsi
->next
))
784 nextsi
= unshare_strinfo (nextsi
);
785 si
->next
= nextsi
->idx
;
788 chainsi
= unshare_strinfo (chainsi
);
789 if (chainsi
->first
== 0)
790 chainsi
->first
= chainsi
->idx
;
792 if (chainsi
->endptr
== NULL_TREE
&& zero_length_string_p (si
))
793 chainsi
->endptr
= ptr
;
794 si
->endptr
= chainsi
->endptr
;
795 si
->prev
= chainsi
->idx
;
796 si
->first
= chainsi
->first
;
797 si
->writable
= chainsi
->writable
;
801 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
802 to a zero-length string and if possible chain it to a related strinfo
803 chain whose part is or might be CHAINSI. */
806 zero_length_string (tree ptr
, strinfo
*chainsi
)
810 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
811 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
812 gcc_checking_assert (TREE_CODE (ptr
) == SSA_NAME
813 && ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] == 0);
815 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr
))
819 si
= verify_related_strinfos (chainsi
);
824 /* We shouldn't mix delayed and non-delayed lengths. */
825 gcc_assert (si
->full_string_p
);
826 if (si
->endptr
== NULL_TREE
)
828 si
= unshare_strinfo (si
);
832 si
= get_next_strinfo (si
);
835 if (zero_length_string_p (chainsi
))
839 chainsi
= unshare_strinfo (chainsi
);
842 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = chainsi
->idx
;
848 /* We shouldn't mix delayed and non-delayed lengths. */
849 gcc_assert (chainsi
->full_string_p
);
850 if (chainsi
->first
|| chainsi
->prev
|| chainsi
->next
)
852 chainsi
= unshare_strinfo (chainsi
);
859 idx
= new_stridx (ptr
);
862 si
= new_strinfo (ptr
, idx
, build_int_cst (size_type_node
, 0), true);
863 set_strinfo (idx
, si
);
867 chainsi
= unshare_strinfo (chainsi
);
868 if (chainsi
->first
== 0)
869 chainsi
->first
= chainsi
->idx
;
871 if (chainsi
->endptr
== NULL_TREE
)
872 chainsi
->endptr
= ptr
;
873 si
->prev
= chainsi
->idx
;
874 si
->first
= chainsi
->first
;
875 si
->writable
= chainsi
->writable
;
880 /* For strinfo ORIGSI whose length has been just updated, adjust other
881 related strinfos so that they match the new ORIGSI. This involves:
883 - adding ADJ to the nonzero_chars fields
884 - copying full_string_p from the new ORIGSI. */
887 adjust_related_strinfos (location_t loc
, strinfo
*origsi
, tree adj
)
889 strinfo
*si
= verify_related_strinfos (origsi
);
902 si
= unshare_strinfo (si
);
903 /* We shouldn't see delayed lengths here; the caller must have
904 calculated the old length in order to calculate the
906 gcc_assert (si
->nonzero_chars
);
907 tem
= fold_convert_loc (loc
, TREE_TYPE (si
->nonzero_chars
), adj
);
908 si
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
909 TREE_TYPE (si
->nonzero_chars
),
910 si
->nonzero_chars
, tem
);
911 si
->full_string_p
= origsi
->full_string_p
;
913 si
->endptr
= NULL_TREE
;
914 si
->dont_invalidate
= true;
916 nsi
= get_next_strinfo (si
);
923 /* Find if there are other SSA_NAME pointers equal to PTR
924 for which we don't track their string lengths yet. If so, use
928 find_equal_ptrs (tree ptr
, int idx
)
930 if (TREE_CODE (ptr
) != SSA_NAME
)
934 gimple
*stmt
= SSA_NAME_DEF_STMT (ptr
);
935 if (!is_gimple_assign (stmt
))
937 ptr
= gimple_assign_rhs1 (stmt
);
938 switch (gimple_assign_rhs_code (stmt
))
943 if (!POINTER_TYPE_P (TREE_TYPE (ptr
)))
945 if (TREE_CODE (ptr
) == SSA_NAME
)
947 if (TREE_CODE (ptr
) != ADDR_EXPR
)
952 int *pidx
= addr_stridxptr (TREE_OPERAND (ptr
, 0));
953 if (pidx
!= NULL
&& *pidx
== 0)
961 /* We might find an endptr created in this pass. Grow the
962 vector in that case. */
963 if (ssa_ver_to_stridx
.length () <= SSA_NAME_VERSION (ptr
))
964 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
966 if (ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] != 0)
968 ssa_ver_to_stridx
[SSA_NAME_VERSION (ptr
)] = idx
;
972 /* Return true if STMT is a call to a builtin function with the right
973 arguments and attributes that should be considered for optimization
977 valid_builtin_call (gimple
*stmt
)
979 if (!gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
982 tree callee
= gimple_call_fndecl (stmt
);
983 switch (DECL_FUNCTION_CODE (callee
))
985 case BUILT_IN_MEMCMP
:
986 case BUILT_IN_MEMCMP_EQ
:
987 case BUILT_IN_STRCHR
:
988 case BUILT_IN_STRLEN
:
989 /* The above functions should be pure. Punt if they aren't. */
990 if (gimple_vdef (stmt
) || gimple_vuse (stmt
) == NULL_TREE
)
994 case BUILT_IN_CALLOC
:
995 case BUILT_IN_MALLOC
:
996 case BUILT_IN_MEMCPY
:
997 case BUILT_IN_MEMCPY_CHK
:
998 case BUILT_IN_MEMPCPY
:
999 case BUILT_IN_MEMPCPY_CHK
:
1000 case BUILT_IN_MEMSET
:
1001 case BUILT_IN_STPCPY
:
1002 case BUILT_IN_STPCPY_CHK
:
1003 case BUILT_IN_STRCAT
:
1004 case BUILT_IN_STRCAT_CHK
:
1005 case BUILT_IN_STRCPY
:
1006 case BUILT_IN_STRCPY_CHK
:
1007 /* The above functions should be neither const nor pure. Punt if they
1009 if (gimple_vdef (stmt
) == NULL_TREE
|| gimple_vuse (stmt
) == NULL_TREE
)
1020 /* If the last .MEM setter statement before STMT is
1021 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1022 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1023 just memcpy (x, y, strlen (y)). SI must be the zero length
1027 adjust_last_stmt (strinfo
*si
, gimple
*stmt
, bool is_strcat
)
1029 tree vuse
, callee
, len
;
1030 struct laststmt_struct last
= laststmt
;
1031 strinfo
*lastsi
, *firstsi
;
1032 unsigned len_arg_no
= 2;
1034 laststmt
.stmt
= NULL
;
1035 laststmt
.len
= NULL_TREE
;
1036 laststmt
.stridx
= 0;
1038 if (last
.stmt
== NULL
)
1041 vuse
= gimple_vuse (stmt
);
1042 if (vuse
== NULL_TREE
1043 || SSA_NAME_DEF_STMT (vuse
) != last
.stmt
1044 || !has_single_use (vuse
))
1047 gcc_assert (last
.stridx
> 0);
1048 lastsi
= get_strinfo (last
.stridx
);
1054 if (lastsi
->first
== 0 || lastsi
->first
!= si
->first
)
1057 firstsi
= verify_related_strinfos (si
);
1058 if (firstsi
== NULL
)
1060 while (firstsi
!= lastsi
)
1062 firstsi
= get_next_strinfo (firstsi
);
1063 if (firstsi
== NULL
)
1068 if (!is_strcat
&& !zero_length_string_p (si
))
1071 if (is_gimple_assign (last
.stmt
))
1073 gimple_stmt_iterator gsi
;
1075 if (!integer_zerop (gimple_assign_rhs1 (last
.stmt
)))
1077 if (stmt_could_throw_p (last
.stmt
))
1079 gsi
= gsi_for_stmt (last
.stmt
);
1080 unlink_stmt_vdef (last
.stmt
);
1081 release_defs (last
.stmt
);
1082 gsi_remove (&gsi
, true);
1086 if (!valid_builtin_call (last
.stmt
))
1089 callee
= gimple_call_fndecl (last
.stmt
);
1090 switch (DECL_FUNCTION_CODE (callee
))
1092 case BUILT_IN_MEMCPY
:
1093 case BUILT_IN_MEMCPY_CHK
:
1099 len
= gimple_call_arg (last
.stmt
, len_arg_no
);
1100 if (tree_fits_uhwi_p (len
))
1102 if (!tree_fits_uhwi_p (last
.len
)
1103 || integer_zerop (len
)
1104 || tree_to_uhwi (len
) != tree_to_uhwi (last
.len
) + 1)
1106 /* Don't adjust the length if it is divisible by 4, it is more efficient
1107 to store the extra '\0' in that case. */
1108 if ((tree_to_uhwi (len
) & 3) == 0)
1111 else if (TREE_CODE (len
) == SSA_NAME
)
1113 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1114 if (!is_gimple_assign (def_stmt
)
1115 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
1116 || gimple_assign_rhs1 (def_stmt
) != last
.len
1117 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
1123 gimple_call_set_arg (last
.stmt
, len_arg_no
, last
.len
);
1124 update_stmt (last
.stmt
);
1127 /* For an LHS that is an SSA_NAME and for strlen() or strnlen() argument
1128 SRC, set LHS range info to [0, min (N, BOUND)] if SRC refers to
1129 a character array A[N] with unknown length bounded by N, and for
1130 strnlen(), by min (N, BOUND). */
1133 maybe_set_strlen_range (tree lhs
, tree src
, tree bound
)
1135 if (TREE_CODE (lhs
) != SSA_NAME
1136 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
1139 if (TREE_CODE (src
) == SSA_NAME
)
1141 gimple
*def
= SSA_NAME_DEF_STMT (src
);
1142 if (is_gimple_assign (def
)
1143 && gimple_assign_rhs_code (def
) == ADDR_EXPR
)
1144 src
= gimple_assign_rhs1 (def
);
1147 wide_int max
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
));
1148 wide_int min
= wi::zero (max
.get_precision ());
1150 if (TREE_CODE (src
) == ADDR_EXPR
)
1152 /* The last array member of a struct can be bigger than its size
1153 suggests if it's treated as a poor-man's flexible array member. */
1154 src
= TREE_OPERAND (src
, 0);
1155 bool src_is_array
= TREE_CODE (TREE_TYPE (src
)) == ARRAY_TYPE
;
1156 if (src_is_array
&& !array_at_struct_end_p (src
))
1158 tree type
= TREE_TYPE (src
);
1159 if (tree dom
= TYPE_DOMAIN (type
))
1161 tree maxval
= TYPE_MAX_VALUE (dom
);
1163 max
= wi::to_wide (maxval
);
1165 max
= wi::zero (min
.get_precision ());
1167 /* For strlen() the upper bound above is equal to
1168 the longest string that can be stored in the array
1169 (i.e., it accounts for the terminating nul. For
1170 strnlen() bump up the maximum by one since the array
1171 need not be nul-terminated. */
1178 if (TREE_CODE (src
) == COMPONENT_REF
&& !src_is_array
)
1179 src
= TREE_OPERAND (src
, 1);
1182 /* Handle the unlikely case of strlen (&c) where c is some
1184 if (tree size
= DECL_SIZE_UNIT (src
))
1185 if (TREE_CODE (size
) == INTEGER_CST
)
1186 max
= wi::to_wide (size
);
1193 /* For strnlen, adjust MIN and MAX as necessary. If the bound
1194 is less than the size of the array set MAX to it. It it's
1195 greater than MAX and MAX is non-zero bump MAX down to account
1196 for the necessary terminating nul. Otherwise leave it alone. */
1197 if (TREE_CODE (bound
) == INTEGER_CST
)
1199 wide_int wibnd
= wi::to_wide (bound
);
1200 int cmp
= wi::cmpu (wibnd
, max
);
1203 else if (cmp
&& wi::ne_p (max
, min
))
1206 else if (TREE_CODE (bound
) == SSA_NAME
)
1208 wide_int minbound
, maxbound
;
1209 value_range_type rng
= get_range_info (bound
, &minbound
, &maxbound
);
1210 if (rng
== VR_RANGE
)
1212 /* For a bound in a known range, adjust the range determined
1213 above as necessary. For a bound in some anti-range or
1214 in an unknown range, use the range determined above. */
1215 if (wi::ltu_p (minbound
, min
))
1217 if (wi::ltu_p (maxbound
, max
))
1224 return wide_int_to_tree (size_type_node
, min
);
1226 set_range_info (lhs
, VR_RANGE
, min
, max
);
1230 /* Handle a strlen call. If strlen of the argument is known, replace
1231 the strlen call with the known value, otherwise remember that strlen
1232 of the argument is stored in the lhs SSA_NAME. */
1235 handle_builtin_strlen (gimple_stmt_iterator
*gsi
)
1237 gimple
*stmt
= gsi_stmt (*gsi
);
1238 tree lhs
= gimple_call_lhs (stmt
);
1240 if (lhs
== NULL_TREE
)
1243 location_t loc
= gimple_location (stmt
);
1244 tree callee
= gimple_call_fndecl (stmt
);
1245 tree src
= gimple_call_arg (stmt
, 0);
1246 tree bound
= (DECL_FUNCTION_CODE (callee
) == BUILT_IN_STRNLEN
1247 ? gimple_call_arg (stmt
, 1) : NULL_TREE
);
1248 int idx
= get_stridx (src
);
1255 rhs
= build_int_cst (TREE_TYPE (lhs
), ~idx
);
1259 si
= get_strinfo (idx
);
1261 rhs
= get_string_length (si
);
1263 if (rhs
!= NULL_TREE
)
1265 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1267 fprintf (dump_file
, "Optimizing: ");
1268 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1270 rhs
= unshare_expr (rhs
);
1271 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
1272 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1274 /* Set for strnlen() calls with a non-constant bound. */
1275 bool noncst_bound
= false;
1279 = fold_build2_loc (loc
, MIN_EXPR
, TREE_TYPE (rhs
), rhs
, bound
);
1281 noncst_bound
= (TREE_CODE (new_rhs
) != INTEGER_CST
1282 || tree_int_cst_lt (new_rhs
, rhs
));
1287 if (!update_call_from_tree (gsi
, rhs
))
1288 gimplify_and_update_call_from_tree (gsi
, rhs
);
1289 stmt
= gsi_stmt (*gsi
);
1291 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1293 fprintf (dump_file
, "into: ");
1294 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1297 /* Avoid storing the length for calls to strnlen() with
1298 a non-constant bound. */
1303 && TREE_CODE (si
->nonzero_chars
) != SSA_NAME
1304 && TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
1305 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1307 si
= unshare_strinfo (si
);
1308 si
->nonzero_chars
= lhs
;
1309 gcc_assert (si
->full_string_p
);
1312 if (strlen_to_stridx
)
1313 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1318 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1322 idx
= new_stridx (src
);
1325 strinfo
*si
= get_strinfo (idx
);
1328 if (!si
->full_string_p
&& !si
->stmt
)
1330 /* Until now we only had a lower bound on the string length.
1331 Install LHS as the actual length. */
1332 si
= unshare_strinfo (si
);
1333 tree old
= si
->nonzero_chars
;
1334 si
->nonzero_chars
= lhs
;
1335 si
->full_string_p
= true;
1336 if (TREE_CODE (old
) == INTEGER_CST
)
1338 old
= fold_convert_loc (loc
, TREE_TYPE (lhs
), old
);
1339 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1340 TREE_TYPE (lhs
), lhs
, old
);
1341 adjust_related_strinfos (loc
, si
, adj
);
1357 /* Only store the new length information for calls to strlen(),
1358 not for those to strnlen(). */
1359 strinfo
*si
= new_strinfo (src
, idx
, lhs
, true);
1360 set_strinfo (idx
, si
);
1361 find_equal_ptrs (src
, idx
);
1364 /* For SRC that is an array of N elements, set LHS's range
1365 to [0, min (N, BOUND)]. A constant return value means
1366 the range would have consisted of a single value. In
1367 that case, fold the result into the returned constant. */
1368 if (tree ret
= maybe_set_strlen_range (lhs
, src
, bound
))
1369 if (TREE_CODE (ret
) == INTEGER_CST
)
1371 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1373 fprintf (dump_file
, "Optimizing: ");
1374 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1376 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (ret
)))
1377 ret
= fold_convert_loc (loc
, TREE_TYPE (lhs
), ret
);
1378 if (!update_call_from_tree (gsi
, ret
))
1379 gimplify_and_update_call_from_tree (gsi
, ret
);
1380 stmt
= gsi_stmt (*gsi
);
1382 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1384 fprintf (dump_file
, "into: ");
1385 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1389 if (strlen_to_stridx
&& !bound
)
1390 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1394 /* Handle a strchr call. If strlen of the first argument is known, replace
1395 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1396 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1399 handle_builtin_strchr (gimple_stmt_iterator
*gsi
)
1403 gimple
*stmt
= gsi_stmt (*gsi
);
1404 tree lhs
= gimple_call_lhs (stmt
);
1406 if (lhs
== NULL_TREE
)
1409 if (!integer_zerop (gimple_call_arg (stmt
, 1)))
1412 src
= gimple_call_arg (stmt
, 0);
1413 idx
= get_stridx (src
);
1420 rhs
= build_int_cst (size_type_node
, ~idx
);
1424 si
= get_strinfo (idx
);
1426 rhs
= get_string_length (si
);
1428 if (rhs
!= NULL_TREE
)
1430 location_t loc
= gimple_location (stmt
);
1432 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1434 fprintf (dump_file
, "Optimizing: ");
1435 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1437 if (si
!= NULL
&& si
->endptr
!= NULL_TREE
)
1439 rhs
= unshare_expr (si
->endptr
);
1440 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1442 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1446 rhs
= fold_convert_loc (loc
, sizetype
, unshare_expr (rhs
));
1447 rhs
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
1448 TREE_TYPE (src
), src
, rhs
);
1449 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1451 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1453 if (!update_call_from_tree (gsi
, rhs
))
1454 gimplify_and_update_call_from_tree (gsi
, rhs
);
1455 stmt
= gsi_stmt (*gsi
);
1457 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1459 fprintf (dump_file
, "into: ");
1460 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1463 && si
->endptr
== NULL_TREE
1464 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1466 si
= unshare_strinfo (si
);
1469 zero_length_string (lhs
, si
);
1473 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1475 if (TREE_CODE (src
) != SSA_NAME
|| !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src
))
1478 idx
= new_stridx (src
);
1479 else if (get_strinfo (idx
) != NULL
)
1481 zero_length_string (lhs
, NULL
);
1486 location_t loc
= gimple_location (stmt
);
1487 tree lhsu
= fold_convert_loc (loc
, size_type_node
, lhs
);
1488 tree srcu
= fold_convert_loc (loc
, size_type_node
, src
);
1489 tree length
= fold_build2_loc (loc
, MINUS_EXPR
,
1490 size_type_node
, lhsu
, srcu
);
1491 strinfo
*si
= new_strinfo (src
, idx
, length
, true);
1493 set_strinfo (idx
, si
);
1494 find_equal_ptrs (src
, idx
);
1495 zero_length_string (lhs
, si
);
1499 zero_length_string (lhs
, NULL
);
1502 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1503 If strlen of the second argument is known, strlen of the first argument
1504 is the same after this call. Furthermore, attempt to convert it to
1508 handle_builtin_strcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1511 tree src
, dst
, srclen
, len
, lhs
, type
, fn
, oldlen
;
1513 gimple
*stmt
= gsi_stmt (*gsi
);
1514 strinfo
*si
, *dsi
, *olddsi
, *zsi
;
1517 src
= gimple_call_arg (stmt
, 1);
1518 dst
= gimple_call_arg (stmt
, 0);
1519 lhs
= gimple_call_lhs (stmt
);
1520 idx
= get_stridx (src
);
1523 si
= get_strinfo (idx
);
1525 didx
= get_stridx (dst
);
1529 olddsi
= get_strinfo (didx
);
1534 adjust_last_stmt (olddsi
, stmt
, false);
1538 srclen
= get_string_length (si
);
1540 srclen
= build_int_cst (size_type_node
, ~idx
);
1542 loc
= gimple_location (stmt
);
1543 if (srclen
== NULL_TREE
)
1546 case BUILT_IN_STRCPY
:
1547 case BUILT_IN_STRCPY_CHK
:
1548 if (lhs
!= NULL_TREE
|| !builtin_decl_implicit_p (BUILT_IN_STPCPY
))
1551 case BUILT_IN_STPCPY
:
1552 case BUILT_IN_STPCPY_CHK
:
1553 if (lhs
== NULL_TREE
)
1557 tree lhsuint
= fold_convert_loc (loc
, size_type_node
, lhs
);
1558 srclen
= fold_convert_loc (loc
, size_type_node
, dst
);
1559 srclen
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
1569 didx
= new_stridx (dst
);
1575 oldlen
= olddsi
->nonzero_chars
;
1576 dsi
= unshare_strinfo (olddsi
);
1577 dsi
->nonzero_chars
= srclen
;
1578 dsi
->full_string_p
= (srclen
!= NULL_TREE
);
1579 /* Break the chain, so adjust_related_strinfo on later pointers in
1580 the chain won't adjust this one anymore. */
1583 dsi
->endptr
= NULL_TREE
;
1587 dsi
= new_strinfo (dst
, didx
, srclen
, srclen
!= NULL_TREE
);
1588 set_strinfo (didx
, dsi
);
1589 find_equal_ptrs (dst
, didx
);
1591 dsi
->writable
= true;
1592 dsi
->dont_invalidate
= true;
1594 if (dsi
->nonzero_chars
== NULL_TREE
)
1598 /* If string length of src is unknown, use delayed length
1599 computation. If string lenth of dst will be needed, it
1600 can be computed by transforming this strcpy call into
1601 stpcpy and subtracting dst from the return value. */
1603 /* Look for earlier strings whose length could be determined if
1604 this strcpy is turned into an stpcpy. */
1606 if (dsi
->prev
!= 0 && (chainsi
= verify_related_strinfos (dsi
)) != NULL
)
1608 for (; chainsi
&& chainsi
!= dsi
; chainsi
= get_strinfo (chainsi
->next
))
1610 /* When setting a stmt for delayed length computation
1611 prevent all strinfos through dsi from being
1613 chainsi
= unshare_strinfo (chainsi
);
1614 chainsi
->stmt
= stmt
;
1615 chainsi
->nonzero_chars
= NULL_TREE
;
1616 chainsi
->full_string_p
= false;
1617 chainsi
->endptr
= NULL_TREE
;
1618 chainsi
->dont_invalidate
= true;
1623 /* Try to detect overlap before returning. This catches cases
1624 like strcpy (d, d + n) where n is non-constant whose range
1625 is such that (n <= strlen (d) holds).
1627 OLDDSI->NONZERO_chars may have been reset by this point with
1628 oldlen holding it original value. */
1629 if (olddsi
&& oldlen
)
1631 /* Add 1 for the terminating NUL. */
1632 tree type
= TREE_TYPE (oldlen
);
1633 oldlen
= fold_build2 (PLUS_EXPR
, type
, oldlen
,
1634 build_int_cst (type
, 1));
1635 check_bounds_or_overlap (as_a
<gcall
*>(stmt
), olddsi
->ptr
, src
,
1644 tree adj
= NULL_TREE
;
1645 if (oldlen
== NULL_TREE
)
1647 else if (integer_zerop (oldlen
))
1649 else if (TREE_CODE (oldlen
) == INTEGER_CST
1650 || TREE_CODE (srclen
) == INTEGER_CST
)
1651 adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1652 TREE_TYPE (srclen
), srclen
,
1653 fold_convert_loc (loc
, TREE_TYPE (srclen
),
1655 if (adj
!= NULL_TREE
)
1656 adjust_related_strinfos (loc
, dsi
, adj
);
1660 /* strcpy src may not overlap dst, so src doesn't need to be
1661 invalidated either. */
1663 si
->dont_invalidate
= true;
1669 case BUILT_IN_STRCPY
:
1670 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
1672 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1674 case BUILT_IN_STRCPY_CHK
:
1675 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
1677 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1679 case BUILT_IN_STPCPY
:
1680 /* This would need adjustment of the lhs (subtract one),
1681 or detection that the trailing '\0' doesn't need to be
1682 written, if it will be immediately overwritten.
1683 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1687 zsi
= zero_length_string (lhs
, dsi
);
1690 case BUILT_IN_STPCPY_CHK
:
1691 /* This would need adjustment of the lhs (subtract one),
1692 or detection that the trailing '\0' doesn't need to be
1693 written, if it will be immediately overwritten.
1694 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1698 zsi
= zero_length_string (lhs
, dsi
);
1705 zsi
->dont_invalidate
= true;
1709 tree args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1710 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
1713 type
= size_type_node
;
1715 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
1716 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
, build_int_cst (type
, 1));
1718 /* Set the no-warning bit on the transformed statement? */
1719 bool set_no_warning
= false;
1721 if (const strinfo
*chksi
= olddsi
? olddsi
: dsi
)
1723 && !check_bounds_or_overlap (as_a
<gcall
*>(stmt
), chksi
->ptr
, si
->ptr
,
1726 gimple_set_no_warning (stmt
, true);
1727 set_no_warning
= true;
1730 if (fn
== NULL_TREE
)
1733 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
1735 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1737 fprintf (dump_file
, "Optimizing: ");
1738 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1740 if (gimple_call_num_args (stmt
) == 2)
1741 success
= update_gimple_call (gsi
, fn
, 3, dst
, src
, len
);
1743 success
= update_gimple_call (gsi
, fn
, 4, dst
, src
, len
,
1744 gimple_call_arg (stmt
, 2));
1747 stmt
= gsi_stmt (*gsi
);
1749 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1751 fprintf (dump_file
, "into: ");
1752 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1754 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1755 laststmt
.stmt
= stmt
;
1756 laststmt
.len
= srclen
;
1757 laststmt
.stridx
= dsi
->idx
;
1759 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1760 fprintf (dump_file
, "not possible.\n");
1763 gimple_set_no_warning (stmt
, true);
1766 /* Check the size argument to the built-in forms of stpncpy and strncpy
1767 for out-of-bounds offsets or overlapping access, and to see if the
1768 size argument is derived from a call to strlen() on the source argument,
1769 and if so, issue an appropriate warning. */
1772 handle_builtin_strncat (built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1774 /* Same as stxncpy(). */
1775 handle_builtin_stxncpy (bcode
, gsi
);
1778 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1779 way. LEN can either be an integer expression, or a pointer (to char).
1780 When it is the latter (such as in recursive calls to self) is is
1781 assumed to be the argument in some call to strlen() whose relationship
1782 to SRC is being ascertained. */
1785 is_strlen_related_p (tree src
, tree len
)
1787 if (TREE_CODE (TREE_TYPE (len
)) == POINTER_TYPE
1788 && operand_equal_p (src
, len
, 0))
1791 if (TREE_CODE (len
) != SSA_NAME
)
1794 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1798 if (is_gimple_call (def_stmt
))
1800 tree func
= gimple_call_fndecl (def_stmt
);
1801 if (!valid_builtin_call (def_stmt
)
1802 || DECL_FUNCTION_CODE (func
) != BUILT_IN_STRLEN
)
1805 tree arg
= gimple_call_arg (def_stmt
, 0);
1806 return is_strlen_related_p (src
, arg
);
1809 if (!is_gimple_assign (def_stmt
))
1812 tree_code code
= gimple_assign_rhs_code (def_stmt
);
1813 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1814 tree rhstype
= TREE_TYPE (rhs1
);
1816 if ((TREE_CODE (rhstype
) == POINTER_TYPE
&& code
== POINTER_PLUS_EXPR
)
1817 || (INTEGRAL_TYPE_P (rhstype
)
1818 && (code
== BIT_AND_EXPR
1819 || code
== NOP_EXPR
)))
1821 /* Pointer plus (an integer), and truncation are considered among
1822 the (potentially) related expressions to strlen. */
1823 return is_strlen_related_p (src
, rhs1
);
1826 if (tree rhs2
= gimple_assign_rhs2 (def_stmt
))
1828 /* Integer subtraction is considered strlen-related when both
1829 arguments are integers and second one is strlen-related. */
1830 rhstype
= TREE_TYPE (rhs2
);
1831 if (INTEGRAL_TYPE_P (rhstype
) && code
== MINUS_EXPR
)
1832 return is_strlen_related_p (src
, rhs2
);
1838 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1840 Check to see if the specified bound is a) equal to the size of
1841 the destination DST and if so, b) if it's immediately followed by
1842 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1843 do nothing. Return true if diagnostic has been issued.
1845 The purpose is to diagnose calls to strncpy and stpncpy that do
1846 not nul-terminate the copy while allowing for the idiom where
1847 such a call is immediately followed by setting the last element
1850 strncpy (a, s, sizeof a);
1851 a[sizeof a - 1] = '\0';
1855 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi
, tree src
, tree cnt
)
1857 gimple
*stmt
= gsi_stmt (gsi
);
1858 if (gimple_no_warning_p (stmt
))
1861 wide_int cntrange
[2];
1863 if (TREE_CODE (cnt
) == INTEGER_CST
)
1864 cntrange
[0] = cntrange
[1] = wi::to_wide (cnt
);
1865 else if (TREE_CODE (cnt
) == SSA_NAME
)
1867 enum value_range_type rng
= get_range_info (cnt
, cntrange
, cntrange
+ 1);
1868 if (rng
== VR_RANGE
)
1870 else if (rng
== VR_ANTI_RANGE
)
1872 wide_int maxobjsize
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
));
1874 if (wi::ltu_p (cntrange
[1], maxobjsize
))
1876 cntrange
[0] = cntrange
[1] + 1;
1877 cntrange
[1] = maxobjsize
;
1881 cntrange
[1] = cntrange
[0] - 1;
1882 cntrange
[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt
)));
1891 /* Negative value is the constant string length. If it's less than
1892 the lower bound there is no truncation. Avoid calling get_stridx()
1893 when ssa_ver_to_stridx is empty. That implies the caller isn't
1894 running under the control of this pass and ssa_ver_to_stridx hasn't
1895 been created yet. */
1896 int sidx
= ssa_ver_to_stridx
.length () ? get_stridx (src
) : 0;
1897 if (sidx
< 0 && wi::gtu_p (cntrange
[0], ~sidx
))
1900 tree dst
= gimple_call_arg (stmt
, 0);
1902 if (TREE_CODE (dstdecl
) == ADDR_EXPR
)
1903 dstdecl
= TREE_OPERAND (dstdecl
, 0);
1905 tree ref
= NULL_TREE
;
1909 /* If the source is a non-string return early to avoid warning
1910 for possible truncation (if the truncation is certain SIDX
1912 tree srcdecl
= gimple_call_arg (stmt
, 1);
1913 if (TREE_CODE (srcdecl
) == ADDR_EXPR
)
1914 srcdecl
= TREE_OPERAND (srcdecl
, 0);
1915 if (get_attr_nonstring_decl (srcdecl
, &ref
))
1919 /* Likewise, if the destination refers to a an array/pointer declared
1920 nonstring return early. */
1921 if (get_attr_nonstring_decl (dstdecl
, &ref
))
1924 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1925 avoid the truncation warning. */
1926 gsi_next_nondebug (&gsi
);
1927 gimple
*next_stmt
= gsi_stmt (gsi
);
1930 /* When there is no statement in the same basic block check
1931 the immediate successor block. */
1932 if (basic_block bb
= gimple_bb (stmt
))
1934 if (single_succ_p (bb
))
1936 /* For simplicity, ignore blocks with multiple outgoing
1937 edges for now and only consider successor blocks along
1939 edge e
= EDGE_SUCC (bb
, 0);
1940 if (!(e
->flags
& EDGE_ABNORMAL
))
1942 gsi
= gsi_start_bb (e
->dest
);
1943 next_stmt
= gsi_stmt (gsi
);
1944 if (next_stmt
&& is_gimple_debug (next_stmt
))
1946 gsi_next_nondebug (&gsi
);
1947 next_stmt
= gsi_stmt (gsi
);
1954 if (next_stmt
&& is_gimple_assign (next_stmt
))
1956 tree lhs
= gimple_assign_lhs (next_stmt
);
1957 tree_code code
= TREE_CODE (lhs
);
1958 if (code
== ARRAY_REF
|| code
== MEM_REF
)
1959 lhs
= TREE_OPERAND (lhs
, 0);
1961 tree func
= gimple_call_fndecl (stmt
);
1962 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STPNCPY
)
1964 tree ret
= gimple_call_lhs (stmt
);
1965 if (ret
&& operand_equal_p (ret
, lhs
, 0))
1969 /* Determine the base address and offset of the reference,
1970 ignoring the innermost array index. */
1971 if (TREE_CODE (ref
) == ARRAY_REF
)
1972 ref
= TREE_OPERAND (ref
, 0);
1975 tree dstbase
= get_addr_base_and_unit_offset (ref
, &dstoff
);
1978 tree lhsbase
= get_addr_base_and_unit_offset (lhs
, &lhsoff
);
1981 && known_eq (dstoff
, lhsoff
)
1982 && operand_equal_p (dstbase
, lhsbase
, 0))
1986 int prec
= TYPE_PRECISION (TREE_TYPE (cnt
));
1987 wide_int lenrange
[2];
1988 if (strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
)
1990 lenrange
[0] = (sisrc
->nonzero_chars
1991 && TREE_CODE (sisrc
->nonzero_chars
) == INTEGER_CST
1992 ? wi::to_wide (sisrc
->nonzero_chars
)
1994 lenrange
[1] = lenrange
[0];
1997 lenrange
[0] = lenrange
[1] = wi::shwi (~sidx
, prec
);
2001 get_range_strlen (src
, range
);
2002 if (range
[0] != NULL_TREE
2003 && TREE_CODE (range
[0]) == INTEGER_CST
2004 && range
[1] != NULL_TREE
2005 && TREE_CODE (range
[1]) == INTEGER_CST
)
2007 lenrange
[0] = wi::to_wide (range
[0], prec
);
2008 lenrange
[1] = wi::to_wide (range
[1], prec
);
2012 lenrange
[0] = wi::shwi (0, prec
);
2013 lenrange
[1] = wi::shwi (-1, prec
);
2017 location_t callloc
= gimple_nonartificial_location (stmt
);
2018 callloc
= expansion_point_location_if_in_system_header (callloc
);
2020 tree func
= gimple_call_fndecl (stmt
);
2022 if (lenrange
[0] != 0 || !wi::neg_p (lenrange
[1]))
2024 /* If the longest source string is shorter than the lower bound
2025 of the specified count the copy is definitely nul-terminated. */
2026 if (wi::ltu_p (lenrange
[1], cntrange
[0]))
2029 if (wi::neg_p (lenrange
[1]))
2031 /* The length of one of the strings is unknown but at least
2032 one has non-zero length and that length is stored in
2033 LENRANGE[1]. Swap the bounds to force a "may be truncated"
2035 lenrange
[1] = lenrange
[0];
2036 lenrange
[0] = wi::shwi (0, prec
);
2039 gcall
*call
= as_a
<gcall
*> (stmt
);
2041 /* Set to true for strncat whose bound is derived from the length
2042 of the destination (the expected usage pattern). */
2043 bool cat_dstlen_bounded
= false;
2044 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STRNCAT
)
2045 cat_dstlen_bounded
= is_strlen_related_p (dst
, cnt
);
2047 if (lenrange
[0] == cntrange
[1] && cntrange
[0] == cntrange
[1])
2048 return warning_n (callloc
, OPT_Wstringop_truncation
,
2049 cntrange
[0].to_uhwi (),
2050 "%G%qD output truncated before terminating "
2051 "nul copying %E byte from a string of the "
2053 "%G%qD output truncated before terminating nul "
2054 "copying %E bytes from a string of the same "
2057 else if (!cat_dstlen_bounded
)
2059 if (wi::geu_p (lenrange
[0], cntrange
[1]))
2061 /* The shortest string is longer than the upper bound of
2062 the count so the truncation is certain. */
2063 if (cntrange
[0] == cntrange
[1])
2064 return warning_n (callloc
, OPT_Wstringop_truncation
,
2065 cntrange
[0].to_uhwi (),
2066 "%G%qD output truncated copying %E byte "
2067 "from a string of length %wu",
2068 "%G%qD output truncated copying %E bytes "
2069 "from a string of length %wu",
2070 call
, func
, cnt
, lenrange
[0].to_uhwi ());
2072 return warning_at (callloc
, OPT_Wstringop_truncation
,
2073 "%G%qD output truncated copying between %wu "
2074 "and %wu bytes from a string of length %wu",
2075 call
, func
, cntrange
[0].to_uhwi (),
2076 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
2078 else if (wi::geu_p (lenrange
[1], cntrange
[1]))
2080 /* The longest string is longer than the upper bound of
2081 the count so the truncation is possible. */
2082 if (cntrange
[0] == cntrange
[1])
2083 return warning_n (callloc
, OPT_Wstringop_truncation
,
2084 cntrange
[0].to_uhwi (),
2085 "%G%qD output may be truncated copying %E "
2086 "byte from a string of length %wu",
2087 "%G%qD output may be truncated copying %E "
2088 "bytes from a string of length %wu",
2089 call
, func
, cnt
, lenrange
[1].to_uhwi ());
2091 return warning_at (callloc
, OPT_Wstringop_truncation
,
2092 "%G%qD output may be truncated copying between "
2093 "%wu and %wu bytes from a string of length %wu",
2094 call
, func
, cntrange
[0].to_uhwi (),
2095 cntrange
[1].to_uhwi (), lenrange
[1].to_uhwi ());
2099 if (!cat_dstlen_bounded
2100 && cntrange
[0] != cntrange
[1]
2101 && wi::leu_p (cntrange
[0], lenrange
[0])
2102 && wi::leu_p (cntrange
[1], lenrange
[0] + 1))
2104 /* If the source (including the terminating nul) is longer than
2105 the lower bound of the specified count but shorter than the
2106 upper bound the copy may (but need not) be truncated. */
2107 return warning_at (callloc
, OPT_Wstringop_truncation
,
2108 "%G%qD output may be truncated copying between "
2109 "%wu and %wu bytes from a string of length %wu",
2110 call
, func
, cntrange
[0].to_uhwi (),
2111 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
2115 if (tree dstsize
= compute_objsize (dst
, 1))
2117 /* The source length is uknown. Try to determine the destination
2118 size and see if it matches the specified bound. If not, bail.
2119 Otherwise go on to see if it should be diagnosed for possible
2124 if (wi::to_wide (dstsize
) != cntrange
[1])
2127 if (cntrange
[0] == cntrange
[1])
2128 return warning_at (callloc
, OPT_Wstringop_truncation
,
2129 "%G%qD specified bound %E equals destination size",
2130 as_a
<gcall
*> (stmt
), func
, cnt
);
2136 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2137 out-of-bounds offsets or overlapping access, and to see if the size
2138 is derived from calling strlen() on the source argument, and if so,
2139 issue the appropriate warning. */
2142 handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*gsi
)
2144 if (!strlen_to_stridx
)
2147 gimple
*stmt
= gsi_stmt (*gsi
);
2149 tree dst
= gimple_call_arg (stmt
, 0);
2150 tree src
= gimple_call_arg (stmt
, 1);
2151 tree len
= gimple_call_arg (stmt
, 2);
2152 tree dstsize
= NULL_TREE
, srcsize
= NULL_TREE
;
2154 int didx
= get_stridx (dst
);
2155 if (strinfo
*sidst
= didx
> 0 ? get_strinfo (didx
) : NULL
)
2157 /* Compute the size of the destination string including the NUL. */
2158 if (sidst
->nonzero_chars
)
2160 tree type
= TREE_TYPE (sidst
->nonzero_chars
);
2161 dstsize
= fold_build2 (PLUS_EXPR
, type
, sidst
->nonzero_chars
,
2162 build_int_cst (type
, 1));
2167 int sidx
= get_stridx (src
);
2168 strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
;
2171 /* strncat() and strncpy() can modify the source string by writing
2172 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2175 /* Compute the size of the source string including the NUL. */
2176 if (sisrc
->nonzero_chars
)
2178 tree type
= TREE_TYPE (sisrc
->nonzero_chars
);
2179 srcsize
= fold_build2 (PLUS_EXPR
, type
, sisrc
->nonzero_chars
,
2180 build_int_cst (type
, 1));
2186 srcsize
= NULL_TREE
;
2188 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, src
,
2191 gimple_set_no_warning (stmt
, true);
2195 /* If the length argument was computed from strlen(S) for some string
2196 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2197 the location of the strlen() call (PSS->SECOND). */
2198 stridx_strlenloc
*pss
= strlen_to_stridx
->get (len
);
2199 if (!pss
|| pss
->first
<= 0)
2201 if (maybe_diag_stxncpy_trunc (*gsi
, src
, len
))
2202 gimple_set_no_warning (stmt
, true);
2207 /* Retrieve the strinfo data for the string S that LEN was computed
2208 from as some function F of strlen (S) (i.e., LEN need not be equal
2210 strinfo
*silen
= get_strinfo (pss
->first
);
2212 location_t callloc
= gimple_nonartificial_location (stmt
);
2213 callloc
= expansion_point_location_if_in_system_header (callloc
);
2215 tree func
= gimple_call_fndecl (stmt
);
2217 bool warned
= false;
2219 /* When -Wstringop-truncation is set, try to determine truncation
2220 before diagnosing possible overflow. Truncation is implied by
2221 the LEN argument being equal to strlen(SRC), regardless of
2222 whether its value is known. Otherwise, issue the more generic
2223 -Wstringop-overflow which triggers for LEN arguments that in
2224 any meaningful way depend on strlen(SRC). */
2226 && is_strlen_related_p (src
, len
)
2227 && warning_at (callloc
, OPT_Wstringop_truncation
,
2228 "%G%qD output truncated before terminating nul "
2229 "copying as many bytes from a string as its length",
2230 as_a
<gcall
*>(stmt
), func
))
2232 else if (silen
&& is_strlen_related_p (src
, silen
->ptr
))
2233 warned
= warning_at (callloc
, OPT_Wstringop_overflow_
,
2234 "%G%qD specified bound depends on the length "
2235 "of the source argument",
2236 as_a
<gcall
*>(stmt
), func
);
2239 location_t strlenloc
= pss
->second
;
2240 if (strlenloc
!= UNKNOWN_LOCATION
&& strlenloc
!= callloc
)
2241 inform (strlenloc
, "length computed here");
2245 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2246 If strlen of the second argument is known and length of the third argument
2247 is that plus one, strlen of the first argument is the same after this
2251 handle_builtin_memcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2254 tree src
, dst
, len
, lhs
, oldlen
, newlen
;
2255 gimple
*stmt
= gsi_stmt (*gsi
);
2256 strinfo
*si
, *dsi
, *olddsi
;
2258 len
= gimple_call_arg (stmt
, 2);
2259 src
= gimple_call_arg (stmt
, 1);
2260 dst
= gimple_call_arg (stmt
, 0);
2261 idx
= get_stridx (src
);
2265 didx
= get_stridx (dst
);
2268 olddsi
= get_strinfo (didx
);
2273 && tree_fits_uhwi_p (len
)
2274 && !integer_zerop (len
))
2275 adjust_last_stmt (olddsi
, stmt
, false);
2282 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2284 si
= get_strinfo (idx
);
2285 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2287 if (TREE_CODE (len
) == INTEGER_CST
2288 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
2290 if (tree_int_cst_le (len
, si
->nonzero_chars
))
2292 /* Copying LEN nonzero characters, where LEN is constant. */
2294 full_string_p
= false;
2298 /* Copying the whole of the analyzed part of SI. */
2299 newlen
= si
->nonzero_chars
;
2300 full_string_p
= si
->full_string_p
;
2305 if (!si
->full_string_p
)
2307 if (TREE_CODE (len
) != SSA_NAME
)
2309 def_stmt
= SSA_NAME_DEF_STMT (len
);
2310 if (!is_gimple_assign (def_stmt
)
2311 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
2312 || gimple_assign_rhs1 (def_stmt
) != si
->nonzero_chars
2313 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
2315 /* Copying variable-length string SI (and no more). */
2316 newlen
= si
->nonzero_chars
;
2317 full_string_p
= true;
2323 /* Handle memcpy (x, "abcd", 5) or
2324 memcpy (x, "abc\0uvw", 7). */
2325 if (!tree_fits_uhwi_p (len
))
2328 unsigned HOST_WIDE_INT clen
= tree_to_uhwi (len
);
2329 unsigned HOST_WIDE_INT nonzero_chars
= ~idx
;
2330 newlen
= build_int_cst (size_type_node
, MIN (nonzero_chars
, clen
));
2331 full_string_p
= clen
> nonzero_chars
;
2334 if (olddsi
!= NULL
&& TREE_CODE (len
) == SSA_NAME
)
2335 adjust_last_stmt (olddsi
, stmt
, false);
2339 didx
= new_stridx (dst
);
2346 dsi
= unshare_strinfo (olddsi
);
2347 oldlen
= olddsi
->nonzero_chars
;
2348 dsi
->nonzero_chars
= newlen
;
2349 dsi
->full_string_p
= full_string_p
;
2350 /* Break the chain, so adjust_related_strinfo on later pointers in
2351 the chain won't adjust this one anymore. */
2354 dsi
->endptr
= NULL_TREE
;
2358 dsi
= new_strinfo (dst
, didx
, newlen
, full_string_p
);
2359 set_strinfo (didx
, dsi
);
2360 find_equal_ptrs (dst
, didx
);
2362 dsi
->writable
= true;
2363 dsi
->dont_invalidate
= true;
2366 tree adj
= NULL_TREE
;
2367 location_t loc
= gimple_location (stmt
);
2368 if (oldlen
== NULL_TREE
)
2370 else if (integer_zerop (oldlen
))
2372 else if (TREE_CODE (oldlen
) == INTEGER_CST
2373 || TREE_CODE (newlen
) == INTEGER_CST
)
2374 adj
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (newlen
), newlen
,
2375 fold_convert_loc (loc
, TREE_TYPE (newlen
),
2377 if (adj
!= NULL_TREE
)
2378 adjust_related_strinfos (loc
, dsi
, adj
);
2382 /* memcpy src may not overlap dst, so src doesn't need to be
2383 invalidated either. */
2385 si
->dont_invalidate
= true;
2389 lhs
= gimple_call_lhs (stmt
);
2392 case BUILT_IN_MEMCPY
:
2393 case BUILT_IN_MEMCPY_CHK
:
2394 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2395 laststmt
.stmt
= stmt
;
2396 laststmt
.len
= dsi
->nonzero_chars
;
2397 laststmt
.stridx
= dsi
->idx
;
2399 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
2401 case BUILT_IN_MEMPCPY
:
2402 case BUILT_IN_MEMPCPY_CHK
:
2410 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2411 If strlen of the second argument is known, strlen of the first argument
2412 is increased by the length of the second argument. Furthermore, attempt
2413 to convert it to memcpy/strcpy if the length of the first argument
2417 handle_builtin_strcat (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2420 tree srclen
, args
, type
, fn
, objsz
, endptr
;
2422 gimple
*stmt
= gsi_stmt (*gsi
);
2424 location_t loc
= gimple_location (stmt
);
2426 tree src
= gimple_call_arg (stmt
, 1);
2427 tree dst
= gimple_call_arg (stmt
, 0);
2429 /* Bail if the source is the same as destination. It will be diagnosed
2431 if (operand_equal_p (src
, dst
, 0))
2434 tree lhs
= gimple_call_lhs (stmt
);
2436 didx
= get_stridx (dst
);
2442 dsi
= get_strinfo (didx
);
2446 idx
= get_stridx (src
);
2448 srclen
= build_int_cst (size_type_node
, ~idx
);
2451 si
= get_strinfo (idx
);
2453 srclen
= get_string_length (si
);
2456 /* Set the no-warning bit on the transformed statement? */
2457 bool set_no_warning
= false;
2459 if (dsi
== NULL
|| get_string_length (dsi
) == NULL_TREE
)
2462 /* The concatenation always involves copying at least one byte
2463 (the terminating nul), even if the source string is empty.
2464 If the source is unknown assume it's one character long and
2465 used that as both sizes. */
2469 tree type
= TREE_TYPE (slen
);
2470 slen
= fold_build2 (PLUS_EXPR
, type
, slen
, build_int_cst (type
, 1));
2473 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2475 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2478 gimple_set_no_warning (stmt
, true);
2479 set_no_warning
= true;
2483 /* strcat (p, q) can be transformed into
2484 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2485 with length endptr - p if we need to compute the length
2486 later on. Don't do this transformation if we don't need
2488 if (builtin_decl_implicit_p (BUILT_IN_STPCPY
) && lhs
== NULL_TREE
)
2492 didx
= new_stridx (dst
);
2498 dsi
= new_strinfo (dst
, didx
, NULL_TREE
, false);
2499 set_strinfo (didx
, dsi
);
2500 find_equal_ptrs (dst
, didx
);
2504 dsi
= unshare_strinfo (dsi
);
2505 dsi
->nonzero_chars
= NULL_TREE
;
2506 dsi
->full_string_p
= false;
2508 dsi
->endptr
= NULL_TREE
;
2510 dsi
->writable
= true;
2512 dsi
->dont_invalidate
= true;
2517 tree dstlen
= dsi
->nonzero_chars
;
2518 endptr
= dsi
->endptr
;
2520 dsi
= unshare_strinfo (dsi
);
2521 dsi
->endptr
= NULL_TREE
;
2523 dsi
->writable
= true;
2525 if (srclen
!= NULL_TREE
)
2527 dsi
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
2528 TREE_TYPE (dsi
->nonzero_chars
),
2529 dsi
->nonzero_chars
, srclen
);
2530 gcc_assert (dsi
->full_string_p
);
2531 adjust_related_strinfos (loc
, dsi
, srclen
);
2532 dsi
->dont_invalidate
= true;
2536 dsi
->nonzero_chars
= NULL
;
2537 dsi
->full_string_p
= false;
2538 if (lhs
== NULL_TREE
&& builtin_decl_implicit_p (BUILT_IN_STPCPY
))
2539 dsi
->dont_invalidate
= true;
2543 /* strcat src may not overlap dst, so src doesn't need to be
2544 invalidated either. */
2545 si
->dont_invalidate
= true;
2547 /* For now. Could remove the lhs from the call and add
2548 lhs = dst; afterwards. */
2556 case BUILT_IN_STRCAT
:
2557 if (srclen
!= NULL_TREE
)
2558 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
2560 fn
= builtin_decl_implicit (BUILT_IN_STRCPY
);
2562 case BUILT_IN_STRCAT_CHK
:
2563 if (srclen
!= NULL_TREE
)
2564 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
2566 fn
= builtin_decl_explicit (BUILT_IN_STRCPY_CHK
);
2567 objsz
= gimple_call_arg (stmt
, 2);
2573 if (fn
== NULL_TREE
)
2578 tree type
= TREE_TYPE (dstlen
);
2580 /* Compute the size of the source sequence, including the nul. */
2581 tree srcsize
= srclen
? srclen
: size_zero_node
;
2582 srcsize
= fold_build2 (PLUS_EXPR
, type
, srcsize
, build_int_cst (type
, 1));
2584 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2586 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2589 gimple_set_no_warning (stmt
, true);
2590 set_no_warning
= true;
2594 tree len
= NULL_TREE
;
2595 if (srclen
!= NULL_TREE
)
2597 args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2598 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
2600 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
2601 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
,
2602 build_int_cst (type
, 1));
2603 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
2607 dst
= fold_convert_loc (loc
, TREE_TYPE (dst
), unshare_expr (endptr
));
2609 dst
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
2610 TREE_TYPE (dst
), unshare_expr (dst
),
2611 fold_convert_loc (loc
, sizetype
,
2612 unshare_expr (dstlen
)));
2613 dst
= force_gimple_operand_gsi (gsi
, dst
, true, NULL_TREE
, true,
2615 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2617 fprintf (dump_file
, "Optimizing: ");
2618 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2620 if (srclen
!= NULL_TREE
)
2621 success
= update_gimple_call (gsi
, fn
, 3 + (objsz
!= NULL_TREE
),
2622 dst
, src
, len
, objsz
);
2624 success
= update_gimple_call (gsi
, fn
, 2 + (objsz
!= NULL_TREE
),
2628 stmt
= gsi_stmt (*gsi
);
2630 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2632 fprintf (dump_file
, "into: ");
2633 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2635 /* If srclen == NULL, note that current string length can be
2636 computed by transforming this strcpy into stpcpy. */
2637 if (srclen
== NULL_TREE
&& dsi
->dont_invalidate
)
2639 adjust_last_stmt (dsi
, stmt
, true);
2640 if (srclen
!= NULL_TREE
)
2642 laststmt
.stmt
= stmt
;
2643 laststmt
.len
= srclen
;
2644 laststmt
.stridx
= dsi
->idx
;
2647 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2648 fprintf (dump_file
, "not possible.\n");
2651 gimple_set_no_warning (stmt
, true);
2654 /* Handle a call to malloc or calloc. */
2657 handle_builtin_malloc (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2659 gimple
*stmt
= gsi_stmt (*gsi
);
2660 tree lhs
= gimple_call_lhs (stmt
);
2661 if (lhs
== NULL_TREE
)
2664 gcc_assert (get_stridx (lhs
) == 0);
2665 int idx
= new_stridx (lhs
);
2666 tree length
= NULL_TREE
;
2667 if (bcode
== BUILT_IN_CALLOC
)
2668 length
= build_int_cst (size_type_node
, 0);
2669 strinfo
*si
= new_strinfo (lhs
, idx
, length
, length
!= NULL_TREE
);
2670 if (bcode
== BUILT_IN_CALLOC
)
2672 set_strinfo (idx
, si
);
2673 si
->writable
= true;
2675 si
->dont_invalidate
= true;
2678 /* Handle a call to memset.
2679 After a call to calloc, memset(,0,) is unnecessary.
2680 memset(malloc(n),0,n) is calloc(n,1).
2681 return true when the call is transfomred, false otherwise. */
2684 handle_builtin_memset (gimple_stmt_iterator
*gsi
)
2686 gimple
*stmt2
= gsi_stmt (*gsi
);
2687 if (!integer_zerop (gimple_call_arg (stmt2
, 1)))
2689 tree ptr
= gimple_call_arg (stmt2
, 0);
2690 int idx1
= get_stridx (ptr
);
2693 strinfo
*si1
= get_strinfo (idx1
);
2696 gimple
*stmt1
= si1
->stmt
;
2697 if (!stmt1
|| !is_gimple_call (stmt1
))
2699 tree callee1
= gimple_call_fndecl (stmt1
);
2700 if (!valid_builtin_call (stmt1
))
2702 enum built_in_function code1
= DECL_FUNCTION_CODE (callee1
);
2703 tree size
= gimple_call_arg (stmt2
, 2);
2704 if (code1
== BUILT_IN_CALLOC
)
2705 /* Not touching stmt1 */ ;
2706 else if (code1
== BUILT_IN_MALLOC
2707 && operand_equal_p (gimple_call_arg (stmt1
, 0), size
, 0))
2709 gimple_stmt_iterator gsi1
= gsi_for_stmt (stmt1
);
2710 update_gimple_call (&gsi1
, builtin_decl_implicit (BUILT_IN_CALLOC
), 2,
2711 size
, build_one_cst (size_type_node
));
2712 si1
->nonzero_chars
= build_int_cst (size_type_node
, 0);
2713 si1
->full_string_p
= true;
2714 si1
->stmt
= gsi_stmt (gsi1
);
2718 tree lhs
= gimple_call_lhs (stmt2
);
2719 unlink_stmt_vdef (stmt2
);
2722 gimple
*assign
= gimple_build_assign (lhs
, ptr
);
2723 gsi_replace (gsi
, assign
, false);
2727 gsi_remove (gsi
, true);
2728 release_defs (stmt2
);
2734 /* Handle a call to memcmp. We try to handle small comparisons by
2735 converting them to load and compare, and replacing the call to memcmp
2736 with a __builtin_memcmp_eq call where possible.
2737 return true when call is transformed, return false otherwise. */
2740 handle_builtin_memcmp (gimple_stmt_iterator
*gsi
)
2742 gcall
*stmt2
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2743 tree res
= gimple_call_lhs (stmt2
);
2744 tree arg1
= gimple_call_arg (stmt2
, 0);
2745 tree arg2
= gimple_call_arg (stmt2
, 1);
2746 tree len
= gimple_call_arg (stmt2
, 2);
2747 unsigned HOST_WIDE_INT leni
;
2748 use_operand_p use_p
;
2749 imm_use_iterator iter
;
2754 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2756 gimple
*ustmt
= USE_STMT (use_p
);
2758 if (is_gimple_debug (ustmt
))
2760 if (gimple_code (ustmt
) == GIMPLE_ASSIGN
)
2762 gassign
*asgn
= as_a
<gassign
*> (ustmt
);
2763 tree_code code
= gimple_assign_rhs_code (asgn
);
2764 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2765 || !integer_zerop (gimple_assign_rhs2 (asgn
)))
2768 else if (gimple_code (ustmt
) == GIMPLE_COND
)
2770 tree_code code
= gimple_cond_code (ustmt
);
2771 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2772 || !integer_zerop (gimple_cond_rhs (ustmt
)))
2779 if (tree_fits_uhwi_p (len
)
2780 && (leni
= tree_to_uhwi (len
)) <= GET_MODE_SIZE (word_mode
)
2781 && pow2p_hwi (leni
))
2783 leni
*= CHAR_TYPE_SIZE
;
2784 unsigned align1
= get_pointer_alignment (arg1
);
2785 unsigned align2
= get_pointer_alignment (arg2
);
2786 unsigned align
= MIN (align1
, align2
);
2787 scalar_int_mode mode
;
2788 if (int_mode_for_size (leni
, 1).exists (&mode
)
2789 && (align
>= leni
|| !targetm
.slow_unaligned_access (mode
, align
)))
2791 location_t loc
= gimple_location (stmt2
);
2793 type
= build_nonstandard_integer_type (leni
, 1);
2794 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type
)), leni
));
2795 tree ptrtype
= build_pointer_type_for_mode (char_type_node
,
2797 off
= build_int_cst (ptrtype
, 0);
2798 arg1
= build2_loc (loc
, MEM_REF
, type
, arg1
, off
);
2799 arg2
= build2_loc (loc
, MEM_REF
, type
, arg2
, off
);
2800 tree tem1
= fold_const_aggregate_ref (arg1
);
2803 tree tem2
= fold_const_aggregate_ref (arg2
);
2806 res
= fold_convert_loc (loc
, TREE_TYPE (res
),
2807 fold_build2_loc (loc
, NE_EXPR
,
2810 gimplify_and_update_call_from_tree (gsi
, res
);
2815 gimple_call_set_fndecl (stmt2
, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ
));
2819 /* Given an index to the strinfo vector, compute the string length for the
2820 corresponding string. Return -1 when unknown. */
2822 static HOST_WIDE_INT
2823 compute_string_length (int idx
)
2825 HOST_WIDE_INT string_leni
= -1;
2826 gcc_assert (idx
!= 0);
2831 strinfo
*si
= get_strinfo (idx
);
2834 tree const_string_len
= get_string_length (si
);
2835 if (const_string_len
&& tree_fits_shwi_p (const_string_len
))
2836 string_leni
= tree_to_shwi (const_string_len
);
2839 if (string_leni
< 0)
2845 /* Determine the minimum size of the object referenced by DEST expression which
2846 must have a pointer type.
2847 Return the minimum size of the object if successful or NULL when the size
2848 cannot be determined. */
2850 determine_min_objsize (tree dest
)
2852 unsigned HOST_WIDE_INT size
= 0;
2854 if (compute_builtin_object_size (dest
, 2, &size
))
2855 return build_int_cst (sizetype
, size
);
2857 /* Try to determine the size of the object through the RHS of the
2858 assign statement. */
2859 if (TREE_CODE (dest
) == SSA_NAME
)
2861 gimple
*stmt
= SSA_NAME_DEF_STMT (dest
);
2862 if (!is_gimple_assign (stmt
))
2865 if (!gimple_assign_single_p (stmt
)
2866 && !gimple_assign_unary_nop_p (stmt
))
2869 dest
= gimple_assign_rhs1 (stmt
);
2870 return determine_min_objsize (dest
);
2873 /* Try to determine the size of the object from its type. */
2874 if (TREE_CODE (dest
) != ADDR_EXPR
)
2877 tree type
= TREE_TYPE (dest
);
2878 if (TREE_CODE (type
) == POINTER_TYPE
)
2879 type
= TREE_TYPE (type
);
2881 type
= TYPE_MAIN_VARIANT (type
);
2883 /* We cannot determine the size of the array if it's a flexible array,
2884 which is declared at the end of a structure. */
2885 if (TREE_CODE (type
) == ARRAY_TYPE
2886 && !array_at_struct_end_p (dest
))
2888 tree
size_t = TYPE_SIZE_UNIT (type
);
2889 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2890 && !integer_zerop (size_t))
2897 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2898 equality test against zero:
2900 A. When the lengths of both arguments are constant and it's a strcmp:
2901 * if the lengths are NOT equal, we can safely fold the call
2902 to a non-zero value.
2903 * otherwise, do nothing now.
2905 B. When the length of one argument is constant, try to replace the call with
2906 a __builtin_str(n)cmp_eq call where possible, i.e:
2908 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2909 string with constant length , C is a constant.
2910 if (C <= strlen(STR) && sizeof_array(s) > C)
2912 replace this call with
2913 strncmp_eq (s, STR, C) (!)= 0
2917 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2918 can handled by the following strcmp.
2921 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2922 string with constant length.
2923 if (sizeof_array(s) > strlen(STR))
2925 replace this call with
2926 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2929 Return true when the call is transformed, return false otherwise.
2933 handle_builtin_string_cmp (gimple_stmt_iterator
*gsi
)
2935 gcall
*stmt
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2936 tree res
= gimple_call_lhs (stmt
);
2937 use_operand_p use_p
;
2938 imm_use_iterator iter
;
2939 tree arg1
= gimple_call_arg (stmt
, 0);
2940 tree arg2
= gimple_call_arg (stmt
, 1);
2941 int idx1
= get_stridx (arg1
);
2942 int idx2
= get_stridx (arg2
);
2943 HOST_WIDE_INT length
= -1;
2944 bool is_ncmp
= false;
2949 /* When both arguments are unknown, do nothing. */
2950 if (idx1
== 0 && idx2
== 0)
2953 /* Handle strncmp function. */
2954 if (gimple_call_num_args (stmt
) == 3)
2956 tree len
= gimple_call_arg (stmt
, 2);
2957 if (tree_fits_shwi_p (len
))
2958 length
= tree_to_shwi (len
);
2963 /* For strncmp, if the length argument is NOT known, do nothing. */
2964 if (is_ncmp
&& length
< 0)
2967 /* When the result is ONLY used to do equality test against zero. */
2968 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2970 gimple
*use_stmt
= USE_STMT (use_p
);
2972 if (is_gimple_debug (use_stmt
))
2974 if (gimple_code (use_stmt
) == GIMPLE_ASSIGN
)
2976 tree_code code
= gimple_assign_rhs_code (use_stmt
);
2977 if (code
== COND_EXPR
)
2979 tree cond_expr
= gimple_assign_rhs1 (use_stmt
);
2980 if ((TREE_CODE (cond_expr
) != EQ_EXPR
2981 && (TREE_CODE (cond_expr
) != NE_EXPR
))
2982 || !integer_zerop (TREE_OPERAND (cond_expr
, 1)))
2985 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
2987 if (!integer_zerop (gimple_assign_rhs2 (use_stmt
)))
2993 else if (gimple_code (use_stmt
) == GIMPLE_COND
)
2995 tree_code code
= gimple_cond_code (use_stmt
);
2996 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2997 || !integer_zerop (gimple_cond_rhs (use_stmt
)))
3004 /* When the lengths of both arguments are known, and they are unequal, we can
3005 safely fold the call to a non-zero value for strcmp;
3006 othewise, do nothing now. */
3007 if (idx1
!= 0 && idx2
!= 0)
3009 HOST_WIDE_INT const_string_leni1
= compute_string_length (idx1
);
3010 HOST_WIDE_INT const_string_leni2
= compute_string_length (idx2
);
3013 && const_string_leni1
!= -1
3014 && const_string_leni2
!= -1
3015 && const_string_leni1
!= const_string_leni2
)
3017 replace_call_with_value (gsi
, integer_one_node
);
3023 /* When the length of one argument is constant. */
3024 tree var_string
= NULL_TREE
;
3025 HOST_WIDE_INT const_string_leni
= -1;
3029 const_string_leni
= compute_string_length (idx1
);
3034 gcc_checking_assert (idx2
);
3035 const_string_leni
= compute_string_length (idx2
);
3039 if (const_string_leni
< 0)
3042 unsigned HOST_WIDE_INT var_sizei
= 0;
3043 /* try to determine the minimum size of the object pointed by var_string. */
3044 tree size
= determine_min_objsize (var_string
);
3049 if (tree_fits_uhwi_p (size
))
3050 var_sizei
= tree_to_uhwi (size
);
3055 /* For strncmp, if length > const_string_leni , this call can be safely
3056 transformed to a strcmp. */
3057 if (is_ncmp
&& length
> const_string_leni
)
3060 unsigned HOST_WIDE_INT final_length
3061 = is_ncmp
? length
: const_string_leni
+ 1;
3063 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
3064 if (var_sizei
> final_length
)
3068 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ
)
3069 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ
));
3072 tree const_string_len
= build_int_cst (size_type_node
, final_length
);
3073 update_gimple_call (gsi
, fn
, 3, arg1
, arg2
, const_string_len
);
3081 /* Handle a POINTER_PLUS_EXPR statement.
3082 For p = "abcd" + 2; compute associated length, or if
3083 p = q + off is pointing to a '\0' character of a string, call
3084 zero_length_string on it. */
3087 handle_pointer_plus (gimple_stmt_iterator
*gsi
)
3089 gimple
*stmt
= gsi_stmt (*gsi
);
3090 tree lhs
= gimple_assign_lhs (stmt
), off
;
3091 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3099 tree off
= gimple_assign_rhs2 (stmt
);
3100 if (tree_fits_uhwi_p (off
)
3101 && tree_to_uhwi (off
) <= (unsigned HOST_WIDE_INT
) ~idx
)
3102 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)]
3103 = ~(~idx
- (int) tree_to_uhwi (off
));
3107 si
= get_strinfo (idx
);
3108 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
3111 off
= gimple_assign_rhs2 (stmt
);
3113 if (si
->full_string_p
&& operand_equal_p (si
->nonzero_chars
, off
, 0))
3114 zsi
= zero_length_string (lhs
, si
);
3115 else if (TREE_CODE (off
) == SSA_NAME
)
3117 gimple
*def_stmt
= SSA_NAME_DEF_STMT (off
);
3118 if (gimple_assign_single_p (def_stmt
)
3119 && si
->full_string_p
3120 && operand_equal_p (si
->nonzero_chars
,
3121 gimple_assign_rhs1 (def_stmt
), 0))
3122 zsi
= zero_length_string (lhs
, si
);
3125 && si
->endptr
!= NULL_TREE
3126 && si
->endptr
!= lhs
3127 && TREE_CODE (si
->endptr
) == SSA_NAME
)
3129 enum tree_code rhs_code
3130 = useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (si
->endptr
))
3131 ? SSA_NAME
: NOP_EXPR
;
3132 gimple_assign_set_rhs_with_ops (gsi
, rhs_code
, si
->endptr
);
3133 gcc_assert (gsi_stmt (*gsi
) == stmt
);
3138 /* If RHS, either directly or indirectly, refers to a string of constant
3139 length, return it. Otherwise return a negative value. */
3141 static HOST_WIDE_INT
3142 get_string_cst_length (tree rhs
)
3144 if (TREE_CODE (rhs
) == MEM_REF
3145 && integer_zerop (TREE_OPERAND (rhs
, 1)))
3147 rhs
= TREE_OPERAND (rhs
, 0);
3148 if (TREE_CODE (rhs
) == ADDR_EXPR
)
3150 tree rhs_addr
= rhs
;
3152 rhs
= TREE_OPERAND (rhs
, 0);
3153 if (TREE_CODE (rhs
) != STRING_CST
)
3155 int idx
= get_stridx (rhs_addr
);
3158 strinfo
*si
= get_strinfo (idx
);
3160 && si
->full_string_p
3161 && tree_fits_shwi_p (si
->nonzero_chars
))
3162 return tree_to_shwi (si
->nonzero_chars
);
3168 if (TREE_CODE (rhs
) == VAR_DECL
3169 && TREE_READONLY (rhs
))
3170 rhs
= DECL_INITIAL (rhs
);
3172 if (rhs
&& TREE_CODE (rhs
) == STRING_CST
)
3173 return strlen (TREE_STRING_POINTER (rhs
));
3178 /* Handle a single character store. */
3181 handle_char_store (gimple_stmt_iterator
*gsi
)
3185 gimple
*stmt
= gsi_stmt (*gsi
);
3186 tree ssaname
= NULL_TREE
, lhs
= gimple_assign_lhs (stmt
);
3187 tree rhs
= gimple_assign_rhs1 (stmt
);
3188 unsigned HOST_WIDE_INT offset
= 0;
3190 if (TREE_CODE (lhs
) == MEM_REF
3191 && TREE_CODE (TREE_OPERAND (lhs
, 0)) == SSA_NAME
)
3193 tree mem_offset
= TREE_OPERAND (lhs
, 1);
3194 if (tree_fits_uhwi_p (mem_offset
))
3196 /* Get the strinfo for the base, and use it if it starts with at
3197 least OFFSET nonzero characters. This is trivially true if
3199 offset
= tree_to_uhwi (mem_offset
);
3200 idx
= get_stridx (TREE_OPERAND (lhs
, 0));
3202 si
= get_strinfo (idx
);
3204 ssaname
= TREE_OPERAND (lhs
, 0);
3205 else if (si
== NULL
|| compare_nonzero_chars (si
, offset
) < 0)
3211 idx
= get_addr_stridx (lhs
, NULL_TREE
, &offset
);
3213 si
= get_strinfo (idx
);
3216 bool storing_zero_p
= initializer_zerop (rhs
);
3217 bool storing_nonzero_p
= !storing_zero_p
&& tree_expr_nonzero_p (rhs
);
3218 /* Set to the length of the string being assigned if known. */
3219 HOST_WIDE_INT rhslen
;
3223 int cmp
= compare_nonzero_chars (si
, offset
);
3224 gcc_assert (offset
== 0 || cmp
>= 0);
3225 if (storing_zero_p
&& cmp
== 0 && si
->full_string_p
)
3227 /* When overwriting a '\0' with a '\0', the store can be removed
3228 if we know it has been stored in the current function. */
3229 if (!stmt_could_throw_p (stmt
) && si
->writable
)
3231 unlink_stmt_vdef (stmt
);
3232 release_defs (stmt
);
3233 gsi_remove (gsi
, true);
3238 si
->writable
= true;
3243 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3244 and if we aren't storing '\0', we know that the length of the
3245 string and any other zero terminated string in memory remains
3246 the same. In that case we move to the next gimple statement and
3247 return to signal the caller that it shouldn't invalidate anything.
3249 This is benefical for cases like:
3254 strcpy (p, "foobar");
3255 size_t len = strlen (p); // This can be optimized into 6
3256 size_t len2 = strlen (q); // This has to be computed
3258 size_t len3 = strlen (p); // This can be optimized into 6
3259 size_t len4 = strlen (q); // This can be optimized into len2
3260 bar (len, len2, len3, len4);
3263 else if (storing_nonzero_p
&& cmp
> 0)
3268 else if (storing_zero_p
|| storing_nonzero_p
|| (offset
!= 0 && cmp
> 0))
3270 /* When storing_nonzero_p, we know that the string now starts
3271 with OFFSET + 1 nonzero characters, but don't know whether
3272 there's a following nul terminator.
3274 When storing_zero_p, we know that the string is now OFFSET
3277 Otherwise, we're storing an unknown value at offset OFFSET,
3278 so need to clip the nonzero_chars to OFFSET. */
3279 location_t loc
= gimple_location (stmt
);
3280 tree oldlen
= si
->nonzero_chars
;
3281 if (cmp
== 0 && si
->full_string_p
)
3282 /* We're overwriting the nul terminator with a nonzero or
3283 unknown character. If the previous stmt was a memcpy,
3284 its length may be decreased. */
3285 adjust_last_stmt (si
, stmt
, false);
3286 si
= unshare_strinfo (si
);
3287 if (storing_nonzero_p
)
3288 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
+ 1);
3290 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
);
3291 si
->full_string_p
= storing_zero_p
;
3294 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3295 si
->endptr
= ssaname
;
3300 si
->writable
= true;
3301 si
->dont_invalidate
= true;
3304 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
3305 si
->nonzero_chars
, oldlen
);
3306 adjust_related_strinfos (loc
, si
, adj
);
3312 else if (idx
== 0 && (storing_zero_p
|| storing_nonzero_p
))
3315 idx
= new_stridx (ssaname
);
3317 idx
= new_addr_stridx (lhs
);
3320 tree ptr
= (ssaname
? ssaname
: build_fold_addr_expr (lhs
));
3321 tree len
= storing_nonzero_p
? size_one_node
: size_zero_node
;
3322 si
= new_strinfo (ptr
, idx
, len
, storing_zero_p
);
3323 set_strinfo (idx
, si
);
3326 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3327 si
->endptr
= ssaname
;
3328 si
->dont_invalidate
= true;
3329 si
->writable
= true;
3333 && (rhslen
= get_string_cst_length (gimple_assign_rhs1 (stmt
))) >= 0
3334 && ssaname
== NULL_TREE
3335 && TREE_CODE (TREE_TYPE (lhs
)) == ARRAY_TYPE
)
3337 HOST_WIDE_INT a
= int_size_in_bytes (TREE_TYPE (lhs
));
3338 if (a
> 0 && (unsigned HOST_WIDE_INT
) a
> (unsigned HOST_WIDE_INT
) rhslen
)
3340 int idx
= new_addr_stridx (lhs
);
3343 si
= new_strinfo (build_fold_addr_expr (lhs
), idx
,
3344 build_int_cst (size_type_node
, rhslen
), true);
3345 set_strinfo (idx
, si
);
3346 si
->dont_invalidate
= true;
3351 if (si
!= NULL
&& offset
== 0 && storing_zero_p
)
3353 /* Allow adjust_last_stmt to remove it if the stored '\0'
3354 is immediately overwritten. */
3355 laststmt
.stmt
= stmt
;
3356 laststmt
.len
= build_int_cst (size_type_node
, 1);
3357 laststmt
.stridx
= si
->idx
;
3362 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3365 fold_strstr_to_strncmp (tree rhs1
, tree rhs2
, gimple
*stmt
)
3367 if (TREE_CODE (rhs1
) != SSA_NAME
3368 || TREE_CODE (rhs2
) != SSA_NAME
)
3371 gimple
*call_stmt
= NULL
;
3372 for (int pass
= 0; pass
< 2; pass
++)
3374 gimple
*g
= SSA_NAME_DEF_STMT (rhs1
);
3375 if (gimple_call_builtin_p (g
, BUILT_IN_STRSTR
)
3376 && has_single_use (rhs1
)
3377 && gimple_call_arg (g
, 0) == rhs2
)
3382 std::swap (rhs1
, rhs2
);
3387 tree arg0
= gimple_call_arg (call_stmt
, 0);
3391 tree arg1
= gimple_call_arg (call_stmt
, 1);
3392 tree arg1_len
= NULL_TREE
;
3393 int idx
= get_stridx (arg1
);
3398 arg1_len
= build_int_cst (size_type_node
, ~idx
);
3401 strinfo
*si
= get_strinfo (idx
);
3403 arg1_len
= get_string_length (si
);
3407 if (arg1_len
!= NULL_TREE
)
3409 gimple_stmt_iterator gsi
= gsi_for_stmt (call_stmt
);
3410 tree strncmp_decl
= builtin_decl_explicit (BUILT_IN_STRNCMP
);
3412 if (!is_gimple_val (arg1_len
))
3414 tree arg1_len_tmp
= make_ssa_name (TREE_TYPE (arg1_len
));
3415 gassign
*arg1_stmt
= gimple_build_assign (arg1_len_tmp
,
3417 gsi_insert_before (&gsi
, arg1_stmt
, GSI_SAME_STMT
);
3418 arg1_len
= arg1_len_tmp
;
3421 gcall
*strncmp_call
= gimple_build_call (strncmp_decl
, 3,
3422 arg0
, arg1
, arg1_len
);
3423 tree strncmp_lhs
= make_ssa_name (integer_type_node
);
3424 gimple_set_vuse (strncmp_call
, gimple_vuse (call_stmt
));
3425 gimple_call_set_lhs (strncmp_call
, strncmp_lhs
);
3426 gsi_remove (&gsi
, true);
3427 gsi_insert_before (&gsi
, strncmp_call
, GSI_SAME_STMT
);
3428 tree zero
= build_zero_cst (TREE_TYPE (strncmp_lhs
));
3430 if (is_gimple_assign (stmt
))
3432 if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
3434 tree cond
= gimple_assign_rhs1 (stmt
);
3435 TREE_OPERAND (cond
, 0) = strncmp_lhs
;
3436 TREE_OPERAND (cond
, 1) = zero
;
3440 gimple_assign_set_rhs1 (stmt
, strncmp_lhs
);
3441 gimple_assign_set_rhs2 (stmt
, zero
);
3446 gcond
*cond
= as_a
<gcond
*> (stmt
);
3447 gimple_cond_set_lhs (cond
, strncmp_lhs
);
3448 gimple_cond_set_rhs (cond
, zero
);
3456 /* Attempt to check for validity of the performed access a single statement
3457 at *GSI using string length knowledge, and to optimize it.
3458 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3462 strlen_check_and_optimize_stmt (gimple_stmt_iterator
*gsi
, bool *cleanup_eh
)
3464 gimple
*stmt
= gsi_stmt (*gsi
);
3466 if (is_gimple_call (stmt
))
3468 tree callee
= gimple_call_fndecl (stmt
);
3469 if (valid_builtin_call (stmt
))
3470 switch (DECL_FUNCTION_CODE (callee
))
3472 case BUILT_IN_STRLEN
:
3473 case BUILT_IN_STRNLEN
:
3474 handle_builtin_strlen (gsi
);
3476 case BUILT_IN_STRCHR
:
3477 handle_builtin_strchr (gsi
);
3479 case BUILT_IN_STRCPY
:
3480 case BUILT_IN_STRCPY_CHK
:
3481 case BUILT_IN_STPCPY
:
3482 case BUILT_IN_STPCPY_CHK
:
3483 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3486 case BUILT_IN_STRNCAT
:
3487 case BUILT_IN_STRNCAT_CHK
:
3488 handle_builtin_strncat (DECL_FUNCTION_CODE (callee
), gsi
);
3491 case BUILT_IN_STPNCPY
:
3492 case BUILT_IN_STPNCPY_CHK
:
3493 case BUILT_IN_STRNCPY
:
3494 case BUILT_IN_STRNCPY_CHK
:
3495 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee
), gsi
);
3498 case BUILT_IN_MEMCPY
:
3499 case BUILT_IN_MEMCPY_CHK
:
3500 case BUILT_IN_MEMPCPY
:
3501 case BUILT_IN_MEMPCPY_CHK
:
3502 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3504 case BUILT_IN_STRCAT
:
3505 case BUILT_IN_STRCAT_CHK
:
3506 handle_builtin_strcat (DECL_FUNCTION_CODE (callee
), gsi
);
3508 case BUILT_IN_MALLOC
:
3509 case BUILT_IN_CALLOC
:
3510 handle_builtin_malloc (DECL_FUNCTION_CODE (callee
), gsi
);
3512 case BUILT_IN_MEMSET
:
3513 if (handle_builtin_memset (gsi
))
3516 case BUILT_IN_MEMCMP
:
3517 if (handle_builtin_memcmp (gsi
))
3520 case BUILT_IN_STRCMP
:
3521 case BUILT_IN_STRNCMP
:
3522 if (handle_builtin_string_cmp (gsi
))
3529 else if (is_gimple_assign (stmt
) && !gimple_clobber_p (stmt
))
3531 tree lhs
= gimple_assign_lhs (stmt
);
3533 if (TREE_CODE (lhs
) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (lhs
)))
3535 if (gimple_assign_single_p (stmt
)
3536 || (gimple_assign_cast_p (stmt
)
3537 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt
)))))
3539 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3540 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = idx
;
3542 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
3543 handle_pointer_plus (gsi
);
3545 else if (TREE_CODE (lhs
) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
3547 enum tree_code code
= gimple_assign_rhs_code (stmt
);
3548 if (code
== COND_EXPR
)
3550 tree cond
= gimple_assign_rhs1 (stmt
);
3551 enum tree_code cond_code
= TREE_CODE (cond
);
3553 if (cond_code
== EQ_EXPR
|| cond_code
== NE_EXPR
)
3554 fold_strstr_to_strncmp (TREE_OPERAND (cond
, 0),
3555 TREE_OPERAND (cond
, 1), stmt
);
3557 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3558 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt
),
3559 gimple_assign_rhs2 (stmt
), stmt
);
3560 else if (gimple_assign_load_p (stmt
)
3561 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
3562 && TYPE_MODE (TREE_TYPE (lhs
)) == TYPE_MODE (char_type_node
)
3563 && (TYPE_PRECISION (TREE_TYPE (lhs
))
3564 == TYPE_PRECISION (char_type_node
))
3565 && !gimple_has_volatile_ops (stmt
))
3567 tree off
= integer_zero_node
;
3568 unsigned HOST_WIDE_INT coff
= 0;
3570 tree rhs1
= gimple_assign_rhs1 (stmt
);
3571 if (code
== MEM_REF
)
3573 idx
= get_stridx (TREE_OPERAND (rhs1
, 0));
3576 strinfo
*si
= get_strinfo (idx
);
3578 && si
->nonzero_chars
3579 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
3580 && (wi::to_widest (si
->nonzero_chars
)
3581 >= wi::to_widest (off
)))
3582 off
= TREE_OPERAND (rhs1
, 1);
3584 /* This case is not useful. See if get_addr_stridx
3585 returns something usable. */
3590 idx
= get_addr_stridx (rhs1
, NULL_TREE
, &coff
);
3593 strinfo
*si
= get_strinfo (idx
);
3595 && si
->nonzero_chars
3596 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
3598 widest_int w1
= wi::to_widest (si
->nonzero_chars
);
3599 widest_int w2
= wi::to_widest (off
) + coff
;
3601 && si
->full_string_p
)
3603 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3605 fprintf (dump_file
, "Optimizing: ");
3606 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3609 /* Reading the final '\0' character. */
3610 tree zero
= build_int_cst (TREE_TYPE (lhs
), 0);
3611 gimple_set_vuse (stmt
, NULL_TREE
);
3612 gimple_assign_set_rhs_from_tree (gsi
, zero
);
3614 |= maybe_clean_or_replace_eh_stmt (stmt
,
3616 stmt
= gsi_stmt (*gsi
);
3619 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3621 fprintf (dump_file
, "into: ");
3622 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3627 /* Reading a character before the final '\0'
3628 character. Just set the value range to ~[0, 0]
3629 if we don't have anything better. */
3631 tree type
= TREE_TYPE (lhs
);
3632 enum value_range_type vr
3633 = get_range_info (lhs
, &min
, &max
);
3634 if (vr
== VR_VARYING
3636 && min
== wi::min_value (TYPE_PRECISION (type
),
3638 && max
== wi::max_value (TYPE_PRECISION (type
),
3640 set_range_info (lhs
, VR_ANTI_RANGE
,
3641 wi::zero (TYPE_PRECISION (type
)),
3642 wi::zero (TYPE_PRECISION (type
)));
3648 if (strlen_to_stridx
)
3650 tree rhs1
= gimple_assign_rhs1 (stmt
);
3651 if (stridx_strlenloc
*ps
= strlen_to_stridx
->get (rhs1
))
3652 strlen_to_stridx
->put (lhs
, stridx_strlenloc (*ps
));
3655 else if (TREE_CODE (lhs
) != SSA_NAME
&& !TREE_SIDE_EFFECTS (lhs
))
3657 tree type
= TREE_TYPE (lhs
);
3658 if (TREE_CODE (type
) == ARRAY_TYPE
)
3659 type
= TREE_TYPE (type
);
3660 if (TREE_CODE (type
) == INTEGER_TYPE
3661 && TYPE_MODE (type
) == TYPE_MODE (char_type_node
)
3662 && TYPE_PRECISION (type
) == TYPE_PRECISION (char_type_node
))
3664 if (! handle_char_store (gsi
))
3669 else if (gcond
*cond
= dyn_cast
<gcond
*> (stmt
))
3671 enum tree_code code
= gimple_cond_code (cond
);
3672 if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3673 fold_strstr_to_strncmp (gimple_cond_lhs (stmt
),
3674 gimple_cond_rhs (stmt
), stmt
);
3677 if (gimple_vdef (stmt
))
3678 maybe_invalidate (stmt
);
3682 /* Recursively call maybe_invalidate on stmts that might be executed
3683 in between dombb and current bb and that contain a vdef. Stop when
3684 *count stmts are inspected, or if the whole strinfo vector has
3685 been invalidated. */
3688 do_invalidate (basic_block dombb
, gimple
*phi
, bitmap visited
, int *count
)
3690 unsigned int i
, n
= gimple_phi_num_args (phi
);
3692 for (i
= 0; i
< n
; i
++)
3694 tree vuse
= gimple_phi_arg_def (phi
, i
);
3695 gimple
*stmt
= SSA_NAME_DEF_STMT (vuse
);
3696 basic_block bb
= gimple_bb (stmt
);
3699 || !bitmap_set_bit (visited
, bb
->index
)
3700 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3704 if (gimple_code (stmt
) == GIMPLE_PHI
)
3706 do_invalidate (dombb
, stmt
, visited
, count
);
3713 if (!maybe_invalidate (stmt
))
3718 vuse
= gimple_vuse (stmt
);
3719 stmt
= SSA_NAME_DEF_STMT (vuse
);
3720 if (gimple_bb (stmt
) != bb
)
3722 bb
= gimple_bb (stmt
);
3725 || !bitmap_set_bit (visited
, bb
->index
)
3726 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3733 class strlen_dom_walker
: public dom_walker
3736 strlen_dom_walker (cdi_direction direction
)
3737 : dom_walker (direction
), m_cleanup_cfg (false)
3740 virtual edge
before_dom_children (basic_block
);
3741 virtual void after_dom_children (basic_block
);
3743 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3744 execute function. */
3748 /* Callback for walk_dominator_tree. Attempt to optimize various
3749 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3752 strlen_dom_walker::before_dom_children (basic_block bb
)
3754 basic_block dombb
= get_immediate_dominator (CDI_DOMINATORS
, bb
);
3757 stridx_to_strinfo
= NULL
;
3760 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) dombb
->aux
);
3761 if (stridx_to_strinfo
)
3763 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3766 gphi
*phi
= gsi
.phi ();
3767 if (virtual_operand_p (gimple_phi_result (phi
)))
3769 bitmap visited
= BITMAP_ALLOC (NULL
);
3770 int count_vdef
= 100;
3771 do_invalidate (dombb
, phi
, visited
, &count_vdef
);
3772 BITMAP_FREE (visited
);
3773 if (count_vdef
== 0)
3775 /* If there were too many vdefs in between immediate
3776 dominator and current bb, invalidate everything.
3777 If stridx_to_strinfo has been unshared, we need
3778 to free it, otherwise just set it to NULL. */
3779 if (!strinfo_shared ())
3785 vec_safe_iterate (stridx_to_strinfo
, i
, &si
);
3789 (*stridx_to_strinfo
)[i
] = NULL
;
3793 stridx_to_strinfo
= NULL
;
3801 /* If all PHI arguments have the same string index, the PHI result
3803 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3806 gphi
*phi
= gsi
.phi ();
3807 tree result
= gimple_phi_result (phi
);
3808 if (!virtual_operand_p (result
) && POINTER_TYPE_P (TREE_TYPE (result
)))
3810 int idx
= get_stridx (gimple_phi_arg_def (phi
, 0));
3813 unsigned int i
, n
= gimple_phi_num_args (phi
);
3814 for (i
= 1; i
< n
; i
++)
3815 if (idx
!= get_stridx (gimple_phi_arg_def (phi
, i
)))
3818 ssa_ver_to_stridx
[SSA_NAME_VERSION (result
)] = idx
;
3823 bool cleanup_eh
= false;
3825 /* Attempt to optimize individual statements. */
3826 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); )
3827 if (strlen_check_and_optimize_stmt (&gsi
, &cleanup_eh
))
3830 if (cleanup_eh
&& gimple_purge_dead_eh_edges (bb
))
3831 m_cleanup_cfg
= true;
3833 bb
->aux
= stridx_to_strinfo
;
3834 if (vec_safe_length (stridx_to_strinfo
) && !strinfo_shared ())
3835 (*stridx_to_strinfo
)[0] = (strinfo
*) bb
;
3839 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3840 owned by the current bb, clear bb->aux. */
3843 strlen_dom_walker::after_dom_children (basic_block bb
)
3847 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) bb
->aux
);
3848 if (vec_safe_length (stridx_to_strinfo
)
3849 && (*stridx_to_strinfo
)[0] == (strinfo
*) bb
)
3854 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
3856 vec_free (stridx_to_strinfo
);
3862 /* Main entry point. */
3866 const pass_data pass_data_strlen
=
3868 GIMPLE_PASS
, /* type */
3869 "strlen", /* name */
3870 OPTGROUP_NONE
, /* optinfo_flags */
3871 TV_TREE_STRLEN
, /* tv_id */
3872 ( PROP_cfg
| PROP_ssa
), /* properties_required */
3873 0, /* properties_provided */
3874 0, /* properties_destroyed */
3875 0, /* todo_flags_start */
3876 0, /* todo_flags_finish */
3879 class pass_strlen
: public gimple_opt_pass
3882 pass_strlen (gcc::context
*ctxt
)
3883 : gimple_opt_pass (pass_data_strlen
, ctxt
)
3886 /* opt_pass methods: */
3887 virtual bool gate (function
*) { return flag_optimize_strlen
!= 0; }
3888 virtual unsigned int execute (function
*);
3890 }; // class pass_strlen
3893 pass_strlen::execute (function
*fun
)
3895 gcc_assert (!strlen_to_stridx
);
3896 if (warn_stringop_overflow
|| warn_stringop_truncation
)
3897 strlen_to_stridx
= new hash_map
<tree
, stridx_strlenloc
> ();
3899 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
3902 calculate_dominance_info (CDI_DOMINATORS
);
3904 /* String length optimization is implemented as a walk of the dominator
3905 tree and a forward walk of statements within each block. */
3906 strlen_dom_walker
walker (CDI_DOMINATORS
);
3907 walker
.walk (fun
->cfg
->x_entry_block_ptr
);
3909 ssa_ver_to_stridx
.release ();
3910 strinfo_pool
.release ();
3911 if (decl_to_stridxlist_htab
)
3913 obstack_free (&stridx_obstack
, NULL
);
3914 delete decl_to_stridxlist_htab
;
3915 decl_to_stridxlist_htab
= NULL
;
3917 laststmt
.stmt
= NULL
;
3918 laststmt
.len
= NULL_TREE
;
3919 laststmt
.stridx
= 0;
3921 if (strlen_to_stridx
)
3923 strlen_to_stridx
->empty ();
3924 delete strlen_to_stridx
;
3925 strlen_to_stridx
= NULL
;
3928 return walker
.m_cleanup_cfg
? TODO_cleanup_cfg
: 0;
3934 make_pass_strlen (gcc::context
*ctxt
)
3936 return new pass_strlen (ctxt
);