]>
Commit | Line | Data |
---|---|---|
8d810329 | 1 | /* Interprocedural reference lists. |
711789cc | 2 | Copyright (C) 2010-2013 Free Software Foundation, Inc. |
8d810329 | 3 | Contributed by Jan Hubicka |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | 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.h" | |
25 | #include "ggc.h" | |
26 | #include "target.h" | |
27 | #include "cgraph.h" | |
3c0fe71b | 28 | #include "ipa-utils.h" |
8d810329 | 29 | |
c70f46b0 | 30 | static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; |
8d810329 | 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 * | |
04ec15fa | 37 | ipa_record_reference (symtab_node referring_node, |
38 | symtab_node referred_node, | |
8d810329 | 39 | enum ipa_ref_use use_type, gimple stmt) |
40 | { | |
41 | struct ipa_ref *ref; | |
42 | struct ipa_ref_list *list, *list2; | |
f1f41a6c | 43 | ipa_ref_t *old_references; |
8d810329 | 44 | |
2dc9831f | 45 | gcc_checking_assert (!stmt || is_a <cgraph_node> (referring_node)); |
04ec15fa | 46 | gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); |
47 | ||
48 | list = &referring_node->symbol.ref_list; | |
f1f41a6c | 49 | old_references = vec_safe_address (list->references); |
50 | vec_safe_grow (list->references, vec_safe_length (list->references) + 1); | |
51 | ref = &list->references->last (); | |
8d810329 | 52 | |
04ec15fa | 53 | list2 = &referred_node->symbol.ref_list; |
f1f41a6c | 54 | list2->referring.safe_push (ref); |
55 | ref->referred_index = list2->referring.length () - 1; | |
04ec15fa | 56 | ref->referring = referring_node; |
57 | ref->referred = referred_node; | |
8d810329 | 58 | ref->stmt = stmt; |
59 | ref->use = use_type; | |
60 | ||
61 | /* If vector was moved in memory, update pointers. */ | |
f1f41a6c | 62 | if (old_references != list->references->address ()) |
8d810329 | 63 | { |
64 | int i; | |
65 | for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) | |
f1f41a6c | 66 | ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref; |
8d810329 | 67 | } |
68 | return ref; | |
69 | } | |
70 | ||
3c0fe71b | 71 | /* If VAL is a reference to a function or a variable, add a reference from |
72 | REFERRING_NODE to the corresponding symbol table node. USE_TYPE specify | |
73 | type of the use and STMT the statement (if it exists). Return the new | |
74 | reference or NULL if none was created. */ | |
75 | ||
76 | struct ipa_ref * | |
77 | ipa_maybe_record_reference (symtab_node referring_node, tree val, | |
78 | enum ipa_ref_use use_type, gimple stmt) | |
79 | { | |
80 | STRIP_NOPS (val); | |
81 | if (TREE_CODE (val) != ADDR_EXPR) | |
82 | return NULL; | |
83 | val = get_base_var (val); | |
84 | if (val && (TREE_CODE (val) == FUNCTION_DECL | |
85 | || TREE_CODE (val) == VAR_DECL)) | |
86 | { | |
87 | symtab_node referred = symtab_get_node (val); | |
88 | gcc_checking_assert (referred); | |
89 | return ipa_record_reference (referring_node, referred, | |
90 | use_type, stmt); | |
91 | } | |
92 | return NULL; | |
93 | } | |
94 | ||
8d810329 | 95 | /* Remove reference REF. */ |
96 | ||
97 | void | |
98 | ipa_remove_reference (struct ipa_ref *ref) | |
99 | { | |
04ec15fa | 100 | struct ipa_ref_list *list = ipa_ref_referred_ref_list (ref); |
101 | struct ipa_ref_list *list2 = ipa_ref_referring_ref_list (ref); | |
f1f41a6c | 102 | vec<ipa_ref_t, va_gc> *old_references = list2->references; |
8d810329 | 103 | struct ipa_ref *last; |
104 | ||
f1f41a6c | 105 | gcc_assert (list->referring[ref->referred_index] == ref); |
106 | last = list->referring.last (); | |
8d810329 | 107 | if (ref != last) |
108 | { | |
f1f41a6c | 109 | list->referring[ref->referred_index] = list->referring.last (); |
110 | list->referring[ref->referred_index]->referred_index | |
111 | = ref->referred_index; | |
8d810329 | 112 | } |
f1f41a6c | 113 | list->referring.pop (); |
8d810329 | 114 | |
f1f41a6c | 115 | last = &list2->references->last (); |
8d810329 | 116 | if (ref != last) |
117 | { | |
118 | *ref = *last; | |
f1f41a6c | 119 | ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref; |
8d810329 | 120 | } |
f1f41a6c | 121 | list2->references->pop (); |
8d810329 | 122 | gcc_assert (list2->references == old_references); |
123 | } | |
124 | ||
125 | /* Remove all references in ref list LIST. */ | |
126 | ||
127 | void | |
128 | ipa_remove_all_references (struct ipa_ref_list *list) | |
129 | { | |
f1f41a6c | 130 | while (vec_safe_length (list->references)) |
131 | ipa_remove_reference (&list->references->last ()); | |
132 | vec_free (list->references); | |
8d810329 | 133 | } |
134 | ||
135 | /* Remove all references in ref list LIST. */ | |
136 | ||
137 | void | |
04ec15fa | 138 | ipa_remove_all_referring (struct ipa_ref_list *list) |
8d810329 | 139 | { |
f1f41a6c | 140 | while (list->referring.length ()) |
141 | ipa_remove_reference (list->referring.last ()); | |
142 | list->referring.release (); | |
8d810329 | 143 | } |
144 | ||
145 | /* Dump references in LIST to FILE. */ | |
146 | ||
147 | void | |
148 | ipa_dump_references (FILE * file, struct ipa_ref_list *list) | |
149 | { | |
150 | struct ipa_ref *ref; | |
151 | int i; | |
152 | for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) | |
153 | { | |
04ec15fa | 154 | fprintf (file, "%s/%i (%s)", |
155 | symtab_node_asm_name (ref->referred), | |
156 | ref->referred->symbol.order, | |
157 | ipa_ref_use_name [ref->use]); | |
8d810329 | 158 | } |
159 | fprintf (file, "\n"); | |
160 | } | |
161 | ||
04ec15fa | 162 | /* Dump referring in LIST to FILE. */ |
8d810329 | 163 | |
164 | void | |
04ec15fa | 165 | ipa_dump_referring (FILE * file, struct ipa_ref_list *list) |
8d810329 | 166 | { |
167 | struct ipa_ref *ref; | |
168 | int i; | |
04ec15fa | 169 | for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) |
8d810329 | 170 | { |
04ec15fa | 171 | fprintf (file, "%s/%i (%s)", |
172 | symtab_node_asm_name (ref->referring), | |
173 | ref->referring->symbol.order, | |
174 | ipa_ref_use_name [ref->use]); | |
8d810329 | 175 | } |
176 | fprintf (file, "\n"); | |
177 | } | |
178 | ||
0a10fd82 | 179 | /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ |
8d810329 | 180 | |
181 | void | |
04ec15fa | 182 | ipa_clone_references (symtab_node dest_node, |
8d810329 | 183 | struct ipa_ref_list *src) |
184 | { | |
185 | struct ipa_ref *ref; | |
186 | int i; | |
187 | for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++) | |
04ec15fa | 188 | ipa_record_reference (dest_node, |
189 | ref->referred, | |
8d810329 | 190 | ref->use, ref->stmt); |
191 | } | |
192 | ||
04ec15fa | 193 | /* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ |
8d810329 | 194 | |
195 | void | |
04ec15fa | 196 | ipa_clone_referring (symtab_node dest_node, |
8d810329 | 197 | struct ipa_ref_list *src) |
198 | { | |
199 | struct ipa_ref *ref; | |
200 | int i; | |
04ec15fa | 201 | for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++) |
202 | ipa_record_reference (ref->referring, | |
203 | dest_node, | |
8d810329 | 204 | ref->use, ref->stmt); |
205 | } | |
023a28e1 | 206 | |
04ec15fa | 207 | /* Return true when execution of REF can lead to return from |
023a28e1 | 208 | function. */ |
209 | bool | |
210 | ipa_ref_cannot_lead_to_return (struct ipa_ref *ref) | |
211 | { | |
04ec15fa | 212 | return cgraph_node_cannot_return (ipa_ref_referring_node (ref)); |
023a28e1 | 213 | } |
c70f46b0 | 214 | |
215 | /* Return true if list contains an alias. */ | |
216 | bool | |
217 | ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list) | |
218 | { | |
219 | struct ipa_ref *ref; | |
220 | int i; | |
04ec15fa | 221 | for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++) |
c70f46b0 | 222 | if (ref->use == IPA_REF_ALIAS) |
223 | return true; | |
224 | return false; | |
225 | } | |
096295f6 | 226 | |
227 | /* Find the structure describing a reference in REFERRING_NODE to REFERRED_NODE | |
228 | and associated with statement STMT. */ | |
229 | ||
230 | struct ipa_ref * | |
231 | ipa_find_reference (symtab_node referring_node, symtab_node referred_node, | |
232 | gimple stmt) | |
233 | { | |
234 | struct ipa_ref *r = NULL; | |
235 | int i; | |
236 | ||
237 | FOR_EACH_VEC_SAFE_ELT (referring_node->symbol.ref_list.references, i, r) | |
238 | if (r->referred == referred_node | |
239 | && (in_lto_p || r->stmt == stmt)) | |
240 | return r; | |
241 | return NULL; | |
242 | } | |
7d9f258f | 243 | |
244 | /* Remove all references from REFERRING_NODE that are associated with statement | |
245 | STMT. */ | |
246 | ||
247 | void | |
248 | ipa_remove_stmt_references (symtab_node referring_node, gimple stmt) | |
249 | { | |
250 | struct ipa_ref *r = NULL; | |
251 | int i; | |
252 | ||
253 | FOR_EACH_VEC_SAFE_ELT (referring_node->symbol.ref_list.references, i, r) | |
254 | if (r->stmt == stmt) | |
255 | ipa_remove_reference (r); | |
256 | } |