[ARM][committed] Sort ARMv8 processors by alphabetic order
[official-gcc.git] / gcc / hsa-gen.c
bloba88294ecd4f71a60643b54d3dd3c8b46075b2e5c
1 /* A pass for lowering gimple to HSAIL
2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 Contributed by Martin Jambor <mjambor@suse.cz> and
4 Martin Liska <mliska@suse.cz>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "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 "cfg.h"
33 #include "function.h"
34 #include "basic-block.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.h"
53 #include "cfghooks.h"
54 #include "tree-cfg.h"
55 #include "cfgloop.h"
56 #include "cfganal.h"
57 #include "builtins.h"
58 #include "params.h"
59 #include "gomp-constants.h"
60 #include "internal-fn.h"
61 #include "builtins.h"
62 #include "stor-layout.h"
64 /* Print a warning message and set that we have seen an error. */
66 #define HSA_SORRY_ATV(location, message, ...) \
67 do \
68 { \
69 hsa_fail_cfun (); \
70 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
71 HSA_SORRY_MSG)) \
72 inform (location, message, __VA_ARGS__); \
73 } \
74 while (false)
76 /* Same as previous, but highlight a location. */
78 #define HSA_SORRY_AT(location, message) \
79 do \
80 { \
81 hsa_fail_cfun (); \
82 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
83 HSA_SORRY_MSG)) \
84 inform (location, message); \
85 } \
86 while (false)
88 /* Default number of threads used by kernel dispatch. */
90 #define HSA_DEFAULT_NUM_THREADS 64
92 /* Following structures are defined in the final version
93 of HSA specification. */
95 /* HSA queue packet is shadow structure, originally provided by AMD. */
97 struct hsa_queue_packet
99 uint16_t header;
100 uint16_t setup;
101 uint16_t workgroup_size_x;
102 uint16_t workgroup_size_y;
103 uint16_t workgroup_size_z;
104 uint16_t reserved0;
105 uint32_t grid_size_x;
106 uint32_t grid_size_y;
107 uint32_t grid_size_z;
108 uint32_t private_segment_size;
109 uint32_t group_segment_size;
110 uint64_t kernel_object;
111 void *kernarg_address;
112 uint64_t reserved2;
113 uint64_t completion_signal;
116 /* HSA queue is shadow structure, originally provided by AMD. */
118 struct hsa_queue
120 int type;
121 uint32_t features;
122 void *base_address;
123 uint64_t doorbell_signal;
124 uint32_t size;
125 uint32_t reserved1;
126 uint64_t id;
129 static struct obstack hsa_obstack;
131 /* List of pointers to all instructions that come from an object allocator. */
132 static vec <hsa_insn_basic *> hsa_instructions;
134 /* List of pointers to all operands that come from an object allocator. */
135 static vec <hsa_op_base *> hsa_operands;
137 hsa_symbol::hsa_symbol ()
138 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
139 m_directive_offset (0), m_type (BRIG_TYPE_NONE),
140 m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
141 m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
142 m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
147 hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
148 BrigLinkage8_t linkage, bool global_scope_p,
149 BrigAllocation allocation, BrigAlignment8_t align)
150 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
151 m_directive_offset (0), m_type (type), m_segment (segment),
152 m_linkage (linkage), m_dim (0), m_cst_value (NULL),
153 m_global_scope_p (global_scope_p), m_seen_error (false),
154 m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
158 unsigned HOST_WIDE_INT
159 hsa_symbol::total_byte_size ()
161 unsigned HOST_WIDE_INT s
162 = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
163 gcc_assert (s % BITS_PER_UNIT == 0);
164 s /= BITS_PER_UNIT;
166 if (m_dim)
167 s *= m_dim;
169 return s;
172 /* Forward declaration. */
174 static BrigType16_t
175 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
176 bool min32int);
178 void
179 hsa_symbol::fillup_for_decl (tree decl)
181 m_decl = decl;
182 m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
183 if (hsa_seen_error ())
185 m_seen_error = true;
186 return;
189 m_align = MAX (m_align, hsa_natural_alignment (m_type));
192 /* Constructor of class representing global HSA function/kernel information and
193 state. FNDECL is function declaration, KERNEL_P is true if the function
194 is going to become a HSA kernel. If the function has body, SSA_NAMES_COUNT
195 should be set to number of SSA names used in the function.
196 MODIFIED_CFG is set to true in case we modified control-flow graph
197 of the function. */
199 hsa_function_representation::hsa_function_representation
200 (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
201 : m_name (NULL),
202 m_reg_count (0), m_input_args (vNULL),
203 m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
204 m_private_variables (vNULL), m_called_functions (vNULL),
205 m_called_internal_fns (vNULL), m_hbb_count (0),
206 m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
207 m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
208 m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
209 m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
210 m_modified_cfg (modified_cfg)
212 int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;;
213 m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
214 m_ssa_map.safe_grow_cleared (ssa_names_count);
217 /* Constructor of class representing HSA function information that
218 is derived for an internal function. */
219 hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
220 : m_reg_count (0), m_input_args (vNULL),
221 m_output_arg (NULL), m_local_symbols (NULL),
222 m_spill_symbols (vNULL), m_global_symbols (vNULL),
223 m_private_variables (vNULL), m_called_functions (vNULL),
224 m_called_internal_fns (vNULL), m_hbb_count (0),
225 m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
226 m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
227 m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
228 m_ssa_map () {}
230 /* Destructor of class holding function/kernel-wide information and state. */
232 hsa_function_representation::~hsa_function_representation ()
234 /* Kernel names are deallocated at the end of BRIG output when deallocating
235 hsa_decl_kernel_mapping. */
236 if (!m_kern_p || m_seen_error)
237 free (m_name);
239 for (unsigned i = 0; i < m_input_args.length (); i++)
240 delete m_input_args[i];
241 m_input_args.release ();
243 delete m_output_arg;
244 delete m_local_symbols;
246 for (unsigned i = 0; i < m_spill_symbols.length (); i++)
247 delete m_spill_symbols[i];
248 m_spill_symbols.release ();
250 hsa_symbol *sym;
251 for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
252 if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
253 delete sym;
254 m_global_symbols.release ();
256 for (unsigned i = 0; i < m_private_variables.length (); i++)
257 delete m_private_variables[i];
258 m_private_variables.release ();
259 m_called_functions.release ();
260 m_ssa_map.release ();
262 for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
263 delete m_called_internal_fns[i];
266 hsa_op_reg *
267 hsa_function_representation::get_shadow_reg ()
269 /* If we compile a function with kernel dispatch and does not set
270 an optimization level, the function won't be inlined and
271 we return NULL. */
272 if (!m_kern_p)
273 return NULL;
275 if (m_shadow_reg)
276 return m_shadow_reg;
278 /* Append the shadow argument. */
279 hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
280 BRIG_LINKAGE_FUNCTION);
281 m_input_args.safe_push (shadow);
282 shadow->m_name = "hsa_runtime_shadow";
284 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
285 hsa_op_address *addr = new hsa_op_address (shadow);
287 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
288 hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
289 m_shadow_reg = r;
291 return r;
294 bool hsa_function_representation::has_shadow_reg_p ()
296 return m_shadow_reg != NULL;
299 void
300 hsa_function_representation::init_extra_bbs ()
302 hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
303 hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
306 void
307 hsa_function_representation::update_dominance ()
309 if (m_modified_cfg)
311 free_dominance_info (CDI_DOMINATORS);
312 calculate_dominance_info (CDI_DOMINATORS);
316 hsa_symbol *
317 hsa_function_representation::create_hsa_temporary (BrigType16_t type)
319 hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
320 BRIG_LINKAGE_FUNCTION);
321 s->m_name_number = m_temp_symbol_count++;
323 hsa_cfun->m_private_variables.safe_push (s);
324 return s;
327 BrigLinkage8_t
328 hsa_function_representation::get_linkage ()
330 if (m_internal_fn)
331 return BRIG_LINKAGE_PROGRAM;
333 return m_kern_p || TREE_PUBLIC (m_decl) ?
334 BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
337 /* Hash map of simple OMP builtins. */
338 static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
339 = NULL;
341 /* Warning messages for OMP builtins. */
343 #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
344 "lock routines"
345 #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
346 "timing routines"
347 #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
348 "undefined semantics within target regions, support for HSA ignores them"
349 #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
350 "affinity feateres"
352 /* Initialize hash map with simple OMP builtins. */
354 static void
355 hsa_init_simple_builtins ()
357 if (omp_simple_builtins != NULL)
358 return;
360 omp_simple_builtins
361 = new hash_map <nofree_string_hash, omp_simple_builtin> ();
363 omp_simple_builtin omp_builtins[] =
365 omp_simple_builtin ("omp_get_initial_device", NULL, false,
366 new hsa_op_immed (GOMP_DEVICE_HOST,
367 (BrigType16_t) BRIG_TYPE_S32)),
368 omp_simple_builtin ("omp_is_initial_device", NULL, false,
369 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
370 omp_simple_builtin ("omp_get_dynamic", NULL, false,
371 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
372 omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
373 omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
374 omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
375 true),
376 omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
377 true),
378 omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
379 omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
380 omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
381 omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
382 omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
383 omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
384 omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
385 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
386 omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
387 omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
388 false,
389 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
390 omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
391 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
392 omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
393 false,
394 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
395 omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
396 false,
397 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
398 omp_simple_builtin ("omp_target_disassociate_ptr",
399 HSA_WARN_MEMORY_ROUTINE,
400 false,
401 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
402 omp_simple_builtin ("omp_set_max_active_levels",
403 "Support for HSA only allows only one active level, "
404 "call to omp_set_max_active_levels will be ignored "
405 "in the generated HSAIL",
406 false, NULL),
407 omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
408 new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
409 omp_simple_builtin ("omp_in_final", NULL, false,
410 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
411 omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
412 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
413 omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
414 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
415 omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
416 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
417 omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
418 NULL),
419 omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
420 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
421 omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
422 false,
423 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
424 omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
425 false, NULL),
426 omp_simple_builtin ("omp_set_default_device",
427 "omp_set_default_device has undefined semantics "
428 "within target regions, support for HSA ignores it",
429 false, NULL),
430 omp_simple_builtin ("omp_get_default_device",
431 "omp_get_default_device has undefined semantics "
432 "within target regions, support for HSA ignores it",
433 false,
434 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
435 omp_simple_builtin ("omp_get_num_devices",
436 "omp_get_num_devices has undefined semantics "
437 "within target regions, support for HSA ignores it",
438 false,
439 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
440 omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
441 omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
442 omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
443 omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
444 omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
445 omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
446 omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
447 omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
448 omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
449 omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
452 unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
454 for (unsigned i = 0; i < count; i++)
455 omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
458 /* Allocate HSA structures that we need only while generating with this. */
460 static void
461 hsa_init_data_for_cfun ()
463 hsa_init_compilation_unit_data ();
464 gcc_obstack_init (&hsa_obstack);
467 /* Deinitialize HSA subsystem and free all allocated memory. */
469 static void
470 hsa_deinit_data_for_cfun (void)
472 basic_block bb;
474 FOR_ALL_BB_FN (bb, cfun)
475 if (bb->aux)
477 hsa_bb *hbb = hsa_bb_for_bb (bb);
478 hbb->~hsa_bb ();
479 bb->aux = NULL;
482 for (unsigned int i = 0; i < hsa_operands.length (); i++)
483 hsa_destroy_operand (hsa_operands[i]);
485 hsa_operands.release ();
487 for (unsigned i = 0; i < hsa_instructions.length (); i++)
488 hsa_destroy_insn (hsa_instructions[i]);
490 hsa_instructions.release ();
492 if (omp_simple_builtins != NULL)
494 delete omp_simple_builtins;
495 omp_simple_builtins = NULL;
498 obstack_free (&hsa_obstack, NULL);
499 delete hsa_cfun;
502 /* Return the type which holds addresses in the given SEGMENT. */
504 static BrigType16_t
505 hsa_get_segment_addr_type (BrigSegment8_t segment)
507 switch (segment)
509 case BRIG_SEGMENT_NONE:
510 gcc_unreachable ();
512 case BRIG_SEGMENT_FLAT:
513 case BRIG_SEGMENT_GLOBAL:
514 case BRIG_SEGMENT_READONLY:
515 case BRIG_SEGMENT_KERNARG:
516 return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
518 case BRIG_SEGMENT_GROUP:
519 case BRIG_SEGMENT_PRIVATE:
520 case BRIG_SEGMENT_SPILL:
521 case BRIG_SEGMENT_ARG:
522 return BRIG_TYPE_U32;
524 gcc_unreachable ();
527 /* Return integer brig type according to provided SIZE in bytes. If SIGN
528 is set to true, return signed integer type. */
530 static BrigType16_t
531 get_integer_type_by_bytes (unsigned size, bool sign)
533 if (sign)
534 switch (size)
536 case 1:
537 return BRIG_TYPE_S8;
538 case 2:
539 return BRIG_TYPE_S16;
540 case 4:
541 return BRIG_TYPE_S32;
542 case 8:
543 return BRIG_TYPE_S64;
544 default:
545 break;
547 else
548 switch (size)
550 case 1:
551 return BRIG_TYPE_U8;
552 case 2:
553 return BRIG_TYPE_U16;
554 case 4:
555 return BRIG_TYPE_U32;
556 case 8:
557 return BRIG_TYPE_U64;
558 default:
559 break;
562 return 0;
565 /* Return HSA type for tree TYPE, which has to fit into BrigType16_t. Pointers
566 are assumed to use flat addressing. If min32int is true, always expand
567 integer types to one that has at least 32 bits. */
569 static BrigType16_t
570 hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
572 HOST_WIDE_INT bsize;
573 const_tree base;
574 BrigType16_t res = BRIG_TYPE_NONE;
576 gcc_checking_assert (TYPE_P (type));
577 gcc_checking_assert (!AGGREGATE_TYPE_P (type));
578 if (POINTER_TYPE_P (type))
579 return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
581 if (TREE_CODE (type) == VECTOR_TYPE || TREE_CODE (type) == COMPLEX_TYPE)
582 base = TREE_TYPE (type);
583 else
584 base = type;
586 if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
588 HSA_SORRY_ATV (EXPR_LOCATION (type),
589 "support for HSA does not implement huge or "
590 "variable-sized type %T", type);
591 return res;
594 bsize = tree_to_uhwi (TYPE_SIZE (base));
595 unsigned byte_size = bsize / BITS_PER_UNIT;
596 if (INTEGRAL_TYPE_P (base))
597 res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
598 else if (SCALAR_FLOAT_TYPE_P (base))
600 switch (bsize)
602 case 16:
603 res = BRIG_TYPE_F16;
604 break;
605 case 32:
606 res = BRIG_TYPE_F32;
607 break;
608 case 64:
609 res = BRIG_TYPE_F64;
610 break;
611 default:
612 break;
616 if (res == BRIG_TYPE_NONE)
618 HSA_SORRY_ATV (EXPR_LOCATION (type),
619 "support for HSA does not implement type %T", type);
620 return res;
623 if (TREE_CODE (type) == VECTOR_TYPE)
625 HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
627 if (bsize == tsize)
629 HSA_SORRY_ATV (EXPR_LOCATION (type),
630 "support for HSA does not implement a vector type "
631 "where a type and unit size are equal: %T", type);
632 return res;
635 switch (tsize)
637 case 32:
638 res |= BRIG_TYPE_PACK_32;
639 break;
640 case 64:
641 res |= BRIG_TYPE_PACK_64;
642 break;
643 case 128:
644 res |= BRIG_TYPE_PACK_128;
645 break;
646 default:
647 HSA_SORRY_ATV (EXPR_LOCATION (type),
648 "support for HSA does not implement type %T", type);
652 if (min32int)
654 /* Registers/immediate operands can only be 32bit or more except for
655 f16. */
656 if (res == BRIG_TYPE_U8 || res == BRIG_TYPE_U16)
657 res = BRIG_TYPE_U32;
658 else if (res == BRIG_TYPE_S8 || res == BRIG_TYPE_S16)
659 res = BRIG_TYPE_S32;
662 if (TREE_CODE (type) == COMPLEX_TYPE)
664 unsigned bsize = 2 * hsa_type_bit_size (res);
665 res = hsa_bittype_for_bitsize (bsize);
668 return res;
671 /* Returns the BRIG type we need to load/store entities of TYPE. */
673 static BrigType16_t
674 mem_type_for_type (BrigType16_t type)
676 /* HSA has non-intuitive constraints on load/store types. If it's
677 a bit-type it _must_ be B128, if it's not a bit-type it must be
678 64bit max. So for loading entities of 128 bits (e.g. vectors)
679 we have to to B128, while for loading the rest we have to use the
680 input type (??? or maybe also flattened to a equally sized non-vector
681 unsigned type?). */
682 if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
683 return BRIG_TYPE_B128;
684 else if (hsa_btype_p (type) || hsa_type_packed_p (type))
686 unsigned bitsize = hsa_type_bit_size (type);
687 if (bitsize < 128)
688 return hsa_uint_for_bitsize (bitsize);
689 else
690 return hsa_bittype_for_bitsize (bitsize);
692 return type;
695 /* Return HSA type for tree TYPE. If it cannot fit into BrigType16_t, some
696 kind of array will be generated, setting DIM appropriately. Otherwise, it
697 will be set to zero. */
699 static BrigType16_t
700 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
701 bool min32int = false)
703 gcc_checking_assert (TYPE_P (type));
704 if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
706 HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
707 "implement huge or variable-sized type %T", type);
708 return BRIG_TYPE_NONE;
711 if (RECORD_OR_UNION_TYPE_P (type))
713 if (dim_p)
714 *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
715 return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
718 if (TREE_CODE (type) == ARRAY_TYPE)
720 /* We try to be nice and use the real base-type when this is an array of
721 scalars and only resort to an array of bytes if the type is more
722 complex. */
724 unsigned HOST_WIDE_INT dim = 1;
726 while (TREE_CODE (type) == ARRAY_TYPE)
728 tree domain = TYPE_DOMAIN (type);
729 if (!TYPE_MIN_VALUE (domain)
730 || !TYPE_MAX_VALUE (domain)
731 || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
732 || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
734 HSA_SORRY_ATV (EXPR_LOCATION (type),
735 "support for HSA does not implement array %T with "
736 "unknown bounds", type);
737 return BRIG_TYPE_NONE;
739 HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
740 HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
741 dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
742 type = TREE_TYPE (type);
745 BrigType16_t res;
746 if (RECORD_OR_UNION_TYPE_P (type))
748 dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
749 res = BRIG_TYPE_U8;
751 else
752 res = hsa_type_for_scalar_tree_type (type, false);
754 if (dim_p)
755 *dim_p = dim;
756 return res | BRIG_TYPE_ARRAY;
759 /* Scalar case: */
760 if (dim_p)
761 *dim_p = 0;
763 return hsa_type_for_scalar_tree_type (type, min32int);
766 /* Returns true if converting from STYPE into DTYPE needs the _CVT
767 opcode. If false a normal _MOV is enough. */
769 static bool
770 hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
772 if (hsa_btype_p (dtype))
773 return false;
775 /* float <-> int conversions are real converts. */
776 if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
777 return true;
778 /* When both types have different size, then we need CVT as well. */
779 if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
780 return true;
781 return false;
784 /* Return declaration name if it exists or create one from UID if it does not.
785 If DECL is a local variable, make UID part of its name. */
787 const char *
788 hsa_get_declaration_name (tree decl)
790 if (!DECL_NAME (decl))
792 char buf[64];
793 snprintf (buf, 64, "__hsa_anon_%u", DECL_UID (decl));
794 size_t len = strlen (buf);
795 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
796 memcpy (copy, buf, len + 1);
797 return copy;
800 tree name_tree;
801 if (TREE_CODE (decl) == FUNCTION_DECL
802 || (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)))
803 name_tree = DECL_ASSEMBLER_NAME (decl);
804 else
805 name_tree = DECL_NAME (decl);
807 const char *name = IDENTIFIER_POINTER (name_tree);
808 /* User-defined assembly names have prepended asterisk symbol. */
809 if (name[0] == '*')
810 name++;
812 if ((TREE_CODE (decl) == VAR_DECL)
813 && decl_function_context (decl))
815 size_t len = strlen (name);
816 char *buf = (char *) alloca (len + 32);
817 snprintf (buf, len + 32, "%s_%u", name, DECL_UID (decl));
818 len = strlen (buf);
819 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
820 memcpy (copy, buf, len + 1);
821 return copy;
823 else
824 return name;
827 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
828 or lookup the hsa_structure corresponding to a PARM_DECL. */
830 static hsa_symbol *
831 get_symbol_for_decl (tree decl)
833 hsa_symbol **slot;
834 hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
836 gcc_assert (TREE_CODE (decl) == PARM_DECL
837 || TREE_CODE (decl) == RESULT_DECL
838 || TREE_CODE (decl) == VAR_DECL
839 || TREE_CODE (decl) == CONST_DECL);
841 dummy.m_decl = decl;
843 bool is_in_global_vars = ((TREE_CODE (decl) == VAR_DECL)
844 && !decl_function_context (decl));
846 if (is_in_global_vars)
847 slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
848 else
849 slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
851 gcc_checking_assert (slot);
852 if (*slot)
854 hsa_symbol *sym = (*slot);
856 /* If the symbol is problematic, mark current function also as
857 problematic. */
858 if (sym->m_seen_error)
859 hsa_fail_cfun ();
861 /* PR hsa/70234: If a global variable was marked to be emitted,
862 but HSAIL generation of a function using the variable fails,
863 we should retry to emit the variable in context of a different
864 function.
866 Iterate elements whether a symbol is already in m_global_symbols
867 of not. */
868 if (is_in_global_vars && !sym->m_emitted_to_brig)
870 for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
871 if (hsa_cfun->m_global_symbols[i] == sym)
872 return *slot;
873 hsa_cfun->m_global_symbols.safe_push (sym);
876 return *slot;
878 else
880 hsa_symbol *sym;
881 /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols. */
882 gcc_assert (TREE_CODE (decl) == VAR_DECL
883 || TREE_CODE (decl) == CONST_DECL);
884 BrigAlignment8_t align = hsa_object_alignment (decl);
886 if (is_in_global_vars)
888 gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
889 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
890 BRIG_LINKAGE_PROGRAM, true,
891 BRIG_ALLOCATION_PROGRAM, align);
892 hsa_cfun->m_global_symbols.safe_push (sym);
893 sym->fillup_for_decl (decl);
894 if (sym->m_align > align)
896 sym->m_seen_error = true;
897 HSA_SORRY_ATV (EXPR_LOCATION (decl),
898 "HSA specification requires that %E is at least "
899 "naturally aligned", decl);
902 else
904 /* As generation of efficient memory copy instructions relies
905 on alignment greater or equal to 8 bytes,
906 we need to increase alignment of all aggregate types.. */
907 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
908 align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
910 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
911 BrigSegment8_t segment;
912 if (TREE_CODE (decl) == CONST_DECL)
914 segment = BRIG_SEGMENT_READONLY;
915 allocation = BRIG_ALLOCATION_AGENT;
917 else if (lookup_attribute ("hsa_group_segment",
918 DECL_ATTRIBUTES (decl)))
919 segment = BRIG_SEGMENT_GROUP;
920 else if (TREE_STATIC (decl)
921 || lookup_attribute ("hsa_global_segment",
922 DECL_ATTRIBUTES (decl)))
923 segment = BRIG_SEGMENT_GLOBAL;
924 else
925 segment = BRIG_SEGMENT_PRIVATE;
927 sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
928 false, allocation, align);
929 sym->fillup_for_decl (decl);
930 hsa_cfun->m_private_variables.safe_push (sym);
933 sym->m_name = hsa_get_declaration_name (decl);
934 *slot = sym;
935 return sym;
939 /* For a given HSA function declaration, return a host
940 function declaration. */
942 tree
943 hsa_get_host_function (tree decl)
945 hsa_function_summary *s
946 = hsa_summaries->get (cgraph_node::get_create (decl));
947 gcc_assert (s->m_kind != HSA_NONE);
948 gcc_assert (s->m_gpu_implementation_p);
950 return s->m_bound_function ? s->m_bound_function->decl : NULL;
953 /* Return true if function DECL has a host equivalent function. */
955 static char *
956 get_brig_function_name (tree decl)
958 tree d = decl;
960 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
961 if (s->m_kind != HSA_NONE
962 && s->m_gpu_implementation_p
963 && s->m_bound_function)
964 d = s->m_bound_function->decl;
966 /* IPA split can create a function that has no host equivalent. */
967 if (d == NULL)
968 d = decl;
970 char *name = xstrdup (hsa_get_declaration_name (d));
971 hsa_sanitize_name (name);
973 return name;
976 /* Create a spill symbol of type TYPE. */
978 hsa_symbol *
979 hsa_get_spill_symbol (BrigType16_t type)
981 hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
982 BRIG_LINKAGE_FUNCTION);
983 hsa_cfun->m_spill_symbols.safe_push (sym);
984 return sym;
987 /* Create a symbol for a read-only string constant. */
988 hsa_symbol *
989 hsa_get_string_cst_symbol (tree string_cst)
991 gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
993 hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
994 if (slot)
995 return *slot;
997 hsa_op_immed *cst = new hsa_op_immed (string_cst);
998 hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
999 BRIG_LINKAGE_MODULE, true,
1000 BRIG_ALLOCATION_AGENT);
1001 sym->m_cst_value = cst;
1002 sym->m_dim = TREE_STRING_LENGTH (string_cst);
1003 sym->m_name_number = hsa_cfun->m_global_symbols.length ();
1005 hsa_cfun->m_global_symbols.safe_push (sym);
1006 hsa_cfun->m_string_constants_map.put (string_cst, sym);
1007 return sym;
1010 /* Constructor of the ancestor of all operands. K is BRIG kind that identified
1011 what the operator is. */
1013 hsa_op_base::hsa_op_base (BrigKind16_t k)
1014 : m_next (NULL), m_brig_op_offset (0), m_kind (k)
1016 hsa_operands.safe_push (this);
1019 /* Constructor of ancestor of all operands which have a type. K is BRIG kind
1020 that identified what the operator is. T is the type of the operator. */
1022 hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
1023 : hsa_op_base (k), m_type (t)
1027 hsa_op_with_type *
1028 hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
1030 if (m_type == dtype)
1031 return this;
1033 hsa_op_reg *dest;
1035 if (hsa_needs_cvt (dtype, m_type))
1037 dest = new hsa_op_reg (dtype);
1038 hbb->append_insn (new hsa_insn_cvt (dest, this));
1040 else if (is_a <hsa_op_reg *> (this))
1042 /* In the end, HSA registers do not really have types, only sizes, so if
1043 the sizes match, we can use the register directly. */
1044 gcc_checking_assert (hsa_type_bit_size (dtype)
1045 == hsa_type_bit_size (m_type));
1046 return this;
1048 else
1050 dest = new hsa_op_reg (m_type);
1051 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV,
1052 dest->m_type, dest, this));
1054 /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
1055 type of the operand must be same as type of the instruction. */
1056 dest->m_type = dtype;
1059 return dest;
1062 /* Constructor of class representing HSA immediate values. TREE_VAL is the
1063 tree representation of the immediate value. If min32int is true,
1064 always expand integer types to one that has at least 32 bits. */
1066 hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
1067 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
1068 hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
1069 min32int))
1071 if (hsa_seen_error ())
1072 return;
1074 gcc_checking_assert ((is_gimple_min_invariant (tree_val)
1075 && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
1076 || TREE_CODE (tree_val) == INTEGER_CST))
1077 || TREE_CODE (tree_val) == CONSTRUCTOR);
1078 m_tree_value = tree_val;
1080 /* Verify that all elements of a constructor are constants. */
1081 if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
1082 for (unsigned i = 0; i < CONSTRUCTOR_NELTS (m_tree_value); i++)
1084 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
1085 if (!CONSTANT_CLASS_P (v))
1087 HSA_SORRY_AT (EXPR_LOCATION (tree_val),
1088 "HSA ctor should have only constants");
1089 return;
1094 /* Constructor of class representing HSA immediate values. INTEGER_VALUE is the
1095 integer representation of the immediate value. TYPE is BRIG type. */
1097 hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
1098 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
1099 m_tree_value (NULL)
1101 gcc_assert (hsa_type_integer_p (type));
1102 m_int_value = integer_value;
1105 hsa_op_immed::hsa_op_immed ()
1106 : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
1110 /* New operator to allocate immediate operands from obstack. */
1112 void *
1113 hsa_op_immed::operator new (size_t size)
1115 return obstack_alloc (&hsa_obstack, size);
1118 /* Destructor. */
1120 hsa_op_immed::~hsa_op_immed ()
1124 /* Change type of the immediate value to T. */
1126 void
1127 hsa_op_immed::set_type (BrigType16_t t)
1129 m_type = t;
1132 /* Constructor of class representing HSA registers and pseudo-registers. T is
1133 the BRIG type of the new register. */
1135 hsa_op_reg::hsa_op_reg (BrigType16_t t)
1136 : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
1137 m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
1138 m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
1142 /* New operator to allocate a register from obstack. */
1144 void *
1145 hsa_op_reg::operator new (size_t size)
1147 return obstack_alloc (&hsa_obstack, size);
1150 /* Verify register operand. */
1152 void
1153 hsa_op_reg::verify_ssa ()
1155 /* Verify that each HSA register has a definition assigned.
1156 Exceptions are VAR_DECL and PARM_DECL that are a default
1157 definition. */
1158 gcc_checking_assert (m_def_insn
1159 || (m_gimple_ssa != NULL
1160 && (!SSA_NAME_VAR (m_gimple_ssa)
1161 || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
1162 != PARM_DECL))
1163 && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
1165 /* Verify that every use of the register is really present
1166 in an instruction. */
1167 for (unsigned i = 0; i < m_uses.length (); i++)
1169 hsa_insn_basic *use = m_uses[i];
1171 bool is_visited = false;
1172 for (unsigned j = 0; j < use->operand_count (); j++)
1174 hsa_op_base *u = use->get_op (j);
1175 hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
1176 if (addr && addr->m_reg)
1177 u = addr->m_reg;
1179 if (u == this)
1181 bool r = !addr && use->op_output_p (j);
1183 if (r)
1185 error ("HSA SSA name defined by instruction that is supposed "
1186 "to be using it");
1187 debug_hsa_operand (this);
1188 debug_hsa_insn (use);
1189 internal_error ("HSA SSA verification failed");
1192 is_visited = true;
1196 if (!is_visited)
1198 error ("HSA SSA name not among operands of instruction that is "
1199 "supposed to use it");
1200 debug_hsa_operand (this);
1201 debug_hsa_insn (use);
1202 internal_error ("HSA SSA verification failed");
1207 hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
1208 HOST_WIDE_INT offset)
1209 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
1210 m_imm_offset (offset)
1214 hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
1215 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
1216 m_imm_offset (offset)
1220 hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
1221 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
1222 m_imm_offset (offset)
1226 /* New operator to allocate address operands from obstack. */
1228 void *
1229 hsa_op_address::operator new (size_t size)
1231 return obstack_alloc (&hsa_obstack, size);
1234 /* Constructor of an operand referring to HSAIL code. */
1236 hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
1237 m_directive_offset (0)
1241 /* Constructor of an operand representing a code list. Set it up so that it
1242 can contain ELEMENTS number of elements. */
1244 hsa_op_code_list::hsa_op_code_list (unsigned elements)
1245 : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
1247 m_offsets.create (1);
1248 m_offsets.safe_grow_cleared (elements);
1251 /* New operator to allocate code list operands from obstack. */
1253 void *
1254 hsa_op_code_list::operator new (size_t size)
1256 return obstack_alloc (&hsa_obstack, size);
1259 /* Constructor of an operand representing an operand list.
1260 Set it up so that it can contain ELEMENTS number of elements. */
1262 hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
1263 : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
1265 m_offsets.create (elements);
1266 m_offsets.safe_grow (elements);
1269 /* New operator to allocate operand list operands from obstack. */
1271 void *
1272 hsa_op_operand_list::operator new (size_t size)
1274 return obstack_alloc (&hsa_obstack, size);
1277 hsa_op_operand_list::~hsa_op_operand_list ()
1279 m_offsets.release ();
1283 hsa_op_reg *
1284 hsa_function_representation::reg_for_gimple_ssa (tree ssa)
1286 hsa_op_reg *hreg;
1288 gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
1289 if (m_ssa_map[SSA_NAME_VERSION (ssa)])
1290 return m_ssa_map[SSA_NAME_VERSION (ssa)];
1292 hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
1293 true));
1294 hreg->m_gimple_ssa = ssa;
1295 m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
1297 return hreg;
1300 void
1301 hsa_op_reg::set_definition (hsa_insn_basic *insn)
1303 if (hsa_cfun->m_in_ssa)
1305 gcc_checking_assert (!m_def_insn);
1306 m_def_insn = insn;
1308 else
1309 m_def_insn = NULL;
1312 /* Constructor of the class which is the bases of all instructions and directly
1313 represents the most basic ones. NOPS is the number of operands that the
1314 operand vector will contain (and which will be cleared). OP is the opcode
1315 of the instruction. This constructor does not set type. */
1317 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
1318 : m_prev (NULL),
1319 m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
1320 m_type (BRIG_TYPE_NONE), m_brig_offset (0)
1322 if (nops > 0)
1323 m_operands.safe_grow_cleared (nops);
1325 hsa_instructions.safe_push (this);
1328 /* Make OP the operand number INDEX of operands of this instruction. If OP is a
1329 register or an address containing a register, then either set the definition
1330 of the register to this instruction if it an output operand or add this
1331 instruction to the uses if it is an input one. */
1333 void
1334 hsa_insn_basic::set_op (int index, hsa_op_base *op)
1336 /* Each address operand is always use. */
1337 hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
1338 if (addr && addr->m_reg)
1339 addr->m_reg->m_uses.safe_push (this);
1340 else
1342 hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
1343 if (reg)
1345 if (op_output_p (index))
1346 reg->set_definition (this);
1347 else
1348 reg->m_uses.safe_push (this);
1352 m_operands[index] = op;
1355 /* Get INDEX-th operand of the instruction. */
1357 hsa_op_base *
1358 hsa_insn_basic::get_op (int index)
1360 return m_operands[index];
1363 /* Get address of INDEX-th operand of the instruction. */
1365 hsa_op_base **
1366 hsa_insn_basic::get_op_addr (int index)
1368 return &m_operands[index];
1371 /* Get number of operands of the instruction. */
1372 unsigned int
1373 hsa_insn_basic::operand_count ()
1375 return m_operands.length ();
1378 /* Constructor of the class which is the bases of all instructions and directly
1379 represents the most basic ones. NOPS is the number of operands that the
1380 operand vector will contain (and which will be cleared). OPC is the opcode
1381 of the instruction, T is the type of the instruction. */
1383 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
1384 hsa_op_base *arg0, hsa_op_base *arg1,
1385 hsa_op_base *arg2, hsa_op_base *arg3)
1386 : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
1387 m_type (t), m_brig_offset (0)
1389 if (nops > 0)
1390 m_operands.safe_grow_cleared (nops);
1392 if (arg0 != NULL)
1394 gcc_checking_assert (nops >= 1);
1395 set_op (0, arg0);
1398 if (arg1 != NULL)
1400 gcc_checking_assert (nops >= 2);
1401 set_op (1, arg1);
1404 if (arg2 != NULL)
1406 gcc_checking_assert (nops >= 3);
1407 set_op (2, arg2);
1410 if (arg3 != NULL)
1412 gcc_checking_assert (nops >= 4);
1413 set_op (3, arg3);
1416 hsa_instructions.safe_push (this);
1419 /* New operator to allocate basic instruction from obstack. */
1421 void *
1422 hsa_insn_basic::operator new (size_t size)
1424 return obstack_alloc (&hsa_obstack, size);
1427 /* Verify the instruction. */
1429 void
1430 hsa_insn_basic::verify ()
1432 hsa_op_address *addr;
1433 hsa_op_reg *reg;
1435 /* Iterate all register operands and verify that the instruction
1436 is set in uses of the register. */
1437 for (unsigned i = 0; i < operand_count (); i++)
1439 hsa_op_base *use = get_op (i);
1441 if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
1443 gcc_assert (addr->m_reg->m_def_insn != this);
1444 use = addr->m_reg;
1447 if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
1449 unsigned j;
1450 for (j = 0; j < reg->m_uses.length (); j++)
1452 if (reg->m_uses[j] == this)
1453 break;
1456 if (j == reg->m_uses.length ())
1458 error ("HSA instruction uses a register but is not among "
1459 "recorded register uses");
1460 debug_hsa_operand (reg);
1461 debug_hsa_insn (this);
1462 internal_error ("HSA instruction verification failed");
1468 /* Constructor of an instruction representing a PHI node. NOPS is the number
1469 of operands (equal to the number of predecessors). */
1471 hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
1472 : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
1474 dst->set_definition (this);
1477 /* Constructor of class representing instructions for control flow and
1478 sychronization, */
1480 hsa_insn_br::hsa_insn_br (unsigned nops, int opc, BrigType16_t t,
1481 BrigWidth8_t width, hsa_op_base *arg0,
1482 hsa_op_base *arg1, hsa_op_base *arg2,
1483 hsa_op_base *arg3)
1484 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1485 m_width (width)
1489 /* Constructor of class representing instruction for conditional jump, CTRL is
1490 the control register determining whether the jump will be carried out, the
1491 new instruction is automatically added to its uses list. */
1493 hsa_insn_cbr::hsa_insn_cbr (hsa_op_reg *ctrl)
1494 : hsa_insn_br (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, BRIG_WIDTH_1, ctrl)
1498 /* Constructor of class representing instruction for switch jump, CTRL is
1499 the index register. */
1501 hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
1502 : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
1503 m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
1504 m_label_code_list (new hsa_op_code_list (jump_count))
1508 /* Replace all occurrences of OLD_BB with NEW_BB in the statements
1509 jump table. */
1511 void
1512 hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
1514 for (unsigned i = 0; i < m_jump_table.length (); i++)
1515 if (m_jump_table[i] == old_bb)
1516 m_jump_table[i] = new_bb;
1519 hsa_insn_sbr::~hsa_insn_sbr ()
1521 m_jump_table.release ();
1524 /* Constructor of comparison instruction. CMP is the comparison operation and T
1525 is the result type. */
1527 hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
1528 hsa_op_base *arg0, hsa_op_base *arg1,
1529 hsa_op_base *arg2)
1530 : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
1534 /* Constructor of classes representing memory accesses. OPC is the opcode (must
1535 be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type. The instruction
1536 operands are provided as ARG0 and ARG1. */
1538 hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
1539 hsa_op_base *arg1)
1540 : hsa_insn_basic (2, opc, t, arg0, arg1),
1541 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1543 gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
1546 /* Constructor for descendants allowing different opcodes and number of
1547 operands, it passes its arguments directly to hsa_insn_basic
1548 constructor. The instruction operands are provided as ARG[0-3]. */
1551 hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
1552 hsa_op_base *arg0, hsa_op_base *arg1,
1553 hsa_op_base *arg2, hsa_op_base *arg3)
1554 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1555 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1559 /* Constructor of class representing atomic instructions. OPC is the principal
1560 opcode, AOP is the specific atomic operation opcode. T is the type of the
1561 instruction. The instruction operands are provided as ARG[0-3]. */
1563 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
1564 enum BrigAtomicOperation aop,
1565 BrigType16_t t, BrigMemoryOrder memorder,
1566 hsa_op_base *arg0,
1567 hsa_op_base *arg1, hsa_op_base *arg2,
1568 hsa_op_base *arg3)
1569 : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
1570 m_memoryorder (memorder),
1571 m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
1573 gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
1574 opc == BRIG_OPCODE_ATOMIC ||
1575 opc == BRIG_OPCODE_SIGNAL ||
1576 opc == BRIG_OPCODE_SIGNALNORET);
1579 /* Constructor of class representing signal instructions. OPC is the prinicpal
1580 opcode, SOP is the specific signal operation opcode. T is the type of the
1581 instruction. The instruction operands are provided as ARG[0-3]. */
1583 hsa_insn_signal::hsa_insn_signal (int nops, int opc,
1584 enum BrigAtomicOperation sop,
1585 BrigType16_t t, BrigMemoryOrder memorder,
1586 hsa_op_base *arg0, hsa_op_base *arg1,
1587 hsa_op_base *arg2, hsa_op_base *arg3)
1588 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1589 m_memory_order (memorder), m_signalop (sop)
1593 /* Constructor of class representing segment conversion instructions. OPC is
1594 the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS. DEST
1595 and SRCT are destination and source types respectively, SEG is the segment
1596 we are converting to or from. The instruction operands are
1597 provided as ARG0 and ARG1. */
1599 hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
1600 BrigSegment8_t seg, hsa_op_base *arg0,
1601 hsa_op_base *arg1)
1602 : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
1603 m_segment (seg)
1605 gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
1608 /* Constructor of class representing a call instruction. CALLEE is the tree
1609 representation of the function being called. */
1611 hsa_insn_call::hsa_insn_call (tree callee)
1612 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
1613 m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
1617 hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
1618 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
1619 m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
1620 m_result_code_list (NULL)
1624 hsa_insn_call::~hsa_insn_call ()
1626 for (unsigned i = 0; i < m_input_args.length (); i++)
1627 delete m_input_args[i];
1629 delete m_output_arg;
1631 m_input_args.release ();
1632 m_input_arg_insns.release ();
1635 /* Constructor of class representing the argument block required to invoke
1636 a call in HSAIL. */
1637 hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
1638 hsa_insn_call * call)
1639 : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
1640 m_call_insn (call)
1644 hsa_insn_comment::hsa_insn_comment (const char *s)
1645 : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
1647 unsigned l = strlen (s);
1649 /* Append '// ' to the string. */
1650 char *buf = XNEWVEC (char, l + 4);
1651 sprintf (buf, "// %s", s);
1652 m_comment = buf;
1655 hsa_insn_comment::~hsa_insn_comment ()
1657 gcc_checking_assert (m_comment);
1658 free (m_comment);
1659 m_comment = NULL;
1662 /* Constructor of class representing the queue instruction in HSAIL. */
1664 hsa_insn_queue::hsa_insn_queue (int nops, int opcode, BrigSegment segment,
1665 BrigMemoryOrder memory_order,
1666 hsa_op_base *arg0, hsa_op_base *arg1,
1667 hsa_op_base *arg2, hsa_op_base *arg3)
1668 : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64, arg0, arg1, arg2, arg3),
1669 m_segment (segment), m_memory_order (memory_order)
1673 /* Constructor of class representing the source type instruction in HSAIL. */
1675 hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
1676 BrigType16_t destt, BrigType16_t srct,
1677 hsa_op_base *arg0, hsa_op_base *arg1,
1678 hsa_op_base *arg2 = NULL)
1679 : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
1680 m_source_type (srct)
1683 /* Constructor of class representing the packed instruction in HSAIL. */
1685 hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
1686 BrigType16_t destt, BrigType16_t srct,
1687 hsa_op_base *arg0, hsa_op_base *arg1,
1688 hsa_op_base *arg2)
1689 : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
1691 m_operand_list = new hsa_op_operand_list (nops - 1);
1694 /* Constructor of class representing the convert instruction in HSAIL. */
1696 hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
1697 : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
1701 /* Constructor of class representing the alloca in HSAIL. */
1703 hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
1704 hsa_op_with_type *size, unsigned alignment)
1705 : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
1706 m_align (BRIG_ALIGNMENT_8)
1708 gcc_assert (dest->m_type == BRIG_TYPE_U32);
1709 if (alignment)
1710 m_align = hsa_alignment_encoding (alignment);
1713 /* Append an instruction INSN into the basic block. */
1715 void
1716 hsa_bb::append_insn (hsa_insn_basic *insn)
1718 gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
1719 gcc_assert (!insn->m_bb);
1721 insn->m_bb = m_bb;
1722 insn->m_prev = m_last_insn;
1723 insn->m_next = NULL;
1724 if (m_last_insn)
1725 m_last_insn->m_next = insn;
1726 m_last_insn = insn;
1727 if (!m_first_insn)
1728 m_first_insn = insn;
1731 void
1732 hsa_bb::append_phi (hsa_insn_phi *hphi)
1734 hphi->m_bb = m_bb;
1736 hphi->m_prev = m_last_phi;
1737 hphi->m_next = NULL;
1738 if (m_last_phi)
1739 m_last_phi->m_next = hphi;
1740 m_last_phi = hphi;
1741 if (!m_first_phi)
1742 m_first_phi = hphi;
1745 /* Insert HSA instruction NEW_INSN immediately before an existing instruction
1746 OLD_INSN. */
1748 static void
1749 hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1751 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1753 if (hbb->m_first_insn == old_insn)
1754 hbb->m_first_insn = new_insn;
1755 new_insn->m_prev = old_insn->m_prev;
1756 new_insn->m_next = old_insn;
1757 if (old_insn->m_prev)
1758 old_insn->m_prev->m_next = new_insn;
1759 old_insn->m_prev = new_insn;
1762 /* Append HSA instruction NEW_INSN immediately after an existing instruction
1763 OLD_INSN. */
1765 static void
1766 hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1768 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1770 if (hbb->m_last_insn == old_insn)
1771 hbb->m_last_insn = new_insn;
1772 new_insn->m_prev = old_insn;
1773 new_insn->m_next = old_insn->m_next;
1774 if (old_insn->m_next)
1775 old_insn->m_next->m_prev = new_insn;
1776 old_insn->m_next = new_insn;
1779 /* Return a register containing the calculated value of EXP which must be an
1780 expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
1781 integer constants as returned by get_inner_reference.
1782 Newly generated HSA instructions will be appended to HBB.
1783 Perform all calculations in ADDRTYPE. */
1785 static hsa_op_with_type *
1786 gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
1788 int opcode;
1790 if (TREE_CODE (exp) == NOP_EXPR)
1791 exp = TREE_OPERAND (exp, 0);
1793 switch (TREE_CODE (exp))
1795 case SSA_NAME:
1796 return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
1798 case INTEGER_CST:
1800 hsa_op_immed *imm = new hsa_op_immed (exp);
1801 if (addrtype != imm->m_type)
1802 imm->m_type = addrtype;
1803 return imm;
1806 case PLUS_EXPR:
1807 opcode = BRIG_OPCODE_ADD;
1808 break;
1810 case MULT_EXPR:
1811 opcode = BRIG_OPCODE_MUL;
1812 break;
1814 default:
1815 gcc_unreachable ();
1818 hsa_op_reg *res = new hsa_op_reg (addrtype);
1819 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
1820 insn->set_op (0, res);
1822 hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
1823 addrtype);
1824 hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
1825 addrtype);
1826 insn->set_op (1, op1);
1827 insn->set_op (2, op2);
1829 hbb->append_insn (insn);
1830 return res;
1833 /* If R1 is NULL, just return R2, otherwise append an instruction adding them
1834 to HBB and return the register holding the result. */
1836 static hsa_op_reg *
1837 add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
1839 gcc_checking_assert (r2);
1840 if (!r1)
1841 return r2;
1843 hsa_op_reg *res = new hsa_op_reg (r1->m_type);
1844 gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
1845 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
1846 insn->set_op (0, res);
1847 insn->set_op (1, r1);
1848 insn->set_op (2, r2);
1849 hbb->append_insn (insn);
1850 return res;
1853 /* Helper of gen_hsa_addr. Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
1854 reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF. */
1856 static void
1857 process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
1858 hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
1860 if (TREE_CODE (base) == SSA_NAME)
1862 gcc_assert (!*reg);
1863 hsa_op_with_type *ssa
1864 = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
1865 *reg = dyn_cast <hsa_op_reg *> (ssa);
1867 else if (TREE_CODE (base) == ADDR_EXPR)
1869 tree decl = TREE_OPERAND (base, 0);
1871 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
1873 HSA_SORRY_AT (EXPR_LOCATION (base),
1874 "support for HSA does not implement a memory reference "
1875 "to a non-declaration type");
1876 return;
1879 gcc_assert (!*symbol);
1881 *symbol = get_symbol_for_decl (decl);
1882 *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
1884 else if (TREE_CODE (base) == INTEGER_CST)
1885 *offset += wi::to_offset (base);
1886 else
1887 gcc_unreachable ();
1890 /* Forward declaration of a function. */
1892 static void
1893 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
1895 /* Generate HSA address operand for a given tree memory reference REF. If
1896 instructions need to be created to calculate the address, they will be added
1897 to the end of HBB. If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
1898 the function assumes that the caller will handle possible
1899 bit-field references. Otherwise if we reference a bit-field, sorry message
1900 is displayed. */
1902 static hsa_op_address *
1903 gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
1904 HOST_WIDE_INT *output_bitpos = NULL)
1906 hsa_symbol *symbol = NULL;
1907 hsa_op_reg *reg = NULL;
1908 offset_int offset = 0;
1909 tree origref = ref;
1910 tree varoffset = NULL_TREE;
1911 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1912 HOST_WIDE_INT bitsize = 0, bitpos = 0;
1913 BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1915 if (TREE_CODE (ref) == STRING_CST)
1917 symbol = hsa_get_string_cst_symbol (ref);
1918 goto out;
1920 else if (TREE_CODE (ref) == BIT_FIELD_REF
1921 && ((tree_to_uhwi (TREE_OPERAND (ref, 1)) % BITS_PER_UNIT) != 0
1922 || (tree_to_uhwi (TREE_OPERAND (ref, 2)) % BITS_PER_UNIT) != 0))
1924 HSA_SORRY_ATV (EXPR_LOCATION (origref),
1925 "support for HSA does not implement "
1926 "bit field references such as %E", ref);
1927 goto out;
1930 if (handled_component_p (ref))
1932 enum machine_mode mode;
1933 int unsignedp, volatilep, preversep;
1935 ref = get_inner_reference (ref, &bitsize, &bitpos, &varoffset, &mode,
1936 &unsignedp, &preversep, &volatilep);
1938 offset = bitpos;
1939 offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
1942 switch (TREE_CODE (ref))
1944 case ADDR_EXPR:
1946 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
1947 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
1948 hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
1949 gen_hsa_addr_insns (ref, r, hbb);
1950 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
1951 r, new hsa_op_address (symbol)));
1953 break;
1955 case SSA_NAME:
1957 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
1958 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
1959 hsa_op_reg *r = hsa_cfun->reg_for_gimple_ssa (ref);
1961 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
1962 r, new hsa_op_address (symbol)));
1964 break;
1966 case PARM_DECL:
1967 case VAR_DECL:
1968 case RESULT_DECL:
1969 case CONST_DECL:
1970 gcc_assert (!symbol);
1971 symbol = get_symbol_for_decl (ref);
1972 addrtype = hsa_get_segment_addr_type (symbol->m_segment);
1973 break;
1975 case MEM_REF:
1976 process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
1977 &offset, hbb);
1979 if (!integer_zerop (TREE_OPERAND (ref, 1)))
1980 offset += wi::to_offset (TREE_OPERAND (ref, 1));
1981 break;
1983 case TARGET_MEM_REF:
1984 process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
1985 if (TMR_INDEX (ref))
1987 hsa_op_reg *disp1;
1988 hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
1989 (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
1990 if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
1992 disp1 = new hsa_op_reg (addrtype);
1993 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
1994 addrtype);
1996 /* As step must respect addrtype, we overwrite the type
1997 of an immediate value. */
1998 hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
1999 step->m_type = addrtype;
2001 insn->set_op (0, disp1);
2002 insn->set_op (1, idx);
2003 insn->set_op (2, step);
2004 hbb->append_insn (insn);
2006 else
2007 disp1 = as_a <hsa_op_reg *> (idx);
2008 reg = add_addr_regs_if_needed (reg, disp1, hbb);
2010 if (TMR_INDEX2 (ref))
2012 if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
2014 hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
2015 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
2016 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
2017 hbb);
2019 else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
2020 offset += wi::to_offset (TMR_INDEX2 (ref));
2021 else
2022 gcc_unreachable ();
2024 offset += wi::to_offset (TMR_OFFSET (ref));
2025 break;
2026 case FUNCTION_DECL:
2027 HSA_SORRY_AT (EXPR_LOCATION (origref),
2028 "support for HSA does not implement function pointers");
2029 goto out;
2030 default:
2031 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
2032 "not implement memory access to %E", origref);
2033 goto out;
2036 if (varoffset)
2038 if (TREE_CODE (varoffset) == INTEGER_CST)
2039 offset += wi::to_offset (varoffset);
2040 else
2042 hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
2043 addrtype);
2044 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
2045 hbb);
2049 gcc_checking_assert ((symbol
2050 && addrtype
2051 == hsa_get_segment_addr_type (symbol->m_segment))
2052 || (!symbol
2053 && addrtype
2054 == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
2055 out:
2056 HOST_WIDE_INT hwi_offset = offset.to_shwi ();
2058 /* Calculate remaining bitsize offset (if presented). */
2059 bitpos %= BITS_PER_UNIT;
2060 /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
2061 is not a reason to think this is a bit-field access. */
2062 if (bitpos == 0
2063 && (bitsize >= BITS_PER_UNIT)
2064 && !(bitsize & (bitsize - 1)))
2065 bitsize = 0;
2067 if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
2068 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
2069 "implement unhandled bit field reference such as %E", ref);
2071 if (output_bitsize != NULL && output_bitpos != NULL)
2073 *output_bitsize = bitsize;
2074 *output_bitpos = bitpos;
2077 return new hsa_op_address (symbol, reg, hwi_offset);
2080 /* Generate HSA address operand for a given tree memory reference REF. If
2081 instructions need to be created to calculate the address, they will be added
2082 to the end of HBB. OUTPUT_ALIGN is alignment of the created address. */
2084 static hsa_op_address *
2085 gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
2087 hsa_op_address *addr = gen_hsa_addr (ref, hbb);
2088 if (addr->m_reg || !addr->m_symbol)
2089 *output_align = hsa_object_alignment (ref);
2090 else
2092 /* If the address consists only of a symbol and an offset, we
2093 compute the alignment ourselves to take into account any alignment
2094 promotions we might have done for the HSA symbol representation. */
2095 unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
2096 unsigned misalign = addr->m_imm_offset & (align - 1);
2097 if (misalign)
2098 align = least_bit_hwi (misalign);
2099 *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
2101 return addr;
2104 /* Generate HSA address for a function call argument of given TYPE.
2105 INDEX is used to generate corresponding name of the arguments.
2106 Special value -1 represents fact that result value is created. */
2108 static hsa_op_address *
2109 gen_hsa_addr_for_arg (tree tree_type, int index)
2111 hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
2112 BRIG_LINKAGE_ARG);
2113 sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
2115 if (index == -1) /* Function result. */
2116 sym->m_name = "res";
2117 else /* Function call arguments. */
2119 sym->m_name = NULL;
2120 sym->m_name_number = index;
2123 return new hsa_op_address (sym);
2126 /* Generate HSA instructions that process all necessary conversions
2127 of an ADDR to flat addressing and place the result into DEST.
2128 Instructions are appended to HBB. */
2130 static void
2131 convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
2132 hsa_bb *hbb)
2134 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
2135 insn->set_op (1, addr);
2136 if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
2138 /* LDA produces segment-relative address, we need to convert
2139 it to the flat one. */
2140 hsa_op_reg *tmp;
2141 tmp = new hsa_op_reg (hsa_get_segment_addr_type
2142 (addr->m_symbol->m_segment));
2143 hsa_insn_seg *seg;
2144 seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
2145 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
2146 tmp->m_type, addr->m_symbol->m_segment, dest,
2147 tmp);
2149 insn->set_op (0, tmp);
2150 insn->m_type = tmp->m_type;
2151 hbb->append_insn (insn);
2152 hbb->append_insn (seg);
2154 else
2156 insn->set_op (0, dest);
2157 insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2158 hbb->append_insn (insn);
2162 /* Generate HSA instructions that calculate address of VAL including all
2163 necessary conversions to flat addressing and place the result into DEST.
2164 Instructions are appended to HBB. */
2166 static void
2167 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
2169 /* Handle cases like tmp = NULL, where we just emit a move instruction
2170 to a register. */
2171 if (TREE_CODE (val) == INTEGER_CST)
2173 hsa_op_immed *c = new hsa_op_immed (val);
2174 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2175 dest->m_type, dest, c);
2176 hbb->append_insn (insn);
2177 return;
2180 hsa_op_address *addr;
2182 gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2183 if (TREE_CODE (val) == ADDR_EXPR)
2184 val = TREE_OPERAND (val, 0);
2185 addr = gen_hsa_addr (val, hbb);
2187 if (TREE_CODE (val) == CONST_DECL
2188 && is_gimple_reg_type (TREE_TYPE (val)))
2190 gcc_assert (addr->m_symbol
2191 && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY);
2192 /* CONST_DECLs are in readonly segment which however does not have
2193 addresses convertible to flat segments. So copy it to a private one
2194 and take address of that. */
2195 BrigType16_t csttype
2196 = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (val),
2197 false));
2198 hsa_op_reg *r = new hsa_op_reg (csttype);
2199 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, csttype, r,
2200 new hsa_op_address (addr->m_symbol)));
2201 hsa_symbol *copysym = hsa_cfun->create_hsa_temporary (csttype);
2202 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, csttype, r,
2203 new hsa_op_address (copysym)));
2204 addr->m_symbol = copysym;
2206 else if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY)
2208 HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
2209 "not implement taking addresses of complex "
2210 "CONST_DECLs such as %E", val);
2211 return;
2215 convert_addr_to_flat_segment (addr, dest, hbb);
2218 /* Return an HSA register or HSA immediate value operand corresponding to
2219 gimple operand OP. */
2221 static hsa_op_with_type *
2222 hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
2224 hsa_op_reg *tmp;
2226 if (TREE_CODE (op) == SSA_NAME)
2227 tmp = hsa_cfun->reg_for_gimple_ssa (op);
2228 else if (!POINTER_TYPE_P (TREE_TYPE (op)))
2229 return new hsa_op_immed (op);
2230 else
2232 tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2233 gen_hsa_addr_insns (op, tmp, hbb);
2235 return tmp;
2238 /* Create a simple movement instruction with register destination DEST and
2239 register or immediate source SRC and append it to the end of HBB. */
2241 void
2242 hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
2244 /* Moves of packed data between registers need to adhere to the same type
2245 rules like when dealing with memory. */
2246 BrigType16_t tp = mem_type_for_type (dest->m_type);
2247 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, tp, dest, src);
2248 if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
2249 gcc_assert (hsa_type_bit_size (dest->m_type)
2250 == hsa_type_bit_size (sreg->m_type));
2251 else
2252 gcc_assert (hsa_type_bit_size (dest->m_type)
2253 == hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type));
2255 hbb->append_insn (insn);
2258 /* Generate HSAIL instructions loading a bit field into register DEST.
2259 VALUE_REG is a register of a SSA name that is used in the bit field
2260 reference. To identify a bit field BITPOS is offset to the loaded memory
2261 and BITSIZE is number of bits of the bit field.
2262 Add instructions to HBB. */
2264 static void
2265 gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
2266 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2267 hsa_bb *hbb)
2269 unsigned type_bitsize = hsa_type_bit_size (dest->m_type);
2270 unsigned left_shift = type_bitsize - (bitsize + bitpos);
2271 unsigned right_shift = left_shift + bitpos;
2273 if (left_shift)
2275 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2276 hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
2278 hsa_insn_basic *lshift
2279 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
2280 value_reg_2, value_reg, c);
2282 hbb->append_insn (lshift);
2284 value_reg = value_reg_2;
2287 if (right_shift)
2289 hsa_op_reg *value_reg_2 = new hsa_op_reg (dest->m_type);
2290 hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
2292 hsa_insn_basic *rshift
2293 = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
2294 value_reg_2, value_reg, c);
2296 hbb->append_insn (rshift);
2298 value_reg = value_reg_2;
2301 hsa_insn_basic *assignment
2302 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, dest, value_reg);
2303 hbb->append_insn (assignment);
2307 /* Generate HSAIL instructions loading a bit field into register DEST. ADDR is
2308 prepared memory address which is used to load the bit field. To identify a
2309 bit field BITPOS is offset to the loaded memory and BITSIZE is number of
2310 bits of the bit field. Add instructions to HBB. Load must be performed in
2311 alignment ALIGN. */
2313 static void
2314 gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
2315 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2316 hsa_bb *hbb, BrigAlignment8_t align)
2318 hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
2319 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, dest->m_type, value_reg,
2320 addr);
2321 mem->set_align (align);
2322 hbb->append_insn (mem);
2323 gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
2326 /* Return the alignment of base memory accesses we issue to perform bit-field
2327 memory access REF. */
2329 static BrigAlignment8_t
2330 hsa_bitmemref_alignment (tree ref)
2332 unsigned HOST_WIDE_INT bit_offset = 0;
2334 while (true)
2336 if (TREE_CODE (ref) == BIT_FIELD_REF)
2338 if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
2339 return BRIG_ALIGNMENT_1;
2340 bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
2342 else if (TREE_CODE (ref) == COMPONENT_REF
2343 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
2344 bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
2345 else
2346 break;
2347 ref = TREE_OPERAND (ref, 0);
2350 unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
2351 unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
2352 BrigAlignment8_t base = hsa_object_alignment (ref);
2353 if (byte_bits == 0)
2354 return base;
2355 return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
2358 /* Generate HSAIL instructions loading something into register DEST. RHS is
2359 tree representation of the loaded data, which are loaded as type TYPE. Add
2360 instructions to HBB. */
2362 static void
2363 gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
2365 /* The destination SSA name will give us the type. */
2366 if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
2367 rhs = TREE_OPERAND (rhs, 0);
2369 if (TREE_CODE (rhs) == SSA_NAME)
2371 hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
2372 hsa_build_append_simple_mov (dest, src, hbb);
2374 else if (is_gimple_min_invariant (rhs)
2375 || TREE_CODE (rhs) == ADDR_EXPR)
2377 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
2379 if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
2381 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2382 "support for HSA does not implement conversion "
2383 "of %E to the requested non-pointer type.", rhs);
2384 return;
2387 gen_hsa_addr_insns (rhs, dest, hbb);
2389 else if (TREE_CODE (rhs) == COMPLEX_CST)
2391 hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
2392 hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
2394 hsa_op_reg *real_part_reg
2395 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2396 true));
2397 hsa_op_reg *imag_part_reg
2398 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2399 true));
2401 hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
2402 hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
2404 BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
2406 hsa_insn_packed *insn
2407 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
2408 src_type, dest, real_part_reg,
2409 imag_part_reg);
2410 hbb->append_insn (insn);
2412 else
2414 hsa_op_immed *imm = new hsa_op_immed (rhs);
2415 hsa_build_append_simple_mov (dest, imm, hbb);
2418 else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
2420 tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
2422 hsa_op_reg *packed_reg
2423 = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
2425 tree complex_rhs = TREE_OPERAND (rhs, 0);
2426 gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
2427 hbb);
2429 hsa_op_reg *real_reg
2430 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2432 hsa_op_reg *imag_reg
2433 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2435 BrigKind16_t brig_type = packed_reg->m_type;
2436 hsa_insn_packed *packed
2437 = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
2438 hsa_bittype_for_type (real_reg->m_type),
2439 brig_type, real_reg, imag_reg, packed_reg);
2441 hbb->append_insn (packed);
2443 hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
2444 real_reg : imag_reg;
2446 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2447 dest->m_type, dest, source);
2449 hbb->append_insn (insn);
2451 else if (TREE_CODE (rhs) == BIT_FIELD_REF
2452 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
2454 tree ssa_name = TREE_OPERAND (rhs, 0);
2455 HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
2456 HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
2458 hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
2459 gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
2461 else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
2462 || TREE_CODE (rhs) == TARGET_MEM_REF
2463 || handled_component_p (rhs))
2465 HOST_WIDE_INT bitsize, bitpos;
2467 /* Load from memory. */
2468 hsa_op_address *addr;
2469 addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
2471 /* Handle load of a bit field. */
2472 if (bitsize > 64)
2474 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2475 "support for HSA does not implement load from a bit "
2476 "field bigger than 64 bits");
2477 return;
2480 if (bitsize || bitpos)
2481 gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
2482 hsa_bitmemref_alignment (rhs));
2483 else
2485 BrigType16_t mtype;
2486 /* Not dest->m_type, that's possibly extended. */
2487 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
2488 false));
2489 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
2490 addr);
2491 mem->set_align (hsa_object_alignment (rhs));
2492 hbb->append_insn (mem);
2495 else
2496 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2497 "support for HSA does not implement loading "
2498 "of expression %E",
2499 rhs);
2502 /* Return number of bits necessary for representation of a bit field,
2503 starting at BITPOS with size of BITSIZE. */
2505 static unsigned
2506 get_bitfield_size (unsigned bitpos, unsigned bitsize)
2508 unsigned s = bitpos + bitsize;
2509 unsigned sizes[] = {8, 16, 32, 64};
2511 for (unsigned i = 0; i < 4; i++)
2512 if (s <= sizes[i])
2513 return sizes[i];
2515 gcc_unreachable ();
2516 return 0;
2519 /* Generate HSAIL instructions storing into memory. LHS is the destination of
2520 the store, SRC is the source operand. Add instructions to HBB. */
2522 static void
2523 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
2525 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2526 BrigAlignment8_t req_align;
2527 BrigType16_t mtype;
2528 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
2529 false));
2530 hsa_op_address *addr;
2531 addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
2533 /* Handle store to a bit field. */
2534 if (bitsize > 64)
2536 HSA_SORRY_AT (EXPR_LOCATION (lhs),
2537 "support for HSA does not implement store to a bit field "
2538 "bigger than 64 bits");
2539 return;
2542 unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
2544 /* HSAIL does not support MOV insn with 16-bits integers. */
2545 if (type_bitsize < 32)
2546 type_bitsize = 32;
2548 if (bitpos || (bitsize && type_bitsize != bitsize))
2550 unsigned HOST_WIDE_INT mask = 0;
2551 BrigType16_t mem_type
2552 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
2553 !TYPE_UNSIGNED (TREE_TYPE (lhs)));
2555 for (unsigned i = 0; i < type_bitsize; i++)
2556 if (i < bitpos || i >= bitpos + bitsize)
2557 mask |= ((unsigned HOST_WIDE_INT)1 << i);
2559 hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
2561 req_align = hsa_bitmemref_alignment (lhs);
2562 /* Load value from memory. */
2563 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
2564 value_reg, addr);
2565 mem->set_align (req_align);
2566 hbb->append_insn (mem);
2568 /* AND the loaded value with prepared mask. */
2569 hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
2571 BrigType16_t t
2572 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
2573 hsa_op_immed *c = new hsa_op_immed (mask, t);
2575 hsa_insn_basic *clearing
2576 = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
2577 value_reg, c);
2578 hbb->append_insn (clearing);
2580 /* Shift to left a value that is going to be stored. */
2581 hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
2583 hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
2584 new_value_reg, src);
2585 hbb->append_insn (basic);
2587 if (bitpos)
2589 hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
2590 c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
2592 hsa_insn_basic *basic
2593 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
2594 shifted_value_reg, new_value_reg, c);
2595 hbb->append_insn (basic);
2597 new_value_reg = shifted_value_reg;
2600 /* OR the prepared value with prepared chunk loaded from memory. */
2601 hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
2602 basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
2603 new_value_reg, cleared_reg);
2604 hbb->append_insn (basic);
2606 src = prepared_reg;
2607 mtype = mem_type;
2609 else
2610 req_align = hsa_object_alignment (lhs);
2612 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
2613 mem->set_align (req_align);
2615 /* The HSAIL verifier has another constraint: if the source is an immediate
2616 then it must match the destination type. If it's a register the low bits
2617 will be used for sub-word stores. We're always allocating new operands so
2618 we can modify the above in place. */
2619 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
2621 if (!hsa_type_packed_p (imm->m_type))
2622 imm->m_type = mem->m_type;
2623 else
2625 /* ...and all vector immediates apparently need to be vectors of
2626 unsigned bytes. */
2627 unsigned bs = hsa_type_bit_size (imm->m_type);
2628 gcc_assert (bs == hsa_type_bit_size (mem->m_type));
2629 switch (bs)
2631 case 32:
2632 imm->m_type = BRIG_TYPE_U8X4;
2633 break;
2634 case 64:
2635 imm->m_type = BRIG_TYPE_U8X8;
2636 break;
2637 case 128:
2638 imm->m_type = BRIG_TYPE_U8X16;
2639 break;
2640 default:
2641 gcc_unreachable ();
2646 hbb->append_insn (mem);
2649 /* Generate memory copy instructions that are going to be used
2650 for copying a SRC memory to TARGET memory,
2651 represented by pointer in a register. MIN_ALIGN is minimal alignment
2652 of provided HSA addresses. */
2654 static void
2655 gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
2656 unsigned size, BrigAlignment8_t min_align)
2658 hsa_op_address *addr;
2659 hsa_insn_mem *mem;
2661 unsigned offset = 0;
2662 unsigned min_byte_align = hsa_byte_alignment (min_align);
2664 while (size)
2666 unsigned s;
2667 if (size >= 8)
2668 s = 8;
2669 else if (size >= 4)
2670 s = 4;
2671 else if (size >= 2)
2672 s = 2;
2673 else
2674 s = 1;
2676 if (s > min_byte_align)
2677 s = min_byte_align;
2679 BrigType16_t t = get_integer_type_by_bytes (s, false);
2681 hsa_op_reg *tmp = new hsa_op_reg (t);
2682 addr = new hsa_op_address (src->m_symbol, src->m_reg,
2683 src->m_imm_offset + offset);
2684 mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
2685 hbb->append_insn (mem);
2687 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2688 target->m_imm_offset + offset);
2689 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
2690 hbb->append_insn (mem);
2691 offset += s;
2692 size -= s;
2696 /* Create a memset mask that is created by copying a CONSTANT byte value
2697 to an integer of BYTE_SIZE bytes. */
2699 static unsigned HOST_WIDE_INT
2700 build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
2702 if (constant == 0)
2703 return 0;
2705 HOST_WIDE_INT v = constant;
2707 for (unsigned i = 1; i < byte_size; i++)
2708 v |= constant << (8 * i);
2710 return v;
2713 /* Generate memory set instructions that are going to be used
2714 for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
2715 MIN_ALIGN is minimal alignment of provided HSA addresses. */
2717 static void
2718 gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
2719 unsigned HOST_WIDE_INT constant,
2720 unsigned size, BrigAlignment8_t min_align)
2722 hsa_op_address *addr;
2723 hsa_insn_mem *mem;
2725 unsigned offset = 0;
2726 unsigned min_byte_align = hsa_byte_alignment (min_align);
2728 while (size)
2730 unsigned s;
2731 if (size >= 8)
2732 s = 8;
2733 else if (size >= 4)
2734 s = 4;
2735 else if (size >= 2)
2736 s = 2;
2737 else
2738 s = 1;
2740 if (s > min_byte_align)
2741 s = min_byte_align;
2743 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2744 target->m_imm_offset + offset);
2746 BrigType16_t t = get_integer_type_by_bytes (s, false);
2747 HOST_WIDE_INT c = build_memset_value (constant, s);
2749 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
2750 addr);
2751 hbb->append_insn (mem);
2752 offset += s;
2753 size -= s;
2757 /* Generate HSAIL instructions for a single assignment
2758 of an empty constructor to an ADDR_LHS. Constructor is passed as a
2759 tree RHS and all instructions are appended to HBB. ALIGN is
2760 alignment of the address. */
2762 void
2763 gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
2764 BrigAlignment8_t align)
2766 if (CONSTRUCTOR_NELTS (rhs))
2768 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2769 "support for HSA does not implement load from constructor");
2770 return;
2773 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2774 gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
2777 /* Generate HSA instructions for a single assignment of RHS to LHS.
2778 HBB is the basic block they will be appended to. */
2780 static void
2781 gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
2783 if (TREE_CODE (lhs) == SSA_NAME)
2785 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
2786 if (hsa_seen_error ())
2787 return;
2789 gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
2791 else if (TREE_CODE (rhs) == SSA_NAME
2792 || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
2794 /* Store to memory. */
2795 hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
2796 if (hsa_seen_error ())
2797 return;
2799 gen_hsa_insns_for_store (lhs, src, hbb);
2801 else
2803 BrigAlignment8_t lhs_align;
2804 hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
2805 &lhs_align);
2807 if (TREE_CODE (rhs) == CONSTRUCTOR)
2808 gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
2809 else
2811 BrigAlignment8_t rhs_align;
2812 hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
2813 &rhs_align);
2815 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2816 gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
2817 MIN (lhs_align, rhs_align));
2822 /* Prepend before INSN a load from spill symbol of SPILL_REG. Return the
2823 register into which we loaded. If this required another register to convert
2824 from a B1 type, return it in *PTMP2, otherwise store NULL into it. We
2825 assume we are out of SSA so the returned register does not have its
2826 definition set. */
2828 hsa_op_reg *
2829 hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2831 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2832 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2833 hsa_op_address *addr = new hsa_op_address (spill_sym);
2835 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
2836 reg, addr);
2837 hsa_insert_insn_before (mem, insn);
2839 *ptmp2 = NULL;
2840 if (spill_reg->m_type == BRIG_TYPE_B1)
2842 hsa_insn_basic *cvtinsn;
2843 *ptmp2 = reg;
2844 reg = new hsa_op_reg (spill_reg->m_type);
2846 cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
2847 hsa_insert_insn_before (cvtinsn, insn);
2849 return reg;
2852 /* Append after INSN a store to spill symbol of SPILL_REG. Return the register
2853 from which we stored. If this required another register to convert to a B1
2854 type, return it in *PTMP2, otherwise store NULL into it. We assume we are
2855 out of SSA so the returned register does not have its use updated. */
2857 hsa_op_reg *
2858 hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2860 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2861 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2862 hsa_op_address *addr = new hsa_op_address (spill_sym);
2863 hsa_op_reg *returnreg;
2865 *ptmp2 = NULL;
2866 returnreg = reg;
2867 if (spill_reg->m_type == BRIG_TYPE_B1)
2869 hsa_insn_basic *cvtinsn;
2870 *ptmp2 = new hsa_op_reg (spill_sym->m_type);
2871 reg->m_type = spill_reg->m_type;
2873 cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
2874 hsa_append_insn_after (cvtinsn, insn);
2875 insn = cvtinsn;
2876 reg = *ptmp2;
2879 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
2880 addr);
2881 hsa_append_insn_after (mem, insn);
2882 return returnreg;
2885 /* Generate a comparison instruction that will compare LHS and RHS with
2886 comparison specified by CODE and put result into register DEST. DEST has to
2887 have its type set already but must not have its definition set yet.
2888 Generated instructions will be added to HBB. */
2890 static void
2891 gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
2892 hsa_op_reg *dest, hsa_bb *hbb)
2894 BrigCompareOperation8_t compare;
2896 switch (code)
2898 case LT_EXPR:
2899 compare = BRIG_COMPARE_LT;
2900 break;
2901 case LE_EXPR:
2902 compare = BRIG_COMPARE_LE;
2903 break;
2904 case GT_EXPR:
2905 compare = BRIG_COMPARE_GT;
2906 break;
2907 case GE_EXPR:
2908 compare = BRIG_COMPARE_GE;
2909 break;
2910 case EQ_EXPR:
2911 compare = BRIG_COMPARE_EQ;
2912 break;
2913 case NE_EXPR:
2914 compare = BRIG_COMPARE_NE;
2915 break;
2916 case UNORDERED_EXPR:
2917 compare = BRIG_COMPARE_NAN;
2918 break;
2919 case ORDERED_EXPR:
2920 compare = BRIG_COMPARE_NUM;
2921 break;
2922 case UNLT_EXPR:
2923 compare = BRIG_COMPARE_LTU;
2924 break;
2925 case UNLE_EXPR:
2926 compare = BRIG_COMPARE_LEU;
2927 break;
2928 case UNGT_EXPR:
2929 compare = BRIG_COMPARE_GTU;
2930 break;
2931 case UNGE_EXPR:
2932 compare = BRIG_COMPARE_GEU;
2933 break;
2934 case UNEQ_EXPR:
2935 compare = BRIG_COMPARE_EQU;
2936 break;
2937 case LTGT_EXPR:
2938 compare = BRIG_COMPARE_NEU;
2939 break;
2941 default:
2942 HSA_SORRY_ATV (EXPR_LOCATION (lhs),
2943 "support for HSA does not implement comparison tree "
2944 "code %s\n", get_tree_code_name (code));
2945 return;
2948 /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
2949 as a result of comparison. */
2951 BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
2952 ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
2954 hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
2955 cmp->set_op (1, hsa_reg_or_immed_for_gimple_op (lhs, hbb));
2956 cmp->set_op (2, hsa_reg_or_immed_for_gimple_op (rhs, hbb));
2958 hbb->append_insn (cmp);
2959 cmp->set_output_in_type (dest, 0, hbb);
2962 /* Generate an unary instruction with OPCODE and append it to a basic block
2963 HBB. The instruction uses DEST as a destination and OP1
2964 as a single operand. */
2966 static void
2967 gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
2968 hsa_op_with_type *op1, hsa_bb *hbb)
2970 gcc_checking_assert (dest);
2971 hsa_insn_basic *insn;
2973 if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
2974 insn = new hsa_insn_cvt (dest, op1);
2975 else if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
2977 BrigType16_t srctype = hsa_type_integer_p (op1->m_type) ? op1->m_type
2978 : hsa_unsigned_type_for_type (op1->m_type);
2979 insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, srctype, NULL,
2980 op1);
2982 else
2984 insn = new hsa_insn_basic (2, opcode, dest->m_type, dest, op1);
2986 if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
2988 /* ABS and NEG only exist in _s form :-/ */
2989 if (insn->m_type == BRIG_TYPE_U32)
2990 insn->m_type = BRIG_TYPE_S32;
2991 else if (insn->m_type == BRIG_TYPE_U64)
2992 insn->m_type = BRIG_TYPE_S64;
2996 hbb->append_insn (insn);
2998 if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
2999 insn->set_output_in_type (dest, 0, hbb);
3002 /* Generate a binary instruction with OPCODE and append it to a basic block
3003 HBB. The instruction uses DEST as a destination and operands OP1
3004 and OP2. */
3006 static void
3007 gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
3008 hsa_op_base *op1, hsa_op_base *op2, hsa_bb *hbb)
3010 gcc_checking_assert (dest);
3012 if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
3013 && is_a <hsa_op_immed *> (op2))
3015 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3016 i->set_type (BRIG_TYPE_U32);
3018 if ((opcode == BRIG_OPCODE_OR
3019 || opcode == BRIG_OPCODE_XOR
3020 || opcode == BRIG_OPCODE_AND)
3021 && is_a <hsa_op_immed *> (op2))
3023 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3024 i->set_type (hsa_unsigned_type_for_type (i->m_type));
3027 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, dest->m_type, dest,
3028 op1, op2);
3029 hbb->append_insn (insn);
3032 /* Generate HSA instructions for a single assignment. HBB is the basic block
3033 they will be appended to. */
3035 static void
3036 gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
3038 tree_code code = gimple_assign_rhs_code (assign);
3039 gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
3041 tree lhs = gimple_assign_lhs (assign);
3042 tree rhs1 = gimple_assign_rhs1 (assign);
3043 tree rhs2 = gimple_assign_rhs2 (assign);
3044 tree rhs3 = gimple_assign_rhs3 (assign);
3046 BrigOpcode opcode;
3048 switch (code)
3050 CASE_CONVERT:
3051 case FLOAT_EXPR:
3052 /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
3053 needs a conversion. */
3054 opcode = BRIG_OPCODE_MOV;
3055 break;
3057 case PLUS_EXPR:
3058 case POINTER_PLUS_EXPR:
3059 opcode = BRIG_OPCODE_ADD;
3060 break;
3061 case MINUS_EXPR:
3062 opcode = BRIG_OPCODE_SUB;
3063 break;
3064 case MULT_EXPR:
3065 opcode = BRIG_OPCODE_MUL;
3066 break;
3067 case MULT_HIGHPART_EXPR:
3068 opcode = BRIG_OPCODE_MULHI;
3069 break;
3070 case RDIV_EXPR:
3071 case TRUNC_DIV_EXPR:
3072 case EXACT_DIV_EXPR:
3073 opcode = BRIG_OPCODE_DIV;
3074 break;
3075 case CEIL_DIV_EXPR:
3076 case FLOOR_DIV_EXPR:
3077 case ROUND_DIV_EXPR:
3078 HSA_SORRY_AT (gimple_location (assign),
3079 "support for HSA does not implement CEIL_DIV_EXPR, "
3080 "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
3081 return;
3082 case TRUNC_MOD_EXPR:
3083 opcode = BRIG_OPCODE_REM;
3084 break;
3085 case CEIL_MOD_EXPR:
3086 case FLOOR_MOD_EXPR:
3087 case ROUND_MOD_EXPR:
3088 HSA_SORRY_AT (gimple_location (assign),
3089 "support for HSA does not implement CEIL_MOD_EXPR, "
3090 "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
3091 return;
3092 case NEGATE_EXPR:
3093 opcode = BRIG_OPCODE_NEG;
3094 break;
3095 case FMA_EXPR:
3096 /* There is a native HSA instruction for scalar FMAs but not for vector
3097 ones. */
3098 if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
3100 hsa_op_reg *dest
3101 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3102 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3103 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3104 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3105 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
3106 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp, op1, op2, hbb);
3107 gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp, op3, hbb);
3108 return;
3110 opcode = BRIG_OPCODE_MAD;
3111 break;
3112 case MIN_EXPR:
3113 opcode = BRIG_OPCODE_MIN;
3114 break;
3115 case MAX_EXPR:
3116 opcode = BRIG_OPCODE_MAX;
3117 break;
3118 case ABS_EXPR:
3119 opcode = BRIG_OPCODE_ABS;
3120 break;
3121 case LSHIFT_EXPR:
3122 opcode = BRIG_OPCODE_SHL;
3123 break;
3124 case RSHIFT_EXPR:
3125 opcode = BRIG_OPCODE_SHR;
3126 break;
3127 case LROTATE_EXPR:
3128 case RROTATE_EXPR:
3130 hsa_insn_basic *insn = NULL;
3131 int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3132 int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3133 BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3134 true);
3136 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3137 hsa_op_reg *op1 = new hsa_op_reg (btype);
3138 hsa_op_reg *op2 = new hsa_op_reg (btype);
3139 hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3141 tree type = TREE_TYPE (rhs2);
3142 unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3144 hsa_op_with_type *shift2 = NULL;
3145 if (TREE_CODE (rhs2) == INTEGER_CST)
3146 shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3147 BRIG_TYPE_U32);
3148 else if (TREE_CODE (rhs2) == SSA_NAME)
3150 hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3151 hsa_op_reg *d = new hsa_op_reg (s->m_type);
3152 hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3154 insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3155 d, s, size_imm);
3156 hbb->append_insn (insn);
3158 shift2 = d;
3160 else
3161 gcc_unreachable ();
3163 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3164 gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3165 gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3166 gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3168 return;
3170 case BIT_IOR_EXPR:
3171 opcode = BRIG_OPCODE_OR;
3172 break;
3173 case BIT_XOR_EXPR:
3174 opcode = BRIG_OPCODE_XOR;
3175 break;
3176 case BIT_AND_EXPR:
3177 opcode = BRIG_OPCODE_AND;
3178 break;
3179 case BIT_NOT_EXPR:
3180 opcode = BRIG_OPCODE_NOT;
3181 break;
3182 case FIX_TRUNC_EXPR:
3184 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3185 hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3187 if (hsa_needs_cvt (dest->m_type, v->m_type))
3189 hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3191 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3192 tmp->m_type, tmp, v);
3193 hbb->append_insn (insn);
3195 hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3196 hbb->append_insn (cvtinsn);
3198 else
3200 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3201 dest->m_type, dest, v);
3202 hbb->append_insn (insn);
3205 return;
3207 opcode = BRIG_OPCODE_TRUNC;
3208 break;
3210 case LT_EXPR:
3211 case LE_EXPR:
3212 case GT_EXPR:
3213 case GE_EXPR:
3214 case EQ_EXPR:
3215 case NE_EXPR:
3216 case UNORDERED_EXPR:
3217 case ORDERED_EXPR:
3218 case UNLT_EXPR:
3219 case UNLE_EXPR:
3220 case UNGT_EXPR:
3221 case UNGE_EXPR:
3222 case UNEQ_EXPR:
3223 case LTGT_EXPR:
3225 hsa_op_reg *dest
3226 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3228 gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3229 return;
3231 case COND_EXPR:
3233 hsa_op_reg *dest
3234 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3235 hsa_op_with_type *ctrl = NULL;
3236 tree cond = rhs1;
3238 if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3239 ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3240 else
3242 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3244 gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3245 TREE_OPERAND (cond, 0),
3246 TREE_OPERAND (cond, 1),
3247 r, hbb);
3249 ctrl = r;
3252 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3253 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3255 BrigType16_t utype = hsa_unsigned_type_for_type (dest->m_type);
3256 if (is_a <hsa_op_immed *> (op2))
3257 op2->m_type = utype;
3258 if (is_a <hsa_op_immed *> (op3))
3259 op3->m_type = utype;
3261 hsa_insn_basic *insn
3262 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3263 hsa_bittype_for_type (dest->m_type),
3264 dest, ctrl, op2, op3);
3266 hbb->append_insn (insn);
3267 return;
3269 case COMPLEX_EXPR:
3271 hsa_op_reg *dest
3272 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3273 hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3274 hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3276 if (hsa_seen_error ())
3277 return;
3279 BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3280 rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3281 rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3283 hsa_insn_packed *insn
3284 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3285 dest, rhs1_reg, rhs2_reg);
3286 hbb->append_insn (insn);
3288 return;
3290 default:
3291 /* Implement others as we come across them. */
3292 HSA_SORRY_ATV (gimple_location (assign),
3293 "support for HSA does not implement operation %s",
3294 get_tree_code_name (code));
3295 return;
3299 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3301 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3302 hsa_op_with_type *op2 = rhs2 != NULL_TREE ?
3303 hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3305 if (hsa_seen_error ())
3306 return;
3308 switch (rhs_class)
3310 case GIMPLE_TERNARY_RHS:
3312 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3313 hsa_insn_basic *insn = new hsa_insn_basic (4, opcode, dest->m_type, dest,
3314 op1, op2, op3);
3315 hbb->append_insn (insn);
3317 return;
3319 case GIMPLE_BINARY_RHS:
3320 gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3321 break;
3323 case GIMPLE_UNARY_RHS:
3324 gen_hsa_unary_operation (opcode, dest, op1, hbb);
3325 break;
3326 default:
3327 gcc_unreachable ();
3331 /* Generate HSA instructions for a given gimple condition statement COND.
3332 Instructions will be appended to HBB, which also needs to be the
3333 corresponding structure to the basic_block of COND. */
3335 static void
3336 gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3338 hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3339 hsa_insn_cbr *cbr;
3341 gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3342 gimple_cond_lhs (cond),
3343 gimple_cond_rhs (cond),
3344 ctrl, hbb);
3346 cbr = new hsa_insn_cbr (ctrl);
3347 hbb->append_insn (cbr);
3350 /* Maximum number of elements in a jump table for an HSA SBR instruction. */
3352 #define HSA_MAXIMUM_SBR_LABELS 16
3354 /* Return lowest value of a switch S that is handled in a non-default
3355 label. */
3357 static tree
3358 get_switch_low (gswitch *s)
3360 unsigned labels = gimple_switch_num_labels (s);
3361 gcc_checking_assert (labels >= 1);
3363 return CASE_LOW (gimple_switch_label (s, 1));
3366 /* Return highest value of a switch S that is handled in a non-default
3367 label. */
3369 static tree
3370 get_switch_high (gswitch *s)
3372 unsigned labels = gimple_switch_num_labels (s);
3374 /* Compare last label to maximum number of labels. */
3375 tree label = gimple_switch_label (s, labels - 1);
3376 tree low = CASE_LOW (label);
3377 tree high = CASE_HIGH (label);
3379 return high != NULL_TREE ? high : low;
3382 static tree
3383 get_switch_size (gswitch *s)
3385 return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3388 /* Generate HSA instructions for a given gimple switch.
3389 Instructions will be appended to HBB. */
3391 static void
3392 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3394 gimple_stmt_iterator it = gsi_for_stmt (s);
3395 gsi_prev (&it);
3397 /* Create preambule that verifies that index - lowest_label >= 0. */
3398 edge e = split_block (hbb->m_bb, gsi_stmt (it));
3399 e->flags &= ~EDGE_FALLTHRU;
3400 e->flags |= EDGE_TRUE_VALUE;
3402 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
3403 tree index_tree = gimple_switch_index (s);
3404 tree lowest = get_switch_low (s);
3405 tree highest = get_switch_high (s);
3407 hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
3409 hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3410 hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest);
3411 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3412 cmp1_reg, index, cmp1_immed));
3414 hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3415 hsa_op_immed *cmp2_immed = new hsa_op_immed (highest);
3416 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3417 cmp2_reg, index, cmp2_immed));
3419 hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3420 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3421 cmp_reg, cmp1_reg, cmp2_reg));
3423 hbb->append_insn (new hsa_insn_cbr (cmp_reg));
3425 tree default_label = gimple_switch_default_label (s);
3426 basic_block default_label_bb = label_to_block_fn (func,
3427 CASE_LABEL (default_label));
3429 if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3431 default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3432 hsa_init_new_bb (default_label_bb);
3435 make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3437 hsa_cfun->m_modified_cfg = true;
3439 /* Basic block with the SBR instruction. */
3440 hbb = hsa_init_new_bb (e->dest);
3442 hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3443 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3444 sub_index, index,
3445 new hsa_op_immed (lowest)));
3447 hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3448 sub_index = as_a <hsa_op_reg *> (tmp);
3449 unsigned labels = gimple_switch_num_labels (s);
3450 unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3452 hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
3454 /* Prepare array with default label destination. */
3455 for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3456 sbr->m_jump_table.safe_push (default_label_bb);
3458 /* Iterate all labels and fill up the jump table. */
3459 for (unsigned i = 1; i < labels; i++)
3461 tree label = gimple_switch_label (s, i);
3462 basic_block bb = label_to_block_fn (func, CASE_LABEL (label));
3464 unsigned HOST_WIDE_INT sub_low
3465 = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3467 unsigned HOST_WIDE_INT sub_high = sub_low;
3468 tree high = CASE_HIGH (label);
3469 if (high != NULL)
3470 sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3472 for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3473 sbr->m_jump_table[j] = bb;
3476 hbb->append_insn (sbr);
3479 /* Verify that the function DECL can be handled by HSA. */
3481 static void
3482 verify_function_arguments (tree decl)
3484 tree type = TREE_TYPE (decl);
3485 if (DECL_STATIC_CHAIN (decl))
3487 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3488 "HSA does not support nested functions: %D", decl);
3489 return;
3491 else if (!TYPE_ARG_TYPES (type) || stdarg_p (type))
3493 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3494 "HSA does not support functions with variadic arguments "
3495 "(or unknown return type): %D", decl);
3496 return;
3500 /* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL,
3501 return ACTUAL_ARG_TYPE. */
3503 static BrigType16_t
3504 get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3506 if (formal_arg_type == NULL)
3507 return actual_arg_type;
3509 BrigType16_t decl_type
3510 = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3511 return mem_type_for_type (decl_type);
3514 /* Generate HSA instructions for a direct call instruction.
3515 Instructions will be appended to HBB, which also needs to be the
3516 corresponding structure to the basic_block of STMT.
3517 If ASSIGN_LHS is false, do not copy HSA function result argument into the
3518 corresponding HSA representation of the gimple statement LHS. */
3520 static void
3521 gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3522 bool assign_lhs = true)
3524 tree decl = gimple_call_fndecl (stmt);
3525 verify_function_arguments (decl);
3526 if (hsa_seen_error ())
3527 return;
3529 hsa_insn_call *call_insn = new hsa_insn_call (decl);
3530 hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3532 /* Argument block start. */
3533 hsa_insn_arg_block *arg_start
3534 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3535 hbb->append_insn (arg_start);
3537 tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3539 /* Preparation of arguments that will be passed to function. */
3540 const unsigned args = gimple_call_num_args (stmt);
3541 for (unsigned i = 0; i < args; ++i)
3543 tree parm = gimple_call_arg (stmt, (int)i);
3544 tree parm_decl_type = parm_type_chain != NULL_TREE
3545 ? TREE_VALUE (parm_type_chain) : NULL_TREE;
3546 hsa_op_address *addr;
3548 if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3550 addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3551 BrigAlignment8_t align;
3552 hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
3553 gen_hsa_memory_copy (hbb, addr, src,
3554 addr->m_symbol->total_byte_size (), align);
3556 else
3558 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3560 if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3562 HSA_SORRY_AT (gimple_location (stmt),
3563 "support for HSA does not implement an aggregate "
3564 "formal argument in a function call, while actual "
3565 "argument is not an aggregate");
3566 return;
3569 BrigType16_t formal_arg_type
3570 = get_format_argument_type (parm_decl_type, src->m_type);
3571 if (hsa_seen_error ())
3572 return;
3574 if (src->m_type != formal_arg_type)
3575 src = src->get_in_type (formal_arg_type, hbb);
3577 addr
3578 = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3579 parm_decl_type: TREE_TYPE (parm), i);
3580 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3581 src, addr);
3583 hbb->append_insn (mem);
3586 call_insn->m_input_args.safe_push (addr->m_symbol);
3587 if (parm_type_chain)
3588 parm_type_chain = TREE_CHAIN (parm_type_chain);
3591 call_insn->m_args_code_list = new hsa_op_code_list (args);
3592 hbb->append_insn (call_insn);
3594 tree result_type = TREE_TYPE (TREE_TYPE (decl));
3596 tree result = gimple_call_lhs (stmt);
3597 hsa_insn_mem *result_insn = NULL;
3598 if (!VOID_TYPE_P (result_type))
3600 hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3602 /* Even if result of a function call is unused, we have to emit
3603 declaration for the result. */
3604 if (result && assign_lhs)
3606 tree lhs_type = TREE_TYPE (result);
3608 if (hsa_seen_error ())
3609 return;
3611 if (AGGREGATE_TYPE_P (lhs_type))
3613 BrigAlignment8_t align;
3614 hsa_op_address *result_addr
3615 = gen_hsa_addr_with_align (result, hbb, &align);
3616 gen_hsa_memory_copy (hbb, result_addr, addr,
3617 addr->m_symbol->total_byte_size (), align);
3619 else
3621 BrigType16_t mtype
3622 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3623 false));
3625 hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3626 result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3627 hbb->append_insn (result_insn);
3631 call_insn->m_output_arg = addr->m_symbol;
3632 call_insn->m_result_code_list = new hsa_op_code_list (1);
3634 else
3636 if (result)
3638 HSA_SORRY_AT (gimple_location (stmt),
3639 "support for HSA does not implement an assignment of "
3640 "return value from a void function");
3641 return;
3644 call_insn->m_result_code_list = new hsa_op_code_list (0);
3647 /* Argument block end. */
3648 hsa_insn_arg_block *arg_end
3649 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3650 hbb->append_insn (arg_end);
3653 /* Generate HSA instructions for a direct call of an internal fn.
3654 Instructions will be appended to HBB, which also needs to be the
3655 corresponding structure to the basic_block of STMT. */
3657 static void
3658 gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3660 tree lhs = gimple_call_lhs (stmt);
3661 if (!lhs)
3662 return;
3664 tree lhs_type = TREE_TYPE (lhs);
3665 tree rhs1 = gimple_call_arg (stmt, 0);
3666 tree rhs1_type = TREE_TYPE (rhs1);
3667 enum internal_fn fn = gimple_call_internal_fn (stmt);
3668 hsa_internal_fn *ifn
3669 = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3670 hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3672 gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3674 if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3675 hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3677 hsa_insn_arg_block *arg_start
3678 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3679 hbb->append_insn (arg_start);
3681 unsigned num_args = gimple_call_num_args (stmt);
3683 /* Function arguments. */
3684 for (unsigned i = 0; i < num_args; i++)
3686 tree parm = gimple_call_arg (stmt, (int)i);
3687 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3689 hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3690 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3691 src, addr);
3693 call_insn->m_input_args.safe_push (addr->m_symbol);
3694 hbb->append_insn (mem);
3697 call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3698 hbb->append_insn (call_insn);
3700 /* Assign returned value. */
3701 hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3703 call_insn->m_output_arg = addr->m_symbol;
3704 call_insn->m_result_code_list = new hsa_op_code_list (1);
3706 /* Argument block end. */
3707 hsa_insn_arg_block *arg_end
3708 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3709 hbb->append_insn (arg_end);
3712 /* Generate HSA instructions for a return value instruction.
3713 Instructions will be appended to HBB, which also needs to be the
3714 corresponding structure to the basic_block of STMT. */
3716 static void
3717 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3719 tree retval = gimple_return_retval (stmt);
3720 if (retval)
3722 hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3724 if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3726 BrigAlignment8_t align;
3727 hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3728 &align);
3729 gen_hsa_memory_copy (hbb, addr, retval_addr,
3730 hsa_cfun->m_output_arg->total_byte_size (),
3731 align);
3733 else
3735 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3736 false);
3737 BrigType16_t mtype = mem_type_for_type (t);
3739 /* Store of return value. */
3740 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3741 src = src->get_in_type (mtype, hbb);
3742 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3743 addr);
3744 hbb->append_insn (mem);
3748 /* HSAIL return instruction emission. */
3749 hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3750 hbb->append_insn (ret);
3753 /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3754 can have a different type, conversion instructions are possibly
3755 appended to HBB. */
3757 void
3758 hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3759 hsa_bb *hbb)
3761 hsa_insn_basic *insn;
3762 gcc_checking_assert (op_output_p (op_index));
3764 if (dest->m_type == m_type)
3766 set_op (op_index, dest);
3767 return;
3770 hsa_op_reg *tmp = new hsa_op_reg (m_type);
3771 set_op (op_index, tmp);
3773 if (hsa_needs_cvt (dest->m_type, m_type))
3774 insn = new hsa_insn_cvt (dest, tmp);
3775 else
3776 insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3777 dest, tmp->get_in_type (dest->m_type, hbb));
3779 hbb->append_insn (insn);
3782 /* Generate instruction OPCODE to query a property of HSA grid along the
3783 given DIMENSION. Store result into DEST and append the instruction to
3784 HBB. */
3786 static void
3787 query_hsa_grid_dim (hsa_op_reg *dest, int opcode, hsa_op_immed *dimension,
3788 hsa_bb *hbb)
3790 hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3791 dimension);
3792 hbb->append_insn (insn);
3793 insn->set_output_in_type (dest, 0, hbb);
3796 /* Generate instruction OPCODE to query a property of HSA grid along the given
3797 dimension which is an immediate in first argument of STMT. Store result
3798 into the register corresponding to LHS of STMT and append the instruction to
3799 HBB. */
3801 static void
3802 query_hsa_grid_dim (gimple *stmt, int opcode, hsa_bb *hbb)
3804 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3805 if (lhs == NULL_TREE)
3806 return;
3808 tree arg = gimple_call_arg (stmt, 0);
3809 unsigned HOST_WIDE_INT dim = 5;
3810 if (tree_fits_uhwi_p (arg))
3811 dim = tree_to_uhwi (arg);
3812 if (dim > 2)
3814 HSA_SORRY_AT (gimple_location (stmt),
3815 "HSA grid query dimension must be immediate constant 0, 1 "
3816 "or 2");
3817 return;
3820 hsa_op_immed *hdim = new hsa_op_immed (dim, (BrigKind16_t) BRIG_TYPE_U32);
3821 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3822 query_hsa_grid_dim (dest, opcode, hdim, hbb);
3825 /* Generate instruction OPCODE to query a property of HSA grid that is
3826 independent of any dimension. Store result into the register corresponding
3827 to LHS of STMT and append the instruction to HBB. */
3829 static void
3830 query_hsa_grid_nodim (gimple *stmt, BrigOpcode16_t opcode, hsa_bb *hbb)
3832 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3833 if (lhs == NULL_TREE)
3834 return;
3835 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3836 BrigType16_t brig_type = hsa_unsigned_type_for_type (dest->m_type);
3837 hsa_insn_basic *insn = new hsa_insn_basic (1, opcode, brig_type, dest);
3838 hbb->append_insn (insn);
3841 /* Emit instructions that set hsa_num_threads according to provided VALUE.
3842 Instructions are appended to basic block HBB. */
3844 static void
3845 gen_set_num_threads (tree value, hsa_bb *hbb)
3847 hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3848 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3850 src = src->get_in_type (hsa_num_threads->m_type, hbb);
3851 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3853 hsa_insn_basic *basic
3854 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3855 hbb->append_insn (basic);
3858 /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3859 is defined in plugin-hsa.c. */
3861 static HOST_WIDE_INT
3862 get_hsa_kernel_dispatch_offset (const char *field_name)
3864 tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3865 if (*hsa_kernel_dispatch_type == NULL)
3867 /* Collection of information needed for a dispatch of a kernel from a
3868 kernel. Keep in sync with libgomp's plugin-hsa.c. */
3870 *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
3871 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3872 get_identifier ("queue"), ptr_type_node);
3873 DECL_CHAIN (id_f1) = NULL_TREE;
3874 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3875 get_identifier ("omp_data_memory"),
3876 ptr_type_node);
3877 DECL_CHAIN (id_f2) = id_f1;
3878 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3879 get_identifier ("kernarg_address"),
3880 ptr_type_node);
3881 DECL_CHAIN (id_f3) = id_f2;
3882 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3883 get_identifier ("object"),
3884 uint64_type_node);
3885 DECL_CHAIN (id_f4) = id_f3;
3886 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3887 get_identifier ("signal"),
3888 uint64_type_node);
3889 DECL_CHAIN (id_f5) = id_f4;
3890 tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3891 get_identifier ("private_segment_size"),
3892 uint32_type_node);
3893 DECL_CHAIN (id_f6) = id_f5;
3894 tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3895 get_identifier ("group_segment_size"),
3896 uint32_type_node);
3897 DECL_CHAIN (id_f7) = id_f6;
3898 tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3899 get_identifier ("kernel_dispatch_count"),
3900 uint64_type_node);
3901 DECL_CHAIN (id_f8) = id_f7;
3902 tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3903 get_identifier ("debug"),
3904 uint64_type_node);
3905 DECL_CHAIN (id_f9) = id_f8;
3906 tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3907 get_identifier ("omp_level"),
3908 uint64_type_node);
3909 DECL_CHAIN (id_f10) = id_f9;
3910 tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3911 get_identifier ("children_dispatches"),
3912 ptr_type_node);
3913 DECL_CHAIN (id_f11) = id_f10;
3914 tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3915 get_identifier ("omp_num_threads"),
3916 uint32_type_node);
3917 DECL_CHAIN (id_f12) = id_f11;
3920 finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
3921 id_f12, NULL_TREE);
3922 TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
3925 for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
3926 chain != NULL_TREE; chain = TREE_CHAIN (chain))
3927 if (strcmp (field_name, IDENTIFIER_POINTER (DECL_NAME (chain))) == 0)
3928 return int_byte_position (chain);
3930 gcc_unreachable ();
3933 /* Return an HSA register that will contain number of threads for
3934 a future dispatched kernel. Instructions are added to HBB. */
3936 static hsa_op_reg *
3937 gen_num_threads_for_dispatch (hsa_bb *hbb)
3939 /* Step 1) Assign to number of threads:
3940 MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads). */
3941 hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
3942 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3944 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
3945 threads, addr));
3947 hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
3948 BRIG_TYPE_U32);
3949 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3950 hsa_insn_cmp * cmp
3951 = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
3952 hbb->append_insn (cmp);
3954 BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
3955 hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
3957 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
3958 threads, limit));
3960 /* Step 2) If the number is equal to zero,
3961 return shadow->omp_num_threads. */
3962 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
3964 hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
3965 addr
3966 = new hsa_op_address (shadow_reg_ptr,
3967 get_hsa_kernel_dispatch_offset ("omp_num_threads"));
3968 hsa_insn_basic *basic
3969 = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
3970 shadow_thread_count, addr);
3971 hbb->append_insn (basic);
3973 hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
3974 r = new hsa_op_reg (BRIG_TYPE_B1);
3975 hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
3976 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
3977 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
3978 shadow_thread_count, tmp));
3980 hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
3982 return as_a <hsa_op_reg *> (dest);
3985 /* Build OPCODE query for all three hsa dimensions, multiply them and store the
3986 result into DEST. */
3988 static void
3989 multiply_grid_dim_characteristics (hsa_op_reg *dest, int opcode, hsa_bb *hbb)
3991 hsa_op_reg *dimx = new hsa_op_reg (BRIG_TYPE_U32);
3992 query_hsa_grid_dim (dimx, opcode,
3993 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
3994 hsa_op_reg *dimy = new hsa_op_reg (BRIG_TYPE_U32);
3995 query_hsa_grid_dim (dimy, opcode,
3996 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
3997 hsa_op_reg *dimz = new hsa_op_reg (BRIG_TYPE_U32);
3998 query_hsa_grid_dim (dimz, opcode,
3999 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4000 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4001 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp,
4002 dimx->get_in_type (dest->m_type, hbb),
4003 dimy->get_in_type (dest->m_type, hbb), hbb);
4004 gen_hsa_binary_operation (BRIG_OPCODE_MUL, dest, tmp,
4005 dimz->get_in_type (dest->m_type, hbb), hbb);
4008 /* Emit instructions that assign number of threads to lhs of gimple STMT.
4009 Instructions are appended to basic block HBB. */
4011 static void
4012 gen_get_num_threads (gimple *stmt, hsa_bb *hbb)
4014 if (gimple_call_lhs (stmt) == NULL_TREE)
4015 return;
4017 hbb->append_insn (new hsa_insn_comment ("omp_get_num_threads"));
4018 tree lhs = gimple_call_lhs (stmt);
4019 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4020 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_CURRENTWORKGROUPSIZE,
4021 hbb);
4024 /* Emit instructions that assign number of teams to lhs of gimple STMT.
4025 Instructions are appended to basic block HBB. */
4027 static void
4028 gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4030 if (gimple_call_lhs (stmt) == NULL_TREE)
4031 return;
4033 hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4034 tree lhs = gimple_call_lhs (stmt);
4035 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4036 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_GRIDGROUPS, hbb);
4039 /* Emit instructions that assign a team number to lhs of gimple STMT.
4040 Instructions are appended to basic block HBB. */
4042 static void
4043 gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4045 if (gimple_call_lhs (stmt) == NULL_TREE)
4046 return;
4048 hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4049 tree lhs = gimple_call_lhs (stmt);
4050 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4052 hsa_op_reg *gnum_x = new hsa_op_reg (BRIG_TYPE_U32);
4053 query_hsa_grid_dim (gnum_x, BRIG_OPCODE_GRIDGROUPS,
4054 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4055 hsa_op_reg *gnum_y = new hsa_op_reg (BRIG_TYPE_U32);
4056 query_hsa_grid_dim (gnum_y, BRIG_OPCODE_GRIDGROUPS,
4057 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4059 hsa_op_reg *gno_z = new hsa_op_reg (BRIG_TYPE_U32);
4060 query_hsa_grid_dim (gno_z, BRIG_OPCODE_WORKGROUPID,
4061 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4063 hsa_op_reg *tmp1 = new hsa_op_reg (dest->m_type);
4064 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp1,
4065 gnum_x->get_in_type (dest->m_type, hbb),
4066 gnum_y->get_in_type (dest->m_type, hbb), hbb);
4067 hsa_op_reg *tmp2 = new hsa_op_reg (dest->m_type);
4068 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp2, tmp1,
4069 gno_z->get_in_type (dest->m_type, hbb), hbb);
4071 hsa_op_reg *gno_y = new hsa_op_reg (BRIG_TYPE_U32);
4072 query_hsa_grid_dim (gno_y, BRIG_OPCODE_WORKGROUPID,
4073 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4074 hsa_op_reg *tmp3 = new hsa_op_reg (dest->m_type);
4075 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp3,
4076 gnum_x->get_in_type (dest->m_type, hbb),
4077 gno_y->get_in_type (dest->m_type, hbb), hbb);
4078 hsa_op_reg *tmp4 = new hsa_op_reg (dest->m_type);
4079 gen_hsa_binary_operation (BRIG_OPCODE_ADD, tmp4, tmp3, tmp2, hbb);
4080 hsa_op_reg *gno_x = new hsa_op_reg (BRIG_TYPE_U32);
4081 query_hsa_grid_dim (gno_x, BRIG_OPCODE_WORKGROUPID,
4082 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4083 gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp4,
4084 gno_x->get_in_type (dest->m_type, hbb), hbb);
4087 /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4088 Instructions are appended to basic block HBB. */
4090 static void
4091 gen_get_level (gimple *stmt, hsa_bb *hbb)
4093 if (gimple_call_lhs (stmt) == NULL_TREE)
4094 return;
4096 hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4098 tree lhs = gimple_call_lhs (stmt);
4099 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4101 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4102 if (shadow_reg_ptr == NULL)
4104 HSA_SORRY_AT (gimple_location (stmt),
4105 "support for HSA does not implement omp_get_level called "
4106 "from a function not being inlined within a kernel");
4107 return;
4110 hsa_op_address *addr
4111 = new hsa_op_address (shadow_reg_ptr,
4112 get_hsa_kernel_dispatch_offset ("omp_level"));
4114 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4115 (hsa_op_base *) NULL, addr);
4116 hbb->append_insn (mem);
4117 mem->set_output_in_type (dest, 0, hbb);
4120 /* Emit instruction that implement omp_get_max_threads of gimple STMT. */
4122 static void
4123 gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4125 tree lhs = gimple_call_lhs (stmt);
4126 if (!lhs)
4127 return;
4129 hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4131 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4132 hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4133 ->get_in_type (dest->m_type, hbb);
4134 hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4137 /* Emit instructions that implement alloca builtin gimple STMT.
4138 Instructions are appended to basic block HBB. */
4140 static void
4141 gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4143 tree lhs = gimple_call_lhs (call);
4144 if (lhs == NULL_TREE)
4145 return;
4147 built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
4149 gcc_checking_assert (fn == BUILT_IN_ALLOCA
4150 || fn == BUILT_IN_ALLOCA_WITH_ALIGN);
4152 unsigned bit_alignment = 0;
4154 if (fn == BUILT_IN_ALLOCA_WITH_ALIGN)
4156 tree alignment_tree = gimple_call_arg (call, 1);
4157 if (TREE_CODE (alignment_tree) != INTEGER_CST)
4159 HSA_SORRY_ATV (gimple_location (call),
4160 "support for HSA does not implement "
4161 "__builtin_alloca_with_align with a non-constant "
4162 "alignment: %E", alignment_tree);
4165 bit_alignment = tree_to_uhwi (alignment_tree);
4168 tree rhs1 = gimple_call_arg (call, 0);
4169 hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4170 ->get_in_type (BRIG_TYPE_U32, hbb);
4171 hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4173 hsa_op_reg *tmp
4174 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4175 hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4176 hbb->append_insn (a);
4178 hsa_insn_seg *seg
4179 = new hsa_insn_seg (BRIG_OPCODE_STOF,
4180 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4181 tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4182 hbb->append_insn (seg);
4185 /* Emit instructions that implement clrsb builtin STMT:
4186 Returns the number of leading redundant sign bits in x, i.e. the number
4187 of bits following the most significant bit that are identical to it.
4188 There are no special cases for 0 or other values.
4189 Instructions are appended to basic block HBB. */
4191 static void
4192 gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4194 tree lhs = gimple_call_lhs (call);
4195 if (lhs == NULL_TREE)
4196 return;
4198 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4199 tree rhs1 = gimple_call_arg (call, 0);
4200 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4201 BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4202 unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
4204 /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers. */
4205 gcc_checking_assert (bitsize == 32 || bitsize == 64);
4207 /* Set true to MOST_SIG if the most significant bit is set to one. */
4208 hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4209 hsa_uint_for_bitsize (bitsize));
4211 hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4212 gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4214 hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4215 hsa_insn_cmp *cmp
4216 = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4217 and_reg, c);
4218 hbb->append_insn (cmp);
4220 /* If the most significant bit is one, negate the input. Otherwise
4221 shift the input value to left by one bit. */
4222 hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4223 gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4225 hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4226 gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4227 new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4229 /* Assign the value that can be used for FIRSTBIT instruction according
4230 to the most significant bit. */
4231 hsa_op_reg *tmp = new hsa_op_reg (bittype);
4232 hsa_insn_basic *cmov
4233 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4234 arg_neg, shifted_arg);
4235 hbb->append_insn (cmov);
4237 hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4238 gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4239 tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4240 hbb), hbb);
4242 /* Set flag if the input value is equal to zero. */
4243 hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4244 cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4245 new hsa_op_immed (0, arg->m_type));
4246 hbb->append_insn (cmp);
4248 /* Return the number of leading bits,
4249 or (bitsize - 1) if the input value is zero. */
4250 cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
4251 new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
4252 leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4253 hbb->append_insn (cmov);
4254 cmov->set_output_in_type (dest, 0, hbb);
4257 /* Emit instructions that implement ffs builtin STMT:
4258 Returns one plus the index of the least significant 1-bit of x,
4259 or if x is zero, returns zero.
4260 Instructions are appended to basic block HBB. */
4262 static void
4263 gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4265 tree lhs = gimple_call_lhs (call);
4266 if (lhs == NULL_TREE)
4267 return;
4269 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4271 tree rhs1 = gimple_call_arg (call, 0);
4272 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4274 hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4275 hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4276 tmp->m_type, arg->m_type,
4277 tmp, arg);
4278 hbb->append_insn (insn);
4280 hsa_insn_basic *addition
4281 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4282 new hsa_op_immed (1, tmp->m_type));
4283 hbb->append_insn (addition);
4284 addition->set_output_in_type (dest, 0, hbb);
4287 static void
4288 gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4290 gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4292 if (hsa_type_bit_size (arg->m_type) < 32)
4293 arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4295 BrigType16_t srctype = hsa_bittype_for_type (arg->m_type);
4296 if (!hsa_btype_p (arg->m_type))
4297 arg = arg->get_in_type (srctype, hbb);
4299 hsa_insn_srctype *popcount
4300 = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4301 srctype, NULL, arg);
4302 hbb->append_insn (popcount);
4303 popcount->set_output_in_type (dest, 0, hbb);
4306 /* Emit instructions that implement parity builtin STMT:
4307 Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4308 Instructions are appended to basic block HBB. */
4310 static void
4311 gen_hsa_parity (gcall *call, hsa_bb *hbb)
4313 tree lhs = gimple_call_lhs (call);
4314 if (lhs == NULL_TREE)
4315 return;
4317 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4318 tree rhs1 = gimple_call_arg (call, 0);
4319 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4321 hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4322 gen_hsa_popcount_to_dest (popcount, arg, hbb);
4324 hsa_insn_basic *insn
4325 = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4326 new hsa_op_immed (2, popcount->m_type));
4327 hbb->append_insn (insn);
4328 insn->set_output_in_type (dest, 0, hbb);
4331 /* Emit instructions that implement popcount builtin STMT.
4332 Instructions are appended to basic block HBB. */
4334 static void
4335 gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4337 tree lhs = gimple_call_lhs (call);
4338 if (lhs == NULL_TREE)
4339 return;
4341 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4342 tree rhs1 = gimple_call_arg (call, 0);
4343 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4345 gen_hsa_popcount_to_dest (dest, arg, hbb);
4348 /* Set VALUE to a shadow kernel debug argument and append a new instruction
4349 to HBB basic block. */
4351 static void
4352 set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4354 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4355 if (shadow_reg_ptr == NULL)
4356 return;
4358 hsa_op_address *addr
4359 = new hsa_op_address (shadow_reg_ptr,
4360 get_hsa_kernel_dispatch_offset ("debug"));
4361 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4362 addr);
4363 hbb->append_insn (mem);
4366 void
4367 omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4369 if (m_sorry)
4371 if (m_warning_message)
4372 HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
4373 else
4374 HSA_SORRY_ATV (gimple_location (stmt),
4375 "Support for HSA does not implement calls to %s\n",
4376 m_name);
4378 else if (m_warning_message != NULL)
4379 warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4381 if (m_return_value != NULL)
4383 tree lhs = gimple_call_lhs (stmt);
4384 if (!lhs)
4385 return;
4387 hbb->append_insn (new hsa_insn_comment (m_name));
4389 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4390 hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4391 hsa_build_append_simple_mov (dest, op, hbb);
4395 /* If STMT is a call of a known library function, generate code to perform
4396 it and return true. */
4398 static bool
4399 gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4401 bool handled = false;
4402 const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4404 char *copy = NULL;
4405 size_t len = strlen (name);
4406 if (len > 0 && name[len - 1] == '_')
4408 copy = XNEWVEC (char, len + 1);
4409 strcpy (copy, name);
4410 copy[len - 1] = '\0';
4411 name = copy;
4414 /* Handle omp_* routines. */
4415 if (strstr (name, "omp_") == name)
4417 hsa_init_simple_builtins ();
4418 omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4419 if (builtin)
4421 builtin->generate (stmt, hbb);
4422 return true;
4425 handled = true;
4426 if (strcmp (name, "omp_set_num_threads") == 0)
4427 gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4428 else if (strcmp (name, "omp_get_thread_num") == 0)
4430 hbb->append_insn (new hsa_insn_comment (name));
4431 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
4433 else if (strcmp (name, "omp_get_num_threads") == 0)
4435 hbb->append_insn (new hsa_insn_comment (name));
4436 gen_get_num_threads (stmt, hbb);
4438 else if (strcmp (name, "omp_get_num_teams") == 0)
4439 gen_get_num_teams (stmt, hbb);
4440 else if (strcmp (name, "omp_get_team_num") == 0)
4441 gen_get_team_num (stmt, hbb);
4442 else if (strcmp (name, "omp_get_level") == 0)
4443 gen_get_level (stmt, hbb);
4444 else if (strcmp (name, "omp_get_active_level") == 0)
4445 gen_get_level (stmt, hbb);
4446 else if (strcmp (name, "omp_in_parallel") == 0)
4447 gen_get_level (stmt, hbb);
4448 else if (strcmp (name, "omp_get_max_threads") == 0)
4449 gen_get_max_threads (stmt, hbb);
4450 else
4451 handled = false;
4453 if (handled)
4455 if (copy)
4456 free (copy);
4457 return true;
4461 if (strcmp (name, "__hsa_set_debug_value") == 0)
4463 handled = true;
4464 if (hsa_cfun->has_shadow_reg_p ())
4466 tree rhs1 = gimple_call_arg (stmt, 0);
4467 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4469 src = src->get_in_type (BRIG_TYPE_U64, hbb);
4470 set_debug_value (hbb, src);
4474 if (copy)
4475 free (copy);
4476 return handled;
4479 /* Helper functions to create a single unary HSA operations out of calls to
4480 builtins. OPCODE is the HSA operation to be generated. STMT is a gimple
4481 call to a builtin. HBB is the HSA BB to which the instruction should be
4482 added. Note that nothing will be created if STMT does not have a LHS. */
4484 static void
4485 gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4487 tree lhs = gimple_call_lhs (stmt);
4488 if (!lhs)
4489 return;
4490 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4491 hsa_op_with_type *op
4492 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4493 gen_hsa_unary_operation (opcode, dest, op, hbb);
4496 /* Helper functions to create a call to standard library if LHS of the
4497 STMT is used. HBB is the HSA BB to which the instruction should be
4498 added. */
4500 static void
4501 gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4503 tree lhs = gimple_call_lhs (stmt);
4504 if (!lhs)
4505 return;
4507 if (gimple_call_internal_p (stmt))
4508 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4509 else
4510 gen_hsa_insns_for_direct_call (stmt, hbb);
4513 /* Helper functions to create a single unary HSA operations out of calls to
4514 builtins (if unsafe math optimizations are enable). Otherwise, create
4515 a call to standard library function.
4516 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. */
4520 static void
4521 gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4522 hsa_bb *hbb)
4524 if (flag_unsafe_math_optimizations)
4525 gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4526 else
4527 gen_hsa_unaryop_builtin_call (stmt, hbb);
4530 /* Generate HSA address corresponding to a value VAL (as opposed to a memory
4531 reference tree), for example an SSA_NAME or an ADDR_EXPR. HBB is the HSA BB
4532 to which the instruction should be added. */
4534 static hsa_op_address *
4535 get_address_from_value (tree val, hsa_bb *hbb)
4537 switch (TREE_CODE (val))
4539 case SSA_NAME:
4541 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4542 hsa_op_base *reg
4543 = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4544 return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4546 case ADDR_EXPR:
4547 return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4549 case INTEGER_CST:
4550 if (tree_fits_shwi_p (val))
4551 return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
4552 /* fall-through */
4554 default:
4555 HSA_SORRY_ATV (EXPR_LOCATION (val),
4556 "support for HSA does not implement memory access to %E",
4557 val);
4558 return new hsa_op_address (NULL, NULL, 0);
4562 /* Expand assignment of a result of a string BUILTIN to DST.
4563 Size of the operation is N bytes, where instructions
4564 will be append to HBB. */
4566 static void
4567 expand_lhs_of_string_op (gimple *stmt,
4568 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4569 enum built_in_function builtin)
4571 /* If LHS is expected, we need to emit a PHI instruction. */
4572 tree lhs = gimple_call_lhs (stmt);
4573 if (!lhs)
4574 return;
4576 hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4578 hsa_op_with_type *dst_reg
4579 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4580 hsa_op_with_type *tmp;
4582 switch (builtin)
4584 case BUILT_IN_MEMPCPY:
4586 tmp = new hsa_op_reg (dst_reg->m_type);
4587 hsa_insn_basic *add
4588 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4589 tmp, dst_reg,
4590 new hsa_op_immed (n, dst_reg->m_type));
4591 hbb->append_insn (add);
4592 break;
4594 case BUILT_IN_MEMCPY:
4595 case BUILT_IN_MEMSET:
4596 tmp = dst_reg;
4597 break;
4598 default:
4599 gcc_unreachable ();
4602 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4603 lhs_reg, tmp));
4606 #define HSA_MEMORY_BUILTINS_LIMIT 128
4608 /* Expand a string builtin (from a gimple STMT) in a way that
4609 according to MISALIGNED_FLAG we process either direct emission
4610 (a bunch of memory load and store instructions), or we emit a function call
4611 of a library function (for instance 'memcpy'). Actually, a basic block
4612 for direct emission is just prepared, where caller is responsible
4613 for emission of corresponding instructions.
4614 All instruction are appended to HBB. */
4616 hsa_bb *
4617 expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4618 hsa_op_reg *misaligned_flag)
4620 edge e = split_block (hbb->m_bb, stmt);
4621 basic_block condition_bb = e->src;
4622 hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
4624 /* Prepare the control flow. */
4625 edge condition_edge = EDGE_SUCC (condition_bb, 0);
4626 basic_block call_bb = split_edge (condition_edge);
4628 basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4629 basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4630 basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4632 condition_edge->flags &= ~EDGE_FALLTHRU;
4633 condition_edge->flags |= EDGE_TRUE_VALUE;
4634 make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4636 redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4638 hsa_cfun->m_modified_cfg = true;
4640 hsa_init_new_bb (expanded_bb);
4642 /* Slow path: function call. */
4643 gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4645 return hsa_bb_for_bb (expanded_bb);
4648 /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4649 a gimple STMT and store all necessary instruction to HBB basic block. */
4651 static void
4652 expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4654 tree byte_size = gimple_call_arg (stmt, 2);
4656 if (!tree_fits_uhwi_p (byte_size))
4658 gen_hsa_insns_for_direct_call (stmt, hbb);
4659 return;
4662 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4664 if (n > HSA_MEMORY_BUILTINS_LIMIT)
4666 gen_hsa_insns_for_direct_call (stmt, hbb);
4667 return;
4670 tree dst = gimple_call_arg (stmt, 0);
4671 tree src = gimple_call_arg (stmt, 1);
4673 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4674 hsa_op_address *src_addr = get_address_from_value (src, hbb);
4676 /* As gen_hsa_memory_copy relies on memory alignment
4677 greater or equal to 8 bytes, we need to verify the alignment. */
4678 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4679 hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4680 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4682 convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4683 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4685 /* Process BIT OR for source and destination addresses. */
4686 hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4687 gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4688 dst_addr_reg, hbb);
4690 /* Process BIT AND with 0x7 to identify the desired alignment
4691 of 8 bytes. */
4692 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4694 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4695 new hsa_op_immed (7, addrtype), hbb);
4697 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4698 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4699 misaligned, masked,
4700 new hsa_op_immed (0, masked->m_type)));
4702 hsa_bb *native_impl_bb
4703 = expand_string_operation_builtin (stmt, hbb, misaligned);
4705 gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4706 hsa_bb *merge_bb
4707 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4708 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4712 /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4713 a gimple STMT and store all necessary instruction to HBB basic block.
4714 The operation set N bytes with a CONSTANT value. */
4716 static void
4717 expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4718 unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4719 enum built_in_function builtin)
4721 tree dst = gimple_call_arg (stmt, 0);
4722 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4724 /* As gen_hsa_memory_set relies on memory alignment
4725 greater or equal to 8 bytes, we need to verify the alignment. */
4726 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4727 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4728 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4730 /* Process BIT AND with 0x7 to identify the desired alignment
4731 of 8 bytes. */
4732 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4734 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4735 new hsa_op_immed (7, addrtype), hbb);
4737 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4738 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4739 misaligned, masked,
4740 new hsa_op_immed (0, masked->m_type)));
4742 hsa_bb *native_impl_bb
4743 = expand_string_operation_builtin (stmt, hbb, misaligned);
4745 gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4746 hsa_bb *merge_bb
4747 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4748 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4751 /* Store into MEMORDER the memory order specified by tree T, which must be an
4752 integer constant representing a C++ memory order. If it isn't, issue an HSA
4753 sorry message using LOC and return true, otherwise return false and store
4754 the name of the requested order to *MNAME. */
4756 static bool
4757 hsa_memorder_from_tree (tree t, BrigMemoryOrder *memorder, const char **mname,
4758 location_t loc)
4760 if (!tree_fits_uhwi_p (t))
4762 HSA_SORRY_ATV (loc, "support for HSA does not implement memory model %E",
4764 return true;
4767 unsigned HOST_WIDE_INT mm = tree_to_uhwi (t);
4768 switch (mm & MEMMODEL_BASE_MASK)
4770 case MEMMODEL_RELAXED:
4771 *memorder = BRIG_MEMORY_ORDER_RELAXED;
4772 *mname = "relaxed";
4773 break;
4774 case MEMMODEL_CONSUME:
4775 /* HSA does not have an equivalent, but we can use the slightly stronger
4776 ACQUIRE. */
4777 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4778 *mname = "consume";
4779 break;
4780 case MEMMODEL_ACQUIRE:
4781 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4782 *mname = "acquire";
4783 break;
4784 case MEMMODEL_RELEASE:
4785 *memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4786 *mname = "release";
4787 break;
4788 case MEMMODEL_ACQ_REL:
4789 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4790 *mname = "acq_rel";
4791 break;
4792 case MEMMODEL_SEQ_CST:
4793 /* Callers implementing a simple load or store need to remove the release
4794 or acquire part respectively. */
4795 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4796 *mname = "seq_cst";
4797 break;
4798 default:
4800 HSA_SORRY_AT (loc, "support for HSA does not implement the specified "
4801 "memory model");
4802 return true;
4805 return false;
4808 /* Helper function to create an HSA atomic operation instruction out of calls
4809 to atomic builtins. RET_ORIG is true if the built-in is the variant that
4810 return s the value before applying operation, and false if it should return
4811 the value after applying the operation (if it returns value at all). ACODE
4812 is the atomic operation code, STMT is a gimple call to a builtin. HBB is
4813 the HSA BB to which the instruction should be added. If SIGNAL is true, the
4814 created operation will work on HSA signals rather than atomic variables. */
4816 static void
4817 gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
4818 gimple *stmt, hsa_bb *hbb, bool signal)
4820 tree lhs = gimple_call_lhs (stmt);
4822 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
4823 BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
4824 BrigType16_t mtype = mem_type_for_type (hsa_type);
4825 BrigMemoryOrder memorder;
4826 const char *mmname;
4828 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 2), &memorder, &mmname,
4829 gimple_location (stmt)))
4830 return;
4832 /* Certain atomic insns must have Bx memory types. */
4833 switch (acode)
4835 case BRIG_ATOMIC_LD:
4836 case BRIG_ATOMIC_ST:
4837 case BRIG_ATOMIC_AND:
4838 case BRIG_ATOMIC_OR:
4839 case BRIG_ATOMIC_XOR:
4840 case BRIG_ATOMIC_EXCH:
4841 mtype = hsa_bittype_for_type (mtype);
4842 break;
4843 default:
4844 break;
4847 hsa_op_reg *dest;
4848 int nops, opcode;
4849 if (lhs)
4851 if (ret_orig)
4852 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4853 else
4854 dest = new hsa_op_reg (hsa_type);
4855 opcode = signal ? BRIG_OPCODE_SIGNAL : BRIG_OPCODE_ATOMIC;
4856 nops = 3;
4858 else
4860 dest = NULL;
4861 opcode = signal ? BRIG_OPCODE_SIGNALNORET : BRIG_OPCODE_ATOMICNORET;
4862 nops = 2;
4865 if (acode == BRIG_ATOMIC_ST)
4867 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
4868 memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4870 if (memorder != BRIG_MEMORY_ORDER_RELAXED
4871 && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
4872 && memorder != BRIG_MEMORY_ORDER_NONE)
4874 HSA_SORRY_ATV (gimple_location (stmt),
4875 "support for HSA does not implement memory model for "
4876 "ATOMIC_ST: %s", mmname);
4877 return;
4881 hsa_insn_basic *atominsn;
4882 hsa_op_base *tgt;
4883 if (signal)
4885 atominsn = new hsa_insn_signal (nops, opcode, acode, mtype, memorder);
4886 tgt = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4888 else
4890 atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, memorder);
4891 hsa_op_address *addr;
4892 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
4893 if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
4895 HSA_SORRY_AT (gimple_location (stmt),
4896 "HSA does not implement atomic operations in private "
4897 "segment");
4898 return;
4900 tgt = addr;
4903 hsa_op_base *op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1),
4904 hbb);
4905 if (lhs)
4907 atominsn->set_op (0, dest);
4908 atominsn->set_op (1, tgt);
4909 atominsn->set_op (2, op);
4911 else
4913 atominsn->set_op (0, tgt);
4914 atominsn->set_op (1, op);
4917 hbb->append_insn (atominsn);
4919 /* HSA does not natively support the variants that return the modified value,
4920 so re-do the operation again non-atomically if that is what was
4921 requested. */
4922 if (lhs && !ret_orig)
4924 int arith;
4925 switch (acode)
4927 case BRIG_ATOMIC_ADD:
4928 arith = BRIG_OPCODE_ADD;
4929 break;
4930 case BRIG_ATOMIC_AND:
4931 arith = BRIG_OPCODE_AND;
4932 break;
4933 case BRIG_ATOMIC_OR:
4934 arith = BRIG_OPCODE_OR;
4935 break;
4936 case BRIG_ATOMIC_SUB:
4937 arith = BRIG_OPCODE_SUB;
4938 break;
4939 case BRIG_ATOMIC_XOR:
4940 arith = BRIG_OPCODE_XOR;
4941 break;
4942 default:
4943 gcc_unreachable ();
4945 hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4946 gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
4950 /* Generate HSA instructions for an internal fn.
4951 Instructions will be appended to HBB, which also needs to be the
4952 corresponding structure to the basic_block of STMT. */
4954 static void
4955 gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
4957 gcc_checking_assert (gimple_call_internal_fn (stmt));
4958 internal_fn fn = gimple_call_internal_fn (stmt);
4960 bool is_float_type_p = false;
4961 if (gimple_call_lhs (stmt) != NULL
4962 && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
4963 is_float_type_p = true;
4965 switch (fn)
4967 case IFN_CEIL:
4968 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
4969 break;
4971 case IFN_FLOOR:
4972 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
4973 break;
4975 case IFN_RINT:
4976 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
4977 break;
4979 case IFN_SQRT:
4980 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
4981 break;
4983 case IFN_RSQRT:
4984 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NRSQRT, stmt, hbb);
4985 break;
4987 case IFN_TRUNC:
4988 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
4989 break;
4991 case IFN_COS:
4993 if (is_float_type_p)
4994 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
4995 else
4996 gen_hsa_unaryop_builtin_call (stmt, hbb);
4998 break;
5000 case IFN_EXP2:
5002 if (is_float_type_p)
5003 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5004 else
5005 gen_hsa_unaryop_builtin_call (stmt, hbb);
5007 break;
5010 case IFN_LOG2:
5012 if (is_float_type_p)
5013 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5014 else
5015 gen_hsa_unaryop_builtin_call (stmt, hbb);
5017 break;
5020 case IFN_SIN:
5022 if (is_float_type_p)
5023 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5024 else
5025 gen_hsa_unaryop_builtin_call (stmt, hbb);
5026 break;
5029 case IFN_CLRSB:
5030 gen_hsa_clrsb (stmt, hbb);
5031 break;
5033 case IFN_CLZ:
5034 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5035 break;
5037 case IFN_CTZ:
5038 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5039 break;
5041 case IFN_FFS:
5042 gen_hsa_ffs (stmt, hbb);
5043 break;
5045 case IFN_PARITY:
5046 gen_hsa_parity (stmt, hbb);
5047 break;
5049 case IFN_POPCOUNT:
5050 gen_hsa_popcount (stmt, hbb);
5051 break;
5053 case IFN_ACOS:
5054 case IFN_ASIN:
5055 case IFN_ATAN:
5056 case IFN_EXP:
5057 case IFN_EXP10:
5058 case IFN_EXPM1:
5059 case IFN_LOG:
5060 case IFN_LOG10:
5061 case IFN_LOG1P:
5062 case IFN_LOGB:
5063 case IFN_SIGNIFICAND:
5064 case IFN_TAN:
5065 case IFN_NEARBYINT:
5066 case IFN_ROUND:
5067 case IFN_ATAN2:
5068 case IFN_COPYSIGN:
5069 case IFN_FMOD:
5070 case IFN_POW:
5071 case IFN_REMAINDER:
5072 case IFN_SCALB:
5073 case IFN_FMIN:
5074 case IFN_FMAX:
5075 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
5076 break;
5078 default:
5079 HSA_SORRY_ATV (gimple_location (stmt),
5080 "support for HSA does not implement internal function: %s",
5081 internal_fn_name (fn));
5082 break;
5086 /* Generate HSA instructions for the given call statement STMT. Instructions
5087 will be appended to HBB. */
5089 static void
5090 gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5092 gcall *call = as_a <gcall *> (stmt);
5093 tree lhs = gimple_call_lhs (stmt);
5094 hsa_op_reg *dest;
5096 if (gimple_call_internal_p (stmt))
5098 gen_hsa_insn_for_internal_fn_call (call, hbb);
5099 return;
5102 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5104 tree function_decl = gimple_call_fndecl (stmt);
5105 /* Prefetch pass can create type-mismatching prefetch builtin calls which
5106 fail the gimple_call_builtin_p test above. Handle them here. */
5107 if (DECL_BUILT_IN_CLASS (function_decl)
5108 && DECL_FUNCTION_CODE (function_decl) == BUILT_IN_PREFETCH)
5109 return;
5111 if (function_decl == NULL_TREE)
5113 HSA_SORRY_AT (gimple_location (stmt),
5114 "support for HSA does not implement indirect calls");
5115 return;
5118 if (hsa_callable_function_p (function_decl))
5119 gen_hsa_insns_for_direct_call (stmt, hbb);
5120 else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5121 HSA_SORRY_AT (gimple_location (stmt),
5122 "HSA supports only calls of functions marked with pragma "
5123 "omp declare target");
5124 return;
5127 tree fndecl = gimple_call_fndecl (stmt);
5128 enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5129 switch (builtin)
5131 case BUILT_IN_FABS:
5132 case BUILT_IN_FABSF:
5133 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5134 break;
5136 case BUILT_IN_CEIL:
5137 case BUILT_IN_CEILF:
5138 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5139 break;
5141 case BUILT_IN_FLOOR:
5142 case BUILT_IN_FLOORF:
5143 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5144 break;
5146 case BUILT_IN_RINT:
5147 case BUILT_IN_RINTF:
5148 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5149 break;
5151 case BUILT_IN_SQRT:
5152 case BUILT_IN_SQRTF:
5153 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5154 break;
5156 case BUILT_IN_TRUNC:
5157 case BUILT_IN_TRUNCF:
5158 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5159 break;
5161 case BUILT_IN_COS:
5162 case BUILT_IN_SIN:
5163 case BUILT_IN_EXP2:
5164 case BUILT_IN_LOG2:
5165 /* HSAIL does not provide an instruction for double argument type. */
5166 gen_hsa_unaryop_builtin_call (stmt, hbb);
5167 break;
5169 case BUILT_IN_COSF:
5170 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5171 break;
5173 case BUILT_IN_EXP2F:
5174 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5175 break;
5177 case BUILT_IN_LOG2F:
5178 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5179 break;
5181 case BUILT_IN_SINF:
5182 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5183 break;
5185 case BUILT_IN_CLRSB:
5186 case BUILT_IN_CLRSBL:
5187 case BUILT_IN_CLRSBLL:
5188 gen_hsa_clrsb (call, hbb);
5189 break;
5191 case BUILT_IN_CLZ:
5192 case BUILT_IN_CLZL:
5193 case BUILT_IN_CLZLL:
5194 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5195 break;
5197 case BUILT_IN_CTZ:
5198 case BUILT_IN_CTZL:
5199 case BUILT_IN_CTZLL:
5200 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5201 break;
5203 case BUILT_IN_FFS:
5204 case BUILT_IN_FFSL:
5205 case BUILT_IN_FFSLL:
5206 gen_hsa_ffs (call, hbb);
5207 break;
5209 case BUILT_IN_PARITY:
5210 case BUILT_IN_PARITYL:
5211 case BUILT_IN_PARITYLL:
5212 gen_hsa_parity (call, hbb);
5213 break;
5215 case BUILT_IN_POPCOUNT:
5216 case BUILT_IN_POPCOUNTL:
5217 case BUILT_IN_POPCOUNTLL:
5218 gen_hsa_popcount (call, hbb);
5219 break;
5221 case BUILT_IN_ATOMIC_LOAD_1:
5222 case BUILT_IN_ATOMIC_LOAD_2:
5223 case BUILT_IN_ATOMIC_LOAD_4:
5224 case BUILT_IN_ATOMIC_LOAD_8:
5225 case BUILT_IN_ATOMIC_LOAD_16:
5227 BrigType16_t mtype;
5228 hsa_op_base *src;
5229 src = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5231 BrigMemoryOrder memorder;
5232 const char *mmname;
5233 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 1), &memorder,
5234 &mmname, gimple_location (stmt)))
5235 return;
5237 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5238 memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5240 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5241 && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5242 && memorder != BRIG_MEMORY_ORDER_NONE)
5244 HSA_SORRY_ATV (gimple_location (stmt),
5245 "support for HSA does not implement "
5246 "memory model for atomic loads: %s", mmname);
5247 return;
5250 if (lhs)
5252 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5253 false);
5254 mtype = mem_type_for_type (t);
5255 mtype = hsa_bittype_for_type (mtype);
5256 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5258 else
5260 mtype = BRIG_TYPE_B64;
5261 dest = new hsa_op_reg (mtype);
5264 hsa_insn_basic *atominsn;
5265 atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD,
5266 mtype, memorder, dest, src);
5268 hbb->append_insn (atominsn);
5269 break;
5272 case BUILT_IN_ATOMIC_EXCHANGE_1:
5273 case BUILT_IN_ATOMIC_EXCHANGE_2:
5274 case BUILT_IN_ATOMIC_EXCHANGE_4:
5275 case BUILT_IN_ATOMIC_EXCHANGE_8:
5276 case BUILT_IN_ATOMIC_EXCHANGE_16:
5277 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb, false);
5278 break;
5279 break;
5281 case BUILT_IN_ATOMIC_FETCH_ADD_1:
5282 case BUILT_IN_ATOMIC_FETCH_ADD_2:
5283 case BUILT_IN_ATOMIC_FETCH_ADD_4:
5284 case BUILT_IN_ATOMIC_FETCH_ADD_8:
5285 case BUILT_IN_ATOMIC_FETCH_ADD_16:
5286 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb, false);
5287 break;
5288 break;
5290 case BUILT_IN_ATOMIC_FETCH_SUB_1:
5291 case BUILT_IN_ATOMIC_FETCH_SUB_2:
5292 case BUILT_IN_ATOMIC_FETCH_SUB_4:
5293 case BUILT_IN_ATOMIC_FETCH_SUB_8:
5294 case BUILT_IN_ATOMIC_FETCH_SUB_16:
5295 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb, false);
5296 break;
5297 break;
5299 case BUILT_IN_ATOMIC_FETCH_AND_1:
5300 case BUILT_IN_ATOMIC_FETCH_AND_2:
5301 case BUILT_IN_ATOMIC_FETCH_AND_4:
5302 case BUILT_IN_ATOMIC_FETCH_AND_8:
5303 case BUILT_IN_ATOMIC_FETCH_AND_16:
5304 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb, false);
5305 break;
5306 break;
5308 case BUILT_IN_ATOMIC_FETCH_XOR_1:
5309 case BUILT_IN_ATOMIC_FETCH_XOR_2:
5310 case BUILT_IN_ATOMIC_FETCH_XOR_4:
5311 case BUILT_IN_ATOMIC_FETCH_XOR_8:
5312 case BUILT_IN_ATOMIC_FETCH_XOR_16:
5313 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb, false);
5314 break;
5315 break;
5317 case BUILT_IN_ATOMIC_FETCH_OR_1:
5318 case BUILT_IN_ATOMIC_FETCH_OR_2:
5319 case BUILT_IN_ATOMIC_FETCH_OR_4:
5320 case BUILT_IN_ATOMIC_FETCH_OR_8:
5321 case BUILT_IN_ATOMIC_FETCH_OR_16:
5322 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb, false);
5323 break;
5324 break;
5326 case BUILT_IN_ATOMIC_STORE_1:
5327 case BUILT_IN_ATOMIC_STORE_2:
5328 case BUILT_IN_ATOMIC_STORE_4:
5329 case BUILT_IN_ATOMIC_STORE_8:
5330 case BUILT_IN_ATOMIC_STORE_16:
5331 /* Since there cannot be any LHS, the first parameter is meaningless. */
5332 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb, false);
5333 break;
5334 break;
5336 case BUILT_IN_ATOMIC_ADD_FETCH_1:
5337 case BUILT_IN_ATOMIC_ADD_FETCH_2:
5338 case BUILT_IN_ATOMIC_ADD_FETCH_4:
5339 case BUILT_IN_ATOMIC_ADD_FETCH_8:
5340 case BUILT_IN_ATOMIC_ADD_FETCH_16:
5341 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb, false);
5342 break;
5344 case BUILT_IN_ATOMIC_SUB_FETCH_1:
5345 case BUILT_IN_ATOMIC_SUB_FETCH_2:
5346 case BUILT_IN_ATOMIC_SUB_FETCH_4:
5347 case BUILT_IN_ATOMIC_SUB_FETCH_8:
5348 case BUILT_IN_ATOMIC_SUB_FETCH_16:
5349 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb, false);
5350 break;
5352 case BUILT_IN_ATOMIC_AND_FETCH_1:
5353 case BUILT_IN_ATOMIC_AND_FETCH_2:
5354 case BUILT_IN_ATOMIC_AND_FETCH_4:
5355 case BUILT_IN_ATOMIC_AND_FETCH_8:
5356 case BUILT_IN_ATOMIC_AND_FETCH_16:
5357 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb, false);
5358 break;
5360 case BUILT_IN_ATOMIC_XOR_FETCH_1:
5361 case BUILT_IN_ATOMIC_XOR_FETCH_2:
5362 case BUILT_IN_ATOMIC_XOR_FETCH_4:
5363 case BUILT_IN_ATOMIC_XOR_FETCH_8:
5364 case BUILT_IN_ATOMIC_XOR_FETCH_16:
5365 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb, false);
5366 break;
5368 case BUILT_IN_ATOMIC_OR_FETCH_1:
5369 case BUILT_IN_ATOMIC_OR_FETCH_2:
5370 case BUILT_IN_ATOMIC_OR_FETCH_4:
5371 case BUILT_IN_ATOMIC_OR_FETCH_8:
5372 case BUILT_IN_ATOMIC_OR_FETCH_16:
5373 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb, false);
5374 break;
5376 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5377 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5378 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5379 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5380 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5382 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5383 BrigType16_t atype
5384 = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5385 BrigMemoryOrder memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
5386 hsa_insn_basic *atominsn;
5387 hsa_op_base *tgt;
5388 atominsn = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC,
5389 BRIG_ATOMIC_CAS, atype, memorder);
5390 tgt = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5392 if (lhs != NULL)
5393 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5394 else
5395 dest = new hsa_op_reg (atype);
5397 atominsn->set_op (0, dest);
5398 atominsn->set_op (1, tgt);
5400 hsa_op_with_type *op
5401 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5402 atominsn->set_op (2, op);
5403 op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5404 atominsn->set_op (3, op);
5406 hbb->append_insn (atominsn);
5407 break;
5410 case BUILT_IN_HSA_WORKGROUPID:
5411 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKGROUPID, hbb);
5412 break;
5413 case BUILT_IN_HSA_WORKITEMID:
5414 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMID, hbb);
5415 break;
5416 case BUILT_IN_HSA_WORKITEMABSID:
5417 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMABSID, hbb);
5418 break;
5419 case BUILT_IN_HSA_GRIDSIZE:
5420 query_hsa_grid_dim (stmt, BRIG_OPCODE_GRIDSIZE, hbb);
5421 break;
5422 case BUILT_IN_HSA_CURRENTWORKGROUPSIZE:
5423 query_hsa_grid_dim (stmt, BRIG_OPCODE_CURRENTWORKGROUPSIZE, hbb);
5424 break;
5426 case BUILT_IN_GOMP_BARRIER:
5427 hbb->append_insn (new hsa_insn_br (0, BRIG_OPCODE_BARRIER, BRIG_TYPE_NONE,
5428 BRIG_WIDTH_ALL));
5429 break;
5430 case BUILT_IN_GOMP_PARALLEL:
5431 HSA_SORRY_AT (gimple_location (stmt),
5432 "support for HSA does not implement non-gridified "
5433 "OpenMP parallel constructs.");
5434 break;
5436 case BUILT_IN_OMP_GET_THREAD_NUM:
5438 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
5439 break;
5442 case BUILT_IN_OMP_GET_NUM_THREADS:
5444 gen_get_num_threads (stmt, hbb);
5445 break;
5447 case BUILT_IN_GOMP_TEAMS:
5449 gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5450 break;
5452 case BUILT_IN_OMP_GET_NUM_TEAMS:
5454 gen_get_num_teams (stmt, hbb);
5455 break;
5457 case BUILT_IN_OMP_GET_TEAM_NUM:
5459 gen_get_team_num (stmt, hbb);
5460 break;
5462 case BUILT_IN_MEMCPY:
5463 case BUILT_IN_MEMPCPY:
5465 expand_memory_copy (stmt, hbb, builtin);
5466 break;
5468 case BUILT_IN_MEMSET:
5470 tree c = gimple_call_arg (stmt, 1);
5472 if (TREE_CODE (c) != INTEGER_CST)
5474 gen_hsa_insns_for_direct_call (stmt, hbb);
5475 return;
5478 tree byte_size = gimple_call_arg (stmt, 2);
5480 if (!tree_fits_uhwi_p (byte_size))
5482 gen_hsa_insns_for_direct_call (stmt, hbb);
5483 return;
5486 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5488 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5490 gen_hsa_insns_for_direct_call (stmt, hbb);
5491 return;
5494 unsigned HOST_WIDE_INT constant
5495 = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5497 expand_memory_set (stmt, n, constant, hbb, builtin);
5499 break;
5501 case BUILT_IN_BZERO:
5503 tree byte_size = gimple_call_arg (stmt, 1);
5505 if (!tree_fits_uhwi_p (byte_size))
5507 gen_hsa_insns_for_direct_call (stmt, hbb);
5508 return;
5511 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5513 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5515 gen_hsa_insns_for_direct_call (stmt, hbb);
5516 return;
5519 expand_memory_set (stmt, n, 0, hbb, builtin);
5521 break;
5523 case BUILT_IN_ALLOCA:
5524 case BUILT_IN_ALLOCA_WITH_ALIGN:
5526 gen_hsa_alloca (call, hbb);
5527 break;
5529 case BUILT_IN_PREFETCH:
5530 break;
5531 default:
5533 tree name_tree = DECL_NAME (fndecl);
5534 const char *s = IDENTIFIER_POINTER (name_tree);
5535 size_t len = strlen (s);
5536 if (len > 4 && (strncmp (s, "__builtin_GOMP_", 15) == 0))
5537 HSA_SORRY_ATV (gimple_location (stmt),
5538 "support for HSA does not implement GOMP function %s",
5540 else
5541 gen_hsa_insns_for_direct_call (stmt, hbb);
5542 return;
5547 /* Generate HSA instructions for a given gimple statement. Instructions will be
5548 appended to HBB. */
5550 static void
5551 gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5553 switch (gimple_code (stmt))
5555 case GIMPLE_ASSIGN:
5556 if (gimple_clobber_p (stmt))
5557 break;
5559 if (gimple_assign_single_p (stmt))
5561 tree lhs = gimple_assign_lhs (stmt);
5562 tree rhs = gimple_assign_rhs1 (stmt);
5563 gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5565 else
5566 gen_hsa_insns_for_operation_assignment (stmt, hbb);
5567 break;
5568 case GIMPLE_RETURN:
5569 gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5570 break;
5571 case GIMPLE_COND:
5572 gen_hsa_insns_for_cond_stmt (stmt, hbb);
5573 break;
5574 case GIMPLE_CALL:
5575 gen_hsa_insns_for_call (stmt, hbb);
5576 break;
5577 case GIMPLE_DEBUG:
5578 /* ??? HSA supports some debug facilities. */
5579 break;
5580 case GIMPLE_LABEL:
5582 tree label = gimple_label_label (as_a <glabel *> (stmt));
5583 if (FORCED_LABEL (label))
5584 HSA_SORRY_AT (gimple_location (stmt),
5585 "support for HSA does not implement gimple label with "
5586 "address taken");
5588 break;
5590 case GIMPLE_NOP:
5592 hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5593 break;
5595 case GIMPLE_SWITCH:
5597 gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5598 break;
5600 default:
5601 HSA_SORRY_ATV (gimple_location (stmt),
5602 "support for HSA does not implement gimple statement %s",
5603 gimple_code_name[(int) gimple_code (stmt)]);
5607 /* Generate a HSA PHI from a gimple PHI. */
5609 static void
5610 gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5612 hsa_insn_phi *hphi;
5613 unsigned count = gimple_phi_num_args (phi_stmt);
5615 hsa_op_reg *dest
5616 = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5617 hphi = new hsa_insn_phi (count, dest);
5618 hphi->m_bb = hbb->m_bb;
5620 tree lhs = gimple_phi_result (phi_stmt);
5622 for (unsigned i = 0; i < count; i++)
5624 tree op = gimple_phi_arg_def (phi_stmt, i);
5626 if (TREE_CODE (op) == SSA_NAME)
5628 hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5629 hphi->set_op (i, hreg);
5631 else
5633 gcc_assert (is_gimple_min_invariant (op));
5634 tree t = TREE_TYPE (op);
5635 if (!POINTER_TYPE_P (t)
5636 || (TREE_CODE (op) == STRING_CST
5637 && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5638 hphi->set_op (i, new hsa_op_immed (op));
5639 else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5640 && TREE_CODE (op) == INTEGER_CST)
5642 /* Handle assignment of NULL value to a pointer type. */
5643 hphi->set_op (i, new hsa_op_immed (op));
5645 else if (TREE_CODE (op) == ADDR_EXPR)
5647 edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5648 hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5649 hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5650 hbb_src);
5652 hsa_op_reg *dest
5653 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
5654 hsa_insn_basic *insn
5655 = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5656 dest, addr);
5657 hbb_src->append_insn (insn);
5659 hphi->set_op (i, dest);
5661 else
5663 HSA_SORRY_AT (gimple_location (phi_stmt),
5664 "support for HSA does not handle PHI nodes with "
5665 "constant address operands");
5666 return;
5671 hbb->append_phi (hphi);
5674 /* Constructor of class containing HSA-specific information about a basic
5675 block. CFG_BB is the CFG BB this HSA BB is associated with. IDX is the new
5676 index of this BB (so that the constructor does not attempt to use
5677 hsa_cfun during its construction). */
5679 hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5680 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5681 m_last_phi (NULL), m_index (idx), m_liveout (BITMAP_ALLOC (NULL)),
5682 m_livein (BITMAP_ALLOC (NULL))
5684 gcc_assert (!cfg_bb->aux);
5685 cfg_bb->aux = this;
5688 /* Constructor of class containing HSA-specific information about a basic
5689 block. CFG_BB is the CFG BB this HSA BB is associated with. */
5691 hsa_bb::hsa_bb (basic_block cfg_bb)
5692 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5693 m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++),
5694 m_liveout (BITMAP_ALLOC (NULL)), m_livein (BITMAP_ALLOC (NULL))
5696 gcc_assert (!cfg_bb->aux);
5697 cfg_bb->aux = this;
5700 /* Destructor of class representing HSA BB. */
5702 hsa_bb::~hsa_bb ()
5704 BITMAP_FREE (m_livein);
5705 BITMAP_FREE (m_liveout);
5708 /* Create and initialize and return a new hsa_bb structure for a given CFG
5709 basic block BB. */
5711 hsa_bb *
5712 hsa_init_new_bb (basic_block bb)
5714 void *m = obstack_alloc (&hsa_obstack, sizeof (hsa_bb));
5715 return new (m) hsa_bb (bb);
5718 /* Initialize OMP in an HSA basic block PROLOGUE. */
5720 static void
5721 init_prologue (void)
5723 if (!hsa_cfun->m_kern_p)
5724 return;
5726 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5728 /* Create a magic number that is going to be printed by libgomp. */
5729 unsigned index = hsa_get_number_decl_kernel_mappings ();
5731 /* Emit store to debug argument. */
5732 if (PARAM_VALUE (PARAM_HSA_GEN_DEBUG_STORES) > 0)
5733 set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5736 /* Initialize hsa_num_threads to a default value. */
5738 static void
5739 init_hsa_num_threads (void)
5741 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5743 /* Save the default value to private variable hsa_num_threads. */
5744 hsa_insn_basic *basic
5745 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5746 new hsa_op_immed (0, hsa_num_threads->m_type),
5747 new hsa_op_address (hsa_num_threads));
5748 prologue->append_insn (basic);
5751 /* Go over gimple representation and generate our internal HSA one. */
5753 static void
5754 gen_body_from_gimple ()
5756 basic_block bb;
5758 /* Verify CFG for complex edges we are unable to handle. */
5759 edge_iterator ei;
5760 edge e;
5762 FOR_EACH_BB_FN (bb, cfun)
5764 FOR_EACH_EDGE (e, ei, bb->succs)
5766 /* Verify all unsupported flags for edges that point
5767 to the same basic block. */
5768 if (e->flags & EDGE_EH)
5770 HSA_SORRY_AT (UNKNOWN_LOCATION,
5771 "support for HSA does not implement exception "
5772 "handling");
5773 return;
5778 FOR_EACH_BB_FN (bb, cfun)
5780 gimple_stmt_iterator gsi;
5781 hsa_bb *hbb = hsa_bb_for_bb (bb);
5782 if (hbb)
5783 continue;
5785 hbb = hsa_init_new_bb (bb);
5787 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5789 gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
5790 if (hsa_seen_error ())
5791 return;
5795 FOR_EACH_BB_FN (bb, cfun)
5797 gimple_stmt_iterator gsi;
5798 hsa_bb *hbb = hsa_bb_for_bb (bb);
5799 gcc_assert (hbb != NULL);
5801 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5802 if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
5803 gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
5806 if (dump_file && (dump_flags & TDF_DETAILS))
5808 fprintf (dump_file, "------- Generated SSA form -------\n");
5809 dump_hsa_cfun (dump_file);
5813 static void
5814 gen_function_decl_parameters (hsa_function_representation *f,
5815 tree decl)
5817 tree parm;
5818 unsigned i;
5820 for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
5821 parm;
5822 parm = TREE_CHAIN (parm), i++)
5824 /* Result type if last in the tree list. */
5825 if (TREE_CHAIN (parm) == NULL)
5826 break;
5828 tree v = TREE_VALUE (parm);
5830 hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5831 BRIG_LINKAGE_NONE);
5832 arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
5833 arg->m_name_number = i;
5835 f->m_input_args.safe_push (arg);
5838 tree result_type = TREE_TYPE (TREE_TYPE (decl));
5839 if (!VOID_TYPE_P (result_type))
5841 f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5842 BRIG_LINKAGE_NONE);
5843 f->m_output_arg->m_type
5844 = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
5845 f->m_output_arg->m_name = "res";
5849 /* Generate the vector of parameters of the HSA representation of the current
5850 function. This also includes the output parameter representing the
5851 result. */
5853 static void
5854 gen_function_def_parameters ()
5856 tree parm;
5858 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5860 for (parm = DECL_ARGUMENTS (cfun->decl); parm;
5861 parm = DECL_CHAIN (parm))
5863 struct hsa_symbol **slot;
5865 hsa_symbol *arg
5866 = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
5867 ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
5868 BRIG_LINKAGE_FUNCTION);
5869 arg->fillup_for_decl (parm);
5871 hsa_cfun->m_input_args.safe_push (arg);
5873 if (hsa_seen_error ())
5874 return;
5876 arg->m_name = hsa_get_declaration_name (parm);
5878 /* Copy all input arguments and create corresponding private symbols
5879 for them. */
5880 hsa_symbol *private_arg;
5881 hsa_op_address *parm_addr = new hsa_op_address (arg);
5883 if (TREE_ADDRESSABLE (parm)
5884 || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
5886 private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
5887 private_arg->fillup_for_decl (parm);
5889 BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
5891 hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
5892 gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
5893 arg->total_byte_size (), align);
5895 else
5896 private_arg = arg;
5898 slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
5899 gcc_assert (!*slot);
5900 *slot = private_arg;
5902 if (is_gimple_reg (parm))
5904 tree ddef = ssa_default_def (cfun, parm);
5905 if (ddef && !has_zero_uses (ddef))
5907 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
5908 false);
5909 BrigType16_t mtype = mem_type_for_type (t);
5910 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
5911 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
5912 dest, parm_addr);
5913 gcc_assert (!parm_addr->m_reg);
5914 prologue->append_insn (mem);
5919 if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
5921 struct hsa_symbol **slot;
5923 hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
5924 BRIG_LINKAGE_FUNCTION);
5925 hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
5927 if (hsa_seen_error ())
5928 return;
5930 hsa_cfun->m_output_arg->m_name = "res";
5931 slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
5932 INSERT);
5933 gcc_assert (!*slot);
5934 *slot = hsa_cfun->m_output_arg;
5938 /* Generate function representation that corresponds to
5939 a function declaration. */
5941 hsa_function_representation *
5942 hsa_generate_function_declaration (tree decl)
5944 hsa_function_representation *fun
5945 = new hsa_function_representation (decl, false, 0);
5947 fun->m_declaration_p = true;
5948 fun->m_name = get_brig_function_name (decl);
5949 gen_function_decl_parameters (fun, decl);
5951 return fun;
5955 /* Generate function representation that corresponds to
5956 an internal FN. */
5958 hsa_function_representation *
5959 hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
5961 hsa_function_representation *fun = new hsa_function_representation (fn);
5963 fun->m_name = fn->name ();
5965 for (unsigned i = 0; i < fn->get_arity (); i++)
5967 hsa_symbol *arg
5968 = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
5969 BRIG_LINKAGE_NONE);
5970 arg->m_name_number = i;
5971 fun->m_input_args.safe_push (arg);
5974 fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
5975 BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
5976 fun->m_output_arg->m_name = "res";
5978 return fun;
5981 /* Return true if switch statement S can be transformed
5982 to a SBR instruction in HSAIL. */
5984 static bool
5985 transformable_switch_to_sbr_p (gswitch *s)
5987 /* Identify if a switch statement can be transformed to
5988 SBR instruction, like:
5990 sbr_u32 $s1 [@label1, @label2, @label3];
5993 tree size = get_switch_size (s);
5994 if (!tree_fits_uhwi_p (size))
5995 return false;
5997 if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
5998 return false;
6000 return true;
6003 /* Structure hold connection between PHI nodes and immediate
6004 values hold by there nodes. */
6006 struct phi_definition
6008 phi_definition (unsigned phi_i, unsigned label_i, tree imm):
6009 phi_index (phi_i), label_index (label_i), phi_value (imm)
6012 unsigned phi_index;
6013 unsigned label_index;
6014 tree phi_value;
6017 /* Sum slice of a vector V, starting from index START and ending
6018 at the index END - 1. */
6020 template <typename T>
6021 static
6022 T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end)
6024 T s = 0;
6026 for (unsigned i = start; i < end; i++)
6027 s += v[i];
6029 return s;
6032 /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
6033 Let's assume following example:
6036 switch (index)
6037 case C1:
6038 L1: hard_work_1 ();
6039 break;
6040 case C2..C3:
6041 L2: hard_work_2 ();
6042 break;
6043 default:
6044 LD: hard_work_3 ();
6045 break;
6047 The transformation encompasses following steps:
6048 1) all immediate values used by edges coming from the switch basic block
6049 are saved
6050 2) all these edges are removed
6051 3) the switch statement (in L0) is replaced by:
6052 if (index == C1)
6053 goto L1;
6054 else
6055 goto L1';
6057 4) newly created basic block Lx' is used for generation of
6058 a next condition
6059 5) else branch of the last condition goes to LD
6060 6) fix all immediate values in PHI nodes that were propagated though
6061 edges that were removed in step 2
6063 Note: if a case is made by a range C1..C2, then process
6064 following transformation:
6066 switch_cond_op1 = C1 <= index;
6067 switch_cond_op2 = index <= C2;
6068 switch_cond_and = switch_cond_op1 & switch_cond_op2;
6069 if (switch_cond_and != 0)
6070 goto Lx;
6071 else
6072 goto Ly;
6076 static bool
6077 convert_switch_statements (void)
6079 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6080 basic_block bb;
6082 bool modified_cfg = false;
6084 FOR_EACH_BB_FN (bb, func)
6086 gimple_stmt_iterator gsi = gsi_last_bb (bb);
6087 if (gsi_end_p (gsi))
6088 continue;
6090 gimple *stmt = gsi_stmt (gsi);
6092 if (gimple_code (stmt) == GIMPLE_SWITCH)
6094 gswitch *s = as_a <gswitch *> (stmt);
6096 /* If the switch can utilize SBR insn, skip the statement. */
6097 if (transformable_switch_to_sbr_p (s))
6098 continue;
6100 modified_cfg = true;
6102 unsigned labels = gimple_switch_num_labels (s);
6103 tree index = gimple_switch_index (s);
6104 tree index_type = TREE_TYPE (index);
6105 tree default_label = gimple_switch_default_label (s);
6106 basic_block default_label_bb
6107 = label_to_block_fn (func, CASE_LABEL (default_label));
6108 basic_block cur_bb = bb;
6110 auto_vec <edge> new_edges;
6111 auto_vec <phi_definition *> phi_todo_list;
6112 auto_vec <gcov_type> edge_counts;
6113 auto_vec <int> edge_probabilities;
6115 /* Investigate all labels that and PHI nodes in these edges which
6116 should be fixed after we add new collection of edges. */
6117 for (unsigned i = 0; i < labels; i++)
6119 tree label = gimple_switch_label (s, i);
6120 basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label));
6121 edge e = find_edge (bb, label_bb);
6122 edge_counts.safe_push (e->count);
6123 edge_probabilities.safe_push (e->probability);
6124 gphi_iterator phi_gsi;
6126 /* Save PHI definitions that will be destroyed because of an edge
6127 is going to be removed. */
6128 unsigned phi_index = 0;
6129 for (phi_gsi = gsi_start_phis (e->dest);
6130 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6132 gphi *phi = phi_gsi.phi ();
6133 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6135 if (gimple_phi_arg_edge (phi, j) == e)
6137 tree imm = gimple_phi_arg_def (phi, j);
6138 phi_definition *p = new phi_definition (phi_index, i,
6139 imm);
6140 phi_todo_list.safe_push (p);
6141 break;
6144 phi_index++;
6148 /* Remove all edges for the current basic block. */
6149 for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6151 edge e = EDGE_SUCC (bb, i);
6152 remove_edge (e);
6155 /* Iterate all non-default labels. */
6156 for (unsigned i = 1; i < labels; i++)
6158 tree label = gimple_switch_label (s, i);
6159 tree low = CASE_LOW (label);
6160 tree high = CASE_HIGH (label);
6162 if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6163 low = fold_convert (index_type, low);
6165 gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6166 gimple *c = NULL;
6167 if (high)
6169 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6170 "switch_cond_op1");
6172 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6173 index);
6175 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6176 "switch_cond_op2");
6178 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6179 high = fold_convert (index_type, high);
6180 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6181 high);
6183 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6184 "switch_cond_and");
6185 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6186 tmp2);
6188 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6189 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6190 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6192 tree b = constant_boolean_node (false, boolean_type_node);
6193 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6195 else
6196 c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6198 gimple_set_location (c, gimple_location (stmt));
6200 gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6202 basic_block label_bb
6203 = label_to_block_fn (func, CASE_LABEL (label));
6204 edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6205 int prob_sum = sum_slice <int> (edge_probabilities, i, labels) +
6206 edge_probabilities[0];
6208 if (prob_sum)
6209 new_edge->probability
6210 = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
6212 new_edge->count = edge_counts[i];
6213 new_edges.safe_push (new_edge);
6215 if (i < labels - 1)
6217 /* Prepare another basic block that will contain
6218 next condition. */
6219 basic_block next_bb = create_empty_bb (cur_bb);
6220 if (current_loops)
6222 add_bb_to_loop (next_bb, cur_bb->loop_father);
6223 loops_state_set (LOOPS_NEED_FIXUP);
6226 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6227 next_edge->probability
6228 = inverse_probability (new_edge->probability);
6229 next_edge->count = edge_counts[0]
6230 + sum_slice <gcov_type> (edge_counts, i, labels);
6231 next_bb->frequency = EDGE_FREQUENCY (next_edge);
6232 cur_bb = next_bb;
6234 else /* Link last IF statement and default label
6235 of the switch. */
6237 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6238 e->probability = inverse_probability (new_edge->probability);
6239 e->count = edge_counts[0];
6240 new_edges.safe_insert (0, e);
6244 /* Restore original PHI immediate value. */
6245 for (unsigned i = 0; i < phi_todo_list.length (); i++)
6247 phi_definition *phi_def = phi_todo_list[i];
6248 edge new_edge = new_edges[phi_def->label_index];
6250 gphi_iterator it = gsi_start_phis (new_edge->dest);
6251 for (unsigned i = 0; i < phi_def->phi_index; i++)
6252 gsi_next (&it);
6254 gphi *phi = it.phi ();
6255 add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6256 delete phi_def;
6259 /* Remove the original GIMPLE switch statement. */
6260 gsi_remove (&gsi, true);
6264 if (dump_file)
6265 dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6267 return modified_cfg;
6270 /* Expand builtins that can't be handled by HSA back-end. */
6272 static void
6273 expand_builtins ()
6275 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6276 basic_block bb;
6278 FOR_EACH_BB_FN (bb, func)
6280 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6281 gsi_next (&gsi))
6283 gimple *stmt = gsi_stmt (gsi);
6285 if (gimple_code (stmt) != GIMPLE_CALL)
6286 continue;
6288 gcall *call = as_a <gcall *> (stmt);
6290 if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6291 continue;
6293 tree fndecl = gimple_call_fndecl (stmt);
6294 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6295 switch (fn)
6297 case BUILT_IN_CEXPF:
6298 case BUILT_IN_CEXPIF:
6299 case BUILT_IN_CEXPI:
6301 /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6302 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z). */
6303 tree lhs = gimple_call_lhs (stmt);
6304 tree rhs = gimple_call_arg (stmt, 0);
6305 tree rhs_type = TREE_TYPE (rhs);
6306 bool float_type_p = rhs_type == float_type_node;
6307 tree real_part = make_temp_ssa_name (rhs_type, NULL,
6308 "cexp_real_part");
6309 tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6310 "cexp_imag_part");
6312 tree cos_fndecl
6313 = mathfn_built_in (rhs_type, fn == float_type_p
6314 ? BUILT_IN_COSF : BUILT_IN_COS);
6315 gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6316 gimple_call_set_lhs (cos, real_part);
6317 gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6319 tree sin_fndecl
6320 = mathfn_built_in (rhs_type, fn == float_type_p
6321 ? BUILT_IN_SINF : BUILT_IN_SIN);
6322 gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6323 gimple_call_set_lhs (sin, imag_part);
6324 gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6327 gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6328 real_part, imag_part);
6329 gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6330 gsi_remove (&gsi, true);
6332 break;
6334 default:
6335 break;
6341 /* Emit HSA module variables that are global for the entire module. */
6343 static void
6344 emit_hsa_module_variables (void)
6346 hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6347 BRIG_LINKAGE_MODULE, true);
6349 hsa_num_threads->m_name = "hsa_num_threads";
6351 hsa_brig_emit_omp_symbols ();
6354 /* Generate HSAIL representation of the current function and write into a
6355 special section of the output file. If KERNEL is set, the function will be
6356 considered an HSA kernel callable from the host, otherwise it will be
6357 compiled as an HSA function callable from other HSA code. */
6359 static void
6360 generate_hsa (bool kernel)
6362 hsa_init_data_for_cfun ();
6364 if (hsa_num_threads == NULL)
6365 emit_hsa_module_variables ();
6367 bool modified_cfg = convert_switch_statements ();
6368 /* Initialize hsa_cfun. */
6369 hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
6370 SSANAMES (cfun)->length (),
6371 modified_cfg);
6372 hsa_cfun->init_extra_bbs ();
6374 if (flag_tm)
6376 HSA_SORRY_AT (UNKNOWN_LOCATION,
6377 "support for HSA does not implement transactional memory");
6378 goto fail;
6381 verify_function_arguments (cfun->decl);
6382 if (hsa_seen_error ())
6383 goto fail;
6385 hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6387 gen_function_def_parameters ();
6388 if (hsa_seen_error ())
6389 goto fail;
6391 init_prologue ();
6393 gen_body_from_gimple ();
6394 if (hsa_seen_error ())
6395 goto fail;
6397 if (hsa_cfun->m_kernel_dispatch_count)
6398 init_hsa_num_threads ();
6400 if (hsa_cfun->m_kern_p)
6402 hsa_function_summary *s
6403 = hsa_summaries->get (cgraph_node::get (hsa_cfun->m_decl));
6404 hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6405 hsa_cfun->m_maximum_omp_data_size,
6406 s->m_gridified_kernel_p);
6409 if (flag_checking)
6411 for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6412 if (hsa_cfun->m_ssa_map[i])
6413 hsa_cfun->m_ssa_map[i]->verify_ssa ();
6415 basic_block bb;
6416 FOR_EACH_BB_FN (bb, cfun)
6418 hsa_bb *hbb = hsa_bb_for_bb (bb);
6420 for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6421 insn = insn->m_next)
6422 insn->verify ();
6426 hsa_regalloc ();
6427 hsa_brig_emit_function ();
6429 fail:
6430 hsa_deinit_data_for_cfun ();
6433 namespace {
6435 const pass_data pass_data_gen_hsail =
6437 GIMPLE_PASS,
6438 "hsagen", /* name */
6439 OPTGROUP_NONE, /* optinfo_flags */
6440 TV_NONE, /* tv_id */
6441 PROP_cfg | PROP_ssa, /* properties_required */
6442 0, /* properties_provided */
6443 0, /* properties_destroyed */
6444 0, /* todo_flags_start */
6445 0 /* todo_flags_finish */
6448 class pass_gen_hsail : public gimple_opt_pass
6450 public:
6451 pass_gen_hsail (gcc::context *ctxt)
6452 : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6455 /* opt_pass methods: */
6456 bool gate (function *);
6457 unsigned int execute (function *);
6459 }; // class pass_gen_hsail
6461 /* Determine whether or not to run generation of HSAIL. */
6463 bool
6464 pass_gen_hsail::gate (function *f)
6466 return hsa_gen_requested_p ()
6467 && hsa_gpu_implementation_p (f->decl);
6470 unsigned int
6471 pass_gen_hsail::execute (function *)
6473 hsa_function_summary *s
6474 = hsa_summaries->get (cgraph_node::get_create (current_function_decl));
6476 expand_builtins ();
6477 generate_hsa (s->m_kind == HSA_KERNEL);
6478 TREE_ASM_WRITTEN (current_function_decl) = 1;
6479 return TODO_discard_function;
6482 } // anon namespace
6484 /* Create the instance of hsa gen pass. */
6486 gimple_opt_pass *
6487 make_pass_gen_hsail (gcc::context *ctxt)
6489 return new pass_gen_hsail (ctxt);