]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-ref.c
PR target/57431
[thirdparty/gcc.git] / gcc / ipa-ref.c
CommitLineData
8d810329 1/* Interprocedural reference lists.
711789cc 2 Copyright (C) 2010-2013 Free Software Foundation, Inc.
8d810329 3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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 30static 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
36struct ipa_ref *
04ec15fa 37ipa_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
76struct ipa_ref *
77ipa_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
97void
98ipa_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
127void
128ipa_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
137void
04ec15fa 138ipa_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
147void
148ipa_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
164void
04ec15fa 165ipa_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
181void
04ec15fa 182ipa_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
195void
04ec15fa 196ipa_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. */
209bool
210ipa_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. */
216bool
217ipa_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
230struct ipa_ref *
231ipa_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
247void
248ipa_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}