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 with integer type and for strlen()
1128 argument SRC, set LHS range info to [0, N] if SRC refers to
1129 a character array A[N] with unknown length bounded by N. */
1132 maybe_set_strlen_range (tree lhs
, tree src
)
1134 if (TREE_CODE (lhs
) != SSA_NAME
1135 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
1138 if (TREE_CODE (src
) == SSA_NAME
)
1140 gimple
*def
= SSA_NAME_DEF_STMT (src
);
1141 if (is_gimple_assign (def
)
1142 && gimple_assign_rhs_code (def
) == ADDR_EXPR
)
1143 src
= gimple_assign_rhs1 (def
);
1146 if (TREE_CODE (src
) != ADDR_EXPR
)
1149 /* The last array member of a struct can be bigger than its size
1150 suggests if it's treated as a poor-man's flexible array member. */
1151 src
= TREE_OPERAND (src
, 0);
1152 if (TREE_CODE (TREE_TYPE (src
)) != ARRAY_TYPE
1153 || array_at_struct_end_p (src
))
1156 tree type
= TREE_TYPE (src
);
1157 if (tree dom
= TYPE_DOMAIN (type
))
1158 if (tree maxval
= TYPE_MAX_VALUE (dom
))
1160 wide_int max
= wi::to_wide (maxval
);
1161 wide_int min
= wi::zero (max
.get_precision ());
1162 set_range_info (lhs
, VR_RANGE
, min
, max
);
1166 /* Handle a strlen call. If strlen of the argument is known, replace
1167 the strlen call with the known value, otherwise remember that strlen
1168 of the argument is stored in the lhs SSA_NAME. */
1171 handle_builtin_strlen (gimple_stmt_iterator
*gsi
)
1175 gimple
*stmt
= gsi_stmt (*gsi
);
1176 tree lhs
= gimple_call_lhs (stmt
);
1178 if (lhs
== NULL_TREE
)
1181 src
= gimple_call_arg (stmt
, 0);
1182 idx
= get_stridx (src
);
1189 rhs
= build_int_cst (TREE_TYPE (lhs
), ~idx
);
1193 si
= get_strinfo (idx
);
1195 rhs
= get_string_length (si
);
1197 if (rhs
!= NULL_TREE
)
1199 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1201 fprintf (dump_file
, "Optimizing: ");
1202 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1204 rhs
= unshare_expr (rhs
);
1205 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
1206 rhs
= fold_convert_loc (gimple_location (stmt
),
1207 TREE_TYPE (lhs
), rhs
);
1208 if (!update_call_from_tree (gsi
, rhs
))
1209 gimplify_and_update_call_from_tree (gsi
, rhs
);
1210 stmt
= gsi_stmt (*gsi
);
1212 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1214 fprintf (dump_file
, "into: ");
1215 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1218 && TREE_CODE (si
->nonzero_chars
) != SSA_NAME
1219 && TREE_CODE (si
->nonzero_chars
) != INTEGER_CST
1220 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1222 si
= unshare_strinfo (si
);
1223 si
->nonzero_chars
= lhs
;
1224 gcc_assert (si
->full_string_p
);
1227 if (strlen_to_stridx
)
1229 location_t loc
= gimple_location (stmt
);
1230 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1235 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1238 idx
= new_stridx (src
);
1241 strinfo
*si
= get_strinfo (idx
);
1244 if (!si
->full_string_p
&& !si
->stmt
)
1246 /* Until now we only had a lower bound on the string length.
1247 Install LHS as the actual length. */
1248 si
= unshare_strinfo (si
);
1249 tree old
= si
->nonzero_chars
;
1250 si
->nonzero_chars
= lhs
;
1251 si
->full_string_p
= true;
1252 if (TREE_CODE (old
) == INTEGER_CST
)
1254 location_t loc
= gimple_location (stmt
);
1255 old
= fold_convert_loc (loc
, TREE_TYPE (lhs
), old
);
1256 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1257 TREE_TYPE (lhs
), lhs
, old
);
1258 adjust_related_strinfos (loc
, si
, adj
);
1272 strinfo
*si
= new_strinfo (src
, idx
, lhs
, true);
1273 set_strinfo (idx
, si
);
1274 find_equal_ptrs (src
, idx
);
1276 /* For SRC that is an array of N elements, set LHS's range
1278 maybe_set_strlen_range (lhs
, src
);
1280 if (strlen_to_stridx
)
1282 location_t loc
= gimple_location (stmt
);
1283 strlen_to_stridx
->put (lhs
, stridx_strlenloc (idx
, loc
));
1288 /* Handle a strchr call. If strlen of the first argument is known, replace
1289 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1290 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1293 handle_builtin_strchr (gimple_stmt_iterator
*gsi
)
1297 gimple
*stmt
= gsi_stmt (*gsi
);
1298 tree lhs
= gimple_call_lhs (stmt
);
1300 if (lhs
== NULL_TREE
)
1303 if (!integer_zerop (gimple_call_arg (stmt
, 1)))
1306 src
= gimple_call_arg (stmt
, 0);
1307 idx
= get_stridx (src
);
1314 rhs
= build_int_cst (size_type_node
, ~idx
);
1318 si
= get_strinfo (idx
);
1320 rhs
= get_string_length (si
);
1322 if (rhs
!= NULL_TREE
)
1324 location_t loc
= gimple_location (stmt
);
1326 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1328 fprintf (dump_file
, "Optimizing: ");
1329 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1331 if (si
!= NULL
&& si
->endptr
!= NULL_TREE
)
1333 rhs
= unshare_expr (si
->endptr
);
1334 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1336 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1340 rhs
= fold_convert_loc (loc
, sizetype
, unshare_expr (rhs
));
1341 rhs
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
1342 TREE_TYPE (src
), src
, rhs
);
1343 if (!useless_type_conversion_p (TREE_TYPE (lhs
),
1345 rhs
= fold_convert_loc (loc
, TREE_TYPE (lhs
), rhs
);
1347 if (!update_call_from_tree (gsi
, rhs
))
1348 gimplify_and_update_call_from_tree (gsi
, rhs
);
1349 stmt
= gsi_stmt (*gsi
);
1351 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1353 fprintf (dump_file
, "into: ");
1354 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1357 && si
->endptr
== NULL_TREE
1358 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1360 si
= unshare_strinfo (si
);
1363 zero_length_string (lhs
, si
);
1367 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs
))
1369 if (TREE_CODE (src
) != SSA_NAME
|| !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src
))
1372 idx
= new_stridx (src
);
1373 else if (get_strinfo (idx
) != NULL
)
1375 zero_length_string (lhs
, NULL
);
1380 location_t loc
= gimple_location (stmt
);
1381 tree lhsu
= fold_convert_loc (loc
, size_type_node
, lhs
);
1382 tree srcu
= fold_convert_loc (loc
, size_type_node
, src
);
1383 tree length
= fold_build2_loc (loc
, MINUS_EXPR
,
1384 size_type_node
, lhsu
, srcu
);
1385 strinfo
*si
= new_strinfo (src
, idx
, length
, true);
1387 set_strinfo (idx
, si
);
1388 find_equal_ptrs (src
, idx
);
1389 zero_length_string (lhs
, si
);
1393 zero_length_string (lhs
, NULL
);
1396 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1397 If strlen of the second argument is known, strlen of the first argument
1398 is the same after this call. Furthermore, attempt to convert it to
1402 handle_builtin_strcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1405 tree src
, dst
, srclen
, len
, lhs
, type
, fn
, oldlen
;
1407 gimple
*stmt
= gsi_stmt (*gsi
);
1408 strinfo
*si
, *dsi
, *olddsi
, *zsi
;
1411 src
= gimple_call_arg (stmt
, 1);
1412 dst
= gimple_call_arg (stmt
, 0);
1413 lhs
= gimple_call_lhs (stmt
);
1414 idx
= get_stridx (src
);
1417 si
= get_strinfo (idx
);
1419 didx
= get_stridx (dst
);
1423 olddsi
= get_strinfo (didx
);
1428 adjust_last_stmt (olddsi
, stmt
, false);
1432 srclen
= get_string_length (si
);
1434 srclen
= build_int_cst (size_type_node
, ~idx
);
1436 loc
= gimple_location (stmt
);
1437 if (srclen
== NULL_TREE
)
1440 case BUILT_IN_STRCPY
:
1441 case BUILT_IN_STRCPY_CHK
:
1442 if (lhs
!= NULL_TREE
|| !builtin_decl_implicit_p (BUILT_IN_STPCPY
))
1445 case BUILT_IN_STPCPY
:
1446 case BUILT_IN_STPCPY_CHK
:
1447 if (lhs
== NULL_TREE
)
1451 tree lhsuint
= fold_convert_loc (loc
, size_type_node
, lhs
);
1452 srclen
= fold_convert_loc (loc
, size_type_node
, dst
);
1453 srclen
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
1463 didx
= new_stridx (dst
);
1469 oldlen
= olddsi
->nonzero_chars
;
1470 dsi
= unshare_strinfo (olddsi
);
1471 dsi
->nonzero_chars
= srclen
;
1472 dsi
->full_string_p
= (srclen
!= NULL_TREE
);
1473 /* Break the chain, so adjust_related_strinfo on later pointers in
1474 the chain won't adjust this one anymore. */
1477 dsi
->endptr
= NULL_TREE
;
1481 dsi
= new_strinfo (dst
, didx
, srclen
, srclen
!= NULL_TREE
);
1482 set_strinfo (didx
, dsi
);
1483 find_equal_ptrs (dst
, didx
);
1485 dsi
->writable
= true;
1486 dsi
->dont_invalidate
= true;
1488 if (dsi
->nonzero_chars
== NULL_TREE
)
1492 /* If string length of src is unknown, use delayed length
1493 computation. If string lenth of dst will be needed, it
1494 can be computed by transforming this strcpy call into
1495 stpcpy and subtracting dst from the return value. */
1497 /* Look for earlier strings whose length could be determined if
1498 this strcpy is turned into an stpcpy. */
1500 if (dsi
->prev
!= 0 && (chainsi
= verify_related_strinfos (dsi
)) != NULL
)
1502 for (; chainsi
&& chainsi
!= dsi
; chainsi
= get_strinfo (chainsi
->next
))
1504 /* When setting a stmt for delayed length computation
1505 prevent all strinfos through dsi from being
1507 chainsi
= unshare_strinfo (chainsi
);
1508 chainsi
->stmt
= stmt
;
1509 chainsi
->nonzero_chars
= NULL_TREE
;
1510 chainsi
->full_string_p
= false;
1511 chainsi
->endptr
= NULL_TREE
;
1512 chainsi
->dont_invalidate
= true;
1517 /* Try to detect overlap before returning. This catches cases
1518 like strcpy (d, d + n) where n is non-constant whose range
1519 is such that (n <= strlen (d) holds).
1521 OLDDSI->NONZERO_chars may have been reset by this point with
1522 oldlen holding it original value. */
1523 if (olddsi
&& oldlen
)
1525 /* Add 1 for the terminating NUL. */
1526 tree type
= TREE_TYPE (oldlen
);
1527 oldlen
= fold_build2 (PLUS_EXPR
, type
, oldlen
,
1528 build_int_cst (type
, 1));
1529 check_bounds_or_overlap (as_a
<gcall
*>(stmt
), olddsi
->ptr
, src
,
1538 tree adj
= NULL_TREE
;
1539 if (oldlen
== NULL_TREE
)
1541 else if (integer_zerop (oldlen
))
1543 else if (TREE_CODE (oldlen
) == INTEGER_CST
1544 || TREE_CODE (srclen
) == INTEGER_CST
)
1545 adj
= fold_build2_loc (loc
, MINUS_EXPR
,
1546 TREE_TYPE (srclen
), srclen
,
1547 fold_convert_loc (loc
, TREE_TYPE (srclen
),
1549 if (adj
!= NULL_TREE
)
1550 adjust_related_strinfos (loc
, dsi
, adj
);
1554 /* strcpy src may not overlap dst, so src doesn't need to be
1555 invalidated either. */
1557 si
->dont_invalidate
= true;
1563 case BUILT_IN_STRCPY
:
1564 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
1566 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1568 case BUILT_IN_STRCPY_CHK
:
1569 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
1571 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
1573 case BUILT_IN_STPCPY
:
1574 /* This would need adjustment of the lhs (subtract one),
1575 or detection that the trailing '\0' doesn't need to be
1576 written, if it will be immediately overwritten.
1577 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1581 zsi
= zero_length_string (lhs
, dsi
);
1584 case BUILT_IN_STPCPY_CHK
:
1585 /* This would need adjustment of the lhs (subtract one),
1586 or detection that the trailing '\0' doesn't need to be
1587 written, if it will be immediately overwritten.
1588 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1592 zsi
= zero_length_string (lhs
, dsi
);
1599 zsi
->dont_invalidate
= true;
1603 tree args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1604 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
1607 type
= size_type_node
;
1609 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
1610 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
, build_int_cst (type
, 1));
1612 /* Set the no-warning bit on the transformed statement? */
1613 bool set_no_warning
= false;
1615 if (const strinfo
*chksi
= olddsi
? olddsi
: dsi
)
1617 && !check_bounds_or_overlap (as_a
<gcall
*>(stmt
), chksi
->ptr
, si
->ptr
,
1620 gimple_set_no_warning (stmt
, true);
1621 set_no_warning
= true;
1624 if (fn
== NULL_TREE
)
1627 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
1629 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1631 fprintf (dump_file
, "Optimizing: ");
1632 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1634 if (gimple_call_num_args (stmt
) == 2)
1635 success
= update_gimple_call (gsi
, fn
, 3, dst
, src
, len
);
1637 success
= update_gimple_call (gsi
, fn
, 4, dst
, src
, len
,
1638 gimple_call_arg (stmt
, 2));
1641 stmt
= gsi_stmt (*gsi
);
1643 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1645 fprintf (dump_file
, "into: ");
1646 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
1648 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1649 laststmt
.stmt
= stmt
;
1650 laststmt
.len
= srclen
;
1651 laststmt
.stridx
= dsi
->idx
;
1653 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
1654 fprintf (dump_file
, "not possible.\n");
1657 gimple_set_no_warning (stmt
, true);
1660 /* Check the size argument to the built-in forms of stpncpy and strncpy
1661 for out-of-bounds offsets or overlapping access, and to see if the
1662 size argument is derived from a call to strlen() on the source argument,
1663 and if so, issue an appropriate warning. */
1666 handle_builtin_strncat (built_in_function bcode
, gimple_stmt_iterator
*gsi
)
1668 /* Same as stxncpy(). */
1669 handle_builtin_stxncpy (bcode
, gsi
);
1672 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1673 way. LEN can either be an integer expression, or a pointer (to char).
1674 When it is the latter (such as in recursive calls to self) is is
1675 assumed to be the argument in some call to strlen() whose relationship
1676 to SRC is being ascertained. */
1679 is_strlen_related_p (tree src
, tree len
)
1681 if (TREE_CODE (TREE_TYPE (len
)) == POINTER_TYPE
1682 && operand_equal_p (src
, len
, 0))
1685 if (TREE_CODE (len
) != SSA_NAME
)
1688 gimple
*def_stmt
= SSA_NAME_DEF_STMT (len
);
1692 if (is_gimple_call (def_stmt
))
1694 tree func
= gimple_call_fndecl (def_stmt
);
1695 if (!valid_builtin_call (def_stmt
)
1696 || DECL_FUNCTION_CODE (func
) != BUILT_IN_STRLEN
)
1699 tree arg
= gimple_call_arg (def_stmt
, 0);
1700 return is_strlen_related_p (src
, arg
);
1703 if (!is_gimple_assign (def_stmt
))
1706 tree_code code
= gimple_assign_rhs_code (def_stmt
);
1707 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1708 tree rhstype
= TREE_TYPE (rhs1
);
1710 if ((TREE_CODE (rhstype
) == POINTER_TYPE
&& code
== POINTER_PLUS_EXPR
)
1711 || (INTEGRAL_TYPE_P (rhstype
)
1712 && (code
== BIT_AND_EXPR
1713 || code
== NOP_EXPR
)))
1715 /* Pointer plus (an integer) and integer cast or truncation are
1716 considered among the (potentially) related expressions to strlen.
1718 return is_strlen_related_p (src
, rhs1
);
1724 /* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
1726 Check to see if the specified bound is a) equal to the size of
1727 the destination DST and if so, b) if it's immediately followed by
1728 DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
1729 do nothing. Return true if diagnostic has been issued.
1731 The purpose is to diagnose calls to strncpy and stpncpy that do
1732 not nul-terminate the copy while allowing for the idiom where
1733 such a call is immediately followed by setting the last element
1736 strncpy (a, s, sizeof a);
1737 a[sizeof a - 1] = '\0';
1741 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi
, tree src
, tree cnt
)
1743 gimple
*stmt
= gsi_stmt (gsi
);
1744 if (gimple_no_warning_p (stmt
))
1747 wide_int cntrange
[2];
1749 if (TREE_CODE (cnt
) == INTEGER_CST
)
1750 cntrange
[0] = cntrange
[1] = wi::to_wide (cnt
);
1751 else if (TREE_CODE (cnt
) == SSA_NAME
)
1753 enum value_range_type rng
= get_range_info (cnt
, cntrange
, cntrange
+ 1);
1754 if (rng
== VR_RANGE
)
1756 else if (rng
== VR_ANTI_RANGE
)
1758 wide_int maxobjsize
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node
));
1760 if (wi::ltu_p (cntrange
[1], maxobjsize
))
1762 cntrange
[0] = cntrange
[1] + 1;
1763 cntrange
[1] = maxobjsize
;
1767 cntrange
[1] = cntrange
[0] - 1;
1768 cntrange
[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt
)));
1777 /* Negative value is the constant string length. If it's less than
1778 the lower bound there is no truncation. Avoid calling get_stridx()
1779 when ssa_ver_to_stridx is empty. That implies the caller isn't
1780 running under the control of this pass and ssa_ver_to_stridx hasn't
1781 been created yet. */
1782 int sidx
= ssa_ver_to_stridx
.length () ? get_stridx (src
) : 0;
1783 if (sidx
< 0 && wi::gtu_p (cntrange
[0], ~sidx
))
1786 tree dst
= gimple_call_arg (stmt
, 0);
1788 if (TREE_CODE (dstdecl
) == ADDR_EXPR
)
1789 dstdecl
= TREE_OPERAND (dstdecl
, 0);
1791 /* If the destination refers to a an array/pointer declared nonstring
1793 tree ref
= NULL_TREE
;
1794 if (get_attr_nonstring_decl (dstdecl
, &ref
))
1797 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1798 avoid the truncation warning. */
1799 gsi_next_nondebug (&gsi
);
1800 gimple
*next_stmt
= gsi_stmt (gsi
);
1803 /* When there is no statement in the same basic block check
1804 the immediate successor block. */
1805 if (basic_block bb
= gimple_bb (stmt
))
1807 if (single_succ_p (bb
))
1809 /* For simplicity, ignore blocks with multiple outgoing
1810 edges for now and only consider successor blocks along
1812 edge e
= EDGE_SUCC (bb
, 0);
1813 if (!(e
->flags
& EDGE_ABNORMAL
))
1815 gsi
= gsi_start_bb (e
->dest
);
1816 next_stmt
= gsi_stmt (gsi
);
1817 if (next_stmt
&& is_gimple_debug (next_stmt
))
1819 gsi_next_nondebug (&gsi
);
1820 next_stmt
= gsi_stmt (gsi
);
1827 if (next_stmt
&& is_gimple_assign (next_stmt
))
1829 tree lhs
= gimple_assign_lhs (next_stmt
);
1830 tree_code code
= TREE_CODE (lhs
);
1831 if (code
== ARRAY_REF
|| code
== MEM_REF
)
1832 lhs
= TREE_OPERAND (lhs
, 0);
1834 tree func
= gimple_call_fndecl (stmt
);
1835 if (DECL_FUNCTION_CODE (func
) == BUILT_IN_STPNCPY
)
1837 tree ret
= gimple_call_lhs (stmt
);
1838 if (ret
&& operand_equal_p (ret
, lhs
, 0))
1842 /* Determine the base address and offset of the reference,
1843 ignoring the innermost array index. */
1844 if (TREE_CODE (ref
) == ARRAY_REF
)
1845 ref
= TREE_OPERAND (ref
, 0);
1848 tree dstbase
= get_addr_base_and_unit_offset (ref
, &dstoff
);
1851 tree lhsbase
= get_addr_base_and_unit_offset (lhs
, &lhsoff
);
1854 && known_eq (dstoff
, lhsoff
)
1855 && operand_equal_p (dstbase
, lhsbase
, 0))
1859 int prec
= TYPE_PRECISION (TREE_TYPE (cnt
));
1860 wide_int lenrange
[2];
1861 if (strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
)
1863 lenrange
[0] = (sisrc
->nonzero_chars
1864 && TREE_CODE (sisrc
->nonzero_chars
) == INTEGER_CST
1865 ? wi::to_wide (sisrc
->nonzero_chars
)
1867 lenrange
[1] = lenrange
[0];
1870 lenrange
[0] = lenrange
[1] = wi::shwi (~sidx
, prec
);
1874 get_range_strlen (src
, range
);
1875 if (range
[0] != NULL_TREE
1876 && TREE_CODE (range
[0]) == INTEGER_CST
1877 && range
[1] != NULL_TREE
1878 && TREE_CODE (range
[1]) == INTEGER_CST
)
1880 lenrange
[0] = wi::to_wide (range
[0], prec
);
1881 lenrange
[1] = wi::to_wide (range
[1], prec
);
1885 lenrange
[0] = wi::shwi (0, prec
);
1886 lenrange
[1] = wi::shwi (-1, prec
);
1890 location_t callloc
= gimple_nonartificial_location (stmt
);
1891 callloc
= expansion_point_location_if_in_system_header (callloc
);
1893 tree func
= gimple_call_fndecl (stmt
);
1895 if (lenrange
[0] != 0 || !wi::neg_p (lenrange
[1]))
1897 /* If the longest source string is shorter than the lower bound
1898 of the specified count the copy is definitely nul-terminated. */
1899 if (wi::ltu_p (lenrange
[1], cntrange
[0]))
1902 if (wi::neg_p (lenrange
[1]))
1904 /* The length of one of the strings is unknown but at least
1905 one has non-zero length and that length is stored in
1906 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1908 lenrange
[1] = lenrange
[0];
1909 lenrange
[0] = wi::shwi (0, prec
);
1912 gcall
*call
= as_a
<gcall
*> (stmt
);
1914 if (lenrange
[0] == cntrange
[1] && cntrange
[0] == cntrange
[1])
1915 return warning_n (callloc
, OPT_Wstringop_truncation
,
1916 cntrange
[0].to_uhwi (),
1917 "%G%qD output truncated before terminating "
1918 "nul copying %E byte from a string of the "
1920 "%G%qD output truncated before terminating nul "
1921 "copying %E bytes from a string of the same "
1924 else if (wi::geu_p (lenrange
[0], cntrange
[1]))
1926 /* The shortest string is longer than the upper bound of
1927 the count so the truncation is certain. */
1928 if (cntrange
[0] == cntrange
[1])
1929 return warning_n (callloc
, OPT_Wstringop_truncation
,
1930 cntrange
[0].to_uhwi (),
1931 "%G%qD output truncated copying %E byte "
1932 "from a string of length %wu",
1933 "%G%qD output truncated copying %E bytes "
1934 "from a string of length %wu",
1935 call
, func
, cnt
, lenrange
[0].to_uhwi ());
1937 return warning_at (callloc
, OPT_Wstringop_truncation
,
1938 "%G%qD output truncated copying between %wu "
1939 "and %wu bytes from a string of length %wu",
1940 call
, func
, cntrange
[0].to_uhwi (),
1941 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
1943 else if (wi::geu_p (lenrange
[1], cntrange
[1]))
1945 /* The longest string is longer than the upper bound of
1946 the count so the truncation is possible. */
1947 if (cntrange
[0] == cntrange
[1])
1948 return warning_n (callloc
, OPT_Wstringop_truncation
,
1949 cntrange
[0].to_uhwi (),
1950 "%G%qD output may be truncated copying %E "
1951 "byte from a string of length %wu",
1952 "%G%qD output may be truncated copying %E "
1953 "bytes from a string of length %wu",
1954 call
, func
, cnt
, lenrange
[1].to_uhwi ());
1956 return warning_at (callloc
, OPT_Wstringop_truncation
,
1957 "%G%qD output may be truncated copying between %wu "
1958 "and %wu bytes from a string of length %wu",
1959 call
, func
, cntrange
[0].to_uhwi (),
1960 cntrange
[1].to_uhwi (), lenrange
[1].to_uhwi ());
1963 if (cntrange
[0] != cntrange
[1]
1964 && wi::leu_p (cntrange
[0], lenrange
[0])
1965 && wi::leu_p (cntrange
[1], lenrange
[0] + 1))
1967 /* If the source (including the terminating nul) is longer than
1968 the lower bound of the specified count but shorter than the
1969 upper bound the copy may (but need not) be truncated. */
1970 return warning_at (callloc
, OPT_Wstringop_truncation
,
1971 "%G%qD output may be truncated copying between "
1972 "%wu and %wu bytes from a string of length %wu",
1973 call
, func
, cntrange
[0].to_uhwi (),
1974 cntrange
[1].to_uhwi (), lenrange
[0].to_uhwi ());
1978 if (tree dstsize
= compute_objsize (dst
, 1))
1980 /* The source length is uknown. Try to determine the destination
1981 size and see if it matches the specified bound. If not, bail.
1982 Otherwise go on to see if it should be diagnosed for possible
1987 if (wi::to_wide (dstsize
) != cntrange
[1])
1990 if (cntrange
[0] == cntrange
[1])
1991 return warning_at (callloc
, OPT_Wstringop_truncation
,
1992 "%G%qD specified bound %E equals destination size",
1993 as_a
<gcall
*> (stmt
), func
, cnt
);
1999 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2000 out-of-bounds offsets or overlapping access, and to see if the size
2001 is derived from calling strlen() on the source argument, and if so,
2002 issue the appropriate warning. */
2005 handle_builtin_stxncpy (built_in_function
, gimple_stmt_iterator
*gsi
)
2007 if (!strlen_to_stridx
)
2010 gimple
*stmt
= gsi_stmt (*gsi
);
2012 tree dst
= gimple_call_arg (stmt
, 0);
2013 tree src
= gimple_call_arg (stmt
, 1);
2014 tree len
= gimple_call_arg (stmt
, 2);
2015 tree dstsize
= NULL_TREE
, srcsize
= NULL_TREE
;
2017 int didx
= get_stridx (dst
);
2018 if (strinfo
*sidst
= didx
> 0 ? get_strinfo (didx
) : NULL
)
2020 /* Compute the size of the destination string including the NUL. */
2021 if (sidst
->nonzero_chars
)
2023 tree type
= TREE_TYPE (sidst
->nonzero_chars
);
2024 dstsize
= fold_build2 (PLUS_EXPR
, type
, sidst
->nonzero_chars
,
2025 build_int_cst (type
, 1));
2030 int sidx
= get_stridx (src
);
2031 strinfo
*sisrc
= sidx
> 0 ? get_strinfo (sidx
) : NULL
;
2034 /* strncat() and strncpy() can modify the source string by writing
2035 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2038 /* Compute the size of the source string including the NUL. */
2039 if (sisrc
->nonzero_chars
)
2041 tree type
= TREE_TYPE (sisrc
->nonzero_chars
);
2042 srcsize
= fold_build2 (PLUS_EXPR
, type
, sisrc
->nonzero_chars
,
2043 build_int_cst (type
, 1));
2049 srcsize
= NULL_TREE
;
2051 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, src
,
2054 gimple_set_no_warning (stmt
, true);
2058 /* If the length argument was computed from strlen(S) for some string
2059 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2060 the location of the strlen() call (PSS->SECOND). */
2061 stridx_strlenloc
*pss
= strlen_to_stridx
->get (len
);
2062 if (!pss
|| pss
->first
<= 0)
2064 if (maybe_diag_stxncpy_trunc (*gsi
, src
, len
))
2065 gimple_set_no_warning (stmt
, true);
2070 /* Retrieve the strinfo data for the string S that LEN was computed
2071 from as some function F of strlen (S) (i.e., LEN need not be equal
2073 strinfo
*silen
= get_strinfo (pss
->first
);
2075 location_t callloc
= gimple_nonartificial_location (stmt
);
2076 callloc
= expansion_point_location_if_in_system_header (callloc
);
2078 tree func
= gimple_call_fndecl (stmt
);
2080 bool warned
= false;
2082 /* When -Wstringop-truncation is set, try to determine truncation
2083 before diagnosing possible overflow. Truncation is implied by
2084 the LEN argument being equal to strlen(SRC), regardless of
2085 whether its value is known. Otherwise, issue the more generic
2086 -Wstringop-overflow which triggers for LEN arguments that in
2087 any meaningful way depend on strlen(SRC). */
2089 && is_strlen_related_p (src
, len
)
2090 && warning_at (callloc
, OPT_Wstringop_truncation
,
2091 "%G%qD output truncated before terminating nul "
2092 "copying as many bytes from a string as its length",
2093 as_a
<gcall
*>(stmt
), func
))
2095 else if (silen
&& is_strlen_related_p (src
, silen
->ptr
))
2096 warned
= warning_at (callloc
, OPT_Wstringop_overflow_
,
2097 "%G%qD specified bound depends on the length "
2098 "of the source argument",
2099 as_a
<gcall
*>(stmt
), func
);
2102 location_t strlenloc
= pss
->second
;
2103 if (strlenloc
!= UNKNOWN_LOCATION
&& strlenloc
!= callloc
)
2104 inform (strlenloc
, "length computed here");
2108 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2109 If strlen of the second argument is known and length of the third argument
2110 is that plus one, strlen of the first argument is the same after this
2114 handle_builtin_memcpy (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2117 tree src
, dst
, len
, lhs
, oldlen
, newlen
;
2118 gimple
*stmt
= gsi_stmt (*gsi
);
2119 strinfo
*si
, *dsi
, *olddsi
;
2121 len
= gimple_call_arg (stmt
, 2);
2122 src
= gimple_call_arg (stmt
, 1);
2123 dst
= gimple_call_arg (stmt
, 0);
2124 idx
= get_stridx (src
);
2128 didx
= get_stridx (dst
);
2131 olddsi
= get_strinfo (didx
);
2136 && tree_fits_uhwi_p (len
)
2137 && !integer_zerop (len
))
2138 adjust_last_stmt (olddsi
, stmt
, false);
2145 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2147 si
= get_strinfo (idx
);
2148 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2150 if (TREE_CODE (len
) == INTEGER_CST
2151 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
2153 if (tree_int_cst_le (len
, si
->nonzero_chars
))
2155 /* Copying LEN nonzero characters, where LEN is constant. */
2157 full_string_p
= false;
2161 /* Copying the whole of the analyzed part of SI. */
2162 newlen
= si
->nonzero_chars
;
2163 full_string_p
= si
->full_string_p
;
2168 if (!si
->full_string_p
)
2170 if (TREE_CODE (len
) != SSA_NAME
)
2172 def_stmt
= SSA_NAME_DEF_STMT (len
);
2173 if (!is_gimple_assign (def_stmt
)
2174 || gimple_assign_rhs_code (def_stmt
) != PLUS_EXPR
2175 || gimple_assign_rhs1 (def_stmt
) != si
->nonzero_chars
2176 || !integer_onep (gimple_assign_rhs2 (def_stmt
)))
2178 /* Copying variable-length string SI (and no more). */
2179 newlen
= si
->nonzero_chars
;
2180 full_string_p
= true;
2186 /* Handle memcpy (x, "abcd", 5) or
2187 memcpy (x, "abc\0uvw", 7). */
2188 if (!tree_fits_uhwi_p (len
))
2191 unsigned HOST_WIDE_INT clen
= tree_to_uhwi (len
);
2192 unsigned HOST_WIDE_INT nonzero_chars
= ~idx
;
2193 newlen
= build_int_cst (size_type_node
, MIN (nonzero_chars
, clen
));
2194 full_string_p
= clen
> nonzero_chars
;
2197 if (olddsi
!= NULL
&& TREE_CODE (len
) == SSA_NAME
)
2198 adjust_last_stmt (olddsi
, stmt
, false);
2202 didx
= new_stridx (dst
);
2209 dsi
= unshare_strinfo (olddsi
);
2210 oldlen
= olddsi
->nonzero_chars
;
2211 dsi
->nonzero_chars
= newlen
;
2212 dsi
->full_string_p
= full_string_p
;
2213 /* Break the chain, so adjust_related_strinfo on later pointers in
2214 the chain won't adjust this one anymore. */
2217 dsi
->endptr
= NULL_TREE
;
2221 dsi
= new_strinfo (dst
, didx
, newlen
, full_string_p
);
2222 set_strinfo (didx
, dsi
);
2223 find_equal_ptrs (dst
, didx
);
2225 dsi
->writable
= true;
2226 dsi
->dont_invalidate
= true;
2229 tree adj
= NULL_TREE
;
2230 location_t loc
= gimple_location (stmt
);
2231 if (oldlen
== NULL_TREE
)
2233 else if (integer_zerop (oldlen
))
2235 else if (TREE_CODE (oldlen
) == INTEGER_CST
2236 || TREE_CODE (newlen
) == INTEGER_CST
)
2237 adj
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (newlen
), newlen
,
2238 fold_convert_loc (loc
, TREE_TYPE (newlen
),
2240 if (adj
!= NULL_TREE
)
2241 adjust_related_strinfos (loc
, dsi
, adj
);
2245 /* memcpy src may not overlap dst, so src doesn't need to be
2246 invalidated either. */
2248 si
->dont_invalidate
= true;
2252 lhs
= gimple_call_lhs (stmt
);
2255 case BUILT_IN_MEMCPY
:
2256 case BUILT_IN_MEMCPY_CHK
:
2257 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2258 laststmt
.stmt
= stmt
;
2259 laststmt
.len
= dsi
->nonzero_chars
;
2260 laststmt
.stridx
= dsi
->idx
;
2262 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = didx
;
2264 case BUILT_IN_MEMPCPY
:
2265 case BUILT_IN_MEMPCPY_CHK
:
2273 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2274 If strlen of the second argument is known, strlen of the first argument
2275 is increased by the length of the second argument. Furthermore, attempt
2276 to convert it to memcpy/strcpy if the length of the first argument
2280 handle_builtin_strcat (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2283 tree srclen
, args
, type
, fn
, objsz
, endptr
;
2285 gimple
*stmt
= gsi_stmt (*gsi
);
2287 location_t loc
= gimple_location (stmt
);
2289 tree src
= gimple_call_arg (stmt
, 1);
2290 tree dst
= gimple_call_arg (stmt
, 0);
2292 /* Bail if the source is the same as destination. It will be diagnosed
2294 if (operand_equal_p (src
, dst
, 0))
2297 tree lhs
= gimple_call_lhs (stmt
);
2299 didx
= get_stridx (dst
);
2305 dsi
= get_strinfo (didx
);
2309 idx
= get_stridx (src
);
2311 srclen
= build_int_cst (size_type_node
, ~idx
);
2314 si
= get_strinfo (idx
);
2316 srclen
= get_string_length (si
);
2319 /* Set the no-warning bit on the transformed statement? */
2320 bool set_no_warning
= false;
2322 if (dsi
== NULL
|| get_string_length (dsi
) == NULL_TREE
)
2325 /* The concatenation always involves copying at least one byte
2326 (the terminating nul), even if the source string is empty.
2327 If the source is unknown assume it's one character long and
2328 used that as both sizes. */
2332 tree type
= TREE_TYPE (slen
);
2333 slen
= fold_build2 (PLUS_EXPR
, type
, slen
, build_int_cst (type
, 1));
2336 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2338 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2341 gimple_set_no_warning (stmt
, true);
2342 set_no_warning
= true;
2346 /* strcat (p, q) can be transformed into
2347 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2348 with length endptr - p if we need to compute the length
2349 later on. Don't do this transformation if we don't need
2351 if (builtin_decl_implicit_p (BUILT_IN_STPCPY
) && lhs
== NULL_TREE
)
2355 didx
= new_stridx (dst
);
2361 dsi
= new_strinfo (dst
, didx
, NULL_TREE
, false);
2362 set_strinfo (didx
, dsi
);
2363 find_equal_ptrs (dst
, didx
);
2367 dsi
= unshare_strinfo (dsi
);
2368 dsi
->nonzero_chars
= NULL_TREE
;
2369 dsi
->full_string_p
= false;
2371 dsi
->endptr
= NULL_TREE
;
2373 dsi
->writable
= true;
2375 dsi
->dont_invalidate
= true;
2380 tree dstlen
= dsi
->nonzero_chars
;
2381 endptr
= dsi
->endptr
;
2383 dsi
= unshare_strinfo (dsi
);
2384 dsi
->endptr
= NULL_TREE
;
2386 dsi
->writable
= true;
2388 if (srclen
!= NULL_TREE
)
2390 dsi
->nonzero_chars
= fold_build2_loc (loc
, PLUS_EXPR
,
2391 TREE_TYPE (dsi
->nonzero_chars
),
2392 dsi
->nonzero_chars
, srclen
);
2393 gcc_assert (dsi
->full_string_p
);
2394 adjust_related_strinfos (loc
, dsi
, srclen
);
2395 dsi
->dont_invalidate
= true;
2399 dsi
->nonzero_chars
= NULL
;
2400 dsi
->full_string_p
= false;
2401 if (lhs
== NULL_TREE
&& builtin_decl_implicit_p (BUILT_IN_STPCPY
))
2402 dsi
->dont_invalidate
= true;
2406 /* strcat src may not overlap dst, so src doesn't need to be
2407 invalidated either. */
2408 si
->dont_invalidate
= true;
2410 /* For now. Could remove the lhs from the call and add
2411 lhs = dst; afterwards. */
2419 case BUILT_IN_STRCAT
:
2420 if (srclen
!= NULL_TREE
)
2421 fn
= builtin_decl_implicit (BUILT_IN_MEMCPY
);
2423 fn
= builtin_decl_implicit (BUILT_IN_STRCPY
);
2425 case BUILT_IN_STRCAT_CHK
:
2426 if (srclen
!= NULL_TREE
)
2427 fn
= builtin_decl_explicit (BUILT_IN_MEMCPY_CHK
);
2429 fn
= builtin_decl_explicit (BUILT_IN_STRCPY_CHK
);
2430 objsz
= gimple_call_arg (stmt
, 2);
2436 if (fn
== NULL_TREE
)
2441 tree type
= TREE_TYPE (dstlen
);
2443 /* Compute the size of the source sequence, including the nul. */
2444 tree srcsize
= srclen
? srclen
: size_zero_node
;
2445 srcsize
= fold_build2 (PLUS_EXPR
, type
, srcsize
, build_int_cst (type
, 1));
2447 tree sptr
= si
&& si
->ptr
? si
->ptr
: src
;
2449 if (!check_bounds_or_overlap (as_a
<gcall
*>(stmt
), dst
, sptr
,
2452 gimple_set_no_warning (stmt
, true);
2453 set_no_warning
= true;
2457 tree len
= NULL_TREE
;
2458 if (srclen
!= NULL_TREE
)
2460 args
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2461 type
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
2463 len
= fold_convert_loc (loc
, type
, unshare_expr (srclen
));
2464 len
= fold_build2_loc (loc
, PLUS_EXPR
, type
, len
,
2465 build_int_cst (type
, 1));
2466 len
= force_gimple_operand_gsi (gsi
, len
, true, NULL_TREE
, true,
2470 dst
= fold_convert_loc (loc
, TREE_TYPE (dst
), unshare_expr (endptr
));
2472 dst
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
2473 TREE_TYPE (dst
), unshare_expr (dst
),
2474 fold_convert_loc (loc
, sizetype
,
2475 unshare_expr (dstlen
)));
2476 dst
= force_gimple_operand_gsi (gsi
, dst
, true, NULL_TREE
, true,
2478 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2480 fprintf (dump_file
, "Optimizing: ");
2481 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2483 if (srclen
!= NULL_TREE
)
2484 success
= update_gimple_call (gsi
, fn
, 3 + (objsz
!= NULL_TREE
),
2485 dst
, src
, len
, objsz
);
2487 success
= update_gimple_call (gsi
, fn
, 2 + (objsz
!= NULL_TREE
),
2491 stmt
= gsi_stmt (*gsi
);
2493 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2495 fprintf (dump_file
, "into: ");
2496 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
2498 /* If srclen == NULL, note that current string length can be
2499 computed by transforming this strcpy into stpcpy. */
2500 if (srclen
== NULL_TREE
&& dsi
->dont_invalidate
)
2502 adjust_last_stmt (dsi
, stmt
, true);
2503 if (srclen
!= NULL_TREE
)
2505 laststmt
.stmt
= stmt
;
2506 laststmt
.len
= srclen
;
2507 laststmt
.stridx
= dsi
->idx
;
2510 else if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
2511 fprintf (dump_file
, "not possible.\n");
2514 gimple_set_no_warning (stmt
, true);
2517 /* Handle a call to malloc or calloc. */
2520 handle_builtin_malloc (enum built_in_function bcode
, gimple_stmt_iterator
*gsi
)
2522 gimple
*stmt
= gsi_stmt (*gsi
);
2523 tree lhs
= gimple_call_lhs (stmt
);
2524 if (lhs
== NULL_TREE
)
2527 gcc_assert (get_stridx (lhs
) == 0);
2528 int idx
= new_stridx (lhs
);
2529 tree length
= NULL_TREE
;
2530 if (bcode
== BUILT_IN_CALLOC
)
2531 length
= build_int_cst (size_type_node
, 0);
2532 strinfo
*si
= new_strinfo (lhs
, idx
, length
, length
!= NULL_TREE
);
2533 if (bcode
== BUILT_IN_CALLOC
)
2535 set_strinfo (idx
, si
);
2536 si
->writable
= true;
2538 si
->dont_invalidate
= true;
2541 /* Handle a call to memset.
2542 After a call to calloc, memset(,0,) is unnecessary.
2543 memset(malloc(n),0,n) is calloc(n,1).
2544 return true when the call is transfomred, false otherwise. */
2547 handle_builtin_memset (gimple_stmt_iterator
*gsi
)
2549 gimple
*stmt2
= gsi_stmt (*gsi
);
2550 if (!integer_zerop (gimple_call_arg (stmt2
, 1)))
2552 tree ptr
= gimple_call_arg (stmt2
, 0);
2553 int idx1
= get_stridx (ptr
);
2556 strinfo
*si1
= get_strinfo (idx1
);
2559 gimple
*stmt1
= si1
->stmt
;
2560 if (!stmt1
|| !is_gimple_call (stmt1
))
2562 tree callee1
= gimple_call_fndecl (stmt1
);
2563 if (!valid_builtin_call (stmt1
))
2565 enum built_in_function code1
= DECL_FUNCTION_CODE (callee1
);
2566 tree size
= gimple_call_arg (stmt2
, 2);
2567 if (code1
== BUILT_IN_CALLOC
)
2568 /* Not touching stmt1 */ ;
2569 else if (code1
== BUILT_IN_MALLOC
2570 && operand_equal_p (gimple_call_arg (stmt1
, 0), size
, 0))
2572 gimple_stmt_iterator gsi1
= gsi_for_stmt (stmt1
);
2573 update_gimple_call (&gsi1
, builtin_decl_implicit (BUILT_IN_CALLOC
), 2,
2574 size
, build_one_cst (size_type_node
));
2575 si1
->nonzero_chars
= build_int_cst (size_type_node
, 0);
2576 si1
->full_string_p
= true;
2577 si1
->stmt
= gsi_stmt (gsi1
);
2581 tree lhs
= gimple_call_lhs (stmt2
);
2582 unlink_stmt_vdef (stmt2
);
2585 gimple
*assign
= gimple_build_assign (lhs
, ptr
);
2586 gsi_replace (gsi
, assign
, false);
2590 gsi_remove (gsi
, true);
2591 release_defs (stmt2
);
2597 /* Handle a call to memcmp. We try to handle small comparisons by
2598 converting them to load and compare, and replacing the call to memcmp
2599 with a __builtin_memcmp_eq call where possible.
2600 return true when call is transformed, return false otherwise. */
2603 handle_builtin_memcmp (gimple_stmt_iterator
*gsi
)
2605 gcall
*stmt2
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2606 tree res
= gimple_call_lhs (stmt2
);
2607 tree arg1
= gimple_call_arg (stmt2
, 0);
2608 tree arg2
= gimple_call_arg (stmt2
, 1);
2609 tree len
= gimple_call_arg (stmt2
, 2);
2610 unsigned HOST_WIDE_INT leni
;
2611 use_operand_p use_p
;
2612 imm_use_iterator iter
;
2617 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2619 gimple
*ustmt
= USE_STMT (use_p
);
2621 if (is_gimple_debug (ustmt
))
2623 if (gimple_code (ustmt
) == GIMPLE_ASSIGN
)
2625 gassign
*asgn
= as_a
<gassign
*> (ustmt
);
2626 tree_code code
= gimple_assign_rhs_code (asgn
);
2627 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2628 || !integer_zerop (gimple_assign_rhs2 (asgn
)))
2631 else if (gimple_code (ustmt
) == GIMPLE_COND
)
2633 tree_code code
= gimple_cond_code (ustmt
);
2634 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2635 || !integer_zerop (gimple_cond_rhs (ustmt
)))
2642 if (tree_fits_uhwi_p (len
)
2643 && (leni
= tree_to_uhwi (len
)) <= GET_MODE_SIZE (word_mode
)
2644 && pow2p_hwi (leni
))
2646 leni
*= CHAR_TYPE_SIZE
;
2647 unsigned align1
= get_pointer_alignment (arg1
);
2648 unsigned align2
= get_pointer_alignment (arg2
);
2649 unsigned align
= MIN (align1
, align2
);
2650 scalar_int_mode mode
;
2651 if (int_mode_for_size (leni
, 1).exists (&mode
)
2652 && (align
>= leni
|| !targetm
.slow_unaligned_access (mode
, align
)))
2654 location_t loc
= gimple_location (stmt2
);
2656 type
= build_nonstandard_integer_type (leni
, 1);
2657 gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type
)), leni
));
2658 tree ptrtype
= build_pointer_type_for_mode (char_type_node
,
2660 off
= build_int_cst (ptrtype
, 0);
2661 arg1
= build2_loc (loc
, MEM_REF
, type
, arg1
, off
);
2662 arg2
= build2_loc (loc
, MEM_REF
, type
, arg2
, off
);
2663 tree tem1
= fold_const_aggregate_ref (arg1
);
2666 tree tem2
= fold_const_aggregate_ref (arg2
);
2669 res
= fold_convert_loc (loc
, TREE_TYPE (res
),
2670 fold_build2_loc (loc
, NE_EXPR
,
2673 gimplify_and_update_call_from_tree (gsi
, res
);
2678 gimple_call_set_fndecl (stmt2
, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ
));
2682 /* Given an index to the strinfo vector, compute the string length for the
2683 corresponding string. Return -1 when unknown. */
2685 static HOST_WIDE_INT
2686 compute_string_length (int idx
)
2688 HOST_WIDE_INT string_leni
= -1;
2689 gcc_assert (idx
!= 0);
2694 strinfo
*si
= get_strinfo (idx
);
2697 tree const_string_len
= get_string_length (si
);
2698 if (const_string_len
&& tree_fits_shwi_p (const_string_len
))
2699 string_leni
= tree_to_shwi (const_string_len
);
2702 if (string_leni
< 0)
2708 /* Determine the minimum size of the object referenced by DEST expression which
2709 must have a pointer type.
2710 Return the minimum size of the object if successful or NULL when the size
2711 cannot be determined. */
2713 determine_min_objsize (tree dest
)
2715 unsigned HOST_WIDE_INT size
= 0;
2717 if (compute_builtin_object_size (dest
, 2, &size
))
2718 return build_int_cst (sizetype
, size
);
2720 /* Try to determine the size of the object through the RHS of the
2721 assign statement. */
2722 if (TREE_CODE (dest
) == SSA_NAME
)
2724 gimple
*stmt
= SSA_NAME_DEF_STMT (dest
);
2725 if (!is_gimple_assign (stmt
))
2728 if (!gimple_assign_single_p (stmt
)
2729 && !gimple_assign_unary_nop_p (stmt
))
2732 dest
= gimple_assign_rhs1 (stmt
);
2733 return determine_min_objsize (dest
);
2736 /* Try to determine the size of the object from its type. */
2737 if (TREE_CODE (dest
) != ADDR_EXPR
)
2740 tree type
= TREE_TYPE (dest
);
2741 if (TREE_CODE (type
) == POINTER_TYPE
)
2742 type
= TREE_TYPE (type
);
2744 type
= TYPE_MAIN_VARIANT (type
);
2746 /* We cannot determine the size of the array if it's a flexible array,
2747 which is declared at the end of a structure. */
2748 if (TREE_CODE (type
) == ARRAY_TYPE
2749 && !array_at_struct_end_p (dest
))
2751 tree
size_t = TYPE_SIZE_UNIT (type
);
2752 if (size_t && TREE_CODE (size_t) == INTEGER_CST
2753 && !integer_zerop (size_t))
2760 /* Handle a call to strcmp or strncmp. When the result is ONLY used to do
2761 equality test against zero:
2763 A. When the lengths of both arguments are constant and it's a strcmp:
2764 * if the lengths are NOT equal, we can safely fold the call
2765 to a non-zero value.
2766 * otherwise, do nothing now.
2768 B. When the length of one argument is constant, try to replace the call with
2769 a __builtin_str(n)cmp_eq call where possible, i.e:
2771 strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
2772 string with constant length , C is a constant.
2773 if (C <= strlen(STR) && sizeof_array(s) > C)
2775 replace this call with
2776 strncmp_eq (s, STR, C) (!)= 0
2780 it can be safely treated as a call to strcmp (s, STR) (!)= 0
2781 can handled by the following strcmp.
2784 strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
2785 string with constant length.
2786 if (sizeof_array(s) > strlen(STR))
2788 replace this call with
2789 strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
2792 Return true when the call is transformed, return false otherwise.
2796 handle_builtin_string_cmp (gimple_stmt_iterator
*gsi
)
2798 gcall
*stmt
= as_a
<gcall
*> (gsi_stmt (*gsi
));
2799 tree res
= gimple_call_lhs (stmt
);
2800 use_operand_p use_p
;
2801 imm_use_iterator iter
;
2802 tree arg1
= gimple_call_arg (stmt
, 0);
2803 tree arg2
= gimple_call_arg (stmt
, 1);
2804 int idx1
= get_stridx (arg1
);
2805 int idx2
= get_stridx (arg2
);
2806 HOST_WIDE_INT length
= -1;
2807 bool is_ncmp
= false;
2812 /* When both arguments are unknown, do nothing. */
2813 if (idx1
== 0 && idx2
== 0)
2816 /* Handle strncmp function. */
2817 if (gimple_call_num_args (stmt
) == 3)
2819 tree len
= gimple_call_arg (stmt
, 2);
2820 if (tree_fits_shwi_p (len
))
2821 length
= tree_to_shwi (len
);
2826 /* For strncmp, if the length argument is NOT known, do nothing. */
2827 if (is_ncmp
&& length
< 0)
2830 /* When the result is ONLY used to do equality test against zero. */
2831 FOR_EACH_IMM_USE_FAST (use_p
, iter
, res
)
2833 gimple
*use_stmt
= USE_STMT (use_p
);
2835 if (is_gimple_debug (use_stmt
))
2837 if (gimple_code (use_stmt
) == GIMPLE_ASSIGN
)
2839 tree_code code
= gimple_assign_rhs_code (use_stmt
);
2840 if (code
== COND_EXPR
)
2842 tree cond_expr
= gimple_assign_rhs1 (use_stmt
);
2843 if ((TREE_CODE (cond_expr
) != EQ_EXPR
2844 && (TREE_CODE (cond_expr
) != NE_EXPR
))
2845 || !integer_zerop (TREE_OPERAND (cond_expr
, 1)))
2848 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
2850 if (!integer_zerop (gimple_assign_rhs2 (use_stmt
)))
2856 else if (gimple_code (use_stmt
) == GIMPLE_COND
)
2858 tree_code code
= gimple_cond_code (use_stmt
);
2859 if ((code
!= EQ_EXPR
&& code
!= NE_EXPR
)
2860 || !integer_zerop (gimple_cond_rhs (use_stmt
)))
2867 /* When the lengths of both arguments are known, and they are unequal, we can
2868 safely fold the call to a non-zero value for strcmp;
2869 othewise, do nothing now. */
2870 if (idx1
!= 0 && idx2
!= 0)
2872 HOST_WIDE_INT const_string_leni1
= compute_string_length (idx1
);
2873 HOST_WIDE_INT const_string_leni2
= compute_string_length (idx2
);
2876 && const_string_leni1
!= -1
2877 && const_string_leni2
!= -1
2878 && const_string_leni1
!= const_string_leni2
)
2880 replace_call_with_value (gsi
, integer_one_node
);
2886 /* When the length of one argument is constant. */
2887 tree var_string
= NULL_TREE
;
2888 HOST_WIDE_INT const_string_leni
= -1;
2892 const_string_leni
= compute_string_length (idx1
);
2897 gcc_checking_assert (idx2
);
2898 const_string_leni
= compute_string_length (idx2
);
2902 if (const_string_leni
< 0)
2905 unsigned HOST_WIDE_INT var_sizei
= 0;
2906 /* try to determine the minimum size of the object pointed by var_string. */
2907 tree size
= determine_min_objsize (var_string
);
2912 if (tree_fits_uhwi_p (size
))
2913 var_sizei
= tree_to_uhwi (size
);
2918 /* For strncmp, if length > const_string_leni , this call can be safely
2919 transformed to a strcmp. */
2920 if (is_ncmp
&& length
> const_string_leni
)
2923 unsigned HOST_WIDE_INT final_length
2924 = is_ncmp
? length
: const_string_leni
+ 1;
2926 /* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
2927 if (var_sizei
> final_length
)
2931 ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ
)
2932 : builtin_decl_implicit (BUILT_IN_STRCMP_EQ
));
2935 tree const_string_len
= build_int_cst (size_type_node
, final_length
);
2936 update_gimple_call (gsi
, fn
, 3, arg1
, arg2
, const_string_len
);
2944 /* Handle a POINTER_PLUS_EXPR statement.
2945 For p = "abcd" + 2; compute associated length, or if
2946 p = q + off is pointing to a '\0' character of a string, call
2947 zero_length_string on it. */
2950 handle_pointer_plus (gimple_stmt_iterator
*gsi
)
2952 gimple
*stmt
= gsi_stmt (*gsi
);
2953 tree lhs
= gimple_assign_lhs (stmt
), off
;
2954 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
2962 tree off
= gimple_assign_rhs2 (stmt
);
2963 if (tree_fits_uhwi_p (off
)
2964 && tree_to_uhwi (off
) <= (unsigned HOST_WIDE_INT
) ~idx
)
2965 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)]
2966 = ~(~idx
- (int) tree_to_uhwi (off
));
2970 si
= get_strinfo (idx
);
2971 if (si
== NULL
|| si
->nonzero_chars
== NULL_TREE
)
2974 off
= gimple_assign_rhs2 (stmt
);
2976 if (si
->full_string_p
&& operand_equal_p (si
->nonzero_chars
, off
, 0))
2977 zsi
= zero_length_string (lhs
, si
);
2978 else if (TREE_CODE (off
) == SSA_NAME
)
2980 gimple
*def_stmt
= SSA_NAME_DEF_STMT (off
);
2981 if (gimple_assign_single_p (def_stmt
)
2982 && si
->full_string_p
2983 && operand_equal_p (si
->nonzero_chars
,
2984 gimple_assign_rhs1 (def_stmt
), 0))
2985 zsi
= zero_length_string (lhs
, si
);
2988 && si
->endptr
!= NULL_TREE
2989 && si
->endptr
!= lhs
2990 && TREE_CODE (si
->endptr
) == SSA_NAME
)
2992 enum tree_code rhs_code
2993 = useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (si
->endptr
))
2994 ? SSA_NAME
: NOP_EXPR
;
2995 gimple_assign_set_rhs_with_ops (gsi
, rhs_code
, si
->endptr
);
2996 gcc_assert (gsi_stmt (*gsi
) == stmt
);
3001 /* If RHS, either directly or indirectly, refers to a string of constant
3002 length, return it. Otherwise return a negative value. */
3004 static HOST_WIDE_INT
3005 get_string_cst_length (tree rhs
)
3007 if (TREE_CODE (rhs
) == MEM_REF
3008 && integer_zerop (TREE_OPERAND (rhs
, 1)))
3010 rhs
= TREE_OPERAND (rhs
, 0);
3011 if (TREE_CODE (rhs
) == ADDR_EXPR
)
3013 tree rhs_addr
= rhs
;
3015 rhs
= TREE_OPERAND (rhs
, 0);
3016 if (TREE_CODE (rhs
) != STRING_CST
)
3018 int idx
= get_stridx (rhs_addr
);
3021 strinfo
*si
= get_strinfo (idx
);
3023 && si
->full_string_p
3024 && tree_fits_shwi_p (si
->nonzero_chars
))
3025 return tree_to_shwi (si
->nonzero_chars
);
3031 if (TREE_CODE (rhs
) == VAR_DECL
3032 && TREE_READONLY (rhs
))
3033 rhs
= DECL_INITIAL (rhs
);
3035 if (rhs
&& TREE_CODE (rhs
) == STRING_CST
)
3036 return strlen (TREE_STRING_POINTER (rhs
));
3041 /* Handle a single character store. */
3044 handle_char_store (gimple_stmt_iterator
*gsi
)
3048 gimple
*stmt
= gsi_stmt (*gsi
);
3049 tree ssaname
= NULL_TREE
, lhs
= gimple_assign_lhs (stmt
);
3050 tree rhs
= gimple_assign_rhs1 (stmt
);
3051 unsigned HOST_WIDE_INT offset
= 0;
3053 if (TREE_CODE (lhs
) == MEM_REF
3054 && TREE_CODE (TREE_OPERAND (lhs
, 0)) == SSA_NAME
)
3056 tree mem_offset
= TREE_OPERAND (lhs
, 1);
3057 if (tree_fits_uhwi_p (mem_offset
))
3059 /* Get the strinfo for the base, and use it if it starts with at
3060 least OFFSET nonzero characters. This is trivially true if
3062 offset
= tree_to_uhwi (mem_offset
);
3063 idx
= get_stridx (TREE_OPERAND (lhs
, 0));
3065 si
= get_strinfo (idx
);
3067 ssaname
= TREE_OPERAND (lhs
, 0);
3068 else if (si
== NULL
|| compare_nonzero_chars (si
, offset
) < 0)
3074 idx
= get_addr_stridx (lhs
, NULL_TREE
, &offset
);
3076 si
= get_strinfo (idx
);
3079 bool storing_zero_p
= initializer_zerop (rhs
);
3080 bool storing_nonzero_p
= !storing_zero_p
&& tree_expr_nonzero_p (rhs
);
3081 /* Set to the length of the string being assigned if known. */
3082 HOST_WIDE_INT rhslen
;
3086 int cmp
= compare_nonzero_chars (si
, offset
);
3087 gcc_assert (offset
== 0 || cmp
>= 0);
3088 if (storing_zero_p
&& cmp
== 0 && si
->full_string_p
)
3090 /* When overwriting a '\0' with a '\0', the store can be removed
3091 if we know it has been stored in the current function. */
3092 if (!stmt_could_throw_p (stmt
) && si
->writable
)
3094 unlink_stmt_vdef (stmt
);
3095 release_defs (stmt
);
3096 gsi_remove (gsi
, true);
3101 si
->writable
= true;
3106 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
3107 and if we aren't storing '\0', we know that the length of the
3108 string and any other zero terminated string in memory remains
3109 the same. In that case we move to the next gimple statement and
3110 return to signal the caller that it shouldn't invalidate anything.
3112 This is benefical for cases like:
3117 strcpy (p, "foobar");
3118 size_t len = strlen (p); // This can be optimized into 6
3119 size_t len2 = strlen (q); // This has to be computed
3121 size_t len3 = strlen (p); // This can be optimized into 6
3122 size_t len4 = strlen (q); // This can be optimized into len2
3123 bar (len, len2, len3, len4);
3126 else if (storing_nonzero_p
&& cmp
> 0)
3131 else if (storing_zero_p
|| storing_nonzero_p
|| (offset
!= 0 && cmp
> 0))
3133 /* When storing_nonzero_p, we know that the string now starts
3134 with OFFSET + 1 nonzero characters, but don't know whether
3135 there's a following nul terminator.
3137 When storing_zero_p, we know that the string is now OFFSET
3140 Otherwise, we're storing an unknown value at offset OFFSET,
3141 so need to clip the nonzero_chars to OFFSET. */
3142 location_t loc
= gimple_location (stmt
);
3143 tree oldlen
= si
->nonzero_chars
;
3144 if (cmp
== 0 && si
->full_string_p
)
3145 /* We're overwriting the nul terminator with a nonzero or
3146 unknown character. If the previous stmt was a memcpy,
3147 its length may be decreased. */
3148 adjust_last_stmt (si
, stmt
, false);
3149 si
= unshare_strinfo (si
);
3150 if (storing_nonzero_p
)
3151 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
+ 1);
3153 si
->nonzero_chars
= build_int_cst (size_type_node
, offset
);
3154 si
->full_string_p
= storing_zero_p
;
3157 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3158 si
->endptr
= ssaname
;
3163 si
->writable
= true;
3164 si
->dont_invalidate
= true;
3167 tree adj
= fold_build2_loc (loc
, MINUS_EXPR
, size_type_node
,
3168 si
->nonzero_chars
, oldlen
);
3169 adjust_related_strinfos (loc
, si
, adj
);
3175 else if (idx
== 0 && (storing_zero_p
|| storing_nonzero_p
))
3178 idx
= new_stridx (ssaname
);
3180 idx
= new_addr_stridx (lhs
);
3183 tree ptr
= (ssaname
? ssaname
: build_fold_addr_expr (lhs
));
3184 tree len
= storing_nonzero_p
? size_one_node
: size_zero_node
;
3185 si
= new_strinfo (ptr
, idx
, len
, storing_zero_p
);
3186 set_strinfo (idx
, si
);
3189 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname
))
3190 si
->endptr
= ssaname
;
3191 si
->dont_invalidate
= true;
3192 si
->writable
= true;
3196 && (rhslen
= get_string_cst_length (gimple_assign_rhs1 (stmt
))) >= 0
3197 && ssaname
== NULL_TREE
3198 && TREE_CODE (TREE_TYPE (lhs
)) == ARRAY_TYPE
)
3200 HOST_WIDE_INT a
= int_size_in_bytes (TREE_TYPE (lhs
));
3201 if (a
> 0 && (unsigned HOST_WIDE_INT
) a
> (unsigned HOST_WIDE_INT
) rhslen
)
3203 int idx
= new_addr_stridx (lhs
);
3206 si
= new_strinfo (build_fold_addr_expr (lhs
), idx
,
3207 build_int_cst (size_type_node
, rhslen
), true);
3208 set_strinfo (idx
, si
);
3209 si
->dont_invalidate
= true;
3214 if (si
!= NULL
&& offset
== 0 && storing_zero_p
)
3216 /* Allow adjust_last_stmt to remove it if the stored '\0'
3217 is immediately overwritten. */
3218 laststmt
.stmt
= stmt
;
3219 laststmt
.len
= build_int_cst (size_type_node
, 1);
3220 laststmt
.stridx
= si
->idx
;
3225 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
3228 fold_strstr_to_strncmp (tree rhs1
, tree rhs2
, gimple
*stmt
)
3230 if (TREE_CODE (rhs1
) != SSA_NAME
3231 || TREE_CODE (rhs2
) != SSA_NAME
)
3234 gimple
*call_stmt
= NULL
;
3235 for (int pass
= 0; pass
< 2; pass
++)
3237 gimple
*g
= SSA_NAME_DEF_STMT (rhs1
);
3238 if (gimple_call_builtin_p (g
, BUILT_IN_STRSTR
)
3239 && has_single_use (rhs1
)
3240 && gimple_call_arg (g
, 0) == rhs2
)
3245 std::swap (rhs1
, rhs2
);
3250 tree arg0
= gimple_call_arg (call_stmt
, 0);
3254 tree arg1
= gimple_call_arg (call_stmt
, 1);
3255 tree arg1_len
= NULL_TREE
;
3256 int idx
= get_stridx (arg1
);
3261 arg1_len
= build_int_cst (size_type_node
, ~idx
);
3264 strinfo
*si
= get_strinfo (idx
);
3266 arg1_len
= get_string_length (si
);
3270 if (arg1_len
!= NULL_TREE
)
3272 gimple_stmt_iterator gsi
= gsi_for_stmt (call_stmt
);
3273 tree strncmp_decl
= builtin_decl_explicit (BUILT_IN_STRNCMP
);
3275 if (!is_gimple_val (arg1_len
))
3277 tree arg1_len_tmp
= make_ssa_name (TREE_TYPE (arg1_len
));
3278 gassign
*arg1_stmt
= gimple_build_assign (arg1_len_tmp
,
3280 gsi_insert_before (&gsi
, arg1_stmt
, GSI_SAME_STMT
);
3281 arg1_len
= arg1_len_tmp
;
3284 gcall
*strncmp_call
= gimple_build_call (strncmp_decl
, 3,
3285 arg0
, arg1
, arg1_len
);
3286 tree strncmp_lhs
= make_ssa_name (integer_type_node
);
3287 gimple_set_vuse (strncmp_call
, gimple_vuse (call_stmt
));
3288 gimple_call_set_lhs (strncmp_call
, strncmp_lhs
);
3289 gsi_remove (&gsi
, true);
3290 gsi_insert_before (&gsi
, strncmp_call
, GSI_SAME_STMT
);
3291 tree zero
= build_zero_cst (TREE_TYPE (strncmp_lhs
));
3293 if (is_gimple_assign (stmt
))
3295 if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
3297 tree cond
= gimple_assign_rhs1 (stmt
);
3298 TREE_OPERAND (cond
, 0) = strncmp_lhs
;
3299 TREE_OPERAND (cond
, 1) = zero
;
3303 gimple_assign_set_rhs1 (stmt
, strncmp_lhs
);
3304 gimple_assign_set_rhs2 (stmt
, zero
);
3309 gcond
*cond
= as_a
<gcond
*> (stmt
);
3310 gimple_cond_set_lhs (cond
, strncmp_lhs
);
3311 gimple_cond_set_rhs (cond
, zero
);
3319 /* Attempt to check for validity of the performed access a single statement
3320 at *GSI using string length knowledge, and to optimize it.
3321 If the given basic block needs clean-up of EH, CLEANUP_EH is set to
3325 strlen_check_and_optimize_stmt (gimple_stmt_iterator
*gsi
, bool *cleanup_eh
)
3327 gimple
*stmt
= gsi_stmt (*gsi
);
3329 if (is_gimple_call (stmt
))
3331 tree callee
= gimple_call_fndecl (stmt
);
3332 if (valid_builtin_call (stmt
))
3333 switch (DECL_FUNCTION_CODE (callee
))
3335 case BUILT_IN_STRLEN
:
3336 handle_builtin_strlen (gsi
);
3338 case BUILT_IN_STRCHR
:
3339 handle_builtin_strchr (gsi
);
3341 case BUILT_IN_STRCPY
:
3342 case BUILT_IN_STRCPY_CHK
:
3343 case BUILT_IN_STPCPY
:
3344 case BUILT_IN_STPCPY_CHK
:
3345 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3348 case BUILT_IN_STRNCAT
:
3349 case BUILT_IN_STRNCAT_CHK
:
3350 handle_builtin_strncat (DECL_FUNCTION_CODE (callee
), gsi
);
3353 case BUILT_IN_STPNCPY
:
3354 case BUILT_IN_STPNCPY_CHK
:
3355 case BUILT_IN_STRNCPY
:
3356 case BUILT_IN_STRNCPY_CHK
:
3357 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee
), gsi
);
3360 case BUILT_IN_MEMCPY
:
3361 case BUILT_IN_MEMCPY_CHK
:
3362 case BUILT_IN_MEMPCPY
:
3363 case BUILT_IN_MEMPCPY_CHK
:
3364 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee
), gsi
);
3366 case BUILT_IN_STRCAT
:
3367 case BUILT_IN_STRCAT_CHK
:
3368 handle_builtin_strcat (DECL_FUNCTION_CODE (callee
), gsi
);
3370 case BUILT_IN_MALLOC
:
3371 case BUILT_IN_CALLOC
:
3372 handle_builtin_malloc (DECL_FUNCTION_CODE (callee
), gsi
);
3374 case BUILT_IN_MEMSET
:
3375 if (handle_builtin_memset (gsi
))
3378 case BUILT_IN_MEMCMP
:
3379 if (handle_builtin_memcmp (gsi
))
3382 case BUILT_IN_STRCMP
:
3383 case BUILT_IN_STRNCMP
:
3384 if (handle_builtin_string_cmp (gsi
))
3391 else if (is_gimple_assign (stmt
) && !gimple_clobber_p (stmt
))
3393 tree lhs
= gimple_assign_lhs (stmt
);
3395 if (TREE_CODE (lhs
) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (lhs
)))
3397 if (gimple_assign_single_p (stmt
)
3398 || (gimple_assign_cast_p (stmt
)
3399 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt
)))))
3401 int idx
= get_stridx (gimple_assign_rhs1 (stmt
));
3402 ssa_ver_to_stridx
[SSA_NAME_VERSION (lhs
)] = idx
;
3404 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
3405 handle_pointer_plus (gsi
);
3407 else if (TREE_CODE (lhs
) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (lhs
)))
3409 enum tree_code code
= gimple_assign_rhs_code (stmt
);
3410 if (code
== COND_EXPR
)
3412 tree cond
= gimple_assign_rhs1 (stmt
);
3413 enum tree_code cond_code
= TREE_CODE (cond
);
3415 if (cond_code
== EQ_EXPR
|| cond_code
== NE_EXPR
)
3416 fold_strstr_to_strncmp (TREE_OPERAND (cond
, 0),
3417 TREE_OPERAND (cond
, 1), stmt
);
3419 else if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3420 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt
),
3421 gimple_assign_rhs2 (stmt
), stmt
);
3422 else if (gimple_assign_load_p (stmt
)
3423 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
3424 && TYPE_MODE (TREE_TYPE (lhs
)) == TYPE_MODE (char_type_node
)
3425 && (TYPE_PRECISION (TREE_TYPE (lhs
))
3426 == TYPE_PRECISION (char_type_node
))
3427 && !gimple_has_volatile_ops (stmt
))
3429 tree off
= integer_zero_node
;
3430 unsigned HOST_WIDE_INT coff
= 0;
3432 tree rhs1
= gimple_assign_rhs1 (stmt
);
3433 if (code
== MEM_REF
)
3435 idx
= get_stridx (TREE_OPERAND (rhs1
, 0));
3438 strinfo
*si
= get_strinfo (idx
);
3440 && si
->nonzero_chars
3441 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
3442 && (wi::to_widest (si
->nonzero_chars
)
3443 >= wi::to_widest (off
)))
3444 off
= TREE_OPERAND (rhs1
, 1);
3446 /* This case is not useful. See if get_addr_stridx
3447 returns something usable. */
3452 idx
= get_addr_stridx (rhs1
, NULL_TREE
, &coff
);
3455 strinfo
*si
= get_strinfo (idx
);
3457 && si
->nonzero_chars
3458 && TREE_CODE (si
->nonzero_chars
) == INTEGER_CST
)
3460 widest_int w1
= wi::to_widest (si
->nonzero_chars
);
3461 widest_int w2
= wi::to_widest (off
) + coff
;
3463 && si
->full_string_p
)
3465 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3467 fprintf (dump_file
, "Optimizing: ");
3468 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3471 /* Reading the final '\0' character. */
3472 tree zero
= build_int_cst (TREE_TYPE (lhs
), 0);
3473 gimple_set_vuse (stmt
, NULL_TREE
);
3474 gimple_assign_set_rhs_from_tree (gsi
, zero
);
3476 |= maybe_clean_or_replace_eh_stmt (stmt
,
3478 stmt
= gsi_stmt (*gsi
);
3481 if (dump_file
&& (dump_flags
& TDF_DETAILS
) != 0)
3483 fprintf (dump_file
, "into: ");
3484 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
3489 /* Reading a character before the final '\0'
3490 character. Just set the value range to ~[0, 0]
3491 if we don't have anything better. */
3493 tree type
= TREE_TYPE (lhs
);
3494 enum value_range_type vr
3495 = get_range_info (lhs
, &min
, &max
);
3496 if (vr
== VR_VARYING
3498 && min
== wi::min_value (TYPE_PRECISION (type
),
3500 && max
== wi::max_value (TYPE_PRECISION (type
),
3502 set_range_info (lhs
, VR_ANTI_RANGE
,
3503 wi::zero (TYPE_PRECISION (type
)),
3504 wi::zero (TYPE_PRECISION (type
)));
3510 if (strlen_to_stridx
)
3512 tree rhs1
= gimple_assign_rhs1 (stmt
);
3513 if (stridx_strlenloc
*ps
= strlen_to_stridx
->get (rhs1
))
3514 strlen_to_stridx
->put (lhs
, stridx_strlenloc (*ps
));
3517 else if (TREE_CODE (lhs
) != SSA_NAME
&& !TREE_SIDE_EFFECTS (lhs
))
3519 tree type
= TREE_TYPE (lhs
);
3520 if (TREE_CODE (type
) == ARRAY_TYPE
)
3521 type
= TREE_TYPE (type
);
3522 if (TREE_CODE (type
) == INTEGER_TYPE
3523 && TYPE_MODE (type
) == TYPE_MODE (char_type_node
)
3524 && TYPE_PRECISION (type
) == TYPE_PRECISION (char_type_node
))
3526 if (! handle_char_store (gsi
))
3531 else if (gcond
*cond
= dyn_cast
<gcond
*> (stmt
))
3533 enum tree_code code
= gimple_cond_code (cond
);
3534 if (code
== EQ_EXPR
|| code
== NE_EXPR
)
3535 fold_strstr_to_strncmp (gimple_cond_lhs (stmt
),
3536 gimple_cond_rhs (stmt
), stmt
);
3539 if (gimple_vdef (stmt
))
3540 maybe_invalidate (stmt
);
3544 /* Recursively call maybe_invalidate on stmts that might be executed
3545 in between dombb and current bb and that contain a vdef. Stop when
3546 *count stmts are inspected, or if the whole strinfo vector has
3547 been invalidated. */
3550 do_invalidate (basic_block dombb
, gimple
*phi
, bitmap visited
, int *count
)
3552 unsigned int i
, n
= gimple_phi_num_args (phi
);
3554 for (i
= 0; i
< n
; i
++)
3556 tree vuse
= gimple_phi_arg_def (phi
, i
);
3557 gimple
*stmt
= SSA_NAME_DEF_STMT (vuse
);
3558 basic_block bb
= gimple_bb (stmt
);
3561 || !bitmap_set_bit (visited
, bb
->index
)
3562 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3566 if (gimple_code (stmt
) == GIMPLE_PHI
)
3568 do_invalidate (dombb
, stmt
, visited
, count
);
3575 if (!maybe_invalidate (stmt
))
3580 vuse
= gimple_vuse (stmt
);
3581 stmt
= SSA_NAME_DEF_STMT (vuse
);
3582 if (gimple_bb (stmt
) != bb
)
3584 bb
= gimple_bb (stmt
);
3587 || !bitmap_set_bit (visited
, bb
->index
)
3588 || !dominated_by_p (CDI_DOMINATORS
, bb
, dombb
))
3595 class strlen_dom_walker
: public dom_walker
3598 strlen_dom_walker (cdi_direction direction
)
3599 : dom_walker (direction
), m_cleanup_cfg (false)
3602 virtual edge
before_dom_children (basic_block
);
3603 virtual void after_dom_children (basic_block
);
3605 /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
3606 execute function. */
3610 /* Callback for walk_dominator_tree. Attempt to optimize various
3611 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3614 strlen_dom_walker::before_dom_children (basic_block bb
)
3616 basic_block dombb
= get_immediate_dominator (CDI_DOMINATORS
, bb
);
3619 stridx_to_strinfo
= NULL
;
3622 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) dombb
->aux
);
3623 if (stridx_to_strinfo
)
3625 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3628 gphi
*phi
= gsi
.phi ();
3629 if (virtual_operand_p (gimple_phi_result (phi
)))
3631 bitmap visited
= BITMAP_ALLOC (NULL
);
3632 int count_vdef
= 100;
3633 do_invalidate (dombb
, phi
, visited
, &count_vdef
);
3634 BITMAP_FREE (visited
);
3635 if (count_vdef
== 0)
3637 /* If there were too many vdefs in between immediate
3638 dominator and current bb, invalidate everything.
3639 If stridx_to_strinfo has been unshared, we need
3640 to free it, otherwise just set it to NULL. */
3641 if (!strinfo_shared ())
3647 vec_safe_iterate (stridx_to_strinfo
, i
, &si
);
3651 (*stridx_to_strinfo
)[i
] = NULL
;
3655 stridx_to_strinfo
= NULL
;
3663 /* If all PHI arguments have the same string index, the PHI result
3665 for (gphi_iterator gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
);
3668 gphi
*phi
= gsi
.phi ();
3669 tree result
= gimple_phi_result (phi
);
3670 if (!virtual_operand_p (result
) && POINTER_TYPE_P (TREE_TYPE (result
)))
3672 int idx
= get_stridx (gimple_phi_arg_def (phi
, 0));
3675 unsigned int i
, n
= gimple_phi_num_args (phi
);
3676 for (i
= 1; i
< n
; i
++)
3677 if (idx
!= get_stridx (gimple_phi_arg_def (phi
, i
)))
3680 ssa_ver_to_stridx
[SSA_NAME_VERSION (result
)] = idx
;
3685 bool cleanup_eh
= false;
3687 /* Attempt to optimize individual statements. */
3688 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); )
3689 if (strlen_check_and_optimize_stmt (&gsi
, &cleanup_eh
))
3692 if (cleanup_eh
&& gimple_purge_dead_eh_edges (bb
))
3693 m_cleanup_cfg
= true;
3695 bb
->aux
= stridx_to_strinfo
;
3696 if (vec_safe_length (stridx_to_strinfo
) && !strinfo_shared ())
3697 (*stridx_to_strinfo
)[0] = (strinfo
*) bb
;
3701 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3702 owned by the current bb, clear bb->aux. */
3705 strlen_dom_walker::after_dom_children (basic_block bb
)
3709 stridx_to_strinfo
= ((vec
<strinfo
*, va_heap
, vl_embed
> *) bb
->aux
);
3710 if (vec_safe_length (stridx_to_strinfo
)
3711 && (*stridx_to_strinfo
)[0] == (strinfo
*) bb
)
3716 for (i
= 1; vec_safe_iterate (stridx_to_strinfo
, i
, &si
); ++i
)
3718 vec_free (stridx_to_strinfo
);
3724 /* Main entry point. */
3728 const pass_data pass_data_strlen
=
3730 GIMPLE_PASS
, /* type */
3731 "strlen", /* name */
3732 OPTGROUP_NONE
, /* optinfo_flags */
3733 TV_TREE_STRLEN
, /* tv_id */
3734 ( PROP_cfg
| PROP_ssa
), /* properties_required */
3735 0, /* properties_provided */
3736 0, /* properties_destroyed */
3737 0, /* todo_flags_start */
3738 0, /* todo_flags_finish */
3741 class pass_strlen
: public gimple_opt_pass
3744 pass_strlen (gcc::context
*ctxt
)
3745 : gimple_opt_pass (pass_data_strlen
, ctxt
)
3748 /* opt_pass methods: */
3749 virtual bool gate (function
*) { return flag_optimize_strlen
!= 0; }
3750 virtual unsigned int execute (function
*);
3752 }; // class pass_strlen
3755 pass_strlen::execute (function
*fun
)
3757 gcc_assert (!strlen_to_stridx
);
3758 if (warn_stringop_overflow
|| warn_stringop_truncation
)
3759 strlen_to_stridx
= new hash_map
<tree
, stridx_strlenloc
> ();
3761 ssa_ver_to_stridx
.safe_grow_cleared (num_ssa_names
);
3764 calculate_dominance_info (CDI_DOMINATORS
);
3766 /* String length optimization is implemented as a walk of the dominator
3767 tree and a forward walk of statements within each block. */
3768 strlen_dom_walker
walker (CDI_DOMINATORS
);
3769 walker
.walk (fun
->cfg
->x_entry_block_ptr
);
3771 ssa_ver_to_stridx
.release ();
3772 strinfo_pool
.release ();
3773 if (decl_to_stridxlist_htab
)
3775 obstack_free (&stridx_obstack
, NULL
);
3776 delete decl_to_stridxlist_htab
;
3777 decl_to_stridxlist_htab
= NULL
;
3779 laststmt
.stmt
= NULL
;
3780 laststmt
.len
= NULL_TREE
;
3781 laststmt
.stridx
= 0;
3783 if (strlen_to_stridx
)
3785 strlen_to_stridx
->empty ();
3786 delete strlen_to_stridx
;
3787 strlen_to_stridx
= NULL
;
3790 return walker
.m_cleanup_cfg
? TODO_cleanup_cfg
: 0;
3796 make_pass_strlen (gcc::context
*ctxt
)
3798 return new pass_strlen (ctxt
);