OSDN Git Service

2012-10-08 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / ipa-ref.c
1 /* Interprocedural reference lists.
2    Copyright (C) 2010, 2011, 2012
3    Free Software Foundation, Inc.
4    Contributed by Jan Hubicka
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "ggc.h"
27 #include "target.h"
28 #include "cgraph.h"
29
30 static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
31
32 /* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE
33    to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
34    of the use and STMT the statement (if it exists).  */
35
36 struct ipa_ref *
37 ipa_record_reference (symtab_node referring_node,
38                       symtab_node referred_node,
39                       enum ipa_ref_use use_type, gimple stmt)
40 {
41   struct ipa_ref *ref;
42   struct ipa_ref_list *list, *list2;
43   VEC(ipa_ref_t,gc) *old_references;
44
45   gcc_checking_assert (!stmt || symtab_function_p (referring_node));
46   gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
47
48   list = &referring_node->symbol.ref_list;
49   old_references = list->references;
50   VEC_safe_grow (ipa_ref_t, gc, list->references,
51                  VEC_length (ipa_ref_t, list->references) + 1);
52   ref = &VEC_last (ipa_ref_t, list->references);
53
54   list2 = &referred_node->symbol.ref_list;
55   VEC_safe_push (ipa_ref_ptr, heap, list2->referring, ref);
56   ref->referred_index = VEC_length (ipa_ref_ptr, list2->referring) - 1;
57   ref->referring = referring_node;
58   ref->referred = referred_node;
59   ref->stmt = stmt;
60   ref->use = use_type;
61
62   /* If vector was moved in memory, update pointers.  */
63   if (old_references != list->references)
64     {
65       int i;
66       for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
67         VEC_replace (ipa_ref_ptr,
68                      ipa_ref_referred_ref_list (ref)->referring,
69                      ref->referred_index, ref);
70     }
71   return ref;
72 }
73
74 /* Remove reference REF.  */
75
76 void
77 ipa_remove_reference (struct ipa_ref *ref)
78 {
79   struct ipa_ref_list *list = ipa_ref_referred_ref_list (ref);
80   struct ipa_ref_list *list2 = ipa_ref_referring_ref_list (ref);
81   VEC(ipa_ref_t,gc) *old_references = list2->references;
82   struct ipa_ref *last;
83
84   gcc_assert (VEC_index (ipa_ref_ptr, list->referring, ref->referred_index) == ref);
85   last = VEC_last (ipa_ref_ptr, list->referring);
86   if (ref != last)
87     {
88       VEC_replace (ipa_ref_ptr, list->referring,
89                    ref->referred_index,
90                    VEC_last (ipa_ref_ptr, list->referring));
91       VEC_index (ipa_ref_ptr, list->referring,
92                  ref->referred_index)->referred_index = ref->referred_index;
93     }
94   VEC_pop (ipa_ref_ptr, list->referring);
95
96   last = &VEC_last (ipa_ref_t, list2->references);
97   if (ref != last)
98     {
99       *ref = *last;
100       VEC_replace (ipa_ref_ptr,
101                    ipa_ref_referred_ref_list (ref)->referring,
102                    ref->referred_index, ref);
103     }
104   VEC_pop (ipa_ref_t, list2->references);
105   gcc_assert (list2->references == old_references);
106 }
107
108 /* Remove all references in ref list LIST.  */
109
110 void
111 ipa_remove_all_references (struct ipa_ref_list *list)
112 {
113   while (VEC_length (ipa_ref_t, list->references))
114     ipa_remove_reference (&VEC_last (ipa_ref_t, list->references));
115   VEC_free (ipa_ref_t, gc, list->references);
116   list->references = NULL;
117 }
118
119 /* Remove all references in ref list LIST.  */
120
121 void
122 ipa_remove_all_referring (struct ipa_ref_list *list)
123 {
124   while (VEC_length (ipa_ref_ptr, list->referring))
125     ipa_remove_reference (VEC_last (ipa_ref_ptr, list->referring));
126   VEC_free (ipa_ref_ptr, heap, list->referring);
127   list->referring = NULL;
128 }
129
130 /* Dump references in LIST to FILE.  */
131
132 void
133 ipa_dump_references (FILE * file, struct ipa_ref_list *list)
134 {
135   struct ipa_ref *ref;
136   int i;
137   for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
138     {
139       fprintf (file, "%s/%i (%s)",
140                symtab_node_asm_name (ref->referred),
141                ref->referred->symbol.order,
142                ipa_ref_use_name [ref->use]);
143     }
144   fprintf (file, "\n");
145 }
146
147 /* Dump referring in LIST to FILE.  */
148
149 void
150 ipa_dump_referring (FILE * file, struct ipa_ref_list *list)
151 {
152   struct ipa_ref *ref;
153   int i;
154   for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
155     {
156       fprintf (file, "%s/%i (%s)",
157                symtab_node_asm_name (ref->referring),
158                ref->referring->symbol.order,
159                ipa_ref_use_name [ref->use]);
160     }
161   fprintf (file, "\n");
162 }
163
164 /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE.  */
165
166 void
167 ipa_clone_references (symtab_node dest_node,
168                       struct ipa_ref_list *src)
169 {
170   struct ipa_ref *ref;
171   int i;
172   for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++)
173     ipa_record_reference (dest_node,
174                           ref->referred,
175                           ref->use, ref->stmt);
176 }
177
178 /* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE.  */
179
180 void
181 ipa_clone_referring (symtab_node dest_node,
182                     struct ipa_ref_list *src)
183 {
184   struct ipa_ref *ref;
185   int i;
186   for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++)
187     ipa_record_reference (ref->referring,
188                           dest_node,
189                           ref->use, ref->stmt);
190 }
191
192 /* Return true when execution of REF can lead to return from
193    function. */
194 bool
195 ipa_ref_cannot_lead_to_return (struct ipa_ref *ref)
196 {
197   return cgraph_node_cannot_return (ipa_ref_referring_node (ref));
198 }
199
200 /* Return true if list contains an alias.  */
201 bool
202 ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
203 {
204   struct ipa_ref *ref;
205   int i;
206   for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++)
207     if (ref->use == IPA_REF_ALIAS)
208       return true;
209   return false;
210 }