]>
Commit | Line | Data |
---|---|---|
8d810329 | 1 | /* Interprocedural reference lists. |
2 | Copyright (C) 2010 | |
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"}; | |
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 (struct cgraph_node *refering_node, | |
38 | struct varpool_node *refering_varpool_node, | |
39 | struct cgraph_node *refered_node, | |
40 | struct varpool_node *refered_varpool_node, | |
41 | enum ipa_ref_use use_type, gimple stmt) | |
42 | { | |
43 | struct ipa_ref *ref; | |
44 | struct ipa_ref_list *list, *list2; | |
45 | VEC(ipa_ref_t,gc) *old_references; | |
46 | gcc_assert ((!refering_node) ^ (!refering_varpool_node)); | |
47 | gcc_assert ((!refered_node) ^ (!refered_varpool_node)); | |
48 | gcc_assert (!stmt || refering_node); | |
49 | ||
50 | list = (refering_node ? &refering_node->ref_list | |
51 | : &refering_varpool_node->ref_list); | |
52 | old_references = list->references; | |
53 | VEC_safe_grow (ipa_ref_t, gc, list->references, | |
54 | VEC_length (ipa_ref_t, list->references) + 1); | |
55 | ref = VEC_last (ipa_ref_t, list->references); | |
56 | ||
57 | list2 = (refered_node ? &refered_node->ref_list | |
58 | : &refered_varpool_node->ref_list); | |
59 | VEC_safe_push (ipa_ref_ptr, heap, list2->refering, ref); | |
60 | ref->refered_index = VEC_length (ipa_ref_ptr, list2->refering) - 1; | |
61 | if (refering_node) | |
62 | { | |
63 | ref->refering.cgraph_node = refering_node; | |
64 | ref->refering_type = IPA_REF_CGRAPH; | |
65 | } | |
66 | else | |
67 | { | |
68 | ref->refering.varpool_node = refering_varpool_node; | |
69 | ref->refering_type = IPA_REF_VARPOOL; | |
70 | gcc_assert (use_type == IPA_REF_ADDR); | |
71 | } | |
72 | if (refered_node) | |
73 | { | |
74 | ref->refered.cgraph_node = refered_node; | |
75 | ref->refered_type = IPA_REF_CGRAPH; | |
76 | gcc_assert (use_type == IPA_REF_ADDR); | |
77 | } | |
78 | else | |
79 | { | |
80 | varpool_mark_needed_node (refered_varpool_node); | |
81 | ref->refered.varpool_node = refered_varpool_node; | |
82 | ref->refered_type = IPA_REF_VARPOOL; | |
83 | } | |
84 | ref->stmt = stmt; | |
85 | ref->use = use_type; | |
86 | ||
87 | /* If vector was moved in memory, update pointers. */ | |
88 | if (old_references != list->references) | |
89 | { | |
90 | int i; | |
91 | for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) | |
92 | VEC_replace (ipa_ref_ptr, | |
93 | ipa_ref_refered_ref_list (ref)->refering, | |
94 | ref->refered_index, ref); | |
95 | } | |
96 | return ref; | |
97 | } | |
98 | ||
99 | /* Remove reference REF. */ | |
100 | ||
101 | void | |
102 | ipa_remove_reference (struct ipa_ref *ref) | |
103 | { | |
104 | struct ipa_ref_list *list = ipa_ref_refered_ref_list (ref); | |
105 | struct ipa_ref_list *list2 = ipa_ref_refering_ref_list (ref); | |
106 | VEC(ipa_ref_t,gc) *old_references = list2->references; | |
107 | struct ipa_ref *last; | |
108 | ||
109 | gcc_assert (VEC_index (ipa_ref_ptr, list->refering, ref->refered_index) == ref); | |
110 | last = VEC_last (ipa_ref_ptr, list->refering); | |
111 | if (ref != last) | |
112 | { | |
113 | VEC_replace (ipa_ref_ptr, list->refering, | |
114 | ref->refered_index, | |
115 | VEC_last (ipa_ref_ptr, list->refering)); | |
116 | VEC_index (ipa_ref_ptr, list->refering, | |
117 | ref->refered_index)->refered_index = ref->refered_index; | |
118 | } | |
119 | VEC_pop (ipa_ref_ptr, list->refering); | |
120 | ||
121 | last = VEC_last (ipa_ref_t, list2->references); | |
122 | if (ref != last) | |
123 | { | |
124 | *ref = *last; | |
125 | VEC_replace (ipa_ref_ptr, | |
126 | ipa_ref_refered_ref_list (ref)->refering, | |
127 | ref->refered_index, ref); | |
128 | } | |
129 | VEC_pop (ipa_ref_t, list2->references); | |
130 | gcc_assert (list2->references == old_references); | |
131 | } | |
132 | ||
133 | /* Remove all references in ref list LIST. */ | |
134 | ||
135 | void | |
136 | ipa_remove_all_references (struct ipa_ref_list *list) | |
137 | { | |
138 | while (VEC_length (ipa_ref_t, list->references)) | |
139 | ipa_remove_reference (VEC_last (ipa_ref_t, list->references)); | |
140 | VEC_free (ipa_ref_t, gc, list->references); | |
141 | list->references = NULL; | |
142 | } | |
143 | ||
144 | /* Remove all references in ref list LIST. */ | |
145 | ||
146 | void | |
147 | ipa_remove_all_refering (struct ipa_ref_list *list) | |
148 | { | |
149 | while (VEC_length (ipa_ref_ptr, list->refering)) | |
150 | ipa_remove_reference (VEC_last (ipa_ref_ptr, list->refering)); | |
151 | VEC_free (ipa_ref_ptr, heap, list->refering); | |
152 | list->refering = NULL; | |
153 | } | |
154 | ||
155 | /* Dump references in LIST to FILE. */ | |
156 | ||
157 | void | |
158 | ipa_dump_references (FILE * file, struct ipa_ref_list *list) | |
159 | { | |
160 | struct ipa_ref *ref; | |
161 | int i; | |
162 | for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) | |
163 | { | |
164 | if (ref->refered_type == IPA_REF_CGRAPH) | |
165 | { | |
166 | fprintf (file, " fn:%s/%i (%s)", cgraph_node_name (ipa_ref_node (ref)), | |
167 | ipa_ref_node (ref)->uid, | |
168 | ipa_ref_use_name [ref->use]); | |
169 | } | |
170 | else | |
171 | fprintf (file, " var:%s (%s)", | |
172 | varpool_node_name (ipa_ref_varpool_node (ref)), | |
173 | ipa_ref_use_name [ref->use]); | |
174 | } | |
175 | fprintf (file, "\n"); | |
176 | } | |
177 | ||
178 | /* Dump refering in LIST to FILE. */ | |
179 | ||
180 | void | |
181 | ipa_dump_refering (FILE * file, struct ipa_ref_list *list) | |
182 | { | |
183 | struct ipa_ref *ref; | |
184 | int i; | |
185 | for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++) | |
186 | { | |
187 | if (ref->refering_type == IPA_REF_CGRAPH) | |
188 | fprintf (file, " fn:%s/%i (%s)", | |
189 | cgraph_node_name (ipa_ref_refering_node (ref)), | |
190 | ipa_ref_refering_node (ref)->uid, | |
191 | ipa_ref_use_name [ref->use]); | |
192 | else | |
193 | fprintf (file, " var:%s (%s)", | |
194 | varpool_node_name (ipa_ref_refering_varpool_node (ref)), | |
195 | ipa_ref_use_name [ref->use]); | |
196 | } | |
197 | fprintf (file, "\n"); | |
198 | } | |
199 | ||
0a10fd82 | 200 | /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ |
8d810329 | 201 | |
202 | void | |
203 | ipa_clone_references (struct cgraph_node *dest_node, | |
204 | struct varpool_node *dest_varpool_node, | |
205 | struct ipa_ref_list *src) | |
206 | { | |
207 | struct ipa_ref *ref; | |
208 | int i; | |
209 | for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++) | |
210 | ipa_record_reference (dest_node, dest_varpool_node, | |
211 | ref->refered_type == IPA_REF_CGRAPH | |
212 | ? ipa_ref_node (ref) : NULL, | |
213 | ref->refered_type == IPA_REF_VARPOOL | |
214 | ? ipa_ref_varpool_node (ref) : NULL, | |
215 | ref->use, ref->stmt); | |
216 | } | |
217 | ||
0a10fd82 | 218 | /* Clone all refering from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ |
8d810329 | 219 | |
220 | void | |
221 | ipa_clone_refering (struct cgraph_node *dest_node, | |
222 | struct varpool_node *dest_varpool_node, | |
223 | struct ipa_ref_list *src) | |
224 | { | |
225 | struct ipa_ref *ref; | |
226 | int i; | |
227 | for (i = 0; ipa_ref_list_refering_iterate (src, i, ref); i++) | |
228 | ipa_record_reference ( | |
229 | ref->refering_type == IPA_REF_CGRAPH | |
230 | ? ipa_ref_refering_node (ref) : NULL, | |
231 | ref->refering_type == IPA_REF_VARPOOL | |
232 | ? ipa_ref_refering_varpool_node (ref) : NULL, | |
233 | dest_node, dest_varpool_node, | |
234 | ref->use, ref->stmt); | |
235 | } | |
023a28e1 | 236 | |
237 | /* Return true when execution of REF can load to return from | |
238 | function. */ | |
239 | bool | |
240 | ipa_ref_cannot_lead_to_return (struct ipa_ref *ref) | |
241 | { | |
242 | return cgraph_node_cannot_return (ipa_ref_refering_node (ref)); | |
243 | } |