PR target/47111
[official-gcc.git] / gcc / ipa-ref.c
blob27c32dcd3d6f8bb36b5695cc65b066e49c4335e0
1 /* Interprocedural reference lists.
2 Copyright (C) 2010
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
11 version.
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.
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/>. */
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"
30 static const char *ipa_ref_use_name[] = {"read","write","addr"};
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). */
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)
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);
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);
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)
63 ref->refering.cgraph_node = refering_node;
64 ref->refering_type = IPA_REF_CGRAPH;
66 else
68 ref->refering.varpool_node = refering_varpool_node;
69 ref->refering_type = IPA_REF_VARPOOL;
70 gcc_assert (use_type == IPA_REF_ADDR);
72 if (refered_node)
74 ref->refered.cgraph_node = refered_node;
75 ref->refered_type = IPA_REF_CGRAPH;
76 gcc_assert (use_type == IPA_REF_ADDR);
78 else
80 varpool_mark_needed_node (refered_varpool_node);
81 ref->refered.varpool_node = refered_varpool_node;
82 ref->refered_type = IPA_REF_VARPOOL;
84 ref->stmt = stmt;
85 ref->use = use_type;
87 /* If vector was moved in memory, update pointers. */
88 if (old_references != list->references)
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);
96 return ref;
99 /* Remove reference REF. */
101 void
102 ipa_remove_reference (struct ipa_ref *ref)
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;
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)
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;
119 VEC_pop (ipa_ref_ptr, list->refering);
121 last = VEC_last (ipa_ref_t, list2->references);
122 if (ref != last)
124 *ref = *last;
125 VEC_replace (ipa_ref_ptr,
126 ipa_ref_refered_ref_list (ref)->refering,
127 ref->refered_index, ref);
129 VEC_pop (ipa_ref_t, list2->references);
130 gcc_assert (list2->references == old_references);
133 /* Remove all references in ref list LIST. */
135 void
136 ipa_remove_all_references (struct ipa_ref_list *list)
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;
144 /* Remove all references in ref list LIST. */
146 void
147 ipa_remove_all_refering (struct ipa_ref_list *list)
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;
155 /* Dump references in LIST to FILE. */
157 void
158 ipa_dump_references (FILE * file, struct ipa_ref_list *list)
160 struct ipa_ref *ref;
161 int i;
162 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
164 if (ref->refered_type == IPA_REF_CGRAPH)
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]);
170 else
171 fprintf (file, " var:%s (%s)",
172 varpool_node_name (ipa_ref_varpool_node (ref)),
173 ipa_ref_use_name [ref->use]);
175 fprintf (file, "\n");
178 /* Dump refering in LIST to FILE. */
180 void
181 ipa_dump_refering (FILE * file, struct ipa_ref_list *list)
183 struct ipa_ref *ref;
184 int i;
185 for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
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]);
197 fprintf (file, "\n");
200 /* Clone all references from SRC to DEST_NODE or DEST_VARPOL_NODE. */
202 void
203 ipa_clone_references (struct cgraph_node *dest_node,
204 struct varpool_node *dest_varpool_node,
205 struct ipa_ref_list *src)
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);
218 /* Clone all refering from SRC to DEST_NODE or DEST_VARPOL_NODE. */
220 void
221 ipa_clone_refering (struct cgraph_node *dest_node,
222 struct varpool_node *dest_varpool_node,
223 struct ipa_ref_list *src)
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);
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)
242 return cgraph_node_cannot_return (ipa_ref_refering_node (ref));