backport: As described in http://gcc.gnu.org/ml/gcc/2012-08/msg00015.html...
[gcc.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 }