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