]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/hsa-gen.c
hooks.h (hook_uint_uintp_false): Declare.
[thirdparty/gcc.git] / gcc / hsa-gen.c
CommitLineData
b2b40051
MJ
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>.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
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"
f90aa46c 45#include "tree-vrp.h"
b2b40051
MJ
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"
63
64/* Print a warning message and set that we have seen an error. */
65
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);
75
76/* Same as previous, but highlight a location. */
77
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);
87
88/* Default number of threads used by kernel dispatch. */
89
90#define HSA_DEFAULT_NUM_THREADS 64
91
92/* Following structures are defined in the final version
93 of HSA specification. */
94
95/* HSA queue packet is shadow structure, originally provided by AMD. */
96
97struct hsa_queue_packet
98{
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;
114};
115
116/* HSA queue is shadow structure, originally provided by AMD. */
117
118struct hsa_queue
119{
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;
127};
128
129/* Alloc pools for allocating basic hsa structures such as operands,
130 instructions and other basic entities. */
131static object_allocator<hsa_op_address> *hsa_allocp_operand_address;
132static object_allocator<hsa_op_immed> *hsa_allocp_operand_immed;
133static object_allocator<hsa_op_reg> *hsa_allocp_operand_reg;
134static object_allocator<hsa_op_code_list> *hsa_allocp_operand_code_list;
135static object_allocator<hsa_op_operand_list> *hsa_allocp_operand_operand_list;
136static object_allocator<hsa_insn_basic> *hsa_allocp_inst_basic;
137static object_allocator<hsa_insn_phi> *hsa_allocp_inst_phi;
138static object_allocator<hsa_insn_mem> *hsa_allocp_inst_mem;
139static object_allocator<hsa_insn_atomic> *hsa_allocp_inst_atomic;
140static object_allocator<hsa_insn_signal> *hsa_allocp_inst_signal;
141static object_allocator<hsa_insn_seg> *hsa_allocp_inst_seg;
142static object_allocator<hsa_insn_cmp> *hsa_allocp_inst_cmp;
143static object_allocator<hsa_insn_br> *hsa_allocp_inst_br;
144static object_allocator<hsa_insn_sbr> *hsa_allocp_inst_sbr;
145static object_allocator<hsa_insn_call> *hsa_allocp_inst_call;
146static object_allocator<hsa_insn_arg_block> *hsa_allocp_inst_arg_block;
147static object_allocator<hsa_insn_comment> *hsa_allocp_inst_comment;
148static object_allocator<hsa_insn_queue> *hsa_allocp_inst_queue;
149static object_allocator<hsa_insn_srctype> *hsa_allocp_inst_srctype;
150static object_allocator<hsa_insn_packed> *hsa_allocp_inst_packed;
151static object_allocator<hsa_insn_cvt> *hsa_allocp_inst_cvt;
152static object_allocator<hsa_insn_alloca> *hsa_allocp_inst_alloca;
153static object_allocator<hsa_bb> *hsa_allocp_bb;
154
155/* List of pointers to all instructions that come from an object allocator. */
156static vec <hsa_insn_basic *> hsa_instructions;
157
158/* List of pointers to all operands that come from an object allocator. */
159static vec <hsa_op_base *> hsa_operands;
160
161hsa_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),
c1db25ac 166 m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
b2b40051
MJ
167{
168}
169
170
171hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
172 BrigLinkage8_t linkage, bool global_scope_p,
320c1a36 173 BrigAllocation allocation, BrigAlignment8_t align)
b2b40051
MJ
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),
320c1a36 178 m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
b2b40051
MJ
179{
180}
181
182unsigned HOST_WIDE_INT
183hsa_symbol::total_byte_size ()
184{
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;
189
190 if (m_dim)
191 s *= m_dim;
192
193 return s;
194}
195
196/* Forward declaration. */
197
198static BrigType16_t
199hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
200 bool min32int);
201
202void
203hsa_symbol::fillup_for_decl (tree decl)
204{
205 m_decl = decl;
206 m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
b2b40051 207 if (hsa_seen_error ())
51d9ed48
MJ
208 {
209 m_seen_error = true;
210 return;
211 }
212
213 m_align = MAX (m_align, hsa_natural_alignment (m_type));
b2b40051
MJ
214}
215
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
65e21467
ML
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. */
b2b40051
MJ
222
223hsa_function_representation::hsa_function_representation
65e21467 224 (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
b2b40051
MJ
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),
65e21467
ML
233 m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
234 m_modified_cfg (modified_cfg)
b2b40051
MJ
235{
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);
239}
240
241/* Constructor of class representing HSA function information that
242 is derived for an internal function. */
243hsa_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 () {}
253
254/* Destructor of class holding function/kernel-wide information and state. */
255
256hsa_function_representation::~hsa_function_representation ()
257{
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);
262
263 for (unsigned i = 0; i < m_input_args.length (); i++)
264 delete m_input_args[i];
265 m_input_args.release ();
266
267 delete m_output_arg;
268 delete m_local_symbols;
269
270 for (unsigned i = 0; i < m_spill_symbols.length (); i++)
271 delete m_spill_symbols[i];
272 m_spill_symbols.release ();
273
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 ();
279
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 ();
285
286 for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
287 delete m_called_internal_fns[i];
288}
289
290hsa_op_reg *
291hsa_function_representation::get_shadow_reg ()
292{
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;
298
299 if (m_shadow_reg)
300 return m_shadow_reg;
301
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";
307
308 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
309 hsa_op_address *addr = new hsa_op_address (shadow);
310
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;
314
315 return r;
316}
317
318bool hsa_function_representation::has_shadow_reg_p ()
319{
320 return m_shadow_reg != NULL;
321}
322
323void
324hsa_function_representation::init_extra_bbs ()
325{
326 hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
327 hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
328}
329
65e21467
ML
330void
331hsa_function_representation::update_dominance ()
332{
333 if (m_modified_cfg)
334 {
335 free_dominance_info (CDI_DOMINATORS);
336 calculate_dominance_info (CDI_DOMINATORS);
337 }
338}
339
b2b40051
MJ
340hsa_symbol *
341hsa_function_representation::create_hsa_temporary (BrigType16_t type)
342{
343 hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
344 BRIG_LINKAGE_FUNCTION);
345 s->m_name_number = m_temp_symbol_count++;
346
347 hsa_cfun->m_private_variables.safe_push (s);
348 return s;
349}
350
351BrigLinkage8_t
352hsa_function_representation::get_linkage ()
353{
354 if (m_internal_fn)
355 return BRIG_LINKAGE_PROGRAM;
356
357 return m_kern_p || TREE_PUBLIC (m_decl) ?
358 BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
359}
360
361/* Hash map of simple OMP builtins. */
362static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
363 = NULL;
364
365/* Warning messages for OMP builtins. */
366
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"
375
376/* Initialize hash map with simple OMP builtins. */
377
378static void
379hsa_init_simple_builtins ()
380{
381 if (omp_simple_builtins != NULL)
382 return;
383
384 omp_simple_builtins
385 = new hash_map <nofree_string_hash, omp_simple_builtin> ();
386
387 omp_simple_builtin omp_builtins[] =
388 {
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)
474 };
475
476 unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
477
478 for (unsigned i = 0; i < count; i++)
479 omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
480}
481
482/* Allocate HSA structures that we need only while generating with this. */
483
484static void
485hsa_init_data_for_cfun ()
486{
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");
534}
535
536/* Deinitialize HSA subsystem and free all allocated memory. */
537
538static void
539hsa_deinit_data_for_cfun (void)
540{
541 basic_block bb;
542
543 FOR_ALL_BB_FN (bb, cfun)
544 if (bb->aux)
545 {
546 hsa_bb *hbb = hsa_bb_for_bb (bb);
547 hbb->~hsa_bb ();
548 bb->aux = NULL;
549 }
550
551 for (unsigned int i = 0; i < hsa_operands.length (); i++)
552 hsa_destroy_operand (hsa_operands[i]);
553
554 hsa_operands.release ();
555
556 for (unsigned i = 0; i < hsa_instructions.length (); i++)
557 hsa_destroy_insn (hsa_instructions[i]);
558
559 hsa_instructions.release ();
560
561 if (omp_simple_builtins != NULL)
562 {
563 delete omp_simple_builtins;
564 omp_simple_builtins = NULL;
565 }
566
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;
591}
592
593/* Return the type which holds addresses in the given SEGMENT. */
594
595static BrigType16_t
596hsa_get_segment_addr_type (BrigSegment8_t segment)
597{
598 switch (segment)
599 {
600 case BRIG_SEGMENT_NONE:
601 gcc_unreachable ();
602
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;
608
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;
614 }
615 gcc_unreachable ();
616}
617
618/* Return integer brig type according to provided SIZE in bytes. If SIGN
619 is set to true, return signed integer type. */
620
621static BrigType16_t
622get_integer_type_by_bytes (unsigned size, bool sign)
623{
624 if (sign)
625 switch (size)
626 {
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;
637 }
638 else
639 switch (size)
640 {
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;
651 }
652
653 return 0;
654}
655
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. */
659
660static BrigType16_t
661hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
662{
663 HOST_WIDE_INT bsize;
664 const_tree base;
665 BrigType16_t res = BRIG_TYPE_NONE;
666
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);
671
672 if (TREE_CODE (type) == VECTOR_TYPE || TREE_CODE (type) == COMPLEX_TYPE)
673 base = TREE_TYPE (type);
674 else
675 base = type;
676
677 if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
678 {
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;
683 }
684
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))
690 {
691 switch (bsize)
692 {
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;
704 }
705 }
706
707 if (res == BRIG_TYPE_NONE)
708 {
709 HSA_SORRY_ATV (EXPR_LOCATION (type),
710 "support for HSA does not implement type %T", type);
711 return res;
712 }
713
714 if (TREE_CODE (type) == VECTOR_TYPE)
715 {
716 HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
717
718 if (bsize == tsize)
719 {
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;
724 }
725
726 switch (tsize)
727 {
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);
740 }
741 }
742
743 if (min32int)
744 {
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;
751 }
752
753 if (TREE_CODE (type) == COMPLEX_TYPE)
754 {
755 unsigned bsize = 2 * hsa_type_bit_size (res);
756 res = hsa_bittype_for_bitsize (bsize);
757 }
758
759 return res;
760}
761
762/* Returns the BRIG type we need to load/store entities of TYPE. */
763
764static BrigType16_t
765mem_type_for_type (BrigType16_t type)
766{
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;
27d39ae1 775 else if (hsa_btype_p (type) || hsa_type_packed_p (type))
b2b40051
MJ
776 {
777 unsigned bitsize = hsa_type_bit_size (type);
778 if (bitsize < 128)
779 return hsa_uint_for_bitsize (bitsize);
27d39ae1
MJ
780 else
781 return hsa_bittype_for_bitsize (bitsize);
b2b40051
MJ
782 }
783 return type;
784}
785
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. */
789
790static BrigType16_t
791hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
792 bool min32int = false)
793{
794 gcc_checking_assert (TYPE_P (type));
795 if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
796 {
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;
800 }
801
802 if (RECORD_OR_UNION_TYPE_P (type))
803 {
804 if (dim_p)
805 *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
806 return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
807 }
808
809 if (TREE_CODE (type) == ARRAY_TYPE)
810 {
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. */
814
815 unsigned HOST_WIDE_INT dim = 1;
816
817 while (TREE_CODE (type) == ARRAY_TYPE)
818 {
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)))
824 {
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;
829 }
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);
834 }
835
836 BrigType16_t res;
837 if (RECORD_OR_UNION_TYPE_P (type))
838 {
839 dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
840 res = BRIG_TYPE_U8;
841 }
842 else
843 res = hsa_type_for_scalar_tree_type (type, false);
844
845 if (dim_p)
846 *dim_p = dim;
847 return res | BRIG_TYPE_ARRAY;
848 }
849
850 /* Scalar case: */
851 if (dim_p)
852 *dim_p = 0;
853
854 return hsa_type_for_scalar_tree_type (type, min32int);
855}
856
857/* Returns true if converting from STYPE into DTYPE needs the _CVT
858 opcode. If false a normal _MOV is enough. */
859
860static bool
861hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
862{
863 if (hsa_btype_p (dtype))
864 return false;
865
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;
873}
874
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. */
877
878static hsa_symbol *
879get_symbol_for_decl (tree decl)
880{
881 hsa_symbol **slot;
882 hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
883
884 gcc_assert (TREE_CODE (decl) == PARM_DECL
885 || TREE_CODE (decl) == RESULT_DECL
886 || TREE_CODE (decl) == VAR_DECL);
887
888 dummy.m_decl = decl;
889
890 bool is_in_global_vars
891 = TREE_CODE (decl) == VAR_DECL && is_global_var (decl);
892
893 if (is_in_global_vars)
894 slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
895 else
896 slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
897
898 gcc_checking_assert (slot);
899 if (*slot)
900 {
c1db25ac
ML
901 hsa_symbol *sym = (*slot);
902
b2b40051
MJ
903 /* If the symbol is problematic, mark current function also as
904 problematic. */
c1db25ac 905 if (sym->m_seen_error)
b2b40051
MJ
906 hsa_fail_cfun ();
907
c1db25ac
ML
908 /* PR hsa/70234: If a global variable was marked to be emitted,
909 but HSAIL generation of a function using the variable fails,
910 we should retry to emit the variable in context of a different
911 function.
912
913 Iterate elements whether a symbol is already in m_global_symbols
914 of not. */
915 if (is_in_global_vars && !sym->m_emitted_to_brig)
916 {
917 for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
918 if (hsa_cfun->m_global_symbols[i] == sym)
919 return *slot;
920 hsa_cfun->m_global_symbols.safe_push (sym);
921 }
922
b2b40051
MJ
923 return *slot;
924 }
925 else
926 {
927 hsa_symbol *sym;
928 gcc_assert (TREE_CODE (decl) == VAR_DECL);
320c1a36 929 BrigAlignment8_t align = hsa_object_alignment (decl);
b2b40051
MJ
930
931 if (is_in_global_vars)
932 {
933 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
934 BRIG_LINKAGE_PROGRAM, true,
320c1a36 935 BRIG_ALLOCATION_PROGRAM, align);
b2b40051 936 hsa_cfun->m_global_symbols.safe_push (sym);
51d9ed48
MJ
937 sym->fillup_for_decl (decl);
938 if (sym->m_align > align)
939 {
940 sym->m_seen_error = true;
941 HSA_SORRY_ATV (EXPR_LOCATION (decl),
942 "HSA specification requires that %E is at least "
943 "naturally aligned", decl);
944 }
b2b40051
MJ
945 }
946 else
947 {
320c1a36
ML
948 /* As generation of efficient memory copy instructions relies
949 on alignment greater or equal to 8 bytes,
950 we need to increase alignment of all aggregate types.. */
951 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
952 align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
953
b2b40051
MJ
954 /* PARM_DECL and RESULT_DECL should be already in m_local_symbols. */
955 gcc_assert (TREE_CODE (decl) == VAR_DECL);
956
957 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_PRIVATE,
958 BRIG_LINKAGE_FUNCTION);
320c1a36 959 sym->m_align = align;
51d9ed48 960 sym->fillup_for_decl (decl);
b2b40051
MJ
961 hsa_cfun->m_private_variables.safe_push (sym);
962 }
963
b2b40051 964 sym->m_name = hsa_get_declaration_name (decl);
b2b40051
MJ
965 *slot = sym;
966 return sym;
967 }
968}
969
970/* For a given HSA function declaration, return a host
971 function declaration. */
972
973tree
974hsa_get_host_function (tree decl)
975{
976 hsa_function_summary *s
977 = hsa_summaries->get (cgraph_node::get_create (decl));
978 gcc_assert (s->m_kind != HSA_NONE);
979 gcc_assert (s->m_gpu_implementation_p);
980
981 return s->m_binded_function->decl;
982}
983
984/* Return true if function DECL has a host equivalent function. */
985
986static char *
987get_brig_function_name (tree decl)
988{
989 tree d = decl;
990
991 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
992 if (s->m_kind != HSA_NONE && s->m_gpu_implementation_p)
993 d = s->m_binded_function->decl;
994
995 /* IPA split can create a function that has no host equivalent. */
996 if (d == NULL)
997 d = decl;
998
999 char *name = xstrdup (hsa_get_declaration_name (d));
1000 hsa_sanitize_name (name);
1001
1002 return name;
1003}
1004
1005/* Create a spill symbol of type TYPE. */
1006
1007hsa_symbol *
1008hsa_get_spill_symbol (BrigType16_t type)
1009{
1010 hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
1011 BRIG_LINKAGE_FUNCTION);
1012 hsa_cfun->m_spill_symbols.safe_push (sym);
1013 return sym;
1014}
1015
1016/* Create a symbol for a read-only string constant. */
1017hsa_symbol *
1018hsa_get_string_cst_symbol (tree string_cst)
1019{
1020 gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
1021
1022 hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
1023 if (slot)
1024 return *slot;
1025
1026 hsa_op_immed *cst = new hsa_op_immed (string_cst);
1027 hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
1028 BRIG_LINKAGE_MODULE, true,
1029 BRIG_ALLOCATION_AGENT);
1030 sym->m_cst_value = cst;
1031 sym->m_dim = TREE_STRING_LENGTH (string_cst);
1032 sym->m_name_number = hsa_cfun->m_global_symbols.length ();
1033
1034 hsa_cfun->m_global_symbols.safe_push (sym);
1035 hsa_cfun->m_string_constants_map.put (string_cst, sym);
1036 return sym;
1037}
1038
1039/* Constructor of the ancestor of all operands. K is BRIG kind that identified
1040 what the operator is. */
1041
1042hsa_op_base::hsa_op_base (BrigKind16_t k)
1043 : m_next (NULL), m_brig_op_offset (0), m_kind (k)
1044{
1045 hsa_operands.safe_push (this);
1046}
1047
1048/* Constructor of ancestor of all operands which have a type. K is BRIG kind
1049 that identified what the operator is. T is the type of the operator. */
1050
1051hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
1052 : hsa_op_base (k), m_type (t)
1053{
1054}
1055
1056hsa_op_with_type *
1057hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
1058{
1059 if (m_type == dtype)
1060 return this;
1061
1062 hsa_op_reg *dest;
1063
1064 if (hsa_needs_cvt (dtype, m_type))
1065 {
1066 dest = new hsa_op_reg (dtype);
1067 hbb->append_insn (new hsa_insn_cvt (dest, this));
1068 }
1069 else
1070 {
1071 dest = new hsa_op_reg (m_type);
1072 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV,
1073 dest->m_type, dest, this));
1074
1075 /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
1076 type of the operand must be same as type of the instruction. */
1077 dest->m_type = dtype;
1078 }
1079
1080 return dest;
1081}
1082
1083/* Constructor of class representing HSA immediate values. TREE_VAL is the
1084 tree representation of the immediate value. If min32int is true,
1085 always expand integer types to one that has at least 32 bits. */
1086
1087hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
1088 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
1089 hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
6f652a50 1090 min32int))
b2b40051
MJ
1091{
1092 if (hsa_seen_error ())
1093 return;
1094
1095 gcc_checking_assert ((is_gimple_min_invariant (tree_val)
1096 && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
1097 || TREE_CODE (tree_val) == INTEGER_CST))
1098 || TREE_CODE (tree_val) == CONSTRUCTOR);
1099 m_tree_value = tree_val;
b2b40051 1100
6f652a50
ML
1101 /* Verify that all elements of a constructor are constants. */
1102 if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
1103 for (unsigned i = 0;
1104 i < vec_safe_length (CONSTRUCTOR_ELTS (m_tree_value)); i++)
1105 {
1106 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
1107 if (!CONSTANT_CLASS_P (v))
1108 {
1109 HSA_SORRY_AT (EXPR_LOCATION (tree_val),
1110 "HSA ctor should have only constants");
1111 return;
1112 }
1113 }
b2b40051
MJ
1114}
1115
1116/* Constructor of class representing HSA immediate values. INTEGER_VALUE is the
1117 integer representation of the immediate value. TYPE is BRIG type. */
1118
1119hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
1120 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
6f652a50 1121 m_tree_value (NULL)
b2b40051
MJ
1122{
1123 gcc_assert (hsa_type_integer_p (type));
1124 m_int_value = integer_value;
b2b40051
MJ
1125}
1126
1127hsa_op_immed::hsa_op_immed ()
6f652a50 1128 : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
b2b40051
MJ
1129{
1130}
1131
1132/* New operator to allocate immediate operands from pool alloc. */
1133
1134void *
1135hsa_op_immed::operator new (size_t)
1136{
1137 return hsa_allocp_operand_immed->allocate_raw ();
1138}
1139
1140/* Destructor. */
1141
1142hsa_op_immed::~hsa_op_immed ()
1143{
b2b40051
MJ
1144}
1145
1146/* Change type of the immediate value to T. */
1147
1148void
1149hsa_op_immed::set_type (BrigType16_t t)
1150{
1151 m_type = t;
1152}
1153
1154/* Constructor of class representing HSA registers and pseudo-registers. T is
1155 the BRIG type of the new register. */
1156
1157hsa_op_reg::hsa_op_reg (BrigType16_t t)
1158 : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
1159 m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
1160 m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
1161{
1162}
1163
1164/* New operator to allocate a register from pool alloc. */
1165
1166void *
1167hsa_op_reg::operator new (size_t)
1168{
1169 return hsa_allocp_operand_reg->allocate_raw ();
1170}
1171
1172/* Verify register operand. */
1173
1174void
1175hsa_op_reg::verify_ssa ()
1176{
1177 /* Verify that each HSA register has a definition assigned.
1178 Exceptions are VAR_DECL and PARM_DECL that are a default
1179 definition. */
1180 gcc_checking_assert (m_def_insn
1181 || (m_gimple_ssa != NULL
1182 && (!SSA_NAME_VAR (m_gimple_ssa)
1183 || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
1184 != PARM_DECL))
1185 && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
1186
1187 /* Verify that every use of the register is really present
1188 in an instruction. */
1189 for (unsigned i = 0; i < m_uses.length (); i++)
1190 {
1191 hsa_insn_basic *use = m_uses[i];
1192
1193 bool is_visited = false;
1194 for (unsigned j = 0; j < use->operand_count (); j++)
1195 {
1196 hsa_op_base *u = use->get_op (j);
1197 hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
1198 if (addr && addr->m_reg)
1199 u = addr->m_reg;
1200
1201 if (u == this)
1202 {
1203 bool r = !addr && use->op_output_p (j);
1204
1205 if (r)
1206 {
1207 error ("HSA SSA name defined by instruction that is supposed "
1208 "to be using it");
1209 debug_hsa_operand (this);
1210 debug_hsa_insn (use);
1211 internal_error ("HSA SSA verification failed");
1212 }
1213
1214 is_visited = true;
1215 }
1216 }
1217
1218 if (!is_visited)
1219 {
1220 error ("HSA SSA name not among operands of instruction that is "
1221 "supposed to use it");
1222 debug_hsa_operand (this);
1223 debug_hsa_insn (use);
1224 internal_error ("HSA SSA verification failed");
1225 }
1226 }
1227}
1228
1229hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
1230 HOST_WIDE_INT offset)
1231 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
1232 m_imm_offset (offset)
1233{
1234}
1235
1236hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
1237 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
1238 m_imm_offset (offset)
1239{
1240}
1241
1242hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
1243 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
1244 m_imm_offset (offset)
1245{
1246}
1247
1248/* New operator to allocate address operands from pool alloc. */
1249
1250void *
1251hsa_op_address::operator new (size_t)
1252{
1253 return hsa_allocp_operand_address->allocate_raw ();
1254}
1255
1256/* Constructor of an operand referring to HSAIL code. */
1257
1258hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
1259 m_directive_offset (0)
1260{
1261}
1262
1263/* Constructor of an operand representing a code list. Set it up so that it
1264 can contain ELEMENTS number of elements. */
1265
1266hsa_op_code_list::hsa_op_code_list (unsigned elements)
1267 : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
1268{
1269 m_offsets.create (1);
1270 m_offsets.safe_grow_cleared (elements);
1271}
1272
1273/* New operator to allocate code list operands from pool alloc. */
1274
1275void *
1276hsa_op_code_list::operator new (size_t)
1277{
1278 return hsa_allocp_operand_code_list->allocate_raw ();
1279}
1280
1281/* Constructor of an operand representing an operand list.
1282 Set it up so that it can contain ELEMENTS number of elements. */
1283
1284hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
1285 : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
1286{
1287 m_offsets.create (elements);
1288 m_offsets.safe_grow (elements);
1289}
1290
1291/* New operator to allocate operand list operands from pool alloc. */
1292
1293void *
1294hsa_op_operand_list::operator new (size_t)
1295{
1296 return hsa_allocp_operand_operand_list->allocate_raw ();
1297}
1298
1299hsa_op_operand_list::~hsa_op_operand_list ()
1300{
1301 m_offsets.release ();
1302}
1303
1304
1305hsa_op_reg *
1306hsa_function_representation::reg_for_gimple_ssa (tree ssa)
1307{
1308 hsa_op_reg *hreg;
1309
1310 gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
1311 if (m_ssa_map[SSA_NAME_VERSION (ssa)])
1312 return m_ssa_map[SSA_NAME_VERSION (ssa)];
1313
1314 hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
1315 true));
1316 hreg->m_gimple_ssa = ssa;
1317 m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
1318
1319 return hreg;
1320}
1321
1322void
1323hsa_op_reg::set_definition (hsa_insn_basic *insn)
1324{
1325 if (hsa_cfun->m_in_ssa)
1326 {
1327 gcc_checking_assert (!m_def_insn);
1328 m_def_insn = insn;
1329 }
1330 else
1331 m_def_insn = NULL;
1332}
1333
1334/* Constructor of the class which is the bases of all instructions and directly
1335 represents the most basic ones. NOPS is the number of operands that the
1336 operand vector will contain (and which will be cleared). OP is the opcode
1337 of the instruction. This constructor does not set type. */
1338
1339hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
1340 : m_prev (NULL),
1341 m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
1342 m_type (BRIG_TYPE_NONE), m_brig_offset (0)
1343{
1344 if (nops > 0)
1345 m_operands.safe_grow_cleared (nops);
1346
1347 hsa_instructions.safe_push (this);
1348}
1349
1350/* Make OP the operand number INDEX of operands of this instruction. If OP is a
1351 register or an address containing a register, then either set the definition
1352 of the register to this instruction if it an output operand or add this
1353 instruction to the uses if it is an input one. */
1354
1355void
1356hsa_insn_basic::set_op (int index, hsa_op_base *op)
1357{
1358 /* Each address operand is always use. */
1359 hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
1360 if (addr && addr->m_reg)
1361 addr->m_reg->m_uses.safe_push (this);
1362 else
1363 {
1364 hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
1365 if (reg)
1366 {
1367 if (op_output_p (index))
1368 reg->set_definition (this);
1369 else
1370 reg->m_uses.safe_push (this);
1371 }
1372 }
1373
1374 m_operands[index] = op;
1375}
1376
1377/* Get INDEX-th operand of the instruction. */
1378
1379hsa_op_base *
1380hsa_insn_basic::get_op (int index)
1381{
1382 return m_operands[index];
1383}
1384
1385/* Get address of INDEX-th operand of the instruction. */
1386
1387hsa_op_base **
1388hsa_insn_basic::get_op_addr (int index)
1389{
1390 return &m_operands[index];
1391}
1392
1393/* Get number of operands of the instruction. */
1394unsigned int
1395hsa_insn_basic::operand_count ()
1396{
1397 return m_operands.length ();
1398}
1399
1400/* Constructor of the class which is the bases of all instructions and directly
1401 represents the most basic ones. NOPS is the number of operands that the
1402 operand vector will contain (and which will be cleared). OPC is the opcode
1403 of the instruction, T is the type of the instruction. */
1404
1405hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
1406 hsa_op_base *arg0, hsa_op_base *arg1,
1407 hsa_op_base *arg2, hsa_op_base *arg3)
1408 : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
1409 m_type (t), m_brig_offset (0)
1410{
1411 if (nops > 0)
1412 m_operands.safe_grow_cleared (nops);
1413
1414 if (arg0 != NULL)
1415 {
1416 gcc_checking_assert (nops >= 1);
1417 set_op (0, arg0);
1418 }
1419
1420 if (arg1 != NULL)
1421 {
1422 gcc_checking_assert (nops >= 2);
1423 set_op (1, arg1);
1424 }
1425
1426 if (arg2 != NULL)
1427 {
1428 gcc_checking_assert (nops >= 3);
1429 set_op (2, arg2);
1430 }
1431
1432 if (arg3 != NULL)
1433 {
1434 gcc_checking_assert (nops >= 4);
1435 set_op (3, arg3);
1436 }
1437
1438 hsa_instructions.safe_push (this);
1439}
1440
1441/* New operator to allocate basic instruction from pool alloc. */
1442
1443void *
1444hsa_insn_basic::operator new (size_t)
1445{
1446 return hsa_allocp_inst_basic->allocate_raw ();
1447}
1448
1449/* Verify the instruction. */
1450
1451void
1452hsa_insn_basic::verify ()
1453{
1454 hsa_op_address *addr;
1455 hsa_op_reg *reg;
1456
1457 /* Iterate all register operands and verify that the instruction
1458 is set in uses of the register. */
1459 for (unsigned i = 0; i < operand_count (); i++)
1460 {
1461 hsa_op_base *use = get_op (i);
1462
1463 if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
1464 {
1465 gcc_assert (addr->m_reg->m_def_insn != this);
1466 use = addr->m_reg;
1467 }
1468
1469 if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
1470 {
1471 unsigned j;
1472 for (j = 0; j < reg->m_uses.length (); j++)
1473 {
1474 if (reg->m_uses[j] == this)
1475 break;
1476 }
1477
1478 if (j == reg->m_uses.length ())
1479 {
1480 error ("HSA instruction uses a register but is not among "
1481 "recorded register uses");
1482 debug_hsa_operand (reg);
1483 debug_hsa_insn (this);
1484 internal_error ("HSA instruction verification failed");
1485 }
1486 }
1487 }
1488}
1489
1490/* Constructor of an instruction representing a PHI node. NOPS is the number
1491 of operands (equal to the number of predecessors). */
1492
1493hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
1494 : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
1495{
1496 dst->set_definition (this);
1497}
1498
1499/* New operator to allocate PHI instruction from pool alloc. */
1500
1501void *
1502hsa_insn_phi::operator new (size_t)
1503{
1504 return hsa_allocp_inst_phi->allocate_raw ();
1505}
1506
1507/* Constructor of class representing instruction for conditional jump, CTRL is
1508 the control register determining whether the jump will be carried out, the
1509 new instruction is automatically added to its uses list. */
1510
1511hsa_insn_br::hsa_insn_br (hsa_op_reg *ctrl)
1512 : hsa_insn_basic (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, ctrl),
1513 m_width (BRIG_WIDTH_1)
1514{
1515}
1516
1517/* New operator to allocate branch instruction from pool alloc. */
1518
1519void *
1520hsa_insn_br::operator new (size_t)
1521{
1522 return hsa_allocp_inst_br->allocate_raw ();
1523}
1524
1525/* Constructor of class representing instruction for switch jump, CTRL is
1526 the index register. */
1527
1528hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
1529 : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
e8661ad6 1530 m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
b2b40051
MJ
1531 m_label_code_list (new hsa_op_code_list (jump_count))
1532{
1533}
1534
1535/* New operator to allocate switch branch instruction from pool alloc. */
1536
1537void *
1538hsa_insn_sbr::operator new (size_t)
1539{
1540 return hsa_allocp_inst_sbr->allocate_raw ();
1541}
1542
1543/* Replace all occurrences of OLD_BB with NEW_BB in the statements
1544 jump table. */
1545
1546void
1547hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
1548{
1549 for (unsigned i = 0; i < m_jump_table.length (); i++)
1550 if (m_jump_table[i] == old_bb)
1551 m_jump_table[i] = new_bb;
1552}
1553
1554hsa_insn_sbr::~hsa_insn_sbr ()
1555{
1556 m_jump_table.release ();
1557}
1558
1559/* Constructor of comparison instruction. CMP is the comparison operation and T
1560 is the result type. */
1561
1562hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
1563 hsa_op_base *arg0, hsa_op_base *arg1,
1564 hsa_op_base *arg2)
1565 : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
1566{
1567}
1568
1569/* New operator to allocate compare instruction from pool alloc. */
1570
1571void *
1572hsa_insn_cmp::operator new (size_t)
1573{
1574 return hsa_allocp_inst_cmp->allocate_raw ();
1575}
1576
1577/* Constructor of classes representing memory accesses. OPC is the opcode (must
1578 be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type. The instruction
1579 operands are provided as ARG0 and ARG1. */
1580
1581hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
1582 hsa_op_base *arg1)
1583 : hsa_insn_basic (2, opc, t, arg0, arg1),
1584 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1585{
1586 gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
1587}
1588
1589/* Constructor for descendants allowing different opcodes and number of
1590 operands, it passes its arguments directly to hsa_insn_basic
1591 constructor. The instruction operands are provided as ARG[0-3]. */
1592
1593
1594hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
1595 hsa_op_base *arg0, hsa_op_base *arg1,
1596 hsa_op_base *arg2, hsa_op_base *arg3)
1597 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1598 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1599{
1600}
1601
1602/* New operator to allocate memory instruction from pool alloc. */
1603
1604void *
1605hsa_insn_mem::operator new (size_t)
1606{
1607 return hsa_allocp_inst_mem->allocate_raw ();
1608}
1609
1610/* Constructor of class representing atomic instructions and signals. OPC is
1611 the principal opcode, aop is the specific atomic operation opcode. T is the
1612 type of the instruction. The instruction operands
1613 are provided as ARG[0-3]. */
1614
1615hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
1616 enum BrigAtomicOperation aop,
1617 BrigType16_t t, BrigMemoryOrder memorder,
1618 hsa_op_base *arg0,
1619 hsa_op_base *arg1, hsa_op_base *arg2,
1620 hsa_op_base *arg3)
1621 : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
1622 m_memoryorder (memorder),
1623 m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
1624{
1625 gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
1626 opc == BRIG_OPCODE_ATOMIC ||
1627 opc == BRIG_OPCODE_SIGNAL ||
1628 opc == BRIG_OPCODE_SIGNALNORET);
1629}
1630
1631/* New operator to allocate signal instruction from pool alloc. */
1632
1633void *
1634hsa_insn_atomic::operator new (size_t)
1635{
1636 return hsa_allocp_inst_atomic->allocate_raw ();
1637}
1638
1639/* Constructor of class representing signal instructions. OPC is the prinicpal
1640 opcode, sop is the specific signal operation opcode. T is the type of the
1641 instruction. The instruction operands are provided as ARG[0-3]. */
1642
1643hsa_insn_signal::hsa_insn_signal (int nops, int opc,
1644 enum BrigAtomicOperation sop,
1645 BrigType16_t t, hsa_op_base *arg0,
1646 hsa_op_base *arg1, hsa_op_base *arg2,
1647 hsa_op_base *arg3)
1648 : hsa_insn_atomic (nops, opc, sop, t, BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE,
1649 arg0, arg1, arg2, arg3)
1650{
1651}
1652
1653/* New operator to allocate signal instruction from pool alloc. */
1654
1655void *
1656hsa_insn_signal::operator new (size_t)
1657{
1658 return hsa_allocp_inst_signal->allocate_raw ();
1659}
1660
1661/* Constructor of class representing segment conversion instructions. OPC is
1662 the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS. DEST
1663 and SRCT are destination and source types respectively, SEG is the segment
1664 we are converting to or from. The instruction operands are
1665 provided as ARG0 and ARG1. */
1666
1667hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
1668 BrigSegment8_t seg, hsa_op_base *arg0,
1669 hsa_op_base *arg1)
1670 : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
1671 m_segment (seg)
1672{
1673 gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
1674}
1675
1676/* New operator to allocate address conversion instruction from pool alloc. */
1677
1678void *
1679hsa_insn_seg::operator new (size_t)
1680{
1681 return hsa_allocp_inst_seg->allocate_raw ();
1682}
1683
1684/* Constructor of class representing a call instruction. CALLEE is the tree
1685 representation of the function being called. */
1686
1687hsa_insn_call::hsa_insn_call (tree callee)
1688 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
1689 m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
1690{
1691}
1692
1693hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
1694 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
1695 m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
1696 m_result_code_list (NULL)
1697{
1698}
1699
1700/* New operator to allocate call instruction from pool alloc. */
1701
1702void *
1703hsa_insn_call::operator new (size_t)
1704{
1705 return hsa_allocp_inst_call->allocate_raw ();
1706}
1707
1708hsa_insn_call::~hsa_insn_call ()
1709{
1710 for (unsigned i = 0; i < m_input_args.length (); i++)
1711 delete m_input_args[i];
1712
1713 delete m_output_arg;
1714
1715 m_input_args.release ();
1716 m_input_arg_insns.release ();
1717}
1718
1719/* Constructor of class representing the argument block required to invoke
1720 a call in HSAIL. */
1721hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
1722 hsa_insn_call * call)
1723 : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
1724 m_call_insn (call)
1725{
1726}
1727
1728/* New operator to allocate argument block instruction from pool alloc. */
1729
1730void *
1731hsa_insn_arg_block::operator new (size_t)
1732{
1733 return hsa_allocp_inst_arg_block->allocate_raw ();
1734}
1735
1736hsa_insn_comment::hsa_insn_comment (const char *s)
1737 : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
1738{
1739 unsigned l = strlen (s);
1740
1741 /* Append '// ' to the string. */
1742 char *buf = XNEWVEC (char, l + 4);
1743 sprintf (buf, "// %s", s);
1744 m_comment = buf;
1745}
1746
1747/* New operator to allocate comment instruction from pool alloc. */
1748
1749void *
1750hsa_insn_comment::operator new (size_t)
1751{
1752 return hsa_allocp_inst_comment->allocate_raw ();
1753}
1754
1755hsa_insn_comment::~hsa_insn_comment ()
1756{
1757 gcc_checking_assert (m_comment);
1758 free (m_comment);
1759 m_comment = NULL;
1760}
1761
1762/* Constructor of class representing the queue instruction in HSAIL. */
1763hsa_insn_queue::hsa_insn_queue (int nops, BrigOpcode opcode)
1764 : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64)
1765{
1766}
1767
1768/* New operator to allocate source type instruction from pool alloc. */
1769
1770void *
1771hsa_insn_srctype::operator new (size_t)
1772{
1773 return hsa_allocp_inst_srctype->allocate_raw ();
1774}
1775
1776/* Constructor of class representing the source type instruction in HSAIL. */
1777
1778hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
1779 BrigType16_t destt, BrigType16_t srct,
1780 hsa_op_base *arg0, hsa_op_base *arg1,
1781 hsa_op_base *arg2 = NULL)
1782 : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
1783 m_source_type (srct)
1784{}
1785
1786/* New operator to allocate packed instruction from pool alloc. */
1787
1788void *
1789hsa_insn_packed::operator new (size_t)
1790{
1791 return hsa_allocp_inst_packed->allocate_raw ();
1792}
1793
1794/* Constructor of class representing the packed instruction in HSAIL. */
1795
1796hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
1797 BrigType16_t destt, BrigType16_t srct,
1798 hsa_op_base *arg0, hsa_op_base *arg1,
1799 hsa_op_base *arg2)
1800 : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
1801{
1802 m_operand_list = new hsa_op_operand_list (nops - 1);
1803}
1804
1805/* New operator to allocate convert instruction from pool alloc. */
1806
1807void *
1808hsa_insn_cvt::operator new (size_t)
1809{
1810 return hsa_allocp_inst_cvt->allocate_raw ();
1811}
1812
1813/* Constructor of class representing the convert instruction in HSAIL. */
1814
1815hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
1816 : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
1817{
1818}
1819
1820/* New operator to allocate alloca from pool alloc. */
1821
1822void *
1823hsa_insn_alloca::operator new (size_t)
1824{
1825 return hsa_allocp_inst_alloca->allocate_raw ();
1826}
1827
1828/* Constructor of class representing the alloca in HSAIL. */
1829
1830hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
1831 hsa_op_with_type *size, unsigned alignment)
1832 : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
1833 m_align (BRIG_ALIGNMENT_8)
1834{
1835 gcc_assert (dest->m_type == BRIG_TYPE_U32);
1836 if (alignment)
1837 m_align = hsa_alignment_encoding (alignment);
1838}
1839
1840/* Append an instruction INSN into the basic block. */
1841
1842void
1843hsa_bb::append_insn (hsa_insn_basic *insn)
1844{
1845 gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
1846 gcc_assert (!insn->m_bb);
1847
1848 insn->m_bb = m_bb;
1849 insn->m_prev = m_last_insn;
1850 insn->m_next = NULL;
1851 if (m_last_insn)
1852 m_last_insn->m_next = insn;
1853 m_last_insn = insn;
1854 if (!m_first_insn)
1855 m_first_insn = insn;
1856}
1857
1858/* Insert HSA instruction NEW_INSN immediately before an existing instruction
1859 OLD_INSN. */
1860
1861static void
1862hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1863{
1864 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1865
1866 if (hbb->m_first_insn == old_insn)
1867 hbb->m_first_insn = new_insn;
1868 new_insn->m_prev = old_insn->m_prev;
1869 new_insn->m_next = old_insn;
1870 if (old_insn->m_prev)
1871 old_insn->m_prev->m_next = new_insn;
1872 old_insn->m_prev = new_insn;
1873}
1874
1875/* Append HSA instruction NEW_INSN immediately after an existing instruction
1876 OLD_INSN. */
1877
1878static void
1879hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1880{
1881 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1882
1883 if (hbb->m_last_insn == old_insn)
1884 hbb->m_last_insn = new_insn;
1885 new_insn->m_prev = old_insn;
1886 new_insn->m_next = old_insn->m_next;
1887 if (old_insn->m_next)
1888 old_insn->m_next->m_prev = new_insn;
1889 old_insn->m_next = new_insn;
1890}
1891
1892/* Return a register containing the calculated value of EXP which must be an
1893 expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
1894 integer constants as returned by get_inner_reference.
1895 Newly generated HSA instructions will be appended to HBB.
1896 Perform all calculations in ADDRTYPE. */
1897
1898static hsa_op_with_type *
1899gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
1900{
1901 int opcode;
1902
1903 if (TREE_CODE (exp) == NOP_EXPR)
1904 exp = TREE_OPERAND (exp, 0);
1905
1906 switch (TREE_CODE (exp))
1907 {
1908 case SSA_NAME:
1909 return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
1910
1911 case INTEGER_CST:
1912 {
1913 hsa_op_immed *imm = new hsa_op_immed (exp);
1914 if (addrtype != imm->m_type)
1915 imm->m_type = addrtype;
1916 return imm;
1917 }
1918
1919 case PLUS_EXPR:
1920 opcode = BRIG_OPCODE_ADD;
1921 break;
1922
1923 case MULT_EXPR:
1924 opcode = BRIG_OPCODE_MUL;
1925 break;
1926
1927 default:
1928 gcc_unreachable ();
1929 }
1930
1931 hsa_op_reg *res = new hsa_op_reg (addrtype);
1932 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
1933 insn->set_op (0, res);
1934
1935 hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
1936 addrtype);
1937 hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
1938 addrtype);
1939 insn->set_op (1, op1);
1940 insn->set_op (2, op2);
1941
1942 hbb->append_insn (insn);
1943 return res;
1944}
1945
1946/* If R1 is NULL, just return R2, otherwise append an instruction adding them
1947 to HBB and return the register holding the result. */
1948
1949static hsa_op_reg *
1950add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
1951{
1952 gcc_checking_assert (r2);
1953 if (!r1)
1954 return r2;
1955
1956 hsa_op_reg *res = new hsa_op_reg (r1->m_type);
1957 gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
1958 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
1959 insn->set_op (0, res);
1960 insn->set_op (1, r1);
1961 insn->set_op (2, r2);
1962 hbb->append_insn (insn);
1963 return res;
1964}
1965
1966/* Helper of gen_hsa_addr. Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
1967 reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF. */
1968
1969static void
1970process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
1971 hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
1972{
1973 if (TREE_CODE (base) == SSA_NAME)
1974 {
1975 gcc_assert (!*reg);
1976 hsa_op_with_type *ssa
1977 = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
1978 *reg = dyn_cast <hsa_op_reg *> (ssa);
1979 }
1980 else if (TREE_CODE (base) == ADDR_EXPR)
1981 {
1982 tree decl = TREE_OPERAND (base, 0);
1983
1984 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
1985 {
1986 HSA_SORRY_AT (EXPR_LOCATION (base),
1987 "support for HSA does not implement a memory reference "
1988 "to a non-declaration type");
1989 return;
1990 }
1991
1992 gcc_assert (!*symbol);
1993
1994 *symbol = get_symbol_for_decl (decl);
1995 *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
1996 }
1997 else if (TREE_CODE (base) == INTEGER_CST)
1998 *offset += wi::to_offset (base);
1999 else
2000 gcc_unreachable ();
2001}
2002
2003/* Forward declaration of a function. */
2004
2005static void
2006gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
2007
2008/* Generate HSA address operand for a given tree memory reference REF. If
2009 instructions need to be created to calculate the address, they will be added
2010 to the end of HBB. If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
2011 the function assumes that the caller will handle possible
2012 bit-field references. Otherwise if we reference a bit-field, sorry message
2013 is displayed. */
2014
2015static hsa_op_address *
2016gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
2017 HOST_WIDE_INT *output_bitpos = NULL)
2018{
2019 hsa_symbol *symbol = NULL;
2020 hsa_op_reg *reg = NULL;
2021 offset_int offset = 0;
2022 tree origref = ref;
2023 tree varoffset = NULL_TREE;
2024 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2025 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2026 BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2027
2028 if (TREE_CODE (ref) == STRING_CST)
2029 {
2030 symbol = hsa_get_string_cst_symbol (ref);
2031 goto out;
2032 }
2033 else if (TREE_CODE (ref) == BIT_FIELD_REF
2034 && ((tree_to_uhwi (TREE_OPERAND (ref, 1)) % BITS_PER_UNIT) != 0
2035 || (tree_to_uhwi (TREE_OPERAND (ref, 2)) % BITS_PER_UNIT) != 0))
2036 {
2037 HSA_SORRY_ATV (EXPR_LOCATION (origref),
2038 "support for HSA does not implement "
2039 "bit field references such as %E", ref);
2040 goto out;
2041 }
2042
2043 if (handled_component_p (ref))
2044 {
2045 enum machine_mode mode;
2046 int unsignedp, volatilep, preversep;
2047
2048 ref = get_inner_reference (ref, &bitsize, &bitpos, &varoffset, &mode,
25b75a48 2049 &unsignedp, &preversep, &volatilep);
b2b40051
MJ
2050
2051 offset = bitpos;
2052 offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
2053 }
2054
2055 switch (TREE_CODE (ref))
2056 {
2057 case ADDR_EXPR:
2058 {
2059 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2060 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2061 hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
2062 gen_hsa_addr_insns (ref, r, hbb);
2063 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2064 r, new hsa_op_address (symbol)));
2065
2066 break;
2067 }
2068 case SSA_NAME:
2069 {
2070 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2071 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2072 hsa_op_reg *r = hsa_cfun->reg_for_gimple_ssa (ref);
2073
2074 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2075 r, new hsa_op_address (symbol)));
2076
2077 break;
2078 }
2079 case PARM_DECL:
2080 case VAR_DECL:
2081 case RESULT_DECL:
2082 gcc_assert (!symbol);
2083 symbol = get_symbol_for_decl (ref);
2084 addrtype = hsa_get_segment_addr_type (symbol->m_segment);
2085 break;
2086
2087 case MEM_REF:
2088 process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
2089 &offset, hbb);
2090
2091 if (!integer_zerop (TREE_OPERAND (ref, 1)))
2092 offset += wi::to_offset (TREE_OPERAND (ref, 1));
2093 break;
2094
2095 case TARGET_MEM_REF:
2096 process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
2097 if (TMR_INDEX (ref))
2098 {
2099 hsa_op_reg *disp1;
2100 hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
2101 (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
2102 if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
2103 {
2104 disp1 = new hsa_op_reg (addrtype);
2105 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
2106 addrtype);
2107
2108 /* As step must respect addrtype, we overwrite the type
2109 of an immediate value. */
2110 hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
2111 step->m_type = addrtype;
2112
2113 insn->set_op (0, disp1);
2114 insn->set_op (1, idx);
2115 insn->set_op (2, step);
2116 hbb->append_insn (insn);
2117 }
2118 else
2119 disp1 = as_a <hsa_op_reg *> (idx);
2120 reg = add_addr_regs_if_needed (reg, disp1, hbb);
2121 }
2122 if (TMR_INDEX2 (ref))
2123 {
de0fef0d
MJ
2124 if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
2125 {
2126 hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
2127 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
2128 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
2129 hbb);
2130 }
2131 else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
2132 offset += wi::to_offset (TMR_INDEX2 (ref));
2133 else
2134 gcc_unreachable ();
b2b40051
MJ
2135 }
2136 offset += wi::to_offset (TMR_OFFSET (ref));
2137 break;
2138 case FUNCTION_DECL:
2139 HSA_SORRY_AT (EXPR_LOCATION (origref),
2140 "support for HSA does not implement function pointers");
2141 goto out;
2142 default:
2143 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
2144 "not implement memory access to %E", origref);
2145 goto out;
2146 }
2147
2148 if (varoffset)
2149 {
2150 if (TREE_CODE (varoffset) == INTEGER_CST)
2151 offset += wi::to_offset (varoffset);
2152 else
2153 {
2154 hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
2155 addrtype);
2156 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
2157 hbb);
2158 }
2159 }
2160
2161 gcc_checking_assert ((symbol
2162 && addrtype
2163 == hsa_get_segment_addr_type (symbol->m_segment))
2164 || (!symbol
2165 && addrtype
2166 == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
2167out:
2168 HOST_WIDE_INT hwi_offset = offset.to_shwi ();
2169
2170 /* Calculate remaining bitsize offset (if presented). */
2171 bitpos %= BITS_PER_UNIT;
2172 /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
2173 is not a reason to think this is a bit-field access. */
2174 if (bitpos == 0
2175 && (bitsize >= BITS_PER_UNIT)
2176 && !(bitsize & (bitsize - 1)))
2177 bitsize = 0;
2178
2179 if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
2180 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
2181 "implement unhandled bit field reference such as %E", ref);
2182
2183 if (output_bitsize != NULL && output_bitpos != NULL)
2184 {
2185 *output_bitsize = bitsize;
2186 *output_bitpos = bitpos;
2187 }
2188
2189 return new hsa_op_address (symbol, reg, hwi_offset);
2190}
2191
320c1a36
ML
2192/* Generate HSA address operand for a given tree memory reference REF. If
2193 instructions need to be created to calculate the address, they will be added
2194 to the end of HBB. OUTPUT_ALIGN is alignment of the created address. */
2195
2196static hsa_op_address *
2197gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
2198{
2199 hsa_op_address *addr = gen_hsa_addr (ref, hbb);
2200 if (addr->m_reg || !addr->m_symbol)
2201 *output_align = hsa_object_alignment (ref);
2202 else
2203 {
2204 /* If the address consists only of a symbol and an offset, we
2205 compute the alignment ourselves to take into account any alignment
2206 promotions we might have done for the HSA symbol representation. */
2207 unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
2208 unsigned misalign = addr->m_imm_offset & (align - 1);
2209 if (misalign)
146ec50f 2210 align = least_bit_hwi (misalign);
320c1a36
ML
2211 *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
2212 }
2213 return addr;
2214}
2215
b2b40051
MJ
2216/* Generate HSA address for a function call argument of given TYPE.
2217 INDEX is used to generate corresponding name of the arguments.
2218 Special value -1 represents fact that result value is created. */
2219
2220static hsa_op_address *
2221gen_hsa_addr_for_arg (tree tree_type, int index)
2222{
2223 hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
2224 BRIG_LINKAGE_ARG);
2225 sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
2226
2227 if (index == -1) /* Function result. */
2228 sym->m_name = "res";
2229 else /* Function call arguments. */
2230 {
2231 sym->m_name = NULL;
2232 sym->m_name_number = index;
2233 }
2234
2235 return new hsa_op_address (sym);
2236}
2237
65e21467
ML
2238/* Generate HSA instructions that process all necessary conversions
2239 of an ADDR to flat addressing and place the result into DEST.
b2b40051
MJ
2240 Instructions are appended to HBB. */
2241
2242static void
65e21467
ML
2243convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
2244 hsa_bb *hbb)
b2b40051 2245{
b2b40051
MJ
2246 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
2247 insn->set_op (1, addr);
2248 if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
2249 {
2250 /* LDA produces segment-relative address, we need to convert
2251 it to the flat one. */
2252 hsa_op_reg *tmp;
2253 tmp = new hsa_op_reg (hsa_get_segment_addr_type
2254 (addr->m_symbol->m_segment));
2255 hsa_insn_seg *seg;
2256 seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
2257 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
2258 tmp->m_type, addr->m_symbol->m_segment, dest,
2259 tmp);
2260
2261 insn->set_op (0, tmp);
2262 insn->m_type = tmp->m_type;
2263 hbb->append_insn (insn);
2264 hbb->append_insn (seg);
2265 }
2266 else
2267 {
2268 insn->set_op (0, dest);
2269 insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2270 hbb->append_insn (insn);
2271 }
2272}
2273
65e21467
ML
2274/* Generate HSA instructions that calculate address of VAL including all
2275 necessary conversions to flat addressing and place the result into DEST.
2276 Instructions are appended to HBB. */
2277
2278static void
2279gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
2280{
2281 /* Handle cases like tmp = NULL, where we just emit a move instruction
2282 to a register. */
2283 if (TREE_CODE (val) == INTEGER_CST)
2284 {
2285 hsa_op_immed *c = new hsa_op_immed (val);
2286 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2287 dest->m_type, dest, c);
2288 hbb->append_insn (insn);
2289 return;
2290 }
2291
2292 hsa_op_address *addr;
2293
2294 gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2295 if (TREE_CODE (val) == ADDR_EXPR)
2296 val = TREE_OPERAND (val, 0);
2297 addr = gen_hsa_addr (val, hbb);
2298
2299 convert_addr_to_flat_segment (addr, dest, hbb);
2300}
2301
b2b40051
MJ
2302/* Return an HSA register or HSA immediate value operand corresponding to
2303 gimple operand OP. */
2304
2305static hsa_op_with_type *
2306hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
2307{
2308 hsa_op_reg *tmp;
2309
2310 if (TREE_CODE (op) == SSA_NAME)
2311 tmp = hsa_cfun->reg_for_gimple_ssa (op);
2312 else if (!POINTER_TYPE_P (TREE_TYPE (op)))
2313 return new hsa_op_immed (op);
2314 else
2315 {
2316 tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2317 gen_hsa_addr_insns (op, tmp, hbb);
2318 }
2319 return tmp;
2320}
2321
2322/* Create a simple movement instruction with register destination DEST and
2323 register or immediate source SRC and append it to the end of HBB. */
2324
2325void
2326hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
2327{
2328 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
2329 dest, src);
2330 if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
2331 gcc_assert (hsa_type_bit_size (dest->m_type)
2332 == hsa_type_bit_size (sreg->m_type));
2333 else
2334 gcc_assert (hsa_type_bit_size (dest->m_type)
2335 == hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type));
2336
2337 hbb->append_insn (insn);
2338}
2339
2340/* Generate HSAIL instructions loading a bit field into register DEST.
2341 VALUE_REG is a register of a SSA name that is used in the bit field
2342 reference. To identify a bit field BITPOS is offset to the loaded memory
2343 and BITSIZE is number of bits of the bit field.
2344 Add instructions to HBB. */
2345
2346static void
2347gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
2348 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2349 hsa_bb *hbb)
2350{
2351 unsigned type_bitsize = hsa_type_bit_size (dest->m_type);
2352 unsigned left_shift = type_bitsize - (bitsize + bitpos);
2353 unsigned right_shift = left_shift + bitpos;
2354
2355 if (left_shift)
2356 {
2357 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2358 hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
2359
2360 hsa_insn_basic *lshift
2361 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
2362 value_reg_2, value_reg, c);
2363
2364 hbb->append_insn (lshift);
2365
2366 value_reg = value_reg_2;
2367 }
2368
2369 if (right_shift)
2370 {
2371 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2372 hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
2373
2374 hsa_insn_basic *rshift
2375 = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
2376 value_reg_2, value_reg, c);
2377
2378 hbb->append_insn (rshift);
2379
2380 value_reg = value_reg_2;
2381 }
2382
2383 hsa_insn_basic *assignment
2384 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, value_reg);
2385 hbb->append_insn (assignment);
2386}
2387
2388
2389/* Generate HSAIL instructions loading a bit field into register DEST. ADDR is
2390 prepared memory address which is used to load the bit field. To identify a
2391 bit field BITPOS is offset to the loaded memory and BITSIZE is number of
2392 bits of the bit field. Add instructions to HBB. Load must be performed in
2393 alignment ALIGN. */
2394
2395static void
2396gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
2397 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2398 hsa_bb *hbb, BrigAlignment8_t align)
2399{
2400 hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
2401 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, dest->m_type, value_reg,
2402 addr);
2403 mem->set_align (align);
2404 hbb->append_insn (mem);
2405 gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
2406}
2407
2408/* Return the alignment of base memory accesses we issue to perform bit-field
2409 memory access REF. */
2410
2411static BrigAlignment8_t
2412hsa_bitmemref_alignment (tree ref)
2413{
2414 unsigned HOST_WIDE_INT bit_offset = 0;
2415
2416 while (true)
2417 {
2418 if (TREE_CODE (ref) == BIT_FIELD_REF)
2419 {
2420 if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
2421 return BRIG_ALIGNMENT_1;
2422 bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
2423 }
2424 else if (TREE_CODE (ref) == COMPONENT_REF
2425 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
2426 bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
2427 else
2428 break;
2429 ref = TREE_OPERAND (ref, 0);
2430 }
2431
2432 unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
2433 unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
320c1a36 2434 BrigAlignment8_t base = hsa_object_alignment (ref);
b2b40051
MJ
2435 if (byte_bits == 0)
2436 return base;
146ec50f 2437 return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
b2b40051
MJ
2438}
2439
2440/* Generate HSAIL instructions loading something into register DEST. RHS is
2441 tree representation of the loaded data, which are loaded as type TYPE. Add
2442 instructions to HBB. */
2443
2444static void
2445gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
2446{
2447 /* The destination SSA name will give us the type. */
2448 if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
2449 rhs = TREE_OPERAND (rhs, 0);
2450
2451 if (TREE_CODE (rhs) == SSA_NAME)
2452 {
2453 hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
2454 hsa_build_append_simple_mov (dest, src, hbb);
2455 }
2456 else if (is_gimple_min_invariant (rhs)
2457 || TREE_CODE (rhs) == ADDR_EXPR)
2458 {
2459 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
2460 {
2461 if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
2462 {
2463 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2464 "support for HSA does not implement conversion "
2465 "of %E to the requested non-pointer type.", rhs);
2466 return;
2467 }
2468
2469 gen_hsa_addr_insns (rhs, dest, hbb);
2470 }
2471 else if (TREE_CODE (rhs) == COMPLEX_CST)
2472 {
2473 hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
2474 hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
2475
2476 hsa_op_reg *real_part_reg
2477 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2478 true));
2479 hsa_op_reg *imag_part_reg
2480 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2481 true));
2482
2483 hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
2484 hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
2485
2486 BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
2487
2488 hsa_insn_packed *insn
2489 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
2490 src_type, dest, real_part_reg,
2491 imag_part_reg);
2492 hbb->append_insn (insn);
2493 }
2494 else
2495 {
2496 hsa_op_immed *imm = new hsa_op_immed (rhs);
2497 hsa_build_append_simple_mov (dest, imm, hbb);
2498 }
2499 }
2500 else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
2501 {
2502 tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
2503
2504 hsa_op_reg *packed_reg
2505 = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
2506
2507 tree complex_rhs = TREE_OPERAND (rhs, 0);
2508 gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
2509 hbb);
2510
2511 hsa_op_reg *real_reg
2512 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2513
2514 hsa_op_reg *imag_reg
2515 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2516
2517 BrigKind16_t brig_type = packed_reg->m_type;
2518 hsa_insn_packed *packed
2519 = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
2520 hsa_bittype_for_type (real_reg->m_type),
2521 brig_type, real_reg, imag_reg, packed_reg);
2522
2523 hbb->append_insn (packed);
2524
2525 hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
2526 real_reg : imag_reg;
2527
2528 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2529 dest->m_type, dest, source);
2530
2531 hbb->append_insn (insn);
2532 }
2533 else if (TREE_CODE (rhs) == BIT_FIELD_REF
2534 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
2535 {
2536 tree ssa_name = TREE_OPERAND (rhs, 0);
2537 HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
2538 HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
2539
2540 hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
2541 gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
2542 }
2543 else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
2544 || TREE_CODE (rhs) == TARGET_MEM_REF
2545 || handled_component_p (rhs))
2546 {
2547 HOST_WIDE_INT bitsize, bitpos;
2548
2549 /* Load from memory. */
2550 hsa_op_address *addr;
2551 addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
2552
2553 /* Handle load of a bit field. */
2554 if (bitsize > 64)
2555 {
2556 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2557 "support for HSA does not implement load from a bit "
2558 "field bigger than 64 bits");
2559 return;
2560 }
2561
2562 if (bitsize || bitpos)
2563 gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
2564 hsa_bitmemref_alignment (rhs));
2565 else
2566 {
2567 BrigType16_t mtype;
2568 /* Not dest->m_type, that's possibly extended. */
2569 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
2570 false));
2571 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
2572 addr);
320c1a36 2573 mem->set_align (hsa_object_alignment (rhs));
b2b40051
MJ
2574 hbb->append_insn (mem);
2575 }
2576 }
2577 else
2578 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2579 "support for HSA does not implement loading "
2580 "of expression %E",
2581 rhs);
2582}
2583
2584/* Return number of bits necessary for representation of a bit field,
2585 starting at BITPOS with size of BITSIZE. */
2586
2587static unsigned
2588get_bitfield_size (unsigned bitpos, unsigned bitsize)
2589{
2590 unsigned s = bitpos + bitsize;
2591 unsigned sizes[] = {8, 16, 32, 64};
2592
2593 for (unsigned i = 0; i < 4; i++)
2594 if (s <= sizes[i])
2595 return sizes[i];
2596
2597 gcc_unreachable ();
2598 return 0;
2599}
2600
2601/* Generate HSAIL instructions storing into memory. LHS is the destination of
2602 the store, SRC is the source operand. Add instructions to HBB. */
2603
2604static void
2605gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
2606{
2607 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2608 BrigAlignment8_t req_align;
2609 BrigType16_t mtype;
2610 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
2611 false));
2612 hsa_op_address *addr;
2613 addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
2614
2615 /* Handle store to a bit field. */
2616 if (bitsize > 64)
2617 {
2618 HSA_SORRY_AT (EXPR_LOCATION (lhs),
2619 "support for HSA does not implement store to a bit field "
2620 "bigger than 64 bits");
2621 return;
2622 }
2623
2624 unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
2625
2626 /* HSAIL does not support MOV insn with 16-bits integers. */
2627 if (type_bitsize < 32)
2628 type_bitsize = 32;
2629
2630 if (bitpos || (bitsize && type_bitsize != bitsize))
2631 {
2632 unsigned HOST_WIDE_INT mask = 0;
2633 BrigType16_t mem_type
2634 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
2635 !TYPE_UNSIGNED (TREE_TYPE (lhs)));
2636
2637 for (unsigned i = 0; i < type_bitsize; i++)
2638 if (i < bitpos || i >= bitpos + bitsize)
2639 mask |= ((unsigned HOST_WIDE_INT)1 << i);
2640
2641 hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
2642
2643 req_align = hsa_bitmemref_alignment (lhs);
2644 /* Load value from memory. */
2645 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
2646 value_reg, addr);
2647 mem->set_align (req_align);
2648 hbb->append_insn (mem);
2649
2650 /* AND the loaded value with prepared mask. */
2651 hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
2652
2653 BrigType16_t t
2654 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
2655 hsa_op_immed *c = new hsa_op_immed (mask, t);
2656
2657 hsa_insn_basic *clearing
2658 = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
2659 value_reg, c);
2660 hbb->append_insn (clearing);
2661
2662 /* Shift to left a value that is going to be stored. */
2663 hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
2664
2665 hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
2666 new_value_reg, src);
2667 hbb->append_insn (basic);
2668
2669 if (bitpos)
2670 {
2671 hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
2672 c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
2673
2674 hsa_insn_basic *basic
2675 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
2676 shifted_value_reg, new_value_reg, c);
2677 hbb->append_insn (basic);
2678
2679 new_value_reg = shifted_value_reg;
2680 }
2681
2682 /* OR the prepared value with prepared chunk loaded from memory. */
2683 hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
2684 basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
2685 new_value_reg, cleared_reg);
2686 hbb->append_insn (basic);
2687
2688 src = prepared_reg;
2689 mtype = mem_type;
2690 }
2691 else
320c1a36 2692 req_align = hsa_object_alignment (lhs);
b2b40051
MJ
2693
2694 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
2695 mem->set_align (req_align);
2696
2697 /* The HSAIL verifier has another constraint: if the source is an immediate
2698 then it must match the destination type. If it's a register the low bits
2699 will be used for sub-word stores. We're always allocating new operands so
2700 we can modify the above in place. */
2701 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
2702 {
27d39ae1 2703 if (!hsa_type_packed_p (imm->m_type))
b2b40051
MJ
2704 imm->m_type = mem->m_type;
2705 else
2706 {
2707 /* ...and all vector immediates apparently need to be vectors of
2708 unsigned bytes. */
2709 unsigned bs = hsa_type_bit_size (imm->m_type);
2710 gcc_assert (bs == hsa_type_bit_size (mem->m_type));
2711 switch (bs)
2712 {
2713 case 32:
2714 imm->m_type = BRIG_TYPE_U8X4;
2715 break;
2716 case 64:
2717 imm->m_type = BRIG_TYPE_U8X8;
2718 break;
2719 case 128:
2720 imm->m_type = BRIG_TYPE_U8X16;
2721 break;
2722 default:
2723 gcc_unreachable ();
2724 }
2725 }
2726 }
2727
2728 hbb->append_insn (mem);
2729}
2730
2731/* Generate memory copy instructions that are going to be used
65e21467 2732 for copying a SRC memory to TARGET memory,
320c1a36 2733 represented by pointer in a register. MIN_ALIGN is minimal alignment
65e21467 2734 of provided HSA addresses. */
b2b40051
MJ
2735
2736static void
2737gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
320c1a36 2738 unsigned size, BrigAlignment8_t min_align)
b2b40051
MJ
2739{
2740 hsa_op_address *addr;
2741 hsa_insn_mem *mem;
2742
2743 unsigned offset = 0;
320c1a36 2744 unsigned min_byte_align = hsa_byte_alignment (min_align);
b2b40051
MJ
2745
2746 while (size)
2747 {
2748 unsigned s;
2749 if (size >= 8)
2750 s = 8;
2751 else if (size >= 4)
2752 s = 4;
2753 else if (size >= 2)
2754 s = 2;
2755 else
2756 s = 1;
2757
320c1a36
ML
2758 if (s > min_byte_align)
2759 s = min_byte_align;
2760
b2b40051
MJ
2761 BrigType16_t t = get_integer_type_by_bytes (s, false);
2762
2763 hsa_op_reg *tmp = new hsa_op_reg (t);
2764 addr = new hsa_op_address (src->m_symbol, src->m_reg,
2765 src->m_imm_offset + offset);
2766 mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
2767 hbb->append_insn (mem);
2768
2769 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2770 target->m_imm_offset + offset);
2771 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
2772 hbb->append_insn (mem);
2773 offset += s;
2774 size -= s;
2775 }
2776}
2777
2778/* Create a memset mask that is created by copying a CONSTANT byte value
2779 to an integer of BYTE_SIZE bytes. */
2780
2781static unsigned HOST_WIDE_INT
2782build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
2783{
2784 if (constant == 0)
2785 return 0;
2786
2787 HOST_WIDE_INT v = constant;
2788
2789 for (unsigned i = 1; i < byte_size; i++)
2790 v |= constant << (8 * i);
2791
2792 return v;
2793}
2794
2795/* Generate memory set instructions that are going to be used
65e21467
ML
2796 for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
2797 MIN_ALIGN is minimal alignment of provided HSA addresses. */
b2b40051
MJ
2798
2799static void
2800gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
2801 unsigned HOST_WIDE_INT constant,
65e21467 2802 unsigned size, BrigAlignment8_t min_align)
b2b40051
MJ
2803{
2804 hsa_op_address *addr;
2805 hsa_insn_mem *mem;
2806
2807 unsigned offset = 0;
65e21467 2808 unsigned min_byte_align = hsa_byte_alignment (min_align);
b2b40051
MJ
2809
2810 while (size)
2811 {
2812 unsigned s;
2813 if (size >= 8)
2814 s = 8;
2815 else if (size >= 4)
2816 s = 4;
2817 else if (size >= 2)
2818 s = 2;
2819 else
2820 s = 1;
2821
65e21467
ML
2822 if (s > min_byte_align)
2823 s = min_byte_align;
2824
b2b40051
MJ
2825 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2826 target->m_imm_offset + offset);
2827
2828 BrigType16_t t = get_integer_type_by_bytes (s, false);
2829 HOST_WIDE_INT c = build_memset_value (constant, s);
2830
2831 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
2832 addr);
2833 hbb->append_insn (mem);
2834 offset += s;
2835 size -= s;
2836 }
2837}
2838
2839/* Generate HSAIL instructions for a single assignment
2840 of an empty constructor to an ADDR_LHS. Constructor is passed as a
65e21467
ML
2841 tree RHS and all instructions are appended to HBB. ALIGN is
2842 alignment of the address. */
b2b40051
MJ
2843
2844void
65e21467
ML
2845gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
2846 BrigAlignment8_t align)
b2b40051
MJ
2847{
2848 if (vec_safe_length (CONSTRUCTOR_ELTS (rhs)))
2849 {
2850 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2851 "support for HSA does not implement load from constructor");
2852 return;
2853 }
2854
2855 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
65e21467 2856 gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
b2b40051
MJ
2857}
2858
2859/* Generate HSA instructions for a single assignment of RHS to LHS.
2860 HBB is the basic block they will be appended to. */
2861
2862static void
2863gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
2864{
2865 if (TREE_CODE (lhs) == SSA_NAME)
2866 {
2867 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
2868 if (hsa_seen_error ())
2869 return;
2870
2871 gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
2872 }
2873 else if (TREE_CODE (rhs) == SSA_NAME
2874 || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
2875 {
2876 /* Store to memory. */
2877 hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
2878 if (hsa_seen_error ())
2879 return;
2880
2881 gen_hsa_insns_for_store (lhs, src, hbb);
2882 }
2883 else
2884 {
320c1a36
ML
2885 BrigAlignment8_t lhs_align;
2886 hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
2887 &lhs_align);
b2b40051
MJ
2888
2889 if (TREE_CODE (rhs) == CONSTRUCTOR)
65e21467 2890 gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
b2b40051
MJ
2891 else
2892 {
320c1a36
ML
2893 BrigAlignment8_t rhs_align;
2894 hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
2895 &rhs_align);
b2b40051
MJ
2896
2897 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
320c1a36
ML
2898 gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
2899 MIN (lhs_align, rhs_align));
b2b40051
MJ
2900 }
2901 }
2902}
2903
2904/* Prepend before INSN a load from spill symbol of SPILL_REG. Return the
2905 register into which we loaded. If this required another register to convert
2906 from a B1 type, return it in *PTMP2, otherwise store NULL into it. We
2907 assume we are out of SSA so the returned register does not have its
2908 definition set. */
2909
2910hsa_op_reg *
2911hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2912{
2913 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2914 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2915 hsa_op_address *addr = new hsa_op_address (spill_sym);
2916
2917 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
2918 reg, addr);
2919 hsa_insert_insn_before (mem, insn);
2920
2921 *ptmp2 = NULL;
2922 if (spill_reg->m_type == BRIG_TYPE_B1)
2923 {
2924 hsa_insn_basic *cvtinsn;
2925 *ptmp2 = reg;
2926 reg = new hsa_op_reg (spill_reg->m_type);
2927
2928 cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
2929 hsa_insert_insn_before (cvtinsn, insn);
2930 }
2931 return reg;
2932}
2933
2934/* Append after INSN a store to spill symbol of SPILL_REG. Return the register
2935 from which we stored. If this required another register to convert to a B1
2936 type, return it in *PTMP2, otherwise store NULL into it. We assume we are
2937 out of SSA so the returned register does not have its use updated. */
2938
2939hsa_op_reg *
2940hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2941{
2942 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2943 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2944 hsa_op_address *addr = new hsa_op_address (spill_sym);
2945 hsa_op_reg *returnreg;
2946
2947 *ptmp2 = NULL;
2948 returnreg = reg;
2949 if (spill_reg->m_type == BRIG_TYPE_B1)
2950 {
2951 hsa_insn_basic *cvtinsn;
2952 *ptmp2 = new hsa_op_reg (spill_sym->m_type);
2953 reg->m_type = spill_reg->m_type;
2954
2955 cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
2956 hsa_append_insn_after (cvtinsn, insn);
2957 insn = cvtinsn;
2958 reg = *ptmp2;
2959 }
2960
2961 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
2962 addr);
2963 hsa_append_insn_after (mem, insn);
2964 return returnreg;
2965}
2966
2967/* Generate a comparison instruction that will compare LHS and RHS with
2968 comparison specified by CODE and put result into register DEST. DEST has to
2969 have its type set already but must not have its definition set yet.
2970 Generated instructions will be added to HBB. */
2971
2972static void
2973gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
2974 hsa_op_reg *dest, hsa_bb *hbb)
2975{
2976 BrigCompareOperation8_t compare;
2977
2978 switch (code)
2979 {
2980 case LT_EXPR:
2981 compare = BRIG_COMPARE_LT;
2982 break;
2983 case LE_EXPR:
2984 compare = BRIG_COMPARE_LE;
2985 break;
2986 case GT_EXPR:
2987 compare = BRIG_COMPARE_GT;
2988 break;
2989 case GE_EXPR:
2990 compare = BRIG_COMPARE_GE;
2991 break;
2992 case EQ_EXPR:
2993 compare = BRIG_COMPARE_EQ;
2994 break;
2995 case NE_EXPR:
2996 compare = BRIG_COMPARE_NE;
2997 break;
2998 case UNORDERED_EXPR:
2999 compare = BRIG_COMPARE_NAN;
3000 break;
3001 case ORDERED_EXPR:
3002 compare = BRIG_COMPARE_NUM;
3003 break;
3004 case UNLT_EXPR:
3005 compare = BRIG_COMPARE_LTU;
3006 break;
3007 case UNLE_EXPR:
3008 compare = BRIG_COMPARE_LEU;
3009 break;
3010 case UNGT_EXPR:
3011 compare = BRIG_COMPARE_GTU;
3012 break;
3013 case UNGE_EXPR:
3014 compare = BRIG_COMPARE_GEU;
3015 break;
3016 case UNEQ_EXPR:
3017 compare = BRIG_COMPARE_EQU;
3018 break;
3019 case LTGT_EXPR:
3020 compare = BRIG_COMPARE_NEU;
3021 break;
3022
3023 default:
3024 HSA_SORRY_ATV (EXPR_LOCATION (lhs),
3025 "support for HSA does not implement comparison tree "
3026 "code %s\n", get_tree_code_name (code));
3027 return;
3028 }
3029
3030 /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
3031 as a result of comparison. */
3032
3033 BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
3034 ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
3035
3036 hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
3037 cmp->set_op (1, hsa_reg_or_immed_for_gimple_op (lhs, hbb));
3038 cmp->set_op (2, hsa_reg_or_immed_for_gimple_op (rhs, hbb));
3039
3040 hbb->append_insn (cmp);
3041 cmp->set_output_in_type (dest, 0, hbb);
3042}
3043
3044/* Generate an unary instruction with OPCODE and append it to a basic block
3045 HBB. The instruction uses DEST as a destination and OP1
3046 as a single operand. */
3047
3048static void
3049gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
3050 hsa_op_with_type *op1, hsa_bb *hbb)
3051{
3052 gcc_checking_assert (dest);
3053 hsa_insn_basic *insn;
3054
3055 if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
3056 insn = new hsa_insn_cvt (dest, op1);
3057 else if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3058 insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, op1->m_type, NULL,
3059 op1);
3060 else
3061 {
3062 insn = new hsa_insn_basic (2, opcode, dest->m_type, dest, op1);
3063
3064 if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
3065 {
3066 /* ABS and NEG only exist in _s form :-/ */
3067 if (insn->m_type == BRIG_TYPE_U32)
3068 insn->m_type = BRIG_TYPE_S32;
3069 else if (insn->m_type == BRIG_TYPE_U64)
3070 insn->m_type = BRIG_TYPE_S64;
3071 }
3072 }
3073
3074 hbb->append_insn (insn);
3075
3076 if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3077 insn->set_output_in_type (dest, 0, hbb);
3078}
3079
3080/* Generate a binary instruction with OPCODE and append it to a basic block
3081 HBB. The instruction uses DEST as a destination and operands OP1
3082 and OP2. */
3083
3084static void
3085gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
3086 hsa_op_base *op1, hsa_op_base *op2, hsa_bb *hbb)
3087{
3088 gcc_checking_assert (dest);
3089
3090 if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
3091 && is_a <hsa_op_immed *> (op2))
3092 {
3093 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3094 i->set_type (BRIG_TYPE_U32);
3095 }
3096 if ((opcode == BRIG_OPCODE_OR
3097 || opcode == BRIG_OPCODE_XOR
3098 || opcode == BRIG_OPCODE_AND)
3099 && is_a <hsa_op_immed *> (op2))
3100 {
3101 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
b15e4689 3102 i->set_type (hsa_unsigned_type_for_type (i->m_type));
b2b40051
MJ
3103 }
3104
3105 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, dest->m_type, dest,
3106 op1, op2);
3107 hbb->append_insn (insn);
3108}
3109
3110/* Generate HSA instructions for a single assignment. HBB is the basic block
3111 they will be appended to. */
3112
3113static void
3114gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
3115{
3116 tree_code code = gimple_assign_rhs_code (assign);
3117 gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
3118
3119 tree lhs = gimple_assign_lhs (assign);
3120 tree rhs1 = gimple_assign_rhs1 (assign);
3121 tree rhs2 = gimple_assign_rhs2 (assign);
3122 tree rhs3 = gimple_assign_rhs3 (assign);
3123
3124 BrigOpcode opcode;
3125
3126 switch (code)
3127 {
3128 CASE_CONVERT:
3129 case FLOAT_EXPR:
3130 /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
3131 needs a conversion. */
3132 opcode = BRIG_OPCODE_MOV;
3133 break;
3134
3135 case PLUS_EXPR:
3136 case POINTER_PLUS_EXPR:
3137 opcode = BRIG_OPCODE_ADD;
3138 break;
3139 case MINUS_EXPR:
3140 opcode = BRIG_OPCODE_SUB;
3141 break;
3142 case MULT_EXPR:
3143 opcode = BRIG_OPCODE_MUL;
3144 break;
3145 case MULT_HIGHPART_EXPR:
3146 opcode = BRIG_OPCODE_MULHI;
3147 break;
3148 case RDIV_EXPR:
3149 case TRUNC_DIV_EXPR:
3150 case EXACT_DIV_EXPR:
3151 opcode = BRIG_OPCODE_DIV;
3152 break;
3153 case CEIL_DIV_EXPR:
3154 case FLOOR_DIV_EXPR:
3155 case ROUND_DIV_EXPR:
3156 HSA_SORRY_AT (gimple_location (assign),
3157 "support for HSA does not implement CEIL_DIV_EXPR, "
3158 "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
3159 return;
3160 case TRUNC_MOD_EXPR:
3161 opcode = BRIG_OPCODE_REM;
3162 break;
3163 case CEIL_MOD_EXPR:
3164 case FLOOR_MOD_EXPR:
3165 case ROUND_MOD_EXPR:
3166 HSA_SORRY_AT (gimple_location (assign),
3167 "support for HSA does not implement CEIL_MOD_EXPR, "
3168 "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
3169 return;
3170 case NEGATE_EXPR:
3171 opcode = BRIG_OPCODE_NEG;
3172 break;
3173 case MIN_EXPR:
3174 opcode = BRIG_OPCODE_MIN;
3175 break;
3176 case MAX_EXPR:
3177 opcode = BRIG_OPCODE_MAX;
3178 break;
3179 case ABS_EXPR:
3180 opcode = BRIG_OPCODE_ABS;
3181 break;
3182 case LSHIFT_EXPR:
3183 opcode = BRIG_OPCODE_SHL;
3184 break;
3185 case RSHIFT_EXPR:
3186 opcode = BRIG_OPCODE_SHR;
3187 break;
3188 case LROTATE_EXPR:
3189 case RROTATE_EXPR:
3190 {
3191 hsa_insn_basic *insn = NULL;
3192 int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3193 int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3194 BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3195 true);
3196
3197 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3198 hsa_op_reg *op1 = new hsa_op_reg (btype);
3199 hsa_op_reg *op2 = new hsa_op_reg (btype);
3200 hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3201
3202 tree type = TREE_TYPE (rhs2);
3203 unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3204
3205 hsa_op_with_type *shift2 = NULL;
3206 if (TREE_CODE (rhs2) == INTEGER_CST)
3207 shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3208 BRIG_TYPE_U32);
3209 else if (TREE_CODE (rhs2) == SSA_NAME)
3210 {
3211 hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3212 hsa_op_reg *d = new hsa_op_reg (s->m_type);
3213 hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3214
3215 insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3216 d, s, size_imm);
3217 hbb->append_insn (insn);
3218
3219 shift2 = d;
3220 }
3221 else
3222 gcc_unreachable ();
3223
3224 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3225 gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3226 gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3227 gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3228
3229 return;
3230 }
3231 case BIT_IOR_EXPR:
3232 opcode = BRIG_OPCODE_OR;
3233 break;
3234 case BIT_XOR_EXPR:
3235 opcode = BRIG_OPCODE_XOR;
3236 break;
3237 case BIT_AND_EXPR:
3238 opcode = BRIG_OPCODE_AND;
3239 break;
3240 case BIT_NOT_EXPR:
3241 opcode = BRIG_OPCODE_NOT;
3242 break;
3243 case FIX_TRUNC_EXPR:
3244 {
3245 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3246 hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3247
3248 if (hsa_needs_cvt (dest->m_type, v->m_type))
3249 {
3250 hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3251
3252 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3253 tmp->m_type, tmp, v);
3254 hbb->append_insn (insn);
3255
3256 hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3257 hbb->append_insn (cvtinsn);
3258 }
3259 else
3260 {
3261 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3262 dest->m_type, dest, v);
3263 hbb->append_insn (insn);
3264 }
3265
3266 return;
3267 }
3268 opcode = BRIG_OPCODE_TRUNC;
3269 break;
3270
3271 case LT_EXPR:
3272 case LE_EXPR:
3273 case GT_EXPR:
3274 case GE_EXPR:
3275 case EQ_EXPR:
3276 case NE_EXPR:
3277 case UNORDERED_EXPR:
3278 case ORDERED_EXPR:
3279 case UNLT_EXPR:
3280 case UNLE_EXPR:
3281 case UNGT_EXPR:
3282 case UNGE_EXPR:
3283 case UNEQ_EXPR:
3284 case LTGT_EXPR:
3285 {
3286 hsa_op_reg *dest
3287 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3288
3289 gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3290 return;
3291 }
3292 case COND_EXPR:
3293 {
3294 hsa_op_reg *dest
3295 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3296 hsa_op_with_type *ctrl = NULL;
3297 tree cond = rhs1;
3298
3299 if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3300 ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3301 else
3302 {
3303 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3304
3305 gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3306 TREE_OPERAND (cond, 0),
3307 TREE_OPERAND (cond, 1),
3308 r, hbb);
3309
3310 ctrl = r;
3311 }
3312
b15e4689
MJ
3313 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3314 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
b2b40051 3315
b15e4689
MJ
3316 BrigType16_t utype = hsa_unsigned_type_for_type (dest->m_type);
3317 if (is_a <hsa_op_immed *> (op2))
3318 op2->m_type = utype;
3319 if (is_a <hsa_op_immed *> (op3))
3320 op3->m_type = utype;
b2b40051
MJ
3321
3322 hsa_insn_basic *insn
b15e4689
MJ
3323 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3324 hsa_bittype_for_type (dest->m_type),
3325 dest, ctrl, op2, op3);
b2b40051
MJ
3326
3327 hbb->append_insn (insn);
b2b40051
MJ
3328 return;
3329 }
3330 case COMPLEX_EXPR:
3331 {
3332 hsa_op_reg *dest
3333 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3334 hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3335 hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3336
3337 if (hsa_seen_error ())
3338 return;
3339
3340 BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3341 rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3342 rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3343
3344 hsa_insn_packed *insn
3345 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3346 dest, rhs1_reg, rhs2_reg);
3347 hbb->append_insn (insn);
3348
3349 return;
3350 }
3351 default:
3352 /* Implement others as we come across them. */
3353 HSA_SORRY_ATV (gimple_location (assign),
3354 "support for HSA does not implement operation %s",
3355 get_tree_code_name (code));
3356 return;
3357 }
3358
3359
3360 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3361
3362 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3363 hsa_op_with_type *op2 = rhs2 != NULL_TREE ?
3364 hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3365
3366 if (hsa_seen_error ())
3367 return;
3368
3369 switch (rhs_class)
3370 {
3371 case GIMPLE_TERNARY_RHS:
3372 gcc_unreachable ();
3373 return;
3374
3375 /* Fall through */
3376 case GIMPLE_BINARY_RHS:
3377 gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3378 break;
3379 /* Fall through */
3380 case GIMPLE_UNARY_RHS:
3381 gen_hsa_unary_operation (opcode, dest, op1, hbb);
3382 break;
3383 default:
3384 gcc_unreachable ();
3385 }
3386}
3387
3388/* Generate HSA instructions for a given gimple condition statement COND.
3389 Instructions will be appended to HBB, which also needs to be the
3390 corresponding structure to the basic_block of COND. */
3391
3392static void
3393gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3394{
3395 hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3396 hsa_insn_br *cbr;
3397
3398 gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3399 gimple_cond_lhs (cond),
3400 gimple_cond_rhs (cond),
3401 ctrl, hbb);
3402
3403 cbr = new hsa_insn_br (ctrl);
3404 hbb->append_insn (cbr);
3405}
3406
3407/* Maximum number of elements in a jump table for an HSA SBR instruction. */
3408
3409#define HSA_MAXIMUM_SBR_LABELS 16
3410
3411/* Return lowest value of a switch S that is handled in a non-default
3412 label. */
3413
3414static tree
3415get_switch_low (gswitch *s)
3416{
3417 unsigned labels = gimple_switch_num_labels (s);
3418 gcc_checking_assert (labels >= 1);
3419
3420 return CASE_LOW (gimple_switch_label (s, 1));
3421}
3422
3423/* Return highest value of a switch S that is handled in a non-default
3424 label. */
3425
3426static tree
3427get_switch_high (gswitch *s)
3428{
3429 unsigned labels = gimple_switch_num_labels (s);
3430
3431 /* Compare last label to maximum number of labels. */
3432 tree label = gimple_switch_label (s, labels - 1);
3433 tree low = CASE_LOW (label);
3434 tree high = CASE_HIGH (label);
3435
3436 return high != NULL_TREE ? high : low;
3437}
3438
3439static tree
3440get_switch_size (gswitch *s)
3441{
3442 return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3443}
3444
3445/* Generate HSA instructions for a given gimple switch.
3446 Instructions will be appended to HBB. */
3447
3448static void
3449gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3450{
e8661ad6
ML
3451 gimple_stmt_iterator it = gsi_for_stmt (s);
3452 gsi_prev (&it);
3453
3454 /* Create preambule that verifies that index - lowest_label >= 0. */
3455 edge e = split_block (hbb->m_bb, gsi_stmt (it));
3456 e->flags &= ~EDGE_FALLTHRU;
3457 e->flags |= EDGE_TRUE_VALUE;
3458
b2b40051
MJ
3459 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
3460 tree index_tree = gimple_switch_index (s);
3461 tree lowest = get_switch_low (s);
e8661ad6 3462 tree highest = get_switch_high (s);
b2b40051
MJ
3463
3464 hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
e8661ad6
ML
3465
3466 hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3467 hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest);
3468 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3469 cmp1_reg, index, cmp1_immed));
3470
3471 hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3472 hsa_op_immed *cmp2_immed = new hsa_op_immed (highest);
3473 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3474 cmp2_reg, index, cmp2_immed));
3475
3476 hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3477 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3478 cmp_reg, cmp1_reg, cmp2_reg));
3479
3480 hbb->append_insn (new hsa_insn_br (cmp_reg));
3481
3482 tree default_label = gimple_switch_default_label (s);
3483 basic_block default_label_bb = label_to_block_fn (func,
3484 CASE_LABEL (default_label));
3485
a5057543
MJ
3486 if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3487 {
3488 default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3489 hsa_init_new_bb (default_label_bb);
3490 }
3491
e8661ad6
ML
3492 make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3493
3494 hsa_cfun->m_modified_cfg = true;
3495
3496 /* Basic block with the SBR instruction. */
3497 hbb = hsa_init_new_bb (e->dest);
3498
b2b40051
MJ
3499 hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3500 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3501 sub_index, index,
3502 new hsa_op_immed (lowest)));
3503
3504 hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3505 sub_index = as_a <hsa_op_reg *> (tmp);
3506 unsigned labels = gimple_switch_num_labels (s);
3507 unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3508
3509 hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
b2b40051
MJ
3510
3511 /* Prepare array with default label destination. */
3512 for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3513 sbr->m_jump_table.safe_push (default_label_bb);
3514
3515 /* Iterate all labels and fill up the jump table. */
3516 for (unsigned i = 1; i < labels; i++)
3517 {
3518 tree label = gimple_switch_label (s, i);
3519 basic_block bb = label_to_block_fn (func, CASE_LABEL (label));
3520
3521 unsigned HOST_WIDE_INT sub_low
3522 = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3523
3524 unsigned HOST_WIDE_INT sub_high = sub_low;
3525 tree high = CASE_HIGH (label);
3526 if (high != NULL)
3527 sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3528
3529 for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3530 sbr->m_jump_table[j] = bb;
3531 }
3532
3533 hbb->append_insn (sbr);
3534}
3535
3536/* Verify that the function DECL can be handled by HSA. */
3537
3538static void
3539verify_function_arguments (tree decl)
3540{
3541 if (DECL_STATIC_CHAIN (decl))
3542 {
3543 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3544 "HSA does not support nested functions: %D", decl);
3545 return;
3546 }
3547 else if (!TYPE_ARG_TYPES (TREE_TYPE (decl)))
3548 {
3549 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3550 "HSA does not support functions with variadic arguments "
3551 "(or unknown return type): %D", decl);
3552 return;
3553 }
3554}
3555
3556/* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL,
3557 return ACTUAL_ARG_TYPE. */
3558
3559static BrigType16_t
3560get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3561{
3562 if (formal_arg_type == NULL)
3563 return actual_arg_type;
3564
3565 BrigType16_t decl_type
3566 = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3567 return mem_type_for_type (decl_type);
3568}
3569
3570/* Generate HSA instructions for a direct call instruction.
3571 Instructions will be appended to HBB, which also needs to be the
65e21467
ML
3572 corresponding structure to the basic_block of STMT.
3573 If ASSIGN_LHS is false, do not copy HSA function result argument into the
3574 corresponding HSA representation of the gimple statement LHS. */
b2b40051
MJ
3575
3576static void
65e21467
ML
3577gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3578 bool assign_lhs = true)
b2b40051
MJ
3579{
3580 tree decl = gimple_call_fndecl (stmt);
3581 verify_function_arguments (decl);
3582 if (hsa_seen_error ())
3583 return;
3584
3585 hsa_insn_call *call_insn = new hsa_insn_call (decl);
3586 hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3587
3588 /* Argument block start. */
3589 hsa_insn_arg_block *arg_start
3590 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3591 hbb->append_insn (arg_start);
3592
3593 tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3594
3595 /* Preparation of arguments that will be passed to function. */
3596 const unsigned args = gimple_call_num_args (stmt);
3597 for (unsigned i = 0; i < args; ++i)
3598 {
3599 tree parm = gimple_call_arg (stmt, (int)i);
3600 tree parm_decl_type = parm_type_chain != NULL_TREE
3601 ? TREE_VALUE (parm_type_chain) : NULL_TREE;
3602 hsa_op_address *addr;
3603
3604 if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3605 {
3606 addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
320c1a36
ML
3607 BrigAlignment8_t align;
3608 hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
b2b40051 3609 gen_hsa_memory_copy (hbb, addr, src,
320c1a36 3610 addr->m_symbol->total_byte_size (), align);
b2b40051
MJ
3611 }
3612 else
3613 {
3614 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3615
3616 if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3617 {
3618 HSA_SORRY_AT (gimple_location (stmt),
3619 "support for HSA does not implement an aggregate "
3620 "formal argument in a function call, while actual "
3621 "argument is not an aggregate");
3622 return;
3623 }
3624
3625 BrigType16_t formal_arg_type
3626 = get_format_argument_type (parm_decl_type, src->m_type);
3627 if (hsa_seen_error ())
3628 return;
3629
3630 if (src->m_type != formal_arg_type)
3631 src = src->get_in_type (formal_arg_type, hbb);
3632
3633 addr
3634 = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3635 parm_decl_type: TREE_TYPE (parm), i);
3636 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3637 src, addr);
3638
3639 hbb->append_insn (mem);
3640 }
3641
3642 call_insn->m_input_args.safe_push (addr->m_symbol);
3643 if (parm_type_chain)
3644 parm_type_chain = TREE_CHAIN (parm_type_chain);
3645 }
3646
3647 call_insn->m_args_code_list = new hsa_op_code_list (args);
3648 hbb->append_insn (call_insn);
3649
3650 tree result_type = TREE_TYPE (TREE_TYPE (decl));
3651
3652 tree result = gimple_call_lhs (stmt);
3653 hsa_insn_mem *result_insn = NULL;
3654 if (!VOID_TYPE_P (result_type))
3655 {
3656 hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3657
3658 /* Even if result of a function call is unused, we have to emit
3659 declaration for the result. */
65e21467 3660 if (result && assign_lhs)
b2b40051
MJ
3661 {
3662 tree lhs_type = TREE_TYPE (result);
3663
3664 if (hsa_seen_error ())
3665 return;
3666
3667 if (AGGREGATE_TYPE_P (lhs_type))
3668 {
320c1a36
ML
3669 BrigAlignment8_t align;
3670 hsa_op_address *result_addr
3671 = gen_hsa_addr_with_align (result, hbb, &align);
b2b40051 3672 gen_hsa_memory_copy (hbb, result_addr, addr,
320c1a36 3673 addr->m_symbol->total_byte_size (), align);
b2b40051
MJ
3674 }
3675 else
3676 {
3677 BrigType16_t mtype
3678 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3679 false));
3680
3681 hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3682 result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3683 hbb->append_insn (result_insn);
3684 }
3685 }
3686
3687 call_insn->m_output_arg = addr->m_symbol;
3688 call_insn->m_result_code_list = new hsa_op_code_list (1);
3689 }
3690 else
3691 {
3692 if (result)
3693 {
3694 HSA_SORRY_AT (gimple_location (stmt),
3695 "support for HSA does not implement an assignment of "
3696 "return value from a void function");
3697 return;
3698 }
3699
3700 call_insn->m_result_code_list = new hsa_op_code_list (0);
3701 }
3702
3703 /* Argument block end. */
3704 hsa_insn_arg_block *arg_end
3705 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3706 hbb->append_insn (arg_end);
3707}
3708
3709/* Generate HSA instructions for a direct call of an internal fn.
3710 Instructions will be appended to HBB, which also needs to be the
3711 corresponding structure to the basic_block of STMT. */
3712
3713static void
3714gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3715{
3716 tree lhs = gimple_call_lhs (stmt);
3717 if (!lhs)
3718 return;
3719
3720 tree lhs_type = TREE_TYPE (lhs);
3721 tree rhs1 = gimple_call_arg (stmt, 0);
3722 tree rhs1_type = TREE_TYPE (rhs1);
3723 enum internal_fn fn = gimple_call_internal_fn (stmt);
3724 hsa_internal_fn *ifn
3725 = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3726 hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3727
3728 gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3729
3730 if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3731 hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3732
3733 hsa_insn_arg_block *arg_start
3734 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3735 hbb->append_insn (arg_start);
3736
3737 unsigned num_args = gimple_call_num_args (stmt);
3738
3739 /* Function arguments. */
3740 for (unsigned i = 0; i < num_args; i++)
3741 {
3742 tree parm = gimple_call_arg (stmt, (int)i);
3743 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3744
3745 hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3746 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3747 src, addr);
3748
3749 call_insn->m_input_args.safe_push (addr->m_symbol);
3750 hbb->append_insn (mem);
3751 }
3752
3753 call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3754 hbb->append_insn (call_insn);
3755
3756 /* Assign returned value. */
3757 hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3758
3759 call_insn->m_output_arg = addr->m_symbol;
3760 call_insn->m_result_code_list = new hsa_op_code_list (1);
3761
3762 /* Argument block end. */
3763 hsa_insn_arg_block *arg_end
3764 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3765 hbb->append_insn (arg_end);
3766}
3767
3768/* Generate HSA instructions for a return value instruction.
3769 Instructions will be appended to HBB, which also needs to be the
3770 corresponding structure to the basic_block of STMT. */
3771
3772static void
3773gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3774{
3775 tree retval = gimple_return_retval (stmt);
3776 if (retval)
3777 {
3778 hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3779
3780 if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3781 {
320c1a36
ML
3782 BrigAlignment8_t align;
3783 hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3784 &align);
b2b40051 3785 gen_hsa_memory_copy (hbb, addr, retval_addr,
320c1a36
ML
3786 hsa_cfun->m_output_arg->total_byte_size (),
3787 align);
b2b40051
MJ
3788 }
3789 else
3790 {
3791 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3792 false);
3793 BrigType16_t mtype = mem_type_for_type (t);
3794
3795 /* Store of return value. */
3796 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3797 src = src->get_in_type (mtype, hbb);
3798 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3799 addr);
3800 hbb->append_insn (mem);
3801 }
3802 }
3803
3804 /* HSAIL return instruction emission. */
3805 hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3806 hbb->append_insn (ret);
3807}
3808
3809/* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3810 can have a different type, conversion instructions are possibly
3811 appended to HBB. */
3812
3813void
3814hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3815 hsa_bb *hbb)
3816{
3817 hsa_insn_basic *insn;
3818 gcc_checking_assert (op_output_p (op_index));
3819
3820 if (dest->m_type == m_type)
3821 {
3822 set_op (op_index, dest);
3823 return;
3824 }
3825
3826 hsa_op_reg *tmp = new hsa_op_reg (m_type);
3827 set_op (op_index, tmp);
3828
3829 if (hsa_needs_cvt (dest->m_type, m_type))
3830 insn = new hsa_insn_cvt (dest, tmp);
3831 else
3832 insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3833 dest, tmp->get_in_type (dest->m_type, hbb));
3834
3835 hbb->append_insn (insn);
3836}
3837
3838/* Generate instruction OPCODE to query a property of HSA grid along the
3839 given DIMENSION. Store result into DEST and append the instruction to
3840 HBB. */
3841
3842static void
3843query_hsa_grid (hsa_op_reg *dest, BrigType16_t opcode, int dimension,
3844 hsa_bb *hbb)
3845{
3846 /* We're using just one-dimensional kernels, so hard-coded
3847 dimension X. */
3848 hsa_op_immed *imm
3849 = new hsa_op_immed (dimension, (BrigKind16_t) BRIG_TYPE_U32);
3850 hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3851 imm);
3852 hbb->append_insn (insn);
3853 insn->set_output_in_type (dest, 0, hbb);
3854}
3855
3856/* Generate a special HSA-related instruction for gimple STMT.
3857 Instructions are appended to basic block HBB. */
3858
3859static void
3860query_hsa_grid (gimple *stmt, BrigOpcode16_t opcode, int dimension,
3861 hsa_bb *hbb)
3862{
3863 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3864 if (lhs == NULL_TREE)
3865 return;
3866
3867 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3868
3869 query_hsa_grid (dest, opcode, dimension, hbb);
3870}
3871
3872/* Emit instructions that set hsa_num_threads according to provided VALUE.
3873 Instructions are appended to basic block HBB. */
3874
3875static void
3876gen_set_num_threads (tree value, hsa_bb *hbb)
3877{
3878 hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3879 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3880
3881 src = src->get_in_type (hsa_num_threads->m_type, hbb);
3882 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3883
3884 hsa_insn_basic *basic
3885 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3886 hbb->append_insn (basic);
3887}
3888
b2b40051
MJ
3889/* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3890 is defined in plugin-hsa.c. */
3891
3892static HOST_WIDE_INT
3893get_hsa_kernel_dispatch_offset (const char *field_name)
3894{
4bf1cec7
MJ
3895 tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3896 if (*hsa_kernel_dispatch_type == NULL)
b2b40051
MJ
3897 {
3898 /* Collection of information needed for a dispatch of a kernel from a
3899 kernel. Keep in sync with libgomp's plugin-hsa.c. */
3900
4bf1cec7 3901 *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
b2b40051
MJ
3902 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3903 get_identifier ("queue"), ptr_type_node);
3904 DECL_CHAIN (id_f1) = NULL_TREE;
3905 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3906 get_identifier ("omp_data_memory"),
3907 ptr_type_node);
3908 DECL_CHAIN (id_f2) = id_f1;
3909 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3910 get_identifier ("kernarg_address"),
3911 ptr_type_node);
3912 DECL_CHAIN (id_f3) = id_f2;
3913 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3914 get_identifier ("object"),
3915 uint64_type_node);
3916 DECL_CHAIN (id_f4) = id_f3;
3917 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3918 get_identifier ("signal"),
3919 uint64_type_node);
3920 DECL_CHAIN (id_f5) = id_f4;
3921 tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3922 get_identifier ("private_segment_size"),
3923 uint32_type_node);
3924 DECL_CHAIN (id_f6) = id_f5;
3925 tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3926 get_identifier ("group_segment_size"),
3927 uint32_type_node);
3928 DECL_CHAIN (id_f7) = id_f6;
3929 tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3930 get_identifier ("kernel_dispatch_count"),
3931 uint64_type_node);
3932 DECL_CHAIN (id_f8) = id_f7;
3933 tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3934 get_identifier ("debug"),
3935 uint64_type_node);
3936 DECL_CHAIN (id_f9) = id_f8;
3937 tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3938 get_identifier ("omp_level"),
3939 uint64_type_node);
3940 DECL_CHAIN (id_f10) = id_f9;
3941 tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3942 get_identifier ("children_dispatches"),
3943 ptr_type_node);
3944 DECL_CHAIN (id_f11) = id_f10;
3945 tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3946 get_identifier ("omp_num_threads"),
3947 uint32_type_node);
3948 DECL_CHAIN (id_f12) = id_f11;
3949
3950
4bf1cec7 3951 finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
b2b40051 3952 id_f12, NULL_TREE);
4bf1cec7 3953 TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
b2b40051
MJ
3954 }
3955
4bf1cec7 3956 for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
b2b40051
MJ
3957 chain != NULL_TREE; chain = TREE_CHAIN (chain))
3958 if (strcmp (field_name, IDENTIFIER_POINTER (DECL_NAME (chain))) == 0)
3959 return int_byte_position (chain);
3960
3961 gcc_unreachable ();
3962}
3963
3964/* Return an HSA register that will contain number of threads for
3965 a future dispatched kernel. Instructions are added to HBB. */
3966
3967static hsa_op_reg *
3968gen_num_threads_for_dispatch (hsa_bb *hbb)
3969{
3970 /* Step 1) Assign to number of threads:
3971 MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads). */
3972 hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
3973 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3974
3975 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
3976 threads, addr));
3977
3978 hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
3979 BRIG_TYPE_U32);
3980 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3981 hsa_insn_cmp * cmp
3982 = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
3983 hbb->append_insn (cmp);
3984
3985 BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
3986 hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
3987
3988 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
3989 threads, limit));
3990
3991 /* Step 2) If the number is equal to zero,
3992 return shadow->omp_num_threads. */
3993 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
3994
3995 hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
3996 addr
3997 = new hsa_op_address (shadow_reg_ptr,
3998 get_hsa_kernel_dispatch_offset ("omp_num_threads"));
3999 hsa_insn_basic *basic
4000 = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
4001 shadow_thread_count, addr);
4002 hbb->append_insn (basic);
4003
4004 hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
4005 r = new hsa_op_reg (BRIG_TYPE_B1);
4006 hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
4007 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
4008 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
4009 shadow_thread_count, tmp));
4010
4011 hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
4012
4013 return as_a <hsa_op_reg *> (dest);
4014}
4015
4016
4017/* Emit instructions that assign number of teams to lhs of gimple STMT.
4018 Instructions are appended to basic block HBB. */
4019
4020static void
4021gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4022{
4023 if (gimple_call_lhs (stmt) == NULL_TREE)
4024 return;
4025
4026 hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4027
4028 tree lhs = gimple_call_lhs (stmt);
4029 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4030 hsa_op_immed *one = new hsa_op_immed (1, dest->m_type);
4031
4032 hsa_insn_basic *basic
4033 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, one);
4034
4035 hbb->append_insn (basic);
4036}
4037
4038/* Emit instructions that assign a team number to lhs of gimple STMT.
4039 Instructions are appended to basic block HBB. */
4040
4041static void
4042gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4043{
4044 if (gimple_call_lhs (stmt) == NULL_TREE)
4045 return;
4046
4047 hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4048
4049 tree lhs = gimple_call_lhs (stmt);
4050 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4051 hsa_op_immed *zero = new hsa_op_immed (0, dest->m_type);
4052
4053 hsa_insn_basic *basic
4054 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, zero);
4055
4056 hbb->append_insn (basic);
4057}
4058
4059/* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4060 Instructions are appended to basic block HBB. */
4061
4062static void
4063gen_get_level (gimple *stmt, hsa_bb *hbb)
4064{
4065 if (gimple_call_lhs (stmt) == NULL_TREE)
4066 return;
4067
4068 hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4069
4070 tree lhs = gimple_call_lhs (stmt);
4071 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4072
4073 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4074 if (shadow_reg_ptr == NULL)
4075 {
4076 HSA_SORRY_AT (gimple_location (stmt),
4077 "support for HSA does not implement omp_get_level called "
4078 "from a function not being inlined within a kernel");
4079 return;
4080 }
4081
4082 hsa_op_address *addr
4083 = new hsa_op_address (shadow_reg_ptr,
4084 get_hsa_kernel_dispatch_offset ("omp_level"));
4085
4086 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4087 (hsa_op_base *) NULL, addr);
4088 hbb->append_insn (mem);
4089 mem->set_output_in_type (dest, 0, hbb);
4090}
4091
4092/* Emit instruction that implement omp_get_max_threads of gimple STMT. */
4093
4094static void
4095gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4096{
4097 tree lhs = gimple_call_lhs (stmt);
4098 if (!lhs)
4099 return;
4100
4101 hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4102
4103 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4104 hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4105 ->get_in_type (dest->m_type, hbb);
4106 hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4107}
4108
4109/* Emit instructions that implement alloca builtin gimple STMT.
4110 Instructions are appended to basic block HBB. */
4111
4112static void
4113gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4114{
4115 tree lhs = gimple_call_lhs (call);
4116 if (lhs == NULL_TREE)
4117 return;
4118
4119 built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
4120
4121 gcc_checking_assert (fn == BUILT_IN_ALLOCA
4122 || fn == BUILT_IN_ALLOCA_WITH_ALIGN);
4123
4124 unsigned bit_alignment = 0;
4125
4126 if (fn == BUILT_IN_ALLOCA_WITH_ALIGN)
4127 {
4128 tree alignment_tree = gimple_call_arg (call, 1);
4129 if (TREE_CODE (alignment_tree) != INTEGER_CST)
4130 {
4131 HSA_SORRY_ATV (gimple_location (call),
4132 "support for HSA does not implement "
4133 "__builtin_alloca_with_align with a non-constant "
4134 "alignment: %E", alignment_tree);
4135 }
4136
4137 bit_alignment = tree_to_uhwi (alignment_tree);
4138 }
4139
4140 tree rhs1 = gimple_call_arg (call, 0);
4141 hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4142 ->get_in_type (BRIG_TYPE_U32, hbb);
4143 hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4144
4145 hsa_op_reg *tmp
4146 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4147 hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4148 hbb->append_insn (a);
4149
4150 hsa_insn_seg *seg
4151 = new hsa_insn_seg (BRIG_OPCODE_STOF,
4152 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4153 tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4154 hbb->append_insn (seg);
4155}
4156
4157/* Emit instructions that implement clrsb builtin STMT:
4158 Returns the number of leading redundant sign bits in x, i.e. the number
4159 of bits following the most significant bit that are identical to it.
4160 There are no special cases for 0 or other values.
4161 Instructions are appended to basic block HBB. */
4162
4163static void
4164gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4165{
4166 tree lhs = gimple_call_lhs (call);
4167 if (lhs == NULL_TREE)
4168 return;
4169
4170 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4171 tree rhs1 = gimple_call_arg (call, 0);
4172 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4173 BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4174 unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
f91d04e7
ML
4175
4176 /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers. */
4177 gcc_checking_assert (bitsize == 32 || bitsize == 64);
b2b40051
MJ
4178
4179 /* Set true to MOST_SIG if the most significant bit is set to one. */
4180 hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4181 hsa_uint_for_bitsize (bitsize));
4182
4183 hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4184 gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4185
4186 hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4187 hsa_insn_cmp *cmp
4188 = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4189 and_reg, c);
4190 hbb->append_insn (cmp);
4191
4192 /* If the most significant bit is one, negate the input. Otherwise
4193 shift the input value to left by one bit. */
4194 hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4195 gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4196
4197 hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4198 gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4199 new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4200
4201 /* Assign the value that can be used for FIRSTBIT instruction according
4202 to the most significant bit. */
4203 hsa_op_reg *tmp = new hsa_op_reg (bittype);
4204 hsa_insn_basic *cmov
4205 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4206 arg_neg, shifted_arg);
4207 hbb->append_insn (cmov);
4208
4209 hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4210 gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4211 tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4212 hbb), hbb);
4213
4214 /* Set flag if the input value is equal to zero. */
4215 hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4216 cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4217 new hsa_op_immed (0, arg->m_type));
4218 hbb->append_insn (cmp);
4219
f91d04e7
ML
4220 /* Return the number of leading bits,
4221 or (bitsize - 1) if the input value is zero. */
b2b40051 4222 cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
f91d04e7 4223 new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
b2b40051
MJ
4224 leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4225 hbb->append_insn (cmov);
4226 cmov->set_output_in_type (dest, 0, hbb);
4227}
4228
4229/* Emit instructions that implement ffs builtin STMT:
4230 Returns one plus the index of the least significant 1-bit of x,
4231 or if x is zero, returns zero.
4232 Instructions are appended to basic block HBB. */
4233
4234static void
4235gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4236{
4237 tree lhs = gimple_call_lhs (call);
4238 if (lhs == NULL_TREE)
4239 return;
4240
4241 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4242
4243 tree rhs1 = gimple_call_arg (call, 0);
4244 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4245
4246 hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4247 hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4248 tmp->m_type, arg->m_type,
4249 tmp, arg);
4250 hbb->append_insn (insn);
4251
4252 hsa_insn_basic *addition
4253 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4254 new hsa_op_immed (1, tmp->m_type));
4255 hbb->append_insn (addition);
4256 addition->set_output_in_type (dest, 0, hbb);
4257}
4258
4259static void
4260gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4261{
4262 gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4263
4264 if (hsa_type_bit_size (arg->m_type) < 32)
4265 arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4266
4267 if (!hsa_btype_p (arg->m_type))
4268 arg = arg->get_in_type (hsa_bittype_for_type (arg->m_type), hbb);
4269
4270 hsa_insn_srctype *popcount
4271 = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4272 arg->m_type, NULL, arg);
4273 hbb->append_insn (popcount);
4274 popcount->set_output_in_type (dest, 0, hbb);
4275}
4276
4277/* Emit instructions that implement parity builtin STMT:
4278 Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4279 Instructions are appended to basic block HBB. */
4280
4281static void
4282gen_hsa_parity (gcall *call, hsa_bb *hbb)
4283{
4284 tree lhs = gimple_call_lhs (call);
4285 if (lhs == NULL_TREE)
4286 return;
4287
4288 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4289 tree rhs1 = gimple_call_arg (call, 0);
4290 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4291
4292 hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4293 gen_hsa_popcount_to_dest (popcount, arg, hbb);
4294
4295 hsa_insn_basic *insn
4296 = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4297 new hsa_op_immed (2, popcount->m_type));
4298 hbb->append_insn (insn);
4299 insn->set_output_in_type (dest, 0, hbb);
4300}
4301
4302/* Emit instructions that implement popcount builtin STMT.
4303 Instructions are appended to basic block HBB. */
4304
4305static void
4306gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4307{
4308 tree lhs = gimple_call_lhs (call);
4309 if (lhs == NULL_TREE)
4310 return;
4311
4312 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4313 tree rhs1 = gimple_call_arg (call, 0);
4314 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4315
4316 gen_hsa_popcount_to_dest (dest, arg, hbb);
4317}
4318
4319/* Set VALUE to a shadow kernel debug argument and append a new instruction
4320 to HBB basic block. */
4321
4322static void
4323set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4324{
4325 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4326 if (shadow_reg_ptr == NULL)
4327 return;
4328
4329 hsa_op_address *addr
4330 = new hsa_op_address (shadow_reg_ptr,
4331 get_hsa_kernel_dispatch_offset ("debug"));
4332 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4333 addr);
4334 hbb->append_insn (mem);
4335}
4336
4337void
4338omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4339{
4340 if (m_sorry)
4341 {
4342 if (m_warning_message)
4343 HSA_SORRY_AT (gimple_location (stmt), m_warning_message)
4344 else
4345 HSA_SORRY_ATV (gimple_location (stmt),
4346 "Support for HSA does not implement calls to %s\n",
4347 m_name)
4348 }
4349 else if (m_warning_message != NULL)
4350 warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4351
4352 if (m_return_value != NULL)
4353 {
4354 tree lhs = gimple_call_lhs (stmt);
4355 if (!lhs)
4356 return;
4357
4358 hbb->append_insn (new hsa_insn_comment (m_name));
4359
4360 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4361 hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4362 hsa_build_append_simple_mov (dest, op, hbb);
4363 }
4364}
4365
4366/* If STMT is a call of a known library function, generate code to perform
4367 it and return true. */
4368
4369static bool
4370gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4371{
4372 bool handled = false;
4373 const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4374
4375 char *copy = NULL;
4376 size_t len = strlen (name);
4377 if (len > 0 && name[len - 1] == '_')
4378 {
4379 copy = XNEWVEC (char, len + 1);
4380 strcpy (copy, name);
4381 copy[len - 1] = '\0';
4382 name = copy;
4383 }
4384
4385 /* Handle omp_* routines. */
4386 if (strstr (name, "omp_") == name)
4387 {
4388 hsa_init_simple_builtins ();
4389 omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4390 if (builtin)
4391 {
4392 builtin->generate (stmt, hbb);
4393 return true;
4394 }
4395
4396 handled = true;
4397 if (strcmp (name, "omp_set_num_threads") == 0)
4398 gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4399 else if (strcmp (name, "omp_get_thread_num") == 0)
4400 {
4401 hbb->append_insn (new hsa_insn_comment (name));
4402 query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
4403 }
4404 else if (strcmp (name, "omp_get_num_threads") == 0)
4405 {
4406 hbb->append_insn (new hsa_insn_comment (name));
4407 query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
4408 }
4409 else if (strcmp (name, "omp_get_num_teams") == 0)
4410 gen_get_num_teams (stmt, hbb);
4411 else if (strcmp (name, "omp_get_team_num") == 0)
4412 gen_get_team_num (stmt, hbb);
4413 else if (strcmp (name, "omp_get_level") == 0)
4414 gen_get_level (stmt, hbb);
4415 else if (strcmp (name, "omp_get_active_level") == 0)
4416 gen_get_level (stmt, hbb);
4417 else if (strcmp (name, "omp_in_parallel") == 0)
4418 gen_get_level (stmt, hbb);
4419 else if (strcmp (name, "omp_get_max_threads") == 0)
4420 gen_get_max_threads (stmt, hbb);
4421 else
4422 handled = false;
4423
4424 if (handled)
4425 {
4426 if (copy)
4427 free (copy);
4428 return true;
4429 }
4430 }
4431
4432 if (strcmp (name, "__hsa_set_debug_value") == 0)
4433 {
4434 handled = true;
4435 if (hsa_cfun->has_shadow_reg_p ())
4436 {
4437 tree rhs1 = gimple_call_arg (stmt, 0);
4438 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4439
4440 src = src->get_in_type (BRIG_TYPE_U64, hbb);
4441 set_debug_value (hbb, src);
4442 }
4443 }
4444
4445 if (copy)
4446 free (copy);
4447 return handled;
4448}
4449
4450/* Helper functions to create a single unary HSA operations out of calls to
4451 builtins. OPCODE is the HSA operation to be generated. STMT is a gimple
4452 call to a builtin. HBB is the HSA BB to which the instruction should be
4453 added. Note that nothing will be created if STMT does not have a LHS. */
4454
4455static void
4456gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4457{
4458 tree lhs = gimple_call_lhs (stmt);
4459 if (!lhs)
4460 return;
4461 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4462 hsa_op_with_type *op
4463 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4464 gen_hsa_unary_operation (opcode, dest, op, hbb);
4465}
4466
4467/* Helper functions to create a call to standard library if LHS of the
4468 STMT is used. HBB is the HSA BB to which the instruction should be
4469 added. */
4470
4471static void
4472gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4473{
4474 tree lhs = gimple_call_lhs (stmt);
4475 if (!lhs)
4476 return;
4477
4478 if (gimple_call_internal_p (stmt))
4479 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4480 else
4481 gen_hsa_insns_for_direct_call (stmt, hbb);
4482}
4483
4484/* Helper functions to create a single unary HSA operations out of calls to
4485 builtins (if unsafe math optimizations are enable). Otherwise, create
4486 a call to standard library function.
4487 OPCODE is the HSA operation to be generated. STMT is a gimple
4488 call to a builtin. HBB is the HSA BB to which the instruction should be
4489 added. Note that nothing will be created if STMT does not have a LHS. */
4490
4491static void
4492gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4493 hsa_bb *hbb)
4494{
4495 if (flag_unsafe_math_optimizations)
4496 gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4497 else
4498 gen_hsa_unaryop_builtin_call (stmt, hbb);
4499}
4500
4501/* Generate HSA address corresponding to a value VAL (as opposed to a memory
4502 reference tree), for example an SSA_NAME or an ADDR_EXPR. HBB is the HSA BB
4503 to which the instruction should be added. */
4504
4505static hsa_op_address *
4506get_address_from_value (tree val, hsa_bb *hbb)
4507{
4508 switch (TREE_CODE (val))
4509 {
4510 case SSA_NAME:
4511 {
4512 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4513 hsa_op_base *reg
4514 = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4515 return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4516 }
4517 case ADDR_EXPR:
4518 return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4519
4520 case INTEGER_CST:
4521 if (tree_fits_shwi_p (val))
4522 return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
191816a3 4523 /* fall-through */
b2b40051
MJ
4524
4525 default:
4526 HSA_SORRY_ATV (EXPR_LOCATION (val),
4527 "support for HSA does not implement memory access to %E",
4528 val);
4529 return new hsa_op_address (NULL, NULL, 0);
4530 }
4531}
4532
65e21467
ML
4533/* Expand assignment of a result of a string BUILTIN to DST.
4534 Size of the operation is N bytes, where instructions
4535 will be append to HBB. */
4536
4537static void
4538expand_lhs_of_string_op (gimple *stmt,
4539 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4540 enum built_in_function builtin)
4541{
4542 /* If LHS is expected, we need to emit a PHI instruction. */
4543 tree lhs = gimple_call_lhs (stmt);
4544 if (!lhs)
4545 return;
4546
4547 hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4548
4549 hsa_op_with_type *dst_reg
4550 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4551 hsa_op_with_type *tmp;
4552
4553 switch (builtin)
4554 {
4555 case BUILT_IN_MEMPCPY:
4556 {
4557 tmp = new hsa_op_reg (dst_reg->m_type);
4558 hsa_insn_basic *add
4559 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4560 tmp, dst_reg,
4561 new hsa_op_immed (n, dst_reg->m_type));
4562 hbb->append_insn (add);
4563 break;
4564 }
4565 case BUILT_IN_MEMCPY:
4566 case BUILT_IN_MEMSET:
4567 tmp = dst_reg;
4568 break;
4569 default:
4570 gcc_unreachable ();
4571 }
4572
4573 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4574 lhs_reg, tmp));
4575}
4576
4577#define HSA_MEMORY_BUILTINS_LIMIT 128
4578
4579/* Expand a string builtin (from a gimple STMT) in a way that
4580 according to MISALIGNED_FLAG we process either direct emission
4581 (a bunch of memory load and store instructions), or we emit a function call
4582 of a library function (for instance 'memcpy'). Actually, a basic block
4583 for direct emission is just prepared, where caller is responsible
4584 for emission of corresponding instructions.
4585 All instruction are appended to HBB. */
4586
4587hsa_bb *
4588expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4589 hsa_op_reg *misaligned_flag)
4590{
4591 edge e = split_block (hbb->m_bb, stmt);
4592 basic_block condition_bb = e->src;
4593 hbb->append_insn (new hsa_insn_br (misaligned_flag));
4594
4595 /* Prepare the control flow. */
4596 edge condition_edge = EDGE_SUCC (condition_bb, 0);
4597 basic_block call_bb = split_edge (condition_edge);
4598
4599 basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4600 basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4601 basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4602
4603 condition_edge->flags &= ~EDGE_FALLTHRU;
4604 condition_edge->flags |= EDGE_TRUE_VALUE;
4605 make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4606
4607 redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4608
4609 hsa_cfun->m_modified_cfg = true;
4610
4611 hsa_init_new_bb (expanded_bb);
4612
4613 /* Slow path: function call. */
4614 gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4615
4616 return hsa_bb_for_bb (expanded_bb);
4617}
4618
4619/* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4620 a gimple STMT and store all necessary instruction to HBB basic block. */
4621
4622static void
4623expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4624{
4625 tree byte_size = gimple_call_arg (stmt, 2);
4626
4627 if (!tree_fits_uhwi_p (byte_size))
4628 {
4629 gen_hsa_insns_for_direct_call (stmt, hbb);
4630 return;
4631 }
4632
4633 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4634
4635 if (n > HSA_MEMORY_BUILTINS_LIMIT)
4636 {
4637 gen_hsa_insns_for_direct_call (stmt, hbb);
4638 return;
4639 }
4640
4641 tree dst = gimple_call_arg (stmt, 0);
4642 tree src = gimple_call_arg (stmt, 1);
4643
4644 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4645 hsa_op_address *src_addr = get_address_from_value (src, hbb);
4646
4647 /* As gen_hsa_memory_copy relies on memory alignment
4648 greater or equal to 8 bytes, we need to verify the alignment. */
4649 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4650 hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4651 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4652
4653 convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4654 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4655
4656 /* Process BIT OR for source and destination addresses. */
4657 hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4658 gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4659 dst_addr_reg, hbb);
4660
4661 /* Process BIT AND with 0x7 to identify the desired alignment
4662 of 8 bytes. */
4663 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4664
4665 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4666 new hsa_op_immed (7, addrtype), hbb);
4667
4668 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4669 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4670 misaligned, masked,
4671 new hsa_op_immed (0, masked->m_type)));
4672
4673 hsa_bb *native_impl_bb
4674 = expand_string_operation_builtin (stmt, hbb, misaligned);
4675
4676 gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4677 hsa_bb *merge_bb
4678 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4679 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4680}
4681
4682
4683/* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4684 a gimple STMT and store all necessary instruction to HBB basic block.
4685 The operation set N bytes with a CONSTANT value. */
4686
4687static void
4688expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4689 unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4690 enum built_in_function builtin)
4691{
4692 tree dst = gimple_call_arg (stmt, 0);
4693 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4694
4695 /* As gen_hsa_memory_set relies on memory alignment
4696 greater or equal to 8 bytes, we need to verify the alignment. */
4697 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4698 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4699 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4700
4701 /* Process BIT AND with 0x7 to identify the desired alignment
4702 of 8 bytes. */
4703 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4704
4705 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4706 new hsa_op_immed (7, addrtype), hbb);
4707
4708 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4709 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4710 misaligned, masked,
4711 new hsa_op_immed (0, masked->m_type)));
4712
4713 hsa_bb *native_impl_bb
4714 = expand_string_operation_builtin (stmt, hbb, misaligned);
4715
4716 gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4717 hsa_bb *merge_bb
4718 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4719 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4720}
4721
b2b40051
MJ
4722/* Return string for MEMMODEL. */
4723
4724static const char *
4725get_memory_order_name (unsigned memmodel)
4726{
fe621379 4727 switch (memmodel & MEMMODEL_BASE_MASK)
b2b40051 4728 {
b1b6d906 4729 case MEMMODEL_RELAXED:
fe621379 4730 return "relaxed";
b1b6d906 4731 case MEMMODEL_CONSUME:
fe621379 4732 return "consume";
b1b6d906 4733 case MEMMODEL_ACQUIRE:
fe621379 4734 return "acquire";
b1b6d906 4735 case MEMMODEL_RELEASE:
fe621379 4736 return "release";
b1b6d906 4737 case MEMMODEL_ACQ_REL:
fe621379 4738 return "acq_rel";
b1b6d906 4739 case MEMMODEL_SEQ_CST:
fe621379 4740 return "seq_cst";
b2b40051
MJ
4741 default:
4742 return NULL;
4743 }
4744}
4745
4746/* Return memory order according to predefined __atomic memory model
4747 constants. LOCATION is provided to locate the problematic statement. */
4748
4749static BrigMemoryOrder
4750get_memory_order (unsigned memmodel, location_t location)
4751{
fe621379 4752 switch (memmodel & MEMMODEL_BASE_MASK)
b2b40051 4753 {
b1b6d906 4754 case MEMMODEL_RELAXED:
b2b40051 4755 return BRIG_MEMORY_ORDER_RELAXED;
fe621379
MJ
4756 case MEMMODEL_CONSUME:
4757 /* HSA does not have an equivalent, but we can use the slightly stronger
4758 ACQUIRE. */
b1b6d906 4759 case MEMMODEL_ACQUIRE:
b2b40051 4760 return BRIG_MEMORY_ORDER_SC_ACQUIRE;
b1b6d906 4761 case MEMMODEL_RELEASE:
b2b40051 4762 return BRIG_MEMORY_ORDER_SC_RELEASE;
b1b6d906 4763 case MEMMODEL_ACQ_REL:
fe621379
MJ
4764 case MEMMODEL_SEQ_CST:
4765 /* Callers implementing a simple load or store need to remove the release
4766 or acquire part respectively. */
b2b40051
MJ
4767 return BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4768 default:
fe621379
MJ
4769 {
4770 const char *mmname = get_memory_order_name (memmodel);
4771 HSA_SORRY_ATV (location,
4772 "support for HSA does not implement the specified "
4773 " memory model%s %s",
4774 mmname ? ": " : "", mmname ? mmname : "");
4775 return BRIG_MEMORY_ORDER_NONE;
4776 }
b2b40051
MJ
4777 }
4778}
4779
4780/* Helper function to create an HSA atomic binary operation instruction out of
4781 calls to atomic builtins. RET_ORIG is true if the built-in is the variant
4782 that return s the value before applying operation, and false if it should
4783 return the value after applying the operation (if it returns value at all).
4784 ACODE is the atomic operation code, STMT is a gimple call to a builtin. HBB
4785 is the HSA BB to which the instruction should be added. */
4786
4787static void
4788gen_hsa_ternary_atomic_for_builtin (bool ret_orig,
4789 enum BrigAtomicOperation acode,
4790 gimple *stmt,
4791 hsa_bb *hbb)
4792{
4793 tree lhs = gimple_call_lhs (stmt);
4794
4795 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
4796 BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
4797 BrigType16_t mtype = mem_type_for_type (hsa_type);
4798 tree model = gimple_call_arg (stmt, 2);
4799
4800 if (!tree_fits_uhwi_p (model))
4801 {
4802 HSA_SORRY_ATV (gimple_location (stmt),
4803 "support for HSA does not implement memory model %E",
4804 model);
4805 return;
4806 }
4807
4808 unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
4809
4810 BrigMemoryOrder memorder = get_memory_order (mmodel, gimple_location (stmt));
4811
4812 /* Certain atomic insns must have Bx memory types. */
4813 switch (acode)
4814 {
4815 case BRIG_ATOMIC_LD:
4816 case BRIG_ATOMIC_ST:
4817 case BRIG_ATOMIC_AND:
4818 case BRIG_ATOMIC_OR:
4819 case BRIG_ATOMIC_XOR:
4820 case BRIG_ATOMIC_EXCH:
4821 mtype = hsa_bittype_for_type (mtype);
4822 break;
4823 default:
4824 break;
4825 }
4826
4827 hsa_op_reg *dest;
4828 int nops, opcode;
4829 if (lhs)
4830 {
4831 if (ret_orig)
4832 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4833 else
4834 dest = new hsa_op_reg (hsa_type);
4835 opcode = BRIG_OPCODE_ATOMIC;
4836 nops = 3;
4837 }
4838 else
4839 {
4840 dest = NULL;
4841 opcode = BRIG_OPCODE_ATOMICNORET;
4842 nops = 2;
4843 }
4844
fe621379 4845 if (acode == BRIG_ATOMIC_ST)
b2b40051 4846 {
fe621379
MJ
4847 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
4848 memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4849
4850 if (memorder != BRIG_MEMORY_ORDER_RELAXED
4851 && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
4852 && memorder != BRIG_MEMORY_ORDER_NONE)
4853 {
4854 HSA_SORRY_ATV (gimple_location (stmt),
4855 "support for HSA does not implement memory model for "
4856 "ATOMIC_ST: %s", get_memory_order_name (mmodel));
4857 return;
4858 }
b2b40051
MJ
4859 }
4860
4861 hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype,
4862 memorder);
4863
4864 hsa_op_address *addr;
4865 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
02108bb5
MJ
4866 if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
4867 {
4868 HSA_SORRY_AT (gimple_location (stmt),
4869 "HSA does not implement atomic operations in private "
4870 "segment");
4871 return;
4872 }
b2b40051
MJ
4873 hsa_op_base *op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1),
4874 hbb);
4875
4876 if (lhs)
4877 {
4878 atominsn->set_op (0, dest);
4879 atominsn->set_op (1, addr);
4880 atominsn->set_op (2, op);
4881 }
4882 else
4883 {
4884 atominsn->set_op (0, addr);
4885 atominsn->set_op (1, op);
4886 }
4887
4888 hbb->append_insn (atominsn);
4889
4890 /* HSA does not natively support the variants that return the modified value,
4891 so re-do the operation again non-atomically if that is what was
4892 requested. */
4893 if (lhs && !ret_orig)
4894 {
4895 int arith;
4896 switch (acode)
4897 {
4898 case BRIG_ATOMIC_ADD:
4899 arith = BRIG_OPCODE_ADD;
4900 break;
4901 case BRIG_ATOMIC_AND:
4902 arith = BRIG_OPCODE_AND;
4903 break;
4904 case BRIG_ATOMIC_OR:
4905 arith = BRIG_OPCODE_OR;
4906 break;
4907 case BRIG_ATOMIC_SUB:
4908 arith = BRIG_OPCODE_SUB;
4909 break;
4910 case BRIG_ATOMIC_XOR:
4911 arith = BRIG_OPCODE_XOR;
4912 break;
4913 default:
4914 gcc_unreachable ();
4915 }
4916 hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4917 gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
4918 }
4919}
4920
4921/* Generate HSA instructions for an internal fn.
4922 Instructions will be appended to HBB, which also needs to be the
4923 corresponding structure to the basic_block of STMT. */
4924
4925static void
4926gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
4927{
4928 gcc_checking_assert (gimple_call_internal_fn (stmt));
4929 internal_fn fn = gimple_call_internal_fn (stmt);
4930
4931 bool is_float_type_p = false;
4932 if (gimple_call_lhs (stmt) != NULL
4933 && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
4934 is_float_type_p = true;
4935
4936 switch (fn)
4937 {
4938 case IFN_CEIL:
4939 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
4940 break;
4941
4942 case IFN_FLOOR:
4943 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
4944 break;
4945
4946 case IFN_RINT:
4947 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
4948 break;
4949
4950 case IFN_SQRT:
4951 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
4952 break;
4953
4954 case IFN_TRUNC:
4955 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
4956 break;
4957
4958 case IFN_COS:
4959 {
4960 if (is_float_type_p)
4961 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
4962 else
4963 gen_hsa_unaryop_builtin_call (stmt, hbb);
4964
4965 break;
4966 }
4967 case IFN_EXP2:
4968 {
4969 if (is_float_type_p)
4970 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
4971 else
4972 gen_hsa_unaryop_builtin_call (stmt, hbb);
4973
4974 break;
4975 }
4976
4977 case IFN_LOG2:
4978 {
4979 if (is_float_type_p)
4980 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
4981 else
4982 gen_hsa_unaryop_builtin_call (stmt, hbb);
4983
4984 break;
4985 }
4986
4987 case IFN_SIN:
4988 {
4989 if (is_float_type_p)
4990 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
4991 else
4992 gen_hsa_unaryop_builtin_call (stmt, hbb);
4993 break;
4994 }
4995
4996 case IFN_CLRSB:
4997 gen_hsa_clrsb (stmt, hbb);
4998 break;
4999
5000 case IFN_CLZ:
5001 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5002 break;
5003
5004 case IFN_CTZ:
5005 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5006 break;
5007
5008 case IFN_FFS:
5009 gen_hsa_ffs (stmt, hbb);
5010 break;
5011
5012 case IFN_PARITY:
5013 gen_hsa_parity (stmt, hbb);
5014 break;
5015
5016 case IFN_POPCOUNT:
5017 gen_hsa_popcount (stmt, hbb);
5018 break;
5019
5020 case IFN_ACOS:
5021 case IFN_ASIN:
5022 case IFN_ATAN:
5023 case IFN_EXP:
5024 case IFN_EXP10:
5025 case IFN_EXPM1:
5026 case IFN_LOG:
5027 case IFN_LOG10:
5028 case IFN_LOG1P:
5029 case IFN_LOGB:
5030 case IFN_SIGNIFICAND:
5031 case IFN_TAN:
5032 case IFN_NEARBYINT:
5033 case IFN_ROUND:
5034 case IFN_ATAN2:
5035 case IFN_COPYSIGN:
5036 case IFN_FMOD:
5037 case IFN_POW:
5038 case IFN_REMAINDER:
5039 case IFN_SCALB:
5040 case IFN_FMIN:
5041 case IFN_FMAX:
5042 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
f0bc3323 5043 break;
b2b40051
MJ
5044
5045 default:
5046 HSA_SORRY_ATV (gimple_location (stmt),
5047 "support for HSA does not implement internal function: %s",
5048 internal_fn_name (fn));
5049 break;
5050 }
5051}
5052
b2b40051
MJ
5053/* Generate HSA instructions for the given call statement STMT. Instructions
5054 will be appended to HBB. */
5055
5056static void
5057gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5058{
5059 gcall *call = as_a <gcall *> (stmt);
5060 tree lhs = gimple_call_lhs (stmt);
5061 hsa_op_reg *dest;
5062
5063 if (gimple_call_internal_p (stmt))
5064 {
5065 gen_hsa_insn_for_internal_fn_call (call, hbb);
5066 return;
5067 }
5068
5069 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5070 {
5071 tree function_decl = gimple_call_fndecl (stmt);
5072 if (function_decl == NULL_TREE)
5073 {
5074 HSA_SORRY_AT (gimple_location (stmt),
5075 "support for HSA does not implement indirect calls");
5076 return;
5077 }
5078
5079 if (hsa_callable_function_p (function_decl))
5080 gen_hsa_insns_for_direct_call (stmt, hbb);
5081 else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5082 HSA_SORRY_AT (gimple_location (stmt),
5083 "HSA supports only calls of functions marked with pragma "
5084 "omp declare target");
5085 return;
5086 }
5087
5088 tree fndecl = gimple_call_fndecl (stmt);
5089 enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5090 switch (builtin)
5091 {
5092 case BUILT_IN_FABS:
5093 case BUILT_IN_FABSF:
5094 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5095 break;
5096
5097 case BUILT_IN_CEIL:
5098 case BUILT_IN_CEILF:
5099 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5100 break;
5101
5102 case BUILT_IN_FLOOR:
5103 case BUILT_IN_FLOORF:
5104 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5105 break;
5106
5107 case BUILT_IN_RINT:
5108 case BUILT_IN_RINTF:
5109 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5110 break;
5111
5112 case BUILT_IN_SQRT:
5113 case BUILT_IN_SQRTF:
5114 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5115 break;
5116
5117 case BUILT_IN_TRUNC:
5118 case BUILT_IN_TRUNCF:
5119 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5120 break;
5121
5122 case BUILT_IN_COS:
5123 case BUILT_IN_SIN:
5124 case BUILT_IN_EXP2:
5125 case BUILT_IN_LOG2:
5126 /* HSAIL does not provide an instruction for double argument type. */
5127 gen_hsa_unaryop_builtin_call (stmt, hbb);
5128 break;
5129
5130 case BUILT_IN_COSF:
5131 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5132 break;
5133
5134 case BUILT_IN_EXP2F:
5135 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5136 break;
5137
5138 case BUILT_IN_LOG2F:
5139 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5140 break;
5141
5142 case BUILT_IN_SINF:
5143 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5144 break;
5145
5146 case BUILT_IN_CLRSB:
5147 case BUILT_IN_CLRSBL:
5148 case BUILT_IN_CLRSBLL:
5149 gen_hsa_clrsb (call, hbb);
5150 break;
5151
5152 case BUILT_IN_CLZ:
5153 case BUILT_IN_CLZL:
5154 case BUILT_IN_CLZLL:
5155 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5156 break;
5157
5158 case BUILT_IN_CTZ:
5159 case BUILT_IN_CTZL:
5160 case BUILT_IN_CTZLL:
5161 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5162 break;
5163
5164 case BUILT_IN_FFS:
5165 case BUILT_IN_FFSL:
5166 case BUILT_IN_FFSLL:
5167 gen_hsa_ffs (call, hbb);
5168 break;
5169
5170 case BUILT_IN_PARITY:
5171 case BUILT_IN_PARITYL:
5172 case BUILT_IN_PARITYLL:
5173 gen_hsa_parity (call, hbb);
5174 break;
5175
5176 case BUILT_IN_POPCOUNT:
5177 case BUILT_IN_POPCOUNTL:
5178 case BUILT_IN_POPCOUNTLL:
5179 gen_hsa_popcount (call, hbb);
5180 break;
5181
5182 case BUILT_IN_ATOMIC_LOAD_1:
5183 case BUILT_IN_ATOMIC_LOAD_2:
5184 case BUILT_IN_ATOMIC_LOAD_4:
5185 case BUILT_IN_ATOMIC_LOAD_8:
5186 case BUILT_IN_ATOMIC_LOAD_16:
5187 {
5188 BrigType16_t mtype;
5189 hsa_op_address *addr;
5190 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5191 tree model = gimple_call_arg (stmt, 1);
5192 if (!tree_fits_uhwi_p (model))
5193 {
5194 HSA_SORRY_ATV (gimple_location (stmt),
5195 "support for HSA does not implement "
5196 "memory model: %E",
5197 model);
5198 return;
5199 }
5200
5201 unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model);
5202 BrigMemoryOrder memorder = get_memory_order (mmodel,
5203 gimple_location (stmt));
5204
fe621379
MJ
5205 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5206 memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5207
b2b40051 5208 if (memorder != BRIG_MEMORY_ORDER_RELAXED
fe621379
MJ
5209 && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5210 && memorder != BRIG_MEMORY_ORDER_NONE)
b2b40051
MJ
5211 {
5212 HSA_SORRY_ATV (gimple_location (stmt),
5213 "support for HSA does not implement "
5214 "memory model for ATOMIC_LD: %s",
5215 get_memory_order_name (mmodel));
5216 return;
5217 }
5218
5219 if (lhs)
5220 {
5221 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5222 false);
5223 mtype = mem_type_for_type (t);
5224 mtype = hsa_bittype_for_type (mtype);
5225 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5226 }
5227 else
5228 {
5229 mtype = BRIG_TYPE_B64;
5230 dest = new hsa_op_reg (mtype);
5231 }
5232
5233 hsa_insn_atomic *atominsn
5234 = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD, mtype,
5235 memorder, dest, addr);
5236
5237 hbb->append_insn (atominsn);
5238 break;
5239 }
5240
5241 case BUILT_IN_ATOMIC_EXCHANGE_1:
5242 case BUILT_IN_ATOMIC_EXCHANGE_2:
5243 case BUILT_IN_ATOMIC_EXCHANGE_4:
5244 case BUILT_IN_ATOMIC_EXCHANGE_8:
5245 case BUILT_IN_ATOMIC_EXCHANGE_16:
5246 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb);
5247 break;
5248
5249 case BUILT_IN_ATOMIC_FETCH_ADD_1:
5250 case BUILT_IN_ATOMIC_FETCH_ADD_2:
5251 case BUILT_IN_ATOMIC_FETCH_ADD_4:
5252 case BUILT_IN_ATOMIC_FETCH_ADD_8:
5253 case BUILT_IN_ATOMIC_FETCH_ADD_16:
5254 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb);
5255 break;
5256
5257 case BUILT_IN_ATOMIC_FETCH_SUB_1:
5258 case BUILT_IN_ATOMIC_FETCH_SUB_2:
5259 case BUILT_IN_ATOMIC_FETCH_SUB_4:
5260 case BUILT_IN_ATOMIC_FETCH_SUB_8:
5261 case BUILT_IN_ATOMIC_FETCH_SUB_16:
5262 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb);
5263 break;
5264
5265 case BUILT_IN_ATOMIC_FETCH_AND_1:
5266 case BUILT_IN_ATOMIC_FETCH_AND_2:
5267 case BUILT_IN_ATOMIC_FETCH_AND_4:
5268 case BUILT_IN_ATOMIC_FETCH_AND_8:
5269 case BUILT_IN_ATOMIC_FETCH_AND_16:
5270 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb);
5271 break;
5272
5273 case BUILT_IN_ATOMIC_FETCH_XOR_1:
5274 case BUILT_IN_ATOMIC_FETCH_XOR_2:
5275 case BUILT_IN_ATOMIC_FETCH_XOR_4:
5276 case BUILT_IN_ATOMIC_FETCH_XOR_8:
5277 case BUILT_IN_ATOMIC_FETCH_XOR_16:
5278 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb);
5279 break;
5280
5281 case BUILT_IN_ATOMIC_FETCH_OR_1:
5282 case BUILT_IN_ATOMIC_FETCH_OR_2:
5283 case BUILT_IN_ATOMIC_FETCH_OR_4:
5284 case BUILT_IN_ATOMIC_FETCH_OR_8:
5285 case BUILT_IN_ATOMIC_FETCH_OR_16:
5286 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb);
5287 break;
5288
5289 case BUILT_IN_ATOMIC_STORE_1:
5290 case BUILT_IN_ATOMIC_STORE_2:
5291 case BUILT_IN_ATOMIC_STORE_4:
5292 case BUILT_IN_ATOMIC_STORE_8:
5293 case BUILT_IN_ATOMIC_STORE_16:
5294 /* Since there cannot be any LHS, the first parameter is meaningless. */
5295 gen_hsa_ternary_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb);
5296 break;
5297
5298 case BUILT_IN_ATOMIC_ADD_FETCH_1:
5299 case BUILT_IN_ATOMIC_ADD_FETCH_2:
5300 case BUILT_IN_ATOMIC_ADD_FETCH_4:
5301 case BUILT_IN_ATOMIC_ADD_FETCH_8:
5302 case BUILT_IN_ATOMIC_ADD_FETCH_16:
5303 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb);
5304 break;
5305
5306 case BUILT_IN_ATOMIC_SUB_FETCH_1:
5307 case BUILT_IN_ATOMIC_SUB_FETCH_2:
5308 case BUILT_IN_ATOMIC_SUB_FETCH_4:
5309 case BUILT_IN_ATOMIC_SUB_FETCH_8:
5310 case BUILT_IN_ATOMIC_SUB_FETCH_16:
5311 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb);
5312 break;
5313
5314 case BUILT_IN_ATOMIC_AND_FETCH_1:
5315 case BUILT_IN_ATOMIC_AND_FETCH_2:
5316 case BUILT_IN_ATOMIC_AND_FETCH_4:
5317 case BUILT_IN_ATOMIC_AND_FETCH_8:
5318 case BUILT_IN_ATOMIC_AND_FETCH_16:
5319 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb);
5320 break;
5321
5322 case BUILT_IN_ATOMIC_XOR_FETCH_1:
5323 case BUILT_IN_ATOMIC_XOR_FETCH_2:
5324 case BUILT_IN_ATOMIC_XOR_FETCH_4:
5325 case BUILT_IN_ATOMIC_XOR_FETCH_8:
5326 case BUILT_IN_ATOMIC_XOR_FETCH_16:
5327 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb);
5328 break;
5329
5330 case BUILT_IN_ATOMIC_OR_FETCH_1:
5331 case BUILT_IN_ATOMIC_OR_FETCH_2:
5332 case BUILT_IN_ATOMIC_OR_FETCH_4:
5333 case BUILT_IN_ATOMIC_OR_FETCH_8:
5334 case BUILT_IN_ATOMIC_OR_FETCH_16:
5335 gen_hsa_ternary_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb);
5336 break;
5337
5338 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5339 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5340 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5341 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5342 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5343 {
5344 /* TODO: Use the appropriate memory model for now. */
5345 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5346
5347 BrigType16_t atype
5348 = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5349
5350 hsa_insn_atomic *atominsn
5351 = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype,
5352 BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE);
5353 hsa_op_address *addr;
5354 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5355
5356 if (lhs != NULL)
5357 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5358 else
5359 dest = new hsa_op_reg (atype);
5360
5361 /* Should check what the memory scope is. */
5362 atominsn->m_memoryscope = BRIG_MEMORY_SCOPE_WORKGROUP;
5363 atominsn->set_op (0, dest);
5364 atominsn->set_op (1, addr);
5365
5366 hsa_op_with_type *op
5367 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5368 atominsn->set_op (2, op);
5369 op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5370 atominsn->set_op (3, op);
5371
5372 hbb->append_insn (atominsn);
5373 break;
5374 }
5375 case BUILT_IN_GOMP_PARALLEL:
5376 HSA_SORRY_AT (gimple_location (stmt),
5377 "support for HSA does not implement non-gridified "
5378 "OpenMP parallel constructs.");
5379 break;
5380 case BUILT_IN_OMP_GET_THREAD_NUM:
5381 {
5382 query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
5383 break;
5384 }
5385
5386 case BUILT_IN_OMP_GET_NUM_THREADS:
5387 {
5388 query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
5389 break;
5390 }
5391 case BUILT_IN_GOMP_TEAMS:
5392 {
5393 gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5394 break;
5395 }
5396 case BUILT_IN_OMP_GET_NUM_TEAMS:
5397 {
5398 gen_get_num_teams (stmt, hbb);
5399 break;
5400 }
5401 case BUILT_IN_OMP_GET_TEAM_NUM:
5402 {
5403 gen_get_team_num (stmt, hbb);
5404 break;
5405 }
5406 case BUILT_IN_MEMCPY:
5407 case BUILT_IN_MEMPCPY:
5408 {
65e21467 5409 expand_memory_copy (stmt, hbb, builtin);
b2b40051
MJ
5410 break;
5411 }
5412 case BUILT_IN_MEMSET:
5413 {
b2b40051
MJ
5414 tree c = gimple_call_arg (stmt, 1);
5415
5416 if (TREE_CODE (c) != INTEGER_CST)
5417 {
5418 gen_hsa_insns_for_direct_call (stmt, hbb);
5419 return;
5420 }
5421
5422 tree byte_size = gimple_call_arg (stmt, 2);
5423
5424 if (!tree_fits_uhwi_p (byte_size))
5425 {
5426 gen_hsa_insns_for_direct_call (stmt, hbb);
5427 return;
5428 }
5429
65e21467 5430 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
b2b40051
MJ
5431
5432 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5433 {
5434 gen_hsa_insns_for_direct_call (stmt, hbb);
5435 return;
5436 }
5437
b2b40051
MJ
5438 unsigned HOST_WIDE_INT constant
5439 = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5440
65e21467 5441 expand_memory_set (stmt, n, constant, hbb, builtin);
b2b40051
MJ
5442
5443 break;
5444 }
5445 case BUILT_IN_BZERO:
5446 {
b2b40051
MJ
5447 tree byte_size = gimple_call_arg (stmt, 1);
5448
5449 if (!tree_fits_uhwi_p (byte_size))
5450 {
5451 gen_hsa_insns_for_direct_call (stmt, hbb);
5452 return;
5453 }
5454
65e21467 5455 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
b2b40051
MJ
5456
5457 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5458 {
5459 gen_hsa_insns_for_direct_call (stmt, hbb);
5460 return;
5461 }
5462
65e21467 5463 expand_memory_set (stmt, n, 0, hbb, builtin);
b2b40051
MJ
5464
5465 break;
5466 }
5467 case BUILT_IN_ALLOCA:
5468 case BUILT_IN_ALLOCA_WITH_ALIGN:
5469 {
5470 gen_hsa_alloca (call, hbb);
5471 break;
5472 }
5473 default:
5474 {
5475 gen_hsa_insns_for_direct_call (stmt, hbb);
5476 return;
5477 }
5478 }
5479}
5480
5481/* Generate HSA instructions for a given gimple statement. Instructions will be
5482 appended to HBB. */
5483
5484static void
5485gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5486{
5487 switch (gimple_code (stmt))
5488 {
5489 case GIMPLE_ASSIGN:
5490 if (gimple_clobber_p (stmt))
5491 break;
5492
5493 if (gimple_assign_single_p (stmt))
5494 {
5495 tree lhs = gimple_assign_lhs (stmt);
5496 tree rhs = gimple_assign_rhs1 (stmt);
5497 gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5498 }
5499 else
5500 gen_hsa_insns_for_operation_assignment (stmt, hbb);
5501 break;
5502 case GIMPLE_RETURN:
5503 gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5504 break;
5505 case GIMPLE_COND:
5506 gen_hsa_insns_for_cond_stmt (stmt, hbb);
5507 break;
5508 case GIMPLE_CALL:
5509 gen_hsa_insns_for_call (stmt, hbb);
5510 break;
5511 case GIMPLE_DEBUG:
5512 /* ??? HSA supports some debug facilities. */
5513 break;
5514 case GIMPLE_LABEL:
5515 {
5516 tree label = gimple_label_label (as_a <glabel *> (stmt));
5517 if (FORCED_LABEL (label))
5518 HSA_SORRY_AT (gimple_location (stmt),
5519 "support for HSA does not implement gimple label with "
5520 "address taken");
5521
5522 break;
5523 }
5524 case GIMPLE_NOP:
5525 {
5526 hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5527 break;
5528 }
5529 case GIMPLE_SWITCH:
5530 {
5531 gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5532 break;
5533 }
5534 default:
5535 HSA_SORRY_ATV (gimple_location (stmt),
5536 "support for HSA does not implement gimple statement %s",
5537 gimple_code_name[(int) gimple_code (stmt)]);
5538 }
5539}
5540
5541/* Generate a HSA PHI from a gimple PHI. */
5542
5543static void
5544gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5545{
5546 hsa_insn_phi *hphi;
5547 unsigned count = gimple_phi_num_args (phi_stmt);
5548
5549 hsa_op_reg *dest
5550 = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5551 hphi = new hsa_insn_phi (count, dest);
5552 hphi->m_bb = hbb->m_bb;
5553
5554 tree lhs = gimple_phi_result (phi_stmt);
5555
5556 for (unsigned i = 0; i < count; i++)
5557 {
5558 tree op = gimple_phi_arg_def (phi_stmt, i);
5559
5560 if (TREE_CODE (op) == SSA_NAME)
5561 {
5562 hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5563 hphi->set_op (i, hreg);
5564 }
5565 else
5566 {
5567 gcc_assert (is_gimple_min_invariant (op));
5568 tree t = TREE_TYPE (op);
5569 if (!POINTER_TYPE_P (t)
5570 || (TREE_CODE (op) == STRING_CST
5571 && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5572 hphi->set_op (i, new hsa_op_immed (op));
5573 else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5574 && TREE_CODE (op) == INTEGER_CST)
5575 {
5576 /* Handle assignment of NULL value to a pointer type. */
5577 hphi->set_op (i, new hsa_op_immed (op));
5578 }
5579 else if (TREE_CODE (op) == ADDR_EXPR)
5580 {
5581 edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5582 hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5583 hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5584 hbb_src);
5585
de0fef0d
MJ
5586 hsa_op_reg *dest
5587 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
b2b40051
MJ
5588 hsa_insn_basic *insn
5589 = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5590 dest, addr);
5591 hbb_src->append_insn (insn);
5592
5593 hphi->set_op (i, dest);
5594 }
5595 else
5596 {
5597 HSA_SORRY_AT (gimple_location (phi_stmt),
5598 "support for HSA does not handle PHI nodes with "
5599 "constant address operands");
5600 return;
5601 }
5602 }
5603 }
5604
5605 hphi->m_prev = hbb->m_last_phi;
5606 hphi->m_next = NULL;
5607 if (hbb->m_last_phi)
5608 hbb->m_last_phi->m_next = hphi;
5609 hbb->m_last_phi = hphi;
5610 if (!hbb->m_first_phi)
5611 hbb->m_first_phi = hphi;
5612}
5613
5614/* Constructor of class containing HSA-specific information about a basic
5615 block. CFG_BB is the CFG BB this HSA BB is associated with. IDX is the new
5616 index of this BB (so that the constructor does not attempt to use
5617 hsa_cfun during its construction). */
5618
5619hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5620 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5621 m_last_phi (NULL), m_index (idx), m_liveout (BITMAP_ALLOC (NULL)),
5622 m_livein (BITMAP_ALLOC (NULL))
5623{
5624 gcc_assert (!cfg_bb->aux);
5625 cfg_bb->aux = this;
5626}
5627
5628/* Constructor of class containing HSA-specific information about a basic
5629 block. CFG_BB is the CFG BB this HSA BB is associated with. */
5630
5631hsa_bb::hsa_bb (basic_block cfg_bb)
5632 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5633 m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++),
5634 m_liveout (BITMAP_ALLOC (NULL)), m_livein (BITMAP_ALLOC (NULL))
5635{
5636 gcc_assert (!cfg_bb->aux);
5637 cfg_bb->aux = this;
5638}
5639
5640/* Destructor of class representing HSA BB. */
5641
5642hsa_bb::~hsa_bb ()
5643{
5644 BITMAP_FREE (m_livein);
5645 BITMAP_FREE (m_liveout);
5646}
5647
5648/* Create and initialize and return a new hsa_bb structure for a given CFG
5649 basic block BB. */
5650
5651hsa_bb *
5652hsa_init_new_bb (basic_block bb)
5653{
5654 return new (*hsa_allocp_bb) hsa_bb (bb);
5655}
5656
5657/* Initialize OMP in an HSA basic block PROLOGUE. */
5658
5659static void
5660init_prologue (void)
5661{
5662 if (!hsa_cfun->m_kern_p)
5663 return;
5664
5665 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5666
5667 /* Create a magic number that is going to be printed by libgomp. */
5668 unsigned index = hsa_get_number_decl_kernel_mappings ();
5669
5670 /* Emit store to debug argument. */
5671 if (PARAM_VALUE (PARAM_HSA_GEN_DEBUG_STORES) > 0)
5672 set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5673}
5674
5675/* Initialize hsa_num_threads to a default value. */
5676
5677static void
5678init_hsa_num_threads (void)
5679{
5680 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5681
5682 /* Save the default value to private variable hsa_num_threads. */
5683 hsa_insn_basic *basic
5684 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5685 new hsa_op_immed (0, hsa_num_threads->m_type),
5686 new hsa_op_address (hsa_num_threads));
5687 prologue->append_insn (basic);
5688}
5689
5690/* Go over gimple representation and generate our internal HSA one. */
5691
5692static void
5693gen_body_from_gimple ()
5694{
5695 basic_block bb;
5696
5697 /* Verify CFG for complex edges we are unable to handle. */
5698 edge_iterator ei;
5699 edge e;
5700
5701 FOR_EACH_BB_FN (bb, cfun)
5702 {
5703 FOR_EACH_EDGE (e, ei, bb->succs)
5704 {
5705 /* Verify all unsupported flags for edges that point
5706 to the same basic block. */
5707 if (e->flags & EDGE_EH)
5708 {
5709 HSA_SORRY_AT (UNKNOWN_LOCATION,
5710 "support for HSA does not implement exception "
5711 "handling");
5712 return;
5713 }
5714 }
5715 }
5716
5717 FOR_EACH_BB_FN (bb, cfun)
5718 {
5719 gimple_stmt_iterator gsi;
5720 hsa_bb *hbb = hsa_bb_for_bb (bb);
5721 if (hbb)
5722 continue;
5723
5724 hbb = hsa_init_new_bb (bb);
5725
5726 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5727 {
5728 gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
5729 if (hsa_seen_error ())
5730 return;
5731 }
5732 }
5733
5734 FOR_EACH_BB_FN (bb, cfun)
5735 {
5736 gimple_stmt_iterator gsi;
5737 hsa_bb *hbb = hsa_bb_for_bb (bb);
5738 gcc_assert (hbb != NULL);
5739
5740 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5741 if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
5742 gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
5743 }
5744
2998cb96 5745 if (dump_file && (dump_flags & TDF_DETAILS))
b2b40051
MJ
5746 {
5747 fprintf (dump_file, "------- Generated SSA form -------\n");
5748 dump_hsa_cfun (dump_file);
5749 }
5750}
5751
5752static void
5753gen_function_decl_parameters (hsa_function_representation *f,
5754 tree decl)
5755{
5756 tree parm;
5757 unsigned i;
5758
5759 for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
5760 parm;
5761 parm = TREE_CHAIN (parm), i++)
5762 {
5763 /* Result type if last in the tree list. */
5764 if (TREE_CHAIN (parm) == NULL)
5765 break;
5766
5767 tree v = TREE_VALUE (parm);
5768
5769 hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5770 BRIG_LINKAGE_NONE);
5771 arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
5772 arg->m_name_number = i;
5773
5774 f->m_input_args.safe_push (arg);
5775 }
5776
5777 tree result_type = TREE_TYPE (TREE_TYPE (decl));
5778 if (!VOID_TYPE_P (result_type))
5779 {
5780 f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5781 BRIG_LINKAGE_NONE);
5782 f->m_output_arg->m_type
5783 = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
5784 f->m_output_arg->m_name = "res";
5785 }
5786}
5787
5788/* Generate the vector of parameters of the HSA representation of the current
5789 function. This also includes the output parameter representing the
5790 result. */
5791
5792static void
5793gen_function_def_parameters ()
5794{
5795 tree parm;
5796
5797 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5798
5799 for (parm = DECL_ARGUMENTS (cfun->decl); parm;
5800 parm = DECL_CHAIN (parm))
5801 {
5802 struct hsa_symbol **slot;
5803
5804 hsa_symbol *arg
5805 = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
5806 ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
5807 BRIG_LINKAGE_FUNCTION);
5808 arg->fillup_for_decl (parm);
5809
5810 hsa_cfun->m_input_args.safe_push (arg);
5811
5812 if (hsa_seen_error ())
5813 return;
5814
5815 arg->m_name = hsa_get_declaration_name (parm);
5816
5817 /* Copy all input arguments and create corresponding private symbols
5818 for them. */
5819 hsa_symbol *private_arg;
5820 hsa_op_address *parm_addr = new hsa_op_address (arg);
5821
5822 if (TREE_ADDRESSABLE (parm)
5823 || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
5824 {
5825 private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
5826 private_arg->fillup_for_decl (parm);
5827
320c1a36
ML
5828 BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
5829
b2b40051
MJ
5830 hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
5831 gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
320c1a36 5832 arg->total_byte_size (), align);
b2b40051
MJ
5833 }
5834 else
5835 private_arg = arg;
5836
5837 slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
5838 gcc_assert (!*slot);
5839 *slot = private_arg;
5840
5841 if (is_gimple_reg (parm))
5842 {
5843 tree ddef = ssa_default_def (cfun, parm);
5844 if (ddef && !has_zero_uses (ddef))
5845 {
5846 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
5847 false);
5848 BrigType16_t mtype = mem_type_for_type (t);
5849 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
5850 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
5851 dest, parm_addr);
5852 gcc_assert (!parm_addr->m_reg);
5853 prologue->append_insn (mem);
5854 }
5855 }
5856 }
5857
5858 if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
5859 {
5860 struct hsa_symbol **slot;
5861
5862 hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5863 BRIG_LINKAGE_FUNCTION);
5864 hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
5865
5866 if (hsa_seen_error ())
5867 return;
5868
5869 hsa_cfun->m_output_arg->m_name = "res";
5870 slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
5871 INSERT);
5872 gcc_assert (!*slot);
5873 *slot = hsa_cfun->m_output_arg;
5874 }
5875}
5876
5877/* Generate function representation that corresponds to
5878 a function declaration. */
5879
5880hsa_function_representation *
5881hsa_generate_function_declaration (tree decl)
5882{
5883 hsa_function_representation *fun
5884 = new hsa_function_representation (decl, false, 0);
5885
5886 fun->m_declaration_p = true;
5887 fun->m_name = get_brig_function_name (decl);
5888 gen_function_decl_parameters (fun, decl);
5889
5890 return fun;
5891}
5892
5893
5894/* Generate function representation that corresponds to
5895 an internal FN. */
5896
5897hsa_function_representation *
5898hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
5899{
5900 hsa_function_representation *fun = new hsa_function_representation (fn);
5901
5902 fun->m_name = fn->name ();
5903
5904 for (unsigned i = 0; i < fn->get_arity (); i++)
5905 {
5906 hsa_symbol *arg
5907 = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
5908 BRIG_LINKAGE_NONE);
5909 arg->m_name_number = i;
5910 fun->m_input_args.safe_push (arg);
5911 }
5912
5913 fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
5914 BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
5915 fun->m_output_arg->m_name = "res";
5916
5917 return fun;
5918}
5919
5920/* Return true if switch statement S can be transformed
5921 to a SBR instruction in HSAIL. */
5922
5923static bool
5924transformable_switch_to_sbr_p (gswitch *s)
5925{
5926 /* Identify if a switch statement can be transformed to
5927 SBR instruction, like:
5928
5929 sbr_u32 $s1 [@label1, @label2, @label3];
5930 */
5931
5932 tree size = get_switch_size (s);
5933 if (!tree_fits_uhwi_p (size))
5934 return false;
5935
5936 if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
5937 return false;
5938
5939 return true;
5940}
5941
5942/* Structure hold connection between PHI nodes and immediate
5943 values hold by there nodes. */
5944
5945struct phi_definition
5946{
5947 phi_definition (unsigned phi_i, unsigned label_i, tree imm):
5948 phi_index (phi_i), label_index (label_i), phi_value (imm)
5949 {}
5950
5951 unsigned phi_index;
5952 unsigned label_index;
5953 tree phi_value;
5954};
5955
5956/* Sum slice of a vector V, starting from index START and ending
5957 at the index END - 1. */
5958
5959template <typename T>
5960static
5961T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end)
5962{
5963 T s = 0;
5964
5965 for (unsigned i = start; i < end; i++)
5966 s += v[i];
5967
5968 return s;
5969}
5970
5971/* Function transforms GIMPLE SWITCH statements to a series of IF statements.
5972 Let's assume following example:
5973
5974L0:
5975 switch (index)
5976 case C1:
5977L1: hard_work_1 ();
5978 break;
5979 case C2..C3:
5980L2: hard_work_2 ();
5981 break;
5982 default:
5983LD: hard_work_3 ();
5984 break;
5985
5986 The transformation encompasses following steps:
5987 1) all immediate values used by edges coming from the switch basic block
5988 are saved
5989 2) all these edges are removed
5990 3) the switch statement (in L0) is replaced by:
5991 if (index == C1)
5992 goto L1;
5993 else
5994 goto L1';
5995
5996 4) newly created basic block Lx' is used for generation of
5997 a next condition
5998 5) else branch of the last condition goes to LD
5999 6) fix all immediate values in PHI nodes that were propagated though
6000 edges that were removed in step 2
6001
6002 Note: if a case is made by a range C1..C2, then process
6003 following transformation:
6004
6005 switch_cond_op1 = C1 <= index;
6006 switch_cond_op2 = index <= C2;
6007 switch_cond_and = switch_cond_op1 & switch_cond_op2;
6008 if (switch_cond_and != 0)
6009 goto Lx;
6010 else
6011 goto Ly;
6012
6013*/
6014
65e21467
ML
6015static bool
6016convert_switch_statements (void)
b2b40051
MJ
6017{
6018 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6019 basic_block bb;
6020
65e21467 6021 bool modified_cfg = false;
b2b40051
MJ
6022
6023 FOR_EACH_BB_FN (bb, func)
6024 {
6025 gimple_stmt_iterator gsi = gsi_last_bb (bb);
6026 if (gsi_end_p (gsi))
6027 continue;
6028
6029 gimple *stmt = gsi_stmt (gsi);
6030
6031 if (gimple_code (stmt) == GIMPLE_SWITCH)
6032 {
6033 gswitch *s = as_a <gswitch *> (stmt);
6034
6035 /* If the switch can utilize SBR insn, skip the statement. */
6036 if (transformable_switch_to_sbr_p (s))
6037 continue;
6038
65e21467 6039 modified_cfg = true;
b2b40051
MJ
6040
6041 unsigned labels = gimple_switch_num_labels (s);
6042 tree index = gimple_switch_index (s);
6043 tree index_type = TREE_TYPE (index);
6044 tree default_label = gimple_switch_default_label (s);
6045 basic_block default_label_bb
6046 = label_to_block_fn (func, CASE_LABEL (default_label));
6047 basic_block cur_bb = bb;
6048
6049 auto_vec <edge> new_edges;
6050 auto_vec <phi_definition *> phi_todo_list;
6051 auto_vec <gcov_type> edge_counts;
6052 auto_vec <int> edge_probabilities;
6053
6054 /* Investigate all labels that and PHI nodes in these edges which
6055 should be fixed after we add new collection of edges. */
6056 for (unsigned i = 0; i < labels; i++)
6057 {
6058 tree label = gimple_switch_label (s, i);
6059 basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label));
6060 edge e = find_edge (bb, label_bb);
6061 edge_counts.safe_push (e->count);
6062 edge_probabilities.safe_push (e->probability);
6063 gphi_iterator phi_gsi;
6064
6065 /* Save PHI definitions that will be destroyed because of an edge
6066 is going to be removed. */
6067 unsigned phi_index = 0;
6068 for (phi_gsi = gsi_start_phis (e->dest);
6069 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6070 {
6071 gphi *phi = phi_gsi.phi ();
6072 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6073 {
6074 if (gimple_phi_arg_edge (phi, j) == e)
6075 {
6076 tree imm = gimple_phi_arg_def (phi, j);
6077 phi_definition *p = new phi_definition (phi_index, i,
6078 imm);
6079 phi_todo_list.safe_push (p);
6080 break;
6081 }
6082 }
6083 phi_index++;
6084 }
6085 }
6086
6087 /* Remove all edges for the current basic block. */
6088 for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6089 {
6090 edge e = EDGE_SUCC (bb, i);
6091 remove_edge (e);
6092 }
6093
6094 /* Iterate all non-default labels. */
6095 for (unsigned i = 1; i < labels; i++)
6096 {
6097 tree label = gimple_switch_label (s, i);
6098 tree low = CASE_LOW (label);
6099 tree high = CASE_HIGH (label);
6100
6101 if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6102 low = fold_convert (index_type, low);
6103
6104 gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6105 gimple *c = NULL;
6106 if (high)
6107 {
6108 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6109 "switch_cond_op1");
6110
6111 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6112 index);
6113
6114 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6115 "switch_cond_op2");
6116
6117 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6118 high = fold_convert (index_type, high);
6119 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6120 high);
6121
6122 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6123 "switch_cond_and");
6124 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6125 tmp2);
6126
6127 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6128 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6129 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6130
6131 tree b = constant_boolean_node (false, boolean_type_node);
6132 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6133 }
6134 else
6135 c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6136
6137 gimple_set_location (c, gimple_location (stmt));
6138
6139 gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6140
6141 basic_block label_bb
6142 = label_to_block_fn (func, CASE_LABEL (label));
6143 edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6144 int prob_sum = sum_slice <int> (edge_probabilities, i, labels) +
6145 edge_probabilities[0];
6146
6147 if (prob_sum)
6148 new_edge->probability
6149 = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
6150
6151 new_edge->count = edge_counts[i];
6152 new_edges.safe_push (new_edge);
6153
6154 if (i < labels - 1)
6155 {
6156 /* Prepare another basic block that will contain
6157 next condition. */
6158 basic_block next_bb = create_empty_bb (cur_bb);
6159 if (current_loops)
6160 {
6161 add_bb_to_loop (next_bb, cur_bb->loop_father);
6162 loops_state_set (LOOPS_NEED_FIXUP);
6163 }
6164
6165 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6166 next_edge->probability
6167 = inverse_probability (new_edge->probability);
6168 next_edge->count = edge_counts[0]
6169 + sum_slice <gcov_type> (edge_counts, i, labels);
6170 next_bb->frequency = EDGE_FREQUENCY (next_edge);
6171 cur_bb = next_bb;
6172 }
6173 else /* Link last IF statement and default label
6174 of the switch. */
6175 {
6176 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6177 e->probability = inverse_probability (new_edge->probability);
6178 e->count = edge_counts[0];
6179 new_edges.safe_insert (0, e);
6180 }
6181 }
6182
6183 /* Restore original PHI immediate value. */
6184 for (unsigned i = 0; i < phi_todo_list.length (); i++)
6185 {
6186 phi_definition *phi_def = phi_todo_list[i];
6187 edge new_edge = new_edges[phi_def->label_index];
6188
6189 gphi_iterator it = gsi_start_phis (new_edge->dest);
6190 for (unsigned i = 0; i < phi_def->phi_index; i++)
6191 gsi_next (&it);
6192
6193 gphi *phi = it.phi ();
6194 add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6195 delete phi_def;
6196 }
6197
6198 /* Remove the original GIMPLE switch statement. */
6199 gsi_remove (&gsi, true);
6200 }
6201 }
6202
6203 if (dump_file)
6204 dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6205
65e21467 6206 return modified_cfg;
b2b40051
MJ
6207}
6208
6209/* Expand builtins that can't be handled by HSA back-end. */
6210
6211static void
6212expand_builtins ()
6213{
6214 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6215 basic_block bb;
6216
6217 FOR_EACH_BB_FN (bb, func)
6218 {
6219 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6220 gsi_next (&gsi))
6221 {
6222 gimple *stmt = gsi_stmt (gsi);
6223
6224 if (gimple_code (stmt) != GIMPLE_CALL)
6225 continue;
6226
6227 gcall *call = as_a <gcall *> (stmt);
6228
6229 if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6230 continue;
6231
6232 tree fndecl = gimple_call_fndecl (stmt);
6233 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6234 switch (fn)
6235 {
6236 case BUILT_IN_CEXPF:
6237 case BUILT_IN_CEXPIF:
6238 case BUILT_IN_CEXPI:
6239 {
6240 /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6241 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z). */
6242 tree lhs = gimple_call_lhs (stmt);
6243 tree rhs = gimple_call_arg (stmt, 0);
6244 tree rhs_type = TREE_TYPE (rhs);
6245 bool float_type_p = rhs_type == float_type_node;
6246 tree real_part = make_temp_ssa_name (rhs_type, NULL,
6247 "cexp_real_part");
6248 tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6249 "cexp_imag_part");
6250
6251 tree cos_fndecl
6252 = mathfn_built_in (rhs_type, fn == float_type_p
6253 ? BUILT_IN_COSF : BUILT_IN_COS);
6254 gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6255 gimple_call_set_lhs (cos, real_part);
6256 gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6257
6258 tree sin_fndecl
6259 = mathfn_built_in (rhs_type, fn == float_type_p
6260 ? BUILT_IN_SINF : BUILT_IN_SIN);
6261 gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6262 gimple_call_set_lhs (sin, imag_part);
6263 gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6264
6265
6266 gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6267 real_part, imag_part);
6268 gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6269 gsi_remove (&gsi, true);
6270
6271 break;
6272 }
6273 default:
6274 break;
6275 }
6276 }
6277 }
6278}
6279
6280/* Emit HSA module variables that are global for the entire module. */
6281
6282static void
6283emit_hsa_module_variables (void)
6284{
6285 hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6286 BRIG_LINKAGE_MODULE, true);
6287
6288 hsa_num_threads->m_name = "hsa_num_threads";
6289
6290 hsa_brig_emit_omp_symbols ();
6291}
6292
6293/* Generate HSAIL representation of the current function and write into a
6294 special section of the output file. If KERNEL is set, the function will be
6295 considered an HSA kernel callable from the host, otherwise it will be
6296 compiled as an HSA function callable from other HSA code. */
6297
6298static void
6299generate_hsa (bool kernel)
6300{
6301 hsa_init_data_for_cfun ();
6302
6303 if (hsa_num_threads == NULL)
6304 emit_hsa_module_variables ();
6305
65e21467 6306 bool modified_cfg = convert_switch_statements ();
b2b40051
MJ
6307 /* Initialize hsa_cfun. */
6308 hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
65e21467
ML
6309 SSANAMES (cfun)->length (),
6310 modified_cfg);
b2b40051
MJ
6311 hsa_cfun->init_extra_bbs ();
6312
6313 if (flag_tm)
6314 {
6315 HSA_SORRY_AT (UNKNOWN_LOCATION,
6316 "support for HSA does not implement transactional memory");
6317 goto fail;
6318 }
6319
6320 verify_function_arguments (cfun->decl);
6321 if (hsa_seen_error ())
6322 goto fail;
6323
6324 hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6325
6326 gen_function_def_parameters ();
6327 if (hsa_seen_error ())
6328 goto fail;
6329
6330 init_prologue ();
6331
6332 gen_body_from_gimple ();
6333 if (hsa_seen_error ())
6334 goto fail;
6335
6336 if (hsa_cfun->m_kernel_dispatch_count)
6337 init_hsa_num_threads ();
6338
6339 if (hsa_cfun->m_kern_p)
6340 {
6341 hsa_function_summary *s
6342 = hsa_summaries->get (cgraph_node::get (hsa_cfun->m_decl));
6343 hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6344 hsa_cfun->m_maximum_omp_data_size,
6345 s->m_gridified_kernel_p);
6346 }
6347
ac400631 6348 if (flag_checking)
b2b40051 6349 {
ac400631
ML
6350 for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6351 if (hsa_cfun->m_ssa_map[i])
6352 hsa_cfun->m_ssa_map[i]->verify_ssa ();
b2b40051 6353
ac400631
ML
6354 basic_block bb;
6355 FOR_EACH_BB_FN (bb, cfun)
6356 {
6357 hsa_bb *hbb = hsa_bb_for_bb (bb);
b2b40051 6358
ac400631
ML
6359 for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6360 insn = insn->m_next)
6361 insn->verify ();
6362 }
6363 }
b2b40051
MJ
6364
6365 hsa_regalloc ();
6366 hsa_brig_emit_function ();
6367
6368 fail:
6369 hsa_deinit_data_for_cfun ();
6370}
6371
6372namespace {
6373
6374const pass_data pass_data_gen_hsail =
6375{
6376 GIMPLE_PASS,
6377 "hsagen", /* name */
6378 OPTGROUP_NONE, /* optinfo_flags */
6379 TV_NONE, /* tv_id */
6380 PROP_cfg | PROP_ssa, /* properties_required */
6381 0, /* properties_provided */
6382 0, /* properties_destroyed */
6383 0, /* todo_flags_start */
6384 0 /* todo_flags_finish */
6385};
6386
6387class pass_gen_hsail : public gimple_opt_pass
6388{
6389public:
6390 pass_gen_hsail (gcc::context *ctxt)
6391 : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6392 {}
6393
6394 /* opt_pass methods: */
6395 bool gate (function *);
6396 unsigned int execute (function *);
6397
6398}; // class pass_gen_hsail
6399
6400/* Determine whether or not to run generation of HSAIL. */
6401
6402bool
6403pass_gen_hsail::gate (function *f)
6404{
6405 return hsa_gen_requested_p ()
6406 && hsa_gpu_implementation_p (f->decl);
6407}
6408
6409unsigned int
6410pass_gen_hsail::execute (function *)
6411{
6412 hsa_function_summary *s
6413 = hsa_summaries->get (cgraph_node::get_create (current_function_decl));
6414
b2b40051
MJ
6415 expand_builtins ();
6416 generate_hsa (s->m_kind == HSA_KERNEL);
6417 TREE_ASM_WRITTEN (current_function_decl) = 1;
6418 return TODO_discard_function;
6419}
6420
6421} // anon namespace
6422
6423/* Create the instance of hsa gen pass. */
6424
6425gimple_opt_pass *
6426make_pass_gen_hsail (gcc::context *ctxt)
6427{
6428 return new pass_gen_hsail (ctxt);
6429}