* tree-ssa.c (target_for_debug_bind, verify_phi_args,
[official-gcc.git] / gcc / hsa-gen.c
blob6f7083a15c997b25468c03bb8dbfc5c096b673a1
1 /* A pass for lowering gimple to HSAIL
2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 Contributed by Martin Jambor <mjambor@suse.cz> and
4 Martin Liska <mliska@suse.cz>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "is-a.h"
27 #include "hash-table.h"
28 #include "vec.h"
29 #include "tree.h"
30 #include "tree-pass.h"
31 #include "cfg.h"
32 #include "function.h"
33 #include "basic-block.h"
34 #include "fold-const.h"
35 #include "gimple.h"
36 #include "gimple-iterator.h"
37 #include "bitmap.h"
38 #include "dumpfile.h"
39 #include "gimple-pretty-print.h"
40 #include "diagnostic-core.h"
41 #include "alloc-pool.h"
42 #include "gimple-ssa.h"
43 #include "tree-phinodes.h"
44 #include "stringpool.h"
45 #include "tree-vrp.h"
46 #include "tree-ssanames.h"
47 #include "tree-dfa.h"
48 #include "ssa-iterators.h"
49 #include "cgraph.h"
50 #include "print-tree.h"
51 #include "symbol-summary.h"
52 #include "hsa.h"
53 #include "cfghooks.h"
54 #include "tree-cfg.h"
55 #include "cfgloop.h"
56 #include "cfganal.h"
57 #include "builtins.h"
58 #include "params.h"
59 #include "gomp-constants.h"
60 #include "internal-fn.h"
61 #include "builtins.h"
62 #include "stor-layout.h"
64 /* Print a warning message and set that we have seen an error. */
66 #define HSA_SORRY_ATV(location, message, ...) \
67 do \
68 { \
69 hsa_fail_cfun (); \
70 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
71 HSA_SORRY_MSG)) \
72 inform (location, message, __VA_ARGS__); \
73 } \
74 while (false);
76 /* Same as previous, but highlight a location. */
78 #define HSA_SORRY_AT(location, message) \
79 do \
80 { \
81 hsa_fail_cfun (); \
82 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
83 HSA_SORRY_MSG)) \
84 inform (location, message); \
85 } \
86 while (false);
88 /* Default number of threads used by kernel dispatch. */
90 #define HSA_DEFAULT_NUM_THREADS 64
92 /* Following structures are defined in the final version
93 of HSA specification. */
95 /* HSA queue packet is shadow structure, originally provided by AMD. */
97 struct hsa_queue_packet
99 uint16_t header;
100 uint16_t setup;
101 uint16_t workgroup_size_x;
102 uint16_t workgroup_size_y;
103 uint16_t workgroup_size_z;
104 uint16_t reserved0;
105 uint32_t grid_size_x;
106 uint32_t grid_size_y;
107 uint32_t grid_size_z;
108 uint32_t private_segment_size;
109 uint32_t group_segment_size;
110 uint64_t kernel_object;
111 void *kernarg_address;
112 uint64_t reserved2;
113 uint64_t completion_signal;
116 /* HSA queue is shadow structure, originally provided by AMD. */
118 struct hsa_queue
120 int type;
121 uint32_t features;
122 void *base_address;
123 uint64_t doorbell_signal;
124 uint32_t size;
125 uint32_t reserved1;
126 uint64_t id;
129 /* Alloc pools for allocating basic hsa structures such as operands,
130 instructions and other basic entities. */
131 static object_allocator<hsa_op_address> *hsa_allocp_operand_address;
132 static object_allocator<hsa_op_immed> *hsa_allocp_operand_immed;
133 static object_allocator<hsa_op_reg> *hsa_allocp_operand_reg;
134 static object_allocator<hsa_op_code_list> *hsa_allocp_operand_code_list;
135 static object_allocator<hsa_op_operand_list> *hsa_allocp_operand_operand_list;
136 static object_allocator<hsa_insn_basic> *hsa_allocp_inst_basic;
137 static object_allocator<hsa_insn_phi> *hsa_allocp_inst_phi;
138 static object_allocator<hsa_insn_mem> *hsa_allocp_inst_mem;
139 static object_allocator<hsa_insn_atomic> *hsa_allocp_inst_atomic;
140 static object_allocator<hsa_insn_signal> *hsa_allocp_inst_signal;
141 static object_allocator<hsa_insn_seg> *hsa_allocp_inst_seg;
142 static object_allocator<hsa_insn_cmp> *hsa_allocp_inst_cmp;
143 static object_allocator<hsa_insn_br> *hsa_allocp_inst_br;
144 static object_allocator<hsa_insn_sbr> *hsa_allocp_inst_sbr;
145 static object_allocator<hsa_insn_call> *hsa_allocp_inst_call;
146 static object_allocator<hsa_insn_arg_block> *hsa_allocp_inst_arg_block;
147 static object_allocator<hsa_insn_comment> *hsa_allocp_inst_comment;
148 static object_allocator<hsa_insn_queue> *hsa_allocp_inst_queue;
149 static object_allocator<hsa_insn_srctype> *hsa_allocp_inst_srctype;
150 static object_allocator<hsa_insn_packed> *hsa_allocp_inst_packed;
151 static object_allocator<hsa_insn_cvt> *hsa_allocp_inst_cvt;
152 static object_allocator<hsa_insn_alloca> *hsa_allocp_inst_alloca;
153 static object_allocator<hsa_bb> *hsa_allocp_bb;
155 /* List of pointers to all instructions that come from an object allocator. */
156 static vec <hsa_insn_basic *> hsa_instructions;
158 /* List of pointers to all operands that come from an object allocator. */
159 static vec <hsa_op_base *> hsa_operands;
161 hsa_symbol::hsa_symbol ()
162 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
163 m_directive_offset (0), m_type (BRIG_TYPE_NONE),
164 m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
165 m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
166 m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
171 hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
172 BrigLinkage8_t linkage, bool global_scope_p,
173 BrigAllocation allocation, BrigAlignment8_t align)
174 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
175 m_directive_offset (0), m_type (type), m_segment (segment),
176 m_linkage (linkage), m_dim (0), m_cst_value (NULL),
177 m_global_scope_p (global_scope_p), m_seen_error (false),
178 m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
182 unsigned HOST_WIDE_INT
183 hsa_symbol::total_byte_size ()
185 unsigned HOST_WIDE_INT s
186 = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
187 gcc_assert (s % BITS_PER_UNIT == 0);
188 s /= BITS_PER_UNIT;
190 if (m_dim)
191 s *= m_dim;
193 return s;
196 /* Forward declaration. */
198 static BrigType16_t
199 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
200 bool min32int);
202 void
203 hsa_symbol::fillup_for_decl (tree decl)
205 m_decl = decl;
206 m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
207 if (hsa_seen_error ())
209 m_seen_error = true;
210 return;
213 m_align = MAX (m_align, hsa_natural_alignment (m_type));
216 /* Constructor of class representing global HSA function/kernel information and
217 state. FNDECL is function declaration, KERNEL_P is true if the function
218 is going to become a HSA kernel. If the function has body, SSA_NAMES_COUNT
219 should be set to number of SSA names used in the function.
220 MODIFIED_CFG is set to true in case we modified control-flow graph
221 of the function. */
223 hsa_function_representation::hsa_function_representation
224 (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
225 : m_name (NULL),
226 m_reg_count (0), m_input_args (vNULL),
227 m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
228 m_private_variables (vNULL), m_called_functions (vNULL),
229 m_called_internal_fns (vNULL), m_hbb_count (0),
230 m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
231 m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
232 m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
233 m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
234 m_modified_cfg (modified_cfg)
236 int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;;
237 m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
238 m_ssa_map.safe_grow_cleared (ssa_names_count);
241 /* Constructor of class representing HSA function information that
242 is derived for an internal function. */
243 hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
244 : m_reg_count (0), m_input_args (vNULL),
245 m_output_arg (NULL), m_local_symbols (NULL),
246 m_spill_symbols (vNULL), m_global_symbols (vNULL),
247 m_private_variables (vNULL), m_called_functions (vNULL),
248 m_called_internal_fns (vNULL), m_hbb_count (0),
249 m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
250 m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
251 m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
252 m_ssa_map () {}
254 /* Destructor of class holding function/kernel-wide information and state. */
256 hsa_function_representation::~hsa_function_representation ()
258 /* Kernel names are deallocated at the end of BRIG output when deallocating
259 hsa_decl_kernel_mapping. */
260 if (!m_kern_p || m_seen_error)
261 free (m_name);
263 for (unsigned i = 0; i < m_input_args.length (); i++)
264 delete m_input_args[i];
265 m_input_args.release ();
267 delete m_output_arg;
268 delete m_local_symbols;
270 for (unsigned i = 0; i < m_spill_symbols.length (); i++)
271 delete m_spill_symbols[i];
272 m_spill_symbols.release ();
274 hsa_symbol *sym;
275 for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
276 if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
277 delete sym;
278 m_global_symbols.release ();
280 for (unsigned i = 0; i < m_private_variables.length (); i++)
281 delete m_private_variables[i];
282 m_private_variables.release ();
283 m_called_functions.release ();
284 m_ssa_map.release ();
286 for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
287 delete m_called_internal_fns[i];
290 hsa_op_reg *
291 hsa_function_representation::get_shadow_reg ()
293 /* If we compile a function with kernel dispatch and does not set
294 an optimization level, the function won't be inlined and
295 we return NULL. */
296 if (!m_kern_p)
297 return NULL;
299 if (m_shadow_reg)
300 return m_shadow_reg;
302 /* Append the shadow argument. */
303 hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
304 BRIG_LINKAGE_FUNCTION);
305 m_input_args.safe_push (shadow);
306 shadow->m_name = "hsa_runtime_shadow";
308 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
309 hsa_op_address *addr = new hsa_op_address (shadow);
311 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
312 hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
313 m_shadow_reg = r;
315 return r;
318 bool hsa_function_representation::has_shadow_reg_p ()
320 return m_shadow_reg != NULL;
323 void
324 hsa_function_representation::init_extra_bbs ()
326 hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
327 hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
330 void
331 hsa_function_representation::update_dominance ()
333 if (m_modified_cfg)
335 free_dominance_info (CDI_DOMINATORS);
336 calculate_dominance_info (CDI_DOMINATORS);
340 hsa_symbol *
341 hsa_function_representation::create_hsa_temporary (BrigType16_t type)
343 hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
344 BRIG_LINKAGE_FUNCTION);
345 s->m_name_number = m_temp_symbol_count++;
347 hsa_cfun->m_private_variables.safe_push (s);
348 return s;
351 BrigLinkage8_t
352 hsa_function_representation::get_linkage ()
354 if (m_internal_fn)
355 return BRIG_LINKAGE_PROGRAM;
357 return m_kern_p || TREE_PUBLIC (m_decl) ?
358 BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
361 /* Hash map of simple OMP builtins. */
362 static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
363 = NULL;
365 /* Warning messages for OMP builtins. */
367 #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
368 "lock routines"
369 #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
370 "timing routines"
371 #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
372 "undefined semantics within target regions, support for HSA ignores them"
373 #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
374 "affinity feateres"
376 /* Initialize hash map with simple OMP builtins. */
378 static void
379 hsa_init_simple_builtins ()
381 if (omp_simple_builtins != NULL)
382 return;
384 omp_simple_builtins
385 = new hash_map <nofree_string_hash, omp_simple_builtin> ();
387 omp_simple_builtin omp_builtins[] =
389 omp_simple_builtin ("omp_get_initial_device", NULL, false,
390 new hsa_op_immed (GOMP_DEVICE_HOST,
391 (BrigType16_t) BRIG_TYPE_S32)),
392 omp_simple_builtin ("omp_is_initial_device", NULL, false,
393 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
394 omp_simple_builtin ("omp_get_dynamic", NULL, false,
395 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
396 omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
397 omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
398 omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
399 true),
400 omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
401 true),
402 omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
403 omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
404 omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
405 omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
406 omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
407 omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
408 omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
409 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
410 omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
411 omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
412 false,
413 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
414 omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
415 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
416 omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
417 false,
418 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
419 omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
420 false,
421 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
422 omp_simple_builtin ("omp_target_disassociate_ptr",
423 HSA_WARN_MEMORY_ROUTINE,
424 false,
425 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
426 omp_simple_builtin ("omp_set_max_active_levels",
427 "Support for HSA only allows only one active level, "
428 "call to omp_set_max_active_levels will be ignored "
429 "in the generated HSAIL",
430 false, NULL),
431 omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
432 new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
433 omp_simple_builtin ("omp_in_final", NULL, false,
434 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
435 omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
436 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
437 omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
438 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
439 omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
440 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
441 omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
442 NULL),
443 omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
444 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
445 omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
446 false,
447 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
448 omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
449 false, NULL),
450 omp_simple_builtin ("omp_set_default_device",
451 "omp_set_default_device has undefined semantics "
452 "within target regions, support for HSA ignores it",
453 false, NULL),
454 omp_simple_builtin ("omp_get_default_device",
455 "omp_get_default_device has undefined semantics "
456 "within target regions, support for HSA ignores it",
457 false,
458 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
459 omp_simple_builtin ("omp_get_num_devices",
460 "omp_get_num_devices has undefined semantics "
461 "within target regions, support for HSA ignores it",
462 false,
463 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
464 omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
465 omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
466 omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
467 omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
468 omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
469 omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
470 omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
471 omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
472 omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
473 omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
476 unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
478 for (unsigned i = 0; i < count; i++)
479 omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
482 /* Allocate HSA structures that we need only while generating with this. */
484 static void
485 hsa_init_data_for_cfun ()
487 hsa_init_compilation_unit_data ();
488 hsa_allocp_operand_address
489 = new object_allocator<hsa_op_address> ("HSA address operands");
490 hsa_allocp_operand_immed
491 = new object_allocator<hsa_op_immed> ("HSA immediate operands");
492 hsa_allocp_operand_reg
493 = new object_allocator<hsa_op_reg> ("HSA register operands");
494 hsa_allocp_operand_code_list
495 = new object_allocator<hsa_op_code_list> ("HSA code list operands");
496 hsa_allocp_operand_operand_list
497 = new object_allocator<hsa_op_operand_list> ("HSA operand list operands");
498 hsa_allocp_inst_basic
499 = new object_allocator<hsa_insn_basic> ("HSA basic instructions");
500 hsa_allocp_inst_phi
501 = new object_allocator<hsa_insn_phi> ("HSA phi operands");
502 hsa_allocp_inst_mem
503 = new object_allocator<hsa_insn_mem> ("HSA memory instructions");
504 hsa_allocp_inst_atomic
505 = new object_allocator<hsa_insn_atomic> ("HSA atomic instructions");
506 hsa_allocp_inst_signal
507 = new object_allocator<hsa_insn_signal> ("HSA signal instructions");
508 hsa_allocp_inst_seg
509 = new object_allocator<hsa_insn_seg> ("HSA segment conversion "
510 "instructions");
511 hsa_allocp_inst_cmp
512 = new object_allocator<hsa_insn_cmp> ("HSA comparison instructions");
513 hsa_allocp_inst_br
514 = new object_allocator<hsa_insn_br> ("HSA branching instructions");
515 hsa_allocp_inst_sbr
516 = new object_allocator<hsa_insn_sbr> ("HSA switch branching instructions");
517 hsa_allocp_inst_call
518 = new object_allocator<hsa_insn_call> ("HSA call instructions");
519 hsa_allocp_inst_arg_block
520 = new object_allocator<hsa_insn_arg_block> ("HSA arg block instructions");
521 hsa_allocp_inst_comment
522 = new object_allocator<hsa_insn_comment> ("HSA comment instructions");
523 hsa_allocp_inst_queue
524 = new object_allocator<hsa_insn_queue> ("HSA queue instructions");
525 hsa_allocp_inst_srctype
526 = new object_allocator<hsa_insn_srctype> ("HSA source type instructions");
527 hsa_allocp_inst_packed
528 = new object_allocator<hsa_insn_packed> ("HSA packed instructions");
529 hsa_allocp_inst_cvt
530 = new object_allocator<hsa_insn_cvt> ("HSA convert instructions");
531 hsa_allocp_inst_alloca
532 = new object_allocator<hsa_insn_alloca> ("HSA alloca instructions");
533 hsa_allocp_bb = new object_allocator<hsa_bb> ("HSA basic blocks");
536 /* Deinitialize HSA subsystem and free all allocated memory. */
538 static void
539 hsa_deinit_data_for_cfun (void)
541 basic_block bb;
543 FOR_ALL_BB_FN (bb, cfun)
544 if (bb->aux)
546 hsa_bb *hbb = hsa_bb_for_bb (bb);
547 hbb->~hsa_bb ();
548 bb->aux = NULL;
551 for (unsigned int i = 0; i < hsa_operands.length (); i++)
552 hsa_destroy_operand (hsa_operands[i]);
554 hsa_operands.release ();
556 for (unsigned i = 0; i < hsa_instructions.length (); i++)
557 hsa_destroy_insn (hsa_instructions[i]);
559 hsa_instructions.release ();
561 if (omp_simple_builtins != NULL)
563 delete omp_simple_builtins;
564 omp_simple_builtins = NULL;
567 delete hsa_allocp_operand_address;
568 delete hsa_allocp_operand_immed;
569 delete hsa_allocp_operand_reg;
570 delete hsa_allocp_operand_code_list;
571 delete hsa_allocp_operand_operand_list;
572 delete hsa_allocp_inst_basic;
573 delete hsa_allocp_inst_phi;
574 delete hsa_allocp_inst_atomic;
575 delete hsa_allocp_inst_mem;
576 delete hsa_allocp_inst_signal;
577 delete hsa_allocp_inst_seg;
578 delete hsa_allocp_inst_cmp;
579 delete hsa_allocp_inst_br;
580 delete hsa_allocp_inst_sbr;
581 delete hsa_allocp_inst_call;
582 delete hsa_allocp_inst_arg_block;
583 delete hsa_allocp_inst_comment;
584 delete hsa_allocp_inst_queue;
585 delete hsa_allocp_inst_srctype;
586 delete hsa_allocp_inst_packed;
587 delete hsa_allocp_inst_cvt;
588 delete hsa_allocp_inst_alloca;
589 delete hsa_allocp_bb;
590 delete hsa_cfun;
593 /* Return the type which holds addresses in the given SEGMENT. */
595 static BrigType16_t
596 hsa_get_segment_addr_type (BrigSegment8_t segment)
598 switch (segment)
600 case BRIG_SEGMENT_NONE:
601 gcc_unreachable ();
603 case BRIG_SEGMENT_FLAT:
604 case BRIG_SEGMENT_GLOBAL:
605 case BRIG_SEGMENT_READONLY:
606 case BRIG_SEGMENT_KERNARG:
607 return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
609 case BRIG_SEGMENT_GROUP:
610 case BRIG_SEGMENT_PRIVATE:
611 case BRIG_SEGMENT_SPILL:
612 case BRIG_SEGMENT_ARG:
613 return BRIG_TYPE_U32;
615 gcc_unreachable ();
618 /* Return integer brig type according to provided SIZE in bytes. If SIGN
619 is set to true, return signed integer type. */
621 static BrigType16_t
622 get_integer_type_by_bytes (unsigned size, bool sign)
624 if (sign)
625 switch (size)
627 case 1:
628 return BRIG_TYPE_S8;
629 case 2:
630 return BRIG_TYPE_S16;
631 case 4:
632 return BRIG_TYPE_S32;
633 case 8:
634 return BRIG_TYPE_S64;
635 default:
636 break;
638 else
639 switch (size)
641 case 1:
642 return BRIG_TYPE_U8;
643 case 2:
644 return BRIG_TYPE_U16;
645 case 4:
646 return BRIG_TYPE_U32;
647 case 8:
648 return BRIG_TYPE_U64;
649 default:
650 break;
653 return 0;
656 /* Return HSA type for tree TYPE, which has to fit into BrigType16_t. Pointers
657 are assumed to use flat addressing. If min32int is true, always expand
658 integer types to one that has at least 32 bits. */
660 static BrigType16_t
661 hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
663 HOST_WIDE_INT bsize;
664 const_tree base;
665 BrigType16_t res = BRIG_TYPE_NONE;
667 gcc_checking_assert (TYPE_P (type));
668 gcc_checking_assert (!AGGREGATE_TYPE_P (type));
669 if (POINTER_TYPE_P (type))
670 return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
672 if (TREE_CODE (type) == VECTOR_TYPE || TREE_CODE (type) == COMPLEX_TYPE)
673 base = TREE_TYPE (type);
674 else
675 base = type;
677 if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
679 HSA_SORRY_ATV (EXPR_LOCATION (type),
680 "support for HSA does not implement huge or "
681 "variable-sized type %T", type);
682 return res;
685 bsize = tree_to_uhwi (TYPE_SIZE (base));
686 unsigned byte_size = bsize / BITS_PER_UNIT;
687 if (INTEGRAL_TYPE_P (base))
688 res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
689 else if (SCALAR_FLOAT_TYPE_P (base))
691 switch (bsize)
693 case 16:
694 res = BRIG_TYPE_F16;
695 break;
696 case 32:
697 res = BRIG_TYPE_F32;
698 break;
699 case 64:
700 res = BRIG_TYPE_F64;
701 break;
702 default:
703 break;
707 if (res == BRIG_TYPE_NONE)
709 HSA_SORRY_ATV (EXPR_LOCATION (type),
710 "support for HSA does not implement type %T", type);
711 return res;
714 if (TREE_CODE (type) == VECTOR_TYPE)
716 HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
718 if (bsize == tsize)
720 HSA_SORRY_ATV (EXPR_LOCATION (type),
721 "support for HSA does not implement a vector type "
722 "where a type and unit size are equal: %T", type);
723 return res;
726 switch (tsize)
728 case 32:
729 res |= BRIG_TYPE_PACK_32;
730 break;
731 case 64:
732 res |= BRIG_TYPE_PACK_64;
733 break;
734 case 128:
735 res |= BRIG_TYPE_PACK_128;
736 break;
737 default:
738 HSA_SORRY_ATV (EXPR_LOCATION (type),
739 "support for HSA does not implement type %T", type);
743 if (min32int)
745 /* Registers/immediate operands can only be 32bit or more except for
746 f16. */
747 if (res == BRIG_TYPE_U8 || res == BRIG_TYPE_U16)
748 res = BRIG_TYPE_U32;
749 else if (res == BRIG_TYPE_S8 || res == BRIG_TYPE_S16)
750 res = BRIG_TYPE_S32;
753 if (TREE_CODE (type) == COMPLEX_TYPE)
755 unsigned bsize = 2 * hsa_type_bit_size (res);
756 res = hsa_bittype_for_bitsize (bsize);
759 return res;
762 /* Returns the BRIG type we need to load/store entities of TYPE. */
764 static BrigType16_t
765 mem_type_for_type (BrigType16_t type)
767 /* HSA has non-intuitive constraints on load/store types. If it's
768 a bit-type it _must_ be B128, if it's not a bit-type it must be
769 64bit max. So for loading entities of 128 bits (e.g. vectors)
770 we have to to B128, while for loading the rest we have to use the
771 input type (??? or maybe also flattened to a equally sized non-vector
772 unsigned type?). */
773 if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
774 return BRIG_TYPE_B128;
775 else if (hsa_btype_p (type) || hsa_type_packed_p (type))
777 unsigned bitsize = hsa_type_bit_size (type);
778 if (bitsize < 128)
779 return hsa_uint_for_bitsize (bitsize);
780 else
781 return hsa_bittype_for_bitsize (bitsize);
783 return type;
786 /* Return HSA type for tree TYPE. If it cannot fit into BrigType16_t, some
787 kind of array will be generated, setting DIM appropriately. Otherwise, it
788 will be set to zero. */
790 static BrigType16_t
791 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
792 bool min32int = false)
794 gcc_checking_assert (TYPE_P (type));
795 if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
797 HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
798 "implement huge or variable-sized type %T", type);
799 return BRIG_TYPE_NONE;
802 if (RECORD_OR_UNION_TYPE_P (type))
804 if (dim_p)
805 *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
806 return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
809 if (TREE_CODE (type) == ARRAY_TYPE)
811 /* We try to be nice and use the real base-type when this is an array of
812 scalars and only resort to an array of bytes if the type is more
813 complex. */
815 unsigned HOST_WIDE_INT dim = 1;
817 while (TREE_CODE (type) == ARRAY_TYPE)
819 tree domain = TYPE_DOMAIN (type);
820 if (!TYPE_MIN_VALUE (domain)
821 || !TYPE_MAX_VALUE (domain)
822 || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
823 || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
825 HSA_SORRY_ATV (EXPR_LOCATION (type),
826 "support for HSA does not implement array %T with "
827 "unknown bounds", type);
828 return BRIG_TYPE_NONE;
830 HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
831 HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
832 dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
833 type = TREE_TYPE (type);
836 BrigType16_t res;
837 if (RECORD_OR_UNION_TYPE_P (type))
839 dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
840 res = BRIG_TYPE_U8;
842 else
843 res = hsa_type_for_scalar_tree_type (type, false);
845 if (dim_p)
846 *dim_p = dim;
847 return res | BRIG_TYPE_ARRAY;
850 /* Scalar case: */
851 if (dim_p)
852 *dim_p = 0;
854 return hsa_type_for_scalar_tree_type (type, min32int);
857 /* Returns true if converting from STYPE into DTYPE needs the _CVT
858 opcode. If false a normal _MOV is enough. */
860 static bool
861 hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
863 if (hsa_btype_p (dtype))
864 return false;
866 /* float <-> int conversions are real converts. */
867 if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
868 return true;
869 /* When both types have different size, then we need CVT as well. */
870 if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
871 return true;
872 return false;
875 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
876 or lookup the hsa_structure corresponding to a PARM_DECL. */
878 static hsa_symbol *
879 get_symbol_for_decl (tree decl)
881 hsa_symbol **slot;
882 hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
884 gcc_assert (TREE_CODE (decl) == PARM_DECL
885 || TREE_CODE (decl) == RESULT_DECL
886 || VAR_P (decl));
888 dummy.m_decl = decl;
890 bool is_in_global_vars = VAR_P (decl) && is_global_var (decl);
892 if (is_in_global_vars)
893 slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
894 else
895 slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
897 gcc_checking_assert (slot);
898 if (*slot)
900 hsa_symbol *sym = (*slot);
902 /* If the symbol is problematic, mark current function also as
903 problematic. */
904 if (sym->m_seen_error)
905 hsa_fail_cfun ();
907 /* PR hsa/70234: If a global variable was marked to be emitted,
908 but HSAIL generation of a function using the variable fails,
909 we should retry to emit the variable in context of a different
910 function.
912 Iterate elements whether a symbol is already in m_global_symbols
913 of not. */
914 if (is_in_global_vars && !sym->m_emitted_to_brig)
916 for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
917 if (hsa_cfun->m_global_symbols[i] == sym)
918 return *slot;
919 hsa_cfun->m_global_symbols.safe_push (sym);
922 return *slot;
924 else
926 hsa_symbol *sym;
927 gcc_assert (VAR_P (decl));
928 BrigAlignment8_t align = hsa_object_alignment (decl);
930 if (is_in_global_vars)
932 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
933 BRIG_LINKAGE_PROGRAM, true,
934 BRIG_ALLOCATION_PROGRAM, align);
935 hsa_cfun->m_global_symbols.safe_push (sym);
936 sym->fillup_for_decl (decl);
937 if (sym->m_align > align)
939 sym->m_seen_error = true;
940 HSA_SORRY_ATV (EXPR_LOCATION (decl),
941 "HSA specification requires that %E is at least "
942 "naturally aligned", decl);
945 else
947 /* As generation of efficient memory copy instructions relies
948 on alignment greater or equal to 8 bytes,
949 we need to increase alignment of all aggregate types.. */
950 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
951 align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
953 /* PARM_DECL and RESULT_DECL should be already in m_local_symbols. */
954 gcc_assert (VAR_P (decl));
956 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_PRIVATE,
957 BRIG_LINKAGE_FUNCTION);
958 sym->m_align = align;
959 sym->fillup_for_decl (decl);
960 hsa_cfun->m_private_variables.safe_push (sym);
963 sym->m_name = hsa_get_declaration_name (decl);
964 *slot = sym;
965 return sym;
969 /* For a given HSA function declaration, return a host
970 function declaration. */
972 tree
973 hsa_get_host_function (tree decl)
975 hsa_function_summary *s
976 = hsa_summaries->get (cgraph_node::get_create (decl));
977 gcc_assert (s->m_kind != HSA_NONE);
978 gcc_assert (s->m_gpu_implementation_p);
980 return s->m_binded_function->decl;
983 /* Return true if function DECL has a host equivalent function. */
985 static char *
986 get_brig_function_name (tree decl)
988 tree d = decl;
990 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
991 if (s->m_kind != HSA_NONE && s->m_gpu_implementation_p)
992 d = s->m_binded_function->decl;
994 /* IPA split can create a function that has no host equivalent. */
995 if (d == NULL)
996 d = decl;
998 char *name = xstrdup (hsa_get_declaration_name (d));
999 hsa_sanitize_name (name);
1001 return name;
1004 /* Create a spill symbol of type TYPE. */
1006 hsa_symbol *
1007 hsa_get_spill_symbol (BrigType16_t type)
1009 hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
1010 BRIG_LINKAGE_FUNCTION);
1011 hsa_cfun->m_spill_symbols.safe_push (sym);
1012 return sym;
1015 /* Create a symbol for a read-only string constant. */
1016 hsa_symbol *
1017 hsa_get_string_cst_symbol (tree string_cst)
1019 gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
1021 hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
1022 if (slot)
1023 return *slot;
1025 hsa_op_immed *cst = new hsa_op_immed (string_cst);
1026 hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
1027 BRIG_LINKAGE_MODULE, true,
1028 BRIG_ALLOCATION_AGENT);
1029 sym->m_cst_value = cst;
1030 sym->m_dim = TREE_STRING_LENGTH (string_cst);
1031 sym->m_name_number = hsa_cfun->m_global_symbols.length ();
1033 hsa_cfun->m_global_symbols.safe_push (sym);
1034 hsa_cfun->m_string_constants_map.put (string_cst, sym);
1035 return sym;
1038 /* Constructor of the ancestor of all operands. K is BRIG kind that identified
1039 what the operator is. */
1041 hsa_op_base::hsa_op_base (BrigKind16_t k)
1042 : m_next (NULL), m_brig_op_offset (0), m_kind (k)
1044 hsa_operands.safe_push (this);
1047 /* Constructor of ancestor of all operands which have a type. K is BRIG kind
1048 that identified what the operator is. T is the type of the operator. */
1050 hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
1051 : hsa_op_base (k), m_type (t)
1055 hsa_op_with_type *
1056 hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
1058 if (m_type == dtype)
1059 return this;
1061 hsa_op_reg *dest;
1063 if (hsa_needs_cvt (dtype, m_type))
1065 dest = new hsa_op_reg (dtype);
1066 hbb->append_insn (new hsa_insn_cvt (dest, this));
1068 else
1070 dest = new hsa_op_reg (m_type);
1071 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV,
1072 dest->m_type, dest, this));
1074 /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
1075 type of the operand must be same as type of the instruction. */
1076 dest->m_type = dtype;
1079 return dest;
1082 /* Constructor of class representing HSA immediate values. TREE_VAL is the
1083 tree representation of the immediate value. If min32int is true,
1084 always expand integer types to one that has at least 32 bits. */
1086 hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
1087 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
1088 hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
1089 min32int))
1091 if (hsa_seen_error ())
1092 return;
1094 gcc_checking_assert ((is_gimple_min_invariant (tree_val)
1095 && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
1096 || TREE_CODE (tree_val) == INTEGER_CST))
1097 || TREE_CODE (tree_val) == CONSTRUCTOR);
1098 m_tree_value = tree_val;
1100 /* Verify that all elements of a constructor are constants. */
1101 if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
1102 for (unsigned i = 0; i < CONSTRUCTOR_NELTS (m_tree_value); i++)
1104 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
1105 if (!CONSTANT_CLASS_P (v))
1107 HSA_SORRY_AT (EXPR_LOCATION (tree_val),
1108 "HSA ctor should have only constants");
1109 return;
1114 /* Constructor of class representing HSA immediate values. INTEGER_VALUE is the
1115 integer representation of the immediate value. TYPE is BRIG type. */
1117 hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
1118 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
1119 m_tree_value (NULL)
1121 gcc_assert (hsa_type_integer_p (type));
1122 m_int_value = integer_value;
1125 hsa_op_immed::hsa_op_immed ()
1126 : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
1130 /* New operator to allocate immediate operands from pool alloc. */
1132 void *
1133 hsa_op_immed::operator new (size_t)
1135 return hsa_allocp_operand_immed->allocate_raw ();
1138 /* Destructor. */
1140 hsa_op_immed::~hsa_op_immed ()
1144 /* Change type of the immediate value to T. */
1146 void
1147 hsa_op_immed::set_type (BrigType16_t t)
1149 m_type = t;
1152 /* Constructor of class representing HSA registers and pseudo-registers. T is
1153 the BRIG type of the new register. */
1155 hsa_op_reg::hsa_op_reg (BrigType16_t t)
1156 : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
1157 m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
1158 m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
1162 /* New operator to allocate a register from pool alloc. */
1164 void *
1165 hsa_op_reg::operator new (size_t)
1167 return hsa_allocp_operand_reg->allocate_raw ();
1170 /* Verify register operand. */
1172 void
1173 hsa_op_reg::verify_ssa ()
1175 /* Verify that each HSA register has a definition assigned.
1176 Exceptions are VAR_DECL and PARM_DECL that are a default
1177 definition. */
1178 gcc_checking_assert (m_def_insn
1179 || (m_gimple_ssa != NULL
1180 && (!SSA_NAME_VAR (m_gimple_ssa)
1181 || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
1182 != PARM_DECL))
1183 && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
1185 /* Verify that every use of the register is really present
1186 in an instruction. */
1187 for (unsigned i = 0; i < m_uses.length (); i++)
1189 hsa_insn_basic *use = m_uses[i];
1191 bool is_visited = false;
1192 for (unsigned j = 0; j < use->operand_count (); j++)
1194 hsa_op_base *u = use->get_op (j);
1195 hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
1196 if (addr && addr->m_reg)
1197 u = addr->m_reg;
1199 if (u == this)
1201 bool r = !addr && use->op_output_p (j);
1203 if (r)
1205 error ("HSA SSA name defined by instruction that is supposed "
1206 "to be using it");
1207 debug_hsa_operand (this);
1208 debug_hsa_insn (use);
1209 internal_error ("HSA SSA verification failed");
1212 is_visited = true;
1216 if (!is_visited)
1218 error ("HSA SSA name not among operands of instruction that is "
1219 "supposed to use it");
1220 debug_hsa_operand (this);
1221 debug_hsa_insn (use);
1222 internal_error ("HSA SSA verification failed");
1227 hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
1228 HOST_WIDE_INT offset)
1229 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
1230 m_imm_offset (offset)
1234 hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
1235 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
1236 m_imm_offset (offset)
1240 hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
1241 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
1242 m_imm_offset (offset)
1246 /* New operator to allocate address operands from pool alloc. */
1248 void *
1249 hsa_op_address::operator new (size_t)
1251 return hsa_allocp_operand_address->allocate_raw ();
1254 /* Constructor of an operand referring to HSAIL code. */
1256 hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
1257 m_directive_offset (0)
1261 /* Constructor of an operand representing a code list. Set it up so that it
1262 can contain ELEMENTS number of elements. */
1264 hsa_op_code_list::hsa_op_code_list (unsigned elements)
1265 : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
1267 m_offsets.create (1);
1268 m_offsets.safe_grow_cleared (elements);
1271 /* New operator to allocate code list operands from pool alloc. */
1273 void *
1274 hsa_op_code_list::operator new (size_t)
1276 return hsa_allocp_operand_code_list->allocate_raw ();
1279 /* Constructor of an operand representing an operand list.
1280 Set it up so that it can contain ELEMENTS number of elements. */
1282 hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
1283 : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
1285 m_offsets.create (elements);
1286 m_offsets.safe_grow (elements);
1289 /* New operator to allocate operand list operands from pool alloc. */
1291 void *
1292 hsa_op_operand_list::operator new (size_t)
1294 return hsa_allocp_operand_operand_list->allocate_raw ();
1297 hsa_op_operand_list::~hsa_op_operand_list ()
1299 m_offsets.release ();
1303 hsa_op_reg *
1304 hsa_function_representation::reg_for_gimple_ssa (tree ssa)
1306 hsa_op_reg *hreg;
1308 gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
1309 if (m_ssa_map[SSA_NAME_VERSION (ssa)])
1310 return m_ssa_map[SSA_NAME_VERSION (ssa)];
1312 hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
1313 true));
1314 hreg->m_gimple_ssa = ssa;
1315 m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
1317 return hreg;
1320 void
1321 hsa_op_reg::set_definition (hsa_insn_basic *insn)
1323 if (hsa_cfun->m_in_ssa)
1325 gcc_checking_assert (!m_def_insn);
1326 m_def_insn = insn;
1328 else
1329 m_def_insn = NULL;
1332 /* Constructor of the class which is the bases of all instructions and directly
1333 represents the most basic ones. NOPS is the number of operands that the
1334 operand vector will contain (and which will be cleared). OP is the opcode
1335 of the instruction. This constructor does not set type. */
1337 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
1338 : m_prev (NULL),
1339 m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
1340 m_type (BRIG_TYPE_NONE), m_brig_offset (0)
1342 if (nops > 0)
1343 m_operands.safe_grow_cleared (nops);
1345 hsa_instructions.safe_push (this);
1348 /* Make OP the operand number INDEX of operands of this instruction. If OP is a
1349 register or an address containing a register, then either set the definition
1350 of the register to this instruction if it an output operand or add this
1351 instruction to the uses if it is an input one. */
1353 void
1354 hsa_insn_basic::set_op (int index, hsa_op_base *op)
1356 /* Each address operand is always use. */
1357 hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
1358 if (addr && addr->m_reg)
1359 addr->m_reg->m_uses.safe_push (this);
1360 else
1362 hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
1363 if (reg)
1365 if (op_output_p (index))
1366 reg->set_definition (this);
1367 else
1368 reg->m_uses.safe_push (this);
1372 m_operands[index] = op;
1375 /* Get INDEX-th operand of the instruction. */
1377 hsa_op_base *
1378 hsa_insn_basic::get_op (int index)
1380 return m_operands[index];
1383 /* Get address of INDEX-th operand of the instruction. */
1385 hsa_op_base **
1386 hsa_insn_basic::get_op_addr (int index)
1388 return &m_operands[index];
1391 /* Get number of operands of the instruction. */
1392 unsigned int
1393 hsa_insn_basic::operand_count ()
1395 return m_operands.length ();
1398 /* Constructor of the class which is the bases of all instructions and directly
1399 represents the most basic ones. NOPS is the number of operands that the
1400 operand vector will contain (and which will be cleared). OPC is the opcode
1401 of the instruction, T is the type of the instruction. */
1403 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
1404 hsa_op_base *arg0, hsa_op_base *arg1,
1405 hsa_op_base *arg2, hsa_op_base *arg3)
1406 : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
1407 m_type (t), m_brig_offset (0)
1409 if (nops > 0)
1410 m_operands.safe_grow_cleared (nops);
1412 if (arg0 != NULL)
1414 gcc_checking_assert (nops >= 1);
1415 set_op (0, arg0);
1418 if (arg1 != NULL)
1420 gcc_checking_assert (nops >= 2);
1421 set_op (1, arg1);
1424 if (arg2 != NULL)
1426 gcc_checking_assert (nops >= 3);
1427 set_op (2, arg2);
1430 if (arg3 != NULL)
1432 gcc_checking_assert (nops >= 4);
1433 set_op (3, arg3);
1436 hsa_instructions.safe_push (this);
1439 /* New operator to allocate basic instruction from pool alloc. */
1441 void *
1442 hsa_insn_basic::operator new (size_t)
1444 return hsa_allocp_inst_basic->allocate_raw ();
1447 /* Verify the instruction. */
1449 void
1450 hsa_insn_basic::verify ()
1452 hsa_op_address *addr;
1453 hsa_op_reg *reg;
1455 /* Iterate all register operands and verify that the instruction
1456 is set in uses of the register. */
1457 for (unsigned i = 0; i < operand_count (); i++)
1459 hsa_op_base *use = get_op (i);
1461 if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
1463 gcc_assert (addr->m_reg->m_def_insn != this);
1464 use = addr->m_reg;
1467 if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
1469 unsigned j;
1470 for (j = 0; j < reg->m_uses.length (); j++)
1472 if (reg->m_uses[j] == this)
1473 break;
1476 if (j == reg->m_uses.length ())
1478 error ("HSA instruction uses a register but is not among "
1479 "recorded register uses");
1480 debug_hsa_operand (reg);
1481 debug_hsa_insn (this);
1482 internal_error ("HSA instruction verification failed");
1488 /* Constructor of an instruction representing a PHI node. NOPS is the number
1489 of operands (equal to the number of predecessors). */
1491 hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
1492 : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
1494 dst->set_definition (this);
1497 /* New operator to allocate PHI instruction from pool alloc. */
1499 void *
1500 hsa_insn_phi::operator new (size_t)
1502 return hsa_allocp_inst_phi->allocate_raw ();
1505 /* Constructor of class representing instruction for conditional jump, CTRL is
1506 the control register determining whether the jump will be carried out, the
1507 new instruction is automatically added to its uses list. */
1509 hsa_insn_br::hsa_insn_br (hsa_op_reg *ctrl)
1510 : hsa_insn_basic (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, ctrl),
1511 m_width (BRIG_WIDTH_1)
1515 /* New operator to allocate branch instruction from pool alloc. */
1517 void *
1518 hsa_insn_br::operator new (size_t)
1520 return hsa_allocp_inst_br->allocate_raw ();
1523 /* Constructor of class representing instruction for switch jump, CTRL is
1524 the index register. */
1526 hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
1527 : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
1528 m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
1529 m_label_code_list (new hsa_op_code_list (jump_count))
1533 /* New operator to allocate switch branch instruction from pool alloc. */
1535 void *
1536 hsa_insn_sbr::operator new (size_t)
1538 return hsa_allocp_inst_sbr->allocate_raw ();
1541 /* Replace all occurrences of OLD_BB with NEW_BB in the statements
1542 jump table. */
1544 void
1545 hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
1547 for (unsigned i = 0; i < m_jump_table.length (); i++)
1548 if (m_jump_table[i] == old_bb)
1549 m_jump_table[i] = new_bb;
1552 hsa_insn_sbr::~hsa_insn_sbr ()
1554 m_jump_table.release ();
1557 /* Constructor of comparison instruction. CMP is the comparison operation and T
1558 is the result type. */
1560 hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
1561 hsa_op_base *arg0, hsa_op_base *arg1,
1562 hsa_op_base *arg2)
1563 : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
1567 /* New operator to allocate compare instruction from pool alloc. */
1569 void *
1570 hsa_insn_cmp::operator new (size_t)
1572 return hsa_allocp_inst_cmp->allocate_raw ();
1575 /* Constructor of classes representing memory accesses. OPC is the opcode (must
1576 be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type. The instruction
1577 operands are provided as ARG0 and ARG1. */
1579 hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
1580 hsa_op_base *arg1)
1581 : hsa_insn_basic (2, opc, t, arg0, arg1),
1582 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1584 gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
1587 /* Constructor for descendants allowing different opcodes and number of
1588 operands, it passes its arguments directly to hsa_insn_basic
1589 constructor. The instruction operands are provided as ARG[0-3]. */
1592 hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
1593 hsa_op_base *arg0, hsa_op_base *arg1,
1594 hsa_op_base *arg2, hsa_op_base *arg3)
1595 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1596 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1600 /* New operator to allocate memory instruction from pool alloc. */
1602 void *
1603 hsa_insn_mem::operator new (size_t)
1605 return hsa_allocp_inst_mem->allocate_raw ();
1608 /* Constructor of class representing atomic instructions and signals. OPC is
1609 the principal opcode, aop is the specific atomic operation opcode. T is the
1610 type of the instruction. The instruction operands
1611 are provided as ARG[0-3]. */
1613 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
1614 enum BrigAtomicOperation aop,
1615 BrigType16_t t, BrigMemoryOrder memorder,
1616 hsa_op_base *arg0,
1617 hsa_op_base *arg1, hsa_op_base *arg2,
1618 hsa_op_base *arg3)
1619 : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
1620 m_memoryorder (memorder),
1621 m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
1623 gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
1624 opc == BRIG_OPCODE_ATOMIC ||
1625 opc == BRIG_OPCODE_SIGNAL ||
1626 opc == BRIG_OPCODE_SIGNALNORET);
1629 /* New operator to allocate signal instruction from pool alloc. */
1631 void *
1632 hsa_insn_atomic::operator new (size_t)
1634 return hsa_allocp_inst_atomic->allocate_raw ();
1637 /* Constructor of class representing signal instructions. OPC is the prinicpal
1638 opcode, sop is the specific signal operation opcode. T is the type of the
1639 instruction. The instruction operands are provided as ARG[0-3]. */
1641 hsa_insn_signal::hsa_insn_signal (int nops, int opc,
1642 enum BrigAtomicOperation sop,
1643 BrigType16_t t, hsa_op_base *arg0,
1644 hsa_op_base *arg1, hsa_op_base *arg2,
1645 hsa_op_base *arg3)
1646 : hsa_insn_atomic (nops, opc, sop, t, BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE,
1647 arg0, arg1, arg2, arg3)
1651 /* New operator to allocate signal instruction from pool alloc. */
1653 void *
1654 hsa_insn_signal::operator new (size_t)
1656 return hsa_allocp_inst_signal->allocate_raw ();
1659 /* Constructor of class representing segment conversion instructions. OPC is
1660 the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS. DEST
1661 and SRCT are destination and source types respectively, SEG is the segment
1662 we are converting to or from. The instruction operands are
1663 provided as ARG0 and ARG1. */
1665 hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
1666 BrigSegment8_t seg, hsa_op_base *arg0,
1667 hsa_op_base *arg1)
1668 : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
1669 m_segment (seg)
1671 gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
1674 /* New operator to allocate address conversion instruction from pool alloc. */
1676 void *
1677 hsa_insn_seg::operator new (size_t)
1679 return hsa_allocp_inst_seg->allocate_raw ();
1682 /* Constructor of class representing a call instruction. CALLEE is the tree
1683 representation of the function being called. */
1685 hsa_insn_call::hsa_insn_call (tree callee)
1686 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
1687 m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
1691 hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
1692 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
1693 m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
1694 m_result_code_list (NULL)
1698 /* New operator to allocate call instruction from pool alloc. */
1700 void *
1701 hsa_insn_call::operator new (size_t)
1703 return hsa_allocp_inst_call->allocate_raw ();
1706 hsa_insn_call::~hsa_insn_call ()
1708 for (unsigned i = 0; i < m_input_args.length (); i++)
1709 delete m_input_args[i];
1711 delete m_output_arg;
1713 m_input_args.release ();
1714 m_input_arg_insns.release ();
1717 /* Constructor of class representing the argument block required to invoke
1718 a call in HSAIL. */
1719 hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
1720 hsa_insn_call * call)
1721 : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
1722 m_call_insn (call)
1726 /* New operator to allocate argument block instruction from pool alloc. */
1728 void *
1729 hsa_insn_arg_block::operator new (size_t)
1731 return hsa_allocp_inst_arg_block->allocate_raw ();
1734 hsa_insn_comment::hsa_insn_comment (const char *s)
1735 : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
1737 unsigned l = strlen (s);
1739 /* Append '// ' to the string. */
1740 char *buf = XNEWVEC (char, l + 4);
1741 sprintf (buf, "// %s", s);
1742 m_comment = buf;
1745 /* New operator to allocate comment instruction from pool alloc. */
1747 void *
1748 hsa_insn_comment::operator new (size_t)
1750 return hsa_allocp_inst_comment->allocate_raw ();
1753 hsa_insn_comment::~hsa_insn_comment ()
1755 gcc_checking_assert (m_comment);
1756 free (m_comment);
1757 m_comment = NULL;
1760 /* Constructor of class representing the queue instruction in HSAIL. */
1761 hsa_insn_queue::hsa_insn_queue (int nops, BrigOpcode opcode)
1762 : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64)
1766 /* New operator to allocate source type instruction from pool alloc. */
1768 void *
1769 hsa_insn_srctype::operator new (size_t)
1771 return hsa_allocp_inst_srctype->allocate_raw ();
1774 /* Constructor of class representing the source type instruction in HSAIL. */
1776 hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
1777 BrigType16_t destt, BrigType16_t srct,
1778 hsa_op_base *arg0, hsa_op_base *arg1,
1779 hsa_op_base *arg2 = NULL)
1780 : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
1781 m_source_type (srct)
1784 /* New operator to allocate packed instruction from pool alloc. */
1786 void *
1787 hsa_insn_packed::operator new (size_t)
1789 return hsa_allocp_inst_packed->allocate_raw ();
1792 /* Constructor of class representing the packed instruction in HSAIL. */
1794 hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
1795 BrigType16_t destt, BrigType16_t srct,
1796 hsa_op_base *arg0, hsa_op_base *arg1,
1797 hsa_op_base *arg2)
1798 : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
1800 m_operand_list = new hsa_op_operand_list (nops - 1);
1803 /* New operator to allocate convert instruction from pool alloc. */
1805 void *
1806 hsa_insn_cvt::operator new (size_t)
1808 return hsa_allocp_inst_cvt->allocate_raw ();
1811 /* Constructor of class representing the convert instruction in HSAIL. */
1813 hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
1814 : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
1818 /* New operator to allocate alloca from pool alloc. */
1820 void *
1821 hsa_insn_alloca::operator new (size_t)
1823 return hsa_allocp_inst_alloca->allocate_raw ();
1826 /* Constructor of class representing the alloca in HSAIL. */
1828 hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
1829 hsa_op_with_type *size, unsigned alignment)
1830 : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
1831 m_align (BRIG_ALIGNMENT_8)
1833 gcc_assert (dest->m_type == BRIG_TYPE_U32);
1834 if (alignment)
1835 m_align = hsa_alignment_encoding (alignment);
1838 /* Append an instruction INSN into the basic block. */
1840 void
1841 hsa_bb::append_insn (hsa_insn_basic *insn)
1843 gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
1844 gcc_assert (!insn->m_bb);
1846 insn->m_bb = m_bb;
1847 insn->m_prev = m_last_insn;
1848 insn->m_next = NULL;
1849 if (m_last_insn)
1850 m_last_insn->m_next = insn;
1851 m_last_insn = insn;
1852 if (!m_first_insn)
1853 m_first_insn = insn;
1856 /* Insert HSA instruction NEW_INSN immediately before an existing instruction
1857 OLD_INSN. */
1859 static void
1860 hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1862 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1864 if (hbb->m_first_insn == old_insn)
1865 hbb->m_first_insn = new_insn;
1866 new_insn->m_prev = old_insn->m_prev;
1867 new_insn->m_next = old_insn;
1868 if (old_insn->m_prev)
1869 old_insn->m_prev->m_next = new_insn;
1870 old_insn->m_prev = new_insn;
1873 /* Append HSA instruction NEW_INSN immediately after an existing instruction
1874 OLD_INSN. */
1876 static void
1877 hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1879 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1881 if (hbb->m_last_insn == old_insn)
1882 hbb->m_last_insn = new_insn;
1883 new_insn->m_prev = old_insn;
1884 new_insn->m_next = old_insn->m_next;
1885 if (old_insn->m_next)
1886 old_insn->m_next->m_prev = new_insn;
1887 old_insn->m_next = new_insn;
1890 /* Return a register containing the calculated value of EXP which must be an
1891 expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
1892 integer constants as returned by get_inner_reference.
1893 Newly generated HSA instructions will be appended to HBB.
1894 Perform all calculations in ADDRTYPE. */
1896 static hsa_op_with_type *
1897 gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
1899 int opcode;
1901 if (TREE_CODE (exp) == NOP_EXPR)
1902 exp = TREE_OPERAND (exp, 0);
1904 switch (TREE_CODE (exp))
1906 case SSA_NAME:
1907 return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
1909 case INTEGER_CST:
1911 hsa_op_immed *imm = new hsa_op_immed (exp);
1912 if (addrtype != imm->m_type)
1913 imm->m_type = addrtype;
1914 return imm;
1917 case PLUS_EXPR:
1918 opcode = BRIG_OPCODE_ADD;
1919 break;
1921 case MULT_EXPR:
1922 opcode = BRIG_OPCODE_MUL;
1923 break;
1925 default:
1926 gcc_unreachable ();
1929 hsa_op_reg *res = new hsa_op_reg (addrtype);
1930 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
1931 insn->set_op (0, res);
1933 hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
1934 addrtype);
1935 hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
1936 addrtype);
1937 insn->set_op (1, op1);
1938 insn->set_op (2, op2);
1940 hbb->append_insn (insn);
1941 return res;
1944 /* If R1 is NULL, just return R2, otherwise append an instruction adding them
1945 to HBB and return the register holding the result. */
1947 static hsa_op_reg *
1948 add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
1950 gcc_checking_assert (r2);
1951 if (!r1)
1952 return r2;
1954 hsa_op_reg *res = new hsa_op_reg (r1->m_type);
1955 gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
1956 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
1957 insn->set_op (0, res);
1958 insn->set_op (1, r1);
1959 insn->set_op (2, r2);
1960 hbb->append_insn (insn);
1961 return res;
1964 /* Helper of gen_hsa_addr. Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
1965 reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF. */
1967 static void
1968 process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
1969 hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
1971 if (TREE_CODE (base) == SSA_NAME)
1973 gcc_assert (!*reg);
1974 hsa_op_with_type *ssa
1975 = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
1976 *reg = dyn_cast <hsa_op_reg *> (ssa);
1978 else if (TREE_CODE (base) == ADDR_EXPR)
1980 tree decl = TREE_OPERAND (base, 0);
1982 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
1984 HSA_SORRY_AT (EXPR_LOCATION (base),
1985 "support for HSA does not implement a memory reference "
1986 "to a non-declaration type");
1987 return;
1990 gcc_assert (!*symbol);
1992 *symbol = get_symbol_for_decl (decl);
1993 *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
1995 else if (TREE_CODE (base) == INTEGER_CST)
1996 *offset += wi::to_offset (base);
1997 else
1998 gcc_unreachable ();
2001 /* Forward declaration of a function. */
2003 static void
2004 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
2006 /* Generate HSA address operand for a given tree memory reference REF. If
2007 instructions need to be created to calculate the address, they will be added
2008 to the end of HBB. If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
2009 the function assumes that the caller will handle possible
2010 bit-field references. Otherwise if we reference a bit-field, sorry message
2011 is displayed. */
2013 static hsa_op_address *
2014 gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
2015 HOST_WIDE_INT *output_bitpos = NULL)
2017 hsa_symbol *symbol = NULL;
2018 hsa_op_reg *reg = NULL;
2019 offset_int offset = 0;
2020 tree origref = ref;
2021 tree varoffset = NULL_TREE;
2022 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2023 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2024 BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2026 if (TREE_CODE (ref) == STRING_CST)
2028 symbol = hsa_get_string_cst_symbol (ref);
2029 goto out;
2031 else if (TREE_CODE (ref) == BIT_FIELD_REF
2032 && ((tree_to_uhwi (TREE_OPERAND (ref, 1)) % BITS_PER_UNIT) != 0
2033 || (tree_to_uhwi (TREE_OPERAND (ref, 2)) % BITS_PER_UNIT) != 0))
2035 HSA_SORRY_ATV (EXPR_LOCATION (origref),
2036 "support for HSA does not implement "
2037 "bit field references such as %E", ref);
2038 goto out;
2041 if (handled_component_p (ref))
2043 enum machine_mode mode;
2044 int unsignedp, volatilep, preversep;
2046 ref = get_inner_reference (ref, &bitsize, &bitpos, &varoffset, &mode,
2047 &unsignedp, &preversep, &volatilep);
2049 offset = bitpos;
2050 offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
2053 switch (TREE_CODE (ref))
2055 case ADDR_EXPR:
2057 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2058 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2059 hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
2060 gen_hsa_addr_insns (ref, r, hbb);
2061 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2062 r, new hsa_op_address (symbol)));
2064 break;
2066 case SSA_NAME:
2068 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2069 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2070 hsa_op_reg *r = hsa_cfun->reg_for_gimple_ssa (ref);
2072 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2073 r, new hsa_op_address (symbol)));
2075 break;
2077 case PARM_DECL:
2078 case VAR_DECL:
2079 case RESULT_DECL:
2080 gcc_assert (!symbol);
2081 symbol = get_symbol_for_decl (ref);
2082 addrtype = hsa_get_segment_addr_type (symbol->m_segment);
2083 break;
2085 case MEM_REF:
2086 process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
2087 &offset, hbb);
2089 if (!integer_zerop (TREE_OPERAND (ref, 1)))
2090 offset += wi::to_offset (TREE_OPERAND (ref, 1));
2091 break;
2093 case TARGET_MEM_REF:
2094 process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
2095 if (TMR_INDEX (ref))
2097 hsa_op_reg *disp1;
2098 hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
2099 (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
2100 if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
2102 disp1 = new hsa_op_reg (addrtype);
2103 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
2104 addrtype);
2106 /* As step must respect addrtype, we overwrite the type
2107 of an immediate value. */
2108 hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
2109 step->m_type = addrtype;
2111 insn->set_op (0, disp1);
2112 insn->set_op (1, idx);
2113 insn->set_op (2, step);
2114 hbb->append_insn (insn);
2116 else
2117 disp1 = as_a <hsa_op_reg *> (idx);
2118 reg = add_addr_regs_if_needed (reg, disp1, hbb);
2120 if (TMR_INDEX2 (ref))
2122 if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
2124 hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
2125 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
2126 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
2127 hbb);
2129 else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
2130 offset += wi::to_offset (TMR_INDEX2 (ref));
2131 else
2132 gcc_unreachable ();
2134 offset += wi::to_offset (TMR_OFFSET (ref));
2135 break;
2136 case FUNCTION_DECL:
2137 HSA_SORRY_AT (EXPR_LOCATION (origref),
2138 "support for HSA does not implement function pointers");
2139 goto out;
2140 default:
2141 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
2142 "not implement memory access to %E", origref);
2143 goto out;
2146 if (varoffset)
2148 if (TREE_CODE (varoffset) == INTEGER_CST)
2149 offset += wi::to_offset (varoffset);
2150 else
2152 hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
2153 addrtype);
2154 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
2155 hbb);
2159 gcc_checking_assert ((symbol
2160 && addrtype
2161 == hsa_get_segment_addr_type (symbol->m_segment))
2162 || (!symbol
2163 && addrtype
2164 == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
2165 out:
2166 HOST_WIDE_INT hwi_offset = offset.to_shwi ();
2168 /* Calculate remaining bitsize offset (if presented). */
2169 bitpos %= BITS_PER_UNIT;
2170 /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
2171 is not a reason to think this is a bit-field access. */
2172 if (bitpos == 0
2173 && (bitsize >= BITS_PER_UNIT)
2174 && !(bitsize & (bitsize - 1)))
2175 bitsize = 0;
2177 if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
2178 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
2179 "implement unhandled bit field reference such as %E", ref);
2181 if (output_bitsize != NULL && output_bitpos != NULL)
2183 *output_bitsize = bitsize;
2184 *output_bitpos = bitpos;
2187 return new hsa_op_address (symbol, reg, hwi_offset);
2190 /* Generate HSA address operand for a given tree memory reference REF. If
2191 instructions need to be created to calculate the address, they will be added
2192 to the end of HBB. OUTPUT_ALIGN is alignment of the created address. */
2194 static hsa_op_address *
2195 gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
2197 hsa_op_address *addr = gen_hsa_addr (ref, hbb);
2198 if (addr->m_reg || !addr->m_symbol)
2199 *output_align = hsa_object_alignment (ref);
2200 else
2202 /* If the address consists only of a symbol and an offset, we
2203 compute the alignment ourselves to take into account any alignment
2204 promotions we might have done for the HSA symbol representation. */
2205 unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
2206 unsigned misalign = addr->m_imm_offset & (align - 1);
2207 if (misalign)
2208 align = least_bit_hwi (misalign);
2209 *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
2211 return addr;
2214 /* Generate HSA address for a function call argument of given TYPE.
2215 INDEX is used to generate corresponding name of the arguments.
2216 Special value -1 represents fact that result value is created. */
2218 static hsa_op_address *
2219 gen_hsa_addr_for_arg (tree tree_type, int index)
2221 hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
2222 BRIG_LINKAGE_ARG);
2223 sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
2225 if (index == -1) /* Function result. */
2226 sym->m_name = "res";
2227 else /* Function call arguments. */
2229 sym->m_name = NULL;
2230 sym->m_name_number = index;
2233 return new hsa_op_address (sym);
2236 /* Generate HSA instructions that process all necessary conversions
2237 of an ADDR to flat addressing and place the result into DEST.
2238 Instructions are appended to HBB. */
2240 static void
2241 convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
2242 hsa_bb *hbb)
2244 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
2245 insn->set_op (1, addr);
2246 if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
2248 /* LDA produces segment-relative address, we need to convert
2249 it to the flat one. */
2250 hsa_op_reg *tmp;
2251 tmp = new hsa_op_reg (hsa_get_segment_addr_type
2252 (addr->m_symbol->m_segment));
2253 hsa_insn_seg *seg;
2254 seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
2255 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
2256 tmp->m_type, addr->m_symbol->m_segment, dest,
2257 tmp);
2259 insn->set_op (0, tmp);
2260 insn->m_type = tmp->m_type;
2261 hbb->append_insn (insn);
2262 hbb->append_insn (seg);
2264 else
2266 insn->set_op (0, dest);
2267 insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2268 hbb->append_insn (insn);
2272 /* Generate HSA instructions that calculate address of VAL including all
2273 necessary conversions to flat addressing and place the result into DEST.
2274 Instructions are appended to HBB. */
2276 static void
2277 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
2279 /* Handle cases like tmp = NULL, where we just emit a move instruction
2280 to a register. */
2281 if (TREE_CODE (val) == INTEGER_CST)
2283 hsa_op_immed *c = new hsa_op_immed (val);
2284 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2285 dest->m_type, dest, c);
2286 hbb->append_insn (insn);
2287 return;
2290 hsa_op_address *addr;
2292 gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2293 if (TREE_CODE (val) == ADDR_EXPR)
2294 val = TREE_OPERAND (val, 0);
2295 addr = gen_hsa_addr (val, hbb);
2297 convert_addr_to_flat_segment (addr, dest, hbb);
2300 /* Return an HSA register or HSA immediate value operand corresponding to
2301 gimple operand OP. */
2303 static hsa_op_with_type *
2304 hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
2306 hsa_op_reg *tmp;
2308 if (TREE_CODE (op) == SSA_NAME)
2309 tmp = hsa_cfun->reg_for_gimple_ssa (op);
2310 else if (!POINTER_TYPE_P (TREE_TYPE (op)))
2311 return new hsa_op_immed (op);
2312 else
2314 tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2315 gen_hsa_addr_insns (op, tmp, hbb);
2317 return tmp;
2320 /* Create a simple movement instruction with register destination DEST and
2321 register or immediate source SRC and append it to the end of HBB. */
2323 void
2324 hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
2326 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
2327 dest, src);
2328 if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
2329 gcc_assert (hsa_type_bit_size (dest->m_type)
2330 == hsa_type_bit_size (sreg->m_type));
2331 else
2332 gcc_assert (hsa_type_bit_size (dest->m_type)
2333 == hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type));
2335 hbb->append_insn (insn);
2338 /* Generate HSAIL instructions loading a bit field into register DEST.
2339 VALUE_REG is a register of a SSA name that is used in the bit field
2340 reference. To identify a bit field BITPOS is offset to the loaded memory
2341 and BITSIZE is number of bits of the bit field.
2342 Add instructions to HBB. */
2344 static void
2345 gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
2346 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2347 hsa_bb *hbb)
2349 unsigned type_bitsize = hsa_type_bit_size (dest->m_type);
2350 unsigned left_shift = type_bitsize - (bitsize + bitpos);
2351 unsigned right_shift = left_shift + bitpos;
2353 if (left_shift)
2355 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2356 hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
2358 hsa_insn_basic *lshift
2359 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
2360 value_reg_2, value_reg, c);
2362 hbb->append_insn (lshift);
2364 value_reg = value_reg_2;
2367 if (right_shift)
2369 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2370 hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
2372 hsa_insn_basic *rshift
2373 = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
2374 value_reg_2, value_reg, c);
2376 hbb->append_insn (rshift);
2378 value_reg = value_reg_2;
2381 hsa_insn_basic *assignment
2382 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, value_reg);
2383 hbb->append_insn (assignment);
2387 /* Generate HSAIL instructions loading a bit field into register DEST. ADDR is
2388 prepared memory address which is used to load the bit field. To identify a
2389 bit field BITPOS is offset to the loaded memory and BITSIZE is number of
2390 bits of the bit field. Add instructions to HBB. Load must be performed in
2391 alignment ALIGN. */
2393 static void
2394 gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
2395 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2396 hsa_bb *hbb, BrigAlignment8_t align)
2398 hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
2399 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, dest->m_type, value_reg,
2400 addr);
2401 mem->set_align (align);
2402 hbb->append_insn (mem);
2403 gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
2406 /* Return the alignment of base memory accesses we issue to perform bit-field
2407 memory access REF. */
2409 static BrigAlignment8_t
2410 hsa_bitmemref_alignment (tree ref)
2412 unsigned HOST_WIDE_INT bit_offset = 0;
2414 while (true)
2416 if (TREE_CODE (ref) == BIT_FIELD_REF)
2418 if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
2419 return BRIG_ALIGNMENT_1;
2420 bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
2422 else if (TREE_CODE (ref) == COMPONENT_REF
2423 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
2424 bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
2425 else
2426 break;
2427 ref = TREE_OPERAND (ref, 0);
2430 unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
2431 unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
2432 BrigAlignment8_t base = hsa_object_alignment (ref);
2433 if (byte_bits == 0)
2434 return base;
2435 return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
2438 /* Generate HSAIL instructions loading something into register DEST. RHS is
2439 tree representation of the loaded data, which are loaded as type TYPE. Add
2440 instructions to HBB. */
2442 static void
2443 gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
2445 /* The destination SSA name will give us the type. */
2446 if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
2447 rhs = TREE_OPERAND (rhs, 0);
2449 if (TREE_CODE (rhs) == SSA_NAME)
2451 hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
2452 hsa_build_append_simple_mov (dest, src, hbb);
2454 else if (is_gimple_min_invariant (rhs)
2455 || TREE_CODE (rhs) == ADDR_EXPR)
2457 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
2459 if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
2461 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2462 "support for HSA does not implement conversion "
2463 "of %E to the requested non-pointer type.", rhs);
2464 return;
2467 gen_hsa_addr_insns (rhs, dest, hbb);
2469 else if (TREE_CODE (rhs) == COMPLEX_CST)
2471 hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
2472 hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
2474 hsa_op_reg *real_part_reg
2475 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2476 true));
2477 hsa_op_reg *imag_part_reg
2478 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2479 true));
2481 hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
2482 hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
2484 BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
2486 hsa_insn_packed *insn
2487 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
2488 src_type, dest, real_part_reg,
2489 imag_part_reg);
2490 hbb->append_insn (insn);
2492 else
2494 hsa_op_immed *imm = new hsa_op_immed (rhs);
2495 hsa_build_append_simple_mov (dest, imm, hbb);
2498 else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
2500 tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
2502 hsa_op_reg *packed_reg
2503 = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
2505 tree complex_rhs = TREE_OPERAND (rhs, 0);
2506 gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
2507 hbb);
2509 hsa_op_reg *real_reg
2510 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2512 hsa_op_reg *imag_reg
2513 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2515 BrigKind16_t brig_type = packed_reg->m_type;
2516 hsa_insn_packed *packed
2517 = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
2518 hsa_bittype_for_type (real_reg->m_type),
2519 brig_type, real_reg, imag_reg, packed_reg);
2521 hbb->append_insn (packed);
2523 hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
2524 real_reg : imag_reg;
2526 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2527 dest->m_type, dest, source);
2529 hbb->append_insn (insn);
2531 else if (TREE_CODE (rhs) == BIT_FIELD_REF
2532 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
2534 tree ssa_name = TREE_OPERAND (rhs, 0);
2535 HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
2536 HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
2538 hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
2539 gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
2541 else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
2542 || TREE_CODE (rhs) == TARGET_MEM_REF
2543 || handled_component_p (rhs))
2545 HOST_WIDE_INT bitsize, bitpos;
2547 /* Load from memory. */
2548 hsa_op_address *addr;
2549 addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
2551 /* Handle load of a bit field. */
2552 if (bitsize > 64)
2554 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2555 "support for HSA does not implement load from a bit "
2556 "field bigger than 64 bits");
2557 return;
2560 if (bitsize || bitpos)
2561 gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
2562 hsa_bitmemref_alignment (rhs));
2563 else
2565 BrigType16_t mtype;
2566 /* Not dest->m_type, that's possibly extended. */
2567 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
2568 false));
2569 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
2570 addr);
2571 mem->set_align (hsa_object_alignment (rhs));
2572 hbb->append_insn (mem);
2575 else
2576 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2577 "support for HSA does not implement loading "
2578 "of expression %E",
2579 rhs);
2582 /* Return number of bits necessary for representation of a bit field,
2583 starting at BITPOS with size of BITSIZE. */
2585 static unsigned
2586 get_bitfield_size (unsigned bitpos, unsigned bitsize)
2588 unsigned s = bitpos + bitsize;
2589 unsigned sizes[] = {8, 16, 32, 64};
2591 for (unsigned i = 0; i < 4; i++)
2592 if (s <= sizes[i])
2593 return sizes[i];
2595 gcc_unreachable ();
2596 return 0;
2599 /* Generate HSAIL instructions storing into memory. LHS is the destination of
2600 the store, SRC is the source operand. Add instructions to HBB. */
2602 static void
2603 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
2605 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2606 BrigAlignment8_t req_align;
2607 BrigType16_t mtype;
2608 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
2609 false));
2610 hsa_op_address *addr;
2611 addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
2613 /* Handle store to a bit field. */
2614 if (bitsize > 64)
2616 HSA_SORRY_AT (EXPR_LOCATION (lhs),
2617 "support for HSA does not implement store to a bit field "
2618 "bigger than 64 bits");
2619 return;
2622 unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
2624 /* HSAIL does not support MOV insn with 16-bits integers. */
2625 if (type_bitsize < 32)
2626 type_bitsize = 32;
2628 if (bitpos || (bitsize && type_bitsize != bitsize))
2630 unsigned HOST_WIDE_INT mask = 0;
2631 BrigType16_t mem_type
2632 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
2633 !TYPE_UNSIGNED (TREE_TYPE (lhs)));
2635 for (unsigned i = 0; i < type_bitsize; i++)
2636 if (i < bitpos || i >= bitpos + bitsize)
2637 mask |= ((unsigned HOST_WIDE_INT)1 << i);
2639 hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
2641 req_align = hsa_bitmemref_alignment (lhs);
2642 /* Load value from memory. */
2643 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
2644 value_reg, addr);
2645 mem->set_align (req_align);
2646 hbb->append_insn (mem);
2648 /* AND the loaded value with prepared mask. */
2649 hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
2651 BrigType16_t t
2652 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
2653 hsa_op_immed *c = new hsa_op_immed (mask, t);
2655 hsa_insn_basic *clearing
2656 = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
2657 value_reg, c);
2658 hbb->append_insn (clearing);
2660 /* Shift to left a value that is going to be stored. */
2661 hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
2663 hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
2664 new_value_reg, src);
2665 hbb->append_insn (basic);
2667 if (bitpos)
2669 hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
2670 c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
2672 hsa_insn_basic *basic
2673 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
2674 shifted_value_reg, new_value_reg, c);
2675 hbb->append_insn (basic);
2677 new_value_reg = shifted_value_reg;
2680 /* OR the prepared value with prepared chunk loaded from memory. */
2681 hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
2682 basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
2683 new_value_reg, cleared_reg);
2684 hbb->append_insn (basic);
2686 src = prepared_reg;
2687 mtype = mem_type;
2689 else
2690 req_align = hsa_object_alignment (lhs);
2692 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
2693 mem->set_align (req_align);
2695 /* The HSAIL verifier has another constraint: if the source is an immediate
2696 then it must match the destination type. If it's a register the low bits
2697 will be used for sub-word stores. We're always allocating new operands so
2698 we can modify the above in place. */
2699 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
2701 if (!hsa_type_packed_p (imm->m_type))
2702 imm->m_type = mem->m_type;
2703 else
2705 /* ...and all vector immediates apparently need to be vectors of
2706 unsigned bytes. */
2707 unsigned bs = hsa_type_bit_size (imm->m_type);
2708 gcc_assert (bs == hsa_type_bit_size (mem->m_type));
2709 switch (bs)
2711 case 32:
2712 imm->m_type = BRIG_TYPE_U8X4;
2713 break;
2714 case 64:
2715 imm->m_type = BRIG_TYPE_U8X8;
2716 break;
2717 case 128:
2718 imm->m_type = BRIG_TYPE_U8X16;
2719 break;
2720 default:
2721 gcc_unreachable ();
2726 hbb->append_insn (mem);
2729 /* Generate memory copy instructions that are going to be used
2730 for copying a SRC memory to TARGET memory,
2731 represented by pointer in a register. MIN_ALIGN is minimal alignment
2732 of provided HSA addresses. */
2734 static void
2735 gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
2736 unsigned size, BrigAlignment8_t min_align)
2738 hsa_op_address *addr;
2739 hsa_insn_mem *mem;
2741 unsigned offset = 0;
2742 unsigned min_byte_align = hsa_byte_alignment (min_align);
2744 while (size)
2746 unsigned s;
2747 if (size >= 8)
2748 s = 8;
2749 else if (size >= 4)
2750 s = 4;
2751 else if (size >= 2)
2752 s = 2;
2753 else
2754 s = 1;
2756 if (s > min_byte_align)
2757 s = min_byte_align;
2759 BrigType16_t t = get_integer_type_by_bytes (s, false);
2761 hsa_op_reg *tmp = new hsa_op_reg (t);
2762 addr = new hsa_op_address (src->m_symbol, src->m_reg,
2763 src->m_imm_offset + offset);
2764 mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
2765 hbb->append_insn (mem);
2767 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2768 target->m_imm_offset + offset);
2769 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
2770 hbb->append_insn (mem);
2771 offset += s;
2772 size -= s;
2776 /* Create a memset mask that is created by copying a CONSTANT byte value
2777 to an integer of BYTE_SIZE bytes. */
2779 static unsigned HOST_WIDE_INT
2780 build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
2782 if (constant == 0)
2783 return 0;
2785 HOST_WIDE_INT v = constant;
2787 for (unsigned i = 1; i < byte_size; i++)
2788 v |= constant << (8 * i);
2790 return v;
2793 /* Generate memory set instructions that are going to be used
2794 for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
2795 MIN_ALIGN is minimal alignment of provided HSA addresses. */
2797 static void
2798 gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
2799 unsigned HOST_WIDE_INT constant,
2800 unsigned size, BrigAlignment8_t min_align)
2802 hsa_op_address *addr;
2803 hsa_insn_mem *mem;
2805 unsigned offset = 0;
2806 unsigned min_byte_align = hsa_byte_alignment (min_align);
2808 while (size)
2810 unsigned s;
2811 if (size >= 8)
2812 s = 8;
2813 else if (size >= 4)
2814 s = 4;
2815 else if (size >= 2)
2816 s = 2;
2817 else
2818 s = 1;
2820 if (s > min_byte_align)
2821 s = min_byte_align;
2823 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2824 target->m_imm_offset + offset);
2826 BrigType16_t t = get_integer_type_by_bytes (s, false);
2827 HOST_WIDE_INT c = build_memset_value (constant, s);
2829 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
2830 addr);
2831 hbb->append_insn (mem);
2832 offset += s;
2833 size -= s;
2837 /* Generate HSAIL instructions for a single assignment
2838 of an empty constructor to an ADDR_LHS. Constructor is passed as a
2839 tree RHS and all instructions are appended to HBB. ALIGN is
2840 alignment of the address. */
2842 void
2843 gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
2844 BrigAlignment8_t align)
2846 if (CONSTRUCTOR_NELTS (rhs))
2848 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2849 "support for HSA does not implement load from constructor");
2850 return;
2853 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2854 gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
2857 /* Generate HSA instructions for a single assignment of RHS to LHS.
2858 HBB is the basic block they will be appended to. */
2860 static void
2861 gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
2863 if (TREE_CODE (lhs) == SSA_NAME)
2865 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
2866 if (hsa_seen_error ())
2867 return;
2869 gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
2871 else if (TREE_CODE (rhs) == SSA_NAME
2872 || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
2874 /* Store to memory. */
2875 hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
2876 if (hsa_seen_error ())
2877 return;
2879 gen_hsa_insns_for_store (lhs, src, hbb);
2881 else
2883 BrigAlignment8_t lhs_align;
2884 hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
2885 &lhs_align);
2887 if (TREE_CODE (rhs) == CONSTRUCTOR)
2888 gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
2889 else
2891 BrigAlignment8_t rhs_align;
2892 hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
2893 &rhs_align);
2895 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2896 gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
2897 MIN (lhs_align, rhs_align));
2902 /* Prepend before INSN a load from spill symbol of SPILL_REG. Return the
2903 register into which we loaded. If this required another register to convert
2904 from a B1 type, return it in *PTMP2, otherwise store NULL into it. We
2905 assume we are out of SSA so the returned register does not have its
2906 definition set. */
2908 hsa_op_reg *
2909 hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2911 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2912 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2913 hsa_op_address *addr = new hsa_op_address (spill_sym);
2915 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
2916 reg, addr);
2917 hsa_insert_insn_before (mem, insn);
2919 *ptmp2 = NULL;
2920 if (spill_reg->m_type == BRIG_TYPE_B1)
2922 hsa_insn_basic *cvtinsn;
2923 *ptmp2 = reg;
2924 reg = new hsa_op_reg (spill_reg->m_type);
2926 cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
2927 hsa_insert_insn_before (cvtinsn, insn);
2929 return reg;
2932 /* Append after INSN a store to spill symbol of SPILL_REG. Return the register
2933 from which we stored. If this required another register to convert to a B1
2934 type, return it in *PTMP2, otherwise store NULL into it. We assume we are
2935 out of SSA so the returned register does not have its use updated. */
2937 hsa_op_reg *
2938 hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2940 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2941 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2942 hsa_op_address *addr = new hsa_op_address (spill_sym);
2943 hsa_op_reg *returnreg;
2945 *ptmp2 = NULL;
2946 returnreg = reg;
2947 if (spill_reg->m_type == BRIG_TYPE_B1)
2949 hsa_insn_basic *cvtinsn;
2950 *ptmp2 = new hsa_op_reg (spill_sym->m_type);
2951 reg->m_type = spill_reg->m_type;
2953 cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
2954 hsa_append_insn_after (cvtinsn, insn);
2955 insn = cvtinsn;
2956 reg = *ptmp2;
2959 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
2960 addr);
2961 hsa_append_insn_after (mem, insn);
2962 return returnreg;
2965 /* Generate a comparison instruction that will compare LHS and RHS with
2966 comparison specified by CODE and put result into register DEST. DEST has to
2967 have its type set already but must not have its definition set yet.
2968 Generated instructions will be added to HBB. */
2970 static void
2971 gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
2972 hsa_op_reg *dest, hsa_bb *hbb)
2974 BrigCompareOperation8_t compare;
2976 switch (code)
2978 case LT_EXPR:
2979 compare = BRIG_COMPARE_LT;
2980 break;
2981 case LE_EXPR:
2982 compare = BRIG_COMPARE_LE;
2983 break;
2984 case GT_EXPR:
2985 compare = BRIG_COMPARE_GT;
2986 break;
2987 case GE_EXPR:
2988 compare = BRIG_COMPARE_GE;
2989 break;
2990 case EQ_EXPR:
2991 compare = BRIG_COMPARE_EQ;
2992 break;
2993 case NE_EXPR:
2994 compare = BRIG_COMPARE_NE;
2995 break;
2996 case UNORDERED_EXPR:
2997 compare = BRIG_COMPARE_NAN;
2998 break;
2999 case ORDERED_EXPR:
3000 compare = BRIG_COMPARE_NUM;
3001 break;
3002 case UNLT_EXPR:
3003 compare = BRIG_COMPARE_LTU;
3004 break;
3005 case UNLE_EXPR:
3006 compare = BRIG_COMPARE_LEU;
3007 break;
3008 case UNGT_EXPR:
3009 compare = BRIG_COMPARE_GTU;
3010 break;
3011 case UNGE_EXPR:
3012 compare = BRIG_COMPARE_GEU;
3013 break;
3014 case UNEQ_EXPR:
3015 compare = BRIG_COMPARE_EQU;
3016 break;
3017 case LTGT_EXPR:
3018 compare = BRIG_COMPARE_NEU;
3019 break;
3021 default:
3022 HSA_SORRY_ATV (EXPR_LOCATION (lhs),
3023 "support for HSA does not implement comparison tree "
3024 "code %s\n", get_tree_code_name (code));
3025 return;
3028 /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
3029 as a result of comparison. */
3031 BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
3032 ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
3034 hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
3035 cmp->set_op (1, hsa_reg_or_immed_for_gimple_op (lhs, hbb));
3036 cmp->set_op (2, hsa_reg_or_immed_for_gimple_op (rhs, hbb));
3038 hbb->append_insn (cmp);
3039 cmp->set_output_in_type (dest, 0, hbb);
3042 /* Generate an unary instruction with OPCODE and append it to a basic block
3043 HBB. The instruction uses DEST as a destination and OP1
3044 as a single operand. */
3046 static void
3047 gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
3048 hsa_op_with_type *op1, hsa_bb *hbb)
3050 gcc_checking_assert (dest);
3051 hsa_insn_basic *insn;
3053 if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
3054 insn = new hsa_insn_cvt (dest, op1);
3055 else if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3056 insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, op1->m_type, NULL,
3057 op1);
3058 else
3060 insn = new hsa_insn_basic (2, opcode, dest->m_type, dest, op1);
3062 if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
3064 /* ABS and NEG only exist in _s form :-/ */
3065 if (insn->m_type == BRIG_TYPE_U32)
3066 insn->m_type = BRIG_TYPE_S32;
3067 else if (insn->m_type == BRIG_TYPE_U64)
3068 insn->m_type = BRIG_TYPE_S64;
3072 hbb->append_insn (insn);
3074 if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3075 insn->set_output_in_type (dest, 0, hbb);
3078 /* Generate a binary instruction with OPCODE and append it to a basic block
3079 HBB. The instruction uses DEST as a destination and operands OP1
3080 and OP2. */
3082 static void
3083 gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
3084 hsa_op_base *op1, hsa_op_base *op2, hsa_bb *hbb)
3086 gcc_checking_assert (dest);
3088 if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
3089 && is_a <hsa_op_immed *> (op2))
3091 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3092 i->set_type (BRIG_TYPE_U32);
3094 if ((opcode == BRIG_OPCODE_OR
3095 || opcode == BRIG_OPCODE_XOR
3096 || opcode == BRIG_OPCODE_AND)
3097 && is_a <hsa_op_immed *> (op2))
3099 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3100 i->set_type (hsa_unsigned_type_for_type (i->m_type));
3103 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, dest->m_type, dest,
3104 op1, op2);
3105 hbb->append_insn (insn);
3108 /* Generate HSA instructions for a single assignment. HBB is the basic block
3109 they will be appended to. */
3111 static void
3112 gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
3114 tree_code code = gimple_assign_rhs_code (assign);
3115 gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
3117 tree lhs = gimple_assign_lhs (assign);
3118 tree rhs1 = gimple_assign_rhs1 (assign);
3119 tree rhs2 = gimple_assign_rhs2 (assign);
3120 tree rhs3 = gimple_assign_rhs3 (assign);
3122 BrigOpcode opcode;
3124 switch (code)
3126 CASE_CONVERT:
3127 case FLOAT_EXPR:
3128 /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
3129 needs a conversion. */
3130 opcode = BRIG_OPCODE_MOV;
3131 break;
3133 case PLUS_EXPR:
3134 case POINTER_PLUS_EXPR:
3135 opcode = BRIG_OPCODE_ADD;
3136 break;
3137 case MINUS_EXPR:
3138 opcode = BRIG_OPCODE_SUB;
3139 break;
3140 case MULT_EXPR:
3141 opcode = BRIG_OPCODE_MUL;
3142 break;
3143 case MULT_HIGHPART_EXPR:
3144 opcode = BRIG_OPCODE_MULHI;
3145 break;
3146 case RDIV_EXPR:
3147 case TRUNC_DIV_EXPR:
3148 case EXACT_DIV_EXPR:
3149 opcode = BRIG_OPCODE_DIV;
3150 break;
3151 case CEIL_DIV_EXPR:
3152 case FLOOR_DIV_EXPR:
3153 case ROUND_DIV_EXPR:
3154 HSA_SORRY_AT (gimple_location (assign),
3155 "support for HSA does not implement CEIL_DIV_EXPR, "
3156 "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
3157 return;
3158 case TRUNC_MOD_EXPR:
3159 opcode = BRIG_OPCODE_REM;
3160 break;
3161 case CEIL_MOD_EXPR:
3162 case FLOOR_MOD_EXPR:
3163 case ROUND_MOD_EXPR:
3164 HSA_SORRY_AT (gimple_location (assign),
3165 "support for HSA does not implement CEIL_MOD_EXPR, "
3166 "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
3167 return;
3168 case NEGATE_EXPR:
3169 opcode = BRIG_OPCODE_NEG;
3170 break;
3171 case MIN_EXPR:
3172 opcode = BRIG_OPCODE_MIN;
3173 break;
3174 case MAX_EXPR:
3175 opcode = BRIG_OPCODE_MAX;
3176 break;
3177 case ABS_EXPR:
3178 opcode = BRIG_OPCODE_ABS;
3179 break;
3180 case LSHIFT_EXPR:
3181 opcode = BRIG_OPCODE_SHL;
3182 break;
3183 case RSHIFT_EXPR:
3184 opcode = BRIG_OPCODE_SHR;
3185 break;
3186 case LROTATE_EXPR:
3187 case RROTATE_EXPR:
3189 hsa_insn_basic *insn = NULL;
3190 int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3191 int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3192 BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3193 true);
3195 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3196 hsa_op_reg *op1 = new hsa_op_reg (btype);
3197 hsa_op_reg *op2 = new hsa_op_reg (btype);
3198 hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3200 tree type = TREE_TYPE (rhs2);
3201 unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3203 hsa_op_with_type *shift2 = NULL;
3204 if (TREE_CODE (rhs2) == INTEGER_CST)
3205 shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3206 BRIG_TYPE_U32);
3207 else if (TREE_CODE (rhs2) == SSA_NAME)
3209 hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3210 hsa_op_reg *d = new hsa_op_reg (s->m_type);
3211 hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3213 insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3214 d, s, size_imm);
3215 hbb->append_insn (insn);
3217 shift2 = d;
3219 else
3220 gcc_unreachable ();
3222 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3223 gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3224 gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3225 gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3227 return;
3229 case BIT_IOR_EXPR:
3230 opcode = BRIG_OPCODE_OR;
3231 break;
3232 case BIT_XOR_EXPR:
3233 opcode = BRIG_OPCODE_XOR;
3234 break;
3235 case BIT_AND_EXPR:
3236 opcode = BRIG_OPCODE_AND;
3237 break;
3238 case BIT_NOT_EXPR:
3239 opcode = BRIG_OPCODE_NOT;
3240 break;
3241 case FIX_TRUNC_EXPR:
3243 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3244 hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3246 if (hsa_needs_cvt (dest->m_type, v->m_type))
3248 hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3250 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3251 tmp->m_type, tmp, v);
3252 hbb->append_insn (insn);
3254 hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3255 hbb->append_insn (cvtinsn);
3257 else
3259 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3260 dest->m_type, dest, v);
3261 hbb->append_insn (insn);
3264 return;
3266 opcode = BRIG_OPCODE_TRUNC;
3267 break;
3269 case LT_EXPR:
3270 case LE_EXPR:
3271 case GT_EXPR:
3272 case GE_EXPR:
3273 case EQ_EXPR:
3274 case NE_EXPR:
3275 case UNORDERED_EXPR:
3276 case ORDERED_EXPR:
3277 case UNLT_EXPR:
3278 case UNLE_EXPR:
3279 case UNGT_EXPR:
3280 case UNGE_EXPR:
3281 case UNEQ_EXPR:
3282 case LTGT_EXPR:
3284 hsa_op_reg *dest
3285 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3287 gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3288 return;
3290 case COND_EXPR:
3292 hsa_op_reg *dest
3293 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3294 hsa_op_with_type *ctrl = NULL;
3295 tree cond = rhs1;
3297 if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3298 ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3299 else
3301 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3303 gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3304 TREE_OPERAND (cond, 0),
3305 TREE_OPERAND (cond, 1),
3306 r, hbb);
3308 ctrl = r;
3311 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3312 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3314 BrigType16_t utype = hsa_unsigned_type_for_type (dest->m_type);
3315 if (is_a <hsa_op_immed *> (op2))
3316 op2->m_type = utype;
3317 if (is_a <hsa_op_immed *> (op3))
3318 op3->m_type = utype;
3320 hsa_insn_basic *insn
3321 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3322 hsa_bittype_for_type (dest->m_type),
3323 dest, ctrl, op2, op3);
3325 hbb->append_insn (insn);
3326 return;
3328 case COMPLEX_EXPR:
3330 hsa_op_reg *dest
3331 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3332 hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3333 hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3335 if (hsa_seen_error ())
3336 return;
3338 BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3339 rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3340 rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3342 hsa_insn_packed *insn
3343 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3344 dest, rhs1_reg, rhs2_reg);
3345 hbb->append_insn (insn);
3347 return;
3349 default:
3350 /* Implement others as we come across them. */
3351 HSA_SORRY_ATV (gimple_location (assign),
3352 "support for HSA does not implement operation %s",
3353 get_tree_code_name (code));
3354 return;
3358 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3360 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3361 hsa_op_with_type *op2 = rhs2 != NULL_TREE ?
3362 hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3364 if (hsa_seen_error ())
3365 return;
3367 switch (rhs_class)
3369 case GIMPLE_TERNARY_RHS:
3370 gcc_unreachable ();
3371 return;
3373 /* Fall through */
3374 case GIMPLE_BINARY_RHS:
3375 gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3376 break;
3377 /* Fall through */
3378 case GIMPLE_UNARY_RHS:
3379 gen_hsa_unary_operation (opcode, dest, op1, hbb);
3380 break;
3381 default:
3382 gcc_unreachable ();
3386 /* Generate HSA instructions for a given gimple condition statement COND.
3387 Instructions will be appended to HBB, which also needs to be the
3388 corresponding structure to the basic_block of COND. */
3390 static void
3391 gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3393 hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3394 hsa_insn_br *cbr;
3396 gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3397 gimple_cond_lhs (cond),
3398 gimple_cond_rhs (cond),
3399 ctrl, hbb);
3401 cbr = new hsa_insn_br (ctrl);
3402 hbb->append_insn (cbr);
3405 /* Maximum number of elements in a jump table for an HSA SBR instruction. */
3407 #define HSA_MAXIMUM_SBR_LABELS 16
3409 /* Return lowest value of a switch S that is handled in a non-default
3410 label. */
3412 static tree
3413 get_switch_low (gswitch *s)
3415 unsigned labels = gimple_switch_num_labels (s);
3416 gcc_checking_assert (labels >= 1);
3418 return CASE_LOW (gimple_switch_label (s, 1));
3421 /* Return highest value of a switch S that is handled in a non-default
3422 label. */
3424 static tree
3425 get_switch_high (gswitch *s)
3427 unsigned labels = gimple_switch_num_labels (s);
3429 /* Compare last label to maximum number of labels. */
3430 tree label = gimple_switch_label (s, labels - 1);
3431 tree low = CASE_LOW (label);
3432 tree high = CASE_HIGH (label);
3434 return high != NULL_TREE ? high : low;
3437 static tree
3438 get_switch_size (gswitch *s)
3440 return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3443 /* Generate HSA instructions for a given gimple switch.
3444 Instructions will be appended to HBB. */
3446 static void
3447 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3449 gimple_stmt_iterator it = gsi_for_stmt (s);
3450 gsi_prev (&it);
3452 /* Create preambule that verifies that index - lowest_label >= 0. */
3453 edge e = split_block (hbb->m_bb, gsi_stmt (it));
3454 e->flags &= ~EDGE_FALLTHRU;
3455 e->flags |= EDGE_TRUE_VALUE;
3457 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
3458 tree index_tree = gimple_switch_index (s);
3459 tree lowest = get_switch_low (s);
3460 tree highest = get_switch_high (s);
3462 hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
3464 hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3465 hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest);
3466 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3467 cmp1_reg, index, cmp1_immed));
3469 hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3470 hsa_op_immed *cmp2_immed = new hsa_op_immed (highest);
3471 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3472 cmp2_reg, index, cmp2_immed));
3474 hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3475 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3476 cmp_reg, cmp1_reg, cmp2_reg));
3478 hbb->append_insn (new hsa_insn_br (cmp_reg));
3480 tree default_label = gimple_switch_default_label (s);
3481 basic_block default_label_bb = label_to_block_fn (func,
3482 CASE_LABEL (default_label));
3484 if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3486 default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3487 hsa_init_new_bb (default_label_bb);
3490 make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3492 hsa_cfun->m_modified_cfg = true;
3494 /* Basic block with the SBR instruction. */
3495 hbb = hsa_init_new_bb (e->dest);
3497 hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3498 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3499 sub_index, index,
3500 new hsa_op_immed (lowest)));
3502 hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3503 sub_index = as_a <hsa_op_reg *> (tmp);
3504 unsigned labels = gimple_switch_num_labels (s);
3505 unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3507 hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
3509 /* Prepare array with default label destination. */
3510 for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3511 sbr->m_jump_table.safe_push (default_label_bb);
3513 /* Iterate all labels and fill up the jump table. */
3514 for (unsigned i = 1; i < labels; i++)
3516 tree label = gimple_switch_label (s, i);
3517 basic_block bb = label_to_block_fn (func, CASE_LABEL (label));
3519 unsigned HOST_WIDE_INT sub_low
3520 = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3522 unsigned HOST_WIDE_INT sub_high = sub_low;
3523 tree high = CASE_HIGH (label);
3524 if (high != NULL)
3525 sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3527 for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3528 sbr->m_jump_table[j] = bb;
3531 hbb->append_insn (sbr);
3534 /* Verify that the function DECL can be handled by HSA. */
3536 static void
3537 verify_function_arguments (tree decl)
3539 if (DECL_STATIC_CHAIN (decl))
3541 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3542 "HSA does not support nested functions: %D", decl);
3543 return;
3545 else if (!TYPE_ARG_TYPES (TREE_TYPE (decl)))
3547 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3548 "HSA does not support functions with variadic arguments "
3549 "(or unknown return type): %D", decl);
3550 return;
3554 /* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL,
3555 return ACTUAL_ARG_TYPE. */
3557 static BrigType16_t
3558 get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3560 if (formal_arg_type == NULL)
3561 return actual_arg_type;
3563 BrigType16_t decl_type
3564 = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3565 return mem_type_for_type (decl_type);
3568 /* Generate HSA instructions for a direct call instruction.
3569 Instructions will be appended to HBB, which also needs to be the
3570 corresponding structure to the basic_block of STMT.
3571 If ASSIGN_LHS is false, do not copy HSA function result argument into the
3572 corresponding HSA representation of the gimple statement LHS. */
3574 static void
3575 gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3576 bool assign_lhs = true)
3578 tree decl = gimple_call_fndecl (stmt);
3579 verify_function_arguments (decl);
3580 if (hsa_seen_error ())
3581 return;
3583 hsa_insn_call *call_insn = new hsa_insn_call (decl);
3584 hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3586 /* Argument block start. */
3587 hsa_insn_arg_block *arg_start
3588 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3589 hbb->append_insn (arg_start);
3591 tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3593 /* Preparation of arguments that will be passed to function. */
3594 const unsigned args = gimple_call_num_args (stmt);
3595 for (unsigned i = 0; i < args; ++i)
3597 tree parm = gimple_call_arg (stmt, (int)i);
3598 tree parm_decl_type = parm_type_chain != NULL_TREE
3599 ? TREE_VALUE (parm_type_chain) : NULL_TREE;
3600 hsa_op_address *addr;
3602 if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3604 addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3605 BrigAlignment8_t align;
3606 hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
3607 gen_hsa_memory_copy (hbb, addr, src,
3608 addr->m_symbol->total_byte_size (), align);
3610 else
3612 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3614 if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3616 HSA_SORRY_AT (gimple_location (stmt),
3617 "support for HSA does not implement an aggregate "
3618 "formal argument in a function call, while actual "
3619 "argument is not an aggregate");
3620 return;
3623 BrigType16_t formal_arg_type
3624 = get_format_argument_type (parm_decl_type, src->m_type);
3625 if (hsa_seen_error ())
3626 return;
3628 if (src->m_type != formal_arg_type)
3629 src = src->get_in_type (formal_arg_type, hbb);
3631 addr
3632 = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3633 parm_decl_type: TREE_TYPE (parm), i);
3634 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3635 src, addr);
3637 hbb->append_insn (mem);
3640 call_insn->m_input_args.safe_push (addr->m_symbol);
3641 if (parm_type_chain)
3642 parm_type_chain = TREE_CHAIN (parm_type_chain);
3645 call_insn->m_args_code_list = new hsa_op_code_list (args);
3646 hbb->append_insn (call_insn);
3648 tree result_type = TREE_TYPE (TREE_TYPE (decl));
3650 tree result = gimple_call_lhs (stmt);
3651 hsa_insn_mem *result_insn = NULL;
3652 if (!VOID_TYPE_P (result_type))
3654 hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3656 /* Even if result of a function call is unused, we have to emit
3657 declaration for the result. */
3658 if (result && assign_lhs)
3660 tree lhs_type = TREE_TYPE (result);
3662 if (hsa_seen_error ())
3663 return;
3665 if (AGGREGATE_TYPE_P (lhs_type))
3667 BrigAlignment8_t align;
3668 hsa_op_address *result_addr
3669 = gen_hsa_addr_with_align (result, hbb, &align);
3670 gen_hsa_memory_copy (hbb, result_addr, addr,
3671 addr->m_symbol->total_byte_size (), align);
3673 else
3675 BrigType16_t mtype
3676 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3677 false));
3679 hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3680 result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3681 hbb->append_insn (result_insn);
3685 call_insn->m_output_arg = addr->m_symbol;
3686 call_insn->m_result_code_list = new hsa_op_code_list (1);
3688 else
3690 if (result)
3692 HSA_SORRY_AT (gimple_location (stmt),
3693 "support for HSA does not implement an assignment of "
3694 "return value from a void function");
3695 return;
3698 call_insn->m_result_code_list = new hsa_op_code_list (0);
3701 /* Argument block end. */
3702 hsa_insn_arg_block *arg_end
3703 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3704 hbb->append_insn (arg_end);
3707 /* Generate HSA instructions for a direct call of an internal fn.
3708 Instructions will be appended to HBB, which also needs to be the
3709 corresponding structure to the basic_block of STMT. */
3711 static void
3712 gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3714 tree lhs = gimple_call_lhs (stmt);
3715 if (!lhs)
3716 return;
3718 tree lhs_type = TREE_TYPE (lhs);
3719 tree rhs1 = gimple_call_arg (stmt, 0);
3720 tree rhs1_type = TREE_TYPE (rhs1);
3721 enum internal_fn fn = gimple_call_internal_fn (stmt);
3722 hsa_internal_fn *ifn
3723 = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3724 hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3726 gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3728 if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3729 hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3731 hsa_insn_arg_block *arg_start
3732 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3733 hbb->append_insn (arg_start);
3735 unsigned num_args = gimple_call_num_args (stmt);
3737 /* Function arguments. */
3738 for (unsigned i = 0; i < num_args; i++)
3740 tree parm = gimple_call_arg (stmt, (int)i);
3741 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3743 hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3744 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3745 src, addr);
3747 call_insn->m_input_args.safe_push (addr->m_symbol);
3748 hbb->append_insn (mem);
3751 call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3752 hbb->append_insn (call_insn);
3754 /* Assign returned value. */
3755 hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3757 call_insn->m_output_arg = addr->m_symbol;
3758 call_insn->m_result_code_list = new hsa_op_code_list (1);
3760 /* Argument block end. */
3761 hsa_insn_arg_block *arg_end
3762 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3763 hbb->append_insn (arg_end);
3766 /* Generate HSA instructions for a return value instruction.
3767 Instructions will be appended to HBB, which also needs to be the
3768 corresponding structure to the basic_block of STMT. */
3770 static void
3771 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3773 tree retval = gimple_return_retval (stmt);
3774 if (retval)
3776 hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3778 if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3780 BrigAlignment8_t align;
3781 hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3782 &align);
3783 gen_hsa_memory_copy (hbb, addr, retval_addr,
3784 hsa_cfun->m_output_arg->total_byte_size (),
3785 align);
3787 else
3789 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3790 false);
3791 BrigType16_t mtype = mem_type_for_type (t);
3793 /* Store of return value. */
3794 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3795 src = src->get_in_type (mtype, hbb);
3796 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3797 addr);
3798 hbb->append_insn (mem);
3802 /* HSAIL return instruction emission. */
3803 hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3804 hbb->append_insn (ret);
3807 /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3808 can have a different type, conversion instructions are possibly
3809 appended to HBB. */
3811 void
3812 hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3813 hsa_bb *hbb)
3815 hsa_insn_basic *insn;
3816 gcc_checking_assert (op_output_p (op_index));
3818 if (dest->m_type == m_type)
3820 set_op (op_index, dest);
3821 return;
3824 hsa_op_reg *tmp = new hsa_op_reg (m_type);
3825 set_op (op_index, tmp);
3827 if (hsa_needs_cvt (dest->m_type, m_type))
3828 insn = new hsa_insn_cvt (dest, tmp);
3829 else
3830 insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3831 dest, tmp->get_in_type (dest->m_type, hbb));
3833 hbb->append_insn (insn);
3836 /* Generate instruction OPCODE to query a property of HSA grid along the
3837 given DIMENSION. Store result into DEST and append the instruction to
3838 HBB. */
3840 static void
3841 query_hsa_grid (hsa_op_reg *dest, BrigType16_t opcode, int dimension,
3842 hsa_bb *hbb)
3844 /* We're using just one-dimensional kernels, so hard-coded
3845 dimension X. */
3846 hsa_op_immed *imm
3847 = new hsa_op_immed (dimension, (BrigKind16_t) BRIG_TYPE_U32);
3848 hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3849 imm);
3850 hbb->append_insn (insn);
3851 insn->set_output_in_type (dest, 0, hbb);
3854 /* Generate a special HSA-related instruction for gimple STMT.
3855 Instructions are appended to basic block HBB. */
3857 static void
3858 query_hsa_grid (gimple *stmt, BrigOpcode16_t opcode, int dimension,
3859 hsa_bb *hbb)
3861 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3862 if (lhs == NULL_TREE)
3863 return;
3865 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3867 query_hsa_grid (dest, opcode, dimension, hbb);
3870 /* Emit instructions that set hsa_num_threads according to provided VALUE.
3871 Instructions are appended to basic block HBB. */
3873 static void
3874 gen_set_num_threads (tree value, hsa_bb *hbb)
3876 hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3877 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3879 src = src->get_in_type (hsa_num_threads->m_type, hbb);
3880 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3882 hsa_insn_basic *basic
3883 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3884 hbb->append_insn (basic);
3887 /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3888 is defined in plugin-hsa.c. */
3890 static HOST_WIDE_INT
3891 get_hsa_kernel_dispatch_offset (const char *field_name)
3893 tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3894 if (*hsa_kernel_dispatch_type == NULL)
3896 /* Collection of information needed for a dispatch of a kernel from a
3897 kernel. Keep in sync with libgomp's plugin-hsa.c. */
3899 *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
3900 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3901 get_identifier ("queue"), ptr_type_node);
3902 DECL_CHAIN (id_f1) = NULL_TREE;
3903 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3904 get_identifier ("omp_data_memory"),
3905 ptr_type_node);
3906 DECL_CHAIN (id_f2) = id_f1;
3907 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3908 get_identifier ("kernarg_address"),
3909 ptr_type_node);
3910 DECL_CHAIN (id_f3) = id_f2;
3911 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3912 get_identifier ("object"),
3913 uint64_type_node);
3914 DECL_CHAIN (id_f4) = id_f3;
3915 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3916 get_identifier ("signal"),
3917 uint64_type_node);
3918 DECL_CHAIN (id_f5) = id_f4;
3919 tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3920 get_identifier ("private_segment_size"),
3921 uint32_type_node);
3922 DECL_CHAIN (id_f6) = id_f5;
3923 tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3924 get_identifier ("group_segment_size"),
3925 uint32_type_node);
3926 DECL_CHAIN (id_f7) = id_f6;
3927 tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3928 get_identifier ("kernel_dispatch_count"),
3929 uint64_type_node);
3930 DECL_CHAIN (id_f8) = id_f7;
3931 tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3932 get_identifier ("debug"),
3933 uint64_type_node);
3934 DECL_CHAIN (id_f9) = id_f8;
3935 tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3936 get_identifier ("omp_level"),
3937 uint64_type_node);
3938 DECL_CHAIN (id_f10) = id_f9;
3939 tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3940 get_identifier ("children_dispatches"),
3941 ptr_type_node);
3942 DECL_CHAIN (id_f11) = id_f10;
3943 tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3944 get_identifier ("omp_num_threads"),
3945 uint32_type_node);
3946 DECL_CHAIN (id_f12) = id_f11;
3949 finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
3950 id_f12, NULL_TREE);
3951 TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
3954 for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
3955 chain != NULL_TREE; chain = TREE_CHAIN (chain))
3956 if (strcmp (field_name, IDENTIFIER_POINTER (DECL_NAME (chain))) == 0)
3957 return int_byte_position (chain);
3959 gcc_unreachable ();
3962 /* Return an HSA register that will contain number of threads for
3963 a future dispatched kernel. Instructions are added to HBB. */
3965 static hsa_op_reg *
3966 gen_num_threads_for_dispatch (hsa_bb *hbb)
3968 /* Step 1) Assign to number of threads:
3969 MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads). */
3970 hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
3971 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3973 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
3974 threads, addr));
3976 hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
3977 BRIG_TYPE_U32);
3978 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3979 hsa_insn_cmp * cmp
3980 = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
3981 hbb->append_insn (cmp);
3983 BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
3984 hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
3986 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
3987 threads, limit));
3989 /* Step 2) If the number is equal to zero,
3990 return shadow->omp_num_threads. */
3991 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
3993 hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
3994 addr
3995 = new hsa_op_address (shadow_reg_ptr,
3996 get_hsa_kernel_dispatch_offset ("omp_num_threads"));
3997 hsa_insn_basic *basic
3998 = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
3999 shadow_thread_count, addr);
4000 hbb->append_insn (basic);
4002 hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
4003 r = new hsa_op_reg (BRIG_TYPE_B1);
4004 hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
4005 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
4006 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
4007 shadow_thread_count, tmp));
4009 hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
4011 return as_a <hsa_op_reg *> (dest);
4015 /* Emit instructions that assign number of teams to lhs of gimple STMT.
4016 Instructions are appended to basic block HBB. */
4018 static void
4019 gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4021 if (gimple_call_lhs (stmt) == NULL_TREE)
4022 return;
4024 hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4026 tree lhs = gimple_call_lhs (stmt);
4027 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4028 hsa_op_immed *one = new hsa_op_immed (1, dest->m_type);
4030 hsa_insn_basic *basic
4031 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, one);
4033 hbb->append_insn (basic);
4036 /* Emit instructions that assign a team number to lhs of gimple STMT.
4037 Instructions are appended to basic block HBB. */
4039 static void
4040 gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4042 if (gimple_call_lhs (stmt) == NULL_TREE)
4043 return;
4045 hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4047 tree lhs = gimple_call_lhs (stmt);
4048 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4049 hsa_op_immed *zero = new hsa_op_immed (0, dest->m_type);
4051 hsa_insn_basic *basic
4052 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, zero);
4054 hbb->append_insn (basic);
4057 /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4058 Instructions are appended to basic block HBB. */
4060 static void
4061 gen_get_level (gimple *stmt, hsa_bb *hbb)
4063 if (gimple_call_lhs (stmt) == NULL_TREE)
4064 return;
4066 hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4068 tree lhs = gimple_call_lhs (stmt);
4069 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4071 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4072 if (shadow_reg_ptr == NULL)
4074 HSA_SORRY_AT (gimple_location (stmt),
4075 "support for HSA does not implement omp_get_level called "
4076 "from a function not being inlined within a kernel");
4077 return;
4080 hsa_op_address *addr
4081 = new hsa_op_address (shadow_reg_ptr,
4082 get_hsa_kernel_dispatch_offset ("omp_level"));
4084 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4085 (hsa_op_base *) NULL, addr);
4086 hbb->append_insn (mem);
4087 mem->set_output_in_type (dest, 0, hbb);
4090 /* Emit instruction that implement omp_get_max_threads of gimple STMT. */
4092 static void
4093 gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4095 tree lhs = gimple_call_lhs (stmt);
4096 if (!lhs)
4097 return;
4099 hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4101 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4102 hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4103 ->get_in_type (dest->m_type, hbb);
4104 hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4107 /* Emit instructions that implement alloca builtin gimple STMT.
4108 Instructions are appended to basic block HBB. */
4110 static void
4111 gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4113 tree lhs = gimple_call_lhs (call);
4114 if (lhs == NULL_TREE)
4115 return;
4117 built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
4119 gcc_checking_assert (fn == BUILT_IN_ALLOCA
4120 || fn == BUILT_IN_ALLOCA_WITH_ALIGN);
4122 unsigned bit_alignment = 0;
4124 if (fn == BUILT_IN_ALLOCA_WITH_ALIGN)
4126 tree alignment_tree = gimple_call_arg (call, 1);
4127 if (TREE_CODE (alignment_tree) != INTEGER_CST)
4129 HSA_SORRY_ATV (gimple_location (call),
4130 "support for HSA does not implement "
4131 "__builtin_alloca_with_align with a non-constant "
4132 "alignment: %E", alignment_tree);
4135 bit_alignment = tree_to_uhwi (alignment_tree);
4138 tree rhs1 = gimple_call_arg (call, 0);
4139 hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4140 ->get_in_type (BRIG_TYPE_U32, hbb);
4141 hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4143 hsa_op_reg *tmp
4144 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4145 hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4146 hbb->append_insn (a);
4148 hsa_insn_seg *seg
4149 = new hsa_insn_seg (BRIG_OPCODE_STOF,
4150 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4151 tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4152 hbb->append_insn (seg);
4155 /* Emit instructions that implement clrsb builtin STMT:
4156 Returns the number of leading redundant sign bits in x, i.e. the number
4157 of bits following the most significant bit that are identical to it.
4158 There are no special cases for 0 or other values.
4159 Instructions are appended to basic block HBB. */
4161 static void
4162 gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4164 tree lhs = gimple_call_lhs (call);
4165 if (lhs == NULL_TREE)
4166 return;
4168 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4169 tree rhs1 = gimple_call_arg (call, 0);
4170 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4171 BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4172 unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
4174 /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers. */
4175 gcc_checking_assert (bitsize == 32 || bitsize == 64);
4177 /* Set true to MOST_SIG if the most significant bit is set to one. */
4178 hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4179 hsa_uint_for_bitsize (bitsize));
4181 hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4182 gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4184 hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4185 hsa_insn_cmp *cmp
4186 = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4187 and_reg, c);
4188 hbb->append_insn (cmp);
4190 /* If the most significant bit is one, negate the input. Otherwise
4191 shift the input value to left by one bit. */
4192 hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4193 gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4195 hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4196 gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4197 new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4199 /* Assign the value that can be used for FIRSTBIT instruction according
4200 to the most significant bit. */
4201 hsa_op_reg *tmp = new hsa_op_reg (bittype);
4202 hsa_insn_basic *cmov
4203 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4204 arg_neg, shifted_arg);
4205 hbb->append_insn (cmov);
4207 hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4208 gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4209 tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4210 hbb), hbb);
4212 /* Set flag if the input value is equal to zero. */
4213 hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4214 cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4215 new hsa_op_immed (0, arg->m_type));
4216 hbb->append_insn (cmp);
4218 /* Return the number of leading bits,
4219 or (bitsize - 1) if the input value is zero. */
4220 cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
4221 new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
4222 leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4223 hbb->append_insn (cmov);
4224 cmov->set_output_in_type (dest, 0, hbb);
4227 /* Emit instructions that implement ffs builtin STMT:
4228 Returns one plus the index of the least significant 1-bit of x,
4229 or if x is zero, returns zero.
4230 Instructions are appended to basic block HBB. */
4232 static void
4233 gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4235 tree lhs = gimple_call_lhs (call);
4236 if (lhs == NULL_TREE)
4237 return;
4239 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4241 tree rhs1 = gimple_call_arg (call, 0);
4242 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4244 hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4245 hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4246 tmp->m_type, arg->m_type,
4247 tmp, arg);
4248 hbb->append_insn (insn);
4250 hsa_insn_basic *addition
4251 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4252 new hsa_op_immed (1, tmp->m_type));
4253 hbb->append_insn (addition);
4254 addition->set_output_in_type (dest, 0, hbb);
4257 static void
4258 gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4260 gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4262 if (hsa_type_bit_size (arg->m_type) < 32)
4263 arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4265 if (!hsa_btype_p (arg->m_type))
4266 arg = arg->get_in_type (hsa_bittype_for_type (arg->m_type), hbb);
4268 hsa_insn_srctype *popcount
4269 = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4270 arg->m_type, NULL, arg);
4271 hbb->append_insn (popcount);
4272 popcount->set_output_in_type (dest, 0, hbb);
4275 /* Emit instructions that implement parity builtin STMT:
4276 Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4277 Instructions are appended to basic block HBB. */
4279 static void
4280 gen_hsa_parity (gcall *call, hsa_bb *hbb)
4282 tree lhs = gimple_call_lhs (call);
4283 if (lhs == NULL_TREE)
4284 return;
4286 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4287 tree rhs1 = gimple_call_arg (call, 0);
4288 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4290 hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4291 gen_hsa_popcount_to_dest (popcount, arg, hbb);
4293 hsa_insn_basic *insn
4294 = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4295 new hsa_op_immed (2, popcount->m_type));
4296 hbb->append_insn (insn);
4297 insn->set_output_in_type (dest, 0, hbb);
4300 /* Emit instructions that implement popcount builtin STMT.
4301 Instructions are appended to basic block HBB. */
4303 static void
4304 gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4306 tree lhs = gimple_call_lhs (call);
4307 if (lhs == NULL_TREE)
4308 return;
4310 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4311 tree rhs1 = gimple_call_arg (call, 0);
4312 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4314 gen_hsa_popcount_to_dest (dest, arg, hbb);
4317 /* Set VALUE to a shadow kernel debug argument and append a new instruction
4318 to HBB basic block. */
4320 static void
4321 set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4323 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4324 if (shadow_reg_ptr == NULL)
4325 return;
4327 hsa_op_address *addr
4328 = new hsa_op_address (shadow_reg_ptr,
4329 get_hsa_kernel_dispatch_offset ("debug"));
4330 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4331 addr);
4332 hbb->append_insn (mem);
4335 void
4336 omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4338 if (m_sorry)
4340 if (m_warning_message)
4341 HSA_SORRY_AT (gimple_location (stmt), m_warning_message)
4342 else
4343 HSA_SORRY_ATV (gimple_location (stmt),
4344 "Support for HSA does not implement calls to %s\n",
4345 m_name)
4347 else if (m_warning_message != NULL)
4348 warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4350 if (m_return_value != NULL)
4352 tree lhs = gimple_call_lhs (stmt);
4353 if (!lhs)
4354 return;
4356 hbb->append_insn (new hsa_insn_comment (m_name));
4358 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4359 hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4360 hsa_build_append_simple_mov (dest, op, hbb);
4364 /* If STMT is a call of a known library function, generate code to perform
4365 it and return true. */
4367 static bool
4368 gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4370 bool handled = false;
4371 const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4373 char *copy = NULL;
4374 size_t len = strlen (name);
4375 if (len > 0 && name[len - 1] == '_')
4377 copy = XNEWVEC (char, len + 1);
4378 strcpy (copy, name);
4379 copy[len - 1] = '\0';
4380 name = copy;
4383 /* Handle omp_* routines. */
4384 if (strstr (name, "omp_") == name)
4386 hsa_init_simple_builtins ();
4387 omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4388 if (builtin)
4390 builtin->generate (stmt, hbb);
4391 return true;
4394 handled = true;
4395 if (strcmp (name, "omp_set_num_threads") == 0)
4396 gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4397 else if (strcmp (name, "omp_get_thread_num") == 0)
4399 hbb->append_insn (new hsa_insn_comment (name));
4400 query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
4402 else if (strcmp (name, "omp_get_num_threads") == 0)
4404 hbb->append_insn (new hsa_insn_comment (name));
4405 query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
4407 else if (strcmp (name, "omp_get_num_teams") == 0)
4408 gen_get_num_teams (stmt, hbb);
4409 else if (strcmp (name, "omp_get_team_num") == 0)
4410 gen_get_team_num (stmt, hbb);
4411 else if (strcmp (name, "omp_get_level") == 0)
4412 gen_get_level (stmt, hbb);
4413 else if (strcmp (name, "omp_get_active_level") == 0)
4414 gen_get_level (stmt, hbb);
4415 else if (strcmp (name, "omp_in_parallel") == 0)
4416 gen_get_level (stmt, hbb);
4417 else if (strcmp (name, "omp_get_max_threads") == 0)
4418 gen_get_max_threads (stmt, hbb);
4419 else
4420 handled = false;
4422 if (handled)
4424 if (copy)
4425 free (copy);
4426 return true;
4430 if (strcmp (name, "__hsa_set_debug_value") == 0)
4432 handled = true;
4433 if (hsa_cfun->has_shadow_reg_p ())
4435 tree rhs1 = gimple_call_arg (stmt, 0);
4436 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4438 src = src->get_in_type (BRIG_TYPE_U64, hbb);
4439 set_debug_value (hbb, src);
4443 if (copy)
4444 free (copy);
4445 return handled;
4448 /* Helper functions to create a single unary HSA operations out of calls to
4449 builtins. OPCODE is the HSA operation to be generated. STMT is a gimple
4450 call to a builtin. HBB is the HSA BB to which the instruction should be
4451 added. Note that nothing will be created if STMT does not have a LHS. */
4453 static void
4454 gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4456 tree lhs = gimple_call_lhs (stmt);
4457 if (!lhs)
4458 return;
4459 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4460 hsa_op_with_type *op
4461 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4462 gen_hsa_unary_operation (opcode, dest, op, hbb);
4465 /* Helper functions to create a call to standard library if LHS of the
4466 STMT is used. HBB is the HSA BB to which the instruction should be
4467 added. */
4469 static void
4470 gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4472 tree lhs = gimple_call_lhs (stmt);
4473 if (!lhs)
4474 return;
4476 if (gimple_call_internal_p (stmt))
4477 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4478 else
4479 gen_hsa_insns_for_direct_call (stmt, hbb);
4482 /* Helper functions to create a single unary HSA operations out of calls to
4483 builtins (if unsafe math optimizations are enable). Otherwise, create
4484 a call to standard library function.
4485 OPCODE is the HSA operation to be generated. STMT is a gimple
4486 call to a builtin. HBB is the HSA BB to which the instruction should be
4487 added. Note that nothing will be created if STMT does not have a LHS. */
4489 static void
4490 gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4491 hsa_bb *hbb)
4493 if (flag_unsafe_math_optimizations)
4494 gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4495 else
4496 gen_hsa_unaryop_builtin_call (stmt, hbb);
4499 /* Generate HSA address corresponding to a value VAL (as opposed to a memory
4500 reference tree), for example an SSA_NAME or an ADDR_EXPR. HBB is the HSA BB
4501 to which the instruction should be added. */
4503 static hsa_op_address *
4504 get_address_from_value (tree val, hsa_bb *hbb)
4506 switch (TREE_CODE (val))
4508 case SSA_NAME:
4510 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4511 hsa_op_base *reg
4512 = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4513 return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4515 case ADDR_EXPR:
4516 return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4518 case INTEGER_CST:
4519 if (tree_fits_shwi_p (val))
4520 return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
4521 /* fall-through */
4523 default:
4524 HSA_SORRY_ATV (EXPR_LOCATION (val),
4525 "support for HSA does not implement memory access to %E",
4526 val);
4527 return new hsa_op_address (NULL, NULL, 0);
4531 /* Expand assignment of a result of a string BUILTIN to DST.
4532 Size of the operation is N bytes, where instructions
4533 will be append to HBB. */
4535 static void
4536 expand_lhs_of_string_op (gimple *stmt,
4537 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4538 enum built_in_function builtin)
4540 /* If LHS is expected, we need to emit a PHI instruction. */
4541 tree lhs = gimple_call_lhs (stmt);
4542 if (!lhs)
4543 return;
4545 hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4547 hsa_op_with_type *dst_reg
4548 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4549 hsa_op_with_type *tmp;
4551 switch (builtin)
4553 case BUILT_IN_MEMPCPY:
4555 tmp = new hsa_op_reg (dst_reg->m_type);
4556 hsa_insn_basic *add
4557 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4558 tmp, dst_reg,
4559 new hsa_op_immed (n, dst_reg->m_type));
4560 hbb->append_insn (add);
4561 break;
4563 case BUILT_IN_MEMCPY:
4564 case BUILT_IN_MEMSET:
4565 tmp = dst_reg;
4566 break;
4567 default:
4568 gcc_unreachable ();
4571 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4572 lhs_reg, tmp));
4575 #define HSA_MEMORY_BUILTINS_LIMIT 128
4577 /* Expand a string builtin (from a gimple STMT) in a way that
4578 according to MISALIGNED_FLAG we process either direct emission
4579 (a bunch of memory load and store instructions), or we emit a function call
4580 of a library function (for instance 'memcpy'). Actually, a basic block
4581 for direct emission is just prepared, where caller is responsible
4582 for emission of corresponding instructions.
4583 All instruction are appended to HBB. */
4585 hsa_bb *
4586 expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4587 hsa_op_reg *misaligned_flag)
4589 edge e = split_block (hbb->m_bb, stmt);
4590 basic_block condition_bb = e->src;
4591 hbb->append_insn (new hsa_insn_br (misaligned_flag));
4593 /* Prepare the control flow. */
4594 edge condition_edge = EDGE_SUCC (condition_bb, 0);
4595 basic_block call_bb = split_edge (condition_edge);
4597 basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4598 basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4599 basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4601 condition_edge->flags &= ~EDGE_FALLTHRU;
4602 condition_edge->flags |= EDGE_TRUE_VALUE;
4603 make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4605 redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4607 hsa_cfun->m_modified_cfg = true;
4609 hsa_init_new_bb (expanded_bb);
4611 /* Slow path: function call. */
4612 gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4614 return hsa_bb_for_bb (expanded_bb);
4617 /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4618 a gimple STMT and store all necessary instruction to HBB basic block. */
4620 static void
4621 expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4623 tree byte_size = gimple_call_arg (stmt, 2);
4625 if (!tree_fits_uhwi_p (byte_size))
4627 gen_hsa_insns_for_direct_call (stmt, hbb);
4628 return;
4631 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4633 if (n > HSA_MEMORY_BUILTINS_LIMIT)
4635 gen_hsa_insns_for_direct_call (stmt, hbb);
4636 return;
4639 tree dst = gimple_call_arg (stmt, 0);
4640 tree src = gimple_call_arg (stmt, 1);
4642 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4643 hsa_op_address *src_addr = get_address_from_value (src, hbb);
4645 /* As gen_hsa_memory_copy relies on memory alignment
4646 greater or equal to 8 bytes, we need to verify the alignment. */
4647 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4648 hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4649 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4651 convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4652 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4654 /* Process BIT OR for source and destination addresses. */
4655 hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4656 gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4657 dst_addr_reg, hbb);
4659 /* Process BIT AND with 0x7 to identify the desired alignment
4660 of 8 bytes. */
4661 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4663 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4664 new hsa_op_immed (7, addrtype), hbb);
4666 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4667 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4668 misaligned, masked,
4669 new hsa_op_immed (0, masked->m_type)));
4671 hsa_bb *native_impl_bb
4672 = expand_string_operation_builtin (stmt, hbb, misaligned);
4674 gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4675 hsa_bb *merge_bb
4676 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4677 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4681 /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4682 a gimple STMT and store all necessary instruction to HBB basic block.
4683 The operation set N bytes with a CONSTANT value. */
4685 static void
4686 expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4687 unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4688 enum built_in_function builtin)
4690 tree dst = gimple_call_arg (stmt, 0);
4691 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4693 /* As gen_hsa_memory_set relies on memory alignment
4694 greater or equal to 8 bytes, we need to verify the alignment. */
4695 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4696 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4697 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4699 /* Process BIT AND with 0x7 to identify the desired alignment
4700 of 8 bytes. */
4701 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4703 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4704 new hsa_op_immed (7, addrtype), hbb);
4706 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4707 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4708 misaligned, masked,
4709 new hsa_op_immed (0, masked->m_type)));
4711 hsa_bb *native_impl_bb
4712 = expand_string_operation_builtin (stmt, hbb, misaligned);
4714 gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4715 hsa_bb *merge_bb
4716 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4717 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4720 /* Return string for MEMMODEL. */
4722 static const char *
4723 get_memory_order_name (unsigned memmodel)
4725 switch (memmodel & MEMMODEL_BASE_MASK)
4727 case MEMMODEL_RELAXED:
4728 return "relaxed";
4729 case MEMMODEL_CONSUME:
4730 return "consume";
4731 case MEMMODEL_ACQUIRE:
4732 return "acquire";
4733 case MEMMODEL_RELEASE:
4734 return "release";
4735 case MEMMODEL_ACQ_REL:
4736 return "acq_rel";
4737 case MEMMODEL_SEQ_CST:
4738 return "seq_cst";
4739 default:
4740 return NULL;
4744 /* Return memory order according to predefined __atomic memory model
4745 constants. LOCATION is provided to locate the problematic statement. */
4747 static BrigMemoryOrder
4748 get_memory_order (unsigned memmodel, location_t location)
4750 switch (memmodel & MEMMODEL_BASE_MASK)
4752 case MEMMODEL_RELAXED:
4753 return BRIG_MEMORY_ORDER_RELAXED;
4754 case MEMMODEL_CONSUME:
4755 /* HSA does not have an equivalent, but we can use the slightly stronger
4756 ACQUIRE. */
4757 case MEMMODEL_ACQUIRE:
4758 return BRIG_MEMORY_ORDER_SC_ACQUIRE;
4759 case MEMMODEL_RELEASE:
4760 return BRIG_MEMORY_ORDER_SC_RELEASE;
4761 case MEMMODEL_ACQ_REL:
4762 case MEMMODEL_SEQ_CST:
4763 /* Callers implementing a simple load or store need to remove the release
4764 or acquire part respectively. */
4765 return BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4766 default:
4768 const char *mmname = get_memory_order_name (memmodel);
4769 HSA_SORRY_ATV (location,
4770 "support for HSA does not implement the specified "
4771 " memory model%s %s",
4772 mmname ? ": " : "", mmname ? mmname : "");
4773 return BRIG_MEMORY_ORDER_NONE;
4778 /* Helper function to create an HSA atomic binary operation instruction out of
4779 calls to atomic builtins. RET_ORIG is true if the built-in is the variant
4780 that return s the value before applying operation, and false if it should
4781 return the value after applying the operation (if it returns value at all).
4782 ACODE is the atomic operation code, STMT is a gimple call to a builtin. HBB
4783 is the HSA BB to which the instruction should be added. */
4785 static void
4786 gen_hsa_ternary_atomic_for_builtin (bool ret_orig,
4787 enum BrigAtomicOperation acode,
4788 gimple *stmt,
4789 hsa_bb *hbb)
4791 tree lhs = gimple_call_lhs (stmt);
4793 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
4794 BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
4795 BrigType16_t mtype = mem_type_for_type (hsa_type);
4796 tree model = gimple_call_arg (stmt, 2);
4798 if (!tree_fits_uhwi_p (model))
4800 HSA_SORRY_ATV (gimple_location (stmt),
4801 "support for HSA does not implement memory model %E",
4802 model);
4803 return;
4806 unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
4808 BrigMemoryOrder memorder = get_memory_order (mmodel, gimple_location (stmt));
4810 /* Certain atomic insns must have Bx memory types. */
4811 switch (acode)
4813 case BRIG_ATOMIC_LD:
4814 case BRIG_ATOMIC_ST:
4815 case BRIG_ATOMIC_AND:
4816 case BRIG_ATOMIC_OR:
4817 case BRIG_ATOMIC_XOR:
4818 case BRIG_ATOMIC_EXCH:
4819 mtype = hsa_bittype_for_type (mtype);
4820 break;
4821 default:
4822 break;
4825 hsa_op_reg *dest;
4826 int nops, opcode;
4827 if (lhs)
4829 if (ret_orig)
4830 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4831 else
4832 dest = new hsa_op_reg (hsa_type);
4833 opcode = BRIG_OPCODE_ATOMIC;
4834 nops = 3;
4836 else
4838 dest = NULL;
4839 opcode = BRIG_OPCODE_ATOMICNORET;
4840 nops = 2;
4843 if (acode == BRIG_ATOMIC_ST)
4845 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
4846 memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4848 if (memorder != BRIG_MEMORY_ORDER_RELAXED
4849 && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
4850 && memorder != BRIG_MEMORY_ORDER_NONE)
4852 HSA_SORRY_ATV (gimple_location (stmt),
4853 "support for HSA does not implement memory model for "
4854 "ATOMIC_ST: %s", get_memory_order_name (mmodel));
4855 return;
4859 hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype,
4860 memorder);
4862 hsa_op_address *addr;
4863 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
4864 if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
4866 HSA_SORRY_AT (gimple_location (stmt),
4867 "HSA does not implement atomic operations in private "
4868 "segment");
4869 return;
4871 hsa_op_base *op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1),
4872 hbb);
4874 if (lhs)
4876 atominsn->set_op (0, dest);
4877 atominsn->set_op (1, addr);
4878 atominsn->set_op (2, op);
4880 else
4882 atominsn->set_op (0, addr);
4883 atominsn->set_op (1, op);
4886 hbb->append_insn (atominsn);
4888 /* HSA does not natively support the variants that return the modified value,
4889 so re-do the operation again non-atomically if that is what was
4890 requested. */
4891 if (lhs && !ret_orig)
4893 int arith;
4894 switch (acode)
4896 case BRIG_ATOMIC_ADD:
4897 arith = BRIG_OPCODE_ADD;
4898 break;
4899 case BRIG_ATOMIC_AND:
4900 arith = BRIG_OPCODE_AND;
4901 break;
4902 case BRIG_ATOMIC_OR:
4903 arith = BRIG_OPCODE_OR;
4904 break;
4905 case BRIG_ATOMIC_SUB:
4906 arith = BRIG_OPCODE_SUB;
4907 break;
4908 case BRIG_ATOMIC_XOR:
4909 arith = BRIG_OPCODE_XOR;
4910 break;
4911 default:
4912 gcc_unreachable ();
4914 hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4915 gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
4919 /* Generate HSA instructions for an internal fn.
4920 Instructions will be appended to HBB, which also needs to be the
4921 corresponding structure to the basic_block of STMT. */
4923 static void
4924 gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
4926 gcc_checking_assert (gimple_call_internal_fn (stmt));
4927 internal_fn fn = gimple_call_internal_fn (stmt);
4929 bool is_float_type_p = false;
4930 if (gimple_call_lhs (stmt) != NULL
4931 && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
4932 is_float_type_p = true;
4934 switch (fn)
4936 case IFN_CEIL:
4937 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
4938 break;
4940 case IFN_FLOOR:
4941 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
4942 break;
4944 case IFN_RINT:
4945 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
4946 break;
4948 case IFN_SQRT:
4949 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
4950 break;
4952 case IFN_TRUNC:
4953 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
4954 break;
4956 case IFN_COS:
4958 if (is_float_type_p)
4959 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
4960 else
4961 gen_hsa_unaryop_builtin_call (stmt, hbb);
4963 break;
4965 case IFN_EXP2:
4967 if (is_float_type_p)
4968 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
4969 else
4970 gen_hsa_unaryop_builtin_call (stmt, hbb);
4972 break;
4975 case IFN_LOG2:
4977 if (is_float_type_p)
4978 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
4979 else
4980 gen_hsa_unaryop_builtin_call (stmt, hbb);
4982 break;
4985 case IFN_SIN:
4987 if (is_float_type_p)
4988 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
4989 else
4990 gen_hsa_unaryop_builtin_call (stmt, hbb);
4991 break;
4994 case IFN_CLRSB:
4995 gen_hsa_clrsb (stmt, hbb);
4996 break;
4998 case IFN_CLZ:
4999 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5000 break;
5002 case IFN_CTZ:
5003 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5004 break;
5006 case IFN_FFS:
5007 gen_hsa_ffs (stmt, hbb);
5008 break;
5010 case IFN_PARITY:
5011 gen_hsa_parity (stmt, hbb);
5012 break;
5014 case IFN_POPCOUNT:
5015 gen_hsa_popcount (stmt, hbb);
5016 break;
5018 case IFN_ACOS:
5019 case IFN_ASIN:
5020 case IFN_ATAN:
5021 case IFN_EXP:
5022 case IFN_EXP10:
5023 case IFN_EXPM1:
5024 case IFN_LOG:
5025 case IFN_LOG10:
5026 case IFN_LOG1P:
5027 case IFN_LOGB:
5028 case IFN_SIGNIFICAND:
5029 case IFN_TAN:
5030 case IFN_NEARBYINT:
5031 case IFN_ROUND:
5032 case IFN_ATAN2:
5033 case IFN_COPYSIGN:
5034 case IFN_FMOD:
5035 case IFN_POW:
5036 case IFN_REMAINDER:
5037 case IFN_SCALB:
5038 case IFN_FMIN:
5039 case IFN_FMAX:
5040 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
5041 break;
5043 default:
5044 HSA_SORRY_ATV (gimple_location (stmt),
5045 "support for HSA does not implement internal function: %s",
5046 internal_fn_name (fn));
5047 break;
5051 /* Generate HSA instructions for the given call statement STMT. Instructions
5052 will be appended to HBB. */
5054 static void
5055 gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5057 gcall *call = as_a <gcall *> (stmt);
5058 tree lhs = gimple_call_lhs (stmt);
5059 hsa_op_reg *dest;
5061 if (gimple_call_internal_p (stmt))
5063 gen_hsa_insn_for_internal_fn_call (call, hbb);
5064 return;
5067 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5069 tree function_decl = gimple_call_fndecl (stmt);
5070 if (function_decl == NULL_TREE)
5072 HSA_SORRY_AT (gimple_location (stmt),
5073 "support for HSA does not implement indirect calls");
5074 return;
5077 if (hsa_callable_function_p (function_decl))
5078 gen_hsa_insns_for_direct_call (stmt, hbb);
5079 else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5080 HSA_SORRY_AT (gimple_location (stmt),
5081 "HSA supports only calls of functions marked with pragma "
5082 "omp declare target");
5083 return;
5086 tree fndecl = gimple_call_fndecl (stmt);
5087 enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5088 switch (builtin)
5090 case BUILT_IN_FABS:
5091 case BUILT_IN_FABSF:
5092 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5093 break;
5095 case BUILT_IN_CEIL:
5096 case BUILT_IN_CEILF:
5097 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5098 break;
5100 case BUILT_IN_FLOOR:
5101 case BUILT_IN_FLOORF:
5102 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5103 break;
5105 case BUILT_IN_RINT:
5106 case BUILT_IN_RINTF:
5107 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5108 break;
5110 case BUILT_IN_SQRT:
5111 case BUILT_IN_SQRTF:
5112 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5113 break;
5115 case BUILT_IN_TRUNC:
5116 case BUILT_IN_TRUNCF:
5117 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5118 break;
5120 case BUILT_IN_COS:
5121 case BUILT_IN_SIN:
5122 case BUILT_IN_EXP2:
5123 case BUILT_IN_LOG2:
5124 /* HSAIL does not provide an instruction for double argument type. */
5125 gen_hsa_unaryop_builtin_call (stmt, hbb);
5126 break;
5128 case BUILT_IN_COSF:
5129 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5130 break;
5132 case BUILT_IN_EXP2F:
5133 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5134 break;
5136 case BUILT_IN_LOG2F:
5137 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5138 break;
5140 case BUILT_IN_SINF:
5141 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5142 break;
5144 case BUILT_IN_CLRSB:
5145 case BUILT_IN_CLRSBL:
5146 case BUILT_IN_CLRSBLL:
5147 gen_hsa_clrsb (call, hbb);
5148 break;
5150 case BUILT_IN_CLZ:
5151 case BUILT_IN_CLZL:
5152 case BUILT_IN_CLZLL:
5153 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5154 break;
5156 case BUILT_IN_CTZ:
5157 case BUILT_IN_CTZL:
5158 case BUILT_IN_CTZLL:
5159 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5160 break;
5162 case BUILT_IN_FFS:
5163 case BUILT_IN_FFSL:
5164 case BUILT_IN_FFSLL:
5165 gen_hsa_ffs (call, hbb);
5166 break;
5168 case BUILT_IN_PARITY:
5169 case BUILT_IN_PARITYL:
5170 case BUILT_IN_PARITYLL:
5171 gen_hsa_parity (call, hbb);
5172 break;
5174 case BUILT_IN_POPCOUNT:
5175 case BUILT_IN_POPCOUNTL:
5176 case BUILT_IN_POPCOUNTLL:
5177 gen_hsa_popcount (call, hbb);
5178 break;
5180 case BUILT_IN_ATOMIC_LOAD_1:
5181 case BUILT_IN_ATOMIC_LOAD_2:
5182 case BUILT_IN_ATOMIC_LOAD_4:
5183 case BUILT_IN_ATOMIC_LOAD_8:
5184 case BUILT_IN_ATOMIC_LOAD_16:
5186 BrigType16_t mtype;
5187 hsa_op_address *addr;
5188 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5189 tree model = gimple_call_arg (stmt, 1);
5190 if (!tree_fits_uhwi_p (model))
5192 HSA_SORRY_ATV (gimple_location (stmt),
5193 "support for HSA does not implement "
5194 "memory model: %E",
5195 model);
5196 return;
5199 unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
5200 BrigMemoryOrder memorder = get_memory_order (mmodel,
5201 gimple_location (stmt));
5203 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5204 memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5206 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5207 && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5208 && memorder != BRIG_MEMORY_ORDER_NONE)
5210 HSA_SORRY_ATV (gimple_location (stmt),
5211 "support for HSA does not implement "
5212 "memory model for ATOMIC_LD: %s",
5213 get_memory_order_name (mmodel));
5214 return;
5217 if (lhs)
5219 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5220 false);
5221 mtype = mem_type_for_type (t);
5222 mtype = hsa_bittype_for_type (mtype);
5223 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5225 else
5227 mtype = BRIG_TYPE_B64;
5228 dest = new hsa_op_reg (mtype);
5231 hsa_insn_atomic *atominsn
5232 = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD, mtype,
5233 memorder, dest, addr);
5235 hbb->append_insn (atominsn);
5236 break;
5239 case BUILT_IN_ATOMIC_EXCHANGE_1:
5240 case BUILT_IN_ATOMIC_EXCHANGE_2:
5241 case BUILT_IN_ATOMIC_EXCHANGE_4:
5242 case BUILT_IN_ATOMIC_EXCHANGE_8:
5243 case BUILT_IN_ATOMIC_EXCHANGE_16:
5244 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb);
5245 break;
5247 case BUILT_IN_ATOMIC_FETCH_ADD_1:
5248 case BUILT_IN_ATOMIC_FETCH_ADD_2:
5249 case BUILT_IN_ATOMIC_FETCH_ADD_4:
5250 case BUILT_IN_ATOMIC_FETCH_ADD_8:
5251 case BUILT_IN_ATOMIC_FETCH_ADD_16:
5252 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb);
5253 break;
5255 case BUILT_IN_ATOMIC_FETCH_SUB_1:
5256 case BUILT_IN_ATOMIC_FETCH_SUB_2:
5257 case BUILT_IN_ATOMIC_FETCH_SUB_4:
5258 case BUILT_IN_ATOMIC_FETCH_SUB_8:
5259 case BUILT_IN_ATOMIC_FETCH_SUB_16:
5260 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb);
5261 break;
5263 case BUILT_IN_ATOMIC_FETCH_AND_1:
5264 case BUILT_IN_ATOMIC_FETCH_AND_2:
5265 case BUILT_IN_ATOMIC_FETCH_AND_4:
5266 case BUILT_IN_ATOMIC_FETCH_AND_8:
5267 case BUILT_IN_ATOMIC_FETCH_AND_16:
5268 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb);
5269 break;
5271 case BUILT_IN_ATOMIC_FETCH_XOR_1:
5272 case BUILT_IN_ATOMIC_FETCH_XOR_2:
5273 case BUILT_IN_ATOMIC_FETCH_XOR_4:
5274 case BUILT_IN_ATOMIC_FETCH_XOR_8:
5275 case BUILT_IN_ATOMIC_FETCH_XOR_16:
5276 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb);
5277 break;
5279 case BUILT_IN_ATOMIC_FETCH_OR_1:
5280 case BUILT_IN_ATOMIC_FETCH_OR_2:
5281 case BUILT_IN_ATOMIC_FETCH_OR_4:
5282 case BUILT_IN_ATOMIC_FETCH_OR_8:
5283 case BUILT_IN_ATOMIC_FETCH_OR_16:
5284 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb);
5285 break;
5287 case BUILT_IN_ATOMIC_STORE_1:
5288 case BUILT_IN_ATOMIC_STORE_2:
5289 case BUILT_IN_ATOMIC_STORE_4:
5290 case BUILT_IN_ATOMIC_STORE_8:
5291 case BUILT_IN_ATOMIC_STORE_16:
5292 /* Since there cannot be any LHS, the first parameter is meaningless. */
5293 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb);
5294 break;
5296 case BUILT_IN_ATOMIC_ADD_FETCH_1:
5297 case BUILT_IN_ATOMIC_ADD_FETCH_2:
5298 case BUILT_IN_ATOMIC_ADD_FETCH_4:
5299 case BUILT_IN_ATOMIC_ADD_FETCH_8:
5300 case BUILT_IN_ATOMIC_ADD_FETCH_16:
5301 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb);
5302 break;
5304 case BUILT_IN_ATOMIC_SUB_FETCH_1:
5305 case BUILT_IN_ATOMIC_SUB_FETCH_2:
5306 case BUILT_IN_ATOMIC_SUB_FETCH_4:
5307 case BUILT_IN_ATOMIC_SUB_FETCH_8:
5308 case BUILT_IN_ATOMIC_SUB_FETCH_16:
5309 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb);
5310 break;
5312 case BUILT_IN_ATOMIC_AND_FETCH_1:
5313 case BUILT_IN_ATOMIC_AND_FETCH_2:
5314 case BUILT_IN_ATOMIC_AND_FETCH_4:
5315 case BUILT_IN_ATOMIC_AND_FETCH_8:
5316 case BUILT_IN_ATOMIC_AND_FETCH_16:
5317 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb);
5318 break;
5320 case BUILT_IN_ATOMIC_XOR_FETCH_1:
5321 case BUILT_IN_ATOMIC_XOR_FETCH_2:
5322 case BUILT_IN_ATOMIC_XOR_FETCH_4:
5323 case BUILT_IN_ATOMIC_XOR_FETCH_8:
5324 case BUILT_IN_ATOMIC_XOR_FETCH_16:
5325 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb);
5326 break;
5328 case BUILT_IN_ATOMIC_OR_FETCH_1:
5329 case BUILT_IN_ATOMIC_OR_FETCH_2:
5330 case BUILT_IN_ATOMIC_OR_FETCH_4:
5331 case BUILT_IN_ATOMIC_OR_FETCH_8:
5332 case BUILT_IN_ATOMIC_OR_FETCH_16:
5333 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb);
5334 break;
5336 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5337 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5338 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5339 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5340 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5342 /* TODO: Use the appropriate memory model for now. */
5343 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5345 BrigType16_t atype
5346 = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5348 hsa_insn_atomic *atominsn
5349 = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype,
5350 BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE);
5351 hsa_op_address *addr;
5352 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5354 if (lhs != NULL)
5355 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5356 else
5357 dest = new hsa_op_reg (atype);
5359 /* Should check what the memory scope is. */
5360 atominsn->m_memoryscope = BRIG_MEMORY_SCOPE_WORKGROUP;
5361 atominsn->set_op (0, dest);
5362 atominsn->set_op (1, addr);
5364 hsa_op_with_type *op
5365 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5366 atominsn->set_op (2, op);
5367 op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5368 atominsn->set_op (3, op);
5370 hbb->append_insn (atominsn);
5371 break;
5373 case BUILT_IN_GOMP_PARALLEL:
5374 HSA_SORRY_AT (gimple_location (stmt),
5375 "support for HSA does not implement non-gridified "
5376 "OpenMP parallel constructs.");
5377 break;
5378 case BUILT_IN_OMP_GET_THREAD_NUM:
5380 query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
5381 break;
5384 case BUILT_IN_OMP_GET_NUM_THREADS:
5386 query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
5387 break;
5389 case BUILT_IN_GOMP_TEAMS:
5391 gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5392 break;
5394 case BUILT_IN_OMP_GET_NUM_TEAMS:
5396 gen_get_num_teams (stmt, hbb);
5397 break;
5399 case BUILT_IN_OMP_GET_TEAM_NUM:
5401 gen_get_team_num (stmt, hbb);
5402 break;
5404 case BUILT_IN_MEMCPY:
5405 case BUILT_IN_MEMPCPY:
5407 expand_memory_copy (stmt, hbb, builtin);
5408 break;
5410 case BUILT_IN_MEMSET:
5412 tree c = gimple_call_arg (stmt, 1);
5414 if (TREE_CODE (c) != INTEGER_CST)
5416 gen_hsa_insns_for_direct_call (stmt, hbb);
5417 return;
5420 tree byte_size = gimple_call_arg (stmt, 2);
5422 if (!tree_fits_uhwi_p (byte_size))
5424 gen_hsa_insns_for_direct_call (stmt, hbb);
5425 return;
5428 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5430 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5432 gen_hsa_insns_for_direct_call (stmt, hbb);
5433 return;
5436 unsigned HOST_WIDE_INT constant
5437 = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5439 expand_memory_set (stmt, n, constant, hbb, builtin);
5441 break;
5443 case BUILT_IN_BZERO:
5445 tree byte_size = gimple_call_arg (stmt, 1);
5447 if (!tree_fits_uhwi_p (byte_size))
5449 gen_hsa_insns_for_direct_call (stmt, hbb);
5450 return;
5453 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5455 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5457 gen_hsa_insns_for_direct_call (stmt, hbb);
5458 return;
5461 expand_memory_set (stmt, n, 0, hbb, builtin);
5463 break;
5465 case BUILT_IN_ALLOCA:
5466 case BUILT_IN_ALLOCA_WITH_ALIGN:
5468 gen_hsa_alloca (call, hbb);
5469 break;
5471 default:
5473 gen_hsa_insns_for_direct_call (stmt, hbb);
5474 return;
5479 /* Generate HSA instructions for a given gimple statement. Instructions will be
5480 appended to HBB. */
5482 static void
5483 gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5485 switch (gimple_code (stmt))
5487 case GIMPLE_ASSIGN:
5488 if (gimple_clobber_p (stmt))
5489 break;
5491 if (gimple_assign_single_p (stmt))
5493 tree lhs = gimple_assign_lhs (stmt);
5494 tree rhs = gimple_assign_rhs1 (stmt);
5495 gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5497 else
5498 gen_hsa_insns_for_operation_assignment (stmt, hbb);
5499 break;
5500 case GIMPLE_RETURN:
5501 gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5502 break;
5503 case GIMPLE_COND:
5504 gen_hsa_insns_for_cond_stmt (stmt, hbb);
5505 break;
5506 case GIMPLE_CALL:
5507 gen_hsa_insns_for_call (stmt, hbb);
5508 break;
5509 case GIMPLE_DEBUG:
5510 /* ??? HSA supports some debug facilities. */
5511 break;
5512 case GIMPLE_LABEL:
5514 tree label = gimple_label_label (as_a <glabel *> (stmt));
5515 if (FORCED_LABEL (label))
5516 HSA_SORRY_AT (gimple_location (stmt),
5517 "support for HSA does not implement gimple label with "
5518 "address taken");
5520 break;
5522 case GIMPLE_NOP:
5524 hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5525 break;
5527 case GIMPLE_SWITCH:
5529 gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5530 break;
5532 default:
5533 HSA_SORRY_ATV (gimple_location (stmt),
5534 "support for HSA does not implement gimple statement %s",
5535 gimple_code_name[(int) gimple_code (stmt)]);
5539 /* Generate a HSA PHI from a gimple PHI. */
5541 static void
5542 gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5544 hsa_insn_phi *hphi;
5545 unsigned count = gimple_phi_num_args (phi_stmt);
5547 hsa_op_reg *dest
5548 = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5549 hphi = new hsa_insn_phi (count, dest);
5550 hphi->m_bb = hbb->m_bb;
5552 tree lhs = gimple_phi_result (phi_stmt);
5554 for (unsigned i = 0; i < count; i++)
5556 tree op = gimple_phi_arg_def (phi_stmt, i);
5558 if (TREE_CODE (op) == SSA_NAME)
5560 hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5561 hphi->set_op (i, hreg);
5563 else
5565 gcc_assert (is_gimple_min_invariant (op));
5566 tree t = TREE_TYPE (op);
5567 if (!POINTER_TYPE_P (t)
5568 || (TREE_CODE (op) == STRING_CST
5569 && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5570 hphi->set_op (i, new hsa_op_immed (op));
5571 else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5572 && TREE_CODE (op) == INTEGER_CST)
5574 /* Handle assignment of NULL value to a pointer type. */
5575 hphi->set_op (i, new hsa_op_immed (op));
5577 else if (TREE_CODE (op) == ADDR_EXPR)
5579 edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5580 hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5581 hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5582 hbb_src);
5584 hsa_op_reg *dest
5585 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
5586 hsa_insn_basic *insn
5587 = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5588 dest, addr);
5589 hbb_src->append_insn (insn);
5591 hphi->set_op (i, dest);
5593 else
5595 HSA_SORRY_AT (gimple_location (phi_stmt),
5596 "support for HSA does not handle PHI nodes with "
5597 "constant address operands");
5598 return;
5603 hphi->m_prev = hbb->m_last_phi;
5604 hphi->m_next = NULL;
5605 if (hbb->m_last_phi)
5606 hbb->m_last_phi->m_next = hphi;
5607 hbb->m_last_phi = hphi;
5608 if (!hbb->m_first_phi)
5609 hbb->m_first_phi = hphi;
5612 /* Constructor of class containing HSA-specific information about a basic
5613 block. CFG_BB is the CFG BB this HSA BB is associated with. IDX is the new
5614 index of this BB (so that the constructor does not attempt to use
5615 hsa_cfun during its construction). */
5617 hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5618 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5619 m_last_phi (NULL), m_index (idx), m_liveout (BITMAP_ALLOC (NULL)),
5620 m_livein (BITMAP_ALLOC (NULL))
5622 gcc_assert (!cfg_bb->aux);
5623 cfg_bb->aux = this;
5626 /* Constructor of class containing HSA-specific information about a basic
5627 block. CFG_BB is the CFG BB this HSA BB is associated with. */
5629 hsa_bb::hsa_bb (basic_block cfg_bb)
5630 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5631 m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++),
5632 m_liveout (BITMAP_ALLOC (NULL)), m_livein (BITMAP_ALLOC (NULL))
5634 gcc_assert (!cfg_bb->aux);
5635 cfg_bb->aux = this;
5638 /* Destructor of class representing HSA BB. */
5640 hsa_bb::~hsa_bb ()
5642 BITMAP_FREE (m_livein);
5643 BITMAP_FREE (m_liveout);
5646 /* Create and initialize and return a new hsa_bb structure for a given CFG
5647 basic block BB. */
5649 hsa_bb *
5650 hsa_init_new_bb (basic_block bb)
5652 return new (*hsa_allocp_bb) hsa_bb (bb);
5655 /* Initialize OMP in an HSA basic block PROLOGUE. */
5657 static void
5658 init_prologue (void)
5660 if (!hsa_cfun->m_kern_p)
5661 return;
5663 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5665 /* Create a magic number that is going to be printed by libgomp. */
5666 unsigned index = hsa_get_number_decl_kernel_mappings ();
5668 /* Emit store to debug argument. */
5669 if (PARAM_VALUE (PARAM_HSA_GEN_DEBUG_STORES) > 0)
5670 set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5673 /* Initialize hsa_num_threads to a default value. */
5675 static void
5676 init_hsa_num_threads (void)
5678 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5680 /* Save the default value to private variable hsa_num_threads. */
5681 hsa_insn_basic *basic
5682 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5683 new hsa_op_immed (0, hsa_num_threads->m_type),
5684 new hsa_op_address (hsa_num_threads));
5685 prologue->append_insn (basic);
5688 /* Go over gimple representation and generate our internal HSA one. */
5690 static void
5691 gen_body_from_gimple ()
5693 basic_block bb;
5695 /* Verify CFG for complex edges we are unable to handle. */
5696 edge_iterator ei;
5697 edge e;
5699 FOR_EACH_BB_FN (bb, cfun)
5701 FOR_EACH_EDGE (e, ei, bb->succs)
5703 /* Verify all unsupported flags for edges that point
5704 to the same basic block. */
5705 if (e->flags & EDGE_EH)
5707 HSA_SORRY_AT (UNKNOWN_LOCATION,
5708 "support for HSA does not implement exception "
5709 "handling");
5710 return;
5715 FOR_EACH_BB_FN (bb, cfun)
5717 gimple_stmt_iterator gsi;
5718 hsa_bb *hbb = hsa_bb_for_bb (bb);
5719 if (hbb)
5720 continue;
5722 hbb = hsa_init_new_bb (bb);
5724 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5726 gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
5727 if (hsa_seen_error ())
5728 return;
5732 FOR_EACH_BB_FN (bb, cfun)
5734 gimple_stmt_iterator gsi;
5735 hsa_bb *hbb = hsa_bb_for_bb (bb);
5736 gcc_assert (hbb != NULL);
5738 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5739 if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
5740 gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
5743 if (dump_file && (dump_flags & TDF_DETAILS))
5745 fprintf (dump_file, "------- Generated SSA form -------\n");
5746 dump_hsa_cfun (dump_file);
5750 static void
5751 gen_function_decl_parameters (hsa_function_representation *f,
5752 tree decl)
5754 tree parm;
5755 unsigned i;
5757 for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
5758 parm;
5759 parm = TREE_CHAIN (parm), i++)
5761 /* Result type if last in the tree list. */
5762 if (TREE_CHAIN (parm) == NULL)
5763 break;
5765 tree v = TREE_VALUE (parm);
5767 hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5768 BRIG_LINKAGE_NONE);
5769 arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
5770 arg->m_name_number = i;
5772 f->m_input_args.safe_push (arg);
5775 tree result_type = TREE_TYPE (TREE_TYPE (decl));
5776 if (!VOID_TYPE_P (result_type))
5778 f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5779 BRIG_LINKAGE_NONE);
5780 f->m_output_arg->m_type
5781 = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
5782 f->m_output_arg->m_name = "res";
5786 /* Generate the vector of parameters of the HSA representation of the current
5787 function. This also includes the output parameter representing the
5788 result. */
5790 static void
5791 gen_function_def_parameters ()
5793 tree parm;
5795 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5797 for (parm = DECL_ARGUMENTS (cfun->decl); parm;
5798 parm = DECL_CHAIN (parm))
5800 struct hsa_symbol **slot;
5802 hsa_symbol *arg
5803 = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
5804 ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
5805 BRIG_LINKAGE_FUNCTION);
5806 arg->fillup_for_decl (parm);
5808 hsa_cfun->m_input_args.safe_push (arg);
5810 if (hsa_seen_error ())
5811 return;
5813 arg->m_name = hsa_get_declaration_name (parm);
5815 /* Copy all input arguments and create corresponding private symbols
5816 for them. */
5817 hsa_symbol *private_arg;
5818 hsa_op_address *parm_addr = new hsa_op_address (arg);
5820 if (TREE_ADDRESSABLE (parm)
5821 || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
5823 private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
5824 private_arg->fillup_for_decl (parm);
5826 BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
5828 hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
5829 gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
5830 arg->total_byte_size (), align);
5832 else
5833 private_arg = arg;
5835 slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
5836 gcc_assert (!*slot);
5837 *slot = private_arg;
5839 if (is_gimple_reg (parm))
5841 tree ddef = ssa_default_def (cfun, parm);
5842 if (ddef && !has_zero_uses (ddef))
5844 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
5845 false);
5846 BrigType16_t mtype = mem_type_for_type (t);
5847 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
5848 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
5849 dest, parm_addr);
5850 gcc_assert (!parm_addr->m_reg);
5851 prologue->append_insn (mem);
5856 if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
5858 struct hsa_symbol **slot;
5860 hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5861 BRIG_LINKAGE_FUNCTION);
5862 hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
5864 if (hsa_seen_error ())
5865 return;
5867 hsa_cfun->m_output_arg->m_name = "res";
5868 slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
5869 INSERT);
5870 gcc_assert (!*slot);
5871 *slot = hsa_cfun->m_output_arg;
5875 /* Generate function representation that corresponds to
5876 a function declaration. */
5878 hsa_function_representation *
5879 hsa_generate_function_declaration (tree decl)
5881 hsa_function_representation *fun
5882 = new hsa_function_representation (decl, false, 0);
5884 fun->m_declaration_p = true;
5885 fun->m_name = get_brig_function_name (decl);
5886 gen_function_decl_parameters (fun, decl);
5888 return fun;
5892 /* Generate function representation that corresponds to
5893 an internal FN. */
5895 hsa_function_representation *
5896 hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
5898 hsa_function_representation *fun = new hsa_function_representation (fn);
5900 fun->m_name = fn->name ();
5902 for (unsigned i = 0; i < fn->get_arity (); i++)
5904 hsa_symbol *arg
5905 = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
5906 BRIG_LINKAGE_NONE);
5907 arg->m_name_number = i;
5908 fun->m_input_args.safe_push (arg);
5911 fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
5912 BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
5913 fun->m_output_arg->m_name = "res";
5915 return fun;
5918 /* Return true if switch statement S can be transformed
5919 to a SBR instruction in HSAIL. */
5921 static bool
5922 transformable_switch_to_sbr_p (gswitch *s)
5924 /* Identify if a switch statement can be transformed to
5925 SBR instruction, like:
5927 sbr_u32 $s1 [@label1, @label2, @label3];
5930 tree size = get_switch_size (s);
5931 if (!tree_fits_uhwi_p (size))
5932 return false;
5934 if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
5935 return false;
5937 return true;
5940 /* Structure hold connection between PHI nodes and immediate
5941 values hold by there nodes. */
5943 struct phi_definition
5945 phi_definition (unsigned phi_i, unsigned label_i, tree imm):
5946 phi_index (phi_i), label_index (label_i), phi_value (imm)
5949 unsigned phi_index;
5950 unsigned label_index;
5951 tree phi_value;
5954 /* Sum slice of a vector V, starting from index START and ending
5955 at the index END - 1. */
5957 template <typename T>
5958 static
5959 T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end)
5961 T s = 0;
5963 for (unsigned i = start; i < end; i++)
5964 s += v[i];
5966 return s;
5969 /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
5970 Let's assume following example:
5973 switch (index)
5974 case C1:
5975 L1: hard_work_1 ();
5976 break;
5977 case C2..C3:
5978 L2: hard_work_2 ();
5979 break;
5980 default:
5981 LD: hard_work_3 ();
5982 break;
5984 The transformation encompasses following steps:
5985 1) all immediate values used by edges coming from the switch basic block
5986 are saved
5987 2) all these edges are removed
5988 3) the switch statement (in L0) is replaced by:
5989 if (index == C1)
5990 goto L1;
5991 else
5992 goto L1';
5994 4) newly created basic block Lx' is used for generation of
5995 a next condition
5996 5) else branch of the last condition goes to LD
5997 6) fix all immediate values in PHI nodes that were propagated though
5998 edges that were removed in step 2
6000 Note: if a case is made by a range C1..C2, then process
6001 following transformation:
6003 switch_cond_op1 = C1 <= index;
6004 switch_cond_op2 = index <= C2;
6005 switch_cond_and = switch_cond_op1 & switch_cond_op2;
6006 if (switch_cond_and != 0)
6007 goto Lx;
6008 else
6009 goto Ly;
6013 static bool
6014 convert_switch_statements (void)
6016 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6017 basic_block bb;
6019 bool modified_cfg = false;
6021 FOR_EACH_BB_FN (bb, func)
6023 gimple_stmt_iterator gsi = gsi_last_bb (bb);
6024 if (gsi_end_p (gsi))
6025 continue;
6027 gimple *stmt = gsi_stmt (gsi);
6029 if (gimple_code (stmt) == GIMPLE_SWITCH)
6031 gswitch *s = as_a <gswitch *> (stmt);
6033 /* If the switch can utilize SBR insn, skip the statement. */
6034 if (transformable_switch_to_sbr_p (s))
6035 continue;
6037 modified_cfg = true;
6039 unsigned labels = gimple_switch_num_labels (s);
6040 tree index = gimple_switch_index (s);
6041 tree index_type = TREE_TYPE (index);
6042 tree default_label = gimple_switch_default_label (s);
6043 basic_block default_label_bb
6044 = label_to_block_fn (func, CASE_LABEL (default_label));
6045 basic_block cur_bb = bb;
6047 auto_vec <edge> new_edges;
6048 auto_vec <phi_definition *> phi_todo_list;
6049 auto_vec <gcov_type> edge_counts;
6050 auto_vec <int> edge_probabilities;
6052 /* Investigate all labels that and PHI nodes in these edges which
6053 should be fixed after we add new collection of edges. */
6054 for (unsigned i = 0; i < labels; i++)
6056 tree label = gimple_switch_label (s, i);
6057 basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label));
6058 edge e = find_edge (bb, label_bb);
6059 edge_counts.safe_push (e->count);
6060 edge_probabilities.safe_push (e->probability);
6061 gphi_iterator phi_gsi;
6063 /* Save PHI definitions that will be destroyed because of an edge
6064 is going to be removed. */
6065 unsigned phi_index = 0;
6066 for (phi_gsi = gsi_start_phis (e->dest);
6067 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6069 gphi *phi = phi_gsi.phi ();
6070 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6072 if (gimple_phi_arg_edge (phi, j) == e)
6074 tree imm = gimple_phi_arg_def (phi, j);
6075 phi_definition *p = new phi_definition (phi_index, i,
6076 imm);
6077 phi_todo_list.safe_push (p);
6078 break;
6081 phi_index++;
6085 /* Remove all edges for the current basic block. */
6086 for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6088 edge e = EDGE_SUCC (bb, i);
6089 remove_edge (e);
6092 /* Iterate all non-default labels. */
6093 for (unsigned i = 1; i < labels; i++)
6095 tree label = gimple_switch_label (s, i);
6096 tree low = CASE_LOW (label);
6097 tree high = CASE_HIGH (label);
6099 if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6100 low = fold_convert (index_type, low);
6102 gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6103 gimple *c = NULL;
6104 if (high)
6106 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6107 "switch_cond_op1");
6109 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6110 index);
6112 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6113 "switch_cond_op2");
6115 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6116 high = fold_convert (index_type, high);
6117 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6118 high);
6120 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6121 "switch_cond_and");
6122 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6123 tmp2);
6125 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6126 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6127 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6129 tree b = constant_boolean_node (false, boolean_type_node);
6130 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6132 else
6133 c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6135 gimple_set_location (c, gimple_location (stmt));
6137 gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6139 basic_block label_bb
6140 = label_to_block_fn (func, CASE_LABEL (label));
6141 edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6142 int prob_sum = sum_slice <int> (edge_probabilities, i, labels) +
6143 edge_probabilities[0];
6145 if (prob_sum)
6146 new_edge->probability
6147 = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
6149 new_edge->count = edge_counts[i];
6150 new_edges.safe_push (new_edge);
6152 if (i < labels - 1)
6154 /* Prepare another basic block that will contain
6155 next condition. */
6156 basic_block next_bb = create_empty_bb (cur_bb);
6157 if (current_loops)
6159 add_bb_to_loop (next_bb, cur_bb->loop_father);
6160 loops_state_set (LOOPS_NEED_FIXUP);
6163 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6164 next_edge->probability
6165 = inverse_probability (new_edge->probability);
6166 next_edge->count = edge_counts[0]
6167 + sum_slice <gcov_type> (edge_counts, i, labels);
6168 next_bb->frequency = EDGE_FREQUENCY (next_edge);
6169 cur_bb = next_bb;
6171 else /* Link last IF statement and default label
6172 of the switch. */
6174 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6175 e->probability = inverse_probability (new_edge->probability);
6176 e->count = edge_counts[0];
6177 new_edges.safe_insert (0, e);
6181 /* Restore original PHI immediate value. */
6182 for (unsigned i = 0; i < phi_todo_list.length (); i++)
6184 phi_definition *phi_def = phi_todo_list[i];
6185 edge new_edge = new_edges[phi_def->label_index];
6187 gphi_iterator it = gsi_start_phis (new_edge->dest);
6188 for (unsigned i = 0; i < phi_def->phi_index; i++)
6189 gsi_next (&it);
6191 gphi *phi = it.phi ();
6192 add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6193 delete phi_def;
6196 /* Remove the original GIMPLE switch statement. */
6197 gsi_remove (&gsi, true);
6201 if (dump_file)
6202 dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6204 return modified_cfg;
6207 /* Expand builtins that can't be handled by HSA back-end. */
6209 static void
6210 expand_builtins ()
6212 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6213 basic_block bb;
6215 FOR_EACH_BB_FN (bb, func)
6217 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6218 gsi_next (&gsi))
6220 gimple *stmt = gsi_stmt (gsi);
6222 if (gimple_code (stmt) != GIMPLE_CALL)
6223 continue;
6225 gcall *call = as_a <gcall *> (stmt);
6227 if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6228 continue;
6230 tree fndecl = gimple_call_fndecl (stmt);
6231 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6232 switch (fn)
6234 case BUILT_IN_CEXPF:
6235 case BUILT_IN_CEXPIF:
6236 case BUILT_IN_CEXPI:
6238 /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6239 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z). */
6240 tree lhs = gimple_call_lhs (stmt);
6241 tree rhs = gimple_call_arg (stmt, 0);
6242 tree rhs_type = TREE_TYPE (rhs);
6243 bool float_type_p = rhs_type == float_type_node;
6244 tree real_part = make_temp_ssa_name (rhs_type, NULL,
6245 "cexp_real_part");
6246 tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6247 "cexp_imag_part");
6249 tree cos_fndecl
6250 = mathfn_built_in (rhs_type, fn == float_type_p
6251 ? BUILT_IN_COSF : BUILT_IN_COS);
6252 gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6253 gimple_call_set_lhs (cos, real_part);
6254 gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6256 tree sin_fndecl
6257 = mathfn_built_in (rhs_type, fn == float_type_p
6258 ? BUILT_IN_SINF : BUILT_IN_SIN);
6259 gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6260 gimple_call_set_lhs (sin, imag_part);
6261 gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6264 gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6265 real_part, imag_part);
6266 gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6267 gsi_remove (&gsi, true);
6269 break;
6271 default:
6272 break;
6278 /* Emit HSA module variables that are global for the entire module. */
6280 static void
6281 emit_hsa_module_variables (void)
6283 hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6284 BRIG_LINKAGE_MODULE, true);
6286 hsa_num_threads->m_name = "hsa_num_threads";
6288 hsa_brig_emit_omp_symbols ();
6291 /* Generate HSAIL representation of the current function and write into a
6292 special section of the output file. If KERNEL is set, the function will be
6293 considered an HSA kernel callable from the host, otherwise it will be
6294 compiled as an HSA function callable from other HSA code. */
6296 static void
6297 generate_hsa (bool kernel)
6299 hsa_init_data_for_cfun ();
6301 if (hsa_num_threads == NULL)
6302 emit_hsa_module_variables ();
6304 bool modified_cfg = convert_switch_statements ();
6305 /* Initialize hsa_cfun. */
6306 hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
6307 SSANAMES (cfun)->length (),
6308 modified_cfg);
6309 hsa_cfun->init_extra_bbs ();
6311 if (flag_tm)
6313 HSA_SORRY_AT (UNKNOWN_LOCATION,
6314 "support for HSA does not implement transactional memory");
6315 goto fail;
6318 verify_function_arguments (cfun->decl);
6319 if (hsa_seen_error ())
6320 goto fail;
6322 hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6324 gen_function_def_parameters ();
6325 if (hsa_seen_error ())
6326 goto fail;
6328 init_prologue ();
6330 gen_body_from_gimple ();
6331 if (hsa_seen_error ())
6332 goto fail;
6334 if (hsa_cfun->m_kernel_dispatch_count)
6335 init_hsa_num_threads ();
6337 if (hsa_cfun->m_kern_p)
6339 hsa_function_summary *s
6340 = hsa_summaries->get (cgraph_node::get (hsa_cfun->m_decl));
6341 hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6342 hsa_cfun->m_maximum_omp_data_size,
6343 s->m_gridified_kernel_p);
6346 if (flag_checking)
6348 for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6349 if (hsa_cfun->m_ssa_map[i])
6350 hsa_cfun->m_ssa_map[i]->verify_ssa ();
6352 basic_block bb;
6353 FOR_EACH_BB_FN (bb, cfun)
6355 hsa_bb *hbb = hsa_bb_for_bb (bb);
6357 for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6358 insn = insn->m_next)
6359 insn->verify ();
6363 hsa_regalloc ();
6364 hsa_brig_emit_function ();
6366 fail:
6367 hsa_deinit_data_for_cfun ();
6370 namespace {
6372 const pass_data pass_data_gen_hsail =
6374 GIMPLE_PASS,
6375 "hsagen", /* name */
6376 OPTGROUP_NONE, /* optinfo_flags */
6377 TV_NONE, /* tv_id */
6378 PROP_cfg | PROP_ssa, /* properties_required */
6379 0, /* properties_provided */
6380 0, /* properties_destroyed */
6381 0, /* todo_flags_start */
6382 0 /* todo_flags_finish */
6385 class pass_gen_hsail : public gimple_opt_pass
6387 public:
6388 pass_gen_hsail (gcc::context *ctxt)
6389 : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6392 /* opt_pass methods: */
6393 bool gate (function *);
6394 unsigned int execute (function *);
6396 }; // class pass_gen_hsail
6398 /* Determine whether or not to run generation of HSAIL. */
6400 bool
6401 pass_gen_hsail::gate (function *f)
6403 return hsa_gen_requested_p ()
6404 && hsa_gpu_implementation_p (f->decl);
6407 unsigned int
6408 pass_gen_hsail::execute (function *)
6410 hsa_function_summary *s
6411 = hsa_summaries->get (cgraph_node::get_create (current_function_decl));
6413 expand_builtins ();
6414 generate_hsa (s->m_kind == HSA_KERNEL);
6415 TREE_ASM_WRITTEN (current_function_decl) = 1;
6416 return TODO_discard_function;
6419 } // anon namespace
6421 /* Create the instance of hsa gen pass. */
6423 gimple_opt_pass *
6424 make_pass_gen_hsail (gcc::context *ctxt)
6426 return new pass_gen_hsail (ctxt);