PR rtl-optimization/88018
[official-gcc.git] / gcc / hsa-gen.c
blob69e092ec4fad2b3dffcbbbff503c6495ecd2c726
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 auto_diagnostic_group d; \
73 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
74 HSA_SORRY_MSG)) \
75 inform (location, message, __VA_ARGS__); \
76 } \
77 while (false)
79 /* Same as previous, but highlight a location. */
81 #define HSA_SORRY_AT(location, message) \
82 do \
83 { \
84 hsa_fail_cfun (); \
85 auto_diagnostic_group d; \
86 if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
87 HSA_SORRY_MSG)) \
88 inform (location, message); \
89 } \
90 while (false)
92 /* Default number of threads used by kernel dispatch. */
94 #define HSA_DEFAULT_NUM_THREADS 64
96 /* Following structures are defined in the final version
97 of HSA specification. */
99 /* HSA queue packet is shadow structure, originally provided by AMD. */
101 struct hsa_queue_packet
103 uint16_t header;
104 uint16_t setup;
105 uint16_t workgroup_size_x;
106 uint16_t workgroup_size_y;
107 uint16_t workgroup_size_z;
108 uint16_t reserved0;
109 uint32_t grid_size_x;
110 uint32_t grid_size_y;
111 uint32_t grid_size_z;
112 uint32_t private_segment_size;
113 uint32_t group_segment_size;
114 uint64_t kernel_object;
115 void *kernarg_address;
116 uint64_t reserved2;
117 uint64_t completion_signal;
120 /* HSA queue is shadow structure, originally provided by AMD. */
122 struct hsa_queue
124 int type;
125 uint32_t features;
126 void *base_address;
127 uint64_t doorbell_signal;
128 uint32_t size;
129 uint32_t reserved1;
130 uint64_t id;
133 static struct obstack hsa_obstack;
135 /* List of pointers to all instructions that come from an object allocator. */
136 static vec <hsa_insn_basic *> hsa_instructions;
138 /* List of pointers to all operands that come from an object allocator. */
139 static vec <hsa_op_base *> hsa_operands;
141 hsa_symbol::hsa_symbol ()
142 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
143 m_directive_offset (0), m_type (BRIG_TYPE_NONE),
144 m_segment (BRIG_SEGMENT_NONE), m_linkage (BRIG_LINKAGE_NONE), m_dim (0),
145 m_cst_value (NULL), m_global_scope_p (false), m_seen_error (false),
146 m_allocation (BRIG_ALLOCATION_AUTOMATIC), m_emitted_to_brig (false)
151 hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
152 BrigLinkage8_t linkage, bool global_scope_p,
153 BrigAllocation allocation, BrigAlignment8_t align)
154 : m_decl (NULL_TREE), m_name (NULL), m_name_number (0),
155 m_directive_offset (0), m_type (type), m_segment (segment),
156 m_linkage (linkage), m_dim (0), m_cst_value (NULL),
157 m_global_scope_p (global_scope_p), m_seen_error (false),
158 m_allocation (allocation), m_emitted_to_brig (false), m_align (align)
162 unsigned HOST_WIDE_INT
163 hsa_symbol::total_byte_size ()
165 unsigned HOST_WIDE_INT s
166 = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type);
167 gcc_assert (s % BITS_PER_UNIT == 0);
168 s /= BITS_PER_UNIT;
170 if (m_dim)
171 s *= m_dim;
173 return s;
176 /* Forward declaration. */
178 static BrigType16_t
179 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p,
180 bool min32int);
182 void
183 hsa_symbol::fillup_for_decl (tree decl)
185 m_decl = decl;
186 m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false);
187 if (hsa_seen_error ())
189 m_seen_error = true;
190 return;
193 m_align = MAX (m_align, hsa_natural_alignment (m_type));
196 /* Constructor of class representing global HSA function/kernel information and
197 state. FNDECL is function declaration, KERNEL_P is true if the function
198 is going to become a HSA kernel. If the function has body, SSA_NAMES_COUNT
199 should be set to number of SSA names used in the function.
200 MODIFIED_CFG is set to true in case we modified control-flow graph
201 of the function. */
203 hsa_function_representation::hsa_function_representation
204 (tree fdecl, bool kernel_p, unsigned ssa_names_count, bool modified_cfg)
205 : m_name (NULL),
206 m_reg_count (0), m_input_args (vNULL),
207 m_output_arg (NULL), m_spill_symbols (vNULL), m_global_symbols (vNULL),
208 m_private_variables (vNULL), m_called_functions (vNULL),
209 m_called_internal_fns (vNULL), m_hbb_count (0),
210 m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false),
211 m_decl (fdecl), m_internal_fn (NULL), m_shadow_reg (NULL),
212 m_kernel_dispatch_count (0), m_maximum_omp_data_size (0),
213 m_seen_error (false), m_temp_symbol_count (0), m_ssa_map (),
214 m_modified_cfg (modified_cfg)
216 int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;
217 m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len);
218 m_ssa_map.safe_grow_cleared (ssa_names_count);
221 /* Constructor of class representing HSA function information that
222 is derived for an internal function. */
223 hsa_function_representation::hsa_function_representation (hsa_internal_fn *fn)
224 : m_reg_count (0), m_input_args (vNULL),
225 m_output_arg (NULL), m_local_symbols (NULL),
226 m_spill_symbols (vNULL), m_global_symbols (vNULL),
227 m_private_variables (vNULL), m_called_functions (vNULL),
228 m_called_internal_fns (vNULL), m_hbb_count (0),
229 m_in_ssa (true), m_kern_p (false), m_declaration_p (true), m_decl (NULL),
230 m_internal_fn (fn), m_shadow_reg (NULL), m_kernel_dispatch_count (0),
231 m_maximum_omp_data_size (0), m_seen_error (false), m_temp_symbol_count (0),
232 m_ssa_map () {}
234 /* Destructor of class holding function/kernel-wide information and state. */
236 hsa_function_representation::~hsa_function_representation ()
238 /* Kernel names are deallocated at the end of BRIG output when deallocating
239 hsa_decl_kernel_mapping. */
240 if (!m_kern_p || m_seen_error)
241 free (m_name);
243 for (unsigned i = 0; i < m_input_args.length (); i++)
244 delete m_input_args[i];
245 m_input_args.release ();
247 delete m_output_arg;
248 delete m_local_symbols;
250 for (unsigned i = 0; i < m_spill_symbols.length (); i++)
251 delete m_spill_symbols[i];
252 m_spill_symbols.release ();
254 hsa_symbol *sym;
255 for (unsigned i = 0; i < m_global_symbols.iterate (i, &sym); i++)
256 if (sym->m_linkage != BRIG_ALLOCATION_PROGRAM)
257 delete sym;
258 m_global_symbols.release ();
260 for (unsigned i = 0; i < m_private_variables.length (); i++)
261 delete m_private_variables[i];
262 m_private_variables.release ();
263 m_called_functions.release ();
264 m_ssa_map.release ();
266 for (unsigned i = 0; i < m_called_internal_fns.length (); i++)
267 delete m_called_internal_fns[i];
270 hsa_op_reg *
271 hsa_function_representation::get_shadow_reg ()
273 /* If we compile a function with kernel dispatch and does not set
274 an optimization level, the function won't be inlined and
275 we return NULL. */
276 if (!m_kern_p)
277 return NULL;
279 if (m_shadow_reg)
280 return m_shadow_reg;
282 /* Append the shadow argument. */
283 hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG,
284 BRIG_LINKAGE_FUNCTION);
285 m_input_args.safe_push (shadow);
286 shadow->m_name = "hsa_runtime_shadow";
288 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64);
289 hsa_op_address *addr = new hsa_op_address (shadow);
291 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, r, addr);
292 hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun))->append_insn (mem);
293 m_shadow_reg = r;
295 return r;
298 bool hsa_function_representation::has_shadow_reg_p ()
300 return m_shadow_reg != NULL;
303 void
304 hsa_function_representation::init_extra_bbs ()
306 hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
307 hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
310 void
311 hsa_function_representation::update_dominance ()
313 if (m_modified_cfg)
315 free_dominance_info (CDI_DOMINATORS);
316 calculate_dominance_info (CDI_DOMINATORS);
320 hsa_symbol *
321 hsa_function_representation::create_hsa_temporary (BrigType16_t type)
323 hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE,
324 BRIG_LINKAGE_FUNCTION);
325 s->m_name_number = m_temp_symbol_count++;
327 hsa_cfun->m_private_variables.safe_push (s);
328 return s;
331 BrigLinkage8_t
332 hsa_function_representation::get_linkage ()
334 if (m_internal_fn)
335 return BRIG_LINKAGE_PROGRAM;
337 return m_kern_p || TREE_PUBLIC (m_decl) ?
338 BRIG_LINKAGE_PROGRAM : BRIG_LINKAGE_MODULE;
341 /* Hash map of simple OMP builtins. */
342 static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
343 = NULL;
345 /* Warning messages for OMP builtins. */
347 #define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OpenMP " \
348 "lock routines"
349 #define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OpenMP " \
350 "timing routines"
351 #define HSA_WARN_MEMORY_ROUTINE "OpenMP device memory library routines have " \
352 "undefined semantics within target regions, support for HSA ignores them"
353 #define HSA_WARN_AFFINITY "Support for HSA does not implement OpenMP " \
354 "affinity feateres"
356 /* Initialize hash map with simple OMP builtins. */
358 static void
359 hsa_init_simple_builtins ()
361 if (omp_simple_builtins != NULL)
362 return;
364 omp_simple_builtins
365 = new hash_map <nofree_string_hash, omp_simple_builtin> ();
367 omp_simple_builtin omp_builtins[] =
369 omp_simple_builtin ("omp_get_initial_device", NULL, false,
370 new hsa_op_immed (GOMP_DEVICE_HOST,
371 (BrigType16_t) BRIG_TYPE_S32)),
372 omp_simple_builtin ("omp_is_initial_device", NULL, false,
373 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
374 omp_simple_builtin ("omp_get_dynamic", NULL, false,
375 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
376 omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
377 omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
378 omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
379 true),
380 omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
381 true),
382 omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
383 omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
384 omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
385 omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
386 omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
387 omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
388 omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
389 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
390 omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
391 omp_simple_builtin ("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
392 false,
393 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
394 omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
395 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
396 omp_simple_builtin ("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
397 false,
398 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
399 omp_simple_builtin ("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE,
400 false,
401 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
402 omp_simple_builtin ("omp_target_disassociate_ptr",
403 HSA_WARN_MEMORY_ROUTINE,
404 false,
405 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
406 omp_simple_builtin ("omp_set_max_active_levels",
407 "Support for HSA only allows only one active level, "
408 "call to omp_set_max_active_levels will be ignored "
409 "in the generated HSAIL",
410 false, NULL),
411 omp_simple_builtin ("omp_get_max_active_levels", NULL, false,
412 new hsa_op_immed (1, (BrigType16_t) BRIG_TYPE_S32)),
413 omp_simple_builtin ("omp_in_final", NULL, false,
414 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
415 omp_simple_builtin ("omp_get_proc_bind", HSA_WARN_AFFINITY, false,
416 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
417 omp_simple_builtin ("omp_get_num_places", HSA_WARN_AFFINITY, false,
418 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
419 omp_simple_builtin ("omp_get_place_num_procs", HSA_WARN_AFFINITY, false,
420 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
421 omp_simple_builtin ("omp_get_place_proc_ids", HSA_WARN_AFFINITY, false,
422 NULL),
423 omp_simple_builtin ("omp_get_place_num", HSA_WARN_AFFINITY, false,
424 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S32)),
425 omp_simple_builtin ("omp_get_partition_num_places", HSA_WARN_AFFINITY,
426 false,
427 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
428 omp_simple_builtin ("omp_get_partition_place_nums", HSA_WARN_AFFINITY,
429 false, NULL),
430 omp_simple_builtin ("omp_set_default_device",
431 "omp_set_default_device has undefined semantics "
432 "within target regions, support for HSA ignores it",
433 false, NULL),
434 omp_simple_builtin ("omp_get_default_device",
435 "omp_get_default_device has undefined semantics "
436 "within target regions, support for HSA ignores it",
437 false,
438 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
439 omp_simple_builtin ("omp_get_num_devices",
440 "omp_get_num_devices has undefined semantics "
441 "within target regions, support for HSA ignores it",
442 false,
443 new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S32)),
444 omp_simple_builtin ("omp_get_num_procs", NULL, true, NULL),
445 omp_simple_builtin ("omp_get_cancellation", NULL, true, NULL),
446 omp_simple_builtin ("omp_set_nested", NULL, true, NULL),
447 omp_simple_builtin ("omp_get_nested", NULL, true, NULL),
448 omp_simple_builtin ("omp_set_schedule", NULL, true, NULL),
449 omp_simple_builtin ("omp_get_schedule", NULL, true, NULL),
450 omp_simple_builtin ("omp_get_thread_limit", NULL, true, NULL),
451 omp_simple_builtin ("omp_get_team_size", NULL, true, NULL),
452 omp_simple_builtin ("omp_get_ancestor_thread_num", NULL, true, NULL),
453 omp_simple_builtin ("omp_get_max_task_priority", NULL, true, NULL)
456 unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
458 for (unsigned i = 0; i < count; i++)
459 omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
462 /* Allocate HSA structures that we need only while generating with this. */
464 static void
465 hsa_init_data_for_cfun ()
467 hsa_init_compilation_unit_data ();
468 gcc_obstack_init (&hsa_obstack);
471 /* Deinitialize HSA subsystem and free all allocated memory. */
473 static void
474 hsa_deinit_data_for_cfun (void)
476 basic_block bb;
478 FOR_ALL_BB_FN (bb, cfun)
479 if (bb->aux)
481 hsa_bb *hbb = hsa_bb_for_bb (bb);
482 hbb->~hsa_bb ();
483 bb->aux = NULL;
486 for (unsigned int i = 0; i < hsa_operands.length (); i++)
487 hsa_destroy_operand (hsa_operands[i]);
489 hsa_operands.release ();
491 for (unsigned i = 0; i < hsa_instructions.length (); i++)
492 hsa_destroy_insn (hsa_instructions[i]);
494 hsa_instructions.release ();
496 if (omp_simple_builtins != NULL)
498 delete omp_simple_builtins;
499 omp_simple_builtins = NULL;
502 obstack_free (&hsa_obstack, NULL);
503 delete hsa_cfun;
506 /* Return the type which holds addresses in the given SEGMENT. */
508 static BrigType16_t
509 hsa_get_segment_addr_type (BrigSegment8_t segment)
511 switch (segment)
513 case BRIG_SEGMENT_NONE:
514 gcc_unreachable ();
516 case BRIG_SEGMENT_FLAT:
517 case BRIG_SEGMENT_GLOBAL:
518 case BRIG_SEGMENT_READONLY:
519 case BRIG_SEGMENT_KERNARG:
520 return hsa_machine_large_p () ? BRIG_TYPE_U64 : BRIG_TYPE_U32;
522 case BRIG_SEGMENT_GROUP:
523 case BRIG_SEGMENT_PRIVATE:
524 case BRIG_SEGMENT_SPILL:
525 case BRIG_SEGMENT_ARG:
526 return BRIG_TYPE_U32;
528 gcc_unreachable ();
531 /* Return integer brig type according to provided SIZE in bytes. If SIGN
532 is set to true, return signed integer type. */
534 static BrigType16_t
535 get_integer_type_by_bytes (unsigned size, bool sign)
537 if (sign)
538 switch (size)
540 case 1:
541 return BRIG_TYPE_S8;
542 case 2:
543 return BRIG_TYPE_S16;
544 case 4:
545 return BRIG_TYPE_S32;
546 case 8:
547 return BRIG_TYPE_S64;
548 default:
549 break;
551 else
552 switch (size)
554 case 1:
555 return BRIG_TYPE_U8;
556 case 2:
557 return BRIG_TYPE_U16;
558 case 4:
559 return BRIG_TYPE_U32;
560 case 8:
561 return BRIG_TYPE_U64;
562 default:
563 break;
566 return 0;
569 /* If T points to an integral type smaller than 32 bits, change it to a 32bit
570 equivalent and return the result. Otherwise just return the result. */
572 static BrigType16_t
573 hsa_extend_inttype_to_32bit (BrigType16_t t)
575 if (t == BRIG_TYPE_U8 || t == BRIG_TYPE_U16)
576 return BRIG_TYPE_U32;
577 else if (t == BRIG_TYPE_S8 || t == BRIG_TYPE_S16)
578 return BRIG_TYPE_S32;
579 return t;
582 /* Return HSA type for tree TYPE, which has to fit into BrigType16_t. Pointers
583 are assumed to use flat addressing. If min32int is true, always expand
584 integer types to one that has at least 32 bits. */
586 static BrigType16_t
587 hsa_type_for_scalar_tree_type (const_tree type, bool min32int)
589 HOST_WIDE_INT bsize;
590 const_tree base;
591 BrigType16_t res = BRIG_TYPE_NONE;
593 gcc_checking_assert (TYPE_P (type));
594 gcc_checking_assert (!AGGREGATE_TYPE_P (type));
595 if (POINTER_TYPE_P (type))
596 return hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
598 if (TREE_CODE (type) == VECTOR_TYPE)
599 base = TREE_TYPE (type);
600 else if (TREE_CODE (type) == COMPLEX_TYPE)
602 base = TREE_TYPE (type);
603 min32int = true;
605 else
606 base = type;
608 if (!tree_fits_uhwi_p (TYPE_SIZE (base)))
610 HSA_SORRY_ATV (EXPR_LOCATION (type),
611 "support for HSA does not implement huge or "
612 "variable-sized type %qT", type);
613 return res;
616 bsize = tree_to_uhwi (TYPE_SIZE (base));
617 unsigned byte_size = bsize / BITS_PER_UNIT;
618 if (INTEGRAL_TYPE_P (base))
619 res = get_integer_type_by_bytes (byte_size, !TYPE_UNSIGNED (base));
620 else if (SCALAR_FLOAT_TYPE_P (base))
622 switch (bsize)
624 case 16:
625 res = BRIG_TYPE_F16;
626 break;
627 case 32:
628 res = BRIG_TYPE_F32;
629 break;
630 case 64:
631 res = BRIG_TYPE_F64;
632 break;
633 default:
634 break;
638 if (res == BRIG_TYPE_NONE)
640 HSA_SORRY_ATV (EXPR_LOCATION (type),
641 "support for HSA does not implement type %qT", type);
642 return res;
645 if (TREE_CODE (type) == VECTOR_TYPE)
647 HOST_WIDE_INT tsize = tree_to_uhwi (TYPE_SIZE (type));
649 if (bsize == tsize)
651 HSA_SORRY_ATV (EXPR_LOCATION (type),
652 "support for HSA does not implement a vector type "
653 "where a type and unit size are equal: %qT", type);
654 return res;
657 switch (tsize)
659 case 32:
660 res |= BRIG_TYPE_PACK_32;
661 break;
662 case 64:
663 res |= BRIG_TYPE_PACK_64;
664 break;
665 case 128:
666 res |= BRIG_TYPE_PACK_128;
667 break;
668 default:
669 HSA_SORRY_ATV (EXPR_LOCATION (type),
670 "support for HSA does not implement type %qT", type);
674 if (min32int)
675 /* Registers/immediate operands can only be 32bit or more except for
676 f16. */
677 res = hsa_extend_inttype_to_32bit (res);
679 if (TREE_CODE (type) == COMPLEX_TYPE)
681 unsigned bsize = 2 * hsa_type_bit_size (res);
682 res = hsa_bittype_for_bitsize (bsize);
685 return res;
688 /* Returns the BRIG type we need to load/store entities of TYPE. */
690 static BrigType16_t
691 mem_type_for_type (BrigType16_t type)
693 /* HSA has non-intuitive constraints on load/store types. If it's
694 a bit-type it _must_ be B128, if it's not a bit-type it must be
695 64bit max. So for loading entities of 128 bits (e.g. vectors)
696 we have to use B128, while for loading the rest we have to use the
697 input type (??? or maybe also flattened to a equally sized non-vector
698 unsigned type?). */
699 if ((type & BRIG_TYPE_PACK_MASK) == BRIG_TYPE_PACK_128)
700 return BRIG_TYPE_B128;
701 else if (hsa_btype_p (type) || hsa_type_packed_p (type))
703 unsigned bitsize = hsa_type_bit_size (type);
704 if (bitsize < 128)
705 return hsa_uint_for_bitsize (bitsize);
706 else
707 return hsa_bittype_for_bitsize (bitsize);
709 return type;
712 /* Return HSA type for tree TYPE. If it cannot fit into BrigType16_t, some
713 kind of array will be generated, setting DIM appropriately. Otherwise, it
714 will be set to zero. */
716 static BrigType16_t
717 hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p = NULL,
718 bool min32int = false)
720 gcc_checking_assert (TYPE_P (type));
721 if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
723 HSA_SORRY_ATV (EXPR_LOCATION (type), "support for HSA does not "
724 "implement huge or variable-sized type %qT", type);
725 return BRIG_TYPE_NONE;
728 if (RECORD_OR_UNION_TYPE_P (type))
730 if (dim_p)
731 *dim_p = tree_to_uhwi (TYPE_SIZE_UNIT (type));
732 return BRIG_TYPE_U8 | BRIG_TYPE_ARRAY;
735 if (TREE_CODE (type) == ARRAY_TYPE)
737 /* We try to be nice and use the real base-type when this is an array of
738 scalars and only resort to an array of bytes if the type is more
739 complex. */
741 unsigned HOST_WIDE_INT dim = 1;
743 while (TREE_CODE (type) == ARRAY_TYPE)
745 tree domain = TYPE_DOMAIN (type);
746 if (!TYPE_MIN_VALUE (domain)
747 || !TYPE_MAX_VALUE (domain)
748 || !tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
749 || !tree_fits_shwi_p (TYPE_MAX_VALUE (domain)))
751 HSA_SORRY_ATV (EXPR_LOCATION (type),
752 "support for HSA does not implement array "
753 "%qT with unknown bounds", type);
754 return BRIG_TYPE_NONE;
756 HOST_WIDE_INT min = tree_to_shwi (TYPE_MIN_VALUE (domain));
757 HOST_WIDE_INT max = tree_to_shwi (TYPE_MAX_VALUE (domain));
758 dim = dim * (unsigned HOST_WIDE_INT) (max - min + 1);
759 type = TREE_TYPE (type);
762 BrigType16_t res;
763 if (RECORD_OR_UNION_TYPE_P (type))
765 dim = dim * tree_to_uhwi (TYPE_SIZE_UNIT (type));
766 res = BRIG_TYPE_U8;
768 else
769 res = hsa_type_for_scalar_tree_type (type, false);
771 if (dim_p)
772 *dim_p = dim;
773 return res | BRIG_TYPE_ARRAY;
776 /* Scalar case: */
777 if (dim_p)
778 *dim_p = 0;
780 return hsa_type_for_scalar_tree_type (type, min32int);
783 /* Returns true if converting from STYPE into DTYPE needs the _CVT
784 opcode. If false a normal _MOV is enough. */
786 static bool
787 hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype)
789 if (hsa_btype_p (dtype))
790 return false;
792 /* float <-> int conversions are real converts. */
793 if (hsa_type_float_p (dtype) != hsa_type_float_p (stype))
794 return true;
795 /* When both types have different size, then we need CVT as well. */
796 if (hsa_type_bit_size (dtype) != hsa_type_bit_size (stype))
797 return true;
798 return false;
801 /* Return declaration name if it exists or create one from UID if it does not.
802 If DECL is a local variable, make UID part of its name. */
804 const char *
805 hsa_get_declaration_name (tree decl)
807 if (!DECL_NAME (decl))
809 char buf[64];
810 snprintf (buf, 64, "__hsa_anon_%u", DECL_UID (decl));
811 size_t len = strlen (buf);
812 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
813 memcpy (copy, buf, len + 1);
814 return copy;
817 tree name_tree;
818 if (TREE_CODE (decl) == FUNCTION_DECL
819 || (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)))
820 name_tree = DECL_ASSEMBLER_NAME (decl);
821 else
822 name_tree = DECL_NAME (decl);
824 const char *name = IDENTIFIER_POINTER (name_tree);
825 /* User-defined assembly names have prepended asterisk symbol. */
826 if (name[0] == '*')
827 name++;
829 if ((TREE_CODE (decl) == VAR_DECL)
830 && decl_function_context (decl))
832 size_t len = strlen (name);
833 char *buf = (char *) alloca (len + 32);
834 snprintf (buf, len + 32, "%s_%u", name, DECL_UID (decl));
835 len = strlen (buf);
836 char *copy = (char *) obstack_alloc (&hsa_obstack, len + 1);
837 memcpy (copy, buf, len + 1);
838 return copy;
840 else
841 return name;
844 /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL
845 or lookup the hsa_structure corresponding to a PARM_DECL. */
847 static hsa_symbol *
848 get_symbol_for_decl (tree decl)
850 hsa_symbol **slot;
851 hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE);
853 gcc_assert (TREE_CODE (decl) == PARM_DECL
854 || TREE_CODE (decl) == RESULT_DECL
855 || TREE_CODE (decl) == VAR_DECL
856 || TREE_CODE (decl) == CONST_DECL);
858 dummy.m_decl = decl;
860 bool is_in_global_vars = ((TREE_CODE (decl) == VAR_DECL)
861 && !decl_function_context (decl));
863 if (is_in_global_vars)
864 slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT);
865 else
866 slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT);
868 gcc_checking_assert (slot);
869 if (*slot)
871 hsa_symbol *sym = (*slot);
873 /* If the symbol is problematic, mark current function also as
874 problematic. */
875 if (sym->m_seen_error)
876 hsa_fail_cfun ();
878 /* PR hsa/70234: If a global variable was marked to be emitted,
879 but HSAIL generation of a function using the variable fails,
880 we should retry to emit the variable in context of a different
881 function.
883 Iterate elements whether a symbol is already in m_global_symbols
884 of not. */
885 if (is_in_global_vars && !sym->m_emitted_to_brig)
887 for (unsigned i = 0; i < hsa_cfun->m_global_symbols.length (); i++)
888 if (hsa_cfun->m_global_symbols[i] == sym)
889 return *slot;
890 hsa_cfun->m_global_symbols.safe_push (sym);
893 return *slot;
895 else
897 hsa_symbol *sym;
898 /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols. */
899 gcc_assert (TREE_CODE (decl) == VAR_DECL
900 || TREE_CODE (decl) == CONST_DECL);
901 BrigAlignment8_t align = hsa_object_alignment (decl);
903 if (is_in_global_vars)
905 gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
906 sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
907 BRIG_LINKAGE_PROGRAM, true,
908 BRIG_ALLOCATION_PROGRAM, align);
909 hsa_cfun->m_global_symbols.safe_push (sym);
910 sym->fillup_for_decl (decl);
911 if (sym->m_align > align)
913 sym->m_seen_error = true;
914 HSA_SORRY_ATV (EXPR_LOCATION (decl),
915 "HSA specification requires that %E is at least "
916 "naturally aligned", decl);
919 else
921 /* As generation of efficient memory copy instructions relies
922 on alignment greater or equal to 8 bytes,
923 we need to increase alignment of all aggregate types.. */
924 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
925 align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
927 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
928 BrigSegment8_t segment;
929 if (TREE_CODE (decl) == CONST_DECL)
931 segment = BRIG_SEGMENT_READONLY;
932 allocation = BRIG_ALLOCATION_AGENT;
934 else if (lookup_attribute ("hsa_group_segment",
935 DECL_ATTRIBUTES (decl)))
936 segment = BRIG_SEGMENT_GROUP;
937 else if (TREE_STATIC (decl))
939 segment = BRIG_SEGMENT_GLOBAL;
940 allocation = BRIG_ALLOCATION_PROGRAM;
942 else if (lookup_attribute ("hsa_global_segment",
943 DECL_ATTRIBUTES (decl)))
944 segment = BRIG_SEGMENT_GLOBAL;
945 else
946 segment = BRIG_SEGMENT_PRIVATE;
948 sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
949 false, allocation, align);
950 sym->fillup_for_decl (decl);
951 hsa_cfun->m_private_variables.safe_push (sym);
954 sym->m_name = hsa_get_declaration_name (decl);
955 *slot = sym;
956 return sym;
960 /* For a given HSA function declaration, return a host
961 function declaration. */
963 tree
964 hsa_get_host_function (tree decl)
966 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
967 gcc_assert (s->m_gpu_implementation_p);
969 return s->m_bound_function ? s->m_bound_function->decl : NULL;
972 /* Return true if function DECL has a host equivalent function. */
974 static char *
975 get_brig_function_name (tree decl)
977 tree d = decl;
979 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
980 if (s != NULL
981 && s->m_gpu_implementation_p
982 && s->m_bound_function)
983 d = s->m_bound_function->decl;
985 /* IPA split can create a function that has no host equivalent. */
986 if (d == NULL)
987 d = decl;
989 char *name = xstrdup (hsa_get_declaration_name (d));
990 hsa_sanitize_name (name);
992 return name;
995 /* Create a spill symbol of type TYPE. */
997 hsa_symbol *
998 hsa_get_spill_symbol (BrigType16_t type)
1000 hsa_symbol *sym = new hsa_symbol (type, BRIG_SEGMENT_SPILL,
1001 BRIG_LINKAGE_FUNCTION);
1002 hsa_cfun->m_spill_symbols.safe_push (sym);
1003 return sym;
1006 /* Create a symbol for a read-only string constant. */
1007 hsa_symbol *
1008 hsa_get_string_cst_symbol (tree string_cst)
1010 gcc_checking_assert (TREE_CODE (string_cst) == STRING_CST);
1012 hsa_symbol **slot = hsa_cfun->m_string_constants_map.get (string_cst);
1013 if (slot)
1014 return *slot;
1016 hsa_op_immed *cst = new hsa_op_immed (string_cst);
1017 hsa_symbol *sym = new hsa_symbol (cst->m_type, BRIG_SEGMENT_GLOBAL,
1018 BRIG_LINKAGE_MODULE, true,
1019 BRIG_ALLOCATION_AGENT);
1020 sym->m_cst_value = cst;
1021 sym->m_dim = TREE_STRING_LENGTH (string_cst);
1022 sym->m_name_number = hsa_cfun->m_global_symbols.length ();
1024 hsa_cfun->m_global_symbols.safe_push (sym);
1025 hsa_cfun->m_string_constants_map.put (string_cst, sym);
1026 return sym;
1029 /* Make the type of a MOV instruction larger if mandated by HSAIL rules. */
1031 static void
1032 hsa_fixup_mov_insn_type (hsa_insn_basic *insn)
1034 insn->m_type = hsa_extend_inttype_to_32bit (insn->m_type);
1035 if (insn->m_type == BRIG_TYPE_B8 || insn->m_type == BRIG_TYPE_B16)
1036 insn->m_type = BRIG_TYPE_B32;
1039 /* Constructor of the ancestor of all operands. K is BRIG kind that identified
1040 what the operator is. */
1042 hsa_op_base::hsa_op_base (BrigKind16_t k)
1043 : m_next (NULL), m_brig_op_offset (0), m_kind (k)
1045 hsa_operands.safe_push (this);
1048 /* Constructor of ancestor of all operands which have a type. K is BRIG kind
1049 that identified what the operator is. T is the type of the operator. */
1051 hsa_op_with_type::hsa_op_with_type (BrigKind16_t k, BrigType16_t t)
1052 : hsa_op_base (k), m_type (t)
1056 hsa_op_with_type *
1057 hsa_op_with_type::get_in_type (BrigType16_t dtype, hsa_bb *hbb)
1059 if (m_type == dtype)
1060 return this;
1062 hsa_op_reg *dest;
1064 if (hsa_needs_cvt (dtype, m_type))
1066 dest = new hsa_op_reg (dtype);
1067 hbb->append_insn (new hsa_insn_cvt (dest, this));
1069 else if (is_a <hsa_op_reg *> (this))
1071 /* In the end, HSA registers do not really have types, only sizes, so if
1072 the sizes match, we can use the register directly. */
1073 gcc_checking_assert (hsa_type_bit_size (dtype)
1074 == hsa_type_bit_size (m_type));
1075 return this;
1077 else
1079 dest = new hsa_op_reg (m_type);
1081 hsa_insn_basic *mov = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
1082 dest->m_type, dest, this);
1083 hsa_fixup_mov_insn_type (mov);
1084 hbb->append_insn (mov);
1085 /* We cannot simply for instance: 'mov_u32 $_3, 48 (s32)' because
1086 type of the operand must be same as type of the instruction. */
1087 dest->m_type = dtype;
1090 return dest;
1093 /* If this operand has integer type smaller than 32 bits, extend it to 32 bits,
1094 adding instructions to HBB if needed. */
1096 hsa_op_with_type *
1097 hsa_op_with_type::extend_int_to_32bit (hsa_bb *hbb)
1099 if (m_type == BRIG_TYPE_U8 || m_type == BRIG_TYPE_U16)
1100 return get_in_type (BRIG_TYPE_U32, hbb);
1101 else if (m_type == BRIG_TYPE_S8 || m_type == BRIG_TYPE_S16)
1102 return get_in_type (BRIG_TYPE_S32, hbb);
1103 else
1104 return this;
1107 /* Constructor of class representing HSA immediate values. TREE_VAL is the
1108 tree representation of the immediate value. If min32int is true,
1109 always expand integer types to one that has at least 32 bits. */
1111 hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
1112 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES,
1113 hsa_type_for_tree_type (TREE_TYPE (tree_val), NULL,
1114 min32int))
1116 if (hsa_seen_error ())
1117 return;
1119 gcc_checking_assert ((is_gimple_min_invariant (tree_val)
1120 && (!POINTER_TYPE_P (TREE_TYPE (tree_val))
1121 || TREE_CODE (tree_val) == INTEGER_CST))
1122 || TREE_CODE (tree_val) == CONSTRUCTOR);
1123 m_tree_value = tree_val;
1125 /* Verify that all elements of a constructor are constants. */
1126 if (TREE_CODE (m_tree_value) == CONSTRUCTOR)
1127 for (unsigned i = 0; i < CONSTRUCTOR_NELTS (m_tree_value); i++)
1129 tree v = CONSTRUCTOR_ELT (m_tree_value, i)->value;
1130 if (!CONSTANT_CLASS_P (v))
1132 HSA_SORRY_AT (EXPR_LOCATION (tree_val),
1133 "HSA ctor should have only constants");
1134 return;
1139 /* Constructor of class representing HSA immediate values. INTEGER_VALUE is the
1140 integer representation of the immediate value. TYPE is BRIG type. */
1142 hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
1143 : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
1144 m_tree_value (NULL)
1146 gcc_assert (hsa_type_integer_p (type));
1147 m_int_value = integer_value;
1150 hsa_op_immed::hsa_op_immed ()
1151 : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE)
1155 /* New operator to allocate immediate operands from obstack. */
1157 void *
1158 hsa_op_immed::operator new (size_t size)
1160 return obstack_alloc (&hsa_obstack, size);
1163 /* Destructor. */
1165 hsa_op_immed::~hsa_op_immed ()
1169 /* Change type of the immediate value to T. */
1171 void
1172 hsa_op_immed::set_type (BrigType16_t t)
1174 m_type = t;
1177 /* Constructor of class representing HSA registers and pseudo-registers. T is
1178 the BRIG type of the new register. */
1180 hsa_op_reg::hsa_op_reg (BrigType16_t t)
1181 : hsa_op_with_type (BRIG_KIND_OPERAND_REGISTER, t), m_gimple_ssa (NULL_TREE),
1182 m_def_insn (NULL), m_spill_sym (NULL), m_order (hsa_cfun->m_reg_count++),
1183 m_lr_begin (0), m_lr_end (0), m_reg_class (0), m_hard_num (0)
1187 /* New operator to allocate a register from obstack. */
1189 void *
1190 hsa_op_reg::operator new (size_t size)
1192 return obstack_alloc (&hsa_obstack, size);
1195 /* Verify register operand. */
1197 void
1198 hsa_op_reg::verify_ssa ()
1200 /* Verify that each HSA register has a definition assigned.
1201 Exceptions are VAR_DECL and PARM_DECL that are a default
1202 definition. */
1203 gcc_checking_assert (m_def_insn
1204 || (m_gimple_ssa != NULL
1205 && (!SSA_NAME_VAR (m_gimple_ssa)
1206 || (TREE_CODE (SSA_NAME_VAR (m_gimple_ssa))
1207 != PARM_DECL))
1208 && SSA_NAME_IS_DEFAULT_DEF (m_gimple_ssa)));
1210 /* Verify that every use of the register is really present
1211 in an instruction. */
1212 for (unsigned i = 0; i < m_uses.length (); i++)
1214 hsa_insn_basic *use = m_uses[i];
1216 bool is_visited = false;
1217 for (unsigned j = 0; j < use->operand_count (); j++)
1219 hsa_op_base *u = use->get_op (j);
1220 hsa_op_address *addr; addr = dyn_cast <hsa_op_address *> (u);
1221 if (addr && addr->m_reg)
1222 u = addr->m_reg;
1224 if (u == this)
1226 bool r = !addr && use->op_output_p (j);
1228 if (r)
1230 error ("HSA SSA name defined by instruction that is supposed "
1231 "to be using it");
1232 debug_hsa_operand (this);
1233 debug_hsa_insn (use);
1234 internal_error ("HSA SSA verification failed");
1237 is_visited = true;
1241 if (!is_visited)
1243 error ("HSA SSA name not among operands of instruction that is "
1244 "supposed to use it");
1245 debug_hsa_operand (this);
1246 debug_hsa_insn (use);
1247 internal_error ("HSA SSA verification failed");
1252 hsa_op_address::hsa_op_address (hsa_symbol *sym, hsa_op_reg *r,
1253 HOST_WIDE_INT offset)
1254 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (r),
1255 m_imm_offset (offset)
1259 hsa_op_address::hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset)
1260 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (sym), m_reg (NULL),
1261 m_imm_offset (offset)
1265 hsa_op_address::hsa_op_address (hsa_op_reg *r, HOST_WIDE_INT offset)
1266 : hsa_op_base (BRIG_KIND_OPERAND_ADDRESS), m_symbol (NULL), m_reg (r),
1267 m_imm_offset (offset)
1271 /* New operator to allocate address operands from obstack. */
1273 void *
1274 hsa_op_address::operator new (size_t size)
1276 return obstack_alloc (&hsa_obstack, size);
1279 /* Constructor of an operand referring to HSAIL code. */
1281 hsa_op_code_ref::hsa_op_code_ref () : hsa_op_base (BRIG_KIND_OPERAND_CODE_REF),
1282 m_directive_offset (0)
1286 /* Constructor of an operand representing a code list. Set it up so that it
1287 can contain ELEMENTS number of elements. */
1289 hsa_op_code_list::hsa_op_code_list (unsigned elements)
1290 : hsa_op_base (BRIG_KIND_OPERAND_CODE_LIST)
1292 m_offsets.create (1);
1293 m_offsets.safe_grow_cleared (elements);
1296 /* New operator to allocate code list operands from obstack. */
1298 void *
1299 hsa_op_code_list::operator new (size_t size)
1301 return obstack_alloc (&hsa_obstack, size);
1304 /* Constructor of an operand representing an operand list.
1305 Set it up so that it can contain ELEMENTS number of elements. */
1307 hsa_op_operand_list::hsa_op_operand_list (unsigned elements)
1308 : hsa_op_base (BRIG_KIND_OPERAND_OPERAND_LIST)
1310 m_offsets.create (elements);
1311 m_offsets.safe_grow (elements);
1314 /* New operator to allocate operand list operands from obstack. */
1316 void *
1317 hsa_op_operand_list::operator new (size_t size)
1319 return obstack_alloc (&hsa_obstack, size);
1322 hsa_op_operand_list::~hsa_op_operand_list ()
1324 m_offsets.release ();
1328 hsa_op_reg *
1329 hsa_function_representation::reg_for_gimple_ssa (tree ssa)
1331 hsa_op_reg *hreg;
1333 gcc_checking_assert (TREE_CODE (ssa) == SSA_NAME);
1334 if (m_ssa_map[SSA_NAME_VERSION (ssa)])
1335 return m_ssa_map[SSA_NAME_VERSION (ssa)];
1337 hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa),
1338 false));
1339 hreg->m_gimple_ssa = ssa;
1340 m_ssa_map[SSA_NAME_VERSION (ssa)] = hreg;
1342 return hreg;
1345 void
1346 hsa_op_reg::set_definition (hsa_insn_basic *insn)
1348 if (hsa_cfun->m_in_ssa)
1350 gcc_checking_assert (!m_def_insn);
1351 m_def_insn = insn;
1353 else
1354 m_def_insn = NULL;
1357 /* Constructor of the class which is the bases of all instructions and directly
1358 represents the most basic ones. NOPS is the number of operands that the
1359 operand vector will contain (and which will be cleared). OP is the opcode
1360 of the instruction. This constructor does not set type. */
1362 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc)
1363 : m_prev (NULL),
1364 m_next (NULL), m_bb (NULL), m_opcode (opc), m_number (0),
1365 m_type (BRIG_TYPE_NONE), m_brig_offset (0)
1367 if (nops > 0)
1368 m_operands.safe_grow_cleared (nops);
1370 hsa_instructions.safe_push (this);
1373 /* Make OP the operand number INDEX of operands of this instruction. If OP is a
1374 register or an address containing a register, then either set the definition
1375 of the register to this instruction if it an output operand or add this
1376 instruction to the uses if it is an input one. */
1378 void
1379 hsa_insn_basic::set_op (int index, hsa_op_base *op)
1381 /* Each address operand is always use. */
1382 hsa_op_address *addr = dyn_cast <hsa_op_address *> (op);
1383 if (addr && addr->m_reg)
1384 addr->m_reg->m_uses.safe_push (this);
1385 else
1387 hsa_op_reg *reg = dyn_cast <hsa_op_reg *> (op);
1388 if (reg)
1390 if (op_output_p (index))
1391 reg->set_definition (this);
1392 else
1393 reg->m_uses.safe_push (this);
1397 m_operands[index] = op;
1400 /* Get INDEX-th operand of the instruction. */
1402 hsa_op_base *
1403 hsa_insn_basic::get_op (int index)
1405 return m_operands[index];
1408 /* Get address of INDEX-th operand of the instruction. */
1410 hsa_op_base **
1411 hsa_insn_basic::get_op_addr (int index)
1413 return &m_operands[index];
1416 /* Get number of operands of the instruction. */
1417 unsigned int
1418 hsa_insn_basic::operand_count ()
1420 return m_operands.length ();
1423 /* Constructor of the class which is the bases of all instructions and directly
1424 represents the most basic ones. NOPS is the number of operands that the
1425 operand vector will contain (and which will be cleared). OPC is the opcode
1426 of the instruction, T is the type of the instruction. */
1428 hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
1429 hsa_op_base *arg0, hsa_op_base *arg1,
1430 hsa_op_base *arg2, hsa_op_base *arg3)
1431 : m_prev (NULL), m_next (NULL), m_bb (NULL), m_opcode (opc),m_number (0),
1432 m_type (t), m_brig_offset (0)
1434 if (nops > 0)
1435 m_operands.safe_grow_cleared (nops);
1437 if (arg0 != NULL)
1439 gcc_checking_assert (nops >= 1);
1440 set_op (0, arg0);
1443 if (arg1 != NULL)
1445 gcc_checking_assert (nops >= 2);
1446 set_op (1, arg1);
1449 if (arg2 != NULL)
1451 gcc_checking_assert (nops >= 3);
1452 set_op (2, arg2);
1455 if (arg3 != NULL)
1457 gcc_checking_assert (nops >= 4);
1458 set_op (3, arg3);
1461 hsa_instructions.safe_push (this);
1464 /* New operator to allocate basic instruction from obstack. */
1466 void *
1467 hsa_insn_basic::operator new (size_t size)
1469 return obstack_alloc (&hsa_obstack, size);
1472 /* Verify the instruction. */
1474 void
1475 hsa_insn_basic::verify ()
1477 hsa_op_address *addr;
1478 hsa_op_reg *reg;
1480 /* Iterate all register operands and verify that the instruction
1481 is set in uses of the register. */
1482 for (unsigned i = 0; i < operand_count (); i++)
1484 hsa_op_base *use = get_op (i);
1486 if ((addr = dyn_cast <hsa_op_address *> (use)) && addr->m_reg)
1488 gcc_assert (addr->m_reg->m_def_insn != this);
1489 use = addr->m_reg;
1492 if ((reg = dyn_cast <hsa_op_reg *> (use)) && !op_output_p (i))
1494 unsigned j;
1495 for (j = 0; j < reg->m_uses.length (); j++)
1497 if (reg->m_uses[j] == this)
1498 break;
1501 if (j == reg->m_uses.length ())
1503 error ("HSA instruction uses a register but is not among "
1504 "recorded register uses");
1505 debug_hsa_operand (reg);
1506 debug_hsa_insn (this);
1507 internal_error ("HSA instruction verification failed");
1513 /* Constructor of an instruction representing a PHI node. NOPS is the number
1514 of operands (equal to the number of predecessors). */
1516 hsa_insn_phi::hsa_insn_phi (unsigned nops, hsa_op_reg *dst)
1517 : hsa_insn_basic (nops, HSA_OPCODE_PHI), m_dest (dst)
1519 dst->set_definition (this);
1522 /* Constructor of class representing instructions for control flow and
1523 sychronization, */
1525 hsa_insn_br::hsa_insn_br (unsigned nops, int opc, BrigType16_t t,
1526 BrigWidth8_t width, hsa_op_base *arg0,
1527 hsa_op_base *arg1, hsa_op_base *arg2,
1528 hsa_op_base *arg3)
1529 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1530 m_width (width)
1534 /* Constructor of class representing instruction for conditional jump, CTRL is
1535 the control register determining whether the jump will be carried out, the
1536 new instruction is automatically added to its uses list. */
1538 hsa_insn_cbr::hsa_insn_cbr (hsa_op_reg *ctrl)
1539 : hsa_insn_br (1, BRIG_OPCODE_CBR, BRIG_TYPE_B1, BRIG_WIDTH_1, ctrl)
1543 /* Constructor of class representing instruction for switch jump, CTRL is
1544 the index register. */
1546 hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
1547 : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
1548 m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
1549 m_label_code_list (new hsa_op_code_list (jump_count))
1553 /* Replace all occurrences of OLD_BB with NEW_BB in the statements
1554 jump table. */
1556 void
1557 hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb)
1559 for (unsigned i = 0; i < m_jump_table.length (); i++)
1560 if (m_jump_table[i] == old_bb)
1561 m_jump_table[i] = new_bb;
1564 hsa_insn_sbr::~hsa_insn_sbr ()
1566 m_jump_table.release ();
1569 /* Constructor of comparison instruction. CMP is the comparison operation and T
1570 is the result type. */
1572 hsa_insn_cmp::hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
1573 hsa_op_base *arg0, hsa_op_base *arg1,
1574 hsa_op_base *arg2)
1575 : hsa_insn_basic (3 , BRIG_OPCODE_CMP, t, arg0, arg1, arg2), m_compare (cmp)
1579 /* Constructor of classes representing memory accesses. OPC is the opcode (must
1580 be BRIG_OPCODE_ST or BRIG_OPCODE_LD) and T is the type. The instruction
1581 operands are provided as ARG0 and ARG1. */
1583 hsa_insn_mem::hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0,
1584 hsa_op_base *arg1)
1585 : hsa_insn_basic (2, opc, t, arg0, arg1),
1586 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1588 gcc_checking_assert (opc == BRIG_OPCODE_LD || opc == BRIG_OPCODE_ST);
1591 /* Constructor for descendants allowing different opcodes and number of
1592 operands, it passes its arguments directly to hsa_insn_basic
1593 constructor. The instruction operands are provided as ARG[0-3]. */
1596 hsa_insn_mem::hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
1597 hsa_op_base *arg0, hsa_op_base *arg1,
1598 hsa_op_base *arg2, hsa_op_base *arg3)
1599 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1600 m_align (hsa_natural_alignment (t)), m_equiv_class (0)
1604 /* Constructor of class representing atomic instructions. OPC is the principal
1605 opcode, AOP is the specific atomic operation opcode. T is the type of the
1606 instruction. The instruction operands are provided as ARG[0-3]. */
1608 hsa_insn_atomic::hsa_insn_atomic (int nops, int opc,
1609 enum BrigAtomicOperation aop,
1610 BrigType16_t t, BrigMemoryOrder memorder,
1611 hsa_op_base *arg0,
1612 hsa_op_base *arg1, hsa_op_base *arg2,
1613 hsa_op_base *arg3)
1614 : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop),
1615 m_memoryorder (memorder),
1616 m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM)
1618 gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET ||
1619 opc == BRIG_OPCODE_ATOMIC ||
1620 opc == BRIG_OPCODE_SIGNAL ||
1621 opc == BRIG_OPCODE_SIGNALNORET);
1624 /* Constructor of class representing signal instructions. OPC is the prinicpal
1625 opcode, SOP is the specific signal operation opcode. T is the type of the
1626 instruction. The instruction operands are provided as ARG[0-3]. */
1628 hsa_insn_signal::hsa_insn_signal (int nops, int opc,
1629 enum BrigAtomicOperation sop,
1630 BrigType16_t t, BrigMemoryOrder memorder,
1631 hsa_op_base *arg0, hsa_op_base *arg1,
1632 hsa_op_base *arg2, hsa_op_base *arg3)
1633 : hsa_insn_basic (nops, opc, t, arg0, arg1, arg2, arg3),
1634 m_memory_order (memorder), m_signalop (sop)
1638 /* Constructor of class representing segment conversion instructions. OPC is
1639 the opcode which must be either BRIG_OPCODE_STOF or BRIG_OPCODE_FTOS. DEST
1640 and SRCT are destination and source types respectively, SEG is the segment
1641 we are converting to or from. The instruction operands are
1642 provided as ARG0 and ARG1. */
1644 hsa_insn_seg::hsa_insn_seg (int opc, BrigType16_t dest, BrigType16_t srct,
1645 BrigSegment8_t seg, hsa_op_base *arg0,
1646 hsa_op_base *arg1)
1647 : hsa_insn_basic (2, opc, dest, arg0, arg1), m_src_type (srct),
1648 m_segment (seg)
1650 gcc_checking_assert (opc == BRIG_OPCODE_STOF || opc == BRIG_OPCODE_FTOS);
1653 /* Constructor of class representing a call instruction. CALLEE is the tree
1654 representation of the function being called. */
1656 hsa_insn_call::hsa_insn_call (tree callee)
1657 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee),
1658 m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL)
1662 hsa_insn_call::hsa_insn_call (hsa_internal_fn *fn)
1663 : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (NULL),
1664 m_called_internal_fn (fn), m_output_arg (NULL), m_args_code_list (NULL),
1665 m_result_code_list (NULL)
1669 hsa_insn_call::~hsa_insn_call ()
1671 for (unsigned i = 0; i < m_input_args.length (); i++)
1672 delete m_input_args[i];
1674 delete m_output_arg;
1676 m_input_args.release ();
1677 m_input_arg_insns.release ();
1680 /* Constructor of class representing the argument block required to invoke
1681 a call in HSAIL. */
1682 hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind,
1683 hsa_insn_call * call)
1684 : hsa_insn_basic (0, HSA_OPCODE_ARG_BLOCK), m_kind (brig_kind),
1685 m_call_insn (call)
1689 hsa_insn_comment::hsa_insn_comment (const char *s)
1690 : hsa_insn_basic (0, BRIG_KIND_DIRECTIVE_COMMENT)
1692 unsigned l = strlen (s);
1694 /* Append '// ' to the string. */
1695 char *buf = XNEWVEC (char, l + 4);
1696 sprintf (buf, "// %s", s);
1697 m_comment = buf;
1700 hsa_insn_comment::~hsa_insn_comment ()
1702 gcc_checking_assert (m_comment);
1703 free (m_comment);
1704 m_comment = NULL;
1707 /* Constructor of class representing the queue instruction in HSAIL. */
1709 hsa_insn_queue::hsa_insn_queue (int nops, int opcode, BrigSegment segment,
1710 BrigMemoryOrder memory_order,
1711 hsa_op_base *arg0, hsa_op_base *arg1,
1712 hsa_op_base *arg2, hsa_op_base *arg3)
1713 : hsa_insn_basic (nops, opcode, BRIG_TYPE_U64, arg0, arg1, arg2, arg3),
1714 m_segment (segment), m_memory_order (memory_order)
1718 /* Constructor of class representing the source type instruction in HSAIL. */
1720 hsa_insn_srctype::hsa_insn_srctype (int nops, BrigOpcode opcode,
1721 BrigType16_t destt, BrigType16_t srct,
1722 hsa_op_base *arg0, hsa_op_base *arg1,
1723 hsa_op_base *arg2 = NULL)
1724 : hsa_insn_basic (nops, opcode, destt, arg0, arg1, arg2),
1725 m_source_type (srct)
1728 /* Constructor of class representing the packed instruction in HSAIL. */
1730 hsa_insn_packed::hsa_insn_packed (int nops, BrigOpcode opcode,
1731 BrigType16_t destt, BrigType16_t srct,
1732 hsa_op_base *arg0, hsa_op_base *arg1,
1733 hsa_op_base *arg2)
1734 : hsa_insn_srctype (nops, opcode, destt, srct, arg0, arg1, arg2)
1736 m_operand_list = new hsa_op_operand_list (nops - 1);
1739 /* Constructor of class representing the convert instruction in HSAIL. */
1741 hsa_insn_cvt::hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src)
1742 : hsa_insn_basic (2, BRIG_OPCODE_CVT, dest->m_type, dest, src)
1746 /* Constructor of class representing the alloca in HSAIL. */
1748 hsa_insn_alloca::hsa_insn_alloca (hsa_op_with_type *dest,
1749 hsa_op_with_type *size, unsigned alignment)
1750 : hsa_insn_basic (2, BRIG_OPCODE_ALLOCA, dest->m_type, dest, size),
1751 m_align (BRIG_ALIGNMENT_8)
1753 gcc_assert (dest->m_type == BRIG_TYPE_U32);
1754 if (alignment)
1755 m_align = hsa_alignment_encoding (alignment);
1758 /* Append an instruction INSN into the basic block. */
1760 void
1761 hsa_bb::append_insn (hsa_insn_basic *insn)
1763 gcc_assert (insn->m_opcode != 0 || insn->operand_count () == 0);
1764 gcc_assert (!insn->m_bb);
1766 insn->m_bb = m_bb;
1767 insn->m_prev = m_last_insn;
1768 insn->m_next = NULL;
1769 if (m_last_insn)
1770 m_last_insn->m_next = insn;
1771 m_last_insn = insn;
1772 if (!m_first_insn)
1773 m_first_insn = insn;
1776 void
1777 hsa_bb::append_phi (hsa_insn_phi *hphi)
1779 hphi->m_bb = m_bb;
1781 hphi->m_prev = m_last_phi;
1782 hphi->m_next = NULL;
1783 if (m_last_phi)
1784 m_last_phi->m_next = hphi;
1785 m_last_phi = hphi;
1786 if (!m_first_phi)
1787 m_first_phi = hphi;
1790 /* Insert HSA instruction NEW_INSN immediately before an existing instruction
1791 OLD_INSN. */
1793 static void
1794 hsa_insert_insn_before (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1796 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1798 if (hbb->m_first_insn == old_insn)
1799 hbb->m_first_insn = new_insn;
1800 new_insn->m_prev = old_insn->m_prev;
1801 new_insn->m_next = old_insn;
1802 if (old_insn->m_prev)
1803 old_insn->m_prev->m_next = new_insn;
1804 old_insn->m_prev = new_insn;
1807 /* Append HSA instruction NEW_INSN immediately after an existing instruction
1808 OLD_INSN. */
1810 static void
1811 hsa_append_insn_after (hsa_insn_basic *new_insn, hsa_insn_basic *old_insn)
1813 hsa_bb *hbb = hsa_bb_for_bb (old_insn->m_bb);
1815 if (hbb->m_last_insn == old_insn)
1816 hbb->m_last_insn = new_insn;
1817 new_insn->m_prev = old_insn;
1818 new_insn->m_next = old_insn->m_next;
1819 if (old_insn->m_next)
1820 old_insn->m_next->m_prev = new_insn;
1821 old_insn->m_next = new_insn;
1824 /* Return a register containing the calculated value of EXP which must be an
1825 expression consisting of PLUS_EXPRs, MULT_EXPRs, NOP_EXPRs, SSA_NAMEs and
1826 integer constants as returned by get_inner_reference.
1827 Newly generated HSA instructions will be appended to HBB.
1828 Perform all calculations in ADDRTYPE. */
1830 static hsa_op_with_type *
1831 gen_address_calculation (tree exp, hsa_bb *hbb, BrigType16_t addrtype)
1833 int opcode;
1835 if (TREE_CODE (exp) == NOP_EXPR)
1836 exp = TREE_OPERAND (exp, 0);
1838 switch (TREE_CODE (exp))
1840 case SSA_NAME:
1841 return hsa_cfun->reg_for_gimple_ssa (exp)->get_in_type (addrtype, hbb);
1843 case INTEGER_CST:
1845 hsa_op_immed *imm = new hsa_op_immed (exp);
1846 if (addrtype != imm->m_type)
1847 imm->m_type = addrtype;
1848 return imm;
1851 case PLUS_EXPR:
1852 opcode = BRIG_OPCODE_ADD;
1853 break;
1855 case MULT_EXPR:
1856 opcode = BRIG_OPCODE_MUL;
1857 break;
1859 default:
1860 gcc_unreachable ();
1863 hsa_op_reg *res = new hsa_op_reg (addrtype);
1864 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, addrtype);
1865 insn->set_op (0, res);
1867 hsa_op_with_type *op1 = gen_address_calculation (TREE_OPERAND (exp, 0), hbb,
1868 addrtype);
1869 hsa_op_with_type *op2 = gen_address_calculation (TREE_OPERAND (exp, 1), hbb,
1870 addrtype);
1871 insn->set_op (1, op1);
1872 insn->set_op (2, op2);
1874 hbb->append_insn (insn);
1875 return res;
1878 /* If R1 is NULL, just return R2, otherwise append an instruction adding them
1879 to HBB and return the register holding the result. */
1881 static hsa_op_reg *
1882 add_addr_regs_if_needed (hsa_op_reg *r1, hsa_op_reg *r2, hsa_bb *hbb)
1884 gcc_checking_assert (r2);
1885 if (!r1)
1886 return r2;
1888 hsa_op_reg *res = new hsa_op_reg (r1->m_type);
1889 gcc_assert (!hsa_needs_cvt (r1->m_type, r2->m_type));
1890 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_ADD, res->m_type);
1891 insn->set_op (0, res);
1892 insn->set_op (1, r1);
1893 insn->set_op (2, r2);
1894 hbb->append_insn (insn);
1895 return res;
1898 /* Helper of gen_hsa_addr. Update *SYMBOL, *ADDRTYPE, *REG and *OFFSET to
1899 reflect BASE which is the first operand of a MEM_REF or a TARGET_MEM_REF. */
1901 static void
1902 process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype,
1903 hsa_op_reg **reg, offset_int *offset, hsa_bb *hbb)
1905 if (TREE_CODE (base) == SSA_NAME)
1907 gcc_assert (!*reg);
1908 hsa_op_with_type *ssa
1909 = hsa_cfun->reg_for_gimple_ssa (base)->get_in_type (*addrtype, hbb);
1910 *reg = dyn_cast <hsa_op_reg *> (ssa);
1912 else if (TREE_CODE (base) == ADDR_EXPR)
1914 tree decl = TREE_OPERAND (base, 0);
1916 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
1918 HSA_SORRY_AT (EXPR_LOCATION (base),
1919 "support for HSA does not implement a memory reference "
1920 "to a non-declaration type");
1921 return;
1924 gcc_assert (!*symbol);
1926 *symbol = get_symbol_for_decl (decl);
1927 *addrtype = hsa_get_segment_addr_type ((*symbol)->m_segment);
1929 else if (TREE_CODE (base) == INTEGER_CST)
1930 *offset += wi::to_offset (base);
1931 else
1932 gcc_unreachable ();
1935 /* Forward declaration of a function. */
1937 static void
1938 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb);
1940 /* Generate HSA address operand for a given tree memory reference REF. If
1941 instructions need to be created to calculate the address, they will be added
1942 to the end of HBB. If a caller provider OUTPUT_BITSIZE and OUTPUT_BITPOS,
1943 the function assumes that the caller will handle possible
1944 bit-field references. Otherwise if we reference a bit-field, sorry message
1945 is displayed. */
1947 static hsa_op_address *
1948 gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
1949 HOST_WIDE_INT *output_bitpos = NULL)
1951 hsa_symbol *symbol = NULL;
1952 hsa_op_reg *reg = NULL;
1953 offset_int offset = 0;
1954 tree origref = ref;
1955 tree varoffset = NULL_TREE;
1956 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1957 HOST_WIDE_INT bitsize = 0, bitpos = 0;
1958 BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
1960 if (TREE_CODE (ref) == STRING_CST)
1962 symbol = hsa_get_string_cst_symbol (ref);
1963 goto out;
1965 else if (TREE_CODE (ref) == BIT_FIELD_REF
1966 && (!multiple_p (bit_field_size (ref), BITS_PER_UNIT)
1967 || !multiple_p (bit_field_offset (ref), BITS_PER_UNIT)))
1969 HSA_SORRY_ATV (EXPR_LOCATION (origref),
1970 "support for HSA does not implement "
1971 "bit field references such as %E", ref);
1972 goto out;
1975 if (handled_component_p (ref))
1977 machine_mode mode;
1978 int unsignedp, volatilep, preversep;
1979 poly_int64 pbitsize, pbitpos;
1980 tree new_ref;
1982 new_ref = get_inner_reference (ref, &pbitsize, &pbitpos, &varoffset,
1983 &mode, &unsignedp, &preversep,
1984 &volatilep);
1985 /* When this isn't true, the switch below will report an
1986 appropriate error. */
1987 if (pbitsize.is_constant () && pbitpos.is_constant ())
1989 bitsize = pbitsize.to_constant ();
1990 bitpos = pbitpos.to_constant ();
1991 ref = new_ref;
1992 offset = bitpos;
1993 offset = wi::rshift (offset, LOG2_BITS_PER_UNIT, SIGNED);
1997 switch (TREE_CODE (ref))
1999 case ADDR_EXPR:
2001 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2002 symbol = hsa_cfun->create_hsa_temporary (flat_addrtype);
2003 hsa_op_reg *r = new hsa_op_reg (flat_addrtype);
2004 gen_hsa_addr_insns (ref, r, hbb);
2005 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2006 r, new hsa_op_address (symbol)));
2008 break;
2010 case SSA_NAME:
2012 addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE);
2013 hsa_op_with_type *r = hsa_cfun->reg_for_gimple_ssa (ref);
2014 if (r->m_type == BRIG_TYPE_B1)
2015 r = r->get_in_type (BRIG_TYPE_U32, hbb);
2016 symbol = hsa_cfun->create_hsa_temporary (r->m_type);
2018 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type,
2019 r, new hsa_op_address (symbol)));
2021 break;
2023 case PARM_DECL:
2024 case VAR_DECL:
2025 case RESULT_DECL:
2026 case CONST_DECL:
2027 gcc_assert (!symbol);
2028 symbol = get_symbol_for_decl (ref);
2029 addrtype = hsa_get_segment_addr_type (symbol->m_segment);
2030 break;
2032 case MEM_REF:
2033 process_mem_base (TREE_OPERAND (ref, 0), &symbol, &addrtype, &reg,
2034 &offset, hbb);
2036 if (!integer_zerop (TREE_OPERAND (ref, 1)))
2037 offset += wi::to_offset (TREE_OPERAND (ref, 1));
2038 break;
2040 case TARGET_MEM_REF:
2041 process_mem_base (TMR_BASE (ref), &symbol, &addrtype, &reg, &offset, hbb);
2042 if (TMR_INDEX (ref))
2044 hsa_op_reg *disp1;
2045 hsa_op_base *idx = hsa_cfun->reg_for_gimple_ssa
2046 (TMR_INDEX (ref))->get_in_type (addrtype, hbb);
2047 if (TMR_STEP (ref) && !integer_onep (TMR_STEP (ref)))
2049 disp1 = new hsa_op_reg (addrtype);
2050 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_MUL,
2051 addrtype);
2053 /* As step must respect addrtype, we overwrite the type
2054 of an immediate value. */
2055 hsa_op_immed *step = new hsa_op_immed (TMR_STEP (ref));
2056 step->m_type = addrtype;
2058 insn->set_op (0, disp1);
2059 insn->set_op (1, idx);
2060 insn->set_op (2, step);
2061 hbb->append_insn (insn);
2063 else
2064 disp1 = as_a <hsa_op_reg *> (idx);
2065 reg = add_addr_regs_if_needed (reg, disp1, hbb);
2067 if (TMR_INDEX2 (ref))
2069 if (TREE_CODE (TMR_INDEX2 (ref)) == SSA_NAME)
2071 hsa_op_base *disp2 = hsa_cfun->reg_for_gimple_ssa
2072 (TMR_INDEX2 (ref))->get_in_type (addrtype, hbb);
2073 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (disp2),
2074 hbb);
2076 else if (TREE_CODE (TMR_INDEX2 (ref)) == INTEGER_CST)
2077 offset += wi::to_offset (TMR_INDEX2 (ref));
2078 else
2079 gcc_unreachable ();
2081 offset += wi::to_offset (TMR_OFFSET (ref));
2082 break;
2083 case FUNCTION_DECL:
2084 HSA_SORRY_AT (EXPR_LOCATION (origref),
2085 "support for HSA does not implement function pointers");
2086 goto out;
2087 default:
2088 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does "
2089 "not implement memory access to %E", origref);
2090 goto out;
2093 if (varoffset)
2095 if (TREE_CODE (varoffset) == INTEGER_CST)
2096 offset += wi::to_offset (varoffset);
2097 else
2099 hsa_op_base *off_op = gen_address_calculation (varoffset, hbb,
2100 addrtype);
2101 reg = add_addr_regs_if_needed (reg, as_a <hsa_op_reg *> (off_op),
2102 hbb);
2106 gcc_checking_assert ((symbol
2107 && addrtype
2108 == hsa_get_segment_addr_type (symbol->m_segment))
2109 || (!symbol
2110 && addrtype
2111 == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)));
2112 out:
2113 HOST_WIDE_INT hwi_offset = offset.to_shwi ();
2115 /* Calculate remaining bitsize offset (if presented). */
2116 bitpos %= BITS_PER_UNIT;
2117 /* If bitsize is a power of two that is greater or equal to BITS_PER_UNIT, it
2118 is not a reason to think this is a bit-field access. */
2119 if (bitpos == 0
2120 && (bitsize >= BITS_PER_UNIT)
2121 && !(bitsize & (bitsize - 1)))
2122 bitsize = 0;
2124 if ((bitpos || bitsize) && (output_bitpos == NULL || output_bitsize == NULL))
2125 HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does not "
2126 "implement unhandled bit field reference such as %E", ref);
2128 if (output_bitsize != NULL && output_bitpos != NULL)
2130 *output_bitsize = bitsize;
2131 *output_bitpos = bitpos;
2134 return new hsa_op_address (symbol, reg, hwi_offset);
2137 /* Generate HSA address operand for a given tree memory reference REF. If
2138 instructions need to be created to calculate the address, they will be added
2139 to the end of HBB. OUTPUT_ALIGN is alignment of the created address. */
2141 static hsa_op_address *
2142 gen_hsa_addr_with_align (tree ref, hsa_bb *hbb, BrigAlignment8_t *output_align)
2144 hsa_op_address *addr = gen_hsa_addr (ref, hbb);
2145 if (addr->m_reg || !addr->m_symbol)
2146 *output_align = hsa_object_alignment (ref);
2147 else
2149 /* If the address consists only of a symbol and an offset, we
2150 compute the alignment ourselves to take into account any alignment
2151 promotions we might have done for the HSA symbol representation. */
2152 unsigned align = hsa_byte_alignment (addr->m_symbol->m_align);
2153 unsigned misalign = addr->m_imm_offset & (align - 1);
2154 if (misalign)
2155 align = least_bit_hwi (misalign);
2156 *output_align = hsa_alignment_encoding (BITS_PER_UNIT * align);
2158 return addr;
2161 /* Generate HSA address for a function call argument of given TYPE.
2162 INDEX is used to generate corresponding name of the arguments.
2163 Special value -1 represents fact that result value is created. */
2165 static hsa_op_address *
2166 gen_hsa_addr_for_arg (tree tree_type, int index)
2168 hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
2169 BRIG_LINKAGE_ARG);
2170 sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim);
2172 if (index == -1) /* Function result. */
2173 sym->m_name = "res";
2174 else /* Function call arguments. */
2176 sym->m_name = NULL;
2177 sym->m_name_number = index;
2180 return new hsa_op_address (sym);
2183 /* Generate HSA instructions that process all necessary conversions
2184 of an ADDR to flat addressing and place the result into DEST.
2185 Instructions are appended to HBB. */
2187 static void
2188 convert_addr_to_flat_segment (hsa_op_address *addr, hsa_op_reg *dest,
2189 hsa_bb *hbb)
2191 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_LDA);
2192 insn->set_op (1, addr);
2193 if (addr->m_symbol && addr->m_symbol->m_segment != BRIG_SEGMENT_GLOBAL)
2195 /* LDA produces segment-relative address, we need to convert
2196 it to the flat one. */
2197 hsa_op_reg *tmp;
2198 tmp = new hsa_op_reg (hsa_get_segment_addr_type
2199 (addr->m_symbol->m_segment));
2200 hsa_insn_seg *seg;
2201 seg = new hsa_insn_seg (BRIG_OPCODE_STOF,
2202 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
2203 tmp->m_type, addr->m_symbol->m_segment, dest,
2204 tmp);
2206 insn->set_op (0, tmp);
2207 insn->m_type = tmp->m_type;
2208 hbb->append_insn (insn);
2209 hbb->append_insn (seg);
2211 else
2213 insn->set_op (0, dest);
2214 insn->m_type = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
2215 hbb->append_insn (insn);
2219 /* Generate HSA instructions that calculate address of VAL including all
2220 necessary conversions to flat addressing and place the result into DEST.
2221 Instructions are appended to HBB. */
2223 static void
2224 gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
2226 /* Handle cases like tmp = NULL, where we just emit a move instruction
2227 to a register. */
2228 if (TREE_CODE (val) == INTEGER_CST)
2230 hsa_op_immed *c = new hsa_op_immed (val);
2231 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2232 dest->m_type, dest, c);
2233 hbb->append_insn (insn);
2234 return;
2237 hsa_op_address *addr;
2239 gcc_assert (dest->m_type == hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2240 if (TREE_CODE (val) == ADDR_EXPR)
2241 val = TREE_OPERAND (val, 0);
2242 addr = gen_hsa_addr (val, hbb);
2244 if (TREE_CODE (val) == CONST_DECL
2245 && is_gimple_reg_type (TREE_TYPE (val)))
2247 gcc_assert (addr->m_symbol
2248 && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY);
2249 /* CONST_DECLs are in readonly segment which however does not have
2250 addresses convertible to flat segments. So copy it to a private one
2251 and take address of that. */
2252 BrigType16_t csttype
2253 = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (val),
2254 false));
2255 hsa_op_reg *r = new hsa_op_reg (csttype);
2256 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, csttype, r,
2257 new hsa_op_address (addr->m_symbol)));
2258 hsa_symbol *copysym = hsa_cfun->create_hsa_temporary (csttype);
2259 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, csttype, r,
2260 new hsa_op_address (copysym)));
2261 addr->m_symbol = copysym;
2263 else if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY)
2265 HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
2266 "not implement taking addresses of complex "
2267 "CONST_DECLs such as %E", val);
2268 return;
2272 convert_addr_to_flat_segment (addr, dest, hbb);
2275 /* Return an HSA register or HSA immediate value operand corresponding to
2276 gimple operand OP. */
2278 static hsa_op_with_type *
2279 hsa_reg_or_immed_for_gimple_op (tree op, hsa_bb *hbb)
2281 hsa_op_reg *tmp;
2283 if (TREE_CODE (op) == SSA_NAME)
2284 tmp = hsa_cfun->reg_for_gimple_ssa (op);
2285 else if (!POINTER_TYPE_P (TREE_TYPE (op)))
2286 return new hsa_op_immed (op);
2287 else
2289 tmp = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
2290 gen_hsa_addr_insns (op, tmp, hbb);
2292 return tmp;
2295 /* Create a simple movement instruction with register destination DEST and
2296 register or immediate source SRC and append it to the end of HBB. */
2298 void
2299 hsa_build_append_simple_mov (hsa_op_reg *dest, hsa_op_base *src, hsa_bb *hbb)
2301 /* Moves of packed data between registers need to adhere to the same type
2302 rules like when dealing with memory. */
2303 BrigType16_t tp = mem_type_for_type (dest->m_type);
2304 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, tp, dest, src);
2305 hsa_fixup_mov_insn_type (insn);
2306 unsigned dest_size = hsa_type_bit_size (dest->m_type);
2307 if (hsa_op_reg *sreg = dyn_cast <hsa_op_reg *> (src))
2308 gcc_assert (dest_size == hsa_type_bit_size (sreg->m_type));
2309 else
2311 unsigned imm_size
2312 = hsa_type_bit_size (as_a <hsa_op_immed *> (src)->m_type);
2313 gcc_assert ((dest_size == imm_size)
2314 /* Eventually < 32bit registers will be promoted to 32bit. */
2315 || (dest_size < 32 && imm_size == 32));
2317 hbb->append_insn (insn);
2320 /* Generate HSAIL instructions loading a bit field into register DEST.
2321 VALUE_REG is a register of a SSA name that is used in the bit field
2322 reference. To identify a bit field BITPOS is offset to the loaded memory
2323 and BITSIZE is number of bits of the bit field.
2324 Add instructions to HBB. */
2326 static void
2327 gen_hsa_insns_for_bitfield (hsa_op_reg *dest, hsa_op_reg *value_reg,
2328 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2329 hsa_bb *hbb)
2331 unsigned type_bitsize
2332 = hsa_type_bit_size (hsa_extend_inttype_to_32bit (dest->m_type));
2333 unsigned left_shift = type_bitsize - (bitsize + bitpos);
2334 unsigned right_shift = left_shift + bitpos;
2336 if (left_shift)
2338 hsa_op_reg *value_reg_2
2339 = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
2340 hsa_op_immed *c = new hsa_op_immed (left_shift, BRIG_TYPE_U32);
2342 hsa_insn_basic *lshift
2343 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, value_reg_2->m_type,
2344 value_reg_2, value_reg, c);
2346 hbb->append_insn (lshift);
2348 value_reg = value_reg_2;
2351 if (right_shift)
2353 hsa_op_reg *value_reg_2
2354 = new hsa_op_reg (hsa_extend_inttype_to_32bit (dest->m_type));
2355 hsa_op_immed *c = new hsa_op_immed (right_shift, BRIG_TYPE_U32);
2357 hsa_insn_basic *rshift
2358 = new hsa_insn_basic (3, BRIG_OPCODE_SHR, value_reg_2->m_type,
2359 value_reg_2, value_reg, c);
2361 hbb->append_insn (rshift);
2363 value_reg = value_reg_2;
2366 hsa_insn_basic *assignment
2367 = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type, NULL, value_reg);
2368 hsa_fixup_mov_insn_type (assignment);
2369 hbb->append_insn (assignment);
2370 assignment->set_output_in_type (dest, 0, hbb);
2374 /* Generate HSAIL instructions loading a bit field into register DEST. ADDR is
2375 prepared memory address which is used to load the bit field. To identify a
2376 bit field BITPOS is offset to the loaded memory and BITSIZE is number of
2377 bits of the bit field. Add instructions to HBB. Load must be performed in
2378 alignment ALIGN. */
2380 static void
2381 gen_hsa_insns_for_bitfield_load (hsa_op_reg *dest, hsa_op_address *addr,
2382 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
2383 hsa_bb *hbb, BrigAlignment8_t align)
2385 hsa_op_reg *value_reg = new hsa_op_reg (dest->m_type);
2386 hsa_insn_mem *mem
2387 = new hsa_insn_mem (BRIG_OPCODE_LD,
2388 hsa_extend_inttype_to_32bit (dest->m_type),
2389 value_reg, addr);
2390 mem->set_align (align);
2391 hbb->append_insn (mem);
2392 gen_hsa_insns_for_bitfield (dest, value_reg, bitsize, bitpos, hbb);
2395 /* Return the alignment of base memory accesses we issue to perform bit-field
2396 memory access REF. */
2398 static BrigAlignment8_t
2399 hsa_bitmemref_alignment (tree ref)
2401 unsigned HOST_WIDE_INT bit_offset = 0;
2403 while (true)
2405 if (TREE_CODE (ref) == BIT_FIELD_REF)
2407 if (!tree_fits_uhwi_p (TREE_OPERAND (ref, 2)))
2408 return BRIG_ALIGNMENT_1;
2409 bit_offset += tree_to_uhwi (TREE_OPERAND (ref, 2));
2411 else if (TREE_CODE (ref) == COMPONENT_REF
2412 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
2413 bit_offset += int_bit_position (TREE_OPERAND (ref, 1));
2414 else
2415 break;
2416 ref = TREE_OPERAND (ref, 0);
2419 unsigned HOST_WIDE_INT bits = bit_offset % BITS_PER_UNIT;
2420 unsigned HOST_WIDE_INT byte_bits = bit_offset - bits;
2421 BrigAlignment8_t base = hsa_object_alignment (ref);
2422 if (byte_bits == 0)
2423 return base;
2424 return MIN (base, hsa_alignment_encoding (least_bit_hwi (byte_bits)));
2427 /* Generate HSAIL instructions loading something into register DEST. RHS is
2428 tree representation of the loaded data, which are loaded as type TYPE. Add
2429 instructions to HBB. */
2431 static void
2432 gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
2434 /* The destination SSA name will give us the type. */
2435 if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
2436 rhs = TREE_OPERAND (rhs, 0);
2438 if (TREE_CODE (rhs) == SSA_NAME)
2440 hsa_op_reg *src = hsa_cfun->reg_for_gimple_ssa (rhs);
2441 hsa_build_append_simple_mov (dest, src, hbb);
2443 else if (is_gimple_min_invariant (rhs)
2444 || TREE_CODE (rhs) == ADDR_EXPR)
2446 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
2448 if (dest->m_type != hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT))
2450 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2451 "support for HSA does not implement conversion "
2452 "of %E to the requested non-pointer type.", rhs);
2453 return;
2456 gen_hsa_addr_insns (rhs, dest, hbb);
2458 else if (TREE_CODE (rhs) == COMPLEX_CST)
2460 hsa_op_immed *real_part = new hsa_op_immed (TREE_REALPART (rhs));
2461 hsa_op_immed *imag_part = new hsa_op_immed (TREE_IMAGPART (rhs));
2463 hsa_op_reg *real_part_reg
2464 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2465 true));
2466 hsa_op_reg *imag_part_reg
2467 = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (type),
2468 true));
2470 hsa_build_append_simple_mov (real_part_reg, real_part, hbb);
2471 hsa_build_append_simple_mov (imag_part_reg, imag_part, hbb);
2473 BrigType16_t src_type = hsa_bittype_for_type (real_part_reg->m_type);
2475 hsa_insn_packed *insn
2476 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
2477 src_type, dest, real_part_reg,
2478 imag_part_reg);
2479 hbb->append_insn (insn);
2481 else
2483 hsa_op_immed *imm = new hsa_op_immed (rhs);
2484 hsa_build_append_simple_mov (dest, imm, hbb);
2487 else if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (rhs) == IMAGPART_EXPR)
2489 tree pack_type = TREE_TYPE (TREE_OPERAND (rhs, 0));
2491 hsa_op_reg *packed_reg
2492 = new hsa_op_reg (hsa_type_for_scalar_tree_type (pack_type, true));
2494 tree complex_rhs = TREE_OPERAND (rhs, 0);
2495 gen_hsa_insns_for_load (packed_reg, complex_rhs, TREE_TYPE (complex_rhs),
2496 hbb);
2498 hsa_op_reg *real_reg
2499 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2501 hsa_op_reg *imag_reg
2502 = new hsa_op_reg (hsa_type_for_scalar_tree_type (type, true));
2504 BrigKind16_t brig_type = packed_reg->m_type;
2505 hsa_insn_packed *packed
2506 = new hsa_insn_packed (3, BRIG_OPCODE_EXPAND,
2507 hsa_bittype_for_type (real_reg->m_type),
2508 brig_type, real_reg, imag_reg, packed_reg);
2510 hbb->append_insn (packed);
2512 hsa_op_reg *source = TREE_CODE (rhs) == REALPART_EXPR ?
2513 real_reg : imag_reg;
2515 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV,
2516 dest->m_type, NULL, source);
2517 hsa_fixup_mov_insn_type (insn);
2518 hbb->append_insn (insn);
2519 insn->set_output_in_type (dest, 0, hbb);
2521 else if (TREE_CODE (rhs) == BIT_FIELD_REF
2522 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
2524 tree ssa_name = TREE_OPERAND (rhs, 0);
2525 HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs, 1));
2526 HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs, 2));
2528 hsa_op_reg *imm_value = hsa_cfun->reg_for_gimple_ssa (ssa_name);
2529 gen_hsa_insns_for_bitfield (dest, imm_value, bitsize, bitpos, hbb);
2531 else if (DECL_P (rhs) || TREE_CODE (rhs) == MEM_REF
2532 || TREE_CODE (rhs) == TARGET_MEM_REF
2533 || handled_component_p (rhs))
2535 HOST_WIDE_INT bitsize, bitpos;
2537 /* Load from memory. */
2538 hsa_op_address *addr;
2539 addr = gen_hsa_addr (rhs, hbb, &bitsize, &bitpos);
2541 /* Handle load of a bit field. */
2542 if (bitsize > 64)
2544 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2545 "support for HSA does not implement load from a bit "
2546 "field bigger than 64 bits");
2547 return;
2550 if (bitsize || bitpos)
2551 gen_hsa_insns_for_bitfield_load (dest, addr, bitsize, bitpos, hbb,
2552 hsa_bitmemref_alignment (rhs));
2553 else
2555 BrigType16_t mtype;
2556 /* Not dest->m_type, that's possibly extended. */
2557 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (type,
2558 false));
2559 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dest,
2560 addr);
2561 mem->set_align (hsa_object_alignment (rhs));
2562 hbb->append_insn (mem);
2565 else
2566 HSA_SORRY_ATV (EXPR_LOCATION (rhs),
2567 "support for HSA does not implement loading "
2568 "of expression %E",
2569 rhs);
2572 /* Return number of bits necessary for representation of a bit field,
2573 starting at BITPOS with size of BITSIZE. */
2575 static unsigned
2576 get_bitfield_size (unsigned bitpos, unsigned bitsize)
2578 unsigned s = bitpos + bitsize;
2579 unsigned sizes[] = {8, 16, 32, 64};
2581 for (unsigned i = 0; i < 4; i++)
2582 if (s <= sizes[i])
2583 return sizes[i];
2585 gcc_unreachable ();
2586 return 0;
2589 /* Generate HSAIL instructions storing into memory. LHS is the destination of
2590 the store, SRC is the source operand. Add instructions to HBB. */
2592 static void
2593 gen_hsa_insns_for_store (tree lhs, hsa_op_base *src, hsa_bb *hbb)
2595 HOST_WIDE_INT bitsize = 0, bitpos = 0;
2596 BrigAlignment8_t req_align;
2597 BrigType16_t mtype;
2598 mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
2599 false));
2600 hsa_op_address *addr;
2601 addr = gen_hsa_addr (lhs, hbb, &bitsize, &bitpos);
2603 /* Handle store to a bit field. */
2604 if (bitsize > 64)
2606 HSA_SORRY_AT (EXPR_LOCATION (lhs),
2607 "support for HSA does not implement store to a bit field "
2608 "bigger than 64 bits");
2609 return;
2612 unsigned type_bitsize = get_bitfield_size (bitpos, bitsize);
2614 /* HSAIL does not support MOV insn with 16-bits integers. */
2615 if (type_bitsize < 32)
2616 type_bitsize = 32;
2618 if (bitpos || (bitsize && type_bitsize != bitsize))
2620 unsigned HOST_WIDE_INT mask = 0;
2621 BrigType16_t mem_type
2622 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT,
2623 !TYPE_UNSIGNED (TREE_TYPE (lhs)));
2625 for (unsigned i = 0; i < type_bitsize; i++)
2626 if (i < bitpos || i >= bitpos + bitsize)
2627 mask |= ((unsigned HOST_WIDE_INT)1 << i);
2629 hsa_op_reg *value_reg = new hsa_op_reg (mem_type);
2631 req_align = hsa_bitmemref_alignment (lhs);
2632 /* Load value from memory. */
2633 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mem_type,
2634 value_reg, addr);
2635 mem->set_align (req_align);
2636 hbb->append_insn (mem);
2638 /* AND the loaded value with prepared mask. */
2639 hsa_op_reg *cleared_reg = new hsa_op_reg (mem_type);
2641 BrigType16_t t
2642 = get_integer_type_by_bytes (type_bitsize / BITS_PER_UNIT, false);
2643 hsa_op_immed *c = new hsa_op_immed (mask, t);
2645 hsa_insn_basic *clearing
2646 = new hsa_insn_basic (3, BRIG_OPCODE_AND, mem_type, cleared_reg,
2647 value_reg, c);
2648 hbb->append_insn (clearing);
2650 /* Shift to left a value that is going to be stored. */
2651 hsa_op_reg *new_value_reg = new hsa_op_reg (mem_type);
2653 hsa_insn_basic *basic = new hsa_insn_basic (2, BRIG_OPCODE_MOV, mem_type,
2654 new_value_reg, src);
2655 hsa_fixup_mov_insn_type (basic);
2656 hbb->append_insn (basic);
2658 if (bitpos)
2660 hsa_op_reg *shifted_value_reg = new hsa_op_reg (mem_type);
2661 c = new hsa_op_immed (bitpos, BRIG_TYPE_U32);
2663 hsa_insn_basic *basic
2664 = new hsa_insn_basic (3, BRIG_OPCODE_SHL, mem_type,
2665 shifted_value_reg, new_value_reg, c);
2666 hbb->append_insn (basic);
2668 new_value_reg = shifted_value_reg;
2671 /* OR the prepared value with prepared chunk loaded from memory. */
2672 hsa_op_reg *prepared_reg= new hsa_op_reg (mem_type);
2673 basic = new hsa_insn_basic (3, BRIG_OPCODE_OR, mem_type, prepared_reg,
2674 new_value_reg, cleared_reg);
2675 hbb->append_insn (basic);
2677 src = prepared_reg;
2678 mtype = mem_type;
2680 else
2681 req_align = hsa_object_alignment (lhs);
2683 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr);
2684 mem->set_align (req_align);
2686 /* The HSAIL verifier has another constraint: if the source is an immediate
2687 then it must match the destination type. If it's a register the low bits
2688 will be used for sub-word stores. We're always allocating new operands so
2689 we can modify the above in place. */
2690 if (hsa_op_immed *imm = dyn_cast <hsa_op_immed *> (src))
2692 if (!hsa_type_packed_p (imm->m_type))
2693 imm->m_type = mem->m_type;
2694 else
2696 /* ...and all vector immediates apparently need to be vectors of
2697 unsigned bytes. */
2698 unsigned bs = hsa_type_bit_size (imm->m_type);
2699 gcc_assert (bs == hsa_type_bit_size (mem->m_type));
2700 switch (bs)
2702 case 32:
2703 imm->m_type = BRIG_TYPE_U8X4;
2704 break;
2705 case 64:
2706 imm->m_type = BRIG_TYPE_U8X8;
2707 break;
2708 case 128:
2709 imm->m_type = BRIG_TYPE_U8X16;
2710 break;
2711 default:
2712 gcc_unreachable ();
2717 hbb->append_insn (mem);
2720 /* Generate memory copy instructions that are going to be used
2721 for copying a SRC memory to TARGET memory,
2722 represented by pointer in a register. MIN_ALIGN is minimal alignment
2723 of provided HSA addresses. */
2725 static void
2726 gen_hsa_memory_copy (hsa_bb *hbb, hsa_op_address *target, hsa_op_address *src,
2727 unsigned size, BrigAlignment8_t min_align)
2729 hsa_op_address *addr;
2730 hsa_insn_mem *mem;
2732 unsigned offset = 0;
2733 unsigned min_byte_align = hsa_byte_alignment (min_align);
2735 while (size)
2737 unsigned s;
2738 if (size >= 8)
2739 s = 8;
2740 else if (size >= 4)
2741 s = 4;
2742 else if (size >= 2)
2743 s = 2;
2744 else
2745 s = 1;
2747 if (s > min_byte_align)
2748 s = min_byte_align;
2750 BrigType16_t t = get_integer_type_by_bytes (s, false);
2752 hsa_op_reg *tmp = new hsa_op_reg (t);
2753 addr = new hsa_op_address (src->m_symbol, src->m_reg,
2754 src->m_imm_offset + offset);
2755 mem = new hsa_insn_mem (BRIG_OPCODE_LD, t, tmp, addr);
2756 hbb->append_insn (mem);
2758 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2759 target->m_imm_offset + offset);
2760 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, tmp, addr);
2761 hbb->append_insn (mem);
2762 offset += s;
2763 size -= s;
2767 /* Create a memset mask that is created by copying a CONSTANT byte value
2768 to an integer of BYTE_SIZE bytes. */
2770 static unsigned HOST_WIDE_INT
2771 build_memset_value (unsigned HOST_WIDE_INT constant, unsigned byte_size)
2773 if (constant == 0)
2774 return 0;
2776 HOST_WIDE_INT v = constant;
2778 for (unsigned i = 1; i < byte_size; i++)
2779 v |= constant << (8 * i);
2781 return v;
2784 /* Generate memory set instructions that are going to be used
2785 for setting a CONSTANT byte value to TARGET memory of SIZE bytes.
2786 MIN_ALIGN is minimal alignment of provided HSA addresses. */
2788 static void
2789 gen_hsa_memory_set (hsa_bb *hbb, hsa_op_address *target,
2790 unsigned HOST_WIDE_INT constant,
2791 unsigned size, BrigAlignment8_t min_align)
2793 hsa_op_address *addr;
2794 hsa_insn_mem *mem;
2796 unsigned offset = 0;
2797 unsigned min_byte_align = hsa_byte_alignment (min_align);
2799 while (size)
2801 unsigned s;
2802 if (size >= 8)
2803 s = 8;
2804 else if (size >= 4)
2805 s = 4;
2806 else if (size >= 2)
2807 s = 2;
2808 else
2809 s = 1;
2811 if (s > min_byte_align)
2812 s = min_byte_align;
2814 addr = new hsa_op_address (target->m_symbol, target->m_reg,
2815 target->m_imm_offset + offset);
2817 BrigType16_t t = get_integer_type_by_bytes (s, false);
2818 HOST_WIDE_INT c = build_memset_value (constant, s);
2820 mem = new hsa_insn_mem (BRIG_OPCODE_ST, t, new hsa_op_immed (c, t),
2821 addr);
2822 hbb->append_insn (mem);
2823 offset += s;
2824 size -= s;
2828 /* Generate HSAIL instructions for a single assignment
2829 of an empty constructor to an ADDR_LHS. Constructor is passed as a
2830 tree RHS and all instructions are appended to HBB. ALIGN is
2831 alignment of the address. */
2833 void
2834 gen_hsa_ctor_assignment (hsa_op_address *addr_lhs, tree rhs, hsa_bb *hbb,
2835 BrigAlignment8_t align)
2837 if (CONSTRUCTOR_NELTS (rhs))
2839 HSA_SORRY_AT (EXPR_LOCATION (rhs),
2840 "support for HSA does not implement load from constructor");
2841 return;
2844 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2845 gen_hsa_memory_set (hbb, addr_lhs, 0, size, align);
2848 /* Generate HSA instructions for a single assignment of RHS to LHS.
2849 HBB is the basic block they will be appended to. */
2851 static void
2852 gen_hsa_insns_for_single_assignment (tree lhs, tree rhs, hsa_bb *hbb)
2854 if (TREE_CODE (lhs) == SSA_NAME)
2856 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
2857 if (hsa_seen_error ())
2858 return;
2860 gen_hsa_insns_for_load (dest, rhs, TREE_TYPE (lhs), hbb);
2862 else if (TREE_CODE (rhs) == SSA_NAME
2863 || (is_gimple_min_invariant (rhs) && TREE_CODE (rhs) != STRING_CST))
2865 /* Store to memory. */
2866 hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
2867 if (hsa_seen_error ())
2868 return;
2870 gen_hsa_insns_for_store (lhs, src, hbb);
2872 else
2874 BrigAlignment8_t lhs_align;
2875 hsa_op_address *addr_lhs = gen_hsa_addr_with_align (lhs, hbb,
2876 &lhs_align);
2878 if (TREE_CODE (rhs) == CONSTRUCTOR)
2879 gen_hsa_ctor_assignment (addr_lhs, rhs, hbb, lhs_align);
2880 else
2882 BrigAlignment8_t rhs_align;
2883 hsa_op_address *addr_rhs = gen_hsa_addr_with_align (rhs, hbb,
2884 &rhs_align);
2886 unsigned size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (rhs)));
2887 gen_hsa_memory_copy (hbb, addr_lhs, addr_rhs, size,
2888 MIN (lhs_align, rhs_align));
2893 /* Prepend before INSN a load from spill symbol of SPILL_REG. Return the
2894 register into which we loaded. If this required another register to convert
2895 from a B1 type, return it in *PTMP2, otherwise store NULL into it. We
2896 assume we are out of SSA so the returned register does not have its
2897 definition set. */
2899 hsa_op_reg *
2900 hsa_spill_in (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2902 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2903 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2904 hsa_op_address *addr = new hsa_op_address (spill_sym);
2906 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, spill_sym->m_type,
2907 reg, addr);
2908 hsa_insert_insn_before (mem, insn);
2910 *ptmp2 = NULL;
2911 if (spill_reg->m_type == BRIG_TYPE_B1)
2913 hsa_insn_basic *cvtinsn;
2914 *ptmp2 = reg;
2915 reg = new hsa_op_reg (spill_reg->m_type);
2917 cvtinsn = new hsa_insn_cvt (reg, *ptmp2);
2918 hsa_insert_insn_before (cvtinsn, insn);
2920 return reg;
2923 /* Append after INSN a store to spill symbol of SPILL_REG. Return the register
2924 from which we stored. If this required another register to convert to a B1
2925 type, return it in *PTMP2, otherwise store NULL into it. We assume we are
2926 out of SSA so the returned register does not have its use updated. */
2928 hsa_op_reg *
2929 hsa_spill_out (hsa_insn_basic *insn, hsa_op_reg *spill_reg, hsa_op_reg **ptmp2)
2931 hsa_symbol *spill_sym = spill_reg->m_spill_sym;
2932 hsa_op_reg *reg = new hsa_op_reg (spill_sym->m_type);
2933 hsa_op_address *addr = new hsa_op_address (spill_sym);
2934 hsa_op_reg *returnreg;
2936 *ptmp2 = NULL;
2937 returnreg = reg;
2938 if (spill_reg->m_type == BRIG_TYPE_B1)
2940 hsa_insn_basic *cvtinsn;
2941 *ptmp2 = new hsa_op_reg (spill_sym->m_type);
2942 reg->m_type = spill_reg->m_type;
2944 cvtinsn = new hsa_insn_cvt (*ptmp2, returnreg);
2945 hsa_append_insn_after (cvtinsn, insn);
2946 insn = cvtinsn;
2947 reg = *ptmp2;
2950 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, spill_sym->m_type, reg,
2951 addr);
2952 hsa_append_insn_after (mem, insn);
2953 return returnreg;
2956 /* Generate a comparison instruction that will compare LHS and RHS with
2957 comparison specified by CODE and put result into register DEST. DEST has to
2958 have its type set already but must not have its definition set yet.
2959 Generated instructions will be added to HBB. */
2961 static void
2962 gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
2963 hsa_op_reg *dest, hsa_bb *hbb)
2965 BrigCompareOperation8_t compare;
2967 switch (code)
2969 case LT_EXPR:
2970 compare = BRIG_COMPARE_LT;
2971 break;
2972 case LE_EXPR:
2973 compare = BRIG_COMPARE_LE;
2974 break;
2975 case GT_EXPR:
2976 compare = BRIG_COMPARE_GT;
2977 break;
2978 case GE_EXPR:
2979 compare = BRIG_COMPARE_GE;
2980 break;
2981 case EQ_EXPR:
2982 compare = BRIG_COMPARE_EQ;
2983 break;
2984 case NE_EXPR:
2985 compare = BRIG_COMPARE_NE;
2986 break;
2987 case UNORDERED_EXPR:
2988 compare = BRIG_COMPARE_NAN;
2989 break;
2990 case ORDERED_EXPR:
2991 compare = BRIG_COMPARE_NUM;
2992 break;
2993 case UNLT_EXPR:
2994 compare = BRIG_COMPARE_LTU;
2995 break;
2996 case UNLE_EXPR:
2997 compare = BRIG_COMPARE_LEU;
2998 break;
2999 case UNGT_EXPR:
3000 compare = BRIG_COMPARE_GTU;
3001 break;
3002 case UNGE_EXPR:
3003 compare = BRIG_COMPARE_GEU;
3004 break;
3005 case UNEQ_EXPR:
3006 compare = BRIG_COMPARE_EQU;
3007 break;
3008 case LTGT_EXPR:
3009 compare = BRIG_COMPARE_NEU;
3010 break;
3012 default:
3013 HSA_SORRY_ATV (EXPR_LOCATION (lhs),
3014 "support for HSA does not implement comparison tree "
3015 "code %s\n", get_tree_code_name (code));
3016 return;
3019 /* CMP instruction returns e.g. 0xffffffff (for a 32-bit with integer)
3020 as a result of comparison. */
3022 BrigType16_t dest_type = hsa_type_integer_p (dest->m_type)
3023 ? (BrigType16_t) BRIG_TYPE_B1 : dest->m_type;
3025 hsa_insn_cmp *cmp = new hsa_insn_cmp (compare, dest_type);
3026 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (lhs, hbb);
3027 cmp->set_op (1, op1->extend_int_to_32bit (hbb));
3028 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs, hbb);
3029 cmp->set_op (2, op2->extend_int_to_32bit (hbb));
3031 hbb->append_insn (cmp);
3032 cmp->set_output_in_type (dest, 0, hbb);
3035 /* Generate an unary instruction with OPCODE and append it to a basic block
3036 HBB. The instruction uses DEST as a destination and OP1
3037 as a single operand. */
3039 static void
3040 gen_hsa_unary_operation (BrigOpcode opcode, hsa_op_reg *dest,
3041 hsa_op_with_type *op1, hsa_bb *hbb)
3043 gcc_checking_assert (dest);
3044 hsa_insn_basic *insn;
3046 if (opcode == BRIG_OPCODE_MOV && hsa_needs_cvt (dest->m_type, op1->m_type))
3048 insn = new hsa_insn_cvt (dest, op1);
3049 hbb->append_insn (insn);
3050 return;
3053 op1 = op1->extend_int_to_32bit (hbb);
3054 if (opcode == BRIG_OPCODE_FIRSTBIT || opcode == BRIG_OPCODE_LASTBIT)
3056 BrigType16_t srctype = hsa_type_integer_p (op1->m_type) ? op1->m_type
3057 : hsa_unsigned_type_for_type (op1->m_type);
3058 insn = new hsa_insn_srctype (2, opcode, BRIG_TYPE_U32, srctype, NULL,
3059 op1);
3061 else
3063 BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
3064 insn = new hsa_insn_basic (2, opcode, optype, NULL, op1);
3066 if (opcode == BRIG_OPCODE_MOV)
3067 hsa_fixup_mov_insn_type (insn);
3068 else if (opcode == BRIG_OPCODE_ABS || opcode == BRIG_OPCODE_NEG)
3070 /* ABS and NEG only exist in _s form :-/ */
3071 if (insn->m_type == BRIG_TYPE_U32)
3072 insn->m_type = BRIG_TYPE_S32;
3073 else if (insn->m_type == BRIG_TYPE_U64)
3074 insn->m_type = BRIG_TYPE_S64;
3078 hbb->append_insn (insn);
3079 insn->set_output_in_type (dest, 0, hbb);
3082 /* Generate a binary instruction with OPCODE and append it to a basic block
3083 HBB. The instruction uses DEST as a destination and operands OP1
3084 and OP2. */
3086 static void
3087 gen_hsa_binary_operation (int opcode, hsa_op_reg *dest,
3088 hsa_op_with_type *op1, hsa_op_with_type *op2,
3089 hsa_bb *hbb)
3091 gcc_checking_assert (dest);
3093 BrigType16_t optype = hsa_extend_inttype_to_32bit (dest->m_type);
3094 op1 = op1->extend_int_to_32bit (hbb);
3095 op2 = op2->extend_int_to_32bit (hbb);
3097 if ((opcode == BRIG_OPCODE_SHL || opcode == BRIG_OPCODE_SHR)
3098 && is_a <hsa_op_immed *> (op2))
3100 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3101 i->set_type (BRIG_TYPE_U32);
3103 if ((opcode == BRIG_OPCODE_OR
3104 || opcode == BRIG_OPCODE_XOR
3105 || opcode == BRIG_OPCODE_AND)
3106 && is_a <hsa_op_immed *> (op2))
3108 hsa_op_immed *i = dyn_cast <hsa_op_immed *> (op2);
3109 i->set_type (hsa_unsigned_type_for_type (i->m_type));
3112 hsa_insn_basic *insn = new hsa_insn_basic (3, opcode, optype, NULL,
3113 op1, op2);
3114 hbb->append_insn (insn);
3115 insn->set_output_in_type (dest, 0, hbb);
3118 /* Generate HSA instructions for a single assignment. HBB is the basic block
3119 they will be appended to. */
3121 static void
3122 gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
3124 tree_code code = gimple_assign_rhs_code (assign);
3125 gimple_rhs_class rhs_class = get_gimple_rhs_class (gimple_expr_code (assign));
3127 tree lhs = gimple_assign_lhs (assign);
3128 tree rhs1 = gimple_assign_rhs1 (assign);
3129 tree rhs2 = gimple_assign_rhs2 (assign);
3130 tree rhs3 = gimple_assign_rhs3 (assign);
3132 BrigOpcode opcode;
3134 switch (code)
3136 CASE_CONVERT:
3137 case FLOAT_EXPR:
3138 /* The opcode is changed to BRIG_OPCODE_CVT if BRIG types
3139 needs a conversion. */
3140 opcode = BRIG_OPCODE_MOV;
3141 break;
3143 case PLUS_EXPR:
3144 case POINTER_PLUS_EXPR:
3145 opcode = BRIG_OPCODE_ADD;
3146 break;
3147 case MINUS_EXPR:
3148 opcode = BRIG_OPCODE_SUB;
3149 break;
3150 case MULT_EXPR:
3151 opcode = BRIG_OPCODE_MUL;
3152 break;
3153 case MULT_HIGHPART_EXPR:
3154 opcode = BRIG_OPCODE_MULHI;
3155 break;
3156 case RDIV_EXPR:
3157 case TRUNC_DIV_EXPR:
3158 case EXACT_DIV_EXPR:
3159 opcode = BRIG_OPCODE_DIV;
3160 break;
3161 case CEIL_DIV_EXPR:
3162 case FLOOR_DIV_EXPR:
3163 case ROUND_DIV_EXPR:
3164 HSA_SORRY_AT (gimple_location (assign),
3165 "support for HSA does not implement CEIL_DIV_EXPR, "
3166 "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
3167 return;
3168 case TRUNC_MOD_EXPR:
3169 opcode = BRIG_OPCODE_REM;
3170 break;
3171 case CEIL_MOD_EXPR:
3172 case FLOOR_MOD_EXPR:
3173 case ROUND_MOD_EXPR:
3174 HSA_SORRY_AT (gimple_location (assign),
3175 "support for HSA does not implement CEIL_MOD_EXPR, "
3176 "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
3177 return;
3178 case NEGATE_EXPR:
3179 opcode = BRIG_OPCODE_NEG;
3180 break;
3181 case MIN_EXPR:
3182 opcode = BRIG_OPCODE_MIN;
3183 break;
3184 case MAX_EXPR:
3185 opcode = BRIG_OPCODE_MAX;
3186 break;
3187 case ABS_EXPR:
3188 opcode = BRIG_OPCODE_ABS;
3189 break;
3190 case LSHIFT_EXPR:
3191 opcode = BRIG_OPCODE_SHL;
3192 break;
3193 case RSHIFT_EXPR:
3194 opcode = BRIG_OPCODE_SHR;
3195 break;
3196 case LROTATE_EXPR:
3197 case RROTATE_EXPR:
3199 hsa_insn_basic *insn = NULL;
3200 int code1 = code == LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3201 int code2 = code != LROTATE_EXPR ? BRIG_OPCODE_SHL : BRIG_OPCODE_SHR;
3202 BrigType16_t btype = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
3203 true);
3205 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3206 hsa_op_reg *op1 = new hsa_op_reg (btype);
3207 hsa_op_reg *op2 = new hsa_op_reg (btype);
3208 hsa_op_with_type *shift1 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3210 tree type = TREE_TYPE (rhs2);
3211 unsigned HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (TYPE_SIZE (type));
3213 hsa_op_with_type *shift2 = NULL;
3214 if (TREE_CODE (rhs2) == INTEGER_CST)
3215 shift2 = new hsa_op_immed (bitsize - tree_to_uhwi (rhs2),
3216 BRIG_TYPE_U32);
3217 else if (TREE_CODE (rhs2) == SSA_NAME)
3219 hsa_op_reg *s = hsa_cfun->reg_for_gimple_ssa (rhs2);
3220 s = as_a <hsa_op_reg *> (s->extend_int_to_32bit (hbb));
3221 hsa_op_reg *d = new hsa_op_reg (s->m_type);
3222 hsa_op_immed *size_imm = new hsa_op_immed (bitsize, BRIG_TYPE_U32);
3224 insn = new hsa_insn_basic (3, BRIG_OPCODE_SUB, d->m_type,
3225 d, s, size_imm);
3226 hbb->append_insn (insn);
3228 shift2 = d;
3230 else
3231 gcc_unreachable ();
3233 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3234 gen_hsa_binary_operation (code1, op1, src, shift1, hbb);
3235 gen_hsa_binary_operation (code2, op2, src, shift2, hbb);
3236 gen_hsa_binary_operation (BRIG_OPCODE_OR, dest, op1, op2, hbb);
3238 return;
3240 case BIT_IOR_EXPR:
3241 opcode = BRIG_OPCODE_OR;
3242 break;
3243 case BIT_XOR_EXPR:
3244 opcode = BRIG_OPCODE_XOR;
3245 break;
3246 case BIT_AND_EXPR:
3247 opcode = BRIG_OPCODE_AND;
3248 break;
3249 case BIT_NOT_EXPR:
3250 opcode = BRIG_OPCODE_NOT;
3251 break;
3252 case FIX_TRUNC_EXPR:
3254 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3255 hsa_op_with_type *v = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3257 if (hsa_needs_cvt (dest->m_type, v->m_type))
3259 hsa_op_reg *tmp = new hsa_op_reg (v->m_type);
3261 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3262 tmp->m_type, tmp, v);
3263 hbb->append_insn (insn);
3265 hsa_insn_basic *cvtinsn = new hsa_insn_cvt (dest, tmp);
3266 hbb->append_insn (cvtinsn);
3268 else
3270 hsa_insn_basic *insn = new hsa_insn_basic (2, BRIG_OPCODE_TRUNC,
3271 dest->m_type, dest, v);
3272 hbb->append_insn (insn);
3275 return;
3277 opcode = BRIG_OPCODE_TRUNC;
3278 break;
3280 case LT_EXPR:
3281 case LE_EXPR:
3282 case GT_EXPR:
3283 case GE_EXPR:
3284 case EQ_EXPR:
3285 case NE_EXPR:
3286 case UNORDERED_EXPR:
3287 case ORDERED_EXPR:
3288 case UNLT_EXPR:
3289 case UNLE_EXPR:
3290 case UNGT_EXPR:
3291 case UNGE_EXPR:
3292 case UNEQ_EXPR:
3293 case LTGT_EXPR:
3295 hsa_op_reg *dest
3296 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3298 gen_hsa_cmp_insn_from_gimple (code, rhs1, rhs2, dest, hbb);
3299 return;
3301 case COND_EXPR:
3303 hsa_op_reg *dest
3304 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3305 hsa_op_with_type *ctrl = NULL;
3306 tree cond = rhs1;
3308 if (CONSTANT_CLASS_P (cond) || TREE_CODE (cond) == SSA_NAME)
3309 ctrl = hsa_reg_or_immed_for_gimple_op (cond, hbb);
3310 else
3312 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
3314 gen_hsa_cmp_insn_from_gimple (TREE_CODE (cond),
3315 TREE_OPERAND (cond, 0),
3316 TREE_OPERAND (cond, 1),
3317 r, hbb);
3319 ctrl = r;
3322 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3323 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3324 op2 = op2->extend_int_to_32bit (hbb);
3325 op3 = op3->extend_int_to_32bit (hbb);
3327 BrigType16_t type = hsa_extend_inttype_to_32bit (dest->m_type);
3328 BrigType16_t utype = hsa_unsigned_type_for_type (type);
3329 if (is_a <hsa_op_immed *> (op2))
3330 op2->m_type = utype;
3331 if (is_a <hsa_op_immed *> (op3))
3332 op3->m_type = utype;
3334 hsa_insn_basic *insn
3335 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV,
3336 hsa_bittype_for_type (type),
3337 NULL, ctrl, op2, op3);
3339 hbb->append_insn (insn);
3340 insn->set_output_in_type (dest, 0, hbb);
3341 return;
3343 case COMPLEX_EXPR:
3345 hsa_op_reg *dest
3346 = hsa_cfun->reg_for_gimple_ssa (gimple_assign_lhs (assign));
3347 hsa_op_with_type *rhs1_reg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3348 rhs1_reg = rhs1_reg->extend_int_to_32bit (hbb);
3349 hsa_op_with_type *rhs2_reg = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
3350 rhs2_reg = rhs2_reg->extend_int_to_32bit (hbb);
3352 if (hsa_seen_error ())
3353 return;
3355 BrigType16_t src_type = hsa_bittype_for_type (rhs1_reg->m_type);
3356 rhs1_reg = rhs1_reg->get_in_type (src_type, hbb);
3357 rhs2_reg = rhs2_reg->get_in_type (src_type, hbb);
3359 hsa_insn_packed *insn
3360 = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type, src_type,
3361 dest, rhs1_reg, rhs2_reg);
3362 hbb->append_insn (insn);
3364 return;
3366 default:
3367 /* Implement others as we come across them. */
3368 HSA_SORRY_ATV (gimple_location (assign),
3369 "support for HSA does not implement operation %s",
3370 get_tree_code_name (code));
3371 return;
3375 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3376 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
3377 hsa_op_with_type *op2
3378 = rhs2 ? hsa_reg_or_immed_for_gimple_op (rhs2, hbb) : NULL;
3380 if (hsa_seen_error ())
3381 return;
3383 switch (rhs_class)
3385 case GIMPLE_TERNARY_RHS:
3387 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
3388 op3 = op3->extend_int_to_32bit (hbb);
3389 hsa_insn_basic *insn = new hsa_insn_basic (4, opcode, dest->m_type, dest,
3390 op1, op2, op3);
3391 hbb->append_insn (insn);
3393 return;
3395 case GIMPLE_BINARY_RHS:
3396 gen_hsa_binary_operation (opcode, dest, op1, op2, hbb);
3397 break;
3399 case GIMPLE_UNARY_RHS:
3400 gen_hsa_unary_operation (opcode, dest, op1, hbb);
3401 break;
3402 default:
3403 gcc_unreachable ();
3407 /* Generate HSA instructions for a given gimple condition statement COND.
3408 Instructions will be appended to HBB, which also needs to be the
3409 corresponding structure to the basic_block of COND. */
3411 static void
3412 gen_hsa_insns_for_cond_stmt (gimple *cond, hsa_bb *hbb)
3414 hsa_op_reg *ctrl = new hsa_op_reg (BRIG_TYPE_B1);
3415 hsa_insn_cbr *cbr;
3417 gen_hsa_cmp_insn_from_gimple (gimple_cond_code (cond),
3418 gimple_cond_lhs (cond),
3419 gimple_cond_rhs (cond),
3420 ctrl, hbb);
3422 cbr = new hsa_insn_cbr (ctrl);
3423 hbb->append_insn (cbr);
3426 /* Maximum number of elements in a jump table for an HSA SBR instruction. */
3428 #define HSA_MAXIMUM_SBR_LABELS 16
3430 /* Return lowest value of a switch S that is handled in a non-default
3431 label. */
3433 static tree
3434 get_switch_low (gswitch *s)
3436 unsigned labels = gimple_switch_num_labels (s);
3437 gcc_checking_assert (labels >= 1);
3439 return CASE_LOW (gimple_switch_label (s, 1));
3442 /* Return highest value of a switch S that is handled in a non-default
3443 label. */
3445 static tree
3446 get_switch_high (gswitch *s)
3448 unsigned labels = gimple_switch_num_labels (s);
3450 /* Compare last label to maximum number of labels. */
3451 tree label = gimple_switch_label (s, labels - 1);
3452 tree low = CASE_LOW (label);
3453 tree high = CASE_HIGH (label);
3455 return high != NULL_TREE ? high : low;
3458 static tree
3459 get_switch_size (gswitch *s)
3461 return int_const_binop (MINUS_EXPR, get_switch_high (s), get_switch_low (s));
3464 /* Generate HSA instructions for a given gimple switch.
3465 Instructions will be appended to HBB. */
3467 static void
3468 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
3470 gimple_stmt_iterator it = gsi_for_stmt (s);
3471 gsi_prev (&it);
3473 /* Create preambule that verifies that index - lowest_label >= 0. */
3474 edge e = split_block (hbb->m_bb, gsi_stmt (it));
3475 e->flags &= ~EDGE_FALLTHRU;
3476 e->flags |= EDGE_TRUE_VALUE;
3478 tree index_tree = gimple_switch_index (s);
3479 tree lowest = get_switch_low (s);
3480 tree highest = get_switch_high (s);
3482 hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
3483 index = as_a <hsa_op_reg *> (index->extend_int_to_32bit (hbb));
3485 hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
3486 hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest, true);
3487 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
3488 cmp1_reg, index, cmp1_immed));
3490 hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
3491 hsa_op_immed *cmp2_immed = new hsa_op_immed (highest, true);
3492 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
3493 cmp2_reg, index, cmp2_immed));
3495 hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
3496 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
3497 cmp_reg, cmp1_reg, cmp2_reg));
3499 hbb->append_insn (new hsa_insn_cbr (cmp_reg));
3501 basic_block default_label_bb = gimple_switch_default_bb (cfun, s);
3503 if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
3505 default_label_bb = split_edge (find_edge (e->dest, default_label_bb));
3506 hsa_init_new_bb (default_label_bb);
3509 make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
3511 hsa_cfun->m_modified_cfg = true;
3513 /* Basic block with the SBR instruction. */
3514 hbb = hsa_init_new_bb (e->dest);
3516 hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
3517 hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
3518 sub_index, index,
3519 new hsa_op_immed (lowest, true)));
3521 hsa_op_base *tmp = sub_index->get_in_type (BRIG_TYPE_U64, hbb);
3522 sub_index = as_a <hsa_op_reg *> (tmp);
3523 unsigned labels = gimple_switch_num_labels (s);
3524 unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
3526 hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
3528 /* Prepare array with default label destination. */
3529 for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
3530 sbr->m_jump_table.safe_push (default_label_bb);
3532 /* Iterate all labels and fill up the jump table. */
3533 for (unsigned i = 1; i < labels; i++)
3535 tree label = gimple_switch_label (s, i);
3536 basic_block bb = label_to_block (cfun, CASE_LABEL (label));
3538 unsigned HOST_WIDE_INT sub_low
3539 = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
3541 unsigned HOST_WIDE_INT sub_high = sub_low;
3542 tree high = CASE_HIGH (label);
3543 if (high != NULL)
3544 sub_high = tree_to_uhwi (int_const_binop (MINUS_EXPR, high, lowest));
3546 for (unsigned HOST_WIDE_INT j = sub_low; j <= sub_high; j++)
3547 sbr->m_jump_table[j] = bb;
3550 hbb->append_insn (sbr);
3553 /* Verify that the function DECL can be handled by HSA. */
3555 static void
3556 verify_function_arguments (tree decl)
3558 tree type = TREE_TYPE (decl);
3559 if (DECL_STATIC_CHAIN (decl))
3561 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3562 "HSA does not support nested functions: %qD", decl);
3563 return;
3565 else if (!TYPE_ARG_TYPES (type) || stdarg_p (type))
3567 HSA_SORRY_ATV (EXPR_LOCATION (decl),
3568 "HSA does not support functions with variadic arguments "
3569 "(or unknown return type): %qD", decl);
3570 return;
3574 /* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL,
3575 return ACTUAL_ARG_TYPE. */
3577 static BrigType16_t
3578 get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type)
3580 if (formal_arg_type == NULL)
3581 return actual_arg_type;
3583 BrigType16_t decl_type
3584 = hsa_type_for_scalar_tree_type (formal_arg_type, false);
3585 return mem_type_for_type (decl_type);
3588 /* Generate HSA instructions for a direct call instruction.
3589 Instructions will be appended to HBB, which also needs to be the
3590 corresponding structure to the basic_block of STMT.
3591 If ASSIGN_LHS is false, do not copy HSA function result argument into the
3592 corresponding HSA representation of the gimple statement LHS. */
3594 static void
3595 gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb,
3596 bool assign_lhs = true)
3598 tree decl = gimple_call_fndecl (stmt);
3599 verify_function_arguments (decl);
3600 if (hsa_seen_error ())
3601 return;
3603 hsa_insn_call *call_insn = new hsa_insn_call (decl);
3604 hsa_cfun->m_called_functions.safe_push (call_insn->m_called_function);
3606 /* Argument block start. */
3607 hsa_insn_arg_block *arg_start
3608 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3609 hbb->append_insn (arg_start);
3611 tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
3613 /* Preparation of arguments that will be passed to function. */
3614 const unsigned args = gimple_call_num_args (stmt);
3615 for (unsigned i = 0; i < args; ++i)
3617 tree parm = gimple_call_arg (stmt, (int)i);
3618 tree parm_decl_type = parm_type_chain != NULL_TREE
3619 ? TREE_VALUE (parm_type_chain) : NULL_TREE;
3620 hsa_op_address *addr;
3622 if (AGGREGATE_TYPE_P (TREE_TYPE (parm)))
3624 addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3625 BrigAlignment8_t align;
3626 hsa_op_address *src = gen_hsa_addr_with_align (parm, hbb, &align);
3627 gen_hsa_memory_copy (hbb, addr, src,
3628 addr->m_symbol->total_byte_size (), align);
3630 else
3632 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3634 if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type))
3636 HSA_SORRY_AT (gimple_location (stmt),
3637 "support for HSA does not implement an aggregate "
3638 "formal argument in a function call, while actual "
3639 "argument is not an aggregate");
3640 return;
3643 BrigType16_t formal_arg_type
3644 = get_format_argument_type (parm_decl_type, src->m_type);
3645 if (hsa_seen_error ())
3646 return;
3648 if (src->m_type != formal_arg_type)
3649 src = src->get_in_type (formal_arg_type, hbb);
3651 addr
3652 = gen_hsa_addr_for_arg (parm_decl_type != NULL_TREE ?
3653 parm_decl_type: TREE_TYPE (parm), i);
3654 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type,
3655 src, addr);
3657 hbb->append_insn (mem);
3660 call_insn->m_input_args.safe_push (addr->m_symbol);
3661 if (parm_type_chain)
3662 parm_type_chain = TREE_CHAIN (parm_type_chain);
3665 call_insn->m_args_code_list = new hsa_op_code_list (args);
3666 hbb->append_insn (call_insn);
3668 tree result_type = TREE_TYPE (TREE_TYPE (decl));
3670 tree result = gimple_call_lhs (stmt);
3671 hsa_insn_mem *result_insn = NULL;
3672 if (!VOID_TYPE_P (result_type))
3674 hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1);
3676 /* Even if result of a function call is unused, we have to emit
3677 declaration for the result. */
3678 if (result && assign_lhs)
3680 tree lhs_type = TREE_TYPE (result);
3682 if (hsa_seen_error ())
3683 return;
3685 if (AGGREGATE_TYPE_P (lhs_type))
3687 BrigAlignment8_t align;
3688 hsa_op_address *result_addr
3689 = gen_hsa_addr_with_align (result, hbb, &align);
3690 gen_hsa_memory_copy (hbb, result_addr, addr,
3691 addr->m_symbol->total_byte_size (), align);
3693 else
3695 BrigType16_t mtype
3696 = mem_type_for_type (hsa_type_for_scalar_tree_type (lhs_type,
3697 false));
3699 hsa_op_reg *dst = hsa_cfun->reg_for_gimple_ssa (result);
3700 result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr);
3701 hbb->append_insn (result_insn);
3705 call_insn->m_output_arg = addr->m_symbol;
3706 call_insn->m_result_code_list = new hsa_op_code_list (1);
3708 else
3710 if (result)
3712 HSA_SORRY_AT (gimple_location (stmt),
3713 "support for HSA does not implement an assignment of "
3714 "return value from a void function");
3715 return;
3718 call_insn->m_result_code_list = new hsa_op_code_list (0);
3721 /* Argument block end. */
3722 hsa_insn_arg_block *arg_end
3723 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3724 hbb->append_insn (arg_end);
3727 /* Generate HSA instructions for a direct call of an internal fn.
3728 Instructions will be appended to HBB, which also needs to be the
3729 corresponding structure to the basic_block of STMT. */
3731 static void
3732 gen_hsa_insns_for_call_of_internal_fn (gimple *stmt, hsa_bb *hbb)
3734 tree lhs = gimple_call_lhs (stmt);
3735 if (!lhs)
3736 return;
3738 tree lhs_type = TREE_TYPE (lhs);
3739 tree rhs1 = gimple_call_arg (stmt, 0);
3740 tree rhs1_type = TREE_TYPE (rhs1);
3741 enum internal_fn fn = gimple_call_internal_fn (stmt);
3742 hsa_internal_fn *ifn
3743 = new hsa_internal_fn (fn, tree_to_uhwi (TYPE_SIZE (rhs1_type)));
3744 hsa_insn_call *call_insn = new hsa_insn_call (ifn);
3746 gcc_checking_assert (FLOAT_TYPE_P (rhs1_type));
3748 if (!hsa_emitted_internal_decls->find (call_insn->m_called_internal_fn))
3749 hsa_cfun->m_called_internal_fns.safe_push (call_insn->m_called_internal_fn);
3751 hsa_insn_arg_block *arg_start
3752 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn);
3753 hbb->append_insn (arg_start);
3755 unsigned num_args = gimple_call_num_args (stmt);
3757 /* Function arguments. */
3758 for (unsigned i = 0; i < num_args; i++)
3760 tree parm = gimple_call_arg (stmt, (int)i);
3761 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb);
3763 hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i);
3764 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, src->m_type,
3765 src, addr);
3767 call_insn->m_input_args.safe_push (addr->m_symbol);
3768 hbb->append_insn (mem);
3771 call_insn->m_args_code_list = new hsa_op_code_list (num_args);
3772 hbb->append_insn (call_insn);
3774 /* Assign returned value. */
3775 hsa_op_address *addr = gen_hsa_addr_for_arg (lhs_type, -1);
3777 call_insn->m_output_arg = addr->m_symbol;
3778 call_insn->m_result_code_list = new hsa_op_code_list (1);
3780 /* Argument block end. */
3781 hsa_insn_arg_block *arg_end
3782 = new hsa_insn_arg_block (BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, call_insn);
3783 hbb->append_insn (arg_end);
3786 /* Generate HSA instructions for a return value instruction.
3787 Instructions will be appended to HBB, which also needs to be the
3788 corresponding structure to the basic_block of STMT. */
3790 static void
3791 gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb)
3793 tree retval = gimple_return_retval (stmt);
3794 if (retval)
3796 hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg);
3798 if (AGGREGATE_TYPE_P (TREE_TYPE (retval)))
3800 BrigAlignment8_t align;
3801 hsa_op_address *retval_addr = gen_hsa_addr_with_align (retval, hbb,
3802 &align);
3803 gen_hsa_memory_copy (hbb, addr, retval_addr,
3804 hsa_cfun->m_output_arg->total_byte_size (),
3805 align);
3807 else
3809 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (retval),
3810 false);
3811 BrigType16_t mtype = mem_type_for_type (t);
3813 /* Store of return value. */
3814 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (retval, hbb);
3815 src = src->get_in_type (mtype, hbb);
3816 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src,
3817 addr);
3818 hbb->append_insn (mem);
3822 /* HSAIL return instruction emission. */
3823 hsa_insn_basic *ret = new hsa_insn_basic (0, BRIG_OPCODE_RET);
3824 hbb->append_insn (ret);
3827 /* Set OP_INDEX-th operand of the instruction to DEST, as the DEST
3828 can have a different type, conversion instructions are possibly
3829 appended to HBB. */
3831 void
3832 hsa_insn_basic::set_output_in_type (hsa_op_reg *dest, unsigned op_index,
3833 hsa_bb *hbb)
3835 gcc_checking_assert (op_output_p (op_index));
3837 if (dest->m_type == m_type)
3839 set_op (op_index, dest);
3840 return;
3843 hsa_insn_basic *insn;
3844 hsa_op_reg *tmp;
3845 if (hsa_needs_cvt (dest->m_type, m_type))
3847 tmp = new hsa_op_reg (m_type);
3848 insn = new hsa_insn_cvt (dest, tmp);
3850 else if (hsa_type_bit_size (dest->m_type) == hsa_type_bit_size (m_type))
3852 /* When output, HSA registers do not really have types, only sizes, so if
3853 the sizes match, we can use the register directly. */
3854 set_op (op_index, dest);
3855 return;
3857 else
3859 tmp = new hsa_op_reg (m_type);
3860 insn = new hsa_insn_basic (2, BRIG_OPCODE_MOV, dest->m_type,
3861 dest, tmp->get_in_type (dest->m_type, hbb));
3862 hsa_fixup_mov_insn_type (insn);
3864 set_op (op_index, tmp);
3865 hbb->append_insn (insn);
3868 /* Generate instruction OPCODE to query a property of HSA grid along the
3869 given DIMENSION. Store result into DEST and append the instruction to
3870 HBB. */
3872 static void
3873 query_hsa_grid_dim (hsa_op_reg *dest, int opcode, hsa_op_immed *dimension,
3874 hsa_bb *hbb)
3876 hsa_insn_basic *insn = new hsa_insn_basic (2, opcode, BRIG_TYPE_U32, NULL,
3877 dimension);
3878 hbb->append_insn (insn);
3879 insn->set_output_in_type (dest, 0, hbb);
3882 /* Generate instruction OPCODE to query a property of HSA grid along the given
3883 dimension which is an immediate in first argument of STMT. Store result
3884 into the register corresponding to LHS of STMT and append the instruction to
3885 HBB. */
3887 static void
3888 query_hsa_grid_dim (gimple *stmt, int opcode, hsa_bb *hbb)
3890 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3891 if (lhs == NULL_TREE)
3892 return;
3894 tree arg = gimple_call_arg (stmt, 0);
3895 unsigned HOST_WIDE_INT dim = 5;
3896 if (tree_fits_uhwi_p (arg))
3897 dim = tree_to_uhwi (arg);
3898 if (dim > 2)
3900 HSA_SORRY_AT (gimple_location (stmt),
3901 "HSA grid query dimension must be immediate constant 0, 1 "
3902 "or 2");
3903 return;
3906 hsa_op_immed *hdim = new hsa_op_immed (dim, (BrigKind16_t) BRIG_TYPE_U32);
3907 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3908 query_hsa_grid_dim (dest, opcode, hdim, hbb);
3911 /* Generate instruction OPCODE to query a property of HSA grid that is
3912 independent of any dimension. Store result into the register corresponding
3913 to LHS of STMT and append the instruction to HBB. */
3915 static void
3916 query_hsa_grid_nodim (gimple *stmt, BrigOpcode16_t opcode, hsa_bb *hbb)
3918 tree lhs = gimple_call_lhs (dyn_cast <gcall *> (stmt));
3919 if (lhs == NULL_TREE)
3920 return;
3921 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
3922 BrigType16_t brig_type = hsa_unsigned_type_for_type (dest->m_type);
3923 hsa_insn_basic *insn = new hsa_insn_basic (1, opcode, brig_type, dest);
3924 hbb->append_insn (insn);
3927 /* Emit instructions that set hsa_num_threads according to provided VALUE.
3928 Instructions are appended to basic block HBB. */
3930 static void
3931 gen_set_num_threads (tree value, hsa_bb *hbb)
3933 hbb->append_insn (new hsa_insn_comment ("omp_set_num_threads"));
3934 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (value, hbb);
3936 src = src->get_in_type (hsa_num_threads->m_type, hbb);
3937 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
3939 hsa_insn_basic *basic
3940 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type, src, addr);
3941 hbb->append_insn (basic);
3944 /* Return byte offset of a FIELD_NAME in GOMP_hsa_kernel_dispatch which
3945 is defined in plugin-hsa.c. */
3947 static HOST_WIDE_INT
3948 get_hsa_kernel_dispatch_offset (const char *field_name)
3950 tree *hsa_kernel_dispatch_type = hsa_get_kernel_dispatch_type ();
3951 if (*hsa_kernel_dispatch_type == NULL)
3953 /* Collection of information needed for a dispatch of a kernel from a
3954 kernel. Keep in sync with libgomp's plugin-hsa.c. */
3956 *hsa_kernel_dispatch_type = make_node (RECORD_TYPE);
3957 tree id_f1 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3958 get_identifier ("queue"), ptr_type_node);
3959 DECL_CHAIN (id_f1) = NULL_TREE;
3960 tree id_f2 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3961 get_identifier ("omp_data_memory"),
3962 ptr_type_node);
3963 DECL_CHAIN (id_f2) = id_f1;
3964 tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3965 get_identifier ("kernarg_address"),
3966 ptr_type_node);
3967 DECL_CHAIN (id_f3) = id_f2;
3968 tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3969 get_identifier ("object"),
3970 uint64_type_node);
3971 DECL_CHAIN (id_f4) = id_f3;
3972 tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3973 get_identifier ("signal"),
3974 uint64_type_node);
3975 DECL_CHAIN (id_f5) = id_f4;
3976 tree id_f6 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3977 get_identifier ("private_segment_size"),
3978 uint32_type_node);
3979 DECL_CHAIN (id_f6) = id_f5;
3980 tree id_f7 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3981 get_identifier ("group_segment_size"),
3982 uint32_type_node);
3983 DECL_CHAIN (id_f7) = id_f6;
3984 tree id_f8 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3985 get_identifier ("kernel_dispatch_count"),
3986 uint64_type_node);
3987 DECL_CHAIN (id_f8) = id_f7;
3988 tree id_f9 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3989 get_identifier ("debug"),
3990 uint64_type_node);
3991 DECL_CHAIN (id_f9) = id_f8;
3992 tree id_f10 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3993 get_identifier ("omp_level"),
3994 uint64_type_node);
3995 DECL_CHAIN (id_f10) = id_f9;
3996 tree id_f11 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3997 get_identifier ("children_dispatches"),
3998 ptr_type_node);
3999 DECL_CHAIN (id_f11) = id_f10;
4000 tree id_f12 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
4001 get_identifier ("omp_num_threads"),
4002 uint32_type_node);
4003 DECL_CHAIN (id_f12) = id_f11;
4006 finish_builtin_struct (*hsa_kernel_dispatch_type, "__hsa_kernel_dispatch",
4007 id_f12, NULL_TREE);
4008 TYPE_ARTIFICIAL (*hsa_kernel_dispatch_type) = 1;
4011 for (tree chain = TYPE_FIELDS (*hsa_kernel_dispatch_type);
4012 chain != NULL_TREE; chain = TREE_CHAIN (chain))
4013 if (id_equal (DECL_NAME (chain), field_name))
4014 return int_byte_position (chain);
4016 gcc_unreachable ();
4019 /* Return an HSA register that will contain number of threads for
4020 a future dispatched kernel. Instructions are added to HBB. */
4022 static hsa_op_reg *
4023 gen_num_threads_for_dispatch (hsa_bb *hbb)
4025 /* Step 1) Assign to number of threads:
4026 MIN (HSA_DEFAULT_NUM_THREADS, hsa_num_threads). */
4027 hsa_op_reg *threads = new hsa_op_reg (hsa_num_threads->m_type);
4028 hsa_op_address *addr = new hsa_op_address (hsa_num_threads);
4030 hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, threads->m_type,
4031 threads, addr));
4033 hsa_op_immed *limit = new hsa_op_immed (HSA_DEFAULT_NUM_THREADS,
4034 BRIG_TYPE_U32);
4035 hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_B1);
4036 hsa_insn_cmp * cmp
4037 = new hsa_insn_cmp (BRIG_COMPARE_LT, r->m_type, r, threads, limit);
4038 hbb->append_insn (cmp);
4040 BrigType16_t btype = hsa_bittype_for_type (threads->m_type);
4041 hsa_op_reg *tmp = new hsa_op_reg (threads->m_type);
4043 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp, r,
4044 threads, limit));
4046 /* Step 2) If the number is equal to zero,
4047 return shadow->omp_num_threads. */
4048 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4050 hsa_op_reg *shadow_thread_count = new hsa_op_reg (BRIG_TYPE_U32);
4051 addr
4052 = new hsa_op_address (shadow_reg_ptr,
4053 get_hsa_kernel_dispatch_offset ("omp_num_threads"));
4054 hsa_insn_basic *basic
4055 = new hsa_insn_mem (BRIG_OPCODE_LD, shadow_thread_count->m_type,
4056 shadow_thread_count, addr);
4057 hbb->append_insn (basic);
4059 hsa_op_reg *tmp2 = new hsa_op_reg (threads->m_type);
4060 r = new hsa_op_reg (BRIG_TYPE_B1);
4061 hsa_op_immed *imm = new hsa_op_immed (0, shadow_thread_count->m_type);
4062 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_EQ, r->m_type, r, tmp, imm));
4063 hbb->append_insn (new hsa_insn_basic (4, BRIG_OPCODE_CMOV, btype, tmp2, r,
4064 shadow_thread_count, tmp));
4066 hsa_op_base *dest = tmp2->get_in_type (BRIG_TYPE_U16, hbb);
4068 return as_a <hsa_op_reg *> (dest);
4071 /* Build OPCODE query for all three hsa dimensions, multiply them and store the
4072 result into DEST. */
4074 static void
4075 multiply_grid_dim_characteristics (hsa_op_reg *dest, int opcode, hsa_bb *hbb)
4077 hsa_op_reg *dimx = new hsa_op_reg (BRIG_TYPE_U32);
4078 query_hsa_grid_dim (dimx, opcode,
4079 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4080 hsa_op_reg *dimy = new hsa_op_reg (BRIG_TYPE_U32);
4081 query_hsa_grid_dim (dimy, opcode,
4082 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4083 hsa_op_reg *dimz = new hsa_op_reg (BRIG_TYPE_U32);
4084 query_hsa_grid_dim (dimz, opcode,
4085 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4086 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4087 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp,
4088 dimx->get_in_type (dest->m_type, hbb),
4089 dimy->get_in_type (dest->m_type, hbb), hbb);
4090 gen_hsa_binary_operation (BRIG_OPCODE_MUL, dest, tmp,
4091 dimz->get_in_type (dest->m_type, hbb), hbb);
4094 /* Emit instructions that assign number of threads to lhs of gimple STMT.
4095 Instructions are appended to basic block HBB. */
4097 static void
4098 gen_get_num_threads (gimple *stmt, hsa_bb *hbb)
4100 if (gimple_call_lhs (stmt) == NULL_TREE)
4101 return;
4103 hbb->append_insn (new hsa_insn_comment ("omp_get_num_threads"));
4104 tree lhs = gimple_call_lhs (stmt);
4105 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4106 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_CURRENTWORKGROUPSIZE,
4107 hbb);
4110 /* Emit instructions that assign number of teams to lhs of gimple STMT.
4111 Instructions are appended to basic block HBB. */
4113 static void
4114 gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
4116 if (gimple_call_lhs (stmt) == NULL_TREE)
4117 return;
4119 hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
4120 tree lhs = gimple_call_lhs (stmt);
4121 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4122 multiply_grid_dim_characteristics (dest, BRIG_OPCODE_GRIDGROUPS, hbb);
4125 /* Emit instructions that assign a team number to lhs of gimple STMT.
4126 Instructions are appended to basic block HBB. */
4128 static void
4129 gen_get_team_num (gimple *stmt, hsa_bb *hbb)
4131 if (gimple_call_lhs (stmt) == NULL_TREE)
4132 return;
4134 hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
4135 tree lhs = gimple_call_lhs (stmt);
4136 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4138 hsa_op_reg *gnum_x = new hsa_op_reg (BRIG_TYPE_U32);
4139 query_hsa_grid_dim (gnum_x, BRIG_OPCODE_GRIDGROUPS,
4140 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4141 hsa_op_reg *gnum_y = new hsa_op_reg (BRIG_TYPE_U32);
4142 query_hsa_grid_dim (gnum_y, BRIG_OPCODE_GRIDGROUPS,
4143 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4145 hsa_op_reg *gno_z = new hsa_op_reg (BRIG_TYPE_U32);
4146 query_hsa_grid_dim (gno_z, BRIG_OPCODE_WORKGROUPID,
4147 new hsa_op_immed (2, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4149 hsa_op_reg *tmp1 = new hsa_op_reg (dest->m_type);
4150 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp1,
4151 gnum_x->get_in_type (dest->m_type, hbb),
4152 gnum_y->get_in_type (dest->m_type, hbb), hbb);
4153 hsa_op_reg *tmp2 = new hsa_op_reg (dest->m_type);
4154 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp2, tmp1,
4155 gno_z->get_in_type (dest->m_type, hbb), hbb);
4157 hsa_op_reg *gno_y = new hsa_op_reg (BRIG_TYPE_U32);
4158 query_hsa_grid_dim (gno_y, BRIG_OPCODE_WORKGROUPID,
4159 new hsa_op_immed (1, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4160 hsa_op_reg *tmp3 = new hsa_op_reg (dest->m_type);
4161 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp3,
4162 gnum_x->get_in_type (dest->m_type, hbb),
4163 gno_y->get_in_type (dest->m_type, hbb), hbb);
4164 hsa_op_reg *tmp4 = new hsa_op_reg (dest->m_type);
4165 gen_hsa_binary_operation (BRIG_OPCODE_ADD, tmp4, tmp3, tmp2, hbb);
4166 hsa_op_reg *gno_x = new hsa_op_reg (BRIG_TYPE_U32);
4167 query_hsa_grid_dim (gno_x, BRIG_OPCODE_WORKGROUPID,
4168 new hsa_op_immed (0, (BrigKind16_t) BRIG_TYPE_U32), hbb);
4169 gen_hsa_binary_operation (BRIG_OPCODE_ADD, dest, tmp4,
4170 gno_x->get_in_type (dest->m_type, hbb), hbb);
4173 /* Emit instructions that get levels-var ICV to lhs of gimple STMT.
4174 Instructions are appended to basic block HBB. */
4176 static void
4177 gen_get_level (gimple *stmt, hsa_bb *hbb)
4179 if (gimple_call_lhs (stmt) == NULL_TREE)
4180 return;
4182 hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
4184 tree lhs = gimple_call_lhs (stmt);
4185 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4187 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4188 if (shadow_reg_ptr == NULL)
4190 HSA_SORRY_AT (gimple_location (stmt),
4191 "support for HSA does not implement omp_get_level called "
4192 "from a function not being inlined within a kernel");
4193 return;
4196 hsa_op_address *addr
4197 = new hsa_op_address (shadow_reg_ptr,
4198 get_hsa_kernel_dispatch_offset ("omp_level"));
4200 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64,
4201 (hsa_op_base *) NULL, addr);
4202 hbb->append_insn (mem);
4203 mem->set_output_in_type (dest, 0, hbb);
4206 /* Emit instruction that implement omp_get_max_threads of gimple STMT. */
4208 static void
4209 gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
4211 tree lhs = gimple_call_lhs (stmt);
4212 if (!lhs)
4213 return;
4215 hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
4217 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4218 hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
4219 ->get_in_type (dest->m_type, hbb);
4220 hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
4223 /* Emit instructions that implement alloca builtin gimple STMT.
4224 Instructions are appended to basic block HBB. */
4226 static void
4227 gen_hsa_alloca (gcall *call, hsa_bb *hbb)
4229 tree lhs = gimple_call_lhs (call);
4230 if (lhs == NULL_TREE)
4231 return;
4233 built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
4235 gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
4237 unsigned bit_alignment = 0;
4239 if (fn != BUILT_IN_ALLOCA)
4241 tree alignment_tree = gimple_call_arg (call, 1);
4242 if (TREE_CODE (alignment_tree) != INTEGER_CST)
4244 HSA_SORRY_ATV (gimple_location (call),
4245 "support for HSA does not implement "
4246 "__builtin_alloca_with_align with a non-constant "
4247 "alignment: %E", alignment_tree);
4250 bit_alignment = tree_to_uhwi (alignment_tree);
4253 tree rhs1 = gimple_call_arg (call, 0);
4254 hsa_op_with_type *size = hsa_reg_or_immed_for_gimple_op (rhs1, hbb)
4255 ->get_in_type (BRIG_TYPE_U32, hbb);
4256 hsa_op_with_type *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4258 hsa_op_reg *tmp
4259 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE));
4260 hsa_insn_alloca *a = new hsa_insn_alloca (tmp, size, bit_alignment);
4261 hbb->append_insn (a);
4263 hsa_insn_seg *seg
4264 = new hsa_insn_seg (BRIG_OPCODE_STOF,
4265 hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT),
4266 tmp->m_type, BRIG_SEGMENT_PRIVATE, dest, tmp);
4267 hbb->append_insn (seg);
4270 /* Emit instructions that implement clrsb builtin STMT:
4271 Returns the number of leading redundant sign bits in x, i.e. the number
4272 of bits following the most significant bit that are identical to it.
4273 There are no special cases for 0 or other values.
4274 Instructions are appended to basic block HBB. */
4276 static void
4277 gen_hsa_clrsb (gcall *call, hsa_bb *hbb)
4279 tree lhs = gimple_call_lhs (call);
4280 if (lhs == NULL_TREE)
4281 return;
4283 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4284 tree rhs1 = gimple_call_arg (call, 0);
4285 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4286 arg->extend_int_to_32bit (hbb);
4287 BrigType16_t bittype = hsa_bittype_for_type (arg->m_type);
4288 unsigned bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs1)));
4290 /* FIRSTBIT instruction is defined just for 32 and 64-bits wide integers. */
4291 gcc_checking_assert (bitsize == 32 || bitsize == 64);
4293 /* Set true to MOST_SIG if the most significant bit is set to one. */
4294 hsa_op_immed *c = new hsa_op_immed (1ul << (bitsize - 1),
4295 hsa_uint_for_bitsize (bitsize));
4297 hsa_op_reg *and_reg = new hsa_op_reg (bittype);
4298 gen_hsa_binary_operation (BRIG_OPCODE_AND, and_reg, arg, c, hbb);
4300 hsa_op_reg *most_sign = new hsa_op_reg (BRIG_TYPE_B1);
4301 hsa_insn_cmp *cmp
4302 = new hsa_insn_cmp (BRIG_COMPARE_EQ, most_sign->m_type, most_sign,
4303 and_reg, c);
4304 hbb->append_insn (cmp);
4306 /* If the most significant bit is one, negate the input. Otherwise
4307 shift the input value to left by one bit. */
4308 hsa_op_reg *arg_neg = new hsa_op_reg (arg->m_type);
4309 gen_hsa_unary_operation (BRIG_OPCODE_NEG, arg_neg, arg, hbb);
4311 hsa_op_reg *shifted_arg = new hsa_op_reg (arg->m_type);
4312 gen_hsa_binary_operation (BRIG_OPCODE_SHL, shifted_arg, arg,
4313 new hsa_op_immed (1, BRIG_TYPE_U64), hbb);
4315 /* Assign the value that can be used for FIRSTBIT instruction according
4316 to the most significant bit. */
4317 hsa_op_reg *tmp = new hsa_op_reg (bittype);
4318 hsa_insn_basic *cmov
4319 = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, bittype, tmp, most_sign,
4320 arg_neg, shifted_arg);
4321 hbb->append_insn (cmov);
4323 hsa_op_reg *leading_bits = new hsa_op_reg (BRIG_TYPE_S32);
4324 gen_hsa_unary_operation (BRIG_OPCODE_FIRSTBIT, leading_bits,
4325 tmp->get_in_type (hsa_uint_for_bitsize (bitsize),
4326 hbb), hbb);
4328 /* Set flag if the input value is equal to zero. */
4329 hsa_op_reg *is_zero = new hsa_op_reg (BRIG_TYPE_B1);
4330 cmp = new hsa_insn_cmp (BRIG_COMPARE_EQ, is_zero->m_type, is_zero, arg,
4331 new hsa_op_immed (0, arg->m_type));
4332 hbb->append_insn (cmp);
4334 /* Return the number of leading bits,
4335 or (bitsize - 1) if the input value is zero. */
4336 cmov = new hsa_insn_basic (4, BRIG_OPCODE_CMOV, BRIG_TYPE_B32, NULL, is_zero,
4337 new hsa_op_immed (bitsize - 1, BRIG_TYPE_U32),
4338 leading_bits->get_in_type (BRIG_TYPE_B32, hbb));
4339 hbb->append_insn (cmov);
4340 cmov->set_output_in_type (dest, 0, hbb);
4343 /* Emit instructions that implement ffs builtin STMT:
4344 Returns one plus the index of the least significant 1-bit of x,
4345 or if x is zero, returns zero.
4346 Instructions are appended to basic block HBB. */
4348 static void
4349 gen_hsa_ffs (gcall *call, hsa_bb *hbb)
4351 tree lhs = gimple_call_lhs (call);
4352 if (lhs == NULL_TREE)
4353 return;
4355 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4357 tree rhs1 = gimple_call_arg (call, 0);
4358 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4359 arg = arg->extend_int_to_32bit (hbb);
4361 hsa_op_reg *tmp = new hsa_op_reg (BRIG_TYPE_U32);
4362 hsa_insn_srctype *insn = new hsa_insn_srctype (2, BRIG_OPCODE_LASTBIT,
4363 tmp->m_type, arg->m_type,
4364 tmp, arg);
4365 hbb->append_insn (insn);
4367 hsa_insn_basic *addition
4368 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type, NULL, tmp,
4369 new hsa_op_immed (1, tmp->m_type));
4370 hbb->append_insn (addition);
4371 addition->set_output_in_type (dest, 0, hbb);
4374 static void
4375 gen_hsa_popcount_to_dest (hsa_op_reg *dest, hsa_op_with_type *arg, hsa_bb *hbb)
4377 gcc_checking_assert (hsa_type_integer_p (arg->m_type));
4379 if (hsa_type_bit_size (arg->m_type) < 32)
4380 arg = arg->get_in_type (BRIG_TYPE_B32, hbb);
4382 BrigType16_t srctype = hsa_bittype_for_type (arg->m_type);
4383 if (!hsa_btype_p (arg->m_type))
4384 arg = arg->get_in_type (srctype, hbb);
4386 hsa_insn_srctype *popcount
4387 = new hsa_insn_srctype (2, BRIG_OPCODE_POPCOUNT, BRIG_TYPE_U32,
4388 srctype, NULL, arg);
4389 hbb->append_insn (popcount);
4390 popcount->set_output_in_type (dest, 0, hbb);
4393 /* Emit instructions that implement parity builtin STMT:
4394 Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
4395 Instructions are appended to basic block HBB. */
4397 static void
4398 gen_hsa_parity (gcall *call, hsa_bb *hbb)
4400 tree lhs = gimple_call_lhs (call);
4401 if (lhs == NULL_TREE)
4402 return;
4404 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4405 tree rhs1 = gimple_call_arg (call, 0);
4406 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4408 hsa_op_reg *popcount = new hsa_op_reg (BRIG_TYPE_U32);
4409 gen_hsa_popcount_to_dest (popcount, arg, hbb);
4411 hsa_insn_basic *insn
4412 = new hsa_insn_basic (3, BRIG_OPCODE_REM, popcount->m_type, NULL, popcount,
4413 new hsa_op_immed (2, popcount->m_type));
4414 hbb->append_insn (insn);
4415 insn->set_output_in_type (dest, 0, hbb);
4418 /* Emit instructions that implement popcount builtin STMT.
4419 Instructions are appended to basic block HBB. */
4421 static void
4422 gen_hsa_popcount (gcall *call, hsa_bb *hbb)
4424 tree lhs = gimple_call_lhs (call);
4425 if (lhs == NULL_TREE)
4426 return;
4428 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4429 tree rhs1 = gimple_call_arg (call, 0);
4430 hsa_op_with_type *arg = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4432 gen_hsa_popcount_to_dest (dest, arg, hbb);
4435 /* Emit instructions that implement DIVMOD builtin STMT.
4436 Instructions are appended to basic block HBB. */
4438 static void
4439 gen_hsa_divmod (gcall *call, hsa_bb *hbb)
4441 tree lhs = gimple_call_lhs (call);
4442 if (lhs == NULL_TREE)
4443 return;
4445 tree rhs0 = gimple_call_arg (call, 0);
4446 tree rhs1 = gimple_call_arg (call, 1);
4448 hsa_op_with_type *arg0 = hsa_reg_or_immed_for_gimple_op (rhs0, hbb);
4449 arg0 = arg0->extend_int_to_32bit (hbb);
4450 hsa_op_with_type *arg1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4451 arg1 = arg1->extend_int_to_32bit (hbb);
4453 hsa_op_reg *dest0 = new hsa_op_reg (arg0->m_type);
4454 hsa_op_reg *dest1 = new hsa_op_reg (arg1->m_type);
4456 hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_DIV, dest0->m_type,
4457 dest0, arg0, arg1);
4458 hbb->append_insn (insn);
4459 insn = new hsa_insn_basic (3, BRIG_OPCODE_REM, dest1->m_type, dest1, arg0,
4460 arg1);
4461 hbb->append_insn (insn);
4463 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4464 BrigType16_t dst_type = hsa_extend_inttype_to_32bit (dest->m_type);
4465 BrigType16_t src_type = hsa_bittype_for_type (dest0->m_type);
4467 insn = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dst_type,
4468 src_type, NULL, dest0, dest1);
4469 hbb->append_insn (insn);
4470 insn->set_output_in_type (dest, 0, hbb);
4473 /* Emit instructions that implement FMA, FMS, FNMA or FNMS call STMT.
4474 Instructions are appended to basic block HBB. NEGATE1 is true for
4475 FNMA and FNMS. NEGATE3 is true for FMS and FNMS. */
4477 static void
4478 gen_hsa_fma (gcall *call, hsa_bb *hbb, bool negate1, bool negate3)
4480 tree lhs = gimple_call_lhs (call);
4481 if (lhs == NULL_TREE)
4482 return;
4484 tree rhs1 = gimple_call_arg (call, 0);
4485 tree rhs2 = gimple_call_arg (call, 1);
4486 tree rhs3 = gimple_call_arg (call, 2);
4488 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4489 hsa_op_with_type *op1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4490 hsa_op_with_type *op2 = hsa_reg_or_immed_for_gimple_op (rhs2, hbb);
4491 hsa_op_with_type *op3 = hsa_reg_or_immed_for_gimple_op (rhs3, hbb);
4493 if (negate1)
4495 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4496 gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op1, hbb);
4497 op1 = tmp;
4500 /* There is a native HSA instruction for scalar FMAs but not for vector
4501 ones. */
4502 if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
4504 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4505 gen_hsa_binary_operation (BRIG_OPCODE_MUL, tmp, op1, op2, hbb);
4506 gen_hsa_binary_operation (negate3 ? BRIG_OPCODE_SUB : BRIG_OPCODE_ADD,
4507 dest, tmp, op3, hbb);
4509 else
4511 if (negate3)
4513 hsa_op_reg *tmp = new hsa_op_reg (dest->m_type);
4514 gen_hsa_unary_operation (BRIG_OPCODE_NEG, tmp, op3, hbb);
4515 op3 = tmp;
4517 hsa_insn_basic *insn = new hsa_insn_basic (4, BRIG_OPCODE_MAD,
4518 dest->m_type, dest,
4519 op1, op2, op3);
4520 hbb->append_insn (insn);
4524 /* Set VALUE to a shadow kernel debug argument and append a new instruction
4525 to HBB basic block. */
4527 static void
4528 set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
4530 hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
4531 if (shadow_reg_ptr == NULL)
4532 return;
4534 hsa_op_address *addr
4535 = new hsa_op_address (shadow_reg_ptr,
4536 get_hsa_kernel_dispatch_offset ("debug"));
4537 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, BRIG_TYPE_U64, value,
4538 addr);
4539 hbb->append_insn (mem);
4542 void
4543 omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
4545 if (m_sorry)
4547 if (m_warning_message)
4548 HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
4549 else
4550 HSA_SORRY_ATV (gimple_location (stmt),
4551 "Support for HSA does not implement calls to %s\n",
4552 m_name);
4554 else if (m_warning_message != NULL)
4555 warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
4557 if (m_return_value != NULL)
4559 tree lhs = gimple_call_lhs (stmt);
4560 if (!lhs)
4561 return;
4563 hbb->append_insn (new hsa_insn_comment (m_name));
4565 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4566 hsa_op_with_type *op = m_return_value->get_in_type (dest->m_type, hbb);
4567 hsa_build_append_simple_mov (dest, op, hbb);
4571 /* If STMT is a call of a known library function, generate code to perform
4572 it and return true. */
4574 static bool
4575 gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
4577 bool handled = false;
4578 const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
4580 char *copy = NULL;
4581 size_t len = strlen (name);
4582 if (len > 0 && name[len - 1] == '_')
4584 copy = XNEWVEC (char, len + 1);
4585 strcpy (copy, name);
4586 copy[len - 1] = '\0';
4587 name = copy;
4590 /* Handle omp_* routines. */
4591 if (strstr (name, "omp_") == name)
4593 hsa_init_simple_builtins ();
4594 omp_simple_builtin *builtin = omp_simple_builtins->get (name);
4595 if (builtin)
4597 builtin->generate (stmt, hbb);
4598 return true;
4601 handled = true;
4602 if (strcmp (name, "omp_set_num_threads") == 0)
4603 gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
4604 else if (strcmp (name, "omp_get_thread_num") == 0)
4606 hbb->append_insn (new hsa_insn_comment (name));
4607 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
4609 else if (strcmp (name, "omp_get_num_threads") == 0)
4611 hbb->append_insn (new hsa_insn_comment (name));
4612 gen_get_num_threads (stmt, hbb);
4614 else if (strcmp (name, "omp_get_num_teams") == 0)
4615 gen_get_num_teams (stmt, hbb);
4616 else if (strcmp (name, "omp_get_team_num") == 0)
4617 gen_get_team_num (stmt, hbb);
4618 else if (strcmp (name, "omp_get_level") == 0)
4619 gen_get_level (stmt, hbb);
4620 else if (strcmp (name, "omp_get_active_level") == 0)
4621 gen_get_level (stmt, hbb);
4622 else if (strcmp (name, "omp_in_parallel") == 0)
4623 gen_get_level (stmt, hbb);
4624 else if (strcmp (name, "omp_get_max_threads") == 0)
4625 gen_get_max_threads (stmt, hbb);
4626 else
4627 handled = false;
4629 if (handled)
4631 if (copy)
4632 free (copy);
4633 return true;
4637 if (strcmp (name, "__hsa_set_debug_value") == 0)
4639 handled = true;
4640 if (hsa_cfun->has_shadow_reg_p ())
4642 tree rhs1 = gimple_call_arg (stmt, 0);
4643 hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
4645 src = src->get_in_type (BRIG_TYPE_U64, hbb);
4646 set_debug_value (hbb, src);
4650 if (copy)
4651 free (copy);
4652 return handled;
4655 /* Helper functions to create a single unary HSA operations out of calls to
4656 builtins. OPCODE is the HSA operation to be generated. STMT is a gimple
4657 call to a builtin. HBB is the HSA BB to which the instruction should be
4658 added. Note that nothing will be created if STMT does not have a LHS. */
4660 static void
4661 gen_hsa_unaryop_for_builtin (BrigOpcode opcode, gimple *stmt, hsa_bb *hbb)
4663 tree lhs = gimple_call_lhs (stmt);
4664 if (!lhs)
4665 return;
4666 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
4667 hsa_op_with_type *op
4668 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4669 gen_hsa_unary_operation (opcode, dest, op, hbb);
4672 /* Helper functions to create a call to standard library if LHS of the
4673 STMT is used. HBB is the HSA BB to which the instruction should be
4674 added. */
4676 static void
4677 gen_hsa_unaryop_builtin_call (gimple *stmt, hsa_bb *hbb)
4679 tree lhs = gimple_call_lhs (stmt);
4680 if (!lhs)
4681 return;
4683 if (gimple_call_internal_p (stmt))
4684 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
4685 else
4686 gen_hsa_insns_for_direct_call (stmt, hbb);
4689 /* Helper functions to create a single unary HSA operations out of calls to
4690 builtins (if unsafe math optimizations are enable). Otherwise, create
4691 a call to standard library function.
4692 OPCODE is the HSA operation to be generated. STMT is a gimple
4693 call to a builtin. HBB is the HSA BB to which the instruction should be
4694 added. Note that nothing will be created if STMT does not have a LHS. */
4696 static void
4697 gen_hsa_unaryop_or_call_for_builtin (BrigOpcode opcode, gimple *stmt,
4698 hsa_bb *hbb)
4700 if (flag_unsafe_math_optimizations)
4701 gen_hsa_unaryop_for_builtin (opcode, stmt, hbb);
4702 else
4703 gen_hsa_unaryop_builtin_call (stmt, hbb);
4706 /* Generate HSA address corresponding to a value VAL (as opposed to a memory
4707 reference tree), for example an SSA_NAME or an ADDR_EXPR. HBB is the HSA BB
4708 to which the instruction should be added. */
4710 static hsa_op_address *
4711 get_address_from_value (tree val, hsa_bb *hbb)
4713 switch (TREE_CODE (val))
4715 case SSA_NAME:
4717 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4718 hsa_op_base *reg
4719 = hsa_cfun->reg_for_gimple_ssa (val)->get_in_type (addrtype, hbb);
4720 return new hsa_op_address (NULL, as_a <hsa_op_reg *> (reg), 0);
4722 case ADDR_EXPR:
4723 return gen_hsa_addr (TREE_OPERAND (val, 0), hbb);
4725 case INTEGER_CST:
4726 if (tree_fits_shwi_p (val))
4727 return new hsa_op_address (NULL, NULL, tree_to_shwi (val));
4728 /* fall-through */
4730 default:
4731 HSA_SORRY_ATV (EXPR_LOCATION (val),
4732 "support for HSA does not implement memory access to %E",
4733 val);
4734 return new hsa_op_address (NULL, NULL, 0);
4738 /* Expand assignment of a result of a string BUILTIN to DST.
4739 Size of the operation is N bytes, where instructions
4740 will be append to HBB. */
4742 static void
4743 expand_lhs_of_string_op (gimple *stmt,
4744 unsigned HOST_WIDE_INT n, hsa_bb *hbb,
4745 enum built_in_function builtin)
4747 /* If LHS is expected, we need to emit a PHI instruction. */
4748 tree lhs = gimple_call_lhs (stmt);
4749 if (!lhs)
4750 return;
4752 hsa_op_reg *lhs_reg = hsa_cfun->reg_for_gimple_ssa (lhs);
4754 hsa_op_with_type *dst_reg
4755 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
4756 hsa_op_with_type *tmp;
4758 switch (builtin)
4760 case BUILT_IN_MEMPCPY:
4762 tmp = new hsa_op_reg (dst_reg->m_type);
4763 hsa_insn_basic *add
4764 = new hsa_insn_basic (3, BRIG_OPCODE_ADD, tmp->m_type,
4765 tmp, dst_reg,
4766 new hsa_op_immed (n, dst_reg->m_type));
4767 hbb->append_insn (add);
4768 break;
4770 case BUILT_IN_MEMCPY:
4771 case BUILT_IN_MEMSET:
4772 tmp = dst_reg;
4773 break;
4774 default:
4775 gcc_unreachable ();
4778 hbb->append_insn (new hsa_insn_basic (2, BRIG_OPCODE_MOV, lhs_reg->m_type,
4779 lhs_reg, tmp));
4782 #define HSA_MEMORY_BUILTINS_LIMIT 128
4784 /* Expand a string builtin (from a gimple STMT) in a way that
4785 according to MISALIGNED_FLAG we process either direct emission
4786 (a bunch of memory load and store instructions), or we emit a function call
4787 of a library function (for instance 'memcpy'). Actually, a basic block
4788 for direct emission is just prepared, where caller is responsible
4789 for emission of corresponding instructions.
4790 All instruction are appended to HBB. */
4792 hsa_bb *
4793 expand_string_operation_builtin (gimple *stmt, hsa_bb *hbb,
4794 hsa_op_reg *misaligned_flag)
4796 edge e = split_block (hbb->m_bb, stmt);
4797 basic_block condition_bb = e->src;
4798 hbb->append_insn (new hsa_insn_cbr (misaligned_flag));
4800 /* Prepare the control flow. */
4801 edge condition_edge = EDGE_SUCC (condition_bb, 0);
4802 basic_block call_bb = split_edge (condition_edge);
4804 basic_block expanded_bb = split_edge (EDGE_SUCC (call_bb, 0));
4805 basic_block cont_bb = EDGE_SUCC (expanded_bb, 0)->dest;
4806 basic_block merge_bb = split_edge (EDGE_PRED (cont_bb, 0));
4808 condition_edge->flags &= ~EDGE_FALLTHRU;
4809 condition_edge->flags |= EDGE_TRUE_VALUE;
4810 make_edge (condition_bb, expanded_bb, EDGE_FALSE_VALUE);
4812 redirect_edge_succ (EDGE_SUCC (call_bb, 0), merge_bb);
4814 hsa_cfun->m_modified_cfg = true;
4816 hsa_init_new_bb (expanded_bb);
4818 /* Slow path: function call. */
4819 gen_hsa_insns_for_direct_call (stmt, hsa_init_new_bb (call_bb), false);
4821 return hsa_bb_for_bb (expanded_bb);
4824 /* Expand a memory copy BUILTIN (BUILT_IN_MEMCPY, BUILT_IN_MEMPCPY) from
4825 a gimple STMT and store all necessary instruction to HBB basic block. */
4827 static void
4828 expand_memory_copy (gimple *stmt, hsa_bb *hbb, enum built_in_function builtin)
4830 tree byte_size = gimple_call_arg (stmt, 2);
4832 if (!tree_fits_uhwi_p (byte_size))
4834 gen_hsa_insns_for_direct_call (stmt, hbb);
4835 return;
4838 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
4840 if (n > HSA_MEMORY_BUILTINS_LIMIT)
4842 gen_hsa_insns_for_direct_call (stmt, hbb);
4843 return;
4846 tree dst = gimple_call_arg (stmt, 0);
4847 tree src = gimple_call_arg (stmt, 1);
4849 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4850 hsa_op_address *src_addr = get_address_from_value (src, hbb);
4852 /* As gen_hsa_memory_copy relies on memory alignment
4853 greater or equal to 8 bytes, we need to verify the alignment. */
4854 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4855 hsa_op_reg *src_addr_reg = new hsa_op_reg (addrtype);
4856 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4858 convert_addr_to_flat_segment (src_addr, src_addr_reg, hbb);
4859 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4861 /* Process BIT OR for source and destination addresses. */
4862 hsa_op_reg *or_reg = new hsa_op_reg (addrtype);
4863 gen_hsa_binary_operation (BRIG_OPCODE_OR, or_reg, src_addr_reg,
4864 dst_addr_reg, hbb);
4866 /* Process BIT AND with 0x7 to identify the desired alignment
4867 of 8 bytes. */
4868 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4870 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, or_reg,
4871 new hsa_op_immed (7, addrtype), hbb);
4873 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4874 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4875 misaligned, masked,
4876 new hsa_op_immed (0, masked->m_type)));
4878 hsa_bb *native_impl_bb
4879 = expand_string_operation_builtin (stmt, hbb, misaligned);
4881 gen_hsa_memory_copy (native_impl_bb, dst_addr, src_addr, n, BRIG_ALIGNMENT_8);
4882 hsa_bb *merge_bb
4883 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4884 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4888 /* Expand a memory set BUILTIN (BUILT_IN_MEMSET, BUILT_IN_BZERO) from
4889 a gimple STMT and store all necessary instruction to HBB basic block.
4890 The operation set N bytes with a CONSTANT value. */
4892 static void
4893 expand_memory_set (gimple *stmt, unsigned HOST_WIDE_INT n,
4894 unsigned HOST_WIDE_INT constant, hsa_bb *hbb,
4895 enum built_in_function builtin)
4897 tree dst = gimple_call_arg (stmt, 0);
4898 hsa_op_address *dst_addr = get_address_from_value (dst, hbb);
4900 /* As gen_hsa_memory_set relies on memory alignment
4901 greater or equal to 8 bytes, we need to verify the alignment. */
4902 BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT);
4903 hsa_op_reg *dst_addr_reg = new hsa_op_reg (addrtype);
4904 convert_addr_to_flat_segment (dst_addr, dst_addr_reg, hbb);
4906 /* Process BIT AND with 0x7 to identify the desired alignment
4907 of 8 bytes. */
4908 hsa_op_reg *masked = new hsa_op_reg (addrtype);
4910 gen_hsa_binary_operation (BRIG_OPCODE_AND, masked, dst_addr_reg,
4911 new hsa_op_immed (7, addrtype), hbb);
4913 hsa_op_reg *misaligned = new hsa_op_reg (BRIG_TYPE_B1);
4914 hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_NE, misaligned->m_type,
4915 misaligned, masked,
4916 new hsa_op_immed (0, masked->m_type)));
4918 hsa_bb *native_impl_bb
4919 = expand_string_operation_builtin (stmt, hbb, misaligned);
4921 gen_hsa_memory_set (native_impl_bb, dst_addr, constant, n, BRIG_ALIGNMENT_8);
4922 hsa_bb *merge_bb
4923 = hsa_init_new_bb (EDGE_SUCC (native_impl_bb->m_bb, 0)->dest);
4924 expand_lhs_of_string_op (stmt, n, merge_bb, builtin);
4927 /* Store into MEMORDER the memory order specified by tree T, which must be an
4928 integer constant representing a C++ memory order. If it isn't, issue an HSA
4929 sorry message using LOC and return true, otherwise return false and store
4930 the name of the requested order to *MNAME. */
4932 static bool
4933 hsa_memorder_from_tree (tree t, BrigMemoryOrder *memorder, const char **mname,
4934 location_t loc)
4936 if (!tree_fits_uhwi_p (t))
4938 HSA_SORRY_ATV (loc, "support for HSA does not implement memory model %E",
4940 return true;
4943 unsigned HOST_WIDE_INT mm = tree_to_uhwi (t);
4944 switch (mm & MEMMODEL_BASE_MASK)
4946 case MEMMODEL_RELAXED:
4947 *memorder = BRIG_MEMORY_ORDER_RELAXED;
4948 *mname = "relaxed";
4949 break;
4950 case MEMMODEL_CONSUME:
4951 /* HSA does not have an equivalent, but we can use the slightly stronger
4952 ACQUIRE. */
4953 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4954 *mname = "consume";
4955 break;
4956 case MEMMODEL_ACQUIRE:
4957 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
4958 *mname = "acquire";
4959 break;
4960 case MEMMODEL_RELEASE:
4961 *memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
4962 *mname = "release";
4963 break;
4964 case MEMMODEL_ACQ_REL:
4965 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4966 *mname = "acq_rel";
4967 break;
4968 case MEMMODEL_SEQ_CST:
4969 /* Callers implementing a simple load or store need to remove the release
4970 or acquire part respectively. */
4971 *memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
4972 *mname = "seq_cst";
4973 break;
4974 default:
4976 HSA_SORRY_AT (loc, "support for HSA does not implement the specified "
4977 "memory model");
4978 return true;
4981 return false;
4984 /* Helper function to create an HSA atomic operation instruction out of calls
4985 to atomic builtins. RET_ORIG is true if the built-in is the variant that
4986 return s the value before applying operation, and false if it should return
4987 the value after applying the operation (if it returns value at all). ACODE
4988 is the atomic operation code, STMT is a gimple call to a builtin. HBB is
4989 the HSA BB to which the instruction should be added. If SIGNAL is true, the
4990 created operation will work on HSA signals rather than atomic variables. */
4992 static void
4993 gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
4994 gimple *stmt, hsa_bb *hbb, bool signal)
4996 tree lhs = gimple_call_lhs (stmt);
4998 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
4999 BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false);
5000 BrigType16_t mtype = mem_type_for_type (hsa_type);
5001 BrigMemoryOrder memorder;
5002 const char *mmname;
5004 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 2), &memorder, &mmname,
5005 gimple_location (stmt)))
5006 return;
5008 /* Certain atomic insns must have Bx memory types. */
5009 switch (acode)
5011 case BRIG_ATOMIC_LD:
5012 case BRIG_ATOMIC_ST:
5013 case BRIG_ATOMIC_AND:
5014 case BRIG_ATOMIC_OR:
5015 case BRIG_ATOMIC_XOR:
5016 case BRIG_ATOMIC_EXCH:
5017 mtype = hsa_bittype_for_type (mtype);
5018 break;
5019 default:
5020 break;
5023 hsa_op_reg *dest;
5024 int nops, opcode;
5025 if (lhs)
5027 if (ret_orig)
5028 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5029 else
5030 dest = new hsa_op_reg (hsa_type);
5031 opcode = signal ? BRIG_OPCODE_SIGNAL : BRIG_OPCODE_ATOMIC;
5032 nops = 3;
5034 else
5036 dest = NULL;
5037 opcode = signal ? BRIG_OPCODE_SIGNALNORET : BRIG_OPCODE_ATOMICNORET;
5038 nops = 2;
5041 if (acode == BRIG_ATOMIC_ST)
5043 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5044 memorder = BRIG_MEMORY_ORDER_SC_RELEASE;
5046 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5047 && memorder != BRIG_MEMORY_ORDER_SC_RELEASE
5048 && memorder != BRIG_MEMORY_ORDER_NONE)
5050 HSA_SORRY_ATV (gimple_location (stmt),
5051 "support for HSA does not implement memory model for "
5052 "ATOMIC_ST: %s", mmname);
5053 return;
5057 hsa_insn_basic *atominsn;
5058 hsa_op_base *tgt;
5059 if (signal)
5061 atominsn = new hsa_insn_signal (nops, opcode, acode, mtype, memorder);
5062 tgt = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 0), hbb);
5064 else
5066 atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, memorder);
5067 hsa_op_address *addr;
5068 addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5069 if (addr->m_symbol && addr->m_symbol->m_segment == BRIG_SEGMENT_PRIVATE)
5071 HSA_SORRY_AT (gimple_location (stmt),
5072 "HSA does not implement atomic operations in private "
5073 "segment");
5074 return;
5076 tgt = addr;
5079 hsa_op_with_type *op
5080 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5081 if (lhs)
5083 atominsn->set_op (0, dest);
5084 atominsn->set_op (1, tgt);
5085 atominsn->set_op (2, op);
5087 else
5089 atominsn->set_op (0, tgt);
5090 atominsn->set_op (1, op);
5093 hbb->append_insn (atominsn);
5095 /* HSA does not natively support the variants that return the modified value,
5096 so re-do the operation again non-atomically if that is what was
5097 requested. */
5098 if (lhs && !ret_orig)
5100 int arith;
5101 switch (acode)
5103 case BRIG_ATOMIC_ADD:
5104 arith = BRIG_OPCODE_ADD;
5105 break;
5106 case BRIG_ATOMIC_AND:
5107 arith = BRIG_OPCODE_AND;
5108 break;
5109 case BRIG_ATOMIC_OR:
5110 arith = BRIG_OPCODE_OR;
5111 break;
5112 case BRIG_ATOMIC_SUB:
5113 arith = BRIG_OPCODE_SUB;
5114 break;
5115 case BRIG_ATOMIC_XOR:
5116 arith = BRIG_OPCODE_XOR;
5117 break;
5118 default:
5119 gcc_unreachable ();
5121 hsa_op_reg *real_dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5122 gen_hsa_binary_operation (arith, real_dest, dest, op, hbb);
5126 /* Generate HSA instructions for an internal fn.
5127 Instructions will be appended to HBB, which also needs to be the
5128 corresponding structure to the basic_block of STMT. */
5130 static void
5131 gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
5133 gcc_checking_assert (gimple_call_internal_fn (stmt));
5134 internal_fn fn = gimple_call_internal_fn (stmt);
5136 bool is_float_type_p = false;
5137 if (gimple_call_lhs (stmt) != NULL
5138 && TREE_TYPE (gimple_call_lhs (stmt)) == float_type_node)
5139 is_float_type_p = true;
5141 switch (fn)
5143 case IFN_CEIL:
5144 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5145 break;
5147 case IFN_FLOOR:
5148 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5149 break;
5151 case IFN_RINT:
5152 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5153 break;
5155 case IFN_SQRT:
5156 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5157 break;
5159 case IFN_RSQRT:
5160 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_NRSQRT, stmt, hbb);
5161 break;
5163 case IFN_TRUNC:
5164 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5165 break;
5167 case IFN_COS:
5169 if (is_float_type_p)
5170 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5171 else
5172 gen_hsa_unaryop_builtin_call (stmt, hbb);
5174 break;
5176 case IFN_EXP2:
5178 if (is_float_type_p)
5179 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5180 else
5181 gen_hsa_unaryop_builtin_call (stmt, hbb);
5183 break;
5186 case IFN_LOG2:
5188 if (is_float_type_p)
5189 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5190 else
5191 gen_hsa_unaryop_builtin_call (stmt, hbb);
5193 break;
5196 case IFN_SIN:
5198 if (is_float_type_p)
5199 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5200 else
5201 gen_hsa_unaryop_builtin_call (stmt, hbb);
5202 break;
5205 case IFN_CLRSB:
5206 gen_hsa_clrsb (stmt, hbb);
5207 break;
5209 case IFN_CLZ:
5210 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5211 break;
5213 case IFN_CTZ:
5214 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5215 break;
5217 case IFN_FFS:
5218 gen_hsa_ffs (stmt, hbb);
5219 break;
5221 case IFN_PARITY:
5222 gen_hsa_parity (stmt, hbb);
5223 break;
5225 case IFN_POPCOUNT:
5226 gen_hsa_popcount (stmt, hbb);
5227 break;
5229 case IFN_DIVMOD:
5230 gen_hsa_divmod (stmt, hbb);
5231 break;
5233 case IFN_ACOS:
5234 case IFN_ASIN:
5235 case IFN_ATAN:
5236 case IFN_EXP:
5237 case IFN_EXP10:
5238 case IFN_EXPM1:
5239 case IFN_LOG:
5240 case IFN_LOG10:
5241 case IFN_LOG1P:
5242 case IFN_LOGB:
5243 case IFN_SIGNIFICAND:
5244 case IFN_TAN:
5245 case IFN_NEARBYINT:
5246 case IFN_ROUND:
5247 case IFN_ATAN2:
5248 case IFN_COPYSIGN:
5249 case IFN_FMOD:
5250 case IFN_POW:
5251 case IFN_REMAINDER:
5252 case IFN_SCALB:
5253 case IFN_FMIN:
5254 case IFN_FMAX:
5255 gen_hsa_insns_for_call_of_internal_fn (stmt, hbb);
5256 break;
5258 case IFN_FMA:
5259 gen_hsa_fma (stmt, hbb, false, false);
5260 break;
5262 case IFN_FMS:
5263 gen_hsa_fma (stmt, hbb, false, true);
5264 break;
5266 case IFN_FNMA:
5267 gen_hsa_fma (stmt, hbb, true, false);
5268 break;
5270 case IFN_FNMS:
5271 gen_hsa_fma (stmt, hbb, true, true);
5272 break;
5274 default:
5275 HSA_SORRY_ATV (gimple_location (stmt),
5276 "support for HSA does not implement internal function: %s",
5277 internal_fn_name (fn));
5278 break;
5282 /* Generate HSA instructions for the given call statement STMT. Instructions
5283 will be appended to HBB. */
5285 static void
5286 gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
5288 gcall *call = as_a <gcall *> (stmt);
5289 tree lhs = gimple_call_lhs (stmt);
5290 hsa_op_reg *dest;
5292 if (gimple_call_internal_p (stmt))
5294 gen_hsa_insn_for_internal_fn_call (call, hbb);
5295 return;
5298 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
5300 tree function_decl = gimple_call_fndecl (stmt);
5301 /* Prefetch pass can create type-mismatching prefetch builtin calls which
5302 fail the gimple_call_builtin_p test above. Handle them here. */
5303 if (fndecl_built_in_p (function_decl, BUILT_IN_PREFETCH))
5304 return;
5306 if (function_decl == NULL_TREE)
5308 HSA_SORRY_AT (gimple_location (stmt),
5309 "support for HSA does not implement indirect calls");
5310 return;
5313 if (hsa_callable_function_p (function_decl))
5314 gen_hsa_insns_for_direct_call (stmt, hbb);
5315 else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
5316 HSA_SORRY_AT (gimple_location (stmt),
5317 "HSA supports only calls of functions marked with pragma "
5318 "omp declare target");
5319 return;
5322 tree fndecl = gimple_call_fndecl (stmt);
5323 enum built_in_function builtin = DECL_FUNCTION_CODE (fndecl);
5324 switch (builtin)
5326 case BUILT_IN_FABS:
5327 case BUILT_IN_FABSF:
5328 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_ABS, stmt, hbb);
5329 break;
5331 case BUILT_IN_CEIL:
5332 case BUILT_IN_CEILF:
5333 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_CEIL, stmt, hbb);
5334 break;
5336 case BUILT_IN_FLOOR:
5337 case BUILT_IN_FLOORF:
5338 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FLOOR, stmt, hbb);
5339 break;
5341 case BUILT_IN_RINT:
5342 case BUILT_IN_RINTF:
5343 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_RINT, stmt, hbb);
5344 break;
5346 case BUILT_IN_SQRT:
5347 case BUILT_IN_SQRTF:
5348 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_SQRT, stmt, hbb);
5349 break;
5351 case BUILT_IN_TRUNC:
5352 case BUILT_IN_TRUNCF:
5353 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_TRUNC, stmt, hbb);
5354 break;
5356 case BUILT_IN_COS:
5357 case BUILT_IN_SIN:
5358 case BUILT_IN_EXP2:
5359 case BUILT_IN_LOG2:
5360 /* HSAIL does not provide an instruction for double argument type. */
5361 gen_hsa_unaryop_builtin_call (stmt, hbb);
5362 break;
5364 case BUILT_IN_COSF:
5365 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NCOS, stmt, hbb);
5366 break;
5368 case BUILT_IN_EXP2F:
5369 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NEXP2, stmt, hbb);
5370 break;
5372 case BUILT_IN_LOG2F:
5373 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NLOG2, stmt, hbb);
5374 break;
5376 case BUILT_IN_SINF:
5377 gen_hsa_unaryop_or_call_for_builtin (BRIG_OPCODE_NSIN, stmt, hbb);
5378 break;
5380 case BUILT_IN_CLRSB:
5381 case BUILT_IN_CLRSBL:
5382 case BUILT_IN_CLRSBLL:
5383 gen_hsa_clrsb (call, hbb);
5384 break;
5386 case BUILT_IN_CLZ:
5387 case BUILT_IN_CLZL:
5388 case BUILT_IN_CLZLL:
5389 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_FIRSTBIT, stmt, hbb);
5390 break;
5392 case BUILT_IN_CTZ:
5393 case BUILT_IN_CTZL:
5394 case BUILT_IN_CTZLL:
5395 gen_hsa_unaryop_for_builtin (BRIG_OPCODE_LASTBIT, stmt, hbb);
5396 break;
5398 case BUILT_IN_FFS:
5399 case BUILT_IN_FFSL:
5400 case BUILT_IN_FFSLL:
5401 gen_hsa_ffs (call, hbb);
5402 break;
5404 case BUILT_IN_PARITY:
5405 case BUILT_IN_PARITYL:
5406 case BUILT_IN_PARITYLL:
5407 gen_hsa_parity (call, hbb);
5408 break;
5410 case BUILT_IN_POPCOUNT:
5411 case BUILT_IN_POPCOUNTL:
5412 case BUILT_IN_POPCOUNTLL:
5413 gen_hsa_popcount (call, hbb);
5414 break;
5416 case BUILT_IN_ATOMIC_LOAD_1:
5417 case BUILT_IN_ATOMIC_LOAD_2:
5418 case BUILT_IN_ATOMIC_LOAD_4:
5419 case BUILT_IN_ATOMIC_LOAD_8:
5420 case BUILT_IN_ATOMIC_LOAD_16:
5422 BrigType16_t mtype;
5423 hsa_op_base *src;
5424 src = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5426 BrigMemoryOrder memorder;
5427 const char *mmname;
5428 if (hsa_memorder_from_tree (gimple_call_arg (stmt, 1), &memorder,
5429 &mmname, gimple_location (stmt)))
5430 return;
5432 if (memorder == BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE)
5433 memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE;
5435 if (memorder != BRIG_MEMORY_ORDER_RELAXED
5436 && memorder != BRIG_MEMORY_ORDER_SC_ACQUIRE
5437 && memorder != BRIG_MEMORY_ORDER_NONE)
5439 HSA_SORRY_ATV (gimple_location (stmt),
5440 "support for HSA does not implement "
5441 "memory model for atomic loads: %s", mmname);
5442 return;
5445 if (lhs)
5447 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (lhs),
5448 false);
5449 mtype = mem_type_for_type (t);
5450 mtype = hsa_bittype_for_type (mtype);
5451 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5453 else
5455 mtype = BRIG_TYPE_B64;
5456 dest = new hsa_op_reg (mtype);
5459 hsa_insn_basic *atominsn;
5460 atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD,
5461 mtype, memorder, dest, src);
5463 hbb->append_insn (atominsn);
5464 break;
5467 case BUILT_IN_ATOMIC_EXCHANGE_1:
5468 case BUILT_IN_ATOMIC_EXCHANGE_2:
5469 case BUILT_IN_ATOMIC_EXCHANGE_4:
5470 case BUILT_IN_ATOMIC_EXCHANGE_8:
5471 case BUILT_IN_ATOMIC_EXCHANGE_16:
5472 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_EXCH, stmt, hbb, false);
5473 break;
5474 break;
5476 case BUILT_IN_ATOMIC_FETCH_ADD_1:
5477 case BUILT_IN_ATOMIC_FETCH_ADD_2:
5478 case BUILT_IN_ATOMIC_FETCH_ADD_4:
5479 case BUILT_IN_ATOMIC_FETCH_ADD_8:
5480 case BUILT_IN_ATOMIC_FETCH_ADD_16:
5481 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ADD, stmt, hbb, false);
5482 break;
5483 break;
5485 case BUILT_IN_ATOMIC_FETCH_SUB_1:
5486 case BUILT_IN_ATOMIC_FETCH_SUB_2:
5487 case BUILT_IN_ATOMIC_FETCH_SUB_4:
5488 case BUILT_IN_ATOMIC_FETCH_SUB_8:
5489 case BUILT_IN_ATOMIC_FETCH_SUB_16:
5490 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_SUB, stmt, hbb, false);
5491 break;
5492 break;
5494 case BUILT_IN_ATOMIC_FETCH_AND_1:
5495 case BUILT_IN_ATOMIC_FETCH_AND_2:
5496 case BUILT_IN_ATOMIC_FETCH_AND_4:
5497 case BUILT_IN_ATOMIC_FETCH_AND_8:
5498 case BUILT_IN_ATOMIC_FETCH_AND_16:
5499 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_AND, stmt, hbb, false);
5500 break;
5501 break;
5503 case BUILT_IN_ATOMIC_FETCH_XOR_1:
5504 case BUILT_IN_ATOMIC_FETCH_XOR_2:
5505 case BUILT_IN_ATOMIC_FETCH_XOR_4:
5506 case BUILT_IN_ATOMIC_FETCH_XOR_8:
5507 case BUILT_IN_ATOMIC_FETCH_XOR_16:
5508 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_XOR, stmt, hbb, false);
5509 break;
5510 break;
5512 case BUILT_IN_ATOMIC_FETCH_OR_1:
5513 case BUILT_IN_ATOMIC_FETCH_OR_2:
5514 case BUILT_IN_ATOMIC_FETCH_OR_4:
5515 case BUILT_IN_ATOMIC_FETCH_OR_8:
5516 case BUILT_IN_ATOMIC_FETCH_OR_16:
5517 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_OR, stmt, hbb, false);
5518 break;
5519 break;
5521 case BUILT_IN_ATOMIC_STORE_1:
5522 case BUILT_IN_ATOMIC_STORE_2:
5523 case BUILT_IN_ATOMIC_STORE_4:
5524 case BUILT_IN_ATOMIC_STORE_8:
5525 case BUILT_IN_ATOMIC_STORE_16:
5526 /* Since there cannot be any LHS, the first parameter is meaningless. */
5527 gen_hsa_atomic_for_builtin (true, BRIG_ATOMIC_ST, stmt, hbb, false);
5528 break;
5529 break;
5531 case BUILT_IN_ATOMIC_ADD_FETCH_1:
5532 case BUILT_IN_ATOMIC_ADD_FETCH_2:
5533 case BUILT_IN_ATOMIC_ADD_FETCH_4:
5534 case BUILT_IN_ATOMIC_ADD_FETCH_8:
5535 case BUILT_IN_ATOMIC_ADD_FETCH_16:
5536 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_ADD, stmt, hbb, false);
5537 break;
5539 case BUILT_IN_ATOMIC_SUB_FETCH_1:
5540 case BUILT_IN_ATOMIC_SUB_FETCH_2:
5541 case BUILT_IN_ATOMIC_SUB_FETCH_4:
5542 case BUILT_IN_ATOMIC_SUB_FETCH_8:
5543 case BUILT_IN_ATOMIC_SUB_FETCH_16:
5544 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_SUB, stmt, hbb, false);
5545 break;
5547 case BUILT_IN_ATOMIC_AND_FETCH_1:
5548 case BUILT_IN_ATOMIC_AND_FETCH_2:
5549 case BUILT_IN_ATOMIC_AND_FETCH_4:
5550 case BUILT_IN_ATOMIC_AND_FETCH_8:
5551 case BUILT_IN_ATOMIC_AND_FETCH_16:
5552 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_AND, stmt, hbb, false);
5553 break;
5555 case BUILT_IN_ATOMIC_XOR_FETCH_1:
5556 case BUILT_IN_ATOMIC_XOR_FETCH_2:
5557 case BUILT_IN_ATOMIC_XOR_FETCH_4:
5558 case BUILT_IN_ATOMIC_XOR_FETCH_8:
5559 case BUILT_IN_ATOMIC_XOR_FETCH_16:
5560 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_XOR, stmt, hbb, false);
5561 break;
5563 case BUILT_IN_ATOMIC_OR_FETCH_1:
5564 case BUILT_IN_ATOMIC_OR_FETCH_2:
5565 case BUILT_IN_ATOMIC_OR_FETCH_4:
5566 case BUILT_IN_ATOMIC_OR_FETCH_8:
5567 case BUILT_IN_ATOMIC_OR_FETCH_16:
5568 gen_hsa_atomic_for_builtin (false, BRIG_ATOMIC_OR, stmt, hbb, false);
5569 break;
5571 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
5572 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
5573 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
5574 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
5575 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
5577 tree type = TREE_TYPE (gimple_call_arg (stmt, 1));
5578 BrigType16_t atype
5579 = hsa_bittype_for_type (hsa_type_for_scalar_tree_type (type, false));
5580 BrigMemoryOrder memorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE;
5581 hsa_insn_basic *atominsn;
5582 hsa_op_base *tgt;
5583 atominsn = new hsa_insn_atomic (4, BRIG_OPCODE_ATOMIC,
5584 BRIG_ATOMIC_CAS, atype, memorder);
5585 tgt = get_address_from_value (gimple_call_arg (stmt, 0), hbb);
5587 if (lhs != NULL)
5588 dest = hsa_cfun->reg_for_gimple_ssa (lhs);
5589 else
5590 dest = new hsa_op_reg (atype);
5592 atominsn->set_op (0, dest);
5593 atominsn->set_op (1, tgt);
5595 hsa_op_with_type *op
5596 = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 1), hbb);
5597 atominsn->set_op (2, op);
5598 op = hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb);
5599 atominsn->set_op (3, op);
5601 hbb->append_insn (atominsn);
5602 break;
5605 case BUILT_IN_HSA_WORKGROUPID:
5606 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKGROUPID, hbb);
5607 break;
5608 case BUILT_IN_HSA_WORKITEMID:
5609 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMID, hbb);
5610 break;
5611 case BUILT_IN_HSA_WORKITEMABSID:
5612 query_hsa_grid_dim (stmt, BRIG_OPCODE_WORKITEMABSID, hbb);
5613 break;
5614 case BUILT_IN_HSA_GRIDSIZE:
5615 query_hsa_grid_dim (stmt, BRIG_OPCODE_GRIDSIZE, hbb);
5616 break;
5617 case BUILT_IN_HSA_CURRENTWORKGROUPSIZE:
5618 query_hsa_grid_dim (stmt, BRIG_OPCODE_CURRENTWORKGROUPSIZE, hbb);
5619 break;
5621 case BUILT_IN_GOMP_BARRIER:
5622 hbb->append_insn (new hsa_insn_br (0, BRIG_OPCODE_BARRIER, BRIG_TYPE_NONE,
5623 BRIG_WIDTH_ALL));
5624 break;
5625 case BUILT_IN_GOMP_PARALLEL:
5626 HSA_SORRY_AT (gimple_location (stmt),
5627 "support for HSA does not implement non-gridified "
5628 "OpenMP parallel constructs.");
5629 break;
5631 case BUILT_IN_OMP_GET_THREAD_NUM:
5633 query_hsa_grid_nodim (stmt, BRIG_OPCODE_WORKITEMFLATABSID, hbb);
5634 break;
5637 case BUILT_IN_OMP_GET_NUM_THREADS:
5639 gen_get_num_threads (stmt, hbb);
5640 break;
5642 case BUILT_IN_GOMP_TEAMS:
5644 gen_set_num_threads (gimple_call_arg (stmt, 1), hbb);
5645 break;
5647 case BUILT_IN_OMP_GET_NUM_TEAMS:
5649 gen_get_num_teams (stmt, hbb);
5650 break;
5652 case BUILT_IN_OMP_GET_TEAM_NUM:
5654 gen_get_team_num (stmt, hbb);
5655 break;
5657 case BUILT_IN_MEMCPY:
5658 case BUILT_IN_MEMPCPY:
5660 expand_memory_copy (stmt, hbb, builtin);
5661 break;
5663 case BUILT_IN_MEMSET:
5665 tree c = gimple_call_arg (stmt, 1);
5667 if (TREE_CODE (c) != INTEGER_CST)
5669 gen_hsa_insns_for_direct_call (stmt, hbb);
5670 return;
5673 tree byte_size = gimple_call_arg (stmt, 2);
5675 if (!tree_fits_uhwi_p (byte_size))
5677 gen_hsa_insns_for_direct_call (stmt, hbb);
5678 return;
5681 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5683 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5685 gen_hsa_insns_for_direct_call (stmt, hbb);
5686 return;
5689 unsigned HOST_WIDE_INT constant
5690 = tree_to_uhwi (fold_convert (unsigned_char_type_node, c));
5692 expand_memory_set (stmt, n, constant, hbb, builtin);
5694 break;
5696 case BUILT_IN_BZERO:
5698 tree byte_size = gimple_call_arg (stmt, 1);
5700 if (!tree_fits_uhwi_p (byte_size))
5702 gen_hsa_insns_for_direct_call (stmt, hbb);
5703 return;
5706 unsigned HOST_WIDE_INT n = tree_to_uhwi (byte_size);
5708 if (n > HSA_MEMORY_BUILTINS_LIMIT)
5710 gen_hsa_insns_for_direct_call (stmt, hbb);
5711 return;
5714 expand_memory_set (stmt, n, 0, hbb, builtin);
5716 break;
5718 CASE_BUILT_IN_ALLOCA:
5720 gen_hsa_alloca (call, hbb);
5721 break;
5723 case BUILT_IN_PREFETCH:
5724 break;
5725 default:
5727 tree name_tree = DECL_NAME (fndecl);
5728 const char *s = IDENTIFIER_POINTER (name_tree);
5729 size_t len = strlen (s);
5730 if (len > 4 && (strncmp (s, "__builtin_GOMP_", 15) == 0))
5731 HSA_SORRY_ATV (gimple_location (stmt),
5732 "support for HSA does not implement GOMP function %s",
5734 else
5735 gen_hsa_insns_for_direct_call (stmt, hbb);
5736 return;
5741 /* Generate HSA instructions for a given gimple statement. Instructions will be
5742 appended to HBB. */
5744 static void
5745 gen_hsa_insns_for_gimple_stmt (gimple *stmt, hsa_bb *hbb)
5747 switch (gimple_code (stmt))
5749 case GIMPLE_ASSIGN:
5750 if (gimple_clobber_p (stmt))
5751 break;
5753 if (gimple_assign_single_p (stmt))
5755 tree lhs = gimple_assign_lhs (stmt);
5756 tree rhs = gimple_assign_rhs1 (stmt);
5757 gen_hsa_insns_for_single_assignment (lhs, rhs, hbb);
5759 else
5760 gen_hsa_insns_for_operation_assignment (stmt, hbb);
5761 break;
5762 case GIMPLE_RETURN:
5763 gen_hsa_insns_for_return (as_a <greturn *> (stmt), hbb);
5764 break;
5765 case GIMPLE_COND:
5766 gen_hsa_insns_for_cond_stmt (stmt, hbb);
5767 break;
5768 case GIMPLE_CALL:
5769 gen_hsa_insns_for_call (stmt, hbb);
5770 break;
5771 case GIMPLE_DEBUG:
5772 /* ??? HSA supports some debug facilities. */
5773 break;
5774 case GIMPLE_LABEL:
5776 tree label = gimple_label_label (as_a <glabel *> (stmt));
5777 if (FORCED_LABEL (label))
5778 HSA_SORRY_AT (gimple_location (stmt),
5779 "support for HSA does not implement gimple label with "
5780 "address taken");
5782 break;
5784 case GIMPLE_NOP:
5786 hbb->append_insn (new hsa_insn_basic (0, BRIG_OPCODE_NOP));
5787 break;
5789 case GIMPLE_SWITCH:
5791 gen_hsa_insns_for_switch_stmt (as_a <gswitch *> (stmt), hbb);
5792 break;
5794 default:
5795 HSA_SORRY_ATV (gimple_location (stmt),
5796 "support for HSA does not implement gimple statement %s",
5797 gimple_code_name[(int) gimple_code (stmt)]);
5801 /* Generate a HSA PHI from a gimple PHI. */
5803 static void
5804 gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb)
5806 hsa_insn_phi *hphi;
5807 unsigned count = gimple_phi_num_args (phi_stmt);
5809 hsa_op_reg *dest
5810 = hsa_cfun->reg_for_gimple_ssa (gimple_phi_result (phi_stmt));
5811 hphi = new hsa_insn_phi (count, dest);
5812 hphi->m_bb = hbb->m_bb;
5814 auto_vec <tree, 8> aexprs;
5815 auto_vec <hsa_op_reg *, 8> aregs;
5817 /* Calling split_edge when processing a PHI node messes up with the order of
5818 gimple phi node arguments (it moves the one associated with the edge to
5819 the end). We need to keep the order of edges and arguments of HSA phi
5820 node arguments consistent, so we do all required splitting as the first
5821 step, and in reverse order as to not be affected by the re-orderings. */
5822 for (unsigned j = count; j != 0; j--)
5824 unsigned i = j - 1;
5825 tree op = gimple_phi_arg_def (phi_stmt, i);
5826 if (TREE_CODE (op) != ADDR_EXPR)
5827 continue;
5829 edge e = gimple_phi_arg_edge (as_a <gphi *> (phi_stmt), i);
5830 hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e));
5831 hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0),
5832 hbb_src);
5834 hsa_op_reg *dest
5835 = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT));
5836 hsa_insn_basic *insn
5837 = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64,
5838 dest, addr);
5839 hbb_src->append_insn (insn);
5840 aexprs.safe_push (op);
5841 aregs.safe_push (dest);
5844 tree lhs = gimple_phi_result (phi_stmt);
5845 for (unsigned i = 0; i < count; i++)
5847 tree op = gimple_phi_arg_def (phi_stmt, i);
5849 if (TREE_CODE (op) == SSA_NAME)
5851 hsa_op_reg *hreg = hsa_cfun->reg_for_gimple_ssa (op);
5852 hphi->set_op (i, hreg);
5854 else
5856 gcc_assert (is_gimple_min_invariant (op));
5857 tree t = TREE_TYPE (op);
5858 if (!POINTER_TYPE_P (t)
5859 || (TREE_CODE (op) == STRING_CST
5860 && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
5861 hphi->set_op (i, new hsa_op_immed (op));
5862 else if (POINTER_TYPE_P (TREE_TYPE (lhs))
5863 && TREE_CODE (op) == INTEGER_CST)
5865 /* Handle assignment of NULL value to a pointer type. */
5866 hphi->set_op (i, new hsa_op_immed (op));
5868 else if (TREE_CODE (op) == ADDR_EXPR)
5870 hsa_op_reg *dest = NULL;
5871 for (unsigned a_idx = 0; a_idx < aexprs.length (); a_idx++)
5872 if (aexprs[a_idx] == op)
5874 dest = aregs[a_idx];
5875 break;
5877 gcc_assert (dest);
5878 hphi->set_op (i, dest);
5880 else
5882 HSA_SORRY_AT (gimple_location (phi_stmt),
5883 "support for HSA does not handle PHI nodes with "
5884 "constant address operands");
5885 return;
5890 hbb->append_phi (hphi);
5893 /* Constructor of class containing HSA-specific information about a basic
5894 block. CFG_BB is the CFG BB this HSA BB is associated with. IDX is the new
5895 index of this BB (so that the constructor does not attempt to use
5896 hsa_cfun during its construction). */
5898 hsa_bb::hsa_bb (basic_block cfg_bb, int idx)
5899 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5900 m_last_phi (NULL), m_index (idx)
5902 gcc_assert (!cfg_bb->aux);
5903 cfg_bb->aux = this;
5906 /* Constructor of class containing HSA-specific information about a basic
5907 block. CFG_BB is the CFG BB this HSA BB is associated with. */
5909 hsa_bb::hsa_bb (basic_block cfg_bb)
5910 : m_bb (cfg_bb), m_first_insn (NULL), m_last_insn (NULL), m_first_phi (NULL),
5911 m_last_phi (NULL), m_index (hsa_cfun->m_hbb_count++)
5913 gcc_assert (!cfg_bb->aux);
5914 cfg_bb->aux = this;
5917 /* Create and initialize and return a new hsa_bb structure for a given CFG
5918 basic block BB. */
5920 hsa_bb *
5921 hsa_init_new_bb (basic_block bb)
5923 void *m = obstack_alloc (&hsa_obstack, sizeof (hsa_bb));
5924 return new (m) hsa_bb (bb);
5927 /* Initialize OMP in an HSA basic block PROLOGUE. */
5929 static void
5930 init_prologue (void)
5932 if (!hsa_cfun->m_kern_p)
5933 return;
5935 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5937 /* Create a magic number that is going to be printed by libgomp. */
5938 unsigned index = hsa_get_number_decl_kernel_mappings ();
5940 /* Emit store to debug argument. */
5941 if (PARAM_VALUE (PARAM_HSA_GEN_DEBUG_STORES) > 0)
5942 set_debug_value (prologue, new hsa_op_immed (1000 + index, BRIG_TYPE_U64));
5945 /* Initialize hsa_num_threads to a default value. */
5947 static void
5948 init_hsa_num_threads (void)
5950 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5952 /* Save the default value to private variable hsa_num_threads. */
5953 hsa_insn_basic *basic
5954 = new hsa_insn_mem (BRIG_OPCODE_ST, hsa_num_threads->m_type,
5955 new hsa_op_immed (0, hsa_num_threads->m_type),
5956 new hsa_op_address (hsa_num_threads));
5957 prologue->append_insn (basic);
5960 /* Go over gimple representation and generate our internal HSA one. */
5962 static void
5963 gen_body_from_gimple ()
5965 basic_block bb;
5967 /* Verify CFG for complex edges we are unable to handle. */
5968 edge_iterator ei;
5969 edge e;
5971 FOR_EACH_BB_FN (bb, cfun)
5973 FOR_EACH_EDGE (e, ei, bb->succs)
5975 /* Verify all unsupported flags for edges that point
5976 to the same basic block. */
5977 if (e->flags & EDGE_EH)
5979 HSA_SORRY_AT (UNKNOWN_LOCATION,
5980 "support for HSA does not implement exception "
5981 "handling");
5982 return;
5987 FOR_EACH_BB_FN (bb, cfun)
5989 gimple_stmt_iterator gsi;
5990 hsa_bb *hbb = hsa_bb_for_bb (bb);
5991 if (hbb)
5992 continue;
5994 hbb = hsa_init_new_bb (bb);
5996 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5998 gen_hsa_insns_for_gimple_stmt (gsi_stmt (gsi), hbb);
5999 if (hsa_seen_error ())
6000 return;
6004 FOR_EACH_BB_FN (bb, cfun)
6006 gimple_stmt_iterator gsi;
6007 hsa_bb *hbb = hsa_bb_for_bb (bb);
6008 gcc_assert (hbb != NULL);
6010 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6011 if (!virtual_operand_p (gimple_phi_result (gsi_stmt (gsi))))
6012 gen_hsa_phi_from_gimple_phi (gsi_stmt (gsi), hbb);
6015 if (dump_file && (dump_flags & TDF_DETAILS))
6017 fprintf (dump_file, "------- Generated SSA form -------\n");
6018 dump_hsa_cfun (dump_file);
6022 static void
6023 gen_function_decl_parameters (hsa_function_representation *f,
6024 tree decl)
6026 tree parm;
6027 unsigned i;
6029 for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0;
6030 parm;
6031 parm = TREE_CHAIN (parm), i++)
6033 /* Result type if last in the tree list. */
6034 if (TREE_CHAIN (parm) == NULL)
6035 break;
6037 tree v = TREE_VALUE (parm);
6039 hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6040 BRIG_LINKAGE_NONE);
6041 arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim);
6042 arg->m_name_number = i;
6044 f->m_input_args.safe_push (arg);
6047 tree result_type = TREE_TYPE (TREE_TYPE (decl));
6048 if (!VOID_TYPE_P (result_type))
6050 f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6051 BRIG_LINKAGE_NONE);
6052 f->m_output_arg->m_type
6053 = hsa_type_for_tree_type (result_type, &f->m_output_arg->m_dim);
6054 f->m_output_arg->m_name = "res";
6058 /* Generate the vector of parameters of the HSA representation of the current
6059 function. This also includes the output parameter representing the
6060 result. */
6062 static void
6063 gen_function_def_parameters ()
6065 tree parm;
6067 hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
6069 for (parm = DECL_ARGUMENTS (cfun->decl); parm;
6070 parm = DECL_CHAIN (parm))
6072 struct hsa_symbol **slot;
6074 hsa_symbol *arg
6075 = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p
6076 ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG,
6077 BRIG_LINKAGE_FUNCTION);
6078 arg->fillup_for_decl (parm);
6080 hsa_cfun->m_input_args.safe_push (arg);
6082 if (hsa_seen_error ())
6083 return;
6085 arg->m_name = hsa_get_declaration_name (parm);
6087 /* Copy all input arguments and create corresponding private symbols
6088 for them. */
6089 hsa_symbol *private_arg;
6090 hsa_op_address *parm_addr = new hsa_op_address (arg);
6092 if (TREE_ADDRESSABLE (parm)
6093 || (!is_gimple_reg (parm) && !TREE_READONLY (parm)))
6095 private_arg = hsa_cfun->create_hsa_temporary (arg->m_type);
6096 private_arg->fillup_for_decl (parm);
6098 BrigAlignment8_t align = MIN (arg->m_align, private_arg->m_align);
6100 hsa_op_address *private_arg_addr = new hsa_op_address (private_arg);
6101 gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr,
6102 arg->total_byte_size (), align);
6104 else
6105 private_arg = arg;
6107 slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT);
6108 gcc_assert (!*slot);
6109 *slot = private_arg;
6111 if (is_gimple_reg (parm))
6113 tree ddef = ssa_default_def (cfun, parm);
6114 if (ddef && !has_zero_uses (ddef))
6116 BrigType16_t t = hsa_type_for_scalar_tree_type (TREE_TYPE (ddef),
6117 false);
6118 BrigType16_t mtype = mem_type_for_type (t);
6119 hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (ddef);
6120 hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype,
6121 dest, parm_addr);
6122 gcc_assert (!parm_addr->m_reg);
6123 prologue->append_insn (mem);
6128 if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
6130 struct hsa_symbol **slot;
6132 hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG,
6133 BRIG_LINKAGE_FUNCTION);
6134 hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl));
6136 if (hsa_seen_error ())
6137 return;
6139 hsa_cfun->m_output_arg->m_name = "res";
6140 slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg,
6141 INSERT);
6142 gcc_assert (!*slot);
6143 *slot = hsa_cfun->m_output_arg;
6147 /* Generate function representation that corresponds to
6148 a function declaration. */
6150 hsa_function_representation *
6151 hsa_generate_function_declaration (tree decl)
6153 hsa_function_representation *fun
6154 = new hsa_function_representation (decl, false, 0);
6156 fun->m_declaration_p = true;
6157 fun->m_name = get_brig_function_name (decl);
6158 gen_function_decl_parameters (fun, decl);
6160 return fun;
6164 /* Generate function representation that corresponds to
6165 an internal FN. */
6167 hsa_function_representation *
6168 hsa_generate_internal_fn_decl (hsa_internal_fn *fn)
6170 hsa_function_representation *fun = new hsa_function_representation (fn);
6172 fun->m_name = fn->name ();
6174 for (unsigned i = 0; i < fn->get_arity (); i++)
6176 hsa_symbol *arg
6177 = new hsa_symbol (fn->get_argument_type (i), BRIG_SEGMENT_ARG,
6178 BRIG_LINKAGE_NONE);
6179 arg->m_name_number = i;
6180 fun->m_input_args.safe_push (arg);
6183 fun->m_output_arg = new hsa_symbol (fn->get_argument_type (-1),
6184 BRIG_SEGMENT_ARG, BRIG_LINKAGE_NONE);
6185 fun->m_output_arg->m_name = "res";
6187 return fun;
6190 /* Return true if switch statement S can be transformed
6191 to a SBR instruction in HSAIL. */
6193 static bool
6194 transformable_switch_to_sbr_p (gswitch *s)
6196 /* Identify if a switch statement can be transformed to
6197 SBR instruction, like:
6199 sbr_u32 $s1 [@label1, @label2, @label3];
6202 tree size = get_switch_size (s);
6203 if (!tree_fits_uhwi_p (size))
6204 return false;
6206 if (tree_to_uhwi (size) > HSA_MAXIMUM_SBR_LABELS)
6207 return false;
6209 return true;
6212 /* Structure hold connection between PHI nodes and immediate
6213 values hold by there nodes. */
6215 struct phi_definition
6217 phi_definition (unsigned phi_i, unsigned label_i, tree imm):
6218 phi_index (phi_i), label_index (label_i), phi_value (imm)
6221 unsigned phi_index;
6222 unsigned label_index;
6223 tree phi_value;
6226 /* Sum slice of a vector V, starting from index START and ending
6227 at the index END - 1. */
6229 template <typename T>
6230 static
6231 T sum_slice (const auto_vec <T> &v, unsigned start, unsigned end,
6232 T zero)
6234 T s = zero;
6236 for (unsigned i = start; i < end; i++)
6237 s += v[i];
6239 return s;
6242 /* Function transforms GIMPLE SWITCH statements to a series of IF statements.
6243 Let's assume following example:
6246 switch (index)
6247 case C1:
6248 L1: hard_work_1 ();
6249 break;
6250 case C2..C3:
6251 L2: hard_work_2 ();
6252 break;
6253 default:
6254 LD: hard_work_3 ();
6255 break;
6257 The transformation encompasses following steps:
6258 1) all immediate values used by edges coming from the switch basic block
6259 are saved
6260 2) all these edges are removed
6261 3) the switch statement (in L0) is replaced by:
6262 if (index == C1)
6263 goto L1;
6264 else
6265 goto L1';
6267 4) newly created basic block Lx' is used for generation of
6268 a next condition
6269 5) else branch of the last condition goes to LD
6270 6) fix all immediate values in PHI nodes that were propagated though
6271 edges that were removed in step 2
6273 Note: if a case is made by a range C1..C2, then process
6274 following transformation:
6276 switch_cond_op1 = C1 <= index;
6277 switch_cond_op2 = index <= C2;
6278 switch_cond_and = switch_cond_op1 & switch_cond_op2;
6279 if (switch_cond_and != 0)
6280 goto Lx;
6281 else
6282 goto Ly;
6286 static bool
6287 convert_switch_statements (void)
6289 basic_block bb;
6291 bool modified_cfg = false;
6293 FOR_EACH_BB_FN (bb, cfun)
6295 gimple_stmt_iterator gsi = gsi_last_bb (bb);
6296 if (gsi_end_p (gsi))
6297 continue;
6299 gimple *stmt = gsi_stmt (gsi);
6301 if (gimple_code (stmt) == GIMPLE_SWITCH)
6303 gswitch *s = as_a <gswitch *> (stmt);
6305 /* If the switch can utilize SBR insn, skip the statement. */
6306 if (transformable_switch_to_sbr_p (s))
6307 continue;
6309 modified_cfg = true;
6311 unsigned labels = gimple_switch_num_labels (s);
6312 tree index = gimple_switch_index (s);
6313 tree index_type = TREE_TYPE (index);
6314 tree default_label = gimple_switch_default_label (s);
6315 basic_block default_label_bb
6316 = label_to_block (cfun, CASE_LABEL (default_label));
6317 basic_block cur_bb = bb;
6319 auto_vec <edge> new_edges;
6320 auto_vec <phi_definition *> phi_todo_list;
6321 auto_vec <profile_count> edge_counts;
6322 auto_vec <profile_probability> edge_probabilities;
6324 /* Investigate all labels that and PHI nodes in these edges which
6325 should be fixed after we add new collection of edges. */
6326 for (unsigned i = 0; i < labels; i++)
6328 basic_block label_bb = gimple_switch_label_bb (cfun, s, i);
6329 edge e = find_edge (bb, label_bb);
6330 edge_counts.safe_push (e->count ());
6331 edge_probabilities.safe_push (e->probability);
6332 gphi_iterator phi_gsi;
6334 /* Save PHI definitions that will be destroyed because of an edge
6335 is going to be removed. */
6336 unsigned phi_index = 0;
6337 for (phi_gsi = gsi_start_phis (e->dest);
6338 !gsi_end_p (phi_gsi); gsi_next (&phi_gsi))
6340 gphi *phi = phi_gsi.phi ();
6341 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
6343 if (gimple_phi_arg_edge (phi, j) == e)
6345 tree imm = gimple_phi_arg_def (phi, j);
6346 phi_definition *p = new phi_definition (phi_index, i,
6347 imm);
6348 phi_todo_list.safe_push (p);
6349 break;
6352 phi_index++;
6356 /* Remove all edges for the current basic block. */
6357 for (int i = EDGE_COUNT (bb->succs) - 1; i >= 0; i--)
6359 edge e = EDGE_SUCC (bb, i);
6360 remove_edge (e);
6363 /* Iterate all non-default labels. */
6364 for (unsigned i = 1; i < labels; i++)
6366 tree label = gimple_switch_label (s, i);
6367 tree low = CASE_LOW (label);
6368 tree high = CASE_HIGH (label);
6370 if (!useless_type_conversion_p (TREE_TYPE (low), index_type))
6371 low = fold_convert (index_type, low);
6373 gimple_stmt_iterator cond_gsi = gsi_last_bb (cur_bb);
6374 gimple *c = NULL;
6375 if (high)
6377 tree tmp1 = make_temp_ssa_name (boolean_type_node, NULL,
6378 "switch_cond_op1");
6380 gimple *assign1 = gimple_build_assign (tmp1, LE_EXPR, low,
6381 index);
6383 tree tmp2 = make_temp_ssa_name (boolean_type_node, NULL,
6384 "switch_cond_op2");
6386 if (!useless_type_conversion_p (TREE_TYPE (high), index_type))
6387 high = fold_convert (index_type, high);
6388 gimple *assign2 = gimple_build_assign (tmp2, LE_EXPR, index,
6389 high);
6391 tree tmp3 = make_temp_ssa_name (boolean_type_node, NULL,
6392 "switch_cond_and");
6393 gimple *assign3 = gimple_build_assign (tmp3, BIT_AND_EXPR, tmp1,
6394 tmp2);
6396 gsi_insert_before (&cond_gsi, assign1, GSI_SAME_STMT);
6397 gsi_insert_before (&cond_gsi, assign2, GSI_SAME_STMT);
6398 gsi_insert_before (&cond_gsi, assign3, GSI_SAME_STMT);
6400 tree b = constant_boolean_node (false, boolean_type_node);
6401 c = gimple_build_cond (NE_EXPR, tmp3, b, NULL, NULL);
6403 else
6404 c = gimple_build_cond (EQ_EXPR, index, low, NULL, NULL);
6406 gimple_set_location (c, gimple_location (stmt));
6408 gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
6410 basic_block label_bb = label_to_block (cfun, CASE_LABEL (label));
6411 edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
6412 profile_probability prob_sum = sum_slice <profile_probability>
6413 (edge_probabilities, i, labels, profile_probability::never ())
6414 + edge_probabilities[0];
6416 if (prob_sum.initialized_p ())
6417 new_edge->probability = edge_probabilities[i] / prob_sum;
6419 new_edges.safe_push (new_edge);
6421 if (i < labels - 1)
6423 /* Prepare another basic block that will contain
6424 next condition. */
6425 basic_block next_bb = create_empty_bb (cur_bb);
6426 if (current_loops)
6428 add_bb_to_loop (next_bb, cur_bb->loop_father);
6429 loops_state_set (LOOPS_NEED_FIXUP);
6432 edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
6433 next_edge->probability = new_edge->probability.invert ();
6434 next_bb->count = next_edge->count ();
6435 cur_bb = next_bb;
6437 else /* Link last IF statement and default label
6438 of the switch. */
6440 edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
6441 e->probability = new_edge->probability.invert ();
6442 new_edges.safe_insert (0, e);
6446 /* Restore original PHI immediate value. */
6447 for (unsigned i = 0; i < phi_todo_list.length (); i++)
6449 phi_definition *phi_def = phi_todo_list[i];
6450 edge new_edge = new_edges[phi_def->label_index];
6452 gphi_iterator it = gsi_start_phis (new_edge->dest);
6453 for (unsigned i = 0; i < phi_def->phi_index; i++)
6454 gsi_next (&it);
6456 gphi *phi = it.phi ();
6457 add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION);
6458 delete phi_def;
6461 /* Remove the original GIMPLE switch statement. */
6462 gsi_remove (&gsi, true);
6466 if (dump_file)
6467 dump_function_to_file (current_function_decl, dump_file, TDF_DETAILS);
6469 return modified_cfg;
6472 /* Expand builtins that can't be handled by HSA back-end. */
6474 static void
6475 expand_builtins ()
6477 basic_block bb;
6479 FOR_EACH_BB_FN (bb, cfun)
6481 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
6482 gsi_next (&gsi))
6484 gimple *stmt = gsi_stmt (gsi);
6486 if (gimple_code (stmt) != GIMPLE_CALL)
6487 continue;
6489 gcall *call = as_a <gcall *> (stmt);
6491 if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
6492 continue;
6494 tree fndecl = gimple_call_fndecl (stmt);
6495 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
6496 switch (fn)
6498 case BUILT_IN_CEXPF:
6499 case BUILT_IN_CEXPIF:
6500 case BUILT_IN_CEXPI:
6502 /* Similar to builtins.c (expand_builtin_cexpi), the builtin
6503 can be transformed to: cexp(I * z) = ccos(z) + I * csin(z). */
6504 tree lhs = gimple_call_lhs (stmt);
6505 tree rhs = gimple_call_arg (stmt, 0);
6506 tree rhs_type = TREE_TYPE (rhs);
6507 bool float_type_p = rhs_type == float_type_node;
6508 tree real_part = make_temp_ssa_name (rhs_type, NULL,
6509 "cexp_real_part");
6510 tree imag_part = make_temp_ssa_name (rhs_type, NULL,
6511 "cexp_imag_part");
6513 tree cos_fndecl
6514 = mathfn_built_in (rhs_type, fn == float_type_p
6515 ? BUILT_IN_COSF : BUILT_IN_COS);
6516 gcall *cos = gimple_build_call (cos_fndecl, 1, rhs);
6517 gimple_call_set_lhs (cos, real_part);
6518 gsi_insert_before (&gsi, cos, GSI_SAME_STMT);
6520 tree sin_fndecl
6521 = mathfn_built_in (rhs_type, fn == float_type_p
6522 ? BUILT_IN_SINF : BUILT_IN_SIN);
6523 gcall *sin = gimple_build_call (sin_fndecl, 1, rhs);
6524 gimple_call_set_lhs (sin, imag_part);
6525 gsi_insert_before (&gsi, sin, GSI_SAME_STMT);
6528 gassign *assign = gimple_build_assign (lhs, COMPLEX_EXPR,
6529 real_part, imag_part);
6530 gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
6531 gsi_remove (&gsi, true);
6533 break;
6535 default:
6536 break;
6542 /* Emit HSA module variables that are global for the entire module. */
6544 static void
6545 emit_hsa_module_variables (void)
6547 hsa_num_threads = new hsa_symbol (BRIG_TYPE_U32, BRIG_SEGMENT_PRIVATE,
6548 BRIG_LINKAGE_MODULE, true);
6550 hsa_num_threads->m_name = "hsa_num_threads";
6552 hsa_brig_emit_omp_symbols ();
6555 /* Generate HSAIL representation of the current function and write into a
6556 special section of the output file. If KERNEL is set, the function will be
6557 considered an HSA kernel callable from the host, otherwise it will be
6558 compiled as an HSA function callable from other HSA code. */
6560 static void
6561 generate_hsa (bool kernel)
6563 hsa_init_data_for_cfun ();
6565 if (hsa_num_threads == NULL)
6566 emit_hsa_module_variables ();
6568 bool modified_cfg = convert_switch_statements ();
6569 /* Initialize hsa_cfun. */
6570 hsa_cfun = new hsa_function_representation (cfun->decl, kernel,
6571 SSANAMES (cfun)->length (),
6572 modified_cfg);
6573 hsa_cfun->init_extra_bbs ();
6575 if (flag_tm)
6577 HSA_SORRY_AT (UNKNOWN_LOCATION,
6578 "support for HSA does not implement transactional memory");
6579 goto fail;
6582 verify_function_arguments (cfun->decl);
6583 if (hsa_seen_error ())
6584 goto fail;
6586 hsa_cfun->m_name = get_brig_function_name (cfun->decl);
6588 gen_function_def_parameters ();
6589 if (hsa_seen_error ())
6590 goto fail;
6592 init_prologue ();
6594 gen_body_from_gimple ();
6595 if (hsa_seen_error ())
6596 goto fail;
6598 if (hsa_cfun->m_kernel_dispatch_count)
6599 init_hsa_num_threads ();
6601 if (hsa_cfun->m_kern_p)
6603 hsa_function_summary *s
6604 = hsa_summaries->get_create (cgraph_node::get (hsa_cfun->m_decl));
6605 hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
6606 hsa_cfun->m_maximum_omp_data_size,
6607 s->m_gridified_kernel_p);
6610 if (flag_checking)
6612 for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
6613 if (hsa_cfun->m_ssa_map[i])
6614 hsa_cfun->m_ssa_map[i]->verify_ssa ();
6616 basic_block bb;
6617 FOR_EACH_BB_FN (bb, cfun)
6619 hsa_bb *hbb = hsa_bb_for_bb (bb);
6621 for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
6622 insn = insn->m_next)
6623 insn->verify ();
6627 hsa_regalloc ();
6628 hsa_brig_emit_function ();
6630 fail:
6631 hsa_deinit_data_for_cfun ();
6634 namespace {
6636 const pass_data pass_data_gen_hsail =
6638 GIMPLE_PASS,
6639 "hsagen", /* name */
6640 OPTGROUP_OMP, /* optinfo_flags */
6641 TV_NONE, /* tv_id */
6642 PROP_cfg | PROP_ssa, /* properties_required */
6643 0, /* properties_provided */
6644 0, /* properties_destroyed */
6645 0, /* todo_flags_start */
6646 0 /* todo_flags_finish */
6649 class pass_gen_hsail : public gimple_opt_pass
6651 public:
6652 pass_gen_hsail (gcc::context *ctxt)
6653 : gimple_opt_pass(pass_data_gen_hsail, ctxt)
6656 /* opt_pass methods: */
6657 bool gate (function *);
6658 unsigned int execute (function *);
6660 }; // class pass_gen_hsail
6662 /* Determine whether or not to run generation of HSAIL. */
6664 bool
6665 pass_gen_hsail::gate (function *f)
6667 return hsa_gen_requested_p ()
6668 && hsa_gpu_implementation_p (f->decl);
6671 unsigned int
6672 pass_gen_hsail::execute (function *)
6674 cgraph_node *node = cgraph_node::get_create (current_function_decl);
6675 hsa_function_summary *s = hsa_summaries->get_create (node);
6677 expand_builtins ();
6678 generate_hsa (s->m_kind == HSA_KERNEL);
6679 TREE_ASM_WRITTEN (current_function_decl) = 1;
6680 return TODO_discard_function;
6683 } // anon namespace
6685 /* Create the instance of hsa gen pass. */
6687 gimple_opt_pass *
6688 make_pass_gen_hsail (gcc::context *ctxt)
6690 return new pass_gen_hsail (ctxt);