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