annotate gcc/ipa-hsa.c @ 120:f93fa5091070

fix conv1.c
author mir3636
date Thu, 08 Mar 2018 14:53:42 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Callgraph based analysis of static variables.
kono
parents:
diff changeset
2 Copyright (C) 2015-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Martin Liska <mliska@suse.cz>
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 /* Interprocedural HSA pass is responsible for creation of HSA clones.
kono
parents:
diff changeset
22 For all these HSA clones, we emit HSAIL instructions and pass processing
kono
parents:
diff changeset
23 is terminated. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 #include "config.h"
kono
parents:
diff changeset
26 #include "system.h"
kono
parents:
diff changeset
27 #include "coretypes.h"
kono
parents:
diff changeset
28 #include "tm.h"
kono
parents:
diff changeset
29 #include "is-a.h"
kono
parents:
diff changeset
30 #include "hash-set.h"
kono
parents:
diff changeset
31 #include "vec.h"
kono
parents:
diff changeset
32 #include "tree.h"
kono
parents:
diff changeset
33 #include "tree-pass.h"
kono
parents:
diff changeset
34 #include "function.h"
kono
parents:
diff changeset
35 #include "basic-block.h"
kono
parents:
diff changeset
36 #include "gimple.h"
kono
parents:
diff changeset
37 #include "dumpfile.h"
kono
parents:
diff changeset
38 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
39 #include "tree-streamer.h"
kono
parents:
diff changeset
40 #include "stringpool.h"
kono
parents:
diff changeset
41 #include "cgraph.h"
kono
parents:
diff changeset
42 #include "print-tree.h"
kono
parents:
diff changeset
43 #include "symbol-summary.h"
kono
parents:
diff changeset
44 #include "hsa-common.h"
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 namespace {
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 /* If NODE is not versionable, warn about not emiting HSAIL and return false.
kono
parents:
diff changeset
49 Otherwise return true. */
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 static bool
kono
parents:
diff changeset
52 check_warn_node_versionable (cgraph_node *node)
kono
parents:
diff changeset
53 {
kono
parents:
diff changeset
54 if (!node->local.versionable)
kono
parents:
diff changeset
55 {
kono
parents:
diff changeset
56 warning_at (EXPR_LOCATION (node->decl), OPT_Whsa,
kono
parents:
diff changeset
57 "could not emit HSAIL for function %s: function cannot be "
kono
parents:
diff changeset
58 "cloned", node->name ());
kono
parents:
diff changeset
59 return false;
kono
parents:
diff changeset
60 }
kono
parents:
diff changeset
61 return true;
kono
parents:
diff changeset
62 }
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* The function creates HSA clones for all functions that were either
kono
parents:
diff changeset
65 marked as HSA kernels or are callable HSA functions. Apart from that,
kono
parents:
diff changeset
66 we redirect all edges that come from an HSA clone and end in another
kono
parents:
diff changeset
67 HSA clone to connect these two functions. */
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 static unsigned int
kono
parents:
diff changeset
70 process_hsa_functions (void)
kono
parents:
diff changeset
71 {
kono
parents:
diff changeset
72 struct cgraph_node *node;
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 if (hsa_summaries == NULL)
kono
parents:
diff changeset
75 hsa_summaries = new hsa_summary_t (symtab);
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
78 {
kono
parents:
diff changeset
79 hsa_function_summary *s = hsa_summaries->get (node);
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 /* A linked function is skipped. */
kono
parents:
diff changeset
82 if (s->m_bound_function != NULL)
kono
parents:
diff changeset
83 continue;
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 if (s->m_kind != HSA_NONE)
kono
parents:
diff changeset
86 {
kono
parents:
diff changeset
87 if (!check_warn_node_versionable (node))
kono
parents:
diff changeset
88 continue;
kono
parents:
diff changeset
89 cgraph_node *clone
kono
parents:
diff changeset
90 = node->create_virtual_clone (vec <cgraph_edge *> (),
kono
parents:
diff changeset
91 NULL, NULL, "hsa");
kono
parents:
diff changeset
92 TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
kono
parents:
diff changeset
93 clone->externally_visible = node->externally_visible;
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 clone->force_output = true;
kono
parents:
diff changeset
96 hsa_summaries->link_functions (clone, node, s->m_kind, false);
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 if (dump_file)
kono
parents:
diff changeset
99 fprintf (dump_file, "Created a new HSA clone: %s, type: %s\n",
kono
parents:
diff changeset
100 clone->name (),
kono
parents:
diff changeset
101 s->m_kind == HSA_KERNEL ? "kernel" : "function");
kono
parents:
diff changeset
102 }
kono
parents:
diff changeset
103 else if (hsa_callable_function_p (node->decl)
kono
parents:
diff changeset
104 /* At this point, this is enough to identify clones for
kono
parents:
diff changeset
105 parallel, which for HSA would need to be kernels anyway. */
kono
parents:
diff changeset
106 && !DECL_ARTIFICIAL (node->decl))
kono
parents:
diff changeset
107 {
kono
parents:
diff changeset
108 if (!check_warn_node_versionable (node))
kono
parents:
diff changeset
109 continue;
kono
parents:
diff changeset
110 cgraph_node *clone
kono
parents:
diff changeset
111 = node->create_virtual_clone (vec <cgraph_edge *> (),
kono
parents:
diff changeset
112 NULL, NULL, "hsa");
kono
parents:
diff changeset
113 TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
kono
parents:
diff changeset
114 clone->externally_visible = node->externally_visible;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 if (!cgraph_local_p (node))
kono
parents:
diff changeset
117 clone->force_output = true;
kono
parents:
diff changeset
118 hsa_summaries->link_functions (clone, node, HSA_FUNCTION, false);
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 if (dump_file)
kono
parents:
diff changeset
121 fprintf (dump_file, "Created a new HSA function clone: %s\n",
kono
parents:
diff changeset
122 clone->name ());
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 /* Redirect all edges that are between HSA clones. */
kono
parents:
diff changeset
127 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
128 {
kono
parents:
diff changeset
129 cgraph_edge *e = node->callees;
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 while (e)
kono
parents:
diff changeset
132 {
kono
parents:
diff changeset
133 hsa_function_summary *src = hsa_summaries->get (node);
kono
parents:
diff changeset
134 if (src->m_kind != HSA_NONE && src->m_gpu_implementation_p)
kono
parents:
diff changeset
135 {
kono
parents:
diff changeset
136 hsa_function_summary *dst = hsa_summaries->get (e->callee);
kono
parents:
diff changeset
137 if (dst->m_kind != HSA_NONE && !dst->m_gpu_implementation_p)
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 e->redirect_callee (dst->m_bound_function);
kono
parents:
diff changeset
140 if (dump_file)
kono
parents:
diff changeset
141 fprintf (dump_file,
kono
parents:
diff changeset
142 "Redirecting edge to HSA function: %s->%s\n",
kono
parents:
diff changeset
143 xstrdup_for_dump (e->caller->name ()),
kono
parents:
diff changeset
144 xstrdup_for_dump (e->callee->name ()));
kono
parents:
diff changeset
145 }
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 e = e->next_callee;
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150 }
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 return 0;
kono
parents:
diff changeset
153 }
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 /* Iterate all HSA functions and stream out HSA function summary. */
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 static void
kono
parents:
diff changeset
158 ipa_hsa_write_summary (void)
kono
parents:
diff changeset
159 {
kono
parents:
diff changeset
160 struct bitpack_d bp;
kono
parents:
diff changeset
161 struct cgraph_node *node;
kono
parents:
diff changeset
162 struct output_block *ob;
kono
parents:
diff changeset
163 unsigned int count = 0;
kono
parents:
diff changeset
164 lto_symtab_encoder_iterator lsei;
kono
parents:
diff changeset
165 lto_symtab_encoder_t encoder;
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 if (!hsa_summaries)
kono
parents:
diff changeset
168 return;
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 ob = create_output_block (LTO_section_ipa_hsa);
kono
parents:
diff changeset
171 encoder = ob->decl_state->symtab_node_encoder;
kono
parents:
diff changeset
172 ob->symbol = NULL;
kono
parents:
diff changeset
173 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
kono
parents:
diff changeset
174 lsei_next_function_in_partition (&lsei))
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 node = lsei_cgraph_node (lsei);
kono
parents:
diff changeset
177 hsa_function_summary *s = hsa_summaries->get (node);
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 if (s->m_kind != HSA_NONE)
kono
parents:
diff changeset
180 count++;
kono
parents:
diff changeset
181 }
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 streamer_write_uhwi (ob, count);
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 /* Process all of the functions. */
kono
parents:
diff changeset
186 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
kono
parents:
diff changeset
187 lsei_next_function_in_partition (&lsei))
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 node = lsei_cgraph_node (lsei);
kono
parents:
diff changeset
190 hsa_function_summary *s = hsa_summaries->get (node);
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 if (s->m_kind != HSA_NONE)
kono
parents:
diff changeset
193 {
kono
parents:
diff changeset
194 encoder = ob->decl_state->symtab_node_encoder;
kono
parents:
diff changeset
195 int node_ref = lto_symtab_encoder_encode (encoder, node);
kono
parents:
diff changeset
196 streamer_write_uhwi (ob, node_ref);
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 bp = bitpack_create (ob->main_stream);
kono
parents:
diff changeset
199 bp_pack_value (&bp, s->m_kind, 2);
kono
parents:
diff changeset
200 bp_pack_value (&bp, s->m_gpu_implementation_p, 1);
kono
parents:
diff changeset
201 bp_pack_value (&bp, s->m_bound_function != NULL, 1);
kono
parents:
diff changeset
202 streamer_write_bitpack (&bp);
kono
parents:
diff changeset
203 if (s->m_bound_function)
kono
parents:
diff changeset
204 stream_write_tree (ob, s->m_bound_function->decl, true);
kono
parents:
diff changeset
205 }
kono
parents:
diff changeset
206 }
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 streamer_write_char_stream (ob->main_stream, 0);
kono
parents:
diff changeset
209 produce_asm (ob, NULL);
kono
parents:
diff changeset
210 destroy_output_block (ob);
kono
parents:
diff changeset
211 }
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 /* Read section in file FILE_DATA of length LEN with data DATA. */
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 static void
kono
parents:
diff changeset
216 ipa_hsa_read_section (struct lto_file_decl_data *file_data, const char *data,
kono
parents:
diff changeset
217 size_t len)
kono
parents:
diff changeset
218 {
kono
parents:
diff changeset
219 const struct lto_function_header *header
kono
parents:
diff changeset
220 = (const struct lto_function_header *) data;
kono
parents:
diff changeset
221 const int cfg_offset = sizeof (struct lto_function_header);
kono
parents:
diff changeset
222 const int main_offset = cfg_offset + header->cfg_size;
kono
parents:
diff changeset
223 const int string_offset = main_offset + header->main_size;
kono
parents:
diff changeset
224 struct data_in *data_in;
kono
parents:
diff changeset
225 unsigned int i;
kono
parents:
diff changeset
226 unsigned int count;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 lto_input_block ib_main ((const char *) data + main_offset,
kono
parents:
diff changeset
229 header->main_size, file_data->mode_table);
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 data_in
kono
parents:
diff changeset
232 = lto_data_in_create (file_data, (const char *) data + string_offset,
kono
parents:
diff changeset
233 header->string_size, vNULL);
kono
parents:
diff changeset
234 count = streamer_read_uhwi (&ib_main);
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 for (i = 0; i < count; i++)
kono
parents:
diff changeset
237 {
kono
parents:
diff changeset
238 unsigned int index;
kono
parents:
diff changeset
239 struct cgraph_node *node;
kono
parents:
diff changeset
240 lto_symtab_encoder_t encoder;
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 index = streamer_read_uhwi (&ib_main);
kono
parents:
diff changeset
243 encoder = file_data->symtab_node_encoder;
kono
parents:
diff changeset
244 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
kono
parents:
diff changeset
245 index));
kono
parents:
diff changeset
246 gcc_assert (node->definition);
kono
parents:
diff changeset
247 hsa_function_summary *s = hsa_summaries->get (node);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 struct bitpack_d bp = streamer_read_bitpack (&ib_main);
kono
parents:
diff changeset
250 s->m_kind = (hsa_function_kind) bp_unpack_value (&bp, 2);
kono
parents:
diff changeset
251 s->m_gpu_implementation_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
252 bool has_tree = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 if (has_tree)
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 tree decl = stream_read_tree (&ib_main, data_in);
kono
parents:
diff changeset
257 s->m_bound_function = cgraph_node::get_create (decl);
kono
parents:
diff changeset
258 }
kono
parents:
diff changeset
259 }
kono
parents:
diff changeset
260 lto_free_section_data (file_data, LTO_section_ipa_hsa, NULL, data,
kono
parents:
diff changeset
261 len);
kono
parents:
diff changeset
262 lto_data_in_delete (data_in);
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 /* Load streamed HSA functions summary and assign the summary to a function. */
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 static void
kono
parents:
diff changeset
268 ipa_hsa_read_summary (void)
kono
parents:
diff changeset
269 {
kono
parents:
diff changeset
270 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
kono
parents:
diff changeset
271 struct lto_file_decl_data *file_data;
kono
parents:
diff changeset
272 unsigned int j = 0;
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 if (hsa_summaries == NULL)
kono
parents:
diff changeset
275 hsa_summaries = new hsa_summary_t (symtab);
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 while ((file_data = file_data_vec[j++]))
kono
parents:
diff changeset
278 {
kono
parents:
diff changeset
279 size_t len;
kono
parents:
diff changeset
280 const char *data = lto_get_section_data (file_data, LTO_section_ipa_hsa,
kono
parents:
diff changeset
281 NULL, &len);
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 if (data)
kono
parents:
diff changeset
284 ipa_hsa_read_section (file_data, data, len);
kono
parents:
diff changeset
285 }
kono
parents:
diff changeset
286 }
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 const pass_data pass_data_ipa_hsa =
kono
parents:
diff changeset
289 {
kono
parents:
diff changeset
290 IPA_PASS, /* type */
kono
parents:
diff changeset
291 "hsa", /* name */
kono
parents:
diff changeset
292 OPTGROUP_OMP, /* optinfo_flags */
kono
parents:
diff changeset
293 TV_IPA_HSA, /* tv_id */
kono
parents:
diff changeset
294 0, /* properties_required */
kono
parents:
diff changeset
295 0, /* properties_provided */
kono
parents:
diff changeset
296 0, /* properties_destroyed */
kono
parents:
diff changeset
297 0, /* todo_flags_start */
kono
parents:
diff changeset
298 TODO_dump_symtab, /* todo_flags_finish */
kono
parents:
diff changeset
299 };
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 class pass_ipa_hsa : public ipa_opt_pass_d
kono
parents:
diff changeset
302 {
kono
parents:
diff changeset
303 public:
kono
parents:
diff changeset
304 pass_ipa_hsa (gcc::context *ctxt)
kono
parents:
diff changeset
305 : ipa_opt_pass_d (pass_data_ipa_hsa, ctxt,
kono
parents:
diff changeset
306 NULL, /* generate_summary */
kono
parents:
diff changeset
307 ipa_hsa_write_summary, /* write_summary */
kono
parents:
diff changeset
308 ipa_hsa_read_summary, /* read_summary */
kono
parents:
diff changeset
309 ipa_hsa_write_summary, /* write_optimization_summary */
kono
parents:
diff changeset
310 ipa_hsa_read_summary, /* read_optimization_summary */
kono
parents:
diff changeset
311 NULL, /* stmt_fixup */
kono
parents:
diff changeset
312 0, /* function_transform_todo_flags_start */
kono
parents:
diff changeset
313 NULL, /* function_transform */
kono
parents:
diff changeset
314 NULL) /* variable_transform */
kono
parents:
diff changeset
315 {}
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 /* opt_pass methods: */
kono
parents:
diff changeset
318 virtual bool gate (function *);
kono
parents:
diff changeset
319
kono
parents:
diff changeset
320 virtual unsigned int execute (function *) { return process_hsa_functions (); }
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 }; // class pass_ipa_reference
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 bool
kono
parents:
diff changeset
325 pass_ipa_hsa::gate (function *)
kono
parents:
diff changeset
326 {
kono
parents:
diff changeset
327 return hsa_gen_requested_p ();
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 } // anon namespace
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 ipa_opt_pass_d *
kono
parents:
diff changeset
333 make_pass_ipa_hsa (gcc::context *ctxt)
kono
parents:
diff changeset
334 {
kono
parents:
diff changeset
335 return new pass_ipa_hsa (ctxt);
kono
parents:
diff changeset
336 }