gcc/ChangeLog:
[official-gcc.git] / gcc / ipa-hsa.c
blob769657f330a5b7f2042aad1ec919fea164fa88bd
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2015-2016 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_binded_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);
94 clone->force_output = true;
95 hsa_summaries->link_functions (clone, node, s->m_kind, false);
97 if (dump_file)
98 fprintf (dump_file, "Created a new HSA clone: %s, type: %s\n",
99 clone->name (),
100 s->m_kind == HSA_KERNEL ? "kernel" : "function");
102 else if (hsa_callable_function_p (node->decl))
104 if (!check_warn_node_versionable (node))
105 continue;
106 cgraph_node *clone
107 = node->create_virtual_clone (vec <cgraph_edge *> (),
108 NULL, NULL, "hsa");
109 TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
111 if (!cgraph_local_p (node))
112 clone->force_output = true;
113 hsa_summaries->link_functions (clone, node, HSA_FUNCTION, false);
115 if (dump_file)
116 fprintf (dump_file, "Created a new HSA function clone: %s\n",
117 clone->name ());
121 /* Redirect all edges that are between HSA clones. */
122 FOR_EACH_DEFINED_FUNCTION (node)
124 cgraph_edge *e = node->callees;
126 while (e)
128 hsa_function_summary *src = hsa_summaries->get (node);
129 if (src->m_kind != HSA_NONE && src->m_gpu_implementation_p)
131 hsa_function_summary *dst = hsa_summaries->get (e->callee);
132 if (dst->m_kind != HSA_NONE && !dst->m_gpu_implementation_p)
134 e->redirect_callee (dst->m_binded_function);
135 if (dump_file)
136 fprintf (dump_file,
137 "Redirecting edge to HSA function: %s->%s\n",
138 xstrdup_for_dump (e->caller->name ()),
139 xstrdup_for_dump (e->callee->name ()));
143 e = e->next_callee;
147 return 0;
150 /* Iterate all HSA functions and stream out HSA function summary. */
152 static void
153 ipa_hsa_write_summary (void)
155 struct bitpack_d bp;
156 struct cgraph_node *node;
157 struct output_block *ob;
158 unsigned int count = 0;
159 lto_symtab_encoder_iterator lsei;
160 lto_symtab_encoder_t encoder;
162 if (!hsa_summaries)
163 return;
165 ob = create_output_block (LTO_section_ipa_hsa);
166 encoder = ob->decl_state->symtab_node_encoder;
167 ob->symbol = NULL;
168 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
169 lsei_next_function_in_partition (&lsei))
171 node = lsei_cgraph_node (lsei);
172 hsa_function_summary *s = hsa_summaries->get (node);
174 if (s->m_kind != HSA_NONE)
175 count++;
178 streamer_write_uhwi (ob, count);
180 /* Process all of the functions. */
181 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
182 lsei_next_function_in_partition (&lsei))
184 node = lsei_cgraph_node (lsei);
185 hsa_function_summary *s = hsa_summaries->get (node);
187 if (s->m_kind != HSA_NONE)
189 encoder = ob->decl_state->symtab_node_encoder;
190 int node_ref = lto_symtab_encoder_encode (encoder, node);
191 streamer_write_uhwi (ob, node_ref);
193 bp = bitpack_create (ob->main_stream);
194 bp_pack_value (&bp, s->m_kind, 2);
195 bp_pack_value (&bp, s->m_gpu_implementation_p, 1);
196 bp_pack_value (&bp, s->m_binded_function != NULL, 1);
197 streamer_write_bitpack (&bp);
198 if (s->m_binded_function)
199 stream_write_tree (ob, s->m_binded_function->decl, true);
203 streamer_write_char_stream (ob->main_stream, 0);
204 produce_asm (ob, NULL);
205 destroy_output_block (ob);
208 /* Read section in file FILE_DATA of length LEN with data DATA. */
210 static void
211 ipa_hsa_read_section (struct lto_file_decl_data *file_data, const char *data,
212 size_t len)
214 const struct lto_function_header *header
215 = (const struct lto_function_header *) data;
216 const int cfg_offset = sizeof (struct lto_function_header);
217 const int main_offset = cfg_offset + header->cfg_size;
218 const int string_offset = main_offset + header->main_size;
219 struct data_in *data_in;
220 unsigned int i;
221 unsigned int count;
223 lto_input_block ib_main ((const char *) data + main_offset,
224 header->main_size, file_data->mode_table);
226 data_in
227 = lto_data_in_create (file_data, (const char *) data + string_offset,
228 header->string_size, vNULL);
229 count = streamer_read_uhwi (&ib_main);
231 for (i = 0; i < count; i++)
233 unsigned int index;
234 struct cgraph_node *node;
235 lto_symtab_encoder_t encoder;
237 index = streamer_read_uhwi (&ib_main);
238 encoder = file_data->symtab_node_encoder;
239 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
240 index));
241 gcc_assert (node->definition);
242 hsa_function_summary *s = hsa_summaries->get (node);
244 struct bitpack_d bp = streamer_read_bitpack (&ib_main);
245 s->m_kind = (hsa_function_kind) bp_unpack_value (&bp, 2);
246 s->m_gpu_implementation_p = bp_unpack_value (&bp, 1);
247 bool has_tree = bp_unpack_value (&bp, 1);
249 if (has_tree)
251 tree decl = stream_read_tree (&ib_main, data_in);
252 s->m_binded_function = cgraph_node::get_create (decl);
255 lto_free_section_data (file_data, LTO_section_ipa_hsa, NULL, data,
256 len);
257 lto_data_in_delete (data_in);
260 /* Load streamed HSA functions summary and assign the summary to a function. */
262 static void
263 ipa_hsa_read_summary (void)
265 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
266 struct lto_file_decl_data *file_data;
267 unsigned int j = 0;
269 if (hsa_summaries == NULL)
270 hsa_summaries = new hsa_summary_t (symtab);
272 while ((file_data = file_data_vec[j++]))
274 size_t len;
275 const char *data = lto_get_section_data (file_data, LTO_section_ipa_hsa,
276 NULL, &len);
278 if (data)
279 ipa_hsa_read_section (file_data, data, len);
283 const pass_data pass_data_ipa_hsa =
285 IPA_PASS, /* type */
286 "hsa", /* name */
287 OPTGROUP_NONE, /* optinfo_flags */
288 TV_IPA_HSA, /* tv_id */
289 0, /* properties_required */
290 0, /* properties_provided */
291 0, /* properties_destroyed */
292 0, /* todo_flags_start */
293 TODO_dump_symtab, /* todo_flags_finish */
296 class pass_ipa_hsa : public ipa_opt_pass_d
298 public:
299 pass_ipa_hsa (gcc::context *ctxt)
300 : ipa_opt_pass_d (pass_data_ipa_hsa, ctxt,
301 NULL, /* generate_summary */
302 ipa_hsa_write_summary, /* write_summary */
303 ipa_hsa_read_summary, /* read_summary */
304 ipa_hsa_write_summary, /* write_optimization_summary */
305 ipa_hsa_read_summary, /* read_optimization_summary */
306 NULL, /* stmt_fixup */
307 0, /* function_transform_todo_flags_start */
308 NULL, /* function_transform */
309 NULL) /* variable_transform */
312 /* opt_pass methods: */
313 virtual bool gate (function *);
315 virtual unsigned int execute (function *) { return process_hsa_functions (); }
317 }; // class pass_ipa_reference
319 bool
320 pass_ipa_hsa::gate (function *)
322 return hsa_gen_requested_p ();
325 } // anon namespace
327 ipa_opt_pass_d *
328 make_pass_ipa_hsa (gcc::context *ctxt)
330 return new pass_ipa_hsa (ctxt);