2018-06-09 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / hsa-gen.c
blob173707d8b111bf52af450cd9304537cf4a47595a
1 /* A pass for lowering gimple to HSAIL
2 Copyright (C) 2013-2018 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 "function.h"
33 #include "basic-block.h"
34 #include "cfg.h"
35 #include "fold-const.h"
36 #include "gimple.h"
37 #include "gimple-iterator.h"
38 #include "bitmap.h"
39 #include "dumpfile.h"
40 #include "gimple-pretty-print.h"
41 #include "diagnostic-core.h"
42 #include "gimple-ssa.h"
43 #include "tree-phinodes.h"
44 #include "stringpool.h"
45 #include "tree-vrp.h"
46 #include "tree-ssanames.h"
47 #include "tree-dfa.h"
48 #include "ssa-iterators.h"
49 #include "cgraph.h"
50 #include "print-tree.h"
51 #include "symbol-summary.h"
52 #include "hsa-common.h"
53 #include "cfghooks.h"
54 #include "tree-cfg.h"
55 #include "cfgloop.h"
56 #include "cfganal.h"
57 #include "builtins.h"
58 #include "params.h"
59 #include "gomp-constants.h"
60 #include "internal-fn.h"
61 #include "builtins.h"
62 #include "stor-layout.h"
63 #include "stringpool.h"
64 #include "attribs.h"
66 /* Print a warning message and set that we have seen an error. */
68 #define HSA_SORRY_ATV(location, message, ...) \
69 do \
70 { \
71 hsa_fail_cfun (); \
72 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
73 HSA_SORRY_MSG)) \
74 inform (location, message, __VA_ARGS__); \
75 } \
76 while (false)
78 /* Same as previous, but highlight a location. */
80 #define HSA_SORRY_AT(location, message) \
81 do \
82 { \
83 hsa_fail_cfun (); \
84 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
85 HSA_SORRY_MSG)) \
86 inform (location, message); \
87 } \
88 while (false)
90 /* Default number of threads used by kernel dispatch. */
92 #define HSA_DEFAULT_NUM_THREADS 64
94 /* Following structures are defined in the final version
95 of HSA specification. */
97 /* HSA queue packet is shadow structure, originally provided by AMD. */
99 struct hsa_queue_packet
101 uint16_t header;
102 uint16_t setup;
103 uint16_t workgroup_size_x;
104 uint16_t workgroup_size_y;
105 uint16_t workgroup_size_z;
106 uint16_t reserved0;
107 uint32_t grid_size_x;
108 uint32_t grid_size_y;
109 uint32_t grid_size_z;
110 uint32_t private_segment_size;
111 uint32_t group_segment_size;
112 uint64_t kernel_object;
113 void *kernarg_address;
114 uint64_t reserved2;
115 uint64_t completion_signal;
118 /* HSA queue is shadow structure, originally provided by AMD. */
120 struct hsa_queue
122 int type;
123 uint32_t features;
124 void *base_address;
125 uint64_t doorbell_signal;
126 uint32_t size;
127 uint32_t reserved1;
128 uint64_t id;
131 static struct obstack hsa_obstack;
133 /* List of pointers to all instructions that come from an object allocator. */
134 static vec <hsa_insn_basic *> hsa_instructions;
136 /* List of pointers to all operands that come from an object allocator. */
137 static vec <hsa_op_base *> hsa_operands;
139 hsa_symbol::hsa_symbol ()
140 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
141 m_directive_offset (0), m_type (BRIG_TYPE_NONE),
142 m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
143 m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
144 m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
149 hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
150 BrigLinkage8_t linkage, bool global_scope_p,
151 BrigAllocation allocation, BrigAlignment8_t align)
152 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
153 m_directive_offset (0), m_type (type), m_segment (segment),
154 m_linkage (linkage), m_dim (0), m_cst_value (NULL),
155 m_global_scope_p (global_scope_p), m_seen_error (false),
156 m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
160 unsigned HOST_WIDE_INT
161 hsa_symbol::total_byte_size ()
163 unsigned HOST_WIDE_INT s
164 = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
165 gcc_assert (s % BITS_PER_UNIT == 0);
166 s /= BITS_PER_UNIT;
168 if (m_dim)
169 s *= m_dim;
171 return s;
174 /* Forward declaration. */
176 static BrigType16_t
177 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
178 bool min32int);
180 void
181 hsa_symbol::fillup_for_decl (tree decl)
183 m_decl = decl;
184 m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
185 if (hsa_seen_error ())
187 m_seen_error = true;
188 return;
191 m_align = MAX (m_align, hsa_natural_alignment (m_type));
194 /* Constructor of class representing global HSA function/kernel information and
195 state. FNDECL is function declaration, KERNEL_P is true if the function
196 is going to become a HSA kernel. If the function has body, SSA_NAMES_COUNT
197 should be set to number of SSA names used in the function.
198 MODIFIED_CFG is set to true in case we modified control-flow graph
199 of the function. */
201 hsa_function_representation::hsa_function_representation
202 (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
203 : m_name (NULL),
204 m_reg_count (0), m_input_args (vNULL),
205 m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
206 m_private_variables (vNULL), m_called_functions (vNULL),
207 m_called_internal_fns (vNULL), m_hbb_count (0),
208 m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
209 m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
210 m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
211 m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
212 m_modified_cfg (modified_cfg)
214 int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;
215 m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
216 m_ssa_map.safe_grow_cleared (ssa_names_count);
219 /* Constructor of class representing HSA function information that
220 is derived for an internal function. */
221 hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
222 : m_reg_count (0), m_input_args (vNULL),
223 m_output_arg (NULL), m_local_symbols (NULL),
224 m_spill_symbols (vNULL), m_global_symbols (vNULL),
225 m_private_variables (vNULL), m_called_functions (vNULL),
226 m_called_internal_fns (vNULL), m_hbb_count (0),
227 m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
228 m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
229 m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
230 m_ssa_map () {}
232 /* Destructor of class holding function/kernel-wide information and state. */
234 hsa_function_representation::~hsa_function_representation ()
236 /* Kernel names are deallocated at the end of BRIG output when deallocating
237 hsa_decl_kernel_mapping. */
238 if (!m_kern_p || m_seen_error)
239 free (m_name);
241 for (unsigned i = 0; i < m_input_args.length (); i++)
242 delete m_input_args[i];
243 m_input_args.release ();
245 delete m_output_arg;
246 delete m_local_symbols;
248 for (unsigned i = 0; i < m_spill_symbols.length (); i++)
249 delete m_spill_symbols[i];
250 m_spill_symbols.release ();
252 hsa_symbol *sym;
253 for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
254 if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
255 delete sym;
256 m_global_symbols.release ();
258 for (unsigned i = 0; i < m_private_variables.length (); i++)
259 delete m_private_variables[i];
260 m_private_variables.release ();
261 m_called_functions.release ();
262 m_ssa_map.release ();
264 for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
265 delete m_called_internal_fns[i];
268 hsa_op_reg *
269 hsa_function_representation::get_shadow_reg ()
271 /* If we compile a function with kernel dispatch and does not set
272 an optimization level, the function won't be inlined and
273 we return NULL. */
274 if (!m_kern_p)
275 return NULL;
277 if (m_shadow_reg)
278 return m_shadow_reg;
280 /* Append the shadow argument. */
281 hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
282 BRIG_LINKAGE_FUNCTION);
283 m_input_args.safe_push (shadow);
284 shadow->m_name = "hsa_runtime_shadow";
286 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
287 hsa_op_address *addr = new hsa_op_address (shadow);
289 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
290 hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
291 m_shadow_reg = r;
293 return r;
296 bool hsa_function_representation::has_shadow_reg_p ()
298 return m_shadow_reg != NULL;
301 void
302 hsa_function_representation::init_extra_bbs ()
304 hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
305 hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
308 void
309 hsa_function_representation::update_dominance ()
311 if (m_modified_cfg)
313 free_dominance_info (CDI_DOMINATORS);
314 calculate_dominance_info (CDI_DOMINATORS);
318 hsa_symbol *
319 hsa_function_representation::create_hsa_temporary (BrigType16_t type)
321 hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
322 BRIG_LINKAGE_FUNCTION);
323 s->m_name_number = m_temp_symbol_count++;
325 hsa_cfun->m_private_variables.safe_push (s);
326 return s;
329 BrigLinkage8_t
330 hsa_function_representation::get_linkage ()
332 if (m_internal_fn)
333 return BRIG_LINKAGE_PROGRAM;
335 return m_kern_p || TREE_PUBLIC (m_decl) ?
336 BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
339 /* Hash map of simple OMP builtins. */
340 static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
341 = NULL;
343 /* Warning messages for OMP builtins. */
345 #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
346 "lock routines"
347 #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
348 "timing routines"
349 #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
350 "undefined semantics within target regions, support for HSA ignores them"
351 #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
352 "affinity feateres"
354 /* Initialize hash map with simple OMP builtins. */
356 static void
357 hsa_init_simple_builtins ()
359 if (omp_simple_builtins != NULL)
360 return;
362 omp_simple_builtins
363 = new hash_map <nofree_string_hash, omp_simple_builtin> ();
365 omp_simple_builtin omp_builtins[] =
367 omp_simple_builtin ("omp_get_initial_device", NULL, false,
368 new hsa_op_immed (GOMP_DEVICE_HOST,
369 (BrigType16_t) BRIG_TYPE_S32)),
370 omp_simple_builtin ("omp_is_initial_device", NULL, false,
371 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
372 omp_simple_builtin ("omp_get_dynamic", NULL, false,
373 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
374 omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
375 omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
376 omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
377 true),
378 omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
379 true),
380 omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
381 omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
382 omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
383 omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
384 omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
385 omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
386 omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
387 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
388 omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
389 omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
390 false,
391 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
392 omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
393 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
394 omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
395 false,
396 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
397 omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
398 false,
399 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
400 omp_simple_builtin ("omp_target_disassociate_ptr",
401 HSA_WARN_MEMORY_ROUTINE,
402 false,
403 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
404 omp_simple_builtin ("omp_set_max_active_levels",
405 "Support for HSA only allows only one active level, "
406 "call to omp_set_max_active_levels will be ignored "
407 "in the generated HSAIL",
408 false, NULL),
409 omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
410 new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
411 omp_simple_builtin ("omp_in_final", NULL, false,
412 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
413 omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
414 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
415 omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
416 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
417 omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
418 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
419 omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
420 NULL),
421 omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
422 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
423 omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
424 false,
425 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
426 omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
427 false, NULL),
428 omp_simple_builtin ("omp_set_default_device",
429 "omp_set_default_device has undefined semantics "
430 "within target regions, support for HSA ignores it",
431 false, NULL),
432 omp_simple_builtin ("omp_get_default_device",
433 "omp_get_default_device has undefined semantics "
434 "within target regions, support for HSA ignores it",
435 false,
436 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
437 omp_simple_builtin ("omp_get_num_devices",
438 "omp_get_num_devices has undefined semantics "
439 "within target regions, support for HSA ignores it",
440 false,
441 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
442 omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
443 omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
444 omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
445 omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
446 omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
447 omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
448 omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
449 omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
450 omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
451 omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
454 unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
456 for (unsigned i = 0; i < count; i++)
457 omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
460 /* Allocate HSA structures that we need only while generating with this. */
462 static void
463 hsa_init_data_for_cfun ()
465 hsa_init_compilation_unit_data ();
466 gcc_obstack_init (&hsa_obstack);
469 /* Deinitialize HSA subsystem and free all allocated memory. */
471 static void
472 hsa_deinit_data_for_cfun (void)
474 basic_block bb;
476 FOR_ALL_BB_FN (bb, cfun)
477 if (bb->aux)
479 hsa_bb *hbb = hsa_bb_for_bb (bb);
480 hbb->~hsa_bb ();
481 bb->aux = NULL;
484 for (unsigned int i = 0; i < hsa_operands.length (); i++)
485 hsa_destroy_operand (hsa_operands[i]);
487 hsa_operands.release ();
489 for (unsigned i = 0; i < hsa_instructions.length (); i++)
490 hsa_destroy_insn (hsa_instructions[i]);
492 hsa_instructions.release ();
494 if (omp_simple_builtins != NULL)
496 delete omp_simple_builtins;
497 omp_simple_builtins = NULL;
500 obstack_free (&hsa_obstack, NULL);
501 delete hsa_cfun;
504 /* Return the type which holds addresses in the given SEGMENT. */
506 static BrigType16_t
507 hsa_get_segment_addr_type (BrigSegment8_t segment)
509 switch (segment)
511 case BRIG_SEGMENT_NONE:
512 gcc_unreachable ();
514 case BRIG_SEGMENT_FLAT:
515 case BRIG_SEGMENT_GLOBAL:
516 case BRIG_SEGMENT_READONLY:
517 case BRIG_SEGMENT_KERNARG:
518 return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
520 case BRIG_SEGMENT_GROUP:
521 case BRIG_SEGMENT_PRIVATE:
522 case BRIG_SEGMENT_SPILL:
523 case BRIG_SEGMENT_ARG:
524 return BRIG_TYPE_U32;
526 gcc_unreachable ();
529 /* Return integer brig type according to provided SIZE in bytes. If SIGN
530 is set to true, return signed integer type. */
532 static BrigType16_t
533 get_integer_type_by_bytes (unsigned size, bool sign)
535 if (sign)
536 switch (size)
538 case 1:
539 return BRIG_TYPE_S8;
540 case 2:
541 return BRIG_TYPE_S16;
542 case 4:
543 return BRIG_TYPE_S32;
544 case 8:
545 return BRIG_TYPE_S64;
546 default:
547 break;
549 else
550 switch (size)
552 case 1:
553 return BRIG_TYPE_U8;
554 case 2:
555 return BRIG_TYPE_U16;
556 case 4:
557 return BRIG_TYPE_U32;
558 case 8:
559 return BRIG_TYPE_U64;
560 default:
561 break;
564 return 0;
567 /* If T points to an integral type smaller than 32 bits, change it to a 32bit
568 equivalent and return the result. Otherwise just return the result. */
570 static BrigType16_t
571 hsa_extend_inttype_to_32bit (BrigType16_t t)
573 if (t == BRIG_TYPE_U8 || t == BRIG_TYPE_U16)
574 return BRIG_TYPE_U32;
575 else if (t == BRIG_TYPE_S8 || t == BRIG_TYPE_S16)
576 return BRIG_TYPE_S32;
577 return t;
580 /* Return HSA type for tree TYPE, which has to fit into BrigType16_t. Pointers
581 are assumed to use flat addressing. If min32int is true, always expand
582 integer types to one that has at least 32 bits. */
584 static BrigType16_t
585 hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
587 HOST_WIDE_INT bsize;
588 const_tree base;
589 BrigType16_t res = BRIG_TYPE_NONE;
591 gcc_checking_assert (TYPE_P (type));
592 gcc_checking_assert (!AGGREGATE_TYPE_P (type));
593 if (POINTER_TYPE_P (type))
594 return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
596 if (TREE_CODE (type) == VECTOR_TYPE)
597 base = TREE_TYPE (type);
598 else if (TREE_CODE (type) == COMPLEX_TYPE)
600 base = TREE_TYPE (type);
601 min32int = true;
603 else
604 base = type;
606 if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
608 HSA_SORRY_ATV (EXPR_LOCATION (type),
609 "support for HSA does not implement huge or "
610 "variable-sized type %qT", type);
611 return res;
614 bsize = tree_to_uhwi (TYPE_SIZE (base));
615 unsigned byte_size = bsize / BITS_PER_UNIT;
616 if (INTEGRAL_TYPE_P (base))
617 res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
618 else if (SCALAR_FLOAT_TYPE_P (base))
620 switch (bsize)
622 case 16:
623 res = BRIG_TYPE_F16;
624 break;
625 case 32:
626 res = BRIG_TYPE_F32;
627 break;
628 case 64:
629 res = BRIG_TYPE_F64;
630 break;
631 default:
632 break;
636 if (res == BRIG_TYPE_NONE)
638 HSA_SORRY_ATV (EXPR_LOCATION (type),
639 "support for HSA does not implement type %qT", type);
640 return res;
643 if (TREE_CODE (type) == VECTOR_TYPE)
645 HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
647 if (bsize == tsize)
649 HSA_SORRY_ATV (EXPR_LOCATION (type),
650 "support for HSA does not implement a vector type "
651 "where a type and unit size are equal: %qT", type);
652 return res;
655 switch (tsize)
657 case 32:
658 res |= BRIG_TYPE_PACK_32;
659 break;
660 case 64:
661 res |= BRIG_TYPE_PACK_64;
662 break;
663 case 128:
664 res |= BRIG_TYPE_PACK_128;
665 break;
666 default:
667 HSA_SORRY_ATV (EXPR_LOCATION (type),
668 "support for HSA does not implement type %qT", type);
672 if (min32int)
673 /* Registers/immediate operands can only be 32bit or more except for
674 f16. */
675 res = hsa_extend_inttype_to_32bit (res);
677 if (TREE_CODE (type) == COMPLEX_TYPE)
679 unsigned bsize = 2 * hsa_type_bit_size (res);
680 res = hsa_bittype_for_bitsize (bsize);
683 return res;
686 /* Returns the BRIG type we need to load/store entities of TYPE. */
688 static BrigType16_t
689 mem_type_for_type (BrigType16_t type)
691 /* HSA has non-intuitive constraints on load/store types. If it's
692 a bit-type it _must_ be B128, if it's not a bit-type it must be
693 64bit max. So for loading entities of 128 bits (e.g. vectors)
694 we have to use B128, while for loading the rest we have to use the
695 input type (??? or maybe also flattened to a equally sized non-vector
696 unsigned type?). */
697 if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
698 return BRIG_TYPE_B128;
699 else if (hsa_btype_p (type) || hsa_type_packed_p (type))
701 unsigned bitsize = hsa_type_bit_size (type);
702 if (bitsize < 128)
703 return hsa_uint_for_bitsize (bitsize);
704 else
705 return hsa_bittype_for_bitsize (bitsize);
707 return type;
710 /* Return HSA type for tree TYPE. If it cannot fit into BrigType16_t, some
711 kind of array will be generated, setting DIM appropriately. Otherwise, it
712 will be set to zero. */
714 static BrigType16_t
715 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
716 bool min32int = false)
718 gcc_checking_assert (TYPE_P (type));
719 if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
721 HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
722 "implement huge or variable-sized type %qT", type);
723 return BRIG_TYPE_NONE;
726 if (RECORD_OR_UNION_TYPE_P (type))
728 if (dim_p)
729 *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
730 return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
733 if (TREE_CODE (type) == ARRAY_TYPE)
735 /* We try to be nice and use the real base-type when this is an array of
736 scalars and only resort to an array of bytes if the type is more
737 complex. */
739 unsigned HOST_WIDE_INT dim = 1;
741 while (TREE_CODE (type) == ARRAY_TYPE)
743 tree domain = TYPE_DOMAIN (type);
744 if (!TYPE_MIN_VALUE (domain)
745 || !TYPE_MAX_VALUE (domain)
746 || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
747 || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
749 HSA_SORRY_ATV (EXPR_LOCATION (type),
750 "support for HSA does not implement array "
751 "%qT with unknown bounds", type);
752 return BRIG_TYPE_NONE;
754 HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
755 HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
756 dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
757 type = TREE_TYPE (type);
760 BrigType16_t res;
761 if (RECORD_OR_UNION_TYPE_P (type))
763 dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
764 res = BRIG_TYPE_U8;
766 else
767 res = hsa_type_for_scalar_tree_type (type, false);
769 if (dim_p)
770 *dim_p = dim;
771 return res | BRIG_TYPE_ARRAY;
774 /* Scalar case: */
775 if (dim_p)
776 *dim_p = 0;
778 return hsa_type_for_scalar_tree_type (type, min32int);
781 /* Returns true if converting from STYPE into DTYPE needs the _CVT
782 opcode. If false a normal _MOV is enough. */
784 static bool
785 hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
787 if (hsa_btype_p (dtype))
788 return false;
790 /* float <-> int conversions are real converts. */
791 if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
792 return true;
793 /* When both types have different size, then we need CVT as well. */
794 if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
795 return true;
796 return false;
799 /* Return declaration name if it exists or create one from UID if it does not.
800 If DECL is a local variable, make UID part of its name. */
802 const char *
803 hsa_get_declaration_name (tree decl)
805 if (!DECL_NAME (decl))
807 char buf[64];
808 snprintf (buf, 64, "__hsa_anon_%u", DECL_UID (decl));
809 size_t len = strlen (buf);
810 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
811 memcpy (copy, buf, len + 1);
812 return copy;
815 tree name_tree;
816 if (TREE_CODE (decl) == FUNCTION_DECL
817 || (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)))
818 name_tree = DECL_ASSEMBLER_NAME (decl);
819 else
820 name_tree = DECL_NAME (decl);
822 const char *name = IDENTIFIER_POINTER (name_tree);
823 /* User-defined assembly names have prepended asterisk symbol. */
824 if (name[0] == '*')
825 name++;
827 if ((TREE_CODE (decl) == VAR_DECL)
828 && decl_function_context (decl))
830 size_t len = strlen (name);
831 char *buf = (char *) alloca (len + 32);
832 snprintf (buf, len + 32, "%s_%u", name, DECL_UID (decl));
833 len = strlen (buf);
834 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
835 memcpy (copy, buf, len + 1);
836 return copy;
838 else
839 return name;
842 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
843 or lookup the hsa_structure corresponding to a PARM_DECL. */
845 static hsa_symbol *
846 get_symbol_for_decl (tree decl)
848 hsa_symbol **slot;
849 hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
851 gcc_assert (TREE_CODE (decl) == PARM_DECL
852 || TREE_CODE (decl) == RESULT_DECL
853 || TREE_CODE (decl) == VAR_DECL
854 || TREE_CODE (decl) == CONST_DECL);
856 dummy.m_decl = decl;
858 bool is_in_global_vars = ((TREE_CODE (decl) == VAR_DECL)
859 && !decl_function_context (decl));
861 if (is_in_global_vars)
862 slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
863 else
864 slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
866 gcc_checking_assert (slot);
867 if (*slot)
869 hsa_symbol *sym = (*slot);
871 /* If the symbol is problematic, mark current function also as
872 problematic. */
873 if (sym->m_seen_error)
874 hsa_fail_cfun ();
876 /* PR hsa/70234: If a global variable was marked to be emitted,
877 but HSAIL generation of a function using the variable fails,
878 we should retry to emit the variable in context of a different
879 function.
881 Iterate elements whether a symbol is already in m_global_symbols
882 of not. */
883 if (is_in_global_vars && !sym->m_emitted_to_brig)
885 for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
886 if (hsa_cfun->m_global_symbols[i] == sym)
887 return *slot;
888 hsa_cfun->m_global_symbols.safe_push (sym);
891 return *slot;
893 else
895 hsa_symbol *sym;
896 /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols. */
897 gcc_assert (TREE_CODE (decl) == VAR_DECL
898 || TREE_CODE (decl) == CONST_DECL);
899 BrigAlignment8_t align = hsa_object_alignment (decl);
901 if (is_in_global_vars)
903 gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
904 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
905 BRIG_LINKAGE_PROGRAM, true,
906 BRIG_ALLOCATION_PROGRAM, align);
907 hsa_cfun->m_global_symbols.safe_push (sym);
908 sym->fillup_for_decl (decl);
909 if (sym->m_align > align)
911 sym->m_seen_error = true;
912 HSA_SORRY_ATV (EXPR_LOCATION (decl),
913 "HSA specification requires that %E is at least "
914 "naturally aligned", decl);
917 else
919 /* As generation of efficient memory copy instructions relies
920 on alignment greater or equal to 8 bytes,
921 we need to increase alignment of all aggregate types.. */
922 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
923 align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
925 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
926 BrigSegment8_t segment;
927 if (TREE_CODE (decl) == CONST_DECL)
929 segment = BRIG_SEGMENT_READONLY;
930 allocation = BRIG_ALLOCATION_AGENT;
932 else if (lookup_attribute ("hsa_group_segment",
933 DECL_ATTRIBUTES (decl)))
934 segment = BRIG_SEGMENT_GROUP;
935 else if (TREE_STATIC (decl))
937 segment = BRIG_SEGMENT_GLOBAL;
938 allocation = BRIG_ALLOCATION_PROGRAM;
940 else if (lookup_attribute ("hsa_global_segment",
941 DECL_ATTRIBUTES (decl)))
942 segment = BRIG_SEGMENT_GLOBAL;
943 else
944 segment = BRIG_SEGMENT_PRIVATE;
946 sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
947 false, allocation, align);
948 sym->fillup_for_decl (decl);
949 hsa_cfun->m_private_variables.safe_push (sym);
952 sym->m_name = hsa_get_declaration_name (decl);
953 *slot = sym;
954 return sym;
958 /* For a given HSA function declaration, return a host
959 function declaration. */
961 tree
962 hsa_get_host_function (tree decl)
964 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
965 gcc_assert (s->m_gpu_implementation_p);
967 return s->m_bound_function ? s->m_bound_function->decl : NULL;
970 /* Return true if function DECL has a host equivalent function. */
972 static char *
973 get_brig_function_name (tree decl)
975 tree d = decl;
977 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
978 if (s != NULL
979 && s->m_gpu_implementation_p
980 && s->m_bound_function)
981 d = s->m_bound_function->decl;
983 /* IPA split can create a function that has no host equivalent. */
984 if (d == NULL)
985 d = decl;
987 char *name = xstrdup (hsa_get_declaration_name (d));
988 hsa_sanitize_name (name);
990 return name;
993 /* Create a spill symbol of type TYPE. */
995 hsa_symbol *
996 hsa_get_spill_symbol (BrigType16_t type)
998 hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
999 BRIG_LINKAGE_FUNCTION);
1000 hsa_cfun->m_spill_symbols.safe_push (sym);
1001 return sym;
1004 /* Create a symbol for a read-only string constant. */
1005 hsa_symbol *
1006 hsa_get_string_cst_symbol (tree string_cst)
1008 gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
1010 hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
1011 if (slot)
1012 return *slot;
1014 hsa_op_immed *cst = new hsa_op_immed (string_cst);
1015 hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
1016 BRIG_LINKAGE_MODULE, true,
1017 BRIG_ALLOCATION_AGENT);
1018 sym->m_cst_value = cst;
1019 sym->m_dim = TREE_STRING_LENGTH (string_cst);
1020 sym->m_name_number = hsa_cfun->m_global_symbols.length ();
1022 hsa_cfun->m_global_symbols.safe_push (sym);
1023 hsa_cfun->m_string_constants_map.put (string_cst, sym);
1024 return sym;
1027 /* Make the type of a MOV instruction larger if mandated by HSAIL rules. */
1029 static void
1030 hsa_fixup_mov_insn_type (hsa_insn_basic *insn)
1032 insn->m_type = hsa_extend_inttype_to_32bit (insn->m_type);
1033 if (insn->m_type == BRIG_TYPE_B8 || insn->m_type == BRIG_TYPE_B16)
1034 insn->m_type = BRIG_TYPE_B32;
1037 /* Constructor of the ancestor of all operands. K is BRIG kind that identified
1038 what the operator is. */
1040 hsa_op_base::hsa_op_base (BrigKind16_t k)
1041 : m_next (NULL), m_brig_op_offset (0), m_kind (k)
1043 hsa_operands.safe_push (this);
1046 /* Constructor of ancestor of all operands which have a type. K is BRIG kind
1047 that identified what the operator is. T is the type of the operator. */
1049 hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
1050 : hsa_op_base (k), m_type (t)
1054 hsa_op_with_type *
1055 hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
1057 if (m_type == dtype)
1058 return this;
1060 hsa_op_reg *dest;
1062 if (hsa_needs_cvt (dtype, m_type))
1064 dest = new hsa_op_reg (dtype);
1065 hbb->append_insn (new hsa_insn_cvt (dest, this));
1067 else if (is_a <hsa_op_reg *> (this))
1069 /* In the end, HSA registers do not really have types, only sizes, so if
1070 the sizes match, we can use the register directly. */
1071 gcc_checking_assert (hsa_type_bit_size (dtype)
1072 == hsa_type_bit_size (m_type));
1073 return this;
1075 else
1077 dest = new hsa_op_reg (m_type);
1079 hsa_insn_basic *mov = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
1080 dest->m_type, dest, this);
1081 hsa_fixup_mov_insn_type (mov);
1082 hbb->append_insn (mov);
1083 /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
1084 type of the operand must be same as type of the instruction. */
1085 dest->m_type = dtype;
1088 return dest;
1091 /* If this operand has integer type smaller than 32 bits, extend it to 32 bits,
1092 adding instructions to HBB if needed. */
1094 hsa_op_with_type *
1095 hsa_op_with_type::extend_int_to_32bit (hsa_bb *hbb)
1097 if (m_type == BRIG_TYPE_U8 || m_type == BRIG_TYPE_U16)
1098 return get_in_type (BRIG_TYPE_U32, hbb);
1099 else if (m_type == BRIG_TYPE_S8 || m_type == BRIG_TYPE_S16)
1100 return get_in_type (BRIG_TYPE_S32, hbb);
1101 else
1102 return this;
1105 /* Constructor of class representing HSA immediate values. TREE_VAL is the
1106 tree representation of the immediate value. If min32int is true,
1107 always expand integer types to one that has at least 32 bits. */
1109 hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
1110 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
1111 hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
1112 min32int))
1114 if (hsa_seen_error ())
1115 return;
1117 gcc_checking_assert ((is_gimple_min_invariant (tree_val)
1118 && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
1119 || TREE_CODE (tree_val) == INTEGER_CST))
1120 || TREE_CODE (tree_val) == CONSTRUCTOR);
1121 m_tree_value = tree_val;
1123 /* Verify that all elements of a constructor are constants. */
1124 if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
1125 for (unsigned i = 0; i < CONSTRUCTOR_NELTS (m_tree_value); i++)
1127 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
1128 if (!CONSTANT_CLASS_P (v))
1130 HSA_SORRY_AT (EXPR_LOCATION (tree_val),
1131 "HSA ctor should have only constants");
1132 return;
1137 /* Constructor of class representing HSA immediate values. INTEGER_VALUE is the
1138 integer representation of the immediate value. TYPE is BRIG type. */
1140 hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
1141 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
1142 m_tree_value (NULL)
1144 gcc_assert (hsa_type_integer_p (type));
1145 m_int_value = integer_value;
1148 hsa_op_immed::hsa_op_immed ()
1149 : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
1153 /* New operator to allocate immediate operands from obstack. */
1155 void *
1156 hsa_op_immed::operator new (size_t size)
1158 return obstack_alloc (&hsa_obstack, size);
1161 /* Destructor. */
1163 hsa_op_immed::~hsa_op_immed ()
1167 /* Change type of the immediate value to T. */
1169 void
1170 hsa_op_immed::set_type (BrigType16_t t)
1172 m_type = t;
1175 /* Constructor of class representing HSA registers and pseudo-registers. T is
1176 the BRIG type of the new register. */
1178 hsa_op_reg::hsa_op_reg (BrigType16_t t)
1179 : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
1180 m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
1181 m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
1185 /* New operator to allocate a register from obstack. */
1187 void *
1188 hsa_op_reg::operator new (size_t size)
1190 return obstack_alloc (&hsa_obstack, size);
1193 /* Verify register operand. */
1195 void
1196 hsa_op_reg::verify_ssa ()
1198 /* Verify that each HSA register has a definition assigned.
1199 Exceptions are VAR_DECL and PARM_DECL that are a default
1200 definition. */
1201 gcc_checking_assert (m_def_insn
1202 || (m_gimple_ssa != NULL
1203 && (!SSA_NAME_VAR (m_gimple_ssa)
1204 || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
1205 != PARM_DECL))
1206 && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
1208 /* Verify that every use of the register is really present
1209 in an instruction. */
1210 for (unsigned i = 0; i < m_uses.length (); i++)
1212 hsa_insn_basic *use = m_uses[i];
1214 bool is_visited = false;
1215 for (unsigned j = 0; j < use->operand_count (); j++)
1217 hsa_op_base *u = use->get_op (j);
1218 hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
1219 if (addr && addr->m_reg)
1220 u = addr->m_reg;
1222 if (u == this)
1224 bool r = !addr && use->op_output_p (j);
1226 if (r)
1228 error ("HSA SSA name defined by instruction that is supposed "
1229 "to be using it");
1230 debug_hsa_operand (this);
1231 debug_hsa_insn (use);
1232 internal_error ("HSA SSA verification failed");
1235 is_visited = true;
1239 if (!is_visited)
1241 error ("HSA SSA name not among operands of instruction that is "
1242 "supposed to use it");
1243 debug_hsa_operand (this);
1244 debug_hsa_insn (use);
1245 internal_error ("HSA SSA verification failed");
1250 hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
1251 HOST_WIDE_INT offset)
1252 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
1253 m_imm_offset (offset)
1257 hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
1258 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
1259 m_imm_offset (offset)
1263 hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
1264 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
1265 m_imm_offset (offset)
1269 /* New operator to allocate address operands from obstack. */
1271 void *
1272 hsa_op_address::operator new (size_t size)
1274 return obstack_alloc (&hsa_obstack, size);
1277 /* Constructor of an operand referring to HSAIL code. */
1279 hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
1280 m_directive_offset (0)
1284 /* Constructor of an operand representing a code list. Set it up so that it
1285 can contain ELEMENTS number of elements. */
1287 hsa_op_code_list::hsa_op_code_list (unsigned elements)
1288 : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
1290 m_offsets.create (1);
1291 m_offsets.safe_grow_cleared (elements);
1294 /* New operator to allocate code list operands from obstack. */
1296 void *
1297 hsa_op_code_list::operator new (size_t size)
1299 return obstack_alloc (&hsa_obstack, size);
1302 /* Constructor of an operand representing an operand list.
1303 Set it up so that it can contain ELEMENTS number of elements. */
1305 hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
1306 : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
1308 m_offsets.create (elements);
1309 m_offsets.safe_grow (elements);
1312 /* New operator to allocate operand list operands from obstack. */
1314 void *
1315 hsa_op_operand_list::operator new (size_t size)
1317 return obstack_alloc (&hsa_obstack, size);
1320 hsa_op_operand_list::~hsa_op_operand_list ()
1322 m_offsets.release ();
1326 hsa_op_reg *
1327 hsa_function_representation::reg_for_gimple_ssa (tree ssa)
1329 hsa_op_reg *hreg;
1331 gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
1332 if (m_ssa_map[SSA_NAME_VERSION (ssa)])
1333 return m_ssa_map[SSA_NAME_VERSION (ssa)];
1335 hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
1336 false));
1337 hreg->m_gimple_ssa = ssa;
1338 m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
1340 return hreg;
1343 void
1344 hsa_op_reg::set_definition (hsa_insn_basic *insn)
1346 if (hsa_cfun->m_in_ssa)
1348 gcc_checking_assert (!m_def_insn);
1349 m_def_insn = insn;
1351 else
1352 m_def_insn = NULL;
1355 /* Constructor of the class which is the bases of all instructions and directly
1356 represents the most basic ones. NOPS is the number of operands that the
1357 operand vector will contain (and which will be cleared). OP is the opcode
1358 of the instruction. This constructor does not set type. */
1360 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
1361 : m_prev (NULL),
1362 m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
1363 m_type (BRIG_TYPE_NONE), m_brig_offset (0)
1365 if (nops > 0)
1366 m_operands.safe_grow_cleared (nops);
1368 hsa_instructions.safe_push (this);
1371 /* Make OP the operand number INDEX of operands of this instruction. If OP is a
1372 register or an address containing a register, then either set the definition
1373 of the register to this instruction if it an output operand or add this
1374 instruction to the uses if it is an input one. */
1376 void
1377 hsa_insn_basic::set_op (int index, hsa_op_base *op)
1379 /* Each address operand is always use. */
1380 hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
1381 if (addr && addr->m_reg)
1382 addr->m_reg->m_uses.safe_push (this);
1383 else
1385 hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
1386 if (reg)
1388 if (op_output_p (index))
1389 reg->set_definition (this);
1390 else
1391 reg->m_uses.safe_push (this);
1395 m_operands[index] = op;
1398 /* Get INDEX-th operand of the instruction. */
1400 hsa_op_base *
1401 hsa_insn_basic::get_op (int index)
1403 return m_operands[index];
1406 /* Get address of INDEX-th operand of the instruction. */
1408 hsa_op_base **
1409 hsa_insn_basic::get_op_addr (int index)
1411 return &m_operands[index];
1414 /* Get number of operands of the instruction. */
1415 unsigned int
1416 hsa_insn_basic::operand_count ()
1418 return m_operands.length ();
1421 /* Constructor of the class which is the bases of all instructions and directly
1422 represents the most basic ones. NOPS is the number of operands that the
1423 operand vector will contain (and which will be cleared). OPC is the opcode
1424 of the instruction, T is the type of the instruction. */
1426 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
1427 hsa_op_base *arg0, hsa_op_base *arg1,
1428 hsa_op_base *arg2, hsa_op_base *arg3)
1429 : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
1430 m_type (t), m_brig_offset (0)
1432 if (nops > 0)
1433 m_operands.safe_grow_cleared (nops);
1435 if (arg0 != NULL)
1437 gcc_checking_assert (nops >= 1);
1438 set_op (0, arg0);
1441 if (arg1 != NULL)
1443 gcc_checking_assert (nops >= 2);
1444 set_op (1, arg1);
1447 if (arg2 != NULL)
1449 gcc_checking_assert (nops >= 3);
1450 set_op (2, arg2);
1453 if (arg3 != NULL)
1455 gcc_checking_assert (nops >= 4);
1456 set_op (3, arg3);
1459 hsa_instructions.safe_push (this);
1462 /* New operator to allocate basic instruction from obstack. */
1464 void *
1465 hsa_insn_basic::operator new (size_t size)
1467 return obstack_alloc (&hsa_obstack, size);
1470 /* Verify the instruction. */
1472 void
1473 hsa_insn_basic::verify ()
1475 hsa_op_address *addr;
1476 hsa_op_reg *reg;
1478 /* Iterate all register operands and verify that the instruction
1479 is set in uses of the register. */
1480 for (unsigned i = 0; i < operand_count (); i++)
1482 hsa_op_base *use = get_op (i);
1484 if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
1486 gcc_assert (addr->m_reg->m_def_insn != this);
1487 use = addr->m_reg;
1490 if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
1492 unsigned j;
1493 for (j = 0; j < reg->m_uses.length (); j++)
1495 if (reg->m_uses[j] == this)
1496 break;
1499 if (j == reg->m_uses.length ())
1501 error ("HSA instruction uses a register but is not among "
1502 "recorded register uses");
1503 debug_hsa_operand (reg);
1504 debug_hsa_insn (this);
1505 internal_error ("HSA instruction verification failed");
1511 /* Constructor of an instruction representing a PHI node. NOPS is the number
1512 of operands (equal to the number of predecessors). */
1514 hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
1515 : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
1517 dst->set_definition (this);
1520 /* Constructor of class representing instructions for control flow and
1521 sychronization, */
1523 hsa_insn_br::hsa_insn_br (unsigned nops, int opc, BrigType16_t t,
1524 BrigWidth8_t width, hsa_op_base *arg0,
1525 hsa_op_base *arg1, hsa_op_base *arg2,
1526 hsa_op_base *arg3)
1527 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1528 m_width (width)
1532 /* Constructor of class representing instruction for conditional jump, CTRL is
1533 the control register determining whether the jump will be carried out, the
1534 new instruction is automatically added to its uses list. */
1536 hsa_insn_cbr::hsa_insn_cbr (hsa_op_reg *ctrl)
1537 : hsa_insn_br (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, BRIG_WIDTH_1, ctrl)
1541 /* Constructor of class representing instruction for switch jump, CTRL is
1542 the index register. */
1544 hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
1545 : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
1546 m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
1547 m_label_code_list (new hsa_op_code_list (jump_count))
1551 /* Replace all occurrences of OLD_BB with NEW_BB in the statements
1552 jump table. */
1554 void
1555 hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
1557 for (unsigned i = 0; i < m_jump_table.length (); i++)
1558 if (m_jump_table[i] == old_bb)
1559 m_jump_table[i] = new_bb;
1562 hsa_insn_sbr::~hsa_insn_sbr ()
1564 m_jump_table.release ();
1567 /* Constructor of comparison instruction. CMP is the comparison operation and T
1568 is the result type. */
1570 hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
1571 hsa_op_base *arg0, hsa_op_base *arg1,
1572 hsa_op_base *arg2)
1573 : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
1577 /* Constructor of classes representing memory accesses. OPC is the opcode (must
1578 be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type. The instruction
1579 operands are provided as ARG0 and ARG1. */
1581 hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
1582 hsa_op_base *arg1)
1583 : hsa_insn_basic (2, opc, t, arg0, arg1),
1584 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1586 gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
1589 /* Constructor for descendants allowing different opcodes and number of
1590 operands, it passes its arguments directly to hsa_insn_basic
1591 constructor. The instruction operands are provided as ARG[0-3]. */
1594 hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
1595 hsa_op_base *arg0, hsa_op_base *arg1,
1596 hsa_op_base *arg2, hsa_op_base *arg3)
1597 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1598 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1602 /* Constructor of class representing atomic instructions. OPC is the principal
1603 opcode, AOP is the specific atomic operation opcode. T is the type of the
1604 instruction. The instruction operands are provided as ARG[0-3]. */
1606 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
1607 enum BrigAtomicOperation aop,
1608 BrigType16_t t, BrigMemoryOrder memorder,
1609 hsa_op_base *arg0,
1610 hsa_op_base *arg1, hsa_op_base *arg2,
1611 hsa_op_base *arg3)
1612 : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
1613 m_memoryorder (memorder),
1614 m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
1616 gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
1617 opc == BRIG_OPCODE_ATOMIC ||
1618 opc == BRIG_OPCODE_SIGNAL ||
1619 opc == BRIG_OPCODE_SIGNALNORET);
1622 /* Constructor of class representing signal instructions. OPC is the prinicpal
1623 opcode, SOP is the specific signal operation opcode. T is the type of the
1624 instruction. The instruction operands are provided as ARG[0-3]. */
1626 hsa_insn_signal::hsa_insn_signal (int nops, int opc,
1627 enum BrigAtomicOperation sop,
1628 BrigType16_t t, BrigMemoryOrder memorder,
1629 hsa_op_base *arg0, hsa_op_base *arg1,
1630 hsa_op_base *arg2, hsa_op_base *arg3)
1631 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1632 m_memory_order (memorder), m_signalop (sop)
1636 /* Constructor of class representing segment conversion instructions. OPC is
1637 the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS. DEST
1638 and SRCT are destination and source types respectively, SEG is the segment
1639 we are converting to or from. The instruction operands are
1640 provided as ARG0 and ARG1. */
1642 hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
1643 BrigSegment8_t seg, hsa_op_base *arg0,
1644 hsa_op_base *arg1)
1645 : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
1646 m_segment (seg)
1648 gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
1651 /* Constructor of class representing a call instruction. CALLEE is the tree
1652 representation of the function being called. */
1654 hsa_insn_call::hsa_insn_call (tree callee)
1655 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
1656 m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
1660 hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
1661 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
1662 m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
1663 m_result_code_list (NULL)
1667 hsa_insn_call::~hsa_insn_call ()
1669 for (unsigned i = 0; i < m_input_args.length (); i++)
1670 delete m_input_args[i];
1672 delete m_output_arg;
1674 m_input_args.release ();
1675 m_input_arg_insns.release ();
1678 /* Constructor of class representing the argument block required to invoke
1679 a call in HSAIL. */
1680 hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
1681 hsa_insn_call * call)
1682 : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
1683 m_call_insn (call)
1687 hsa_insn_comment::hsa_insn_comment (const char *s)
1688 : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
1690 unsigned l = strlen (s);
1692 /* Append '// ' to the string. */
1693 char *buf = XNEWVEC (char, l + 4);
1694 sprintf (buf, "// %s", s);
1695 m_comment = buf;
1698 hsa_insn_comment::~hsa_insn_comment ()
1700 gcc_checking_assert (m_comment);
1701 free (m_comment);
1702 m_comment = NULL;
1705 /* Constructor of class representing the queue instruction in HSAIL. */
1707 hsa_insn_queue::hsa_insn_queue (int nops, int opcode, BrigSegment segment,
1708 BrigMemoryOrder memory_order,
1709 hsa_op_base *arg0, hsa_op_base *arg1,
1710 hsa_op_base *arg2, hsa_op_base *arg3)
1711 : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64, arg0, arg1, arg2, arg3),
1712 m_segment (segment), m_memory_order (memory_order)
1716 /* Constructor of class representing the source type instruction in HSAIL. */
1718 hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
1719 BrigType16_t destt, BrigType16_t srct,
1720 hsa_op_base *arg0, hsa_op_base *arg1,
1721 hsa_op_base *arg2 = NULL)
1722 : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
1723 m_source_type (srct)
1726 /* Constructor of class representing the packed instruction in HSAIL. */
1728 hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
1729 BrigType16_t destt, BrigType16_t srct,
1730 hsa_op_base *arg0, hsa_op_base *arg1,
1731 hsa_op_base *arg2)
1732 : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
1734 m_operand_list = new hsa_op_operand_list (nops - 1);
1737 /* Constructor of class representing the convert instruction in HSAIL. */
1739 hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
1740 : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
1744 /* Constructor of class representing the alloca in HSAIL. */
1746 hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
1747 hsa_op_with_type *size, unsigned alignment)
1748 : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
1749 m_align (BRIG_ALIGNMENT_8)
1751 gcc_assert (dest->m_type == BRIG_TYPE_U32);
1752 if (alignment)
1753 m_align = hsa_alignment_encoding (alignment);
1756 /* Append an instruction INSN into the basic block. */
1758 void
1759 hsa_bb::append_insn (hsa_insn_basic *insn)
1761 gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
1762 gcc_assert (!insn->m_bb);
1764 insn->m_bb = m_bb;
1765 insn->m_prev = m_last_insn;
1766 insn->m_next = NULL;
1767 if (m_last_insn)
1768 m_last_insn->m_next = insn;
1769 m_last_insn = insn;
1770 if (!m_first_insn)
1771 m_first_insn = insn;
1774 void
1775 hsa_bb::append_phi (hsa_insn_phi *hphi)
1777 hphi->m_bb = m_bb;
1779 hphi->m_prev = m_last_phi;
1780 hphi->m_next = NULL;
1781 if (m_last_phi)
1782 m_last_phi->m_next = hphi;
1783 m_last_phi = hphi;
1784 if (!m_first_phi)
1785 m_first_phi = hphi;
1788 /* Insert HSA instruction NEW_INSN immediately before an existing instruction
1789 OLD_INSN. */
1791 static void
1792 hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1794 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1796 if (hbb->m_first_insn == old_insn)
1797 hbb->m_first_insn = new_insn;
1798 new_insn->m_prev = old_insn->m_prev;
1799 new_insn->m_next = old_insn;
1800 if (old_insn->m_prev)
1801 old_insn->m_prev->m_next = new_insn;
1802 old_insn->m_prev = new_insn;
1805 /* Append HSA instruction NEW_INSN immediately after an existing instruction
1806 OLD_INSN. */
1808 static void
1809 hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1811 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1813 if (hbb->m_last_insn == old_insn)
1814 hbb->m_last_insn = new_insn;
1815 new_insn->m_prev = old_insn;
1816 new_insn->m_next = old_insn->m_next;
1817 if (old_insn->m_next)
1818 old_insn->m_next->m_prev = new_insn;
1819 old_insn->m_next = new_insn;
1822 /* Return a register containing the calculated value of EXP which must be an
1823 expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
1824 integer constants as returned by get_inner_reference.
1825 Newly generated HSA instructions will be appended to HBB.
1826 Perform all calculations in ADDRTYPE. */
1828 static hsa_op_with_type *
1829 gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
1831 int opcode;
1833 if (TREE_CODE (exp) == NOP_EXPR)
1834 exp = TREE_OPERAND (exp, 0);
1836 switch (TREE_CODE (exp))
1838 case SSA_NAME:
1839 return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
1841 case INTEGER_CST:
1843 hsa_op_immed *imm = new hsa_op_immed (exp);
1844 if (addrtype != imm->m_type)
1845 imm->m_type = addrtype;
1846 return imm;
1849 case PLUS_EXPR:
1850 opcode = BRIG_OPCODE_ADD;
1851 break;
1853 case MULT_EXPR:
1854 opcode = BRIG_OPCODE_MUL;
1855 break;
1857 default:
1858 gcc_unreachable ();
1861 hsa_op_reg *res = new hsa_op_reg (addrtype);
1862 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
1863 insn->set_op (0, res);
1865 hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
1866 addrtype);
1867 hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
1868 addrtype);
1869 insn->set_op (1, op1);
1870 insn->set_op (2, op2);
1872 hbb->append_insn (insn);
1873 return res;
1876 /* If R1 is NULL, just return R2, otherwise append an instruction adding them
1877 to HBB and return the register holding the result. */
1879 static hsa_op_reg *
1880 add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
1882 gcc_checking_assert (r2);
1883 if (!r1)
1884 return r2;
1886 hsa_op_reg *res = new hsa_op_reg (r1->m_type);
1887 gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
1888 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
1889 insn->set_op (0, res);
1890 insn->set_op (1, r1);
1891 insn->set_op (2, r2);
1892 hbb->append_insn (insn);
1893 return res;
1896 /* Helper of gen_hsa_addr. Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
1897 reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF. */
1899 static void
1900 process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
1901 hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
1903 if (TREE_CODE (base) == SSA_NAME)
1905 gcc_assert (!*reg);
1906 hsa_op_with_type *ssa
1907 = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
1908 *reg = dyn_cast <hsa_op_reg *> (ssa);
1910 else if (TREE_CODE (base) == ADDR_EXPR)
1912 tree decl = TREE_OPERAND (base, 0);
1914 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
1916 HSA_SORRY_AT (EXPR_LOCATION (base),
1917 "support for HSA does not implement a memory reference "
1918 "to a non-declaration type");
1919 return;
1922 gcc_assert (!*symbol);
1924 *symbol = get_symbol_for_decl (decl);
1925 *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
1927 else if (TREE_CODE (base) == INTEGER_CST)
1928 *offset += wi::to_offset (base);
1929 else
1930 gcc_unreachable ();
1933 /* Forward declaration of a function. */
1935 static void
1936 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
1938 /* Generate HSA address operand for a given tree memory reference REF. If
1939 instructions need to be created to calculate the address, they will be added
1940 to the end of HBB. If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
1941 the function assumes that the caller will handle possible
1942 bit-field references. Otherwise if we reference a bit-field, sorry message
1943 is displayed. */
1945 static hsa_op_address *
1946 gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
1947 HOST_WIDE_INT *output_bitpos = NULL)
1949 hsa_symbol *symbol = NULL;
1950 hsa_op_reg *reg = NULL;
1951 offset_int offset = 0;
1952 tree origref = ref;
1953 tree varoffset = NULL_TREE;
1954 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1955 HOST_WIDE_INT bitsize = 0, bitpos = 0;
1956 BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1958 if (TREE_CODE (ref) == STRING_CST)
1960 symbol = hsa_get_string_cst_symbol (ref);
1961 goto out;
1963 else if (TREE_CODE (ref) == BIT_FIELD_REF
1964 && (!multiple_p (bit_field_size (ref), BITS_PER_UNIT)
1965 || !multiple_p (bit_field_offset (ref), BITS_PER_UNIT)))
1967 HSA_SORRY_ATV (EXPR_LOCATION (origref),
1968 "support for HSA does not implement "
1969 "bit field references such as %E", ref);
1970 goto out;
1973 if (handled_component_p (ref))
1975 machine_mode mode;
1976 int unsignedp, volatilep, preversep;
1977 poly_int64 pbitsize, pbitpos;
1978 tree new_ref;
1980 new_ref = get_inner_reference (ref, &pbitsize, &pbitpos, &varoffset,
1981 &mode, &unsignedp, &preversep,
1982 &volatilep);
1983 /* When this isn't true, the switch below will report an
1984 appropriate error. */
1985 if (pbitsize.is_constant () && pbitpos.is_constant ())
1987 bitsize = pbitsize.to_constant ();
1988 bitpos = pbitpos.to_constant ();
1989 ref = new_ref;
1990 offset = bitpos;
1991 offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
1995 switch (TREE_CODE (ref))
1997 case ADDR_EXPR:
1999 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2000 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2001 hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
2002 gen_hsa_addr_insns (ref, r, hbb);
2003 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2004 r, new hsa_op_address (symbol)));
2006 break;
2008 case SSA_NAME:
2010 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2011 hsa_op_with_type *r = hsa_cfun->reg_for_gimple_ssa (ref);
2012 if (r->m_type == BRIG_TYPE_B1)
2013 r = r->get_in_type (BRIG_TYPE_U32, hbb);
2014 symbol = hsa_cfun->create_hsa_temporary (r->m_type);
2016 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2017 r, new hsa_op_address (symbol)));
2019 break;
2021 case PARM_DECL:
2022 case VAR_DECL:
2023 case RESULT_DECL:
2024 case CONST_DECL:
2025 gcc_assert (!symbol);
2026 symbol = get_symbol_for_decl (ref);
2027 addrtype = hsa_get_segment_addr_type (symbol->m_segment);
2028 break;
2030 case MEM_REF:
2031 process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
2032 &offset, hbb);
2034 if (!integer_zerop (TREE_OPERAND (ref, 1)))
2035 offset += wi::to_offset (TREE_OPERAND (ref, 1));
2036 break;
2038 case TARGET_MEM_REF:
2039 process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
2040 if (TMR_INDEX (ref))
2042 hsa_op_reg *disp1;
2043 hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
2044 (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
2045 if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
2047 disp1 = new hsa_op_reg (addrtype);
2048 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
2049 addrtype);
2051 /* As step must respect addrtype, we overwrite the type
2052 of an immediate value. */
2053 hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
2054 step->m_type = addrtype;
2056 insn->set_op (0, disp1);
2057 insn->set_op (1, idx);
2058 insn->set_op (2, step);
2059 hbb->append_insn (insn);
2061 else
2062 disp1 = as_a <hsa_op_reg *> (idx);
2063 reg = add_addr_regs_if_needed (reg, disp1, hbb);
2065 if (TMR_INDEX2 (ref))
2067 if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
2069 hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
2070 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
2071 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
2072 hbb);
2074 else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
2075 offset += wi::to_offset (TMR_INDEX2 (ref));
2076 else
2077 gcc_unreachable ();
2079 offset += wi::to_offset (TMR_OFFSET (ref));
2080 break;
2081 case FUNCTION_DECL:
2082 HSA_SORRY_AT (EXPR_LOCATION (origref),
2083 "support for HSA does not implement function pointers");
2084 goto out;
2085 default:
2086 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
2087 "not implement memory access to %E", origref);
2088 goto out;
2091 if (varoffset)
2093 if (TREE_CODE (varoffset) == INTEGER_CST)
2094 offset += wi::to_offset (varoffset);
2095 else
2097 hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
2098 addrtype);
2099 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
2100 hbb);
2104 gcc_checking_assert ((symbol
2105 && addrtype
2106 == hsa_get_segment_addr_type (symbol->m_segment))
2107 || (!symbol
2108 && addrtype
2109 == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
2110 out:
2111 HOST_WIDE_INT hwi_offset = offset.to_shwi ();
2113 /* Calculate remaining bitsize offset (if presented). */
2114 bitpos %= BITS_PER_UNIT;
2115 /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
2116 is not a reason to think this is a bit-field access. */
2117 if (bitpos == 0
2118 && (bitsize >= BITS_PER_UNIT)
2119 && !(bitsize & (bitsize - 1)))
2120 bitsize = 0;
2122 if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
2123 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
2124 "implement unhandled bit field reference such as %E", ref);
2126 if (output_bitsize != NULL && output_bitpos != NULL)
2128 *output_bitsize = bitsize;
2129 *output_bitpos = bitpos;
2132 return new hsa_op_address (symbol, reg, hwi_offset);
2135 /* Generate HSA address operand for a given tree memory reference REF. If
2136 instructions need to be created to calculate the address, they will be added
2137 to the end of HBB. OUTPUT_ALIGN is alignment of the created address. */
2139 static hsa_op_address *
2140 gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
2142 hsa_op_address *addr = gen_hsa_addr (ref, hbb);
2143 if (addr->m_reg || !addr->m_symbol)
2144 *output_align = hsa_object_alignment (ref);
2145 else
2147 /* If the address consists only of a symbol and an offset, we
2148 compute the alignment ourselves to take into account any alignment
2149 promotions we might have done for the HSA symbol representation. */
2150 unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
2151 unsigned misalign = addr->m_imm_offset & (align - 1);
2152 if (misalign)
2153 align = least_bit_hwi (misalign);
2154 *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
2156 return addr;
2159 /* Generate HSA address for a function call argument of given TYPE.
2160 INDEX is used to generate corresponding name of the arguments.
2161 Special value -1 represents fact that result value is created. */
2163 static hsa_op_address *
2164 gen_hsa_addr_for_arg (tree tree_type, int index)
2166 hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
2167 BRIG_LINKAGE_ARG);
2168 sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
2170 if (index == -1) /* Function result. */
2171 sym->m_name = "res";
2172 else /* Function call arguments. */
2174 sym->m_name = NULL;
2175 sym->m_name_number = index;
2178 return new hsa_op_address (sym);
2181 /* Generate HSA instructions that process all necessary conversions
2182 of an ADDR to flat addressing and place the result into DEST.
2183 Instructions are appended to HBB. */
2185 static void
2186 convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
2187 hsa_bb *hbb)
2189 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
2190 insn->set_op (1, addr);
2191 if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
2193 /* LDA produces segment-relative address, we need to convert
2194 it to the flat one. */
2195 hsa_op_reg *tmp;
2196 tmp = new hsa_op_reg (hsa_get_segment_addr_type
2197 (addr->m_symbol->m_segment));
2198 hsa_insn_seg *seg;
2199 seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
2200 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
2201 tmp->m_type, addr->m_symbol->m_segment, dest,
2202 tmp);
2204 insn->set_op (0, tmp);
2205 insn->m_type = tmp->m_type;
2206 hbb->append_insn (insn);
2207 hbb->append_insn (seg);
2209 else
2211 insn->set_op (0, dest);
2212 insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2213 hbb->append_insn (insn);
2217 /* Generate HSA instructions that calculate address of VAL including all
2218 necessary conversions to flat addressing and place the result into DEST.
2219 Instructions are appended to HBB. */
2221 static void
2222 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
2224 /* Handle cases like tmp = NULL, where we just emit a move instruction
2225 to a register. */
2226 if (TREE_CODE (val) == INTEGER_CST)
2228 hsa_op_immed *c = new hsa_op_immed (val);
2229 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2230 dest->m_type, dest, c);
2231 hbb->append_insn (insn);
2232 return;
2235 hsa_op_address *addr;
2237 gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2238 if (TREE_CODE (val) == ADDR_EXPR)
2239 val = TREE_OPERAND (val, 0);
2240 addr = gen_hsa_addr (val, hbb);
2242 if (TREE_CODE (val) == CONST_DECL
2243 && is_gimple_reg_type (TREE_TYPE (val)))
2245 gcc_assert (addr->m_symbol
2246 && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY);
2247 /* CONST_DECLs are in readonly segment which however does not have
2248 addresses convertible to flat segments. So copy it to a private one
2249 and take address of that. */
2250 BrigType16_t csttype
2251 = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (val),
2252 false));
2253 hsa_op_reg *r = new hsa_op_reg (csttype);
2254 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, csttype, r,
2255 new hsa_op_address (addr->m_symbol)));
2256 hsa_symbol *copysym = hsa_cfun->create_hsa_temporary (csttype);
2257 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, csttype, r,
2258 new hsa_op_address (copysym)));
2259 addr->m_symbol = copysym;
2261 else if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY)
2263 HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
2264 "not implement taking addresses of complex "
2265 "CONST_DECLs such as %E", val);
2266 return;
2270 convert_addr_to_flat_segment (addr, dest, hbb);
2273 /* Return an HSA register or HSA immediate value operand corresponding to
2274 gimple operand OP. */
2276 static hsa_op_with_type *
2277 hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
2279 hsa_op_reg *tmp;
2281 if (TREE_CODE (op) == SSA_NAME)
2282 tmp = hsa_cfun->reg_for_gimple_ssa (op);
2283 else if (!POINTER_TYPE_P (TREE_TYPE (op)))
2284 return new hsa_op_immed (op);
2285 else
2287 tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2288 gen_hsa_addr_insns (op, tmp, hbb);
2290 return tmp;
2293 /* Create a simple movement instruction with register destination DEST and
2294 register or immediate source SRC and append it to the end of HBB. */
2296 void
2297 hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
2299 /* Moves of packed data between registers need to adhere to the same type
2300 rules like when dealing with memory. */
2301 BrigType16_t tp = mem_type_for_type (dest->m_type);
2302 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, tp, dest, src);
2303 hsa_fixup_mov_insn_type (insn);
2304 unsigned dest_size = hsa_type_bit_size (dest->m_type);
2305 if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
2306 gcc_assert (dest_size == hsa_type_bit_size (sreg->m_type));
2307 else
2309 unsigned imm_size
2310 = hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type);
2311 gcc_assert ((dest_size == imm_size)
2312 /* Eventually < 32bit registers will be promoted to 32bit. */
2313 || (dest_size < 32 && imm_size == 32));
2315 hbb->append_insn (insn);
2318 /* Generate HSAIL instructions loading a bit field into register DEST.
2319 VALUE_REG is a register of a SSA name that is used in the bit field
2320 reference. To identify a bit field BITPOS is offset to the loaded memory
2321 and BITSIZE is number of bits of the bit field.
2322 Add instructions to HBB. */
2324 static void
2325 gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
2326 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2327 hsa_bb *hbb)
2329 unsigned type_bitsize
2330 = hsa_type_bit_size (hsa_extend_inttype_to_32bit (dest->m_type));
2331 unsigned left_shift = type_bitsize - (bitsize + bitpos);
2332 unsigned right_shift = left_shift + bitpos;
2334 if (left_shift)
2336 hsa_op_reg *value_reg_2
2337 = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
2338 hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
2340 hsa_insn_basic *lshift
2341 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
2342 value_reg_2, value_reg, c);
2344 hbb->append_insn (lshift);
2346 value_reg = value_reg_2;
2349 if (right_shift)
2351 hsa_op_reg *value_reg_2
2352 = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
2353 hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
2355 hsa_insn_basic *rshift
2356 = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
2357 value_reg_2, value_reg, c);
2359 hbb->append_insn (rshift);
2361 value_reg = value_reg_2;
2364 hsa_insn_basic *assignment
2365 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, NULL, value_reg);
2366 hsa_fixup_mov_insn_type (assignment);
2367 hbb->append_insn (assignment);
2368 assignment->set_output_in_type (dest, 0, hbb);
2372 /* Generate HSAIL instructions loading a bit field into register DEST. ADDR is
2373 prepared memory address which is used to load the bit field. To identify a
2374 bit field BITPOS is offset to the loaded memory and BITSIZE is number of
2375 bits of the bit field. Add instructions to HBB. Load must be performed in
2376 alignment ALIGN. */
2378 static void
2379 gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
2380 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2381 hsa_bb *hbb, BrigAlignment8_t align)
2383 hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
2384 hsa_insn_mem *mem
2385 = new hsa_insn_mem (BRIG_OPCODE_LD,
2386 hsa_extend_inttype_to_32bit (dest->m_type),
2387 value_reg, addr);
2388 mem->set_align (align);
2389 hbb->append_insn (mem);
2390 gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
2393 /* Return the alignment of base memory accesses we issue to perform bit-field
2394 memory access REF. */
2396 static BrigAlignment8_t
2397 hsa_bitmemref_alignment (tree ref)
2399 unsigned HOST_WIDE_INT bit_offset = 0;
2401 while (true)
2403 if (TREE_CODE (ref) == BIT_FIELD_REF)
2405 if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
2406 return BRIG_ALIGNMENT_1;
2407 bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
2409 else if (TREE_CODE (ref) == COMPONENT_REF
2410 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
2411 bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
2412 else
2413 break;
2414 ref = TREE_OPERAND (ref, 0);
2417 unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
2418 unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
2419 BrigAlignment8_t base = hsa_object_alignment (ref);
2420 if (byte_bits == 0)
2421 return base;
2422 return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
2425 /* Generate HSAIL instructions loading something into register DEST. RHS is
2426 tree representation of the loaded data, which are loaded as type TYPE. Add
2427 instructions to HBB. */
2429 static void
2430 gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
2432 /* The destination SSA name will give us the type. */
2433 if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
2434 rhs = TREE_OPERAND (rhs, 0);
2436 if (TREE_CODE (rhs) == SSA_NAME)
2438 hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
2439 hsa_build_append_simple_mov (dest, src, hbb);
2441 else if (is_gimple_min_invariant (rhs)
2442 || TREE_CODE (rhs) == ADDR_EXPR)
2444 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
2446 if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
2448 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2449 "support for HSA does not implement conversion "
2450 "of %E to the requested non-pointer type.", rhs);
2451 return;
2454 gen_hsa_addr_insns (rhs, dest, hbb);
2456 else if (TREE_CODE (rhs) == COMPLEX_CST)
2458 hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
2459 hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
2461 hsa_op_reg *real_part_reg
2462 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2463 true));
2464 hsa_op_reg *imag_part_reg
2465 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2466 true));
2468 hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
2469 hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
2471 BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
2473 hsa_insn_packed *insn
2474 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
2475 src_type, dest, real_part_reg,
2476 imag_part_reg);
2477 hbb->append_insn (insn);
2479 else
2481 hsa_op_immed *imm = new hsa_op_immed (rhs);
2482 hsa_build_append_simple_mov (dest, imm, hbb);
2485 else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
2487 tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
2489 hsa_op_reg *packed_reg
2490 = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
2492 tree complex_rhs = TREE_OPERAND (rhs, 0);
2493 gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
2494 hbb);
2496 hsa_op_reg *real_reg
2497 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2499 hsa_op_reg *imag_reg
2500 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2502 BrigKind16_t brig_type = packed_reg->m_type;
2503 hsa_insn_packed *packed
2504 = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
2505 hsa_bittype_for_type (real_reg->m_type),
2506 brig_type, real_reg, imag_reg, packed_reg);
2508 hbb->append_insn (packed);
2510 hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
2511 real_reg : imag_reg;
2513 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2514 dest->m_type, NULL, source);
2515 hsa_fixup_mov_insn_type (insn);
2516 hbb->append_insn (insn);
2517 insn->set_output_in_type (dest, 0, hbb);
2519 else if (TREE_CODE (rhs) == BIT_FIELD_REF
2520 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
2522 tree ssa_name = TREE_OPERAND (rhs, 0);
2523 HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
2524 HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
2526 hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
2527 gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
2529 else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
2530 || TREE_CODE (rhs) == TARGET_MEM_REF
2531 || handled_component_p (rhs))
2533 HOST_WIDE_INT bitsize, bitpos;
2535 /* Load from memory. */
2536 hsa_op_address *addr;
2537 addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
2539 /* Handle load of a bit field. */
2540 if (bitsize > 64)
2542 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2543 "support for HSA does not implement load from a bit "
2544 "field bigger than 64 bits");
2545 return;
2548 if (bitsize || bitpos)
2549 gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
2550 hsa_bitmemref_alignment (rhs));
2551 else
2553 BrigType16_t mtype;
2554 /* Not dest->m_type, that's possibly extended. */
2555 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
2556 false));
2557 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
2558 addr);
2559 mem->set_align (hsa_object_alignment (rhs));
2560 hbb->append_insn (mem);
2563 else
2564 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2565 "support for HSA does not implement loading "
2566 "of expression %E",
2567 rhs);
2570 /* Return number of bits necessary for representation of a bit field,
2571 starting at BITPOS with size of BITSIZE. */
2573 static unsigned
2574 get_bitfield_size (unsigned bitpos, unsigned bitsize)
2576 unsigned s = bitpos + bitsize;
2577 unsigned sizes[] = {8, 16, 32, 64};
2579 for (unsigned i = 0; i < 4; i++)
2580 if (s <= sizes[i])
2581 return sizes[i];
2583 gcc_unreachable ();
2584 return 0;
2587 /* Generate HSAIL instructions storing into memory. LHS is the destination of
2588 the store, SRC is the source operand. Add instructions to HBB. */
2590 static void
2591 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
2593 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2594 BrigAlignment8_t req_align;
2595 BrigType16_t mtype;
2596 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
2597 false));
2598 hsa_op_address *addr;
2599 addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
2601 /* Handle store to a bit field. */
2602 if (bitsize > 64)
2604 HSA_SORRY_AT (EXPR_LOCATION (lhs),
2605 "support for HSA does not implement store to a bit field "
2606 "bigger than 64 bits");
2607 return;
2610 unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
2612 /* HSAIL does not support MOV insn with 16-bits integers. */
2613 if (type_bitsize < 32)
2614 type_bitsize = 32;
2616 if (bitpos || (bitsize && type_bitsize != bitsize))
2618 unsigned HOST_WIDE_INT mask = 0;
2619 BrigType16_t mem_type
2620 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
2621 !TYPE_UNSIGNED (TREE_TYPE (lhs)));
2623 for (unsigned i = 0; i < type_bitsize; i++)
2624 if (i < bitpos || i >= bitpos + bitsize)
2625 mask |= ((unsigned HOST_WIDE_INT)1 << i);
2627 hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
2629 req_align = hsa_bitmemref_alignment (lhs);
2630 /* Load value from memory. */
2631 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
2632 value_reg, addr);
2633 mem->set_align (req_align);
2634 hbb->append_insn (mem);
2636 /* AND the loaded value with prepared mask. */
2637 hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
2639 BrigType16_t t
2640 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
2641 hsa_op_immed *c = new hsa_op_immed (mask, t);
2643 hsa_insn_basic *clearing
2644 = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
2645 value_reg, c);
2646 hbb->append_insn (clearing);
2648 /* Shift to left a value that is going to be stored. */
2649 hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
2651 hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
2652 new_value_reg, src);
2653 hsa_fixup_mov_insn_type (basic);
2654 hbb->append_insn (basic);
2656 if (bitpos)
2658 hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
2659 c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
2661 hsa_insn_basic *basic
2662 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
2663 shifted_value_reg, new_value_reg, c);
2664 hbb->append_insn (basic);
2666 new_value_reg = shifted_value_reg;
2669 /* OR the prepared value with prepared chunk loaded from memory. */
2670 hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
2671 basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
2672 new_value_reg, cleared_reg);
2673 hbb->append_insn (basic);
2675 src = prepared_reg;
2676 mtype = mem_type;
2678 else
2679 req_align = hsa_object_alignment (lhs);
2681 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
2682 mem->set_align (req_align);
2684 /* The HSAIL verifier has another constraint: if the source is an immediate
2685 then it must match the destination type. If it's a register the low bits
2686 will be used for sub-word stores. We're always allocating new operands so
2687 we can modify the above in place. */
2688 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
2690 if (!hsa_type_packed_p (imm->m_type))
2691 imm->m_type = mem->m_type;
2692 else
2694 /* ...and all vector immediates apparently need to be vectors of
2695 unsigned bytes. */
2696 unsigned bs = hsa_type_bit_size (imm->m_type);
2697 gcc_assert (bs == hsa_type_bit_size (mem->m_type));
2698 switch (bs)
2700 case 32:
2701 imm->m_type = BRIG_TYPE_U8X4;
2702 break;
2703 case 64:
2704 imm->m_type = BRIG_TYPE_U8X8;
2705 break;
2706 case 128:
2707 imm->m_type = BRIG_TYPE_U8X16;
2708 break;
2709 default:
2710 gcc_unreachable ();
2715 hbb->append_insn (mem);
2718 /* Generate memory copy instructions that are going to be used
2719 for copying a SRC memory to TARGET memory,
2720 represented by pointer in a register. MIN_ALIGN is minimal alignment
2721 of provided HSA addresses. */
2723 static void
2724 gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
2725 unsigned size, BrigAlignment8_t min_align)
2727 hsa_op_address *addr;
2728 hsa_insn_mem *mem;
2730 unsigned offset = 0;
2731 unsigned min_byte_align = hsa_byte_alignment (min_align);
2733 while (size)
2735 unsigned s;
2736 if (size >= 8)
2737 s = 8;
2738 else if (size >= 4)
2739 s = 4;
2740 else if (size >= 2)
2741 s = 2;
2742 else
2743 s = 1;
2745 if (s > min_byte_align)
2746 s = min_byte_align;
2748 BrigType16_t t = get_integer_type_by_bytes (s, false);
2750 hsa_op_reg *tmp = new hsa_op_reg (t);
2751 addr = new hsa_op_address (src->m_symbol, src->m_reg,
2752 src->m_imm_offset + offset);
2753 mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
2754 hbb->append_insn (mem);
2756 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2757 target->m_imm_offset + offset);
2758 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
2759 hbb->append_insn (mem);
2760 offset += s;
2761 size -= s;
2765 /* Create a memset mask that is created by copying a CONSTANT byte value
2766 to an integer of BYTE_SIZE bytes. */
2768 static unsigned HOST_WIDE_INT
2769 build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
2771 if (constant == 0)
2772 return 0;
2774 HOST_WIDE_INT v = constant;
2776 for (unsigned i = 1; i < byte_size; i++)
2777 v |= constant << (8 * i);
2779 return v;
2782 /* Generate memory set instructions that are going to be used
2783 for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
2784 MIN_ALIGN is minimal alignment of provided HSA addresses. */
2786 static void
2787 gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
2788 unsigned HOST_WIDE_INT constant,
2789 unsigned size, BrigAlignment8_t min_align)
2791 hsa_op_address *addr;
2792 hsa_insn_mem *mem;
2794 unsigned offset = 0;
2795 unsigned min_byte_align = hsa_byte_alignment (min_align);
2797 while (size)
2799 unsigned s;
2800 if (size >= 8)
2801 s = 8;
2802 else if (size >= 4)
2803 s = 4;
2804 else if (size >= 2)
2805 s = 2;
2806 else
2807 s = 1;
2809 if (s > min_byte_align)
2810 s = min_byte_align;
2812 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2813 target->m_imm_offset + offset);
2815 BrigType16_t t = get_integer_type_by_bytes (s, false);
2816 HOST_WIDE_INT c = build_memset_value (constant, s);
2818 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
2819 addr);
2820 hbb->append_insn (mem);
2821 offset += s;
2822 size -= s;
2826 /* Generate HSAIL instructions for a single assignment
2827 of an empty constructor to an ADDR_LHS. Constructor is passed as a
2828 tree RHS and all instructions are appended to HBB. ALIGN is
2829 alignment of the address. */
2831 void
2832 gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
2833 BrigAlignment8_t align)
2835 if (CONSTRUCTOR_NELTS (rhs))
2837 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2838 "support for HSA does not implement load from constructor");
2839 return;
2842 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2843 gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
2846 /* Generate HSA instructions for a single assignment of RHS to LHS.
2847 HBB is the basic block they will be appended to. */
2849 static void
2850 gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
2852 if (TREE_CODE (lhs) == SSA_NAME)
2854 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
2855 if (hsa_seen_error ())
2856 return;
2858 gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
2860 else if (TREE_CODE (rhs) == SSA_NAME
2861 || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
2863 /* Store to memory. */
2864 hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
2865 if (hsa_seen_error ())
2866 return;
2868 gen_hsa_insns_for_store (lhs, src, hbb);
2870 else
2872 BrigAlignment8_t lhs_align;
2873 hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
2874 &lhs_align);
2876 if (TREE_CODE (rhs) == CONSTRUCTOR)
2877 gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
2878 else
2880 BrigAlignment8_t rhs_align;
2881 hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
2882 &rhs_align);
2884 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2885 gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
2886 MIN (lhs_align, rhs_align));
2891 /* Prepend before INSN a load from spill symbol of SPILL_REG. Return the
2892 register into which we loaded. If this required another register to convert
2893 from a B1 type, return it in *PTMP2, otherwise store NULL into it. We
2894 assume we are out of SSA so the returned register does not have its
2895 definition set. */
2897 hsa_op_reg *
2898 hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2900 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2901 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2902 hsa_op_address *addr = new hsa_op_address (spill_sym);
2904 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
2905 reg, addr);
2906 hsa_insert_insn_before (mem, insn);
2908 *ptmp2 = NULL;
2909 if (spill_reg->m_type == BRIG_TYPE_B1)
2911 hsa_insn_basic *cvtinsn;
2912 *ptmp2 = reg;
2913 reg = new hsa_op_reg (spill_reg->m_type);
2915 cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
2916 hsa_insert_insn_before (cvtinsn, insn);
2918 return reg;
2921 /* Append after INSN a store to spill symbol of SPILL_REG. Return the register
2922 from which we stored. If this required another register to convert to a B1
2923 type, return it in *PTMP2, otherwise store NULL into it. We assume we are
2924 out of SSA so the returned register does not have its use updated. */
2926 hsa_op_reg *
2927 hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2929 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2930 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2931 hsa_op_address *addr = new hsa_op_address (spill_sym);
2932 hsa_op_reg *returnreg;
2934 *ptmp2 = NULL;
2935 returnreg = reg;
2936 if (spill_reg->m_type == BRIG_TYPE_B1)
2938 hsa_insn_basic *cvtinsn;
2939 *ptmp2 = new hsa_op_reg (spill_sym->m_type);
2940 reg->m_type = spill_reg->m_type;
2942 cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
2943 hsa_append_insn_after (cvtinsn, insn);
2944 insn = cvtinsn;
2945 reg = *ptmp2;
2948 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
2949 addr);
2950 hsa_append_insn_after (mem, insn);
2951 return returnreg;
2954 /* Generate a comparison instruction that will compare LHS and RHS with
2955 comparison specified by CODE and put result into register DEST. DEST has to
2956 have its type set already but must not have its definition set yet.
2957 Generated instructions will be added to HBB. */
2959 static void
2960 gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
2961 hsa_op_reg *dest, hsa_bb *hbb)
2963 BrigCompareOperation8_t compare;
2965 switch (code)
2967 case LT_EXPR:
2968 compare = BRIG_COMPARE_LT;
2969 break;
2970 case LE_EXPR:
2971 compare = BRIG_COMPARE_LE;
2972 break;
2973 case GT_EXPR:
2974 compare = BRIG_COMPARE_GT;
2975 break;
2976 case GE_EXPR:
2977 compare = BRIG_COMPARE_GE;
2978 break;
2979 case EQ_EXPR:
2980 compare = BRIG_COMPARE_EQ;
2981 break;
2982 case NE_EXPR:
2983 compare = BRIG_COMPARE_NE;
2984 break;
2985 case UNORDERED_EXPR:
2986 compare = BRIG_COMPARE_NAN;
2987 break;
2988 case ORDERED_EXPR:
2989 compare = BRIG_COMPARE_NUM;
2990 break;
2991 case UNLT_EXPR:
2992 compare = BRIG_COMPARE_LTU;
2993 break;
2994 case UNLE_EXPR:
2995 compare = BRIG_COMPARE_LEU;
2996 break;
2997 case UNGT_EXPR:
2998 compare = BRIG_COMPARE_GTU;
2999 break;
3000 case UNGE_EXPR:
3001 compare = BRIG_COMPARE_GEU;
3002 break;
3003 case UNEQ_EXPR:
3004 compare = BRIG_COMPARE_EQU;
3005 break;
3006 case LTGT_EXPR:
3007 compare = BRIG_COMPARE_NEU;
3008 break;
3010 default:
3011 HSA_SORRY_ATV (EXPR_LOCATION (lhs),
3012 "support for HSA does not implement comparison tree "
3013 "code %s\n", get_tree_code_name (code));
3014 return;
3017 /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
3018 as a result of comparison. */
3020 BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
3021 ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
3023 hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
3024 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (lhs, hbb);
3025 cmp->set_op (1, op1->extend_int_to_32bit (hbb));
3026 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
3027 cmp->set_op (2, op2->extend_int_to_32bit (hbb));
3029 hbb->append_insn (cmp);
3030 cmp->set_output_in_type (dest, 0, hbb);
3033 /* Generate an unary instruction with OPCODE and append it to a basic block
3034 HBB. The instruction uses DEST as a destination and OP1
3035 as a single operand. */
3037 static void
3038 gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
3039 hsa_op_with_type *op1, hsa_bb *hbb)
3041 gcc_checking_assert (dest);
3042 hsa_insn_basic *insn;
3044 if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
3046 insn = new hsa_insn_cvt (dest, op1);
3047 hbb->append_insn (insn);
3048 return;
3051 op1 = op1->extend_int_to_32bit (hbb);
3052 if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3054 BrigType16_t srctype = hsa_type_integer_p (op1->m_type) ? op1->m_type
3055 : hsa_unsigned_type_for_type (op1->m_type);
3056 insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, srctype, NULL,
3057 op1);
3059 else
3061 BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
3062 insn = new hsa_insn_basic (2, opcode, optype, NULL, op1);
3064 if (opcode == BRIG_OPCODE_MOV)
3065 hsa_fixup_mov_insn_type (insn);
3066 else if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
3068 /* ABS and NEG only exist in _s form :-/ */
3069 if (insn->m_type == BRIG_TYPE_U32)
3070 insn->m_type = BRIG_TYPE_S32;
3071 else if (insn->m_type == BRIG_TYPE_U64)
3072 insn->m_type = BRIG_TYPE_S64;
3076 hbb->append_insn (insn);
3077 insn->set_output_in_type (dest, 0, hbb);
3080 /* Generate a binary instruction with OPCODE and append it to a basic block
3081 HBB. The instruction uses DEST as a destination and operands OP1
3082 and OP2. */
3084 static void
3085 gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
3086 hsa_op_with_type *op1, hsa_op_with_type *op2,
3087 hsa_bb *hbb)
3089 gcc_checking_assert (dest);
3091 BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
3092 op1 = op1->extend_int_to_32bit (hbb);
3093 op2 = op2->extend_int_to_32bit (hbb);
3095 if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
3096 && is_a <hsa_op_immed *> (op2))
3098 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3099 i->set_type (BRIG_TYPE_U32);
3101 if ((opcode == BRIG_OPCODE_OR
3102 || opcode == BRIG_OPCODE_XOR
3103 || opcode == BRIG_OPCODE_AND)
3104 && is_a <hsa_op_immed *> (op2))
3106 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3107 i->set_type (hsa_unsigned_type_for_type (i->m_type));
3110 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, optype, NULL,
3111 op1, op2);
3112 hbb->append_insn (insn);
3113 insn->set_output_in_type (dest, 0, hbb);
3116 /* Generate HSA instructions for a single assignment. HBB is the basic block
3117 they will be appended to. */
3119 static void
3120 gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
3122 tree_code code = gimple_assign_rhs_code (assign);
3123 gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
3125 tree lhs = gimple_assign_lhs (assign);
3126 tree rhs1 = gimple_assign_rhs1 (assign);
3127 tree rhs2 = gimple_assign_rhs2 (assign);
3128 tree rhs3 = gimple_assign_rhs3 (assign);
3130 BrigOpcode opcode;
3132 switch (code)
3134 CASE_CONVERT:
3135 case FLOAT_EXPR:
3136 /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
3137 needs a conversion. */
3138 opcode = BRIG_OPCODE_MOV;
3139 break;
3141 case PLUS_EXPR:
3142 case POINTER_PLUS_EXPR:
3143 opcode = BRIG_OPCODE_ADD;
3144 break;
3145 case MINUS_EXPR:
3146 opcode = BRIG_OPCODE_SUB;
3147 break;
3148 case MULT_EXPR:
3149 opcode = BRIG_OPCODE_MUL;
3150 break;
3151 case MULT_HIGHPART_EXPR:
3152 opcode = BRIG_OPCODE_MULHI;
3153 break;
3154 case RDIV_EXPR:
3155 case TRUNC_DIV_EXPR:
3156 case EXACT_DIV_EXPR:
3157 opcode = BRIG_OPCODE_DIV;
3158 break;
3159 case CEIL_DIV_EXPR:
3160 case FLOOR_DIV_EXPR:
3161 case ROUND_DIV_EXPR:
3162 HSA_SORRY_AT (gimple_location (assign),
3163 "support for HSA does not implement CEIL_DIV_EXPR, "
3164 "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
3165 return;
3166 case TRUNC_MOD_EXPR:
3167 opcode = BRIG_OPCODE_REM;
3168 break;
3169 case CEIL_MOD_EXPR:
3170 case FLOOR_MOD_EXPR:
3171 case ROUND_MOD_EXPR:
3172 HSA_SORRY_AT (gimple_location (assign),
3173 "support for HSA does not implement CEIL_MOD_EXPR, "
3174 "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
3175 return;
3176 case NEGATE_EXPR:
3177 opcode = BRIG_OPCODE_NEG;
3178 break;
3179 case MIN_EXPR:
3180 opcode = BRIG_OPCODE_MIN;
3181 break;
3182 case MAX_EXPR:
3183 opcode = BRIG_OPCODE_MAX;
3184 break;
3185 case ABS_EXPR:
3186 opcode = BRIG_OPCODE_ABS;
3187 break;
3188 case LSHIFT_EXPR:
3189 opcode = BRIG_OPCODE_SHL;
3190 break;
3191 case RSHIFT_EXPR:
3192 opcode = BRIG_OPCODE_SHR;
3193 break;
3194 case LROTATE_EXPR:
3195 case RROTATE_EXPR:
3197 hsa_insn_basic *insn = NULL;
3198 int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3199 int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3200 BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3201 true);
3203 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3204 hsa_op_reg *op1 = new hsa_op_reg (btype);
3205 hsa_op_reg *op2 = new hsa_op_reg (btype);
3206 hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3208 tree type = TREE_TYPE (rhs2);
3209 unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3211 hsa_op_with_type *shift2 = NULL;
3212 if (TREE_CODE (rhs2) == INTEGER_CST)
3213 shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3214 BRIG_TYPE_U32);
3215 else if (TREE_CODE (rhs2) == SSA_NAME)
3217 hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3218 s = as_a <hsa_op_reg *> (s->extend_int_to_32bit (hbb));
3219 hsa_op_reg *d = new hsa_op_reg (s->m_type);
3220 hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3222 insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3223 d, s, size_imm);
3224 hbb->append_insn (insn);
3226 shift2 = d;
3228 else
3229 gcc_unreachable ();
3231 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3232 gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3233 gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3234 gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3236 return;
3238 case BIT_IOR_EXPR:
3239 opcode = BRIG_OPCODE_OR;
3240 break;
3241 case BIT_XOR_EXPR:
3242 opcode = BRIG_OPCODE_XOR;
3243 break;
3244 case BIT_AND_EXPR:
3245 opcode = BRIG_OPCODE_AND;
3246 break;
3247 case BIT_NOT_EXPR:
3248 opcode = BRIG_OPCODE_NOT;
3249 break;
3250 case FIX_TRUNC_EXPR:
3252 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3253 hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3255 if (hsa_needs_cvt (dest->m_type, v->m_type))
3257 hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3259 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3260 tmp->m_type, tmp, v);
3261 hbb->append_insn (insn);
3263 hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3264 hbb->append_insn (cvtinsn);
3266 else
3268 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3269 dest->m_type, dest, v);
3270 hbb->append_insn (insn);
3273 return;
3275 opcode = BRIG_OPCODE_TRUNC;
3276 break;
3278 case LT_EXPR:
3279 case LE_EXPR:
3280 case GT_EXPR:
3281 case GE_EXPR:
3282 case EQ_EXPR:
3283 case NE_EXPR:
3284 case UNORDERED_EXPR:
3285 case ORDERED_EXPR:
3286 case UNLT_EXPR:
3287 case UNLE_EXPR:
3288 case UNGT_EXPR:
3289 case UNGE_EXPR:
3290 case UNEQ_EXPR:
3291 case LTGT_EXPR:
3293 hsa_op_reg *dest
3294 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3296 gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3297 return;
3299 case COND_EXPR:
3301 hsa_op_reg *dest
3302 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3303 hsa_op_with_type *ctrl = NULL;
3304 tree cond = rhs1;
3306 if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3307 ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3308 else
3310 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3312 gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3313 TREE_OPERAND (cond, 0),
3314 TREE_OPERAND (cond, 1),
3315 r, hbb);
3317 ctrl = r;
3320 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3321 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3322 op2 = op2->extend_int_to_32bit (hbb);
3323 op3 = op3->extend_int_to_32bit (hbb);
3325 BrigType16_t type = hsa_extend_inttype_to_32bit (dest->m_type);
3326 BrigType16_t utype = hsa_unsigned_type_for_type (type);
3327 if (is_a <hsa_op_immed *> (op2))
3328 op2->m_type = utype;
3329 if (is_a <hsa_op_immed *> (op3))
3330 op3->m_type = utype;
3332 hsa_insn_basic *insn
3333 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3334 hsa_bittype_for_type (type),
3335 NULL, ctrl, op2, op3);
3337 hbb->append_insn (insn);
3338 insn->set_output_in_type (dest, 0, hbb);
3339 return;
3341 case COMPLEX_EXPR:
3343 hsa_op_reg *dest
3344 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3345 hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3346 rhs1_reg = rhs1_reg->extend_int_to_32bit (hbb);
3347 hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3348 rhs2_reg = rhs2_reg->extend_int_to_32bit (hbb);
3350 if (hsa_seen_error ())
3351 return;
3353 BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3354 rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3355 rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3357 hsa_insn_packed *insn
3358 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3359 dest, rhs1_reg, rhs2_reg);
3360 hbb->append_insn (insn);
3362 return;
3364 default:
3365 /* Implement others as we come across them. */
3366 HSA_SORRY_ATV (gimple_location (assign),
3367 "support for HSA does not implement operation %s",
3368 get_tree_code_name (code));
3369 return;
3373 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3374 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3375 hsa_op_with_type *op2
3376 = rhs2 ? hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3378 if (hsa_seen_error ())
3379 return;
3381 switch (rhs_class)
3383 case GIMPLE_TERNARY_RHS:
3385 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3386 op3 = op3->extend_int_to_32bit (hbb);
3387 hsa_insn_basic *insn = new hsa_insn_basic (4, opcode, dest->m_type, dest,
3388 op1, op2, op3);
3389 hbb->append_insn (insn);
3391 return;
3393 case GIMPLE_BINARY_RHS:
3394 gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3395 break;
3397 case GIMPLE_UNARY_RHS:
3398 gen_hsa_unary_operation (opcode, dest, op1, hbb);
3399 break;
3400 default:
3401 gcc_unreachable ();
3405 /* Generate HSA instructions for a given gimple condition statement COND.
3406 Instructions will be appended to HBB, which also needs to be the
3407 corresponding structure to the basic_block of COND. */
3409 static void
3410 gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3412 hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3413 hsa_insn_cbr *cbr;
3415 gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3416 gimple_cond_lhs (cond),
3417 gimple_cond_rhs (cond),
3418 ctrl, hbb);
3420 cbr = new hsa_insn_cbr (ctrl);
3421 hbb->append_insn (cbr);
3424 /* Maximum number of elements in a jump table for an HSA SBR instruction. */
3426 #define HSA_MAXIMUM_SBR_LABELS 16
3428 /* Return lowest value of a switch S that is handled in a non-default
3429 label. */
3431 static tree
3432 get_switch_low (gswitch *s)
3434 unsigned labels = gimple_switch_num_labels (s);
3435 gcc_checking_assert (labels >= 1);
3437 return CASE_LOW (gimple_switch_label (s, 1));
3440 /* Return highest value of a switch S that is handled in a non-default
3441 label. */
3443 static tree
3444 get_switch_high (gswitch *s)
3446 unsigned labels = gimple_switch_num_labels (s);
3448 /* Compare last label to maximum number of labels. */
3449 tree label = gimple_switch_label (s, labels - 1);
3450 tree low = CASE_LOW (label);
3451 tree high = CASE_HIGH (label);
3453 return high != NULL_TREE ? high : low;
3456 static tree
3457 get_switch_size (gswitch *s)
3459 return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3462 /* Generate HSA instructions for a given gimple switch.
3463 Instructions will be appended to HBB. */
3465 static void
3466 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3468 gimple_stmt_iterator it = gsi_for_stmt (s);
3469 gsi_prev (&it);
3471 /* Create preambule that verifies that index - lowest_label >= 0. */
3472 edge e = split_block (hbb->m_bb, gsi_stmt (it));
3473 e->flags &= ~EDGE_FALLTHRU;
3474 e->flags |= EDGE_TRUE_VALUE;
3476 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
3477 tree index_tree = gimple_switch_index (s);
3478 tree lowest = get_switch_low (s);
3479 tree highest = get_switch_high (s);
3481 hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
3482 index = as_a <hsa_op_reg *> (index->extend_int_to_32bit (hbb));
3484 hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3485 hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest, true);
3486 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3487 cmp1_reg, index, cmp1_immed));
3489 hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3490 hsa_op_immed *cmp2_immed = new hsa_op_immed (highest, true);
3491 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3492 cmp2_reg, index, cmp2_immed));
3494 hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3495 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3496 cmp_reg, cmp1_reg, cmp2_reg));
3498 hbb->append_insn (new hsa_insn_cbr (cmp_reg));
3500 tree default_label = gimple_switch_default_label (s);
3501 basic_block default_label_bb = label_to_block_fn (func,
3502 CASE_LABEL (default_label));
3504 if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3506 default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3507 hsa_init_new_bb (default_label_bb);
3510 make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3512 hsa_cfun->m_modified_cfg = true;
3514 /* Basic block with the SBR instruction. */
3515 hbb = hsa_init_new_bb (e->dest);
3517 hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3518 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3519 sub_index, index,
3520 new hsa_op_immed (lowest, true)));
3522 hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3523 sub_index = as_a <hsa_op_reg *> (tmp);
3524 unsigned labels = gimple_switch_num_labels (s);
3525 unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3527 hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
3529 /* Prepare array with default label destination. */
3530 for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3531 sbr->m_jump_table.safe_push (default_label_bb);
3533 /* Iterate all labels and fill up the jump table. */
3534 for (unsigned i = 1; i < labels; i++)
3536 tree label = gimple_switch_label (s, i);
3537 basic_block bb = label_to_block_fn (func, CASE_LABEL (label));
3539 unsigned HOST_WIDE_INT sub_low
3540 = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3542 unsigned HOST_WIDE_INT sub_high = sub_low;
3543 tree high = CASE_HIGH (label);
3544 if (high != NULL)
3545 sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3547 for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3548 sbr->m_jump_table[j] = bb;
3551 hbb->append_insn (sbr);
3554 /* Verify that the function DECL can be handled by HSA. */
3556 static void
3557 verify_function_arguments (tree decl)
3559 tree type = TREE_TYPE (decl);
3560 if (DECL_STATIC_CHAIN (decl))
3562 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3563 "HSA does not support nested functions: %qD", decl);
3564 return;
3566 else if (!TYPE_ARG_TYPES (type) || stdarg_p (type))
3568 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3569 "HSA does not support functions with variadic arguments "
3570 "(or unknown return type): %qD", decl);
3571 return;
3575 /* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL,
3576 return ACTUAL_ARG_TYPE. */
3578 static BrigType16_t
3579 get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3581 if (formal_arg_type == NULL)
3582 return actual_arg_type;
3584 BrigType16_t decl_type
3585 = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3586 return mem_type_for_type (decl_type);
3589 /* Generate HSA instructions for a direct call instruction.
3590 Instructions will be appended to HBB, which also needs to be the
3591 corresponding structure to the basic_block of STMT.
3592 If ASSIGN_LHS is false, do not copy HSA function result argument into the
3593 corresponding HSA representation of the gimple statement LHS. */
3595 static void
3596 gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3597 bool assign_lhs = true)
3599 tree decl = gimple_call_fndecl (stmt);
3600 verify_function_arguments (decl);
3601 if (hsa_seen_error ())
3602 return;
3604 hsa_insn_call *call_insn = new hsa_insn_call (decl);
3605 hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3607 /* Argument block start. */
3608 hsa_insn_arg_block *arg_start
3609 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3610 hbb->append_insn (arg_start);
3612 tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3614 /* Preparation of arguments that will be passed to function. */
3615 const unsigned args = gimple_call_num_args (stmt);
3616 for (unsigned i = 0; i < args; ++i)
3618 tree parm = gimple_call_arg (stmt, (int)i);
3619 tree parm_decl_type = parm_type_chain != NULL_TREE
3620 ? TREE_VALUE (parm_type_chain) : NULL_TREE;
3621 hsa_op_address *addr;
3623 if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3625 addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3626 BrigAlignment8_t align;
3627 hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
3628 gen_hsa_memory_copy (hbb, addr, src,
3629 addr->m_symbol->total_byte_size (), align);
3631 else
3633 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3635 if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3637 HSA_SORRY_AT (gimple_location (stmt),
3638 "support for HSA does not implement an aggregate "
3639 "formal argument in a function call, while actual "
3640 "argument is not an aggregate");
3641 return;
3644 BrigType16_t formal_arg_type
3645 = get_format_argument_type (parm_decl_type, src->m_type);
3646 if (hsa_seen_error ())
3647 return;
3649 if (src->m_type != formal_arg_type)
3650 src = src->get_in_type (formal_arg_type, hbb);
3652 addr
3653 = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3654 parm_decl_type: TREE_TYPE (parm), i);
3655 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3656 src, addr);
3658 hbb->append_insn (mem);
3661 call_insn->m_input_args.safe_push (addr->m_symbol);
3662 if (parm_type_chain)
3663 parm_type_chain = TREE_CHAIN (parm_type_chain);
3666 call_insn->m_args_code_list = new hsa_op_code_list (args);
3667 hbb->append_insn (call_insn);
3669 tree result_type = TREE_TYPE (TREE_TYPE (decl));
3671 tree result = gimple_call_lhs (stmt);
3672 hsa_insn_mem *result_insn = NULL;
3673 if (!VOID_TYPE_P (result_type))
3675 hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3677 /* Even if result of a function call is unused, we have to emit
3678 declaration for the result. */
3679 if (result && assign_lhs)
3681 tree lhs_type = TREE_TYPE (result);
3683 if (hsa_seen_error ())
3684 return;
3686 if (AGGREGATE_TYPE_P (lhs_type))
3688 BrigAlignment8_t align;
3689 hsa_op_address *result_addr
3690 = gen_hsa_addr_with_align (result, hbb, &align);
3691 gen_hsa_memory_copy (hbb, result_addr, addr,
3692 addr->m_symbol->total_byte_size (), align);
3694 else
3696 BrigType16_t mtype
3697 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3698 false));
3700 hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3701 result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3702 hbb->append_insn (result_insn);
3706 call_insn->m_output_arg = addr->m_symbol;
3707 call_insn->m_result_code_list = new hsa_op_code_list (1);
3709 else
3711 if (result)
3713 HSA_SORRY_AT (gimple_location (stmt),
3714 "support for HSA does not implement an assignment of "
3715 "return value from a void function");
3716 return;
3719 call_insn->m_result_code_list = new hsa_op_code_list (0);
3722 /* Argument block end. */
3723 hsa_insn_arg_block *arg_end
3724 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3725 hbb->append_insn (arg_end);
3728 /* Generate HSA instructions for a direct call of an internal fn.
3729 Instructions will be appended to HBB, which also needs to be the
3730 corresponding structure to the basic_block of STMT. */
3732 static void
3733 gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3735 tree lhs = gimple_call_lhs (stmt);
3736 if (!lhs)
3737 return;
3739 tree lhs_type = TREE_TYPE (lhs);
3740 tree rhs1 = gimple_call_arg (stmt, 0);
3741 tree rhs1_type = TREE_TYPE (rhs1);
3742 enum internal_fn fn = gimple_call_internal_fn (stmt);
3743 hsa_internal_fn *ifn
3744 = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3745 hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3747 gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3749 if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3750 hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3752 hsa_insn_arg_block *arg_start
3753 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3754 hbb->append_insn (arg_start);
3756 unsigned num_args = gimple_call_num_args (stmt);
3758 /* Function arguments. */
3759 for (unsigned i = 0; i < num_args; i++)
3761 tree parm = gimple_call_arg (stmt, (int)i);
3762 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3764 hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3765 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3766 src, addr);
3768 call_insn->m_input_args.safe_push (addr->m_symbol);
3769 hbb->append_insn (mem);
3772 call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3773 hbb->append_insn (call_insn);
3775 /* Assign returned value. */
3776 hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3778 call_insn->m_output_arg = addr->m_symbol;
3779 call_insn->m_result_code_list = new hsa_op_code_list (1);
3781 /* Argument block end. */
3782 hsa_insn_arg_block *arg_end
3783 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3784 hbb->append_insn (arg_end);
3787 /* Generate HSA instructions for a return value instruction.
3788 Instructions will be appended to HBB, which also needs to be the
3789 corresponding structure to the basic_block of STMT. */
3791 static void
3792 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3794 tree retval = gimple_return_retval (stmt);
3795 if (retval)
3797 hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3799 if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3801 BrigAlignment8_t align;
3802 hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3803 &align);
3804 gen_hsa_memory_copy (hbb, addr, retval_addr,
3805 hsa_cfun->m_output_arg->total_byte_size (),
3806 align);
3808 else
3810 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3811 false);
3812 BrigType16_t mtype = mem_type_for_type (t);
3814 /* Store of return value. */
3815 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3816 src = src->get_in_type (mtype, hbb);
3817 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3818 addr);
3819 hbb->append_insn (mem);
3823 /* HSAIL return instruction emission. */
3824 hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3825 hbb->append_insn (ret);
3828 /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3829 can have a different type, conversion instructions are possibly
3830 appended to HBB. */
3832 void
3833 hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3834 hsa_bb *hbb)
3836 gcc_checking_assert (op_output_p (op_index));
3838 if (dest->m_type == m_type)
3840 set_op (op_index, dest);
3841 return;
3844 hsa_insn_basic *insn;
3845 hsa_op_reg *tmp;
3846 if (hsa_needs_cvt (dest->m_type, m_type))
3848 tmp = new hsa_op_reg (m_type);
3849 insn = new hsa_insn_cvt (dest, tmp);
3851 else if (hsa_type_bit_size (dest->m_type) == hsa_type_bit_size (m_type))
3853 /* When output, HSA registers do not really have types, only sizes, so if
3854 the sizes match, we can use the register directly. */
3855 set_op (op_index, dest);
3856 return;
3858 else
3860 tmp = new hsa_op_reg (m_type);
3861 insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3862 dest, tmp->get_in_type (dest->m_type, hbb));
3863 hsa_fixup_mov_insn_type (insn);
3865 set_op (op_index, tmp);
3866 hbb->append_insn (insn);
3869 /* Generate instruction OPCODE to query a property of HSA grid along the
3870 given DIMENSION. Store result into DEST and append the instruction to
3871 HBB. */
3873 static void
3874 query_hsa_grid_dim (hsa_op_reg *dest, int opcode, hsa_op_immed *dimension,
3875 hsa_bb *hbb)
3877 hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3878 dimension);
3879 hbb->append_insn (insn);
3880 insn->set_output_in_type (dest, 0, hbb);
3883 /* Generate instruction OPCODE to query a property of HSA grid along the given
3884 dimension which is an immediate in first argument of STMT. Store result
3885 into the register corresponding to LHS of STMT and append the instruction to
3886 HBB. */
3888 static void
3889 query_hsa_grid_dim (gimple *stmt, int opcode, hsa_bb *hbb)
3891 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3892 if (lhs == NULL_TREE)
3893 return;
3895 tree arg = gimple_call_arg (stmt, 0);
3896 unsigned HOST_WIDE_INT dim = 5;
3897 if (tree_fits_uhwi_p (arg))
3898 dim = tree_to_uhwi (arg);
3899 if (dim > 2)
3901 HSA_SORRY_AT (gimple_location (stmt),
3902 "HSA grid query dimension must be immediate constant 0, 1 "
3903 "or 2");
3904 return;
3907 hsa_op_immed *hdim = new hsa_op_immed (dim, (BrigKind16_t) BRIG_TYPE_U32);
3908 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3909 query_hsa_grid_dim (dest, opcode, hdim, hbb);
3912 /* Generate instruction OPCODE to query a property of HSA grid that is
3913 independent of any dimension. Store result into the register corresponding
3914 to LHS of STMT and append the instruction to HBB. */
3916 static void
3917 query_hsa_grid_nodim (gimple *stmt, BrigOpcode16_t opcode, hsa_bb *hbb)
3919 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3920 if (lhs == NULL_TREE)
3921 return;
3922 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3923 BrigType16_t brig_type = hsa_unsigned_type_for_type (dest->m_type);
3924 hsa_insn_basic *insn = new hsa_insn_basic (1, opcode, brig_type, dest);
3925 hbb->append_insn (insn);
3928 /* Emit instructions that set hsa_num_threads according to provided VALUE.
3929 Instructions are appended to basic block HBB. */
3931 static void
3932 gen_set_num_threads (tree value, hsa_bb *hbb)
3934 hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3935 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3937 src = src->get_in_type (hsa_num_threads->m_type, hbb);
3938 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3940 hsa_insn_basic *basic
3941 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3942 hbb->append_insn (basic);
3945 /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3946 is defined in plugin-hsa.c. */
3948 static HOST_WIDE_INT
3949 get_hsa_kernel_dispatch_offset (const char *field_name)
3951 tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3952 if (*hsa_kernel_dispatch_type == NULL)
3954 /* Collection of information needed for a dispatch of a kernel from a
3955 kernel. Keep in sync with libgomp's plugin-hsa.c. */
3957 *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
3958 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3959 get_identifier ("queue"), ptr_type_node);
3960 DECL_CHAIN (id_f1) = NULL_TREE;
3961 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3962 get_identifier ("omp_data_memory"),
3963 ptr_type_node);
3964 DECL_CHAIN (id_f2) = id_f1;
3965 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3966 get_identifier ("kernarg_address"),
3967 ptr_type_node);
3968 DECL_CHAIN (id_f3) = id_f2;
3969 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3970 get_identifier ("object"),
3971 uint64_type_node);
3972 DECL_CHAIN (id_f4) = id_f3;
3973 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3974 get_identifier ("signal"),
3975 uint64_type_node);
3976 DECL_CHAIN (id_f5) = id_f4;
3977 tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3978 get_identifier ("private_segment_size"),
3979 uint32_type_node);
3980 DECL_CHAIN (id_f6) = id_f5;
3981 tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3982 get_identifier ("group_segment_size"),
3983 uint32_type_node);
3984 DECL_CHAIN (id_f7) = id_f6;
3985 tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3986 get_identifier ("kernel_dispatch_count"),
3987 uint64_type_node);
3988 DECL_CHAIN (id_f8) = id_f7;
3989 tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3990 get_identifier ("debug"),
3991 uint64_type_node);
3992 DECL_CHAIN (id_f9) = id_f8;
3993 tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3994 get_identifier ("omp_level"),
3995 uint64_type_node);
3996 DECL_CHAIN (id_f10) = id_f9;
3997 tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3998 get_identifier ("children_dispatches"),
3999 ptr_type_node);
4000 DECL_CHAIN (id_f11) = id_f10;
4001 tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
4002 get_identifier ("omp_num_threads"),
4003 uint32_type_node);
4004 DECL_CHAIN (id_f12) = id_f11;
4007 finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
4008 id_f12, NULL_TREE);
4009 TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
4012 for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
4013 chain != NULL_TREE; chain = TREE_CHAIN (chain))
4014 if (id_equal (DECL_NAME (chain), field_name))
4015 return int_byte_position (chain);
4017 gcc_unreachable ();
4020 /* Return an HSA register that will contain number of threads for
4021 a future dispatched kernel. Instructions are added to HBB. */
4023 static hsa_op_reg *
4024 gen_num_threads_for_dispatch (hsa_bb *hbb)
4026 /* Step 1) Assign to number of threads:
4027 MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads). */
4028 hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
4029 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
4031 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
4032 threads, addr));
4034 hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
4035 BRIG_TYPE_U32);
4036 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
4037 hsa_insn_cmp * cmp
4038 = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
4039 hbb->append_insn (cmp);
4041 BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
4042 hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
4044 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
4045 threads, limit));
4047 /* Step 2) If the number is equal to zero,
4048 return shadow->omp_num_threads. */
4049 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4051 hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
4052 addr
4053 = new hsa_op_address (shadow_reg_ptr,
4054 get_hsa_kernel_dispatch_offset ("omp_num_threads"));
4055 hsa_insn_basic *basic
4056 = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
4057 shadow_thread_count, addr);
4058 hbb->append_insn (basic);
4060 hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
4061 r = new hsa_op_reg (BRIG_TYPE_B1);
4062 hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
4063 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
4064 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
4065 shadow_thread_count, tmp));
4067 hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
4069 return as_a <hsa_op_reg *> (dest);
4072 /* Build OPCODE query for all three hsa dimensions, multiply them and store the
4073 result into DEST. */
4075 static void
4076 multiply_grid_dim_characteristics (hsa_op_reg *dest, int opcode, hsa_bb *hbb)
4078 hsa_op_reg *dimx = new hsa_op_reg (BRIG_TYPE_U32);
4079 query_hsa_grid_dim (dimx, opcode,
4080 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4081 hsa_op_reg *dimy = new hsa_op_reg (BRIG_TYPE_U32);
4082 query_hsa_grid_dim (dimy, opcode,
4083 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4084 hsa_op_reg *dimz = new hsa_op_reg (BRIG_TYPE_U32);
4085 query_hsa_grid_dim (dimz, opcode,
4086 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4087 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4088 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp,
4089 dimx->get_in_type (dest->m_type, hbb),
4090 dimy->get_in_type (dest->m_type, hbb), hbb);
4091 gen_hsa_binary_operation (BRIG_OPCODE_MUL, dest, tmp,
4092 dimz->get_in_type (dest->m_type, hbb), hbb);
4095 /* Emit instructions that assign number of threads to lhs of gimple STMT.
4096 Instructions are appended to basic block HBB. */
4098 static void
4099 gen_get_num_threads (gimple *stmt, hsa_bb *hbb)
4101 if (gimple_call_lhs (stmt) == NULL_TREE)
4102 return;
4104 hbb->append_insn (new hsa_insn_comment ("omp_get_num_threads"));
4105 tree lhs = gimple_call_lhs (stmt);
4106 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4107 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_CURRENTWORKGROUPSIZE,
4108 hbb);
4111 /* Emit instructions that assign number of teams to lhs of gimple STMT.
4112 Instructions are appended to basic block HBB. */
4114 static void
4115 gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4117 if (gimple_call_lhs (stmt) == NULL_TREE)
4118 return;
4120 hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4121 tree lhs = gimple_call_lhs (stmt);
4122 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4123 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_GRIDGROUPS, hbb);
4126 /* Emit instructions that assign a team number to lhs of gimple STMT.
4127 Instructions are appended to basic block HBB. */
4129 static void
4130 gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4132 if (gimple_call_lhs (stmt) == NULL_TREE)
4133 return;
4135 hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4136 tree lhs = gimple_call_lhs (stmt);
4137 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4139 hsa_op_reg *gnum_x = new hsa_op_reg (BRIG_TYPE_U32);
4140 query_hsa_grid_dim (gnum_x, BRIG_OPCODE_GRIDGROUPS,
4141 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4142 hsa_op_reg *gnum_y = new hsa_op_reg (BRIG_TYPE_U32);
4143 query_hsa_grid_dim (gnum_y, BRIG_OPCODE_GRIDGROUPS,
4144 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4146 hsa_op_reg *gno_z = new hsa_op_reg (BRIG_TYPE_U32);
4147 query_hsa_grid_dim (gno_z, BRIG_OPCODE_WORKGROUPID,
4148 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4150 hsa_op_reg *tmp1 = new hsa_op_reg (dest->m_type);
4151 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp1,
4152 gnum_x->get_in_type (dest->m_type, hbb),
4153 gnum_y->get_in_type (dest->m_type, hbb), hbb);
4154 hsa_op_reg *tmp2 = new hsa_op_reg (dest->m_type);
4155 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp2, tmp1,
4156 gno_z->get_in_type (dest->m_type, hbb), hbb);
4158 hsa_op_reg *gno_y = new hsa_op_reg (BRIG_TYPE_U32);
4159 query_hsa_grid_dim (gno_y, BRIG_OPCODE_WORKGROUPID,
4160 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4161 hsa_op_reg *tmp3 = new hsa_op_reg (dest->m_type);
4162 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp3,
4163 gnum_x->get_in_type (dest->m_type, hbb),
4164 gno_y->get_in_type (dest->m_type, hbb), hbb);
4165 hsa_op_reg *tmp4 = new hsa_op_reg (dest->m_type);
4166 gen_hsa_binary_operation (BRIG_OPCODE_ADD, tmp4, tmp3, tmp2, hbb);
4167 hsa_op_reg *gno_x = new hsa_op_reg (BRIG_TYPE_U32);
4168 query_hsa_grid_dim (gno_x, BRIG_OPCODE_WORKGROUPID,
4169 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4170 gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp4,
4171 gno_x->get_in_type (dest->m_type, hbb), hbb);
4174 /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4175 Instructions are appended to basic block HBB. */
4177 static void
4178 gen_get_level (gimple *stmt, hsa_bb *hbb)
4180 if (gimple_call_lhs (stmt) == NULL_TREE)
4181 return;
4183 hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4185 tree lhs = gimple_call_lhs (stmt);
4186 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4188 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4189 if (shadow_reg_ptr == NULL)
4191 HSA_SORRY_AT (gimple_location (stmt),
4192 "support for HSA does not implement omp_get_level called "
4193 "from a function not being inlined within a kernel");
4194 return;
4197 hsa_op_address *addr
4198 = new hsa_op_address (shadow_reg_ptr,
4199 get_hsa_kernel_dispatch_offset ("omp_level"));
4201 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4202 (hsa_op_base *) NULL, addr);
4203 hbb->append_insn (mem);
4204 mem->set_output_in_type (dest, 0, hbb);
4207 /* Emit instruction that implement omp_get_max_threads of gimple STMT. */
4209 static void
4210 gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4212 tree lhs = gimple_call_lhs (stmt);
4213 if (!lhs)
4214 return;
4216 hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4218 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4219 hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4220 ->get_in_type (dest->m_type, hbb);
4221 hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4224 /* Emit instructions that implement alloca builtin gimple STMT.
4225 Instructions are appended to basic block HBB. */
4227 static void
4228 gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4230 tree lhs = gimple_call_lhs (call);
4231 if (lhs == NULL_TREE)
4232 return;
4234 built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
4236 gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
4238 unsigned bit_alignment = 0;
4240 if (fn != BUILT_IN_ALLOCA)
4242 tree alignment_tree = gimple_call_arg (call, 1);
4243 if (TREE_CODE (alignment_tree) != INTEGER_CST)
4245 HSA_SORRY_ATV (gimple_location (call),
4246 "support for HSA does not implement "
4247 "__builtin_alloca_with_align with a non-constant "
4248 "alignment: %E", alignment_tree);
4251 bit_alignment = tree_to_uhwi (alignment_tree);
4254 tree rhs1 = gimple_call_arg (call, 0);
4255 hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4256 ->get_in_type (BRIG_TYPE_U32, hbb);
4257 hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4259 hsa_op_reg *tmp
4260 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4261 hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4262 hbb->append_insn (a);
4264 hsa_insn_seg *seg
4265 = new hsa_insn_seg (BRIG_OPCODE_STOF,
4266 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4267 tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4268 hbb->append_insn (seg);
4271 /* Emit instructions that implement clrsb builtin STMT:
4272 Returns the number of leading redundant sign bits in x, i.e. the number
4273 of bits following the most significant bit that are identical to it.
4274 There are no special cases for 0 or other values.
4275 Instructions are appended to basic block HBB. */
4277 static void
4278 gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4280 tree lhs = gimple_call_lhs (call);
4281 if (lhs == NULL_TREE)
4282 return;
4284 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4285 tree rhs1 = gimple_call_arg (call, 0);
4286 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4287 arg->extend_int_to_32bit (hbb);
4288 BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4289 unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
4291 /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers. */
4292 gcc_checking_assert (bitsize == 32 || bitsize == 64);
4294 /* Set true to MOST_SIG if the most significant bit is set to one. */
4295 hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4296 hsa_uint_for_bitsize (bitsize));
4298 hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4299 gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4301 hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4302 hsa_insn_cmp *cmp
4303 = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4304 and_reg, c);
4305 hbb->append_insn (cmp);
4307 /* If the most significant bit is one, negate the input. Otherwise
4308 shift the input value to left by one bit. */
4309 hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4310 gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4312 hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4313 gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4314 new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4316 /* Assign the value that can be used for FIRSTBIT instruction according
4317 to the most significant bit. */
4318 hsa_op_reg *tmp = new hsa_op_reg (bittype);
4319 hsa_insn_basic *cmov
4320 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4321 arg_neg, shifted_arg);
4322 hbb->append_insn (cmov);
4324 hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4325 gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4326 tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4327 hbb), hbb);
4329 /* Set flag if the input value is equal to zero. */
4330 hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4331 cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4332 new hsa_op_immed (0, arg->m_type));
4333 hbb->append_insn (cmp);
4335 /* Return the number of leading bits,
4336 or (bitsize - 1) if the input value is zero. */
4337 cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
4338 new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
4339 leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4340 hbb->append_insn (cmov);
4341 cmov->set_output_in_type (dest, 0, hbb);
4344 /* Emit instructions that implement ffs builtin STMT:
4345 Returns one plus the index of the least significant 1-bit of x,
4346 or if x is zero, returns zero.
4347 Instructions are appended to basic block HBB. */
4349 static void
4350 gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4352 tree lhs = gimple_call_lhs (call);
4353 if (lhs == NULL_TREE)
4354 return;
4356 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4358 tree rhs1 = gimple_call_arg (call, 0);
4359 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4360 arg = arg->extend_int_to_32bit (hbb);
4362 hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4363 hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4364 tmp->m_type, arg->m_type,
4365 tmp, arg);
4366 hbb->append_insn (insn);
4368 hsa_insn_basic *addition
4369 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4370 new hsa_op_immed (1, tmp->m_type));
4371 hbb->append_insn (addition);
4372 addition->set_output_in_type (dest, 0, hbb);
4375 static void
4376 gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4378 gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4380 if (hsa_type_bit_size (arg->m_type) < 32)
4381 arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4383 BrigType16_t srctype = hsa_bittype_for_type (arg->m_type);
4384 if (!hsa_btype_p (arg->m_type))
4385 arg = arg->get_in_type (srctype, hbb);
4387 hsa_insn_srctype *popcount
4388 = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4389 srctype, NULL, arg);
4390 hbb->append_insn (popcount);
4391 popcount->set_output_in_type (dest, 0, hbb);
4394 /* Emit instructions that implement parity builtin STMT:
4395 Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4396 Instructions are appended to basic block HBB. */
4398 static void
4399 gen_hsa_parity (gcall *call, hsa_bb *hbb)
4401 tree lhs = gimple_call_lhs (call);
4402 if (lhs == NULL_TREE)
4403 return;
4405 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4406 tree rhs1 = gimple_call_arg (call, 0);
4407 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4409 hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4410 gen_hsa_popcount_to_dest (popcount, arg, hbb);
4412 hsa_insn_basic *insn
4413 = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4414 new hsa_op_immed (2, popcount->m_type));
4415 hbb->append_insn (insn);
4416 insn->set_output_in_type (dest, 0, hbb);
4419 /* Emit instructions that implement popcount builtin STMT.
4420 Instructions are appended to basic block HBB. */
4422 static void
4423 gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4425 tree lhs = gimple_call_lhs (call);
4426 if (lhs == NULL_TREE)
4427 return;
4429 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4430 tree rhs1 = gimple_call_arg (call, 0);
4431 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4433 gen_hsa_popcount_to_dest (dest, arg, hbb);
4436 /* Emit instructions that implement DIVMOD builtin STMT.
4437 Instructions are appended to basic block HBB. */
4439 static void
4440 gen_hsa_divmod (gcall *call, hsa_bb *hbb)
4442 tree lhs = gimple_call_lhs (call);
4443 if (lhs == NULL_TREE)
4444 return;
4446 tree rhs0 = gimple_call_arg (call, 0);
4447 tree rhs1 = gimple_call_arg (call, 1);
4449 hsa_op_with_type *arg0 = hsa_reg_or_immed_for_gimple_op (rhs0, hbb);
4450 arg0 = arg0->extend_int_to_32bit (hbb);
4451 hsa_op_with_type *arg1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4452 arg1 = arg1->extend_int_to_32bit (hbb);
4454 hsa_op_reg *dest0 = new hsa_op_reg (arg0->m_type);
4455 hsa_op_reg *dest1 = new hsa_op_reg (arg1->m_type);
4457 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_DIV, dest0->m_type,
4458 dest0, arg0, arg1);
4459 hbb->append_insn (insn);
4460 insn = new hsa_insn_basic (3, BRIG_OPCODE_REM, dest1->m_type, dest1, arg0,
4461 arg1);
4462 hbb->append_insn (insn);
4464 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4465 BrigType16_t dst_type = hsa_extend_inttype_to_32bit (dest->m_type);
4466 BrigType16_t src_type = hsa_bittype_for_type (dest0->m_type);
4468 insn = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dst_type,
4469 src_type, NULL, dest0, dest1);
4470 hbb->append_insn (insn);
4471 insn->set_output_in_type (dest, 0, hbb);
4474 /* Emit instructions that implement FMA, FMS, FNMA or FNMS call STMT.
4475 Instructions are appended to basic block HBB. NEGATE1 is true for
4476 FNMA and FNMS. NEGATE3 is true for FMS and FNMS. */
4478 static void
4479 gen_hsa_fma (gcall *call, hsa_bb *hbb, bool negate1, bool negate3)
4481 tree lhs = gimple_call_lhs (call);
4482 if (lhs == NULL_TREE)
4483 return;
4485 tree rhs1 = gimple_call_arg (call, 0);
4486 tree rhs2 = gimple_call_arg (call, 1);
4487 tree rhs3 = gimple_call_arg (call, 2);
4489 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4490 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4491 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
4492 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
4494 if (negate1)
4496 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4497 gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op1, hbb);
4498 op1 = tmp;
4501 /* There is a native HSA instruction for scalar FMAs but not for vector
4502 ones. */
4503 if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
4505 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4506 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp, op1, op2, hbb);
4507 gen_hsa_binary_operation (negate3 ? BRIG_OPCODE_SUB : BRIG_OPCODE_ADD,
4508 dest, tmp, op3, hbb);
4510 else
4512 if (negate3)
4514 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4515 gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op3, hbb);
4516 op3 = tmp;
4518 hsa_insn_basic *insn = new hsa_insn_basic (4, BRIG_OPCODE_MAD,
4519 dest->m_type, dest,
4520 op1, op2, op3);
4521 hbb->append_insn (insn);
4525 /* Set VALUE to a shadow kernel debug argument and append a new instruction
4526 to HBB basic block. */
4528 static void
4529 set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4531 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4532 if (shadow_reg_ptr == NULL)
4533 return;
4535 hsa_op_address *addr
4536 = new hsa_op_address (shadow_reg_ptr,
4537 get_hsa_kernel_dispatch_offset ("debug"));
4538 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4539 addr);
4540 hbb->append_insn (mem);
4543 void
4544 omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4546 if (m_sorry)
4548 if (m_warning_message)
4549 HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
4550 else
4551 HSA_SORRY_ATV (gimple_location (stmt),
4552 "Support for HSA does not implement calls to %s\n",
4553 m_name);
4555 else if (m_warning_message != NULL)
4556 warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4558 if (m_return_value != NULL)
4560 tree lhs = gimple_call_lhs (stmt);
4561 if (!lhs)
4562 return;
4564 hbb->append_insn (new hsa_insn_comment (m_name));
4566 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4567 hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4568 hsa_build_append_simple_mov (dest, op, hbb);
4572 /* If STMT is a call of a known library function, generate code to perform
4573 it and return true. */
4575 static bool
4576 gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4578 bool handled = false;
4579 const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4581 char *copy = NULL;
4582 size_t len = strlen (name);
4583 if (len > 0 && name[len - 1] == '_')
4585 copy = XNEWVEC (char, len + 1);
4586 strcpy (copy, name);
4587 copy[len - 1] = '\0';
4588 name = copy;
4591 /* Handle omp_* routines. */
4592 if (strstr (name, "omp_") == name)
4594 hsa_init_simple_builtins ();
4595 omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4596 if (builtin)
4598 builtin->generate (stmt, hbb);
4599 return true;
4602 handled = true;
4603 if (strcmp (name, "omp_set_num_threads") == 0)
4604 gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4605 else if (strcmp (name, "omp_get_thread_num") == 0)
4607 hbb->append_insn (new hsa_insn_comment (name));
4608 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
4610 else if (strcmp (name, "omp_get_num_threads") == 0)
4612 hbb->append_insn (new hsa_insn_comment (name));
4613 gen_get_num_threads (stmt, hbb);
4615 else if (strcmp (name, "omp_get_num_teams") == 0)
4616 gen_get_num_teams (stmt, hbb);
4617 else if (strcmp (name, "omp_get_team_num") == 0)
4618 gen_get_team_num (stmt, hbb);
4619 else if (strcmp (name, "omp_get_level") == 0)
4620 gen_get_level (stmt, hbb);
4621 else if (strcmp (name, "omp_get_active_level") == 0)
4622 gen_get_level (stmt, hbb);
4623 else if (strcmp (name, "omp_in_parallel") == 0)
4624 gen_get_level (stmt, hbb);
4625 else if (strcmp (name, "omp_get_max_threads") == 0)
4626 gen_get_max_threads (stmt, hbb);
4627 else
4628 handled = false;
4630 if (handled)
4632 if (copy)
4633 free (copy);
4634 return true;
4638 if (strcmp (name, "__hsa_set_debug_value") == 0)
4640 handled = true;
4641 if (hsa_cfun->has_shadow_reg_p ())
4643 tree rhs1 = gimple_call_arg (stmt, 0);
4644 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4646 src = src->get_in_type (BRIG_TYPE_U64, hbb);
4647 set_debug_value (hbb, src);
4651 if (copy)
4652 free (copy);
4653 return handled;
4656 /* Helper functions to create a single unary HSA operations out of calls to
4657 builtins. OPCODE is the HSA operation to be generated. STMT is a gimple
4658 call to a builtin. HBB is the HSA BB to which the instruction should be
4659 added. Note that nothing will be created if STMT does not have a LHS. */
4661 static void
4662 gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4664 tree lhs = gimple_call_lhs (stmt);
4665 if (!lhs)
4666 return;
4667 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4668 hsa_op_with_type *op
4669 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4670 gen_hsa_unary_operation (opcode, dest, op, hbb);
4673 /* Helper functions to create a call to standard library if LHS of the
4674 STMT is used. HBB is the HSA BB to which the instruction should be
4675 added. */
4677 static void
4678 gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4680 tree lhs = gimple_call_lhs (stmt);
4681 if (!lhs)
4682 return;
4684 if (gimple_call_internal_p (stmt))
4685 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4686 else
4687 gen_hsa_insns_for_direct_call (stmt, hbb);
4690 /* Helper functions to create a single unary HSA operations out of calls to
4691 builtins (if unsafe math optimizations are enable). Otherwise, create
4692 a call to standard library function.
4693 OPCODE is the HSA operation to be generated. STMT is a gimple
4694 call to a builtin. HBB is the HSA BB to which the instruction should be
4695 added. Note that nothing will be created if STMT does not have a LHS. */
4697 static void
4698 gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4699 hsa_bb *hbb)
4701 if (flag_unsafe_math_optimizations)
4702 gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4703 else
4704 gen_hsa_unaryop_builtin_call (stmt, hbb);
4707 /* Generate HSA address corresponding to a value VAL (as opposed to a memory
4708 reference tree), for example an SSA_NAME or an ADDR_EXPR. HBB is the HSA BB
4709 to which the instruction should be added. */
4711 static hsa_op_address *
4712 get_address_from_value (tree val, hsa_bb *hbb)
4714 switch (TREE_CODE (val))
4716 case SSA_NAME:
4718 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4719 hsa_op_base *reg
4720 = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4721 return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4723 case ADDR_EXPR:
4724 return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4726 case INTEGER_CST:
4727 if (tree_fits_shwi_p (val))
4728 return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
4729 /* fall-through */
4731 default:
4732 HSA_SORRY_ATV (EXPR_LOCATION (val),
4733 "support for HSA does not implement memory access to %E",
4734 val);
4735 return new hsa_op_address (NULL, NULL, 0);
4739 /* Expand assignment of a result of a string BUILTIN to DST.
4740 Size of the operation is N bytes, where instructions
4741 will be append to HBB. */
4743 static void
4744 expand_lhs_of_string_op (gimple *stmt,
4745 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4746 enum built_in_function builtin)
4748 /* If LHS is expected, we need to emit a PHI instruction. */
4749 tree lhs = gimple_call_lhs (stmt);
4750 if (!lhs)
4751 return;
4753 hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4755 hsa_op_with_type *dst_reg
4756 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4757 hsa_op_with_type *tmp;
4759 switch (builtin)
4761 case BUILT_IN_MEMPCPY:
4763 tmp = new hsa_op_reg (dst_reg->m_type);
4764 hsa_insn_basic *add
4765 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4766 tmp, dst_reg,
4767 new hsa_op_immed (n, dst_reg->m_type));
4768 hbb->append_insn (add);
4769 break;
4771 case BUILT_IN_MEMCPY:
4772 case BUILT_IN_MEMSET:
4773 tmp = dst_reg;
4774 break;
4775 default:
4776 gcc_unreachable ();
4779 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4780 lhs_reg, tmp));
4783 #define HSA_MEMORY_BUILTINS_LIMIT 128
4785 /* Expand a string builtin (from a gimple STMT) in a way that
4786 according to MISALIGNED_FLAG we process either direct emission
4787 (a bunch of memory load and store instructions), or we emit a function call
4788 of a library function (for instance 'memcpy'). Actually, a basic block
4789 for direct emission is just prepared, where caller is responsible
4790 for emission of corresponding instructions.
4791 All instruction are appended to HBB. */
4793 hsa_bb *
4794 expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4795 hsa_op_reg *misaligned_flag)
4797 edge e = split_block (hbb->m_bb, stmt);
4798 basic_block condition_bb = e->src;
4799 hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
4801 /* Prepare the control flow. */
4802 edge condition_edge = EDGE_SUCC (condition_bb, 0);
4803 basic_block call_bb = split_edge (condition_edge);
4805 basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4806 basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4807 basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4809 condition_edge->flags &= ~EDGE_FALLTHRU;
4810 condition_edge->flags |= EDGE_TRUE_VALUE;
4811 make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4813 redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4815 hsa_cfun->m_modified_cfg = true;
4817 hsa_init_new_bb (expanded_bb);
4819 /* Slow path: function call. */
4820 gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4822 return hsa_bb_for_bb (expanded_bb);
4825 /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4826 a gimple STMT and store all necessary instruction to HBB basic block. */
4828 static void
4829 expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4831 tree byte_size = gimple_call_arg (stmt, 2);
4833 if (!tree_fits_uhwi_p (byte_size))
4835 gen_hsa_insns_for_direct_call (stmt, hbb);
4836 return;
4839 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4841 if (n > HSA_MEMORY_BUILTINS_LIMIT)
4843 gen_hsa_insns_for_direct_call (stmt, hbb);
4844 return;
4847 tree dst = gimple_call_arg (stmt, 0);
4848 tree src = gimple_call_arg (stmt, 1);
4850 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4851 hsa_op_address *src_addr = get_address_from_value (src, hbb);
4853 /* As gen_hsa_memory_copy relies on memory alignment
4854 greater or equal to 8 bytes, we need to verify the alignment. */
4855 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4856 hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4857 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4859 convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4860 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4862 /* Process BIT OR for source and destination addresses. */
4863 hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4864 gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4865 dst_addr_reg, hbb);
4867 /* Process BIT AND with 0x7 to identify the desired alignment
4868 of 8 bytes. */
4869 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4871 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4872 new hsa_op_immed (7, addrtype), hbb);
4874 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4875 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4876 misaligned, masked,
4877 new hsa_op_immed (0, masked->m_type)));
4879 hsa_bb *native_impl_bb
4880 = expand_string_operation_builtin (stmt, hbb, misaligned);
4882 gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4883 hsa_bb *merge_bb
4884 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4885 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4889 /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4890 a gimple STMT and store all necessary instruction to HBB basic block.
4891 The operation set N bytes with a CONSTANT value. */
4893 static void
4894 expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4895 unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4896 enum built_in_function builtin)
4898 tree dst = gimple_call_arg (stmt, 0);
4899 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4901 /* As gen_hsa_memory_set relies on memory alignment
4902 greater or equal to 8 bytes, we need to verify the alignment. */
4903 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4904 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4905 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4907 /* Process BIT AND with 0x7 to identify the desired alignment
4908 of 8 bytes. */
4909 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4911 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4912 new hsa_op_immed (7, addrtype), hbb);
4914 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4915 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4916 misaligned, masked,
4917 new hsa_op_immed (0, masked->m_type)));
4919 hsa_bb *native_impl_bb
4920 = expand_string_operation_builtin (stmt, hbb, misaligned);
4922 gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4923 hsa_bb *merge_bb
4924 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4925 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4928 /* Store into MEMORDER the memory order specified by tree T, which must be an
4929 integer constant representing a C++ memory order. If it isn't, issue an HSA
4930 sorry message using LOC and return true, otherwise return false and store
4931 the name of the requested order to *MNAME. */
4933 static bool
4934 hsa_memorder_from_tree (tree t, BrigMemoryOrder *memorder, const char **mname,
4935 location_t loc)
4937 if (!tree_fits_uhwi_p (t))
4939 HSA_SORRY_ATV (loc, "support for HSA does not implement memory model %E",
4941 return true;
4944 unsigned HOST_WIDE_INT mm = tree_to_uhwi (t);
4945 switch (mm & MEMMODEL_BASE_MASK)
4947 case MEMMODEL_RELAXED:
4948 *memorder = BRIG_MEMORY_ORDER_RELAXED;
4949 *mname = "relaxed";
4950 break;
4951 case MEMMODEL_CONSUME:
4952 /* HSA does not have an equivalent, but we can use the slightly stronger
4953 ACQUIRE. */
4954 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4955 *mname = "consume";
4956 break;
4957 case MEMMODEL_ACQUIRE:
4958 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4959 *mname = "acquire";
4960 break;
4961 case MEMMODEL_RELEASE:
4962 *memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4963 *mname = "release";
4964 break;
4965 case MEMMODEL_ACQ_REL:
4966 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4967 *mname = "acq_rel";
4968 break;
4969 case MEMMODEL_SEQ_CST:
4970 /* Callers implementing a simple load or store need to remove the release
4971 or acquire part respectively. */
4972 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4973 *mname = "seq_cst";
4974 break;
4975 default:
4977 HSA_SORRY_AT (loc, "support for HSA does not implement the specified "
4978 "memory model");
4979 return true;
4982 return false;
4985 /* Helper function to create an HSA atomic operation instruction out of calls
4986 to atomic builtins. RET_ORIG is true if the built-in is the variant that
4987 return s the value before applying operation, and false if it should return
4988 the value after applying the operation (if it returns value at all). ACODE
4989 is the atomic operation code, STMT is a gimple call to a builtin. HBB is
4990 the HSA BB to which the instruction should be added. If SIGNAL is true, the
4991 created operation will work on HSA signals rather than atomic variables. */
4993 static void
4994 gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
4995 gimple *stmt, hsa_bb *hbb, bool signal)
4997 tree lhs = gimple_call_lhs (stmt);
4999 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5000 BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
5001 BrigType16_t mtype = mem_type_for_type (hsa_type);
5002 BrigMemoryOrder memorder;
5003 const char *mmname;
5005 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 2), &memorder, &mmname,
5006 gimple_location (stmt)))
5007 return;
5009 /* Certain atomic insns must have Bx memory types. */
5010 switch (acode)
5012 case BRIG_ATOMIC_LD:
5013 case BRIG_ATOMIC_ST:
5014 case BRIG_ATOMIC_AND:
5015 case BRIG_ATOMIC_OR:
5016 case BRIG_ATOMIC_XOR:
5017 case BRIG_ATOMIC_EXCH:
5018 mtype = hsa_bittype_for_type (mtype);
5019 break;
5020 default:
5021 break;
5024 hsa_op_reg *dest;
5025 int nops, opcode;
5026 if (lhs)
5028 if (ret_orig)
5029 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5030 else
5031 dest = new hsa_op_reg (hsa_type);
5032 opcode = signal ? BRIG_OPCODE_SIGNAL : BRIG_OPCODE_ATOMIC;
5033 nops = 3;
5035 else
5037 dest = NULL;
5038 opcode = signal ? BRIG_OPCODE_SIGNALNORET : BRIG_OPCODE_ATOMICNORET;
5039 nops = 2;
5042 if (acode == BRIG_ATOMIC_ST)
5044 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5045 memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
5047 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5048 && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
5049 && memorder != BRIG_MEMORY_ORDER_NONE)
5051 HSA_SORRY_ATV (gimple_location (stmt),
5052 "support for HSA does not implement memory model for "
5053 "ATOMIC_ST: %s", mmname);
5054 return;
5058 hsa_insn_basic *atominsn;
5059 hsa_op_base *tgt;
5060 if (signal)
5062 atominsn = new hsa_insn_signal (nops, opcode, acode, mtype, memorder);
5063 tgt = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
5065 else
5067 atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, memorder);
5068 hsa_op_address *addr;
5069 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5070 if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
5072 HSA_SORRY_AT (gimple_location (stmt),
5073 "HSA does not implement atomic operations in private "
5074 "segment");
5075 return;
5077 tgt = addr;
5080 hsa_op_with_type *op
5081 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5082 if (lhs)
5084 atominsn->set_op (0, dest);
5085 atominsn->set_op (1, tgt);
5086 atominsn->set_op (2, op);
5088 else
5090 atominsn->set_op (0, tgt);
5091 atominsn->set_op (1, op);
5094 hbb->append_insn (atominsn);
5096 /* HSA does not natively support the variants that return the modified value,
5097 so re-do the operation again non-atomically if that is what was
5098 requested. */
5099 if (lhs && !ret_orig)
5101 int arith;
5102 switch (acode)
5104 case BRIG_ATOMIC_ADD:
5105 arith = BRIG_OPCODE_ADD;
5106 break;
5107 case BRIG_ATOMIC_AND:
5108 arith = BRIG_OPCODE_AND;
5109 break;
5110 case BRIG_ATOMIC_OR:
5111 arith = BRIG_OPCODE_OR;
5112 break;
5113 case BRIG_ATOMIC_SUB:
5114 arith = BRIG_OPCODE_SUB;
5115 break;
5116 case BRIG_ATOMIC_XOR:
5117 arith = BRIG_OPCODE_XOR;
5118 break;
5119 default:
5120 gcc_unreachable ();
5122 hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5123 gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
5127 /* Generate HSA instructions for an internal fn.
5128 Instructions will be appended to HBB, which also needs to be the
5129 corresponding structure to the basic_block of STMT. */
5131 static void
5132 gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
5134 gcc_checking_assert (gimple_call_internal_fn (stmt));
5135 internal_fn fn = gimple_call_internal_fn (stmt);
5137 bool is_float_type_p = false;
5138 if (gimple_call_lhs (stmt) != NULL
5139 && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
5140 is_float_type_p = true;
5142 switch (fn)
5144 case IFN_CEIL:
5145 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5146 break;
5148 case IFN_FLOOR:
5149 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5150 break;
5152 case IFN_RINT:
5153 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5154 break;
5156 case IFN_SQRT:
5157 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5158 break;
5160 case IFN_RSQRT:
5161 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NRSQRT, stmt, hbb);
5162 break;
5164 case IFN_TRUNC:
5165 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5166 break;
5168 case IFN_COS:
5170 if (is_float_type_p)
5171 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5172 else
5173 gen_hsa_unaryop_builtin_call (stmt, hbb);
5175 break;
5177 case IFN_EXP2:
5179 if (is_float_type_p)
5180 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5181 else
5182 gen_hsa_unaryop_builtin_call (stmt, hbb);
5184 break;
5187 case IFN_LOG2:
5189 if (is_float_type_p)
5190 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5191 else
5192 gen_hsa_unaryop_builtin_call (stmt, hbb);
5194 break;
5197 case IFN_SIN:
5199 if (is_float_type_p)
5200 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5201 else
5202 gen_hsa_unaryop_builtin_call (stmt, hbb);
5203 break;
5206 case IFN_CLRSB:
5207 gen_hsa_clrsb (stmt, hbb);
5208 break;
5210 case IFN_CLZ:
5211 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5212 break;
5214 case IFN_CTZ:
5215 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5216 break;
5218 case IFN_FFS:
5219 gen_hsa_ffs (stmt, hbb);
5220 break;
5222 case IFN_PARITY:
5223 gen_hsa_parity (stmt, hbb);
5224 break;
5226 case IFN_POPCOUNT:
5227 gen_hsa_popcount (stmt, hbb);
5228 break;
5230 case IFN_DIVMOD:
5231 gen_hsa_divmod (stmt, hbb);
5232 break;
5234 case IFN_ACOS:
5235 case IFN_ASIN:
5236 case IFN_ATAN:
5237 case IFN_EXP:
5238 case IFN_EXP10:
5239 case IFN_EXPM1:
5240 case IFN_LOG:
5241 case IFN_LOG10:
5242 case IFN_LOG1P:
5243 case IFN_LOGB:
5244 case IFN_SIGNIFICAND:
5245 case IFN_TAN:
5246 case IFN_NEARBYINT:
5247 case IFN_ROUND:
5248 case IFN_ATAN2:
5249 case IFN_COPYSIGN:
5250 case IFN_FMOD:
5251 case IFN_POW:
5252 case IFN_REMAINDER:
5253 case IFN_SCALB:
5254 case IFN_FMIN:
5255 case IFN_FMAX:
5256 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
5257 break;
5259 case IFN_FMA:
5260 gen_hsa_fma (stmt, hbb, false, false);
5261 break;
5263 case IFN_FMS:
5264 gen_hsa_fma (stmt, hbb, false, true);
5265 break;
5267 case IFN_FNMA:
5268 gen_hsa_fma (stmt, hbb, true, false);
5269 break;
5271 case IFN_FNMS:
5272 gen_hsa_fma (stmt, hbb, true, true);
5273 break;
5275 default:
5276 HSA_SORRY_ATV (gimple_location (stmt),
5277 "support for HSA does not implement internal function: %s",
5278 internal_fn_name (fn));
5279 break;
5283 /* Generate HSA instructions for the given call statement STMT. Instructions
5284 will be appended to HBB. */
5286 static void
5287 gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5289 gcall *call = as_a <gcall *> (stmt);
5290 tree lhs = gimple_call_lhs (stmt);
5291 hsa_op_reg *dest;
5293 if (gimple_call_internal_p (stmt))
5295 gen_hsa_insn_for_internal_fn_call (call, hbb);
5296 return;
5299 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5301 tree function_decl = gimple_call_fndecl (stmt);
5302 /* Prefetch pass can create type-mismatching prefetch builtin calls which
5303 fail the gimple_call_builtin_p test above. Handle them here. */
5304 if (DECL_BUILT_IN_CLASS (function_decl)
5305 && DECL_FUNCTION_CODE (function_decl) == BUILT_IN_PREFETCH)
5306 return;
5308 if (function_decl == NULL_TREE)
5310 HSA_SORRY_AT (gimple_location (stmt),
5311 "support for HSA does not implement indirect calls");
5312 return;
5315 if (hsa_callable_function_p (function_decl))
5316 gen_hsa_insns_for_direct_call (stmt, hbb);
5317 else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5318 HSA_SORRY_AT (gimple_location (stmt),
5319 "HSA supports only calls of functions marked with pragma "
5320 "omp declare target");
5321 return;
5324 tree fndecl = gimple_call_fndecl (stmt);
5325 enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5326 switch (builtin)
5328 case BUILT_IN_FABS:
5329 case BUILT_IN_FABSF:
5330 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5331 break;
5333 case BUILT_IN_CEIL:
5334 case BUILT_IN_CEILF:
5335 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5336 break;
5338 case BUILT_IN_FLOOR:
5339 case BUILT_IN_FLOORF:
5340 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5341 break;
5343 case BUILT_IN_RINT:
5344 case BUILT_IN_RINTF:
5345 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5346 break;
5348 case BUILT_IN_SQRT:
5349 case BUILT_IN_SQRTF:
5350 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5351 break;
5353 case BUILT_IN_TRUNC:
5354 case BUILT_IN_TRUNCF:
5355 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5356 break;
5358 case BUILT_IN_COS:
5359 case BUILT_IN_SIN:
5360 case BUILT_IN_EXP2:
5361 case BUILT_IN_LOG2:
5362 /* HSAIL does not provide an instruction for double argument type. */
5363 gen_hsa_unaryop_builtin_call (stmt, hbb);
5364 break;
5366 case BUILT_IN_COSF:
5367 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5368 break;
5370 case BUILT_IN_EXP2F:
5371 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5372 break;
5374 case BUILT_IN_LOG2F:
5375 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5376 break;
5378 case BUILT_IN_SINF:
5379 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5380 break;
5382 case BUILT_IN_CLRSB:
5383 case BUILT_IN_CLRSBL:
5384 case BUILT_IN_CLRSBLL:
5385 gen_hsa_clrsb (call, hbb);
5386 break;
5388 case BUILT_IN_CLZ:
5389 case BUILT_IN_CLZL:
5390 case BUILT_IN_CLZLL:
5391 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5392 break;
5394 case BUILT_IN_CTZ:
5395 case BUILT_IN_CTZL:
5396 case BUILT_IN_CTZLL:
5397 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5398 break;
5400 case BUILT_IN_FFS:
5401 case BUILT_IN_FFSL:
5402 case BUILT_IN_FFSLL:
5403 gen_hsa_ffs (call, hbb);
5404 break;
5406 case BUILT_IN_PARITY:
5407 case BUILT_IN_PARITYL:
5408 case BUILT_IN_PARITYLL:
5409 gen_hsa_parity (call, hbb);
5410 break;
5412 case BUILT_IN_POPCOUNT:
5413 case BUILT_IN_POPCOUNTL:
5414 case BUILT_IN_POPCOUNTLL:
5415 gen_hsa_popcount (call, hbb);
5416 break;
5418 case BUILT_IN_ATOMIC_LOAD_1:
5419 case BUILT_IN_ATOMIC_LOAD_2:
5420 case BUILT_IN_ATOMIC_LOAD_4:
5421 case BUILT_IN_ATOMIC_LOAD_8:
5422 case BUILT_IN_ATOMIC_LOAD_16:
5424 BrigType16_t mtype;
5425 hsa_op_base *src;
5426 src = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5428 BrigMemoryOrder memorder;
5429 const char *mmname;
5430 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 1), &memorder,
5431 &mmname, gimple_location (stmt)))
5432 return;
5434 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5435 memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5437 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5438 && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5439 && memorder != BRIG_MEMORY_ORDER_NONE)
5441 HSA_SORRY_ATV (gimple_location (stmt),
5442 "support for HSA does not implement "
5443 "memory model for atomic loads: %s", mmname);
5444 return;
5447 if (lhs)
5449 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5450 false);
5451 mtype = mem_type_for_type (t);
5452 mtype = hsa_bittype_for_type (mtype);
5453 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5455 else
5457 mtype = BRIG_TYPE_B64;
5458 dest = new hsa_op_reg (mtype);
5461 hsa_insn_basic *atominsn;
5462 atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD,
5463 mtype, memorder, dest, src);
5465 hbb->append_insn (atominsn);
5466 break;
5469 case BUILT_IN_ATOMIC_EXCHANGE_1:
5470 case BUILT_IN_ATOMIC_EXCHANGE_2:
5471 case BUILT_IN_ATOMIC_EXCHANGE_4:
5472 case BUILT_IN_ATOMIC_EXCHANGE_8:
5473 case BUILT_IN_ATOMIC_EXCHANGE_16:
5474 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb, false);
5475 break;
5476 break;
5478 case BUILT_IN_ATOMIC_FETCH_ADD_1:
5479 case BUILT_IN_ATOMIC_FETCH_ADD_2:
5480 case BUILT_IN_ATOMIC_FETCH_ADD_4:
5481 case BUILT_IN_ATOMIC_FETCH_ADD_8:
5482 case BUILT_IN_ATOMIC_FETCH_ADD_16:
5483 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb, false);
5484 break;
5485 break;
5487 case BUILT_IN_ATOMIC_FETCH_SUB_1:
5488 case BUILT_IN_ATOMIC_FETCH_SUB_2:
5489 case BUILT_IN_ATOMIC_FETCH_SUB_4:
5490 case BUILT_IN_ATOMIC_FETCH_SUB_8:
5491 case BUILT_IN_ATOMIC_FETCH_SUB_16:
5492 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb, false);
5493 break;
5494 break;
5496 case BUILT_IN_ATOMIC_FETCH_AND_1:
5497 case BUILT_IN_ATOMIC_FETCH_AND_2:
5498 case BUILT_IN_ATOMIC_FETCH_AND_4:
5499 case BUILT_IN_ATOMIC_FETCH_AND_8:
5500 case BUILT_IN_ATOMIC_FETCH_AND_16:
5501 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb, false);
5502 break;
5503 break;
5505 case BUILT_IN_ATOMIC_FETCH_XOR_1:
5506 case BUILT_IN_ATOMIC_FETCH_XOR_2:
5507 case BUILT_IN_ATOMIC_FETCH_XOR_4:
5508 case BUILT_IN_ATOMIC_FETCH_XOR_8:
5509 case BUILT_IN_ATOMIC_FETCH_XOR_16:
5510 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb, false);
5511 break;
5512 break;
5514 case BUILT_IN_ATOMIC_FETCH_OR_1:
5515 case BUILT_IN_ATOMIC_FETCH_OR_2:
5516 case BUILT_IN_ATOMIC_FETCH_OR_4:
5517 case BUILT_IN_ATOMIC_FETCH_OR_8:
5518 case BUILT_IN_ATOMIC_FETCH_OR_16:
5519 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb, false);
5520 break;
5521 break;
5523 case BUILT_IN_ATOMIC_STORE_1:
5524 case BUILT_IN_ATOMIC_STORE_2:
5525 case BUILT_IN_ATOMIC_STORE_4:
5526 case BUILT_IN_ATOMIC_STORE_8:
5527 case BUILT_IN_ATOMIC_STORE_16:
5528 /* Since there cannot be any LHS, the first parameter is meaningless. */
5529 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb, false);
5530 break;
5531 break;
5533 case BUILT_IN_ATOMIC_ADD_FETCH_1:
5534 case BUILT_IN_ATOMIC_ADD_FETCH_2:
5535 case BUILT_IN_ATOMIC_ADD_FETCH_4:
5536 case BUILT_IN_ATOMIC_ADD_FETCH_8:
5537 case BUILT_IN_ATOMIC_ADD_FETCH_16:
5538 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb, false);
5539 break;
5541 case BUILT_IN_ATOMIC_SUB_FETCH_1:
5542 case BUILT_IN_ATOMIC_SUB_FETCH_2:
5543 case BUILT_IN_ATOMIC_SUB_FETCH_4:
5544 case BUILT_IN_ATOMIC_SUB_FETCH_8:
5545 case BUILT_IN_ATOMIC_SUB_FETCH_16:
5546 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb, false);
5547 break;
5549 case BUILT_IN_ATOMIC_AND_FETCH_1:
5550 case BUILT_IN_ATOMIC_AND_FETCH_2:
5551 case BUILT_IN_ATOMIC_AND_FETCH_4:
5552 case BUILT_IN_ATOMIC_AND_FETCH_8:
5553 case BUILT_IN_ATOMIC_AND_FETCH_16:
5554 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb, false);
5555 break;
5557 case BUILT_IN_ATOMIC_XOR_FETCH_1:
5558 case BUILT_IN_ATOMIC_XOR_FETCH_2:
5559 case BUILT_IN_ATOMIC_XOR_FETCH_4:
5560 case BUILT_IN_ATOMIC_XOR_FETCH_8:
5561 case BUILT_IN_ATOMIC_XOR_FETCH_16:
5562 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb, false);
5563 break;
5565 case BUILT_IN_ATOMIC_OR_FETCH_1:
5566 case BUILT_IN_ATOMIC_OR_FETCH_2:
5567 case BUILT_IN_ATOMIC_OR_FETCH_4:
5568 case BUILT_IN_ATOMIC_OR_FETCH_8:
5569 case BUILT_IN_ATOMIC_OR_FETCH_16:
5570 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb, false);
5571 break;
5573 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5574 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5575 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5576 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5577 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5579 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5580 BrigType16_t atype
5581 = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5582 BrigMemoryOrder memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
5583 hsa_insn_basic *atominsn;
5584 hsa_op_base *tgt;
5585 atominsn = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC,
5586 BRIG_ATOMIC_CAS, atype, memorder);
5587 tgt = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5589 if (lhs != NULL)
5590 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5591 else
5592 dest = new hsa_op_reg (atype);
5594 atominsn->set_op (0, dest);
5595 atominsn->set_op (1, tgt);
5597 hsa_op_with_type *op
5598 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5599 atominsn->set_op (2, op);
5600 op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5601 atominsn->set_op (3, op);
5603 hbb->append_insn (atominsn);
5604 break;
5607 case BUILT_IN_HSA_WORKGROUPID:
5608 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKGROUPID, hbb);
5609 break;
5610 case BUILT_IN_HSA_WORKITEMID:
5611 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMID, hbb);
5612 break;
5613 case BUILT_IN_HSA_WORKITEMABSID:
5614 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMABSID, hbb);
5615 break;
5616 case BUILT_IN_HSA_GRIDSIZE:
5617 query_hsa_grid_dim (stmt, BRIG_OPCODE_GRIDSIZE, hbb);
5618 break;
5619 case BUILT_IN_HSA_CURRENTWORKGROUPSIZE:
5620 query_hsa_grid_dim (stmt, BRIG_OPCODE_CURRENTWORKGROUPSIZE, hbb);
5621 break;
5623 case BUILT_IN_GOMP_BARRIER:
5624 hbb->append_insn (new hsa_insn_br (0, BRIG_OPCODE_BARRIER, BRIG_TYPE_NONE,
5625 BRIG_WIDTH_ALL));
5626 break;
5627 case BUILT_IN_GOMP_PARALLEL:
5628 HSA_SORRY_AT (gimple_location (stmt),
5629 "support for HSA does not implement non-gridified "
5630 "OpenMP parallel constructs.");
5631 break;
5633 case BUILT_IN_OMP_GET_THREAD_NUM:
5635 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
5636 break;
5639 case BUILT_IN_OMP_GET_NUM_THREADS:
5641 gen_get_num_threads (stmt, hbb);
5642 break;
5644 case BUILT_IN_GOMP_TEAMS:
5646 gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5647 break;
5649 case BUILT_IN_OMP_GET_NUM_TEAMS:
5651 gen_get_num_teams (stmt, hbb);
5652 break;
5654 case BUILT_IN_OMP_GET_TEAM_NUM:
5656 gen_get_team_num (stmt, hbb);
5657 break;
5659 case BUILT_IN_MEMCPY:
5660 case BUILT_IN_MEMPCPY:
5662 expand_memory_copy (stmt, hbb, builtin);
5663 break;
5665 case BUILT_IN_MEMSET:
5667 tree c = gimple_call_arg (stmt, 1);
5669 if (TREE_CODE (c) != INTEGER_CST)
5671 gen_hsa_insns_for_direct_call (stmt, hbb);
5672 return;
5675 tree byte_size = gimple_call_arg (stmt, 2);
5677 if (!tree_fits_uhwi_p (byte_size))
5679 gen_hsa_insns_for_direct_call (stmt, hbb);
5680 return;
5683 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5685 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5687 gen_hsa_insns_for_direct_call (stmt, hbb);
5688 return;
5691 unsigned HOST_WIDE_INT constant
5692 = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5694 expand_memory_set (stmt, n, constant, hbb, builtin);
5696 break;
5698 case BUILT_IN_BZERO:
5700 tree byte_size = gimple_call_arg (stmt, 1);
5702 if (!tree_fits_uhwi_p (byte_size))
5704 gen_hsa_insns_for_direct_call (stmt, hbb);
5705 return;
5708 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5710 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5712 gen_hsa_insns_for_direct_call (stmt, hbb);
5713 return;
5716 expand_memory_set (stmt, n, 0, hbb, builtin);
5718 break;
5720 CASE_BUILT_IN_ALLOCA:
5722 gen_hsa_alloca (call, hbb);
5723 break;
5725 case BUILT_IN_PREFETCH:
5726 break;
5727 default:
5729 tree name_tree = DECL_NAME (fndecl);
5730 const char *s = IDENTIFIER_POINTER (name_tree);
5731 size_t len = strlen (s);
5732 if (len > 4 && (strncmp (s, "__builtin_GOMP_", 15) == 0))
5733 HSA_SORRY_ATV (gimple_location (stmt),
5734 "support for HSA does not implement GOMP function %s",
5736 else
5737 gen_hsa_insns_for_direct_call (stmt, hbb);
5738 return;
5743 /* Generate HSA instructions for a given gimple statement. Instructions will be
5744 appended to HBB. */
5746 static void
5747 gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5749 switch (gimple_code (stmt))
5751 case GIMPLE_ASSIGN:
5752 if (gimple_clobber_p (stmt))
5753 break;
5755 if (gimple_assign_single_p (stmt))
5757 tree lhs = gimple_assign_lhs (stmt);
5758 tree rhs = gimple_assign_rhs1 (stmt);
5759 gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5761 else
5762 gen_hsa_insns_for_operation_assignment (stmt, hbb);
5763 break;
5764 case GIMPLE_RETURN:
5765 gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5766 break;
5767 case GIMPLE_COND:
5768 gen_hsa_insns_for_cond_stmt (stmt, hbb);
5769 break;
5770 case GIMPLE_CALL:
5771 gen_hsa_insns_for_call (stmt, hbb);
5772 break;
5773 case GIMPLE_DEBUG:
5774 /* ??? HSA supports some debug facilities. */
5775 break;
5776 case GIMPLE_LABEL:
5778 tree label = gimple_label_label (as_a <glabel *> (stmt));
5779 if (FORCED_LABEL (label))
5780 HSA_SORRY_AT (gimple_location (stmt),
5781 "support for HSA does not implement gimple label with "
5782 "address taken");
5784 break;
5786 case GIMPLE_NOP:
5788 hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5789 break;
5791 case GIMPLE_SWITCH:
5793 gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5794 break;
5796 default:
5797 HSA_SORRY_ATV (gimple_location (stmt),
5798 "support for HSA does not implement gimple statement %s",
5799 gimple_code_name[(int) gimple_code (stmt)]);
5803 /* Generate a HSA PHI from a gimple PHI. */
5805 static void
5806 gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5808 hsa_insn_phi *hphi;
5809 unsigned count = gimple_phi_num_args (phi_stmt);
5811 hsa_op_reg *dest
5812 = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5813 hphi = new hsa_insn_phi (count, dest);
5814 hphi->m_bb = hbb->m_bb;
5816 auto_vec <tree, 8> aexprs;
5817 auto_vec <hsa_op_reg *, 8> aregs;
5819 /* Calling split_edge when processing a PHI node messes up with the order of
5820 gimple phi node arguments (it moves the one associated with the edge to
5821 the end). We need to keep the order of edges and arguments of HSA phi
5822 node arguments consistent, so we do all required splitting as the first
5823 step, and in reverse order as to not be affected by the re-orderings. */
5824 for (unsigned j = count; j != 0; j--)
5826 unsigned i = j - 1;
5827 tree op = gimple_phi_arg_def (phi_stmt, i);
5828 if (TREE_CODE (op) != ADDR_EXPR)
5829 continue;
5831 edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5832 hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5833 hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5834 hbb_src);
5836 hsa_op_reg *dest
5837 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
5838 hsa_insn_basic *insn
5839 = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5840 dest, addr);
5841 hbb_src->append_insn (insn);
5842 aexprs.safe_push (op);
5843 aregs.safe_push (dest);
5846 tree lhs = gimple_phi_result (phi_stmt);
5847 for (unsigned i = 0; i < count; i++)
5849 tree op = gimple_phi_arg_def (phi_stmt, i);
5851 if (TREE_CODE (op) == SSA_NAME)
5853 hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5854 hphi->set_op (i, hreg);
5856 else
5858 gcc_assert (is_gimple_min_invariant (op));
5859 tree t = TREE_TYPE (op);
5860 if (!POINTER_TYPE_P (t)
5861 || (TREE_CODE (op) == STRING_CST
5862 && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5863 hphi->set_op (i, new hsa_op_immed (op));
5864 else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5865 && TREE_CODE (op) == INTEGER_CST)
5867 /* Handle assignment of NULL value to a pointer type. */
5868 hphi->set_op (i, new hsa_op_immed (op));
5870 else if (TREE_CODE (op) == ADDR_EXPR)
5872 hsa_op_reg *dest = NULL;
5873 for (unsigned a_idx = 0; a_idx < aexprs.length (); a_idx++)
5874 if (aexprs[a_idx] == op)
5876 dest = aregs[a_idx];
5877 break;
5879 gcc_assert (dest);
5880 hphi->set_op (i, dest);
5882 else
5884 HSA_SORRY_AT (gimple_location (phi_stmt),
5885 "support for HSA does not handle PHI nodes with "
5886 "constant address operands");
5887 return;
5892 hbb->append_phi (hphi);
5895 /* Constructor of class containing HSA-specific information about a basic
5896 block. CFG_BB is the CFG BB this HSA BB is associated with. IDX is the new
5897 index of this BB (so that the constructor does not attempt to use
5898 hsa_cfun during its construction). */
5900 hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5901 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5902 m_last_phi (NULL), m_index (idx)
5904 gcc_assert (!cfg_bb->aux);
5905 cfg_bb->aux = this;
5908 /* Constructor of class containing HSA-specific information about a basic
5909 block. CFG_BB is the CFG BB this HSA BB is associated with. */
5911 hsa_bb::hsa_bb (basic_block cfg_bb)
5912 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5913 m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++)
5915 gcc_assert (!cfg_bb->aux);
5916 cfg_bb->aux = this;
5919 /* Create and initialize and return a new hsa_bb structure for a given CFG
5920 basic block BB. */
5922 hsa_bb *
5923 hsa_init_new_bb (basic_block bb)
5925 void *m = obstack_alloc (&hsa_obstack, sizeof (hsa_bb));
5926 return new (m) hsa_bb (bb);
5929 /* Initialize OMP in an HSA basic block PROLOGUE. */
5931 static void
5932 init_prologue (void)
5934 if (!hsa_cfun->m_kern_p)
5935 return;
5937 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5939 /* Create a magic number that is going to be printed by libgomp. */
5940 unsigned index = hsa_get_number_decl_kernel_mappings ();
5942 /* Emit store to debug argument. */
5943 if (PARAM_VALUE (PARAM_HSA_GEN_DEBUG_STORES) > 0)
5944 set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5947 /* Initialize hsa_num_threads to a default value. */
5949 static void
5950 init_hsa_num_threads (void)
5952 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5954 /* Save the default value to private variable hsa_num_threads. */
5955 hsa_insn_basic *basic
5956 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5957 new hsa_op_immed (0, hsa_num_threads->m_type),
5958 new hsa_op_address (hsa_num_threads));
5959 prologue->append_insn (basic);
5962 /* Go over gimple representation and generate our internal HSA one. */
5964 static void
5965 gen_body_from_gimple ()
5967 basic_block bb;
5969 /* Verify CFG for complex edges we are unable to handle. */
5970 edge_iterator ei;
5971 edge e;
5973 FOR_EACH_BB_FN (bb, cfun)
5975 FOR_EACH_EDGE (e, ei, bb->succs)
5977 /* Verify all unsupported flags for edges that point
5978 to the same basic block. */
5979 if (e->flags & EDGE_EH)
5981 HSA_SORRY_AT (UNKNOWN_LOCATION,
5982 "support for HSA does not implement exception "
5983 "handling");
5984 return;
5989 FOR_EACH_BB_FN (bb, cfun)
5991 gimple_stmt_iterator gsi;
5992 hsa_bb *hbb = hsa_bb_for_bb (bb);
5993 if (hbb)
5994 continue;
5996 hbb = hsa_init_new_bb (bb);
5998 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6000 gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
6001 if (hsa_seen_error ())
6002 return;
6006 FOR_EACH_BB_FN (bb, cfun)
6008 gimple_stmt_iterator gsi;
6009 hsa_bb *hbb = hsa_bb_for_bb (bb);
6010 gcc_assert (hbb != NULL);
6012 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6013 if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
6014 gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
6017 if (dump_file && (dump_flags & TDF_DETAILS))
6019 fprintf (dump_file, "------- Generated SSA form -------\n");
6020 dump_hsa_cfun (dump_file);
6024 static void
6025 gen_function_decl_parameters (hsa_function_representation *f,
6026 tree decl)
6028 tree parm;
6029 unsigned i;
6031 for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
6032 parm;
6033 parm = TREE_CHAIN (parm), i++)
6035 /* Result type if last in the tree list. */
6036 if (TREE_CHAIN (parm) == NULL)
6037 break;
6039 tree v = TREE_VALUE (parm);
6041 hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6042 BRIG_LINKAGE_NONE);
6043 arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
6044 arg->m_name_number = i;
6046 f->m_input_args.safe_push (arg);
6049 tree result_type = TREE_TYPE (TREE_TYPE (decl));
6050 if (!VOID_TYPE_P (result_type))
6052 f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6053 BRIG_LINKAGE_NONE);
6054 f->m_output_arg->m_type
6055 = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
6056 f->m_output_arg->m_name = "res";
6060 /* Generate the vector of parameters of the HSA representation of the current
6061 function. This also includes the output parameter representing the
6062 result. */
6064 static void
6065 gen_function_def_parameters ()
6067 tree parm;
6069 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
6071 for (parm = DECL_ARGUMENTS (cfun->decl); parm;
6072 parm = DECL_CHAIN (parm))
6074 struct hsa_symbol **slot;
6076 hsa_symbol *arg
6077 = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
6078 ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
6079 BRIG_LINKAGE_FUNCTION);
6080 arg->fillup_for_decl (parm);
6082 hsa_cfun->m_input_args.safe_push (arg);
6084 if (hsa_seen_error ())
6085 return;
6087 arg->m_name = hsa_get_declaration_name (parm);
6089 /* Copy all input arguments and create corresponding private symbols
6090 for them. */
6091 hsa_symbol *private_arg;
6092 hsa_op_address *parm_addr = new hsa_op_address (arg);
6094 if (TREE_ADDRESSABLE (parm)
6095 || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
6097 private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
6098 private_arg->fillup_for_decl (parm);
6100 BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
6102 hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
6103 gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
6104 arg->total_byte_size (), align);
6106 else
6107 private_arg = arg;
6109 slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
6110 gcc_assert (!*slot);
6111 *slot = private_arg;
6113 if (is_gimple_reg (parm))
6115 tree ddef = ssa_default_def (cfun, parm);
6116 if (ddef && !has_zero_uses (ddef))
6118 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
6119 false);
6120 BrigType16_t mtype = mem_type_for_type (t);
6121 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
6122 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
6123 dest, parm_addr);
6124 gcc_assert (!parm_addr->m_reg);
6125 prologue->append_insn (mem);
6130 if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
6132 struct hsa_symbol **slot;
6134 hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6135 BRIG_LINKAGE_FUNCTION);
6136 hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
6138 if (hsa_seen_error ())
6139 return;
6141 hsa_cfun->m_output_arg->m_name = "res";
6142 slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
6143 INSERT);
6144 gcc_assert (!*slot);
6145 *slot = hsa_cfun->m_output_arg;
6149 /* Generate function representation that corresponds to
6150 a function declaration. */
6152 hsa_function_representation *
6153 hsa_generate_function_declaration (tree decl)
6155 hsa_function_representation *fun
6156 = new hsa_function_representation (decl, false, 0);
6158 fun->m_declaration_p = true;
6159 fun->m_name = get_brig_function_name (decl);
6160 gen_function_decl_parameters (fun, decl);
6162 return fun;
6166 /* Generate function representation that corresponds to
6167 an internal FN. */
6169 hsa_function_representation *
6170 hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
6172 hsa_function_representation *fun = new hsa_function_representation (fn);
6174 fun->m_name = fn->name ();
6176 for (unsigned i = 0; i < fn->get_arity (); i++)
6178 hsa_symbol *arg
6179 = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
6180 BRIG_LINKAGE_NONE);
6181 arg->m_name_number = i;
6182 fun->m_input_args.safe_push (arg);
6185 fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
6186 BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
6187 fun->m_output_arg->m_name = "res";
6189 return fun;
6192 /* Return true if switch statement S can be transformed
6193 to a SBR instruction in HSAIL. */
6195 static bool
6196 transformable_switch_to_sbr_p (gswitch *s)
6198 /* Identify if a switch statement can be transformed to
6199 SBR instruction, like:
6201 sbr_u32 $s1 [@label1, @label2, @label3];
6204 tree size = get_switch_size (s);
6205 if (!tree_fits_uhwi_p (size))
6206 return false;
6208 if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
6209 return false;
6211 return true;
6214 /* Structure hold connection between PHI nodes and immediate
6215 values hold by there nodes. */
6217 struct phi_definition
6219 phi_definition (unsigned phi_i, unsigned label_i, tree imm):
6220 phi_index (phi_i), label_index (label_i), phi_value (imm)
6223 unsigned phi_index;
6224 unsigned label_index;
6225 tree phi_value;
6228 /* Sum slice of a vector V, starting from index START and ending
6229 at the index END - 1. */
6231 template <typename T>
6232 static
6233 T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end,
6234 T zero)
6236 T s = zero;
6238 for (unsigned i = start; i < end; i++)
6239 s += v[i];
6241 return s;
6244 /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
6245 Let's assume following example:
6248 switch (index)
6249 case C1:
6250 L1: hard_work_1 ();
6251 break;
6252 case C2..C3:
6253 L2: hard_work_2 ();
6254 break;
6255 default:
6256 LD: hard_work_3 ();
6257 break;
6259 The transformation encompasses following steps:
6260 1) all immediate values used by edges coming from the switch basic block
6261 are saved
6262 2) all these edges are removed
6263 3) the switch statement (in L0) is replaced by:
6264 if (index == C1)
6265 goto L1;
6266 else
6267 goto L1';
6269 4) newly created basic block Lx' is used for generation of
6270 a next condition
6271 5) else branch of the last condition goes to LD
6272 6) fix all immediate values in PHI nodes that were propagated though
6273 edges that were removed in step 2
6275 Note: if a case is made by a range C1..C2, then process
6276 following transformation:
6278 switch_cond_op1 = C1 <= index;
6279 switch_cond_op2 = index <= C2;
6280 switch_cond_and = switch_cond_op1 & switch_cond_op2;
6281 if (switch_cond_and != 0)
6282 goto Lx;
6283 else
6284 goto Ly;
6288 static bool
6289 convert_switch_statements (void)
6291 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6292 basic_block bb;
6294 bool modified_cfg = false;
6296 FOR_EACH_BB_FN (bb, func)
6298 gimple_stmt_iterator gsi = gsi_last_bb (bb);
6299 if (gsi_end_p (gsi))
6300 continue;
6302 gimple *stmt = gsi_stmt (gsi);
6304 if (gimple_code (stmt) == GIMPLE_SWITCH)
6306 gswitch *s = as_a <gswitch *> (stmt);
6308 /* If the switch can utilize SBR insn, skip the statement. */
6309 if (transformable_switch_to_sbr_p (s))
6310 continue;
6312 modified_cfg = true;
6314 unsigned labels = gimple_switch_num_labels (s);
6315 tree index = gimple_switch_index (s);
6316 tree index_type = TREE_TYPE (index);
6317 tree default_label = gimple_switch_default_label (s);
6318 basic_block default_label_bb
6319 = label_to_block_fn (func, CASE_LABEL (default_label));
6320 basic_block cur_bb = bb;
6322 auto_vec <edge> new_edges;
6323 auto_vec <phi_definition *> phi_todo_list;
6324 auto_vec <profile_count> edge_counts;
6325 auto_vec <profile_probability> edge_probabilities;
6327 /* Investigate all labels that and PHI nodes in these edges which
6328 should be fixed after we add new collection of edges. */
6329 for (unsigned i = 0; i < labels; i++)
6331 tree label = gimple_switch_label (s, i);
6332 basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label));
6333 edge e = find_edge (bb, label_bb);
6334 edge_counts.safe_push (e->count ());
6335 edge_probabilities.safe_push (e->probability);
6336 gphi_iterator phi_gsi;
6338 /* Save PHI definitions that will be destroyed because of an edge
6339 is going to be removed. */
6340 unsigned phi_index = 0;
6341 for (phi_gsi = gsi_start_phis (e->dest);
6342 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6344 gphi *phi = phi_gsi.phi ();
6345 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6347 if (gimple_phi_arg_edge (phi, j) == e)
6349 tree imm = gimple_phi_arg_def (phi, j);
6350 phi_definition *p = new phi_definition (phi_index, i,
6351 imm);
6352 phi_todo_list.safe_push (p);
6353 break;
6356 phi_index++;
6360 /* Remove all edges for the current basic block. */
6361 for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6363 edge e = EDGE_SUCC (bb, i);
6364 remove_edge (e);
6367 /* Iterate all non-default labels. */
6368 for (unsigned i = 1; i < labels; i++)
6370 tree label = gimple_switch_label (s, i);
6371 tree low = CASE_LOW (label);
6372 tree high = CASE_HIGH (label);
6374 if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6375 low = fold_convert (index_type, low);
6377 gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6378 gimple *c = NULL;
6379 if (high)
6381 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6382 "switch_cond_op1");
6384 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6385 index);
6387 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6388 "switch_cond_op2");
6390 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6391 high = fold_convert (index_type, high);
6392 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6393 high);
6395 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6396 "switch_cond_and");
6397 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6398 tmp2);
6400 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6401 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6402 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6404 tree b = constant_boolean_node (false, boolean_type_node);
6405 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6407 else
6408 c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6410 gimple_set_location (c, gimple_location (stmt));
6412 gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6414 basic_block label_bb
6415 = label_to_block_fn (func, CASE_LABEL (label));
6416 edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6417 profile_probability prob_sum = sum_slice <profile_probability>
6418 (edge_probabilities, i, labels, profile_probability::never ())
6419 + edge_probabilities[0];
6421 if (prob_sum.initialized_p ())
6422 new_edge->probability = edge_probabilities[i] / prob_sum;
6424 new_edges.safe_push (new_edge);
6426 if (i < labels - 1)
6428 /* Prepare another basic block that will contain
6429 next condition. */
6430 basic_block next_bb = create_empty_bb (cur_bb);
6431 if (current_loops)
6433 add_bb_to_loop (next_bb, cur_bb->loop_father);
6434 loops_state_set (LOOPS_NEED_FIXUP);
6437 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6438 next_edge->probability = new_edge->probability.invert ();
6439 next_bb->count = next_edge->count ();
6440 cur_bb = next_bb;
6442 else /* Link last IF statement and default label
6443 of the switch. */
6445 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6446 e->probability = new_edge->probability.invert ();
6447 new_edges.safe_insert (0, e);
6451 /* Restore original PHI immediate value. */
6452 for (unsigned i = 0; i < phi_todo_list.length (); i++)
6454 phi_definition *phi_def = phi_todo_list[i];
6455 edge new_edge = new_edges[phi_def->label_index];
6457 gphi_iterator it = gsi_start_phis (new_edge->dest);
6458 for (unsigned i = 0; i < phi_def->phi_index; i++)
6459 gsi_next (&it);
6461 gphi *phi = it.phi ();
6462 add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6463 delete phi_def;
6466 /* Remove the original GIMPLE switch statement. */
6467 gsi_remove (&gsi, true);
6471 if (dump_file)
6472 dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6474 return modified_cfg;
6477 /* Expand builtins that can't be handled by HSA back-end. */
6479 static void
6480 expand_builtins ()
6482 function *func = DECL_STRUCT_FUNCTION (current_function_decl);
6483 basic_block bb;
6485 FOR_EACH_BB_FN (bb, func)
6487 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6488 gsi_next (&gsi))
6490 gimple *stmt = gsi_stmt (gsi);
6492 if (gimple_code (stmt) != GIMPLE_CALL)
6493 continue;
6495 gcall *call = as_a <gcall *> (stmt);
6497 if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6498 continue;
6500 tree fndecl = gimple_call_fndecl (stmt);
6501 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6502 switch (fn)
6504 case BUILT_IN_CEXPF:
6505 case BUILT_IN_CEXPIF:
6506 case BUILT_IN_CEXPI:
6508 /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6509 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z). */
6510 tree lhs = gimple_call_lhs (stmt);
6511 tree rhs = gimple_call_arg (stmt, 0);
6512 tree rhs_type = TREE_TYPE (rhs);
6513 bool float_type_p = rhs_type == float_type_node;
6514 tree real_part = make_temp_ssa_name (rhs_type, NULL,
6515 "cexp_real_part");
6516 tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6517 "cexp_imag_part");
6519 tree cos_fndecl
6520 = mathfn_built_in (rhs_type, fn == float_type_p
6521 ? BUILT_IN_COSF : BUILT_IN_COS);
6522 gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6523 gimple_call_set_lhs (cos, real_part);
6524 gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6526 tree sin_fndecl
6527 = mathfn_built_in (rhs_type, fn == float_type_p
6528 ? BUILT_IN_SINF : BUILT_IN_SIN);
6529 gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6530 gimple_call_set_lhs (sin, imag_part);
6531 gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6534 gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6535 real_part, imag_part);
6536 gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6537 gsi_remove (&gsi, true);
6539 break;
6541 default:
6542 break;
6548 /* Emit HSA module variables that are global for the entire module. */
6550 static void
6551 emit_hsa_module_variables (void)
6553 hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6554 BRIG_LINKAGE_MODULE, true);
6556 hsa_num_threads->m_name = "hsa_num_threads";
6558 hsa_brig_emit_omp_symbols ();
6561 /* Generate HSAIL representation of the current function and write into a
6562 special section of the output file. If KERNEL is set, the function will be
6563 considered an HSA kernel callable from the host, otherwise it will be
6564 compiled as an HSA function callable from other HSA code. */
6566 static void
6567 generate_hsa (bool kernel)
6569 hsa_init_data_for_cfun ();
6571 if (hsa_num_threads == NULL)
6572 emit_hsa_module_variables ();
6574 bool modified_cfg = convert_switch_statements ();
6575 /* Initialize hsa_cfun. */
6576 hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
6577 SSANAMES (cfun)->length (),
6578 modified_cfg);
6579 hsa_cfun->init_extra_bbs ();
6581 if (flag_tm)
6583 HSA_SORRY_AT (UNKNOWN_LOCATION,
6584 "support for HSA does not implement transactional memory");
6585 goto fail;
6588 verify_function_arguments (cfun->decl);
6589 if (hsa_seen_error ())
6590 goto fail;
6592 hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6594 gen_function_def_parameters ();
6595 if (hsa_seen_error ())
6596 goto fail;
6598 init_prologue ();
6600 gen_body_from_gimple ();
6601 if (hsa_seen_error ())
6602 goto fail;
6604 if (hsa_cfun->m_kernel_dispatch_count)
6605 init_hsa_num_threads ();
6607 if (hsa_cfun->m_kern_p)
6609 hsa_function_summary *s
6610 = hsa_summaries->get_create (cgraph_node::get (hsa_cfun->m_decl));
6611 hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6612 hsa_cfun->m_maximum_omp_data_size,
6613 s->m_gridified_kernel_p);
6616 if (flag_checking)
6618 for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6619 if (hsa_cfun->m_ssa_map[i])
6620 hsa_cfun->m_ssa_map[i]->verify_ssa ();
6622 basic_block bb;
6623 FOR_EACH_BB_FN (bb, cfun)
6625 hsa_bb *hbb = hsa_bb_for_bb (bb);
6627 for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6628 insn = insn->m_next)
6629 insn->verify ();
6633 hsa_regalloc ();
6634 hsa_brig_emit_function ();
6636 fail:
6637 hsa_deinit_data_for_cfun ();
6640 namespace {
6642 const pass_data pass_data_gen_hsail =
6644 GIMPLE_PASS,
6645 "hsagen", /* name */
6646 OPTGROUP_OMP, /* optinfo_flags */
6647 TV_NONE, /* tv_id */
6648 PROP_cfg | PROP_ssa, /* properties_required */
6649 0, /* properties_provided */
6650 0, /* properties_destroyed */
6651 0, /* todo_flags_start */
6652 0 /* todo_flags_finish */
6655 class pass_gen_hsail : public gimple_opt_pass
6657 public:
6658 pass_gen_hsail (gcc::context *ctxt)
6659 : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6662 /* opt_pass methods: */
6663 bool gate (function *);
6664 unsigned int execute (function *);
6666 }; // class pass_gen_hsail
6668 /* Determine whether or not to run generation of HSAIL. */
6670 bool
6671 pass_gen_hsail::gate (function *f)
6673 return hsa_gen_requested_p ()
6674 && hsa_gpu_implementation_p (f->decl);
6677 unsigned int
6678 pass_gen_hsail::execute (function *)
6680 cgraph_node *node = cgraph_node::get_create (current_function_decl);
6681 hsa_function_summary *s = hsa_summaries->get_create (node);
6683 expand_builtins ();
6684 generate_hsa (s->m_kind == HSA_KERNEL);
6685 TREE_ASM_WRITTEN (current_function_decl) = 1;
6686 return TODO_discard_function;
6689 } // anon namespace
6691 /* Create the instance of hsa gen pass. */
6693 gimple_opt_pass *
6694 make_pass_gen_hsail (gcc::context *ctxt)
6696 return new pass_gen_hsail (ctxt);