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
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/>. */
21 /* Interprocedural HSA pass is responsible for creation of HSA clones.
22 For all these HSA clones, we emit HSAIL instructions and pass processing
27 #include "coretypes.h"
33 #include "tree-pass.h"
35 #include "basic-block.h"
38 #include "gimple-pretty-print.h"
39 #include "tree-streamer.h"
40 #include "stringpool.h"
42 #include "print-tree.h"
43 #include "symbol-summary.h"
48 /* If NODE is not versionable, warn about not emiting HSAIL and return false.
49 Otherwise return true. */
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 ());
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. */
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
)
85 if (s
->m_kind
!= HSA_NONE
)
87 if (!check_warn_node_versionable (node
))
90 = node
->create_virtual_clone (vec
<cgraph_edge
*> (),
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);
99 fprintf (dump_file
, "Created a new HSA clone: %s, type: %s\n",
101 s
->m_kind
== HSA_KERNEL
? "kernel" : "function");
103 else if (hsa_callable_function_p (node
->decl
))
105 if (!check_warn_node_versionable (node
))
108 = node
->create_virtual_clone (vec
<cgraph_edge
*> (),
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);
118 fprintf (dump_file
, "Created a new HSA function clone: %s\n",
123 /* Redirect all edges that are between HSA clones. */
124 FOR_EACH_DEFINED_FUNCTION (node
)
126 cgraph_edge
*e
= node
->callees
;
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
);
139 "Redirecting edge to HSA function: %s->%s\n",
140 xstrdup_for_dump (e
->caller
->name ()),
141 xstrdup_for_dump (e
->callee
->name ()));
152 /* Iterate all HSA functions and stream out HSA function summary. */
155 ipa_hsa_write_summary (void)
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
;
167 ob
= create_output_block (LTO_section_ipa_hsa
);
168 encoder
= ob
->decl_state
->symtab_node_encoder
;
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
)
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. */
213 ipa_hsa_read_section (struct lto_file_decl_data
*file_data
, const char *data
,
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
;
225 lto_input_block
ib_main ((const char *) data
+ main_offset
,
226 header
->main_size
, file_data
->mode_table
);
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
++)
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
,
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);
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
,
259 lto_data_in_delete (data_in
);
262 /* Load streamed HSA functions summary and assign the summary to a function. */
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
;
271 if (hsa_summaries
== NULL
)
272 hsa_summaries
= new hsa_summary_t (symtab
);
274 while ((file_data
= file_data_vec
[j
++]))
277 const char *data
= lto_get_section_data (file_data
, LTO_section_ipa_hsa
,
281 ipa_hsa_read_section (file_data
, data
, len
);
285 const pass_data pass_data_ipa_hsa
=
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
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
322 pass_ipa_hsa::gate (function
*)
324 return hsa_gen_requested_p ();
330 make_pass_ipa_hsa (gcc::context
*ctxt
)
332 return new pass_ipa_hsa (ctxt
);