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