1 /* Interprocedural reference lists.
3 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka
6 This file is part of GCC.
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
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
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/>. */
24 #include "coretypes.h"
30 static const char *ipa_ref_use_name
[] = {"read","write","addr","alias"};
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). */
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
)
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 gcc_assert (use_type
!= IPA_REF_ALIAS
|| !stmt
);
51 list
= (refering_node
? &refering_node
->ref_list
52 : &refering_varpool_node
->ref_list
);
53 old_references
= list
->references
;
54 VEC_safe_grow (ipa_ref_t
, gc
, list
->references
,
55 VEC_length (ipa_ref_t
, list
->references
) + 1);
56 ref
= VEC_last (ipa_ref_t
, list
->references
);
58 list2
= (refered_node
? &refered_node
->ref_list
59 : &refered_varpool_node
->ref_list
);
60 VEC_safe_push (ipa_ref_ptr
, heap
, list2
->refering
, ref
);
61 ref
->refered_index
= VEC_length (ipa_ref_ptr
, list2
->refering
) - 1;
64 ref
->refering
.cgraph_node
= refering_node
;
65 ref
->refering_type
= IPA_REF_CGRAPH
;
69 ref
->refering
.varpool_node
= refering_varpool_node
;
70 ref
->refering_type
= IPA_REF_VARPOOL
;
71 gcc_assert (use_type
== IPA_REF_ADDR
|| use_type
== IPA_REF_ALIAS
);
75 ref
->refered
.cgraph_node
= refered_node
;
76 ref
->refered_type
= IPA_REF_CGRAPH
;
77 gcc_assert (use_type
== IPA_REF_ADDR
|| use_type
== IPA_REF_ALIAS
);
81 varpool_mark_needed_node (refered_varpool_node
);
82 ref
->refered
.varpool_node
= refered_varpool_node
;
83 ref
->refered_type
= IPA_REF_VARPOOL
;
88 /* If vector was moved in memory, update pointers. */
89 if (old_references
!= list
->references
)
92 for (i
= 0; ipa_ref_list_reference_iterate (list
, i
, ref
); i
++)
93 VEC_replace (ipa_ref_ptr
,
94 ipa_ref_refered_ref_list (ref
)->refering
,
95 ref
->refered_index
, ref
);
100 /* Remove reference REF. */
103 ipa_remove_reference (struct ipa_ref
*ref
)
105 struct ipa_ref_list
*list
= ipa_ref_refered_ref_list (ref
);
106 struct ipa_ref_list
*list2
= ipa_ref_refering_ref_list (ref
);
107 VEC(ipa_ref_t
,gc
) *old_references
= list2
->references
;
108 struct ipa_ref
*last
;
110 gcc_assert (VEC_index (ipa_ref_ptr
, list
->refering
, ref
->refered_index
) == ref
);
111 last
= VEC_last (ipa_ref_ptr
, list
->refering
);
114 VEC_replace (ipa_ref_ptr
, list
->refering
,
116 VEC_last (ipa_ref_ptr
, list
->refering
));
117 VEC_index (ipa_ref_ptr
, list
->refering
,
118 ref
->refered_index
)->refered_index
= ref
->refered_index
;
120 VEC_pop (ipa_ref_ptr
, list
->refering
);
122 last
= VEC_last (ipa_ref_t
, list2
->references
);
126 VEC_replace (ipa_ref_ptr
,
127 ipa_ref_refered_ref_list (ref
)->refering
,
128 ref
->refered_index
, ref
);
130 VEC_pop (ipa_ref_t
, list2
->references
);
131 gcc_assert (list2
->references
== old_references
);
134 /* Remove all references in ref list LIST. */
137 ipa_remove_all_references (struct ipa_ref_list
*list
)
139 while (VEC_length (ipa_ref_t
, list
->references
))
140 ipa_remove_reference (VEC_last (ipa_ref_t
, list
->references
));
141 VEC_free (ipa_ref_t
, gc
, list
->references
);
142 list
->references
= NULL
;
145 /* Remove all references in ref list LIST. */
148 ipa_remove_all_refering (struct ipa_ref_list
*list
)
150 while (VEC_length (ipa_ref_ptr
, list
->refering
))
151 ipa_remove_reference (VEC_last (ipa_ref_ptr
, list
->refering
));
152 VEC_free (ipa_ref_ptr
, heap
, list
->refering
);
153 list
->refering
= NULL
;
156 /* Dump references in LIST to FILE. */
159 ipa_dump_references (FILE * file
, struct ipa_ref_list
*list
)
163 for (i
= 0; ipa_ref_list_reference_iterate (list
, i
, ref
); i
++)
165 if (ref
->refered_type
== IPA_REF_CGRAPH
)
167 fprintf (file
, " fn:%s/%i (%s)", cgraph_node_name (ipa_ref_node (ref
)),
168 ipa_ref_node (ref
)->uid
,
169 ipa_ref_use_name
[ref
->use
]);
172 fprintf (file
, " var:%s (%s)",
173 varpool_node_name (ipa_ref_varpool_node (ref
)),
174 ipa_ref_use_name
[ref
->use
]);
176 fprintf (file
, "\n");
179 /* Dump refering in LIST to FILE. */
182 ipa_dump_refering (FILE * file
, struct ipa_ref_list
*list
)
186 for (i
= 0; ipa_ref_list_refering_iterate (list
, i
, ref
); i
++)
188 if (ref
->refering_type
== IPA_REF_CGRAPH
)
189 fprintf (file
, " fn:%s/%i (%s)",
190 cgraph_node_name (ipa_ref_refering_node (ref
)),
191 ipa_ref_refering_node (ref
)->uid
,
192 ipa_ref_use_name
[ref
->use
]);
194 fprintf (file
, " var:%s (%s)",
195 varpool_node_name (ipa_ref_refering_varpool_node (ref
)),
196 ipa_ref_use_name
[ref
->use
]);
198 fprintf (file
, "\n");
201 /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
204 ipa_clone_references (struct cgraph_node
*dest_node
,
205 struct varpool_node
*dest_varpool_node
,
206 struct ipa_ref_list
*src
)
210 for (i
= 0; ipa_ref_list_reference_iterate (src
, i
, ref
); i
++)
211 ipa_record_reference (dest_node
, dest_varpool_node
,
212 ref
->refered_type
== IPA_REF_CGRAPH
213 ? ipa_ref_node (ref
) : NULL
,
214 ref
->refered_type
== IPA_REF_VARPOOL
215 ? ipa_ref_varpool_node (ref
) : NULL
,
216 ref
->use
, ref
->stmt
);
219 /* Clone all refering from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
222 ipa_clone_refering (struct cgraph_node
*dest_node
,
223 struct varpool_node
*dest_varpool_node
,
224 struct ipa_ref_list
*src
)
228 for (i
= 0; ipa_ref_list_refering_iterate (src
, i
, ref
); i
++)
229 ipa_record_reference (
230 ref
->refering_type
== IPA_REF_CGRAPH
231 ? ipa_ref_refering_node (ref
) : NULL
,
232 ref
->refering_type
== IPA_REF_VARPOOL
233 ? ipa_ref_refering_varpool_node (ref
) : NULL
,
234 dest_node
, dest_varpool_node
,
235 ref
->use
, ref
->stmt
);
238 /* Return true when execution of REF can load to return from
241 ipa_ref_cannot_lead_to_return (struct ipa_ref
*ref
)
243 return cgraph_node_cannot_return (ipa_ref_refering_node (ref
));
246 /* Return true if list contains an alias. */
248 ipa_ref_has_aliases_p (struct ipa_ref_list
*ref_list
)
252 for (i
= 0; ipa_ref_list_refering_iterate (ref_list
, i
, ref
); i
++)
253 if (ref
->use
== IPA_REF_ALIAS
)