* download_ecj: Remove.
[official-gcc.git] / gcc / ipa-hsa.c
blob4391b580566936b6306878f29e0f2ec2538ad76d
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2015-2017 Free Software Foundation, Inc.
3 Contributed by Martin Liska <mliska@suse.cz>
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
10 version.
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
15 for more details.
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/>. */
21 /* Interprocedural HSA pass is responsible for creation of HSA clones.
22 For all these HSA clones, we emit HSAIL instructions and pass processing
23 is terminated. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "is-a.h"
30 #include "hash-set.h"
31 #include "vec.h"
32 #include "tree.h"
33 #include "tree-pass.h"
34 #include "function.h"
35 #include "basic-block.h"
36 #include "gimple.h"
37 #include "dumpfile.h"
38 #include "gimple-pretty-print.h"
39 #include "tree-streamer.h"
40 #include "stringpool.h"
41 #include "cgraph.h"
42 #include "print-tree.h"
43 #include "symbol-summary.h"
44 #include "hsa.h"
46 namespace {
48 /* If NODE is not versionable, warn about not emiting HSAIL and return false.
49 Otherwise return true. */
51 static bool
52 check_warn_node_versionable (cgraph_node *node)
54 if (!node->local.versionable)
56 warning_at (EXPR_LOCATION (node->decl), OPT_Whsa,
57 "could not emit HSAIL for function %s: function cannot be "
58 "cloned", node->name ());
59 return false;
61 return true;
64 /* The function creates HSA clones for all functions that were either
65 marked as HSA kernels or are callable HSA functions. Apart from that,
66 we redirect all edges that come from an HSA clone and end in another
67 HSA clone to connect these two functions. */
69 static unsigned int
70 process_hsa_functions (void)
72 struct cgraph_node *node;
74 if (hsa_summaries == NULL)
75 hsa_summaries = new hsa_summary_t (symtab);
77 FOR_EACH_DEFINED_FUNCTION (node)
79 hsa_function_summary *s = hsa_summaries->get (node);
81 /* A linked function is skipped. */
82 if (s->m_bound_function != NULL)
83 continue;
85 if (s->m_kind != HSA_NONE)
87 if (!check_warn_node_versionable (node))
88 continue;
89 cgraph_node *clone
90 = node->create_virtual_clone (vec <cgraph_edge *> (),
91 NULL, NULL, "hsa");
92 TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
93 clone->externally_visible = node->externally_visible;
95 clone->force_output = true;
96 hsa_summaries->link_functions (clone, node, s->m_kind, false);
98 if (dump_file)
99 fprintf (dump_file, "Created a new HSA clone: %s, type: %s\n",
100 clone->name (),
101 s->m_kind == HSA_KERNEL ? "kernel" : "function");
103 else if (hsa_callable_function_p (node->decl))
105 if (!check_warn_node_versionable (node))
106 continue;
107 cgraph_node *clone
108 = node->create_virtual_clone (vec <cgraph_edge *> (),
109 NULL, NULL, "hsa");
110 TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
111 clone->externally_visible = node->externally_visible;
113 if (!cgraph_local_p (node))
114 clone->force_output = true;
115 hsa_summaries->link_functions (clone, node, HSA_FUNCTION, false);
117 if (dump_file)
118 fprintf (dump_file, "Created a new HSA function clone: %s\n",
119 clone->name ());
123 /* Redirect all edges that are between HSA clones. */
124 FOR_EACH_DEFINED_FUNCTION (node)
126 cgraph_edge *e = node->callees;
128 while (e)
130 hsa_function_summary *src = hsa_summaries->get (node);
131 if (src->m_kind != HSA_NONE && src->m_gpu_implementation_p)
133 hsa_function_summary *dst = hsa_summaries->get (e->callee);
134 if (dst->m_kind != HSA_NONE && !dst->m_gpu_implementation_p)
136 e->redirect_callee (dst->m_bound_function);
137 if (dump_file)
138 fprintf (dump_file,
139 "Redirecting edge to HSA function: %s->%s\n",
140 xstrdup_for_dump (e->caller->name ()),
141 xstrdup_for_dump (e->callee->name ()));
145 e = e->next_callee;
149 return 0;
152 /* Iterate all HSA functions and stream out HSA function summary. */
154 static void
155 ipa_hsa_write_summary (void)
157 struct bitpack_d bp;
158 struct cgraph_node *node;
159 struct output_block *ob;
160 unsigned int count = 0;
161 lto_symtab_encoder_iterator lsei;
162 lto_symtab_encoder_t encoder;
164 if (!hsa_summaries)
165 return;
167 ob = create_output_block (LTO_section_ipa_hsa);
168 encoder = ob->decl_state->symtab_node_encoder;
169 ob->symbol = NULL;
170 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
171 lsei_next_function_in_partition (&lsei))
173 node = lsei_cgraph_node (lsei);
174 hsa_function_summary *s = hsa_summaries->get (node);
176 if (s->m_kind != HSA_NONE)
177 count++;
180 streamer_write_uhwi (ob, count);
182 /* Process all of the functions. */
183 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
184 lsei_next_function_in_partition (&lsei))
186 node = lsei_cgraph_node (lsei);
187 hsa_function_summary *s = hsa_summaries->get (node);
189 if (s->m_kind != HSA_NONE)
191 encoder = ob->decl_state->symtab_node_encoder;
192 int node_ref = lto_symtab_encoder_encode (encoder, node);
193 streamer_write_uhwi (ob, node_ref);
195 bp = bitpack_create (ob->main_stream);
196 bp_pack_value (&bp, s->m_kind, 2);
197 bp_pack_value (&bp, s->m_gpu_implementation_p, 1);
198 bp_pack_value (&bp, s->m_bound_function != NULL, 1);
199 streamer_write_bitpack (&bp);
200 if (s->m_bound_function)
201 stream_write_tree (ob, s->m_bound_function->decl, true);
205 streamer_write_char_stream (ob->main_stream, 0);
206 produce_asm (ob, NULL);
207 destroy_output_block (ob);
210 /* Read section in file FILE_DATA of length LEN with data DATA. */
212 static void
213 ipa_hsa_read_section (struct lto_file_decl_data *file_data, const char *data,
214 size_t len)
216 const struct lto_function_header *header
217 = (const struct lto_function_header *) data;
218 const int cfg_offset = sizeof (struct lto_function_header);
219 const int main_offset = cfg_offset + header->cfg_size;
220 const int string_offset = main_offset + header->main_size;
221 struct data_in *data_in;
222 unsigned int i;
223 unsigned int count;
225 lto_input_block ib_main ((const char *) data + main_offset,
226 header->main_size, file_data->mode_table);
228 data_in
229 = lto_data_in_create (file_data, (const char *) data + string_offset,
230 header->string_size, vNULL);
231 count = streamer_read_uhwi (&ib_main);
233 for (i = 0; i < count; i++)
235 unsigned int index;
236 struct cgraph_node *node;
237 lto_symtab_encoder_t encoder;
239 index = streamer_read_uhwi (&ib_main);
240 encoder = file_data->symtab_node_encoder;
241 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
242 index));
243 gcc_assert (node->definition);
244 hsa_function_summary *s = hsa_summaries->get (node);
246 struct bitpack_d bp = streamer_read_bitpack (&ib_main);
247 s->m_kind = (hsa_function_kind) bp_unpack_value (&bp, 2);
248 s->m_gpu_implementation_p = bp_unpack_value (&bp, 1);
249 bool has_tree = bp_unpack_value (&bp, 1);
251 if (has_tree)
253 tree decl = stream_read_tree (&ib_main, data_in);
254 s->m_bound_function = cgraph_node::get_create (decl);
257 lto_free_section_data (file_data, LTO_section_ipa_hsa, NULL, data,
258 len);
259 lto_data_in_delete (data_in);
262 /* Load streamed HSA functions summary and assign the summary to a function. */
264 static void
265 ipa_hsa_read_summary (void)
267 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
268 struct lto_file_decl_data *file_data;
269 unsigned int j = 0;
271 if (hsa_summaries == NULL)
272 hsa_summaries = new hsa_summary_t (symtab);
274 while ((file_data = file_data_vec[j++]))
276 size_t len;
277 const char *data = lto_get_section_data (file_data, LTO_section_ipa_hsa,
278 NULL, &len);
280 if (data)
281 ipa_hsa_read_section (file_data, data, len);
285 const pass_data pass_data_ipa_hsa =
287 IPA_PASS, /* type */
288 "hsa", /* name */
289 OPTGROUP_NONE, /* optinfo_flags */
290 TV_IPA_HSA, /* tv_id */
291 0, /* properties_required */
292 0, /* properties_provided */
293 0, /* properties_destroyed */
294 0, /* todo_flags_start */
295 TODO_dump_symtab, /* todo_flags_finish */
298 class pass_ipa_hsa : public ipa_opt_pass_d
300 public:
301 pass_ipa_hsa (gcc::context *ctxt)
302 : ipa_opt_pass_d (pass_data_ipa_hsa, ctxt,
303 NULL, /* generate_summary */
304 ipa_hsa_write_summary, /* write_summary */
305 ipa_hsa_read_summary, /* read_summary */
306 ipa_hsa_write_summary, /* write_optimization_summary */
307 ipa_hsa_read_summary, /* read_optimization_summary */
308 NULL, /* stmt_fixup */
309 0, /* function_transform_todo_flags_start */
310 NULL, /* function_transform */
311 NULL) /* variable_transform */
314 /* opt_pass methods: */
315 virtual bool gate (function *);
317 virtual unsigned int execute (function *) { return process_hsa_functions (); }
319 }; // class pass_ipa_reference
321 bool
322 pass_ipa_hsa::gate (function *)
324 return hsa_gen_requested_p ();
327 } // anon namespace
329 ipa_opt_pass_d *
330 make_pass_ipa_hsa (gcc::context *ctxt)
332 return new pass_ipa_hsa (ctxt);