OSDN Git Service

Split out LTO's writing of top level asm nodes in preparation of extending
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-strlen.c
1 /* String length optimization
2    Copyright (C) 2011 Free Software Foundation, Inc.
3    Contributed by Jakub Jelinek <jakub@redhat.com>
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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.
16
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/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree-flow.h"
25 #include "tree-pass.h"
26 #include "domwalk.h"
27 #include "alloc-pool.h"
28 #include "tree-ssa-propagate.h"
29 #include "gimple-pretty-print.h"
30 #include "params.h"
31
32 /* A vector indexed by SSA_NAME_VERSION.  0 means unknown, positive value
33    is an index into strinfo vector, negative value stands for
34    string length of a string literal (~strlen).  */
35 static VEC (int, heap) *ssa_ver_to_stridx;
36
37 /* Number of currently active string indexes plus one.  */
38 static int max_stridx;
39
40 /* String information record.  */
41 typedef struct strinfo_struct
42 {
43   /* String length of this string.  */
44   tree length;
45   /* Any of the corresponding pointers for querying alias oracle.  */
46   tree ptr;
47   /* Statement for delayed length computation.  */
48   gimple stmt;
49   /* Pointer to '\0' if known, if NULL, it can be computed as
50      ptr + length.  */
51   tree endptr;
52   /* Reference count.  Any changes to strinfo entry possibly shared
53      with dominating basic blocks need unshare_strinfo first, except
54      for dont_invalidate which affects only the immediately next
55      maybe_invalidate.  */
56   int refcount;
57   /* Copy of index.  get_strinfo (si->idx) should return si;  */
58   int idx;
59   /* These 3 fields are for chaining related string pointers together.
60      E.g. for
61      bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
62      strcpy (c, d); e = c + dl;
63      strinfo(a) -> strinfo(c) -> strinfo(e)
64      All have ->first field equal to strinfo(a)->idx and are doubly
65      chained through prev/next fields.  The later strinfos are required
66      to point into the same string with zero or more bytes after
67      the previous pointer and all bytes in between the two pointers
68      must be non-zero.  Functions like strcpy or memcpy are supposed
69      to adjust all previous strinfo lengths, but not following strinfo
70      lengths (those are uncertain, usually invalidated during
71      maybe_invalidate, except when the alias oracle knows better).
72      Functions like strcat on the other side adjust the whole
73      related strinfo chain.
74      They are updated lazily, so to use the chain the same first fields
75      and si->prev->next == si->idx needs to be verified.  */
76   int first;
77   int next;
78   int prev;
79   /* A flag whether the string is known to be written in the current
80      function.  */
81   bool writable;
82   /* A flag for the next maybe_invalidate that this strinfo shouldn't
83      be invalidated.  Always cleared by maybe_invalidate.  */
84   bool dont_invalidate;
85 } *strinfo;
86 DEF_VEC_P(strinfo);
87 DEF_VEC_ALLOC_P(strinfo,heap);
88
89 /* Pool for allocating strinfo_struct entries.  */
90 static alloc_pool strinfo_pool;
91
92 /* Vector mapping positive string indexes to strinfo, for the
93    current basic block.  The first pointer in the vector is special,
94    it is either NULL, meaning the vector isn't shared, or it is
95    a basic block pointer to the owner basic_block if shared.
96    If some other bb wants to modify the vector, the vector needs
97    to be unshared first, and only the owner bb is supposed to free it.  */
98 static VEC(strinfo, heap) *stridx_to_strinfo;
99
100 /* One OFFSET->IDX mapping.  */
101 struct stridxlist
102 {
103   struct stridxlist *next;
104   HOST_WIDE_INT offset;
105   int idx;
106 };
107
108 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings.  */
109 struct decl_stridxlist_map
110 {
111   struct tree_map_base base;
112   struct stridxlist list;
113 };
114
115 /* Hash table for mapping decls to a chained list of offset -> idx
116    mappings.  */
117 static htab_t decl_to_stridxlist_htab;
118
119 /* Obstack for struct stridxlist and struct decl_stridxlist_map.  */
120 static struct obstack stridx_obstack;
121
122 /* Last memcpy statement if it could be adjusted if the trailing
123    '\0' written is immediately overwritten, or
124    *x = '\0' store that could be removed if it is immediately overwritten.  */
125 struct laststmt_struct
126 {
127   gimple stmt;
128   tree len;
129   int stridx;
130 } laststmt;
131
132 /* Hash a from tree in a decl_stridxlist_map.  */
133
134 static unsigned int
135 decl_to_stridxlist_hash (const void *item)
136 {
137   return DECL_UID (((const struct decl_stridxlist_map *) item)->base.from);
138 }
139
140 /* Helper function for get_stridx.  */
141
142 static int
143 get_addr_stridx (tree exp)
144 {
145   HOST_WIDE_INT off;
146   struct decl_stridxlist_map ent, *e;
147   struct stridxlist *list;
148   tree base;
149
150   if (decl_to_stridxlist_htab == NULL)
151     return 0;
152
153   base = get_addr_base_and_unit_offset (exp, &off);
154   if (base == NULL || !DECL_P (base))
155     return 0;
156
157   ent.base.from = base;
158   e = (struct decl_stridxlist_map *)
159       htab_find_with_hash (decl_to_stridxlist_htab, &ent, DECL_UID (base));
160   if (e == NULL)
161     return 0;
162
163   list = &e->list;
164   do
165     {
166       if (list->offset == off)
167         return list->idx;
168       list = list->next;
169     }
170   while (list);
171   return 0;
172 }
173
174 /* Return string index for EXP.  */
175
176 static int
177 get_stridx (tree exp)
178 {
179   tree l;
180
181   if (TREE_CODE (exp) == SSA_NAME)
182     return VEC_index (int, ssa_ver_to_stridx, SSA_NAME_VERSION (exp));
183
184   if (TREE_CODE (exp) == ADDR_EXPR)
185     {
186       int idx = get_addr_stridx (TREE_OPERAND (exp, 0));
187       if (idx != 0)
188         return idx;
189     }
190
191   l = c_strlen (exp, 0);
192   if (l != NULL_TREE
193       && host_integerp (l, 1))
194     {
195       unsigned HOST_WIDE_INT len = tree_low_cst (l, 1);
196       if (len == (unsigned int) len
197           && (int) len >= 0)
198         return ~(int) len;
199     }
200   return 0;
201 }
202
203 /* Return true if strinfo vector is shared with the immediate dominator.  */
204
205 static inline bool
206 strinfo_shared (void)
207 {
208   return VEC_length (strinfo, stridx_to_strinfo)
209          && VEC_index (strinfo, stridx_to_strinfo, 0) != NULL;
210 }
211
212 /* Unshare strinfo vector that is shared with the immediate dominator.  */
213
214 static void
215 unshare_strinfo_vec (void)
216 {
217   strinfo si;
218   unsigned int i = 0;
219
220   gcc_assert (strinfo_shared ());
221   stridx_to_strinfo = VEC_copy (strinfo, heap, stridx_to_strinfo);
222   for (i = 1; VEC_iterate (strinfo, stridx_to_strinfo, i, si); ++i)
223     if (si != NULL)
224       si->refcount++;
225   VEC_replace (strinfo, stridx_to_strinfo, 0, NULL);
226 }
227
228 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
229    Return a pointer to the location where the string index can
230    be stored (if 0) or is stored, or NULL if this can't be tracked.  */
231
232 static int *
233 addr_stridxptr (tree exp)
234 {
235   void **slot;
236   struct decl_stridxlist_map ent;
237   struct stridxlist *list;
238   HOST_WIDE_INT off;
239
240   tree base = get_addr_base_and_unit_offset (exp, &off);
241   if (base == NULL_TREE || !DECL_P (base))
242     return NULL;
243
244   if (decl_to_stridxlist_htab == NULL)
245     {
246       decl_to_stridxlist_htab
247         = htab_create (64, decl_to_stridxlist_hash, tree_map_base_eq, NULL);
248       gcc_obstack_init (&stridx_obstack);
249     }
250   ent.base.from = base;
251   slot = htab_find_slot_with_hash (decl_to_stridxlist_htab, &ent,
252                                    DECL_UID (base), INSERT);
253   if (*slot)
254     {
255       int i;
256       list = &((struct decl_stridxlist_map *)*slot)->list;
257       for (i = 0; i < 16; i++)
258         {
259           if (list->offset == off)
260             return &list->idx;
261           if (list->next == NULL)
262             break;
263         }
264       if (i == 16)
265         return NULL;
266       list->next = XOBNEW (&stridx_obstack, struct stridxlist);
267       list = list->next;
268     }
269   else
270     {
271       struct decl_stridxlist_map *e
272         = XOBNEW (&stridx_obstack, struct decl_stridxlist_map);
273       e->base.from = base;
274       *slot = (void *) e;
275       list = &e->list;
276     }
277   list->next = NULL;
278   list->offset = off;
279   list->idx = 0;
280   return &list->idx;
281 }
282
283 /* Create a new string index, or return 0 if reached limit.  */
284
285 static int
286 new_stridx (tree exp)
287 {
288   int idx;
289   if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
290     return 0;
291   if (TREE_CODE (exp) == SSA_NAME)
292     {
293       if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
294         return 0;
295       idx = max_stridx++;
296       VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (exp), idx);
297       return idx;
298     }
299   if (TREE_CODE (exp) == ADDR_EXPR)
300     {
301       int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
302       if (pidx != NULL)
303         {
304           gcc_assert (*pidx == 0);
305           *pidx = max_stridx++;
306           return *pidx;
307         }
308     }
309   return 0;
310 }
311
312 /* Like new_stridx, but for ADDR_EXPR's operand instead.  */
313
314 static int
315 new_addr_stridx (tree exp)
316 {
317   int *pidx;
318   if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
319     return 0;
320   pidx = addr_stridxptr (exp);
321   if (pidx != NULL)
322     {
323       gcc_assert (*pidx == 0);
324       *pidx = max_stridx++;
325       return *pidx;
326     }
327   return 0;
328 }
329
330 /* Create a new strinfo.  */
331
332 static strinfo
333 new_strinfo (tree ptr, int idx, tree length)
334 {
335   strinfo si = (strinfo) pool_alloc (strinfo_pool);
336   si->length = length;
337   si->ptr = ptr;
338   si->stmt = NULL;
339   si->endptr = NULL_TREE;
340   si->refcount = 1;
341   si->idx = idx;
342   si->first = 0;
343   si->prev = 0;
344   si->next = 0;
345   si->writable = false;
346   si->dont_invalidate = false;
347   return si;
348 }
349
350 /* Decrease strinfo refcount and free it if not referenced anymore.  */
351
352 static inline void
353 free_strinfo (strinfo si)
354 {
355   if (si && --si->refcount == 0)
356     pool_free (strinfo_pool, si);
357 }
358
359 /* Return strinfo vector entry IDX.  */
360
361 static inline strinfo
362 get_strinfo (int idx)
363 {
364   if (VEC_length (strinfo, stridx_to_strinfo) <= (unsigned int) idx)
365     return NULL;
366   return VEC_index (strinfo, stridx_to_strinfo, idx);
367 }
368
369 /* Set strinfo in the vector entry IDX to SI.  */
370
371 static inline void
372 set_strinfo (int idx, strinfo si)
373 {
374   if (VEC_length (strinfo, stridx_to_strinfo) && VEC_index (strinfo, stridx_to_strinfo, 0))
375     unshare_strinfo_vec ();
376   if (VEC_length (strinfo, stridx_to_strinfo) <= (unsigned int) idx)
377     VEC_safe_grow_cleared (strinfo, heap, stridx_to_strinfo, idx + 1);
378   VEC_replace (strinfo, stridx_to_strinfo, idx, si);
379 }
380
381 /* Return string length, or NULL if it can't be computed.  */
382
383 static tree
384 get_string_length (strinfo si)
385 {
386   if (si->length)
387     return si->length;
388
389   if (si->stmt)
390     {
391       gimple stmt = si->stmt, lenstmt;
392       tree callee, lhs, lhs_var, fn, tem;
393       location_t loc;
394       gimple_stmt_iterator gsi;
395
396       gcc_assert (is_gimple_call (stmt));
397       callee = gimple_call_fndecl (stmt);
398       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
399       lhs = gimple_call_lhs (stmt);
400       gcc_assert (implicit_built_in_decls[BUILT_IN_STRCPY] != NULL_TREE);
401       /* unshare_strinfo is intentionally not called here.  The (delayed)
402          transformation of strcpy or strcat into stpcpy is done at the place
403          of the former strcpy/strcat call and so can affect all the strinfos
404          with the same stmt.  If they were unshared before and transformation
405          has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
406          just compute the right length.  */
407       switch (DECL_FUNCTION_CODE (callee))
408         {
409         case BUILT_IN_STRCAT:
410         case BUILT_IN_STRCAT_CHK:
411           gsi = gsi_for_stmt (stmt);
412           fn = implicit_built_in_decls[BUILT_IN_STRLEN];
413           gcc_assert (lhs == NULL_TREE);
414           lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
415           add_referenced_var (lhs_var);
416           tem = unshare_expr (gimple_call_arg (stmt, 0));
417           lenstmt = gimple_build_call (fn, 1, tem);
418           lhs = make_ssa_name (lhs_var, lenstmt);
419           gimple_call_set_lhs (lenstmt, lhs);
420           gimple_set_vuse (lenstmt, gimple_vuse (stmt));
421           gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
422           lhs_var = create_tmp_var (TREE_TYPE (gimple_call_arg (stmt, 0)),
423                                     NULL);
424           add_referenced_var (lhs_var);
425           tem = gimple_call_arg (stmt, 0);
426           lenstmt
427             = gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
428                                             make_ssa_name (lhs_var, NULL),
429                                             tem, lhs);
430           gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
431           gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
432           lhs = NULL_TREE;
433           /* FALLTHRU */
434         case BUILT_IN_STRCPY:
435         case BUILT_IN_STRCPY_CHK:
436           if (gimple_call_num_args (stmt) == 2)
437             fn = implicit_built_in_decls[BUILT_IN_STPCPY];
438           else
439             fn = built_in_decls[BUILT_IN_STPCPY_CHK];
440           gcc_assert (lhs == NULL_TREE);
441           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
442             {
443               fprintf (dump_file, "Optimizing: ");
444               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
445             }
446           gimple_call_set_fndecl (stmt, fn);
447           lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
448           add_referenced_var (lhs_var);
449           lhs = make_ssa_name (lhs_var, stmt);
450           gimple_call_set_lhs (stmt, lhs);
451           update_stmt (stmt);
452           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
453             {
454               fprintf (dump_file, "into: ");
455               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
456             }
457           /* FALLTHRU */
458         case BUILT_IN_STPCPY:
459         case BUILT_IN_STPCPY_CHK:
460           gcc_assert (lhs != NULL_TREE);
461           loc = gimple_location (stmt);
462           si->endptr = lhs;
463           si->stmt = NULL;
464           lhs = fold_convert_loc (loc, size_type_node, lhs);
465           si->length = fold_convert_loc (loc, size_type_node, si->ptr);
466           si->length = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
467                                         lhs, si->length);
468           break;
469         default:
470           gcc_unreachable ();
471           break;
472         }
473     }
474
475   return si->length;
476 }
477
478 /* Invalidate string length information for strings whose length
479    might change due to stores in stmt.  */
480
481 static bool
482 maybe_invalidate (gimple stmt)
483 {
484   strinfo si;
485   unsigned int i;
486   bool nonempty = false;
487
488   for (i = 1; VEC_iterate (strinfo, stridx_to_strinfo, i, si); ++i)
489     if (si != NULL)
490       {
491         if (!si->dont_invalidate)
492           {
493             ao_ref r;
494             ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
495             if (stmt_may_clobber_ref_p_1 (stmt, &r))
496               {
497                 set_strinfo (i, NULL);
498                 free_strinfo (si);
499                 continue;
500               }
501           }
502         si->dont_invalidate = false;
503         nonempty = true;
504       }
505   return nonempty;
506 }
507
508 /* Unshare strinfo record SI, if it has recount > 1 or
509    if stridx_to_strinfo vector is shared with some other
510    bbs.  */
511
512 static strinfo
513 unshare_strinfo (strinfo si)
514 {
515   strinfo nsi;
516
517   if (si->refcount == 1 && !strinfo_shared ())
518     return si;
519
520   nsi = new_strinfo (si->ptr, si->idx, si->length);
521   nsi->stmt = si->stmt;
522   nsi->endptr = si->endptr;
523   nsi->first = si->first;
524   nsi->prev = si->prev;
525   nsi->next = si->next;
526   nsi->writable = si->writable;
527   set_strinfo (si->idx, nsi);
528   free_strinfo (si);
529   return nsi;
530 }
531
532 /* Return first strinfo in the related strinfo chain
533    if all strinfos in between belong to the chain, otherwise
534    NULL.  */
535
536 static strinfo
537 verify_related_strinfos (strinfo origsi)
538 {
539   strinfo si = origsi, psi;
540
541   if (origsi->first == 0)
542     return NULL;
543   for (; si->prev; si = psi)
544     {
545       if (si->first != origsi->first)
546         return NULL;
547       psi = get_strinfo (si->prev);
548       if (psi == NULL)
549         return NULL;
550       if (psi->next != si->idx)
551         return NULL;
552     }
553   if (si->idx != si->first)
554     return NULL;
555   return si;
556 }
557
558 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
559    to a zero-length string and if possible chain it to a related strinfo
560    chain whose part is or might be CHAINSI.  */
561
562 static strinfo
563 zero_length_string (tree ptr, strinfo chainsi)
564 {
565   strinfo si;
566   int idx;
567   gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
568                        && get_stridx (ptr) == 0);
569
570   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
571     return NULL;
572   if (chainsi != NULL)
573     {
574       si = verify_related_strinfos (chainsi);
575       if (si)
576         {
577           chainsi = si;
578           for (; chainsi->next; chainsi = si)
579             {
580               if (chainsi->endptr == NULL_TREE)
581                 {
582                   chainsi = unshare_strinfo (chainsi);
583                   chainsi->endptr = ptr;
584                 }
585               si = get_strinfo (chainsi->next);
586               if (si == NULL
587                   || si->first != chainsi->first
588                   || si->prev != chainsi->idx)
589                 break;
590             }
591           gcc_assert (chainsi->length);
592           if (chainsi->endptr == NULL_TREE)
593             {
594               chainsi = unshare_strinfo (chainsi);
595               chainsi->endptr = ptr;
596             }
597           if (integer_zerop (chainsi->length))
598             {
599               if (chainsi->next)
600                 {
601                   chainsi = unshare_strinfo (chainsi);
602                   chainsi->next = 0;
603                 }
604               VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (ptr),
605                            chainsi->idx);
606               return chainsi;
607             }
608         }
609       else if (chainsi->first || chainsi->prev || chainsi->next)
610         {
611           chainsi = unshare_strinfo (chainsi);
612           chainsi->first = 0;
613           chainsi->prev = 0;
614           chainsi->next = 0;
615         }
616     }
617   idx = new_stridx (ptr);
618   if (idx == 0)
619     return NULL;
620   si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0));
621   set_strinfo (idx, si);
622   si->endptr = ptr;
623   if (chainsi != NULL)
624     {
625       chainsi = unshare_strinfo (chainsi);
626       if (chainsi->first == 0)
627         chainsi->first = chainsi->idx;
628       chainsi->next = idx;
629       si->prev = chainsi->idx;
630       si->first = chainsi->first;
631       si->writable = chainsi->writable;
632     }
633   return si;
634 }
635
636 /* For strinfo ORIGSI whose length has been just updated
637    update also related strinfo lengths (add ADJ to each,
638    but don't adjust ORIGSI).  */
639
640 static void
641 adjust_related_strinfos (location_t loc, strinfo origsi, tree adj)
642 {
643   strinfo si = verify_related_strinfos (origsi);
644
645   if (si == NULL)
646     return;
647
648   while (1)
649     {
650       strinfo nsi;
651
652       if (si != origsi)
653         {
654           tree tem;
655
656           si = unshare_strinfo (si);
657           gcc_assert (si->length);
658           tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
659           si->length = fold_build2_loc (loc, PLUS_EXPR,
660                                         TREE_TYPE (si->length), si->length,
661                                         tem);
662           si->endptr = NULL_TREE;
663           si->dont_invalidate = true;
664         }
665       if (si->next == 0)
666         return;
667       nsi = get_strinfo (si->next);
668       if (nsi == NULL
669           || nsi->first != si->first
670           || nsi->prev != si->idx)
671         return;
672       si = nsi;
673     }
674 }
675
676 /* Find if there are other SSA_NAME pointers equal to PTR
677    for which we don't track their string lengths yet.  If so, use
678    IDX for them.  */
679
680 static void
681 find_equal_ptrs (tree ptr, int idx)
682 {
683   if (TREE_CODE (ptr) != SSA_NAME)
684     return;
685   while (1)
686     {
687       gimple stmt = SSA_NAME_DEF_STMT (ptr);
688       if (!is_gimple_assign (stmt))
689         return;
690       ptr = gimple_assign_rhs1 (stmt);
691       switch (gimple_assign_rhs_code (stmt))
692         {
693         case SSA_NAME:
694           break;
695         case ADDR_EXPR:
696           {
697             int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
698             if (pidx != NULL && *pidx == 0)
699               *pidx = idx;
700             return;
701           }
702         CASE_CONVERT:
703           if (POINTER_TYPE_P (TREE_TYPE (ptr)))
704             break;
705           return;
706         default:
707           return;
708         }
709
710       /* We might find an endptr created in this pass.  Grow the
711          vector in that case.  */
712       if (VEC_length (int, ssa_ver_to_stridx) <= SSA_NAME_VERSION (ptr))
713         VEC_safe_grow_cleared (int, heap, ssa_ver_to_stridx, num_ssa_names);
714
715       if (VEC_index (int, ssa_ver_to_stridx, SSA_NAME_VERSION (ptr)) != 0)
716         return;
717       VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (ptr), idx);
718     }
719 }
720
721 /* If the last .MEM setter statement before STMT is
722    memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
723    and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
724    just memcpy (x, y, strlen (y)).  SI must be the zero length
725    strinfo.  */
726
727 static void
728 adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat)
729 {
730   tree vuse, callee, len;
731   struct laststmt_struct last = laststmt;
732   strinfo lastsi, firstsi;
733
734   laststmt.stmt = NULL;
735   laststmt.len = NULL_TREE;
736   laststmt.stridx = 0;
737
738   if (last.stmt == NULL)
739     return;
740
741   vuse = gimple_vuse (stmt);
742   if (vuse == NULL_TREE
743       || SSA_NAME_DEF_STMT (vuse) != last.stmt
744       || !has_single_use (vuse))
745     return;
746
747   gcc_assert (last.stridx > 0);
748   lastsi = get_strinfo (last.stridx);
749   if (lastsi == NULL)
750     return;
751
752   if (lastsi != si)
753     {
754       if (lastsi->first == 0 || lastsi->first != si->first)
755         return;
756
757       firstsi = verify_related_strinfos (si);
758       if (firstsi == NULL)
759         return;
760       while (firstsi != lastsi)
761         {
762           strinfo nextsi;
763           if (firstsi->next == 0)
764             return;
765           nextsi = get_strinfo (firstsi->next);
766           if (nextsi == NULL
767               || nextsi->prev != firstsi->idx
768               || nextsi->first != si->first)
769             return;
770           firstsi = nextsi;
771         }
772     }
773
774   if (!is_strcat)
775     {
776       if (si->length == NULL_TREE || !integer_zerop (si->length))
777         return;
778     }
779
780   if (is_gimple_assign (last.stmt))
781     {
782       gimple_stmt_iterator gsi;
783
784       if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
785         return;
786       if (stmt_could_throw_p (last.stmt))
787         return;
788       gsi = gsi_for_stmt (last.stmt);
789       unlink_stmt_vdef (last.stmt);
790       release_defs (last.stmt);
791       gsi_remove (&gsi, true);
792       return;
793     }
794
795   if (!is_gimple_call (last.stmt))
796     return;
797   callee = gimple_call_fndecl (last.stmt);
798   if (callee == NULL_TREE || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
799     return;
800
801   switch (DECL_FUNCTION_CODE (callee))
802     {
803     case BUILT_IN_MEMCPY:
804     case BUILT_IN_MEMCPY_CHK:
805       break;
806     default:
807       return;
808     }
809
810   len = gimple_call_arg (last.stmt, 2);
811   if (host_integerp (len, 1))
812     {
813       if (!host_integerp (last.len, 1)
814           || integer_zerop (len)
815           || (unsigned HOST_WIDE_INT) tree_low_cst (len, 1)
816              != (unsigned HOST_WIDE_INT) tree_low_cst (last.len, 1) + 1)
817         return;
818       /* Don't adjust the length if it is divisible by 4, it is more efficient
819          to store the extra '\0' in that case.  */
820       if ((((unsigned HOST_WIDE_INT) tree_low_cst (len, 1)) & 3) == 0)
821         return;
822     }
823   else if (TREE_CODE (len) == SSA_NAME)
824     {
825       gimple def_stmt = SSA_NAME_DEF_STMT (len);
826       if (!is_gimple_assign (def_stmt)
827           || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
828           || gimple_assign_rhs1 (def_stmt) != last.len
829           || !integer_onep (gimple_assign_rhs2 (def_stmt)))
830         return;
831     }
832   else
833     return;
834
835   gimple_call_set_arg (last.stmt, 2, last.len);
836   update_stmt (last.stmt);
837 }
838
839 /* Handle a strlen call.  If strlen of the argument is known, replace
840    the strlen call with the known value, otherwise remember that strlen
841    of the argument is stored in the lhs SSA_NAME.  */
842
843 static void
844 handle_builtin_strlen (gimple_stmt_iterator *gsi)
845 {
846   int idx;
847   tree src;
848   gimple stmt = gsi_stmt (*gsi);
849   tree lhs = gimple_call_lhs (stmt);
850
851   if (lhs == NULL_TREE)
852     return;
853
854   src = gimple_call_arg (stmt, 0);
855   idx = get_stridx (src);
856   if (idx)
857     {
858       strinfo si = NULL;
859       tree rhs;
860
861       if (idx < 0)
862         rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
863       else
864         {
865           rhs = NULL_TREE;
866           si = get_strinfo (idx);
867           if (si != NULL)
868             rhs = get_string_length (si);
869         }
870       if (rhs != NULL_TREE)
871         {
872           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
873             {
874               fprintf (dump_file, "Optimizing: ");
875               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
876             }
877           rhs = unshare_expr (rhs);
878           if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
879             rhs = fold_convert_loc (gimple_location (stmt),
880                                     TREE_TYPE (lhs), rhs);
881           if (!update_call_from_tree (gsi, rhs))
882             gimplify_and_update_call_from_tree (gsi, rhs);
883           stmt = gsi_stmt (*gsi);
884           update_stmt (stmt);
885           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
886             {
887               fprintf (dump_file, "into: ");
888               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
889             }
890           if (si != NULL
891               && TREE_CODE (si->length) != SSA_NAME
892               && TREE_CODE (si->length) != INTEGER_CST
893               && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
894             {
895               si = unshare_strinfo (si);
896               si->length = lhs;
897             }
898           return;
899         }
900     }
901   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
902     return;
903   if (idx == 0)
904     idx = new_stridx (src);
905   else if (get_strinfo (idx) != NULL)
906     return;
907   if (idx)
908     {
909       strinfo si = new_strinfo (src, idx, lhs);
910       set_strinfo (idx, si);
911       find_equal_ptrs (src, idx);
912     }
913 }
914
915 /* Handle a strchr call.  If strlen of the first argument is known, replace
916    the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
917    that lhs of the call is endptr and strlen of the argument is endptr - x.  */
918
919 static void
920 handle_builtin_strchr (gimple_stmt_iterator *gsi)
921 {
922   int idx;
923   tree src;
924   gimple stmt = gsi_stmt (*gsi);
925   tree lhs = gimple_call_lhs (stmt);
926
927   if (lhs == NULL_TREE)
928     return;
929
930   if (!integer_zerop (gimple_call_arg (stmt, 1)))
931     return;
932
933   src = gimple_call_arg (stmt, 0);
934   idx = get_stridx (src);
935   if (idx)
936     {
937       strinfo si = NULL;
938       tree rhs;
939
940       if (idx < 0)
941         rhs = build_int_cst (size_type_node, ~idx);
942       else
943         {
944           rhs = NULL_TREE;
945           si = get_strinfo (idx);
946           if (si != NULL)
947             rhs = get_string_length (si);
948         }
949       if (rhs != NULL_TREE)
950         {
951           location_t loc = gimple_location (stmt);
952
953           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
954             {
955               fprintf (dump_file, "Optimizing: ");
956               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
957             }
958           if (si != NULL && si->endptr != NULL_TREE)
959             {
960               rhs = unshare_expr (si->endptr);
961               if (!useless_type_conversion_p (TREE_TYPE (lhs),
962                                               TREE_TYPE (rhs)))
963                 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
964             }
965           else
966             {
967               rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
968               rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
969                                      TREE_TYPE (src), src, rhs);
970               if (!useless_type_conversion_p (TREE_TYPE (lhs),
971                                               TREE_TYPE (rhs)))
972                 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
973             }
974           if (!update_call_from_tree (gsi, rhs))
975             gimplify_and_update_call_from_tree (gsi, rhs);
976           stmt = gsi_stmt (*gsi);
977           update_stmt (stmt);
978           if (dump_file && (dump_flags & TDF_DETAILS) != 0)
979             {
980               fprintf (dump_file, "into: ");
981               print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
982             }
983           if (si != NULL
984               && si->endptr == NULL_TREE
985               && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
986             {
987               si = unshare_strinfo (si);
988               si->endptr = lhs;
989             }
990           zero_length_string (lhs, si);
991           return;
992         }
993     }
994   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
995     return;
996   if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
997     {
998       if (idx == 0)
999         idx = new_stridx (src);
1000       else if (get_strinfo (idx) != NULL)
1001         {
1002           zero_length_string (lhs, NULL);
1003           return;
1004         }
1005       if (idx)
1006         {
1007           location_t loc = gimple_location (stmt);
1008           tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1009           tree srcu = fold_convert_loc (loc, size_type_node, src);
1010           tree length = fold_build2_loc (loc, MINUS_EXPR,
1011                                          size_type_node, lhsu, srcu);
1012           strinfo si = new_strinfo (src, idx, length);
1013           si->endptr = lhs;
1014           set_strinfo (idx, si);
1015           find_equal_ptrs (src, idx);
1016           zero_length_string (lhs, si);
1017         }
1018     }
1019   else
1020     zero_length_string (lhs, NULL);
1021 }
1022
1023 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1024    If strlen of the second argument is known, strlen of the first argument
1025    is the same after this call.  Furthermore, attempt to convert it to
1026    memcpy.  */
1027
1028 static void
1029 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1030 {
1031   int idx, didx;
1032   tree src, dst, srclen, len, lhs, args, type, fn, oldlen;
1033   bool success;
1034   gimple stmt = gsi_stmt (*gsi);
1035   strinfo si, dsi, olddsi, zsi;
1036   location_t loc;
1037
1038   src = gimple_call_arg (stmt, 1);
1039   dst = gimple_call_arg (stmt, 0);
1040   lhs = gimple_call_lhs (stmt);
1041   idx = get_stridx (src);
1042   si = NULL;
1043   if (idx > 0)
1044     si = get_strinfo (idx);
1045
1046   didx = get_stridx (dst);
1047   olddsi = NULL;
1048   oldlen = NULL_TREE;
1049   if (didx > 0)
1050     olddsi = get_strinfo (didx);
1051   else if (didx < 0)
1052     return;
1053
1054   if (olddsi != NULL)
1055     adjust_last_stmt (olddsi, stmt, false);
1056
1057   srclen = NULL_TREE;
1058   if (si != NULL)
1059     srclen = get_string_length (si);
1060   else if (idx < 0)
1061     srclen = build_int_cst (size_type_node, ~idx);
1062
1063   loc = gimple_location (stmt);
1064   if (srclen == NULL_TREE)
1065     switch (bcode)
1066       {
1067       case BUILT_IN_STRCPY:
1068       case BUILT_IN_STRCPY_CHK:
1069         if (implicit_built_in_decls[BUILT_IN_STPCPY] == NULL_TREE
1070             || lhs != NULL_TREE)
1071           return;
1072         break;
1073       case BUILT_IN_STPCPY:
1074       case BUILT_IN_STPCPY_CHK:
1075         if (lhs == NULL_TREE)
1076           return;
1077         else
1078           {
1079             tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1080             srclen = fold_convert_loc (loc, size_type_node, dst);
1081             srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1082                                       lhsuint, srclen);
1083           }
1084         break;
1085       default:
1086         gcc_unreachable ();
1087       }
1088
1089   if (didx == 0)
1090     {
1091       didx = new_stridx (dst);
1092       if (didx == 0)
1093         return;
1094     }
1095   if (olddsi != NULL)
1096     {
1097       oldlen = olddsi->length;
1098       dsi = unshare_strinfo (olddsi);
1099       dsi->length = srclen;
1100       /* Break the chain, so adjust_related_strinfo on later pointers in
1101          the chain won't adjust this one anymore.  */
1102       dsi->next = 0;
1103       dsi->stmt = NULL;
1104       dsi->endptr = NULL_TREE;
1105     }
1106   else
1107     {
1108       dsi = new_strinfo (dst, didx, srclen);
1109       set_strinfo (didx, dsi);
1110       find_equal_ptrs (dst, didx);
1111     }
1112   dsi->writable = true;
1113   dsi->dont_invalidate = true;
1114
1115   if (dsi->length == NULL_TREE)
1116     {
1117       /* If string length of src is unknown, use delayed length
1118          computation.  If string lenth of dst will be needed, it
1119          can be computed by transforming this strcpy call into
1120          stpcpy and subtracting dst from the return value.  */
1121       dsi->stmt = stmt;
1122       return;
1123     }
1124
1125   if (olddsi != NULL)
1126     {
1127       tree adj = NULL_TREE;
1128       if (oldlen == NULL_TREE)
1129         ;
1130       else if (integer_zerop (oldlen))
1131         adj = srclen;
1132       else if (TREE_CODE (oldlen) == INTEGER_CST
1133                || TREE_CODE (srclen) == INTEGER_CST)
1134         adj = fold_build2_loc (loc, MINUS_EXPR,
1135                                TREE_TYPE (srclen), srclen,
1136                                fold_convert_loc (loc, TREE_TYPE (srclen),
1137                                                  oldlen));
1138       if (adj != NULL_TREE)
1139         adjust_related_strinfos (loc, dsi, adj);
1140       else
1141         dsi->prev = 0;
1142     }
1143   /* strcpy src may not overlap dst, so src doesn't need to be
1144      invalidated either.  */
1145   if (si != NULL)
1146     si->dont_invalidate = true;
1147
1148   fn = NULL_TREE;
1149   zsi = NULL;
1150   switch (bcode)
1151     {
1152     case BUILT_IN_STRCPY:
1153       fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
1154       if (lhs)
1155         VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
1156       break;
1157     case BUILT_IN_STRCPY_CHK:
1158       fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
1159       if (lhs)
1160         VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
1161       break;
1162     case BUILT_IN_STPCPY:
1163       /* This would need adjustment of the lhs (subtract one),
1164          or detection that the trailing '\0' doesn't need to be
1165          written, if it will be immediately overwritten.
1166       fn = built_in_decls[BUILT_IN_MEMPCPY];  */
1167       if (lhs)
1168         {
1169           dsi->endptr = lhs;
1170           zsi = zero_length_string (lhs, dsi);
1171         }
1172       break;
1173     case BUILT_IN_STPCPY_CHK:
1174       /* This would need adjustment of the lhs (subtract one),
1175          or detection that the trailing '\0' doesn't need to be
1176          written, if it will be immediately overwritten.
1177       fn = built_in_decls[BUILT_IN_MEMPCPY_CHK];  */
1178       if (lhs)
1179         {
1180           dsi->endptr = lhs;
1181           zsi = zero_length_string (lhs, dsi);
1182         }
1183       break;
1184     default:
1185       gcc_unreachable ();
1186     }
1187   if (zsi != NULL)
1188     zsi->dont_invalidate = true;
1189
1190   if (fn == NULL_TREE)
1191     return;
1192
1193   args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1194   type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1195
1196   len = fold_convert_loc (loc, type, unshare_expr (srclen));
1197   len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1198   len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1199                                   GSI_SAME_STMT);
1200   if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1201     {
1202       fprintf (dump_file, "Optimizing: ");
1203       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1204     }
1205   if (gimple_call_num_args (stmt) == 2)
1206     success = update_gimple_call (gsi, fn, 3, dst, src, len);
1207   else
1208     success = update_gimple_call (gsi, fn, 4, dst, src, len,
1209                                   gimple_call_arg (stmt, 2));
1210   if (success)
1211     {
1212       stmt = gsi_stmt (*gsi);
1213       update_stmt (stmt);
1214       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1215         {
1216           fprintf (dump_file, "into: ");
1217           print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1218         }
1219       /* Allow adjust_last_stmt to decrease this memcpy's size.  */
1220       laststmt.stmt = stmt;
1221       laststmt.len = srclen;
1222       laststmt.stridx = dsi->idx;
1223     }
1224   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1225     fprintf (dump_file, "not possible.\n");
1226 }
1227
1228 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
1229    If strlen of the second argument is known and length of the third argument
1230    is that plus one, strlen of the first argument is the same after this
1231    call.  */
1232
1233 static void
1234 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1235 {
1236   int idx, didx;
1237   tree src, dst, len, lhs, oldlen, newlen;
1238   gimple stmt = gsi_stmt (*gsi);
1239   strinfo si, dsi, olddsi;
1240
1241   len = gimple_call_arg (stmt, 2);
1242   src = gimple_call_arg (stmt, 1);
1243   dst = gimple_call_arg (stmt, 0);
1244   idx = get_stridx (src);
1245   if (idx == 0)
1246     return;
1247
1248   didx = get_stridx (dst);
1249   olddsi = NULL;
1250   if (didx > 0)
1251     olddsi = get_strinfo (didx);
1252   else if (didx < 0)
1253     return;
1254
1255   if (olddsi != NULL
1256       && host_integerp (len, 1)
1257       && !integer_zerop (len))
1258     adjust_last_stmt (olddsi, stmt, false);
1259
1260   if (idx > 0)
1261     {
1262       gimple def_stmt;
1263
1264       /* Handle memcpy (x, y, l) where l is strlen (y) + 1.  */
1265       si = get_strinfo (idx);
1266       if (si == NULL || si->length == NULL_TREE)
1267         return;
1268       if (TREE_CODE (len) != SSA_NAME)
1269         return;
1270       def_stmt = SSA_NAME_DEF_STMT (len);
1271       if (!is_gimple_assign (def_stmt)
1272           || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1273           || gimple_assign_rhs1 (def_stmt) != si->length
1274           || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1275         return;
1276     }
1277   else
1278     {
1279       si = NULL;
1280       /* Handle memcpy (x, "abcd", 5) or
1281          memcpy (x, "abc\0uvw", 7).  */
1282       if (!host_integerp (len, 1)
1283           || (unsigned HOST_WIDE_INT) tree_low_cst (len, 1)
1284              <= (unsigned HOST_WIDE_INT) ~idx)
1285         return;
1286     }
1287
1288   if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
1289     adjust_last_stmt (olddsi, stmt, false);
1290
1291   if (didx == 0)
1292     {
1293       didx = new_stridx (dst);
1294       if (didx == 0)
1295         return;
1296     }
1297   if (si != NULL)
1298     newlen = si->length;
1299   else
1300     newlen = build_int_cst (TREE_TYPE (len), ~idx);
1301   oldlen = NULL_TREE;
1302   if (olddsi != NULL)
1303     {
1304       dsi = unshare_strinfo (olddsi);
1305       oldlen = olddsi->length;
1306       dsi->length = newlen;
1307       /* Break the chain, so adjust_related_strinfo on later pointers in
1308          the chain won't adjust this one anymore.  */
1309       dsi->next = 0;
1310       dsi->stmt = NULL;
1311       dsi->endptr = NULL_TREE;
1312     }
1313   else
1314     {
1315       dsi = new_strinfo (dst, didx, newlen);
1316       set_strinfo (didx, dsi);
1317       find_equal_ptrs (dst, didx);
1318     }
1319   dsi->writable = true;
1320   dsi->dont_invalidate = true;
1321   if (olddsi != NULL)
1322     {
1323       tree adj = NULL_TREE;
1324       location_t loc = gimple_location (stmt);
1325       if (oldlen == NULL_TREE)
1326         ;
1327       else if (integer_zerop (oldlen))
1328         adj = dsi->length;
1329       else if (TREE_CODE (oldlen) == INTEGER_CST
1330                || TREE_CODE (dsi->length) == INTEGER_CST)
1331         adj = fold_build2_loc (loc, MINUS_EXPR,
1332                                TREE_TYPE (dsi->length), dsi->length,
1333                                fold_convert_loc (loc, TREE_TYPE (dsi->length),
1334                                                  oldlen));
1335       if (adj != NULL_TREE)
1336         adjust_related_strinfos (loc, dsi, adj);
1337       else
1338         dsi->prev = 0;
1339     }
1340   /* memcpy src may not overlap dst, so src doesn't need to be
1341      invalidated either.  */
1342   if (si != NULL)
1343     si->dont_invalidate = true;
1344
1345   lhs = gimple_call_lhs (stmt);
1346   switch (bcode)
1347     {
1348     case BUILT_IN_MEMCPY:
1349     case BUILT_IN_MEMCPY_CHK:
1350       /* Allow adjust_last_stmt to decrease this memcpy's size.  */
1351       laststmt.stmt = stmt;
1352       laststmt.len = dsi->length;
1353       laststmt.stridx = dsi->idx;
1354       if (lhs)
1355         VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
1356       break;
1357     case BUILT_IN_MEMPCPY:
1358     case BUILT_IN_MEMPCPY_CHK:
1359       break;
1360     default:
1361       gcc_unreachable ();
1362     }
1363 }
1364
1365 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
1366    If strlen of the second argument is known, strlen of the first argument
1367    is increased by the length of the second argument.  Furthermore, attempt
1368    to convert it to memcpy/strcpy if the length of the first argument
1369    is known.  */
1370
1371 static void
1372 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1373 {
1374   int idx, didx;
1375   tree src, dst, srclen, dstlen, len, lhs, args, type, fn, objsz, endptr;
1376   bool success;
1377   gimple stmt = gsi_stmt (*gsi);
1378   strinfo si, dsi;
1379   location_t loc;
1380
1381   src = gimple_call_arg (stmt, 1);
1382   dst = gimple_call_arg (stmt, 0);
1383   lhs = gimple_call_lhs (stmt);
1384
1385   didx = get_stridx (dst);
1386   if (didx < 0)
1387     return;
1388
1389   dsi = NULL;
1390   if (didx > 0)
1391     dsi = get_strinfo (didx);
1392   if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
1393     {
1394       /* strcat (p, q) can be transformed into
1395          tmp = p + strlen (p); endptr = strpcpy (tmp, q);
1396          with length endptr - p if we need to compute the length
1397          later on.  Don't do this transformation if we don't need
1398          it.  */
1399       if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
1400           && lhs == NULL_TREE)
1401         {
1402           if (didx == 0)
1403             {
1404               didx = new_stridx (dst);
1405               if (didx == 0)
1406                 return;
1407             }
1408           if (dsi == NULL)
1409             {
1410               dsi = new_strinfo (dst, didx, NULL_TREE);
1411               set_strinfo (didx, dsi);
1412               find_equal_ptrs (dst, didx);
1413             }
1414           else
1415             {
1416               dsi = unshare_strinfo (dsi);
1417               dsi->length = NULL_TREE;
1418               dsi->next = 0;
1419               dsi->endptr = NULL_TREE;
1420             }
1421           dsi->writable = true;
1422           dsi->stmt = stmt;
1423           dsi->dont_invalidate = true;
1424         }
1425       return;
1426     }
1427
1428   srclen = NULL_TREE;
1429   si = NULL;
1430   idx = get_stridx (src);
1431   if (idx < 0)
1432     srclen = build_int_cst (size_type_node, ~idx);
1433   else if (idx > 0)
1434     {
1435       si = get_strinfo (idx);
1436       if (si != NULL)
1437         srclen = get_string_length (si);
1438     }
1439
1440   loc = gimple_location (stmt);
1441   dstlen = dsi->length;
1442   endptr = dsi->endptr;
1443
1444   dsi = unshare_strinfo (dsi);
1445   dsi->endptr = NULL_TREE;
1446   dsi->stmt = NULL;
1447   dsi->writable = true;
1448
1449   if (srclen != NULL_TREE)
1450     {
1451       dsi->length = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (dsi->length),
1452                                      dsi->length, srclen);
1453       adjust_related_strinfos (loc, dsi, srclen);
1454       dsi->dont_invalidate = true;
1455     }
1456   else
1457     {
1458       dsi->length = NULL;
1459       if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
1460           && lhs == NULL_TREE)
1461         dsi->dont_invalidate = true;
1462     }
1463
1464   if (si != NULL)
1465     /* strcat src may not overlap dst, so src doesn't need to be
1466        invalidated either.  */
1467     si->dont_invalidate = true;
1468
1469   /* For now.  Could remove the lhs from the call and add
1470      lhs = dst; afterwards.  */
1471   if (lhs)
1472     return;
1473
1474   fn = NULL_TREE;
1475   objsz = NULL_TREE;
1476   switch (bcode)
1477     {
1478     case BUILT_IN_STRCAT:
1479       if (srclen != NULL_TREE)
1480         fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
1481       else
1482         fn = implicit_built_in_decls[BUILT_IN_STRCPY];
1483       break;
1484     case BUILT_IN_STRCAT_CHK:
1485       if (srclen != NULL_TREE)
1486         fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
1487       else
1488         fn = built_in_decls[BUILT_IN_STRCPY_CHK];
1489       objsz = gimple_call_arg (stmt, 2);
1490       break;
1491     default:
1492       gcc_unreachable ();
1493     }
1494
1495   if (fn == NULL_TREE)
1496     return;
1497
1498   len = NULL_TREE;
1499   if (srclen != NULL_TREE)
1500     {
1501       args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1502       type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1503
1504       len = fold_convert_loc (loc, type, unshare_expr (srclen));
1505       len = fold_build2_loc (loc, PLUS_EXPR, type, len,
1506                              build_int_cst (type, 1));
1507       len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1508                                       GSI_SAME_STMT);
1509     }
1510   if (endptr)
1511     dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
1512   else
1513     dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1514                            TREE_TYPE (dst), unshare_expr (dst),
1515                            fold_convert_loc (loc, sizetype,
1516                                              unshare_expr (dstlen)));
1517   dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
1518                                   GSI_SAME_STMT);
1519   if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1520     {
1521       fprintf (dump_file, "Optimizing: ");
1522       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1523     }
1524   if (srclen != NULL_TREE)
1525     success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
1526                                   dst, src, len, objsz);
1527   else
1528     success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
1529                                   dst, src, objsz);
1530   if (success)
1531     {
1532       stmt = gsi_stmt (*gsi);
1533       update_stmt (stmt);
1534       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1535         {
1536           fprintf (dump_file, "into: ");
1537           print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1538         }
1539       /* If srclen == NULL, note that current string length can be
1540          computed by transforming this strcpy into stpcpy.  */
1541       if (srclen == NULL_TREE && dsi->dont_invalidate)
1542         dsi->stmt = stmt;
1543       adjust_last_stmt (dsi, stmt, true);
1544       if (srclen != NULL_TREE)
1545         {
1546           laststmt.stmt = stmt;
1547           laststmt.len = srclen;
1548           laststmt.stridx = dsi->idx;
1549         }
1550     }
1551   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1552     fprintf (dump_file, "not possible.\n");
1553 }
1554
1555 /* Handle a POINTER_PLUS_EXPR statement.
1556    For p = "abcd" + 2; compute associated length, or if
1557    p = q + off is pointing to a '\0' character of a string, call
1558    zero_length_string on it.  */
1559
1560 static void
1561 handle_pointer_plus (gimple_stmt_iterator *gsi)
1562 {
1563   gimple stmt = gsi_stmt (*gsi);
1564   tree lhs = gimple_assign_lhs (stmt), off;
1565   int idx = get_stridx (gimple_assign_rhs1 (stmt));
1566   strinfo si, zsi;
1567
1568   if (idx == 0)
1569     return;
1570
1571   if (idx < 0)
1572     {
1573       tree off = gimple_assign_rhs2 (stmt);
1574       if (host_integerp (off, 1)
1575           && (unsigned HOST_WIDE_INT) tree_low_cst (off, 1)
1576              <= (unsigned HOST_WIDE_INT) ~idx)
1577         VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs),
1578                      ~(~idx - (int) tree_low_cst (off, 1)));
1579       return;
1580     }
1581
1582   si = get_strinfo (idx);
1583   if (si == NULL || si->length == NULL_TREE)
1584     return;
1585
1586   off = gimple_assign_rhs2 (stmt);
1587   zsi = NULL;
1588   if (operand_equal_p (si->length, off, 0))
1589     zsi = zero_length_string (lhs, si);
1590   else if (TREE_CODE (off) == SSA_NAME)
1591     {
1592       gimple def_stmt = SSA_NAME_DEF_STMT (off);
1593       if (gimple_assign_single_p (def_stmt)
1594           && operand_equal_p (si->length, gimple_assign_rhs1 (def_stmt), 0))
1595         zsi = zero_length_string (lhs, si);
1596     }
1597   if (zsi != NULL
1598       && si->endptr != NULL_TREE
1599       && si->endptr != lhs
1600       && TREE_CODE (si->endptr) == SSA_NAME)
1601     {
1602       enum tree_code rhs_code
1603         = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
1604           ? SSA_NAME : NOP_EXPR;
1605       gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr, NULL_TREE);
1606       gcc_assert (gsi_stmt (*gsi) == stmt);
1607       update_stmt (stmt);
1608     }
1609 }
1610
1611 /* Handle a single character store.  */
1612
1613 static bool
1614 handle_char_store (gimple_stmt_iterator *gsi)
1615 {
1616   int idx = -1;
1617   strinfo si = NULL;
1618   gimple stmt = gsi_stmt (*gsi);
1619   tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
1620
1621   if (TREE_CODE (lhs) == MEM_REF
1622       && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
1623     {
1624       if (integer_zerop (TREE_OPERAND (lhs, 1)))
1625         {
1626           ssaname = TREE_OPERAND (lhs, 0);
1627           idx = get_stridx (ssaname);
1628         }
1629     }
1630   else
1631     idx = get_addr_stridx (lhs);
1632
1633   if (idx > 0)
1634     {
1635       si = get_strinfo (idx);
1636       if (si != NULL && si->length != NULL_TREE && integer_zerop (si->length))
1637         {
1638           if (initializer_zerop (gimple_assign_rhs1 (stmt)))
1639             {
1640               /* When storing '\0', the store can be removed
1641                  if we know it has been stored in the current function.  */
1642               if (!stmt_could_throw_p (stmt) && si->writable)
1643                 {
1644                   unlink_stmt_vdef (stmt);
1645                   release_defs (stmt);
1646                   gsi_remove (gsi, true);
1647                   return false;
1648                 }
1649               else
1650                 {
1651                   si->writable = true;
1652                   si->dont_invalidate = true;
1653                 }
1654             }
1655           else
1656             /* Otherwise this statement overwrites the '\0' with
1657                something, if the previous stmt was a memcpy,
1658                its length may be decreased.  */
1659             adjust_last_stmt (si, stmt, false);
1660         }
1661       else if (si != NULL)
1662         {
1663           si = unshare_strinfo (si);
1664           si->length = build_int_cst (size_type_node, 0);
1665           si->endptr = NULL;
1666           si->prev = 0;
1667           si->next = 0;
1668           si->stmt = NULL;
1669           si->first = 0;
1670           si->writable = true;
1671           if (ssaname && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
1672             si->endptr = ssaname;
1673           si->dont_invalidate = true;
1674         }
1675     }
1676   else if (idx == 0 && initializer_zerop (gimple_assign_rhs1 (stmt)))
1677     {
1678       if (ssaname)
1679         {
1680           si = zero_length_string (ssaname, NULL);
1681           if (si != NULL)
1682             si->dont_invalidate = true;
1683         }
1684       else
1685         {
1686           int idx = new_addr_stridx (lhs);
1687           if (idx != 0)
1688             {
1689               si = new_strinfo (build_fold_addr_expr (lhs), idx,
1690                                 build_int_cst (size_type_node, 0));
1691               set_strinfo (idx, si);
1692               si->dont_invalidate = true;
1693             }
1694         }
1695       if (si != NULL)
1696         si->writable = true;
1697     }
1698
1699   if (si != NULL && initializer_zerop (gimple_assign_rhs1 (stmt)))
1700     {
1701       /* Allow adjust_last_stmt to remove it if the stored '\0'
1702          is immediately overwritten.  */
1703       laststmt.stmt = stmt;
1704       laststmt.len = build_int_cst (size_type_node, 1);
1705       laststmt.stridx = si->idx;
1706     }
1707   return true;
1708 }
1709
1710 /* Attempt to optimize a single statement at *GSI using string length
1711    knowledge.  */
1712
1713 static bool
1714 strlen_optimize_stmt (gimple_stmt_iterator *gsi)
1715 {
1716   gimple stmt = gsi_stmt (*gsi);
1717
1718   if (is_gimple_call (stmt))
1719     {
1720       tree callee = gimple_call_fndecl (stmt);
1721       if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
1722         switch (DECL_FUNCTION_CODE (callee))
1723           {
1724           case BUILT_IN_STRLEN:
1725             handle_builtin_strlen (gsi);
1726             break;
1727           case BUILT_IN_STRCHR:
1728             handle_builtin_strchr (gsi);
1729             break;
1730           case BUILT_IN_STRCPY:
1731           case BUILT_IN_STRCPY_CHK:
1732           case BUILT_IN_STPCPY:
1733           case BUILT_IN_STPCPY_CHK:
1734             handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
1735             break;
1736           case BUILT_IN_MEMCPY:
1737           case BUILT_IN_MEMCPY_CHK:
1738           case BUILT_IN_MEMPCPY:
1739           case BUILT_IN_MEMPCPY_CHK:
1740             handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
1741             break;
1742           case BUILT_IN_STRCAT:
1743           case BUILT_IN_STRCAT_CHK:
1744             handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
1745             break;
1746           default:
1747             break;
1748           }
1749     }
1750   else if (is_gimple_assign (stmt))
1751     {
1752       tree lhs = gimple_assign_lhs (stmt);
1753
1754       if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
1755         {
1756           if (gimple_assign_single_p (stmt)
1757               || (gimple_assign_cast_p (stmt)
1758                   && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
1759             {
1760               int idx = get_stridx (gimple_assign_rhs1 (stmt));
1761               VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs),
1762                            idx);
1763             }
1764           else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1765             handle_pointer_plus (gsi);
1766         }
1767       else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
1768         {
1769           tree type = TREE_TYPE (lhs);
1770           if (TREE_CODE (type) == ARRAY_TYPE)
1771             type = TREE_TYPE (type);
1772           if (TREE_CODE (type) == INTEGER_TYPE
1773               && TYPE_MODE (type) == TYPE_MODE (char_type_node)
1774               && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
1775             {
1776               if (! handle_char_store (gsi))
1777                 return false;
1778             }
1779         }
1780     }
1781
1782   if (gimple_vdef (stmt))
1783     maybe_invalidate (stmt);
1784   return true;
1785 }
1786
1787 /* Recursively call maybe_invalidate on stmts that might be executed
1788    in between dombb and current bb and that contain a vdef.  Stop when
1789    *count stmts are inspected, or if the whole strinfo vector has
1790    been invalidated.  */
1791
1792 static void
1793 do_invalidate (basic_block dombb, gimple phi, bitmap visited, int *count)
1794 {
1795   unsigned int i, n = gimple_phi_num_args (phi);
1796
1797   for (i = 0; i < n; i++)
1798     {
1799       tree vuse = gimple_phi_arg_def (phi, i);
1800       gimple stmt = SSA_NAME_DEF_STMT (vuse);
1801       basic_block bb = gimple_bb (stmt);
1802       if (bb == NULL
1803           || bb == dombb
1804           || !bitmap_set_bit (visited, bb->index)
1805           || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
1806         continue;
1807       while (1)
1808         {
1809           if (gimple_code (stmt) == GIMPLE_PHI)
1810             {
1811               do_invalidate (dombb, stmt, visited, count);
1812               if (*count == 0)
1813                 return;
1814               break;
1815             }
1816           if (--*count == 0)
1817             return;
1818           if (!maybe_invalidate (stmt))
1819             {
1820               *count = 0;
1821               return;
1822             }
1823           vuse = gimple_vuse (stmt);
1824           stmt = SSA_NAME_DEF_STMT (vuse);
1825           if (gimple_bb (stmt) != bb)
1826             {
1827               bb = gimple_bb (stmt);
1828               if (bb == NULL
1829                   || bb == dombb
1830                   || !bitmap_set_bit (visited, bb->index)
1831                   || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
1832                 break;
1833             }
1834         }
1835     }
1836 }
1837
1838 /* Callback for walk_dominator_tree.  Attempt to optimize various
1839    string ops by remembering string lenths pointed by pointer SSA_NAMEs.  */
1840
1841 static void
1842 strlen_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
1843                     basic_block bb)
1844 {
1845   gimple_stmt_iterator gsi;
1846   basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
1847
1848   if (dombb == NULL)
1849     stridx_to_strinfo = NULL;
1850   else
1851     {
1852       stridx_to_strinfo = (VEC(strinfo, heap) *) dombb->aux;
1853       if (stridx_to_strinfo)
1854         {
1855           for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1856             {
1857               gimple phi = gsi_stmt (gsi);
1858               if (!is_gimple_reg (gimple_phi_result (phi)))
1859                 {
1860                   bitmap visited = BITMAP_ALLOC (NULL);
1861                   int count_vdef = 100;
1862                   do_invalidate (dombb, phi, visited, &count_vdef);
1863                   BITMAP_FREE (visited);
1864                   break;
1865                 }
1866             }
1867         }
1868     }
1869
1870   /* If all PHI arguments have the same string index, the PHI result
1871      has it as well.  */
1872   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1873     {
1874       gimple phi = gsi_stmt (gsi);
1875       tree result = gimple_phi_result (phi);
1876       if (is_gimple_reg (result) && POINTER_TYPE_P (TREE_TYPE (result)))
1877         {
1878           int idx = get_stridx (gimple_phi_arg_def (phi, 0));
1879           if (idx != 0)
1880             {
1881               unsigned int i, n = gimple_phi_num_args (phi);
1882               for (i = 1; i < n; i++)
1883                 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
1884                   break;
1885               if (i == n)
1886                 VEC_replace (int, ssa_ver_to_stridx,
1887                              SSA_NAME_VERSION (result), idx);
1888             }
1889         }
1890     }
1891
1892   /* Attempt to optimize individual statements.  */
1893   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
1894     if (strlen_optimize_stmt (&gsi))
1895       gsi_next (&gsi);
1896
1897   bb->aux = stridx_to_strinfo;
1898   if (VEC_length (strinfo, stridx_to_strinfo) && !strinfo_shared ())
1899     VEC_replace (strinfo, stridx_to_strinfo, 0, (strinfo) bb);
1900 }
1901
1902 /* Callback for walk_dominator_tree.  Free strinfo vector if it is
1903    owned by the current bb, clear bb->aux.  */
1904
1905 static void
1906 strlen_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
1907                     basic_block bb)
1908 {
1909   if (bb->aux)
1910     {
1911       stridx_to_strinfo = (VEC(strinfo, heap) *) bb->aux;
1912       if (VEC_length (strinfo, stridx_to_strinfo)
1913           && VEC_index (strinfo, stridx_to_strinfo, 0) == (strinfo) bb)
1914         {
1915           unsigned int i;
1916           strinfo si;
1917
1918           for (i = 1; VEC_iterate (strinfo, stridx_to_strinfo, i, si); ++i)
1919             free_strinfo (si);
1920           VEC_free (strinfo, heap, stridx_to_strinfo);
1921         }
1922       bb->aux = NULL;
1923     }
1924 }
1925
1926 /* Main entry point.  */
1927
1928 static unsigned int
1929 tree_ssa_strlen (void)
1930 {
1931   struct dom_walk_data walk_data;
1932
1933   VEC_safe_grow_cleared (int, heap, ssa_ver_to_stridx, num_ssa_names);
1934   max_stridx = 1;
1935   strinfo_pool = create_alloc_pool ("strinfo_struct pool",
1936                                     sizeof (struct strinfo_struct), 64);
1937
1938   calculate_dominance_info (CDI_DOMINATORS);
1939
1940   /* String length optimization is implemented as a walk of the dominator
1941      tree and a forward walk of statements within each block.  */
1942   walk_data.dom_direction = CDI_DOMINATORS;
1943   walk_data.initialize_block_local_data = NULL;
1944   walk_data.before_dom_children = strlen_enter_block;
1945   walk_data.after_dom_children = strlen_leave_block;
1946   walk_data.block_local_data_size = 0;
1947   walk_data.global_data = NULL;
1948
1949   /* Initialize the dominator walker.  */
1950   init_walk_dominator_tree (&walk_data);
1951
1952   /* Recursively walk the dominator tree.  */
1953   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
1954
1955   /* Finalize the dominator walker.  */
1956   fini_walk_dominator_tree (&walk_data);
1957
1958   VEC_free (int, heap, ssa_ver_to_stridx);
1959   free_alloc_pool (strinfo_pool);
1960   if (decl_to_stridxlist_htab)
1961     {
1962       obstack_free (&stridx_obstack, NULL);
1963       htab_delete (decl_to_stridxlist_htab);
1964       decl_to_stridxlist_htab = NULL;
1965     }
1966   laststmt.stmt = NULL;
1967   laststmt.len = NULL_TREE;
1968   laststmt.stridx = 0;
1969
1970   return 0;
1971 }
1972
1973 static bool
1974 gate_strlen (void)
1975 {
1976   return flag_optimize_strlen != 0;
1977 }
1978
1979 struct gimple_opt_pass pass_strlen =
1980 {
1981  {
1982   GIMPLE_PASS,
1983   "strlen",                     /* name */
1984   gate_strlen,                  /* gate */
1985   tree_ssa_strlen,              /* execute */
1986   NULL,                         /* sub */
1987   NULL,                         /* next */
1988   0,                            /* static_pass_number */
1989   TV_TREE_STRLEN,               /* tv_id */
1990   PROP_cfg | PROP_ssa,          /* properties_required */
1991   0,                            /* properties_provided */
1992   0,                            /* properties_destroyed */
1993   0,                            /* todo_flags_start */
1994   TODO_ggc_collect
1995     | TODO_verify_ssa           /* todo_flags_finish */
1996  }
1997 };