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_binded_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
);
94 clone
->force_output
= true;
95 hsa_summaries
->link_functions (clone
, node
, s
->m_kind
, false);
98 fprintf (dump_file
, "Created a new HSA clone: %s, type: %s\n",
100 s
->m_kind
== HSA_KERNEL
? "kernel" : "function");
102 else if (hsa_callable_function_p (node
->decl
))
104 if (!check_warn_node_versionable (node
))
107 = node
->create_virtual_clone (vec
<cgraph_edge
*> (),
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);
116 fprintf (dump_file
, "Created a new HSA function clone: %s\n",
121 /* Redirect all edges that are between HSA clones. */
122 FOR_EACH_DEFINED_FUNCTION (node
)
124 cgraph_edge
*e
= node
->callees
;
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
);
137 "Redirecting edge to HSA function: %s->%s\n",
138 xstrdup_for_dump (e
->caller
->name ()),
139 xstrdup_for_dump (e
->callee
->name ()));
150 /* Iterate all HSA functions and stream out HSA function summary. */
153 ipa_hsa_write_summary (void)
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
;
165 ob
= create_output_block (LTO_section_ipa_hsa
);
166 encoder
= ob
->decl_state
->symtab_node_encoder
;
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
)
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. */
211 ipa_hsa_read_section (struct lto_file_decl_data
*file_data
, const char *data
,
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
;
223 lto_input_block
ib_main ((const char *) data
+ main_offset
,
224 header
->main_size
, file_data
->mode_table
);
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
++)
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
,
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);
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
,
257 lto_data_in_delete (data_in
);
260 /* Load streamed HSA functions summary and assign the summary to a function. */
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
;
269 if (hsa_summaries
== NULL
)
270 hsa_summaries
= new hsa_summary_t (symtab
);
272 while ((file_data
= file_data_vec
[j
++]))
275 const char *data
= lto_get_section_data (file_data
, LTO_section_ipa_hsa
,
279 ipa_hsa_read_section (file_data
, data
, len
);
283 const pass_data pass_data_ipa_hsa
=
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
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
320 pass_ipa_hsa::gate (function
*)
322 return hsa_gen_requested_p ();
328 make_pass_ipa_hsa (gcc::context
*ctxt
)
330 return new pass_ipa_hsa (ctxt
);