1 /* Interprocedural reference lists.
2 Copyright (C) 2010-2013 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
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
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
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/>. */
23 #include "coretypes.h"
28 #include "ipa-utils.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 (symtab_node referring_node
,
38 symtab_node referred_node
,
39 enum ipa_ref_use use_type
, gimple stmt
)
41 struct ipa_ref
*ref
, *ref2
;
42 struct ipa_ref_list
*list
, *list2
;
43 ipa_ref_t
*old_references
;
45 gcc_checking_assert (!stmt
|| is_a
<cgraph_node
> (referring_node
));
46 gcc_checking_assert (use_type
!= IPA_REF_ALIAS
|| !stmt
);
48 list
= &referring_node
->symbol
.ref_list
;
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 ();
53 list2
= &referred_node
->symbol
.ref_list
;
54 list2
->referring
.safe_push (ref
);
55 ref
->referred_index
= list2
->referring
.length () - 1;
56 ref
->referring
= referring_node
;
57 ref
->referred
= referred_node
;
59 ref
->lto_stmt_uid
= 0;
63 /* If vector was moved in memory, update pointers. */
64 if (old_references
!= list
->references
->address ())
67 for (i
= 0; ipa_ref_list_reference_iterate (list
, i
, ref2
); i
++)
68 ipa_ref_referred_ref_list (ref2
)->referring
[ref2
->referred_index
] = ref2
;
73 /* If VAL is a reference to a function or a variable, add a reference from
74 REFERRING_NODE to the corresponding symbol table node. USE_TYPE specify
75 type of the use and STMT the statement (if it exists). Return the new
76 reference or NULL if none was created. */
79 ipa_maybe_record_reference (symtab_node referring_node
, tree val
,
80 enum ipa_ref_use use_type
, gimple stmt
)
83 if (TREE_CODE (val
) != ADDR_EXPR
)
85 val
= get_base_var (val
);
86 if (val
&& (TREE_CODE (val
) == FUNCTION_DECL
87 || TREE_CODE (val
) == VAR_DECL
))
89 symtab_node referred
= symtab_get_node (val
);
90 gcc_checking_assert (referred
);
91 return ipa_record_reference (referring_node
, referred
,
97 /* Remove reference REF. */
100 ipa_remove_reference (struct ipa_ref
*ref
)
102 struct ipa_ref_list
*list
= ipa_ref_referred_ref_list (ref
);
103 struct ipa_ref_list
*list2
= ipa_ref_referring_ref_list (ref
);
104 vec
<ipa_ref_t
, va_gc
> *old_references
= list2
->references
;
105 struct ipa_ref
*last
;
107 gcc_assert (list
->referring
[ref
->referred_index
] == ref
);
108 last
= list
->referring
.last ();
111 list
->referring
[ref
->referred_index
] = list
->referring
.last ();
112 list
->referring
[ref
->referred_index
]->referred_index
113 = ref
->referred_index
;
115 list
->referring
.pop ();
117 last
= &list2
->references
->last ();
121 ipa_ref_referred_ref_list (ref
)->referring
[ref
->referred_index
] = ref
;
123 list2
->references
->pop ();
124 gcc_assert (list2
->references
== old_references
);
127 /* Remove all references in ref list LIST. */
130 ipa_remove_all_references (struct ipa_ref_list
*list
)
132 while (vec_safe_length (list
->references
))
133 ipa_remove_reference (&list
->references
->last ());
134 vec_free (list
->references
);
137 /* Remove all references in ref list LIST. */
140 ipa_remove_all_referring (struct ipa_ref_list
*list
)
142 while (list
->referring
.length ())
143 ipa_remove_reference (list
->referring
.last ());
144 list
->referring
.release ();
147 /* Dump references in LIST to FILE. */
150 ipa_dump_references (FILE * file
, struct ipa_ref_list
*list
)
154 for (i
= 0; ipa_ref_list_reference_iterate (list
, i
, ref
); i
++)
156 fprintf (file
, "%s/%i (%s)",
157 symtab_node_asm_name (ref
->referred
),
158 ref
->referred
->symbol
.order
,
159 ipa_ref_use_name
[ref
->use
]);
160 if (ref
->speculative
)
161 fprintf (file
, " (speculative)");
163 fprintf (file
, "\n");
166 /* Dump referring in LIST to FILE. */
169 ipa_dump_referring (FILE * file
, struct ipa_ref_list
*list
)
173 for (i
= 0; ipa_ref_list_referring_iterate (list
, i
, ref
); i
++)
175 fprintf (file
, "%s/%i (%s)",
176 symtab_node_asm_name (ref
->referring
),
177 ref
->referring
->symbol
.order
,
178 ipa_ref_use_name
[ref
->use
]);
179 if (ref
->speculative
)
180 fprintf (file
, " (speculative)");
182 fprintf (file
, "\n");
185 /* Clone reference REF to DEST_NODE and set its stmt to STMT. */
188 ipa_clone_ref (struct ipa_ref
*ref
,
189 symtab_node dest_node
,
192 bool speculative
= ref
->speculative
;
193 unsigned int stmt_uid
= ref
->lto_stmt_uid
;
194 struct ipa_ref
*ref2
;
196 ref2
= ipa_record_reference (dest_node
,
199 ref2
->speculative
= speculative
;
200 ref2
->lto_stmt_uid
= stmt_uid
;
204 /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
207 ipa_clone_references (symtab_node dest_node
,
208 struct ipa_ref_list
*src
)
210 struct ipa_ref
*ref
, *ref2
;
212 for (i
= 0; ipa_ref_list_reference_iterate (src
, i
, ref
); i
++)
214 bool speculative
= ref
->speculative
;
215 unsigned int stmt_uid
= ref
->lto_stmt_uid
;
217 ref2
= ipa_record_reference (dest_node
,
219 ref
->use
, ref
->stmt
);
220 ref2
->speculative
= speculative
;
221 ref2
->lto_stmt_uid
= stmt_uid
;
225 /* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
228 ipa_clone_referring (symtab_node dest_node
,
229 struct ipa_ref_list
*src
)
231 struct ipa_ref
*ref
, *ref2
;
233 for (i
= 0; ipa_ref_list_referring_iterate (src
, i
, ref
); i
++)
235 bool speculative
= ref
->speculative
;
236 unsigned int stmt_uid
= ref
->lto_stmt_uid
;
238 ref2
= ipa_record_reference (ref
->referring
,
240 ref
->use
, ref
->stmt
);
241 ref2
->speculative
= speculative
;
242 ref2
->lto_stmt_uid
= stmt_uid
;
246 /* Return true when execution of REF can lead to return from
249 ipa_ref_cannot_lead_to_return (struct ipa_ref
*ref
)
251 return cgraph_node_cannot_return (ipa_ref_referring_node (ref
));
254 /* Return true if list contains an alias. */
256 ipa_ref_has_aliases_p (struct ipa_ref_list
*ref_list
)
261 for (i
= 0; ipa_ref_list_referring_iterate (ref_list
, i
, ref
); i
++)
262 if (ref
->use
== IPA_REF_ALIAS
)
267 /* Find the structure describing a reference in REFERRING_NODE to REFERRED_NODE
268 and associated with statement STMT. */
271 ipa_find_reference (symtab_node referring_node
, symtab_node referred_node
,
272 gimple stmt
, unsigned int lto_stmt_uid
)
274 struct ipa_ref
*r
= NULL
;
277 for (i
= 0; ipa_ref_list_reference_iterate (&referring_node
->symbol
.ref_list
, i
, r
); i
++)
278 if (r
->referred
== referred_node
280 && ((stmt
&& r
->stmt
== stmt
)
281 || (lto_stmt_uid
&& r
->lto_stmt_uid
== lto_stmt_uid
)
282 || (!stmt
&& !lto_stmt_uid
&& !r
->stmt
&& !r
->lto_stmt_uid
)))
287 /* Remove all references from REFERRING_NODE that are associated with statement
291 ipa_remove_stmt_references (symtab_node referring_node
, gimple stmt
)
293 struct ipa_ref
*r
= NULL
;
296 for (i
= 0; ipa_ref_list_reference_iterate (&referring_node
->symbol
.ref_list
, i
, r
); i
++)
298 ipa_remove_reference (r
);
301 /* Remove all stmt references in non-speculative references.
302 Those are not maintained during inlining & clonning.
303 The exception are speculative references that are updated along
304 with callgraph edges associated with them. */
307 ipa_clear_stmts_in_references (symtab_node referring_node
)
309 struct ipa_ref
*r
= NULL
;
312 for (i
= 0; ipa_ref_list_reference_iterate (&referring_node
->symbol
.ref_list
, i
, r
); i
++)