re PR middle-end/91603 (Unaligned access in expand_assignment)
[official-gcc.git] / gcc / hsa-common.h
blob912253974b6f1fcebe284c449c84c874bcc52b82
1 /* HSAIL and BRIG related macros and definitions.
2 Copyright (C) 2013-2019 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef HSA_H
21 #define HSA_H
23 #include "hsa-brig-format.h"
24 #include "is-a.h"
25 #include "predict.h"
26 #include "tree.h"
27 #include "vec.h"
28 #include "hash-table.h"
29 #include "basic-block.h"
30 #include "bitmap.h"
33 /* Return true if the compiler should produce HSAIL. */
35 static inline bool
36 hsa_gen_requested_p (void)
38 #ifndef ENABLE_HSA
39 return false;
40 #endif
41 return !flag_disable_hsa;
44 /* Standard warning message if we failed to generate HSAIL for a function. */
46 #define HSA_SORRY_MSG "could not emit HSAIL for the function"
48 class hsa_op_immed;
49 class hsa_op_cst_list;
50 class hsa_insn_basic;
51 class hsa_op_address;
52 class hsa_op_reg;
53 class hsa_bb;
55 /* Class representing an input argument, output argument (result) or a
56 variable, that will eventually end up being a symbol directive. */
58 class hsa_symbol
60 public:
61 /* Constructor. */
62 hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
63 BrigLinkage8_t linkage, bool global_scope_p = false,
64 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
65 BrigAlignment8_t align = BRIG_ALIGNMENT_8);
67 /* Return total size of the symbol. */
68 unsigned HOST_WIDE_INT total_byte_size ();
70 /* Fill in those values into the symbol according to DECL, which are
71 determined independently from whether it is parameter, result,
72 or a variable, local or global. */
73 void fillup_for_decl (tree decl);
75 /* Pointer to the original tree, which is PARM_DECL for input parameters and
76 RESULT_DECL for the output parameters. Also can be CONST_DECL for Fortran
77 constants which need to be put into readonly segment. */
78 tree m_decl;
80 /* Name of the symbol, that will be written into output and dumps. Can be
81 NULL, see name_number below. */
82 const char *m_name;
84 /* If name is NULL, artificial name will be formed from the segment name and
85 this number. */
86 int m_name_number;
88 /* Once written, this is the offset of the associated symbol directive. Zero
89 means the symbol has not been written yet. */
90 unsigned m_directive_offset;
92 /* HSA type of the parameter. */
93 BrigType16_t m_type;
95 /* The HSA segment this will eventually end up in. */
96 BrigSegment8_t m_segment;
98 /* The HSA kind of linkage. */
99 BrigLinkage8_t m_linkage;
101 /* Array dimension, if non-zero. */
102 unsigned HOST_WIDE_INT m_dim;
104 /* Constant value, used for string constants. */
105 hsa_op_immed *m_cst_value;
107 /* Is in global scope. */
108 bool m_global_scope_p;
110 /* True if an error has been seen for the symbol. */
111 bool m_seen_error;
113 /* Symbol allocation. */
114 BrigAllocation m_allocation;
116 /* Flag used for global variables if a variable is already emitted or not. */
117 bool m_emitted_to_brig;
119 /* Alignment of the symbol. */
120 BrigAlignment8_t m_align;
122 private:
123 /* Default constructor. */
124 hsa_symbol ();
127 /* Abstract class for HSA instruction operands. */
129 class hsa_op_base
131 public:
132 /* Next operand scheduled to be written when writing BRIG operand
133 section. */
134 hsa_op_base *m_next;
136 /* Offset to which the associated operand structure will be written. Zero if
137 yet not scheduled for writing. */
138 unsigned m_brig_op_offset;
140 /* The type of a particular operand. */
141 BrigKind16_t m_kind;
143 protected:
144 hsa_op_base (BrigKind16_t k);
145 private:
146 /* Make the default constructor inaccessible. */
147 hsa_op_base () {}
150 /* Common abstract ancestor for operands which have a type. */
152 class hsa_op_with_type : public hsa_op_base
154 public:
155 /* The type. */
156 BrigType16_t m_type;
158 /* Convert an operand to a destination type DTYPE and attach insns
159 to HBB if needed. */
160 hsa_op_with_type *get_in_type (BrigType16_t dtype, hsa_bb *hbb);
161 /* If this operand has integer type smaller than 32 bits, extend it to 32
162 bits, adding instructions to HBB if needed. */
163 hsa_op_with_type *extend_int_to_32bit (hsa_bb *hbb);
165 protected:
166 hsa_op_with_type (BrigKind16_t k, BrigType16_t t);
167 private:
168 /* Make the default constructor inaccessible. */
169 hsa_op_with_type () : hsa_op_base (BRIG_KIND_NONE) {}
172 /* An immediate HSA operand. */
174 class hsa_op_immed : public hsa_op_with_type
176 public:
177 hsa_op_immed (tree tree_val, bool min32int = true);
178 hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
179 void *operator new (size_t);
180 ~hsa_op_immed ();
181 void set_type (BrigKind16_t t);
183 /* Function returns pointer to a buffer that contains binary representation
184 of the immeadiate value. The buffer has length of BRIG_SIZE and
185 a caller is responsible for deallocation of the buffer. */
186 char *emit_to_buffer (unsigned *brig_size);
188 /* Value as represented by middle end. */
189 tree m_tree_value;
191 /* Integer value representation. */
192 HOST_WIDE_INT m_int_value;
194 private:
195 /* Make the default constructor inaccessible. */
196 hsa_op_immed ();
197 /* All objects are deallocated by destroying their pool, so make delete
198 inaccessible too. */
199 void operator delete (void *) {}
202 /* Report whether or not P is a an immediate operand. */
204 template <>
205 template <>
206 inline bool
207 is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
209 return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
212 /* Likewise, but for a more specified base. */
214 template <>
215 template <>
216 inline bool
217 is_a_helper <hsa_op_immed *>::test (hsa_op_with_type *p)
219 return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
223 /* HSA register operand. */
225 class hsa_op_reg : public hsa_op_with_type
227 friend class hsa_insn_basic;
228 friend class hsa_insn_phi;
229 public:
230 hsa_op_reg (BrigType16_t t);
231 void *operator new (size_t);
233 /* Verify register operand. */
234 void verify_ssa ();
236 /* If NON-NULL, gimple SSA that we come from. NULL if none. */
237 tree m_gimple_ssa;
239 /* Defining instruction while still in the SSA. */
240 hsa_insn_basic *m_def_insn;
242 /* If the register allocator decides to spill the register, this is the
243 appropriate spill symbol. */
244 hsa_symbol *m_spill_sym;
246 /* Number of this register structure in the order in which they were
247 allocated. */
248 int m_order;
249 int m_lr_begin, m_lr_end;
251 /* Zero if the register is not yet allocated. After, allocation, this must
252 be 'c', 's', 'd' or 'q'. */
253 char m_reg_class;
254 /* If allocated, the number of the HW register (within its HSA register
255 class). */
256 char m_hard_num;
258 private:
259 /* Make the default constructor inaccessible. */
260 hsa_op_reg () : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
261 /* All objects are deallocated by destroying their pool, so make delete
262 inaccessible too. */
263 void operator delete (void *) {}
264 /* Set definition where the register is defined. */
265 void set_definition (hsa_insn_basic *insn);
266 /* Uses of the value while still in SSA. */
267 auto_vec <hsa_insn_basic *> m_uses;
270 /* Report whether or not P is a register operand. */
272 template <>
273 template <>
274 inline bool
275 is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
277 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
280 /* Report whether or not P is a register operand. */
282 template <>
283 template <>
284 inline bool
285 is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
287 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
290 /* An address HSA operand. */
292 class hsa_op_address : public hsa_op_base
294 public:
295 /* set up a new address operand consisting of base symbol SYM, register R and
296 immediate OFFSET. If the machine model is not large and offset is 64 bit,
297 the upper, 32 bits have to be zero. */
298 hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
299 HOST_WIDE_INT offset = 0);
301 void *operator new (size_t);
303 /* Set up a new address operand consisting of base symbol SYM and
304 immediate OFFSET. If the machine model is not large and offset is 64 bit,
305 the upper, 32 bits have to be zero. */
306 hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
308 /* Set up a new address operand consisting of register R and
309 immediate OFFSET. If the machine model is not large and offset is 64 bit,
310 the upper, 32 bits have to be zero. */
311 hsa_op_address (hsa_op_reg *reg, HOST_WIDE_INT offset = 0);
313 /* Symbol base of the address. Can be NULL if there is none. */
314 hsa_symbol *m_symbol;
316 /* Register offset. Can be NULL if there is none. */
317 hsa_op_reg *m_reg;
319 /* Immediate byte offset. */
320 HOST_WIDE_INT m_imm_offset;
322 private:
323 /* Make the default constructor inaccessible. */
324 hsa_op_address () : hsa_op_base (BRIG_KIND_NONE) {}
325 /* All objects are deallocated by destroying their pool, so make delete
326 inaccessible too. */
327 void operator delete (void *) {}
330 /* Report whether or not P is an address operand. */
332 template <>
333 template <>
334 inline bool
335 is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
337 return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
340 /* A reference to code HSA operand. It can be either reference
341 to a start of a BB or a start of a function. */
343 class hsa_op_code_ref : public hsa_op_base
345 public:
346 hsa_op_code_ref ();
348 /* Offset in the code section that this refers to. */
349 unsigned m_directive_offset;
352 /* Report whether or not P is a code reference operand. */
354 template <>
355 template <>
356 inline bool
357 is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
359 return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
362 /* Code list HSA operand. */
364 class hsa_op_code_list: public hsa_op_base
366 public:
367 hsa_op_code_list (unsigned elements);
368 void *operator new (size_t);
370 /* Offset to variable-sized array in hsa_data section, where
371 are offsets to entries in the hsa_code section. */
372 auto_vec<unsigned> m_offsets;
373 private:
374 /* Make the default constructor inaccessible. */
375 hsa_op_code_list () : hsa_op_base (BRIG_KIND_NONE) {}
376 /* All objects are deallocated by destroying their pool, so make delete
377 inaccessible too. */
378 void operator delete (void *) {}
381 /* Report whether or not P is a code list operand. */
383 template <>
384 template <>
385 inline bool
386 is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
388 return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
391 /* Operand list HSA operand. */
393 class hsa_op_operand_list: public hsa_op_base
395 public:
396 hsa_op_operand_list (unsigned elements);
397 ~hsa_op_operand_list ();
398 void *operator new (size_t);
400 /* Offset to variable-sized array in hsa_data section, where
401 are offsets to entries in the hsa_code section. */
402 auto_vec<unsigned> m_offsets;
403 private:
404 /* Make the default constructor inaccessible. */
405 hsa_op_operand_list () : hsa_op_base (BRIG_KIND_NONE) {}
406 /* All objects are deallocated by destroying their pool, so make delete
407 inaccessible too. */
408 void operator delete (void *) {}
411 /* Report whether or not P is a code list operand. */
413 template <>
414 template <>
415 inline bool
416 is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
418 return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
421 /* Opcodes of instructions that are not part of HSA but that we use to
422 represent it nevertheless. */
424 #define HSA_OPCODE_PHI (-1)
425 #define HSA_OPCODE_ARG_BLOCK (-2)
427 /* The number of operand pointers we can directly in an instruction. */
428 #define HSA_BRIG_INT_STORAGE_OPERANDS 5
430 /* Class representing an HSA instruction. Unlike typical ancestors for
431 specialized classes, this one is also directly used for all instructions
432 that are then represented as BrigInstBasic. */
434 class hsa_insn_basic
436 public:
437 hsa_insn_basic (unsigned nops, int opc);
438 hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
439 hsa_op_base *arg0 = NULL,
440 hsa_op_base *arg1 = NULL,
441 hsa_op_base *arg2 = NULL,
442 hsa_op_base *arg3 = NULL);
444 void *operator new (size_t);
445 void set_op (int index, hsa_op_base *op);
446 hsa_op_base *get_op (int index);
447 hsa_op_base **get_op_addr (int index);
448 unsigned int operand_count ();
449 void verify ();
450 unsigned input_count ();
451 unsigned num_used_ops ();
452 void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
453 bool op_output_p (unsigned opnum);
455 /* The previous and next instruction in the basic block. */
456 hsa_insn_basic *m_prev, *m_next;
458 /* Basic block this instruction belongs to. */
459 basic_block m_bb;
461 /* Operand code distinguishing different types of instructions. Eventually
462 these should only be BRIG_INST_* values from the BrigOpcode16_t range but
463 initially we use negative values for PHI nodes and such. */
464 int m_opcode;
466 /* Linearized number assigned to the instruction by HSA RA. */
467 int m_number;
469 /* Type of the destination of the operations. */
470 BrigType16_t m_type;
472 /* BRIG offset of the instruction in code section. */
473 unsigned int m_brig_offset;
475 private:
476 /* Make the default constructor inaccessible. */
477 hsa_insn_basic () {}
478 /* All objects are deallocated by destroying their pool, so make delete
479 inaccessible too. */
480 void operator delete (void *) {}
481 /* The individual operands. All instructions but PHI nodes have five or
482 fewer instructions and so will fit the internal storage. */
483 /* TODO: Vast majority of instructions have three or fewer operands, so we
484 may actually try reducing it. */
485 auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands;
488 /* Class representing a PHI node of the SSA form of HSA virtual
489 registers. */
491 class hsa_insn_phi : public hsa_insn_basic
493 public:
494 hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
496 /* Destination. */
497 hsa_op_reg *m_dest;
499 private:
500 /* Make the default constructor inaccessible. */
501 hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
504 /* Report whether or not P is a PHI node. */
506 template <>
507 template <>
508 inline bool
509 is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
511 return p->m_opcode == HSA_OPCODE_PHI;
514 /* HSA instruction for */
515 class hsa_insn_br : public hsa_insn_basic
517 public:
518 hsa_insn_br (unsigned nops, int opc, BrigType16_t t, BrigWidth8_t width,
519 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
520 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
522 /* Number of work-items affected in the same way by the instruction. */
523 BrigWidth8_t m_width;
525 private:
526 /* Make the default constructor inaccessible. */
527 hsa_insn_br () : hsa_insn_basic (0, BRIG_OPCODE_BR) {}
530 /* Return true if P is a branching/synchronization instruction. */
532 template <>
533 template <>
534 inline bool
535 is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
537 return p->m_opcode == BRIG_OPCODE_BARRIER
538 || p->m_opcode == BRIG_OPCODE_BR;
541 /* HSA instruction for conditional branches. Structurally the same as
542 hsa_insn_br but we represent it specially because of inherent control
543 flow it represents. */
545 class hsa_insn_cbr : public hsa_insn_br
547 public:
548 hsa_insn_cbr (hsa_op_reg *ctrl);
550 private:
551 /* Make the default constructor inaccessible. */
552 hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
553 BRIG_WIDTH_1) {}
556 /* Report whether P is a contitional branching instruction. */
558 template <>
559 template <>
560 inline bool
561 is_a_helper <hsa_insn_cbr *>::test (hsa_insn_basic *p)
563 return p->m_opcode == BRIG_OPCODE_CBR;
566 /* HSA instruction for switch branches. */
568 class hsa_insn_sbr : public hsa_insn_basic
570 public:
571 hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
573 /* Default destructor. */
574 ~hsa_insn_sbr ();
576 void replace_all_labels (basic_block old_bb, basic_block new_bb);
578 /* Width as described in HSA documentation. */
579 BrigWidth8_t m_width;
581 /* Jump table. */
582 vec <basic_block> m_jump_table;
584 /* Code list for label references. */
585 hsa_op_code_list *m_label_code_list;
587 private:
588 /* Make the default constructor inaccessible. */
589 hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
592 /* Report whether P is a switch branching instruction. */
594 template <>
595 template <>
596 inline bool
597 is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
599 return p->m_opcode == BRIG_OPCODE_SBR;
602 /* HSA instruction for comparisons. */
604 class hsa_insn_cmp : public hsa_insn_basic
606 public:
607 hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
608 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
609 hsa_op_base *arg2 = NULL);
611 /* Source type should be derived from operand types. */
613 /* The comparison operation. */
614 BrigCompareOperation8_t m_compare;
616 /* TODO: Modifiers and packing control are missing but so are everywhere
617 else. */
618 private:
619 /* Make the default constructor inaccessible. */
620 hsa_insn_cmp () : hsa_insn_basic (1, BRIG_OPCODE_CMP) {}
623 /* Report whether or not P is a comparison instruction. */
625 template <>
626 template <>
627 inline bool
628 is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
630 return p->m_opcode == BRIG_OPCODE_CMP;
633 /* HSA instruction for memory operations. */
635 class hsa_insn_mem : public hsa_insn_basic
637 public:
638 hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
640 /* Set alignment to VALUE. */
642 void set_align (BrigAlignment8_t value);
644 /* The segment is of the memory access is either the segment of the symbol in
645 the address operand or flat address is there is no symbol there. */
647 /* Required alignment of the memory operation. */
648 BrigAlignment8_t m_align;
650 /* HSA equiv class, basically an alias set number. */
651 uint8_t m_equiv_class;
653 /* TODO: Add width modifier, perhaps also other things. */
654 protected:
655 hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
656 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
657 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
659 private:
660 /* Make the default constructor inaccessible. */
661 hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
664 /* Report whether or not P is a memory instruction. */
666 template <>
667 template <>
668 inline bool
669 is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
671 return (p->m_opcode == BRIG_OPCODE_LD
672 || p->m_opcode == BRIG_OPCODE_ST);
675 /* HSA instruction for atomic operations. */
677 class hsa_insn_atomic : public hsa_insn_mem
679 public:
680 hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
681 BrigType16_t t, BrigMemoryOrder memorder,
682 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
683 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
685 /* The operation itself. */
686 enum BrigAtomicOperation m_atomicop;
688 /* Things like acquire/release/aligned. */
689 enum BrigMemoryOrder m_memoryorder;
691 /* Scope of the atomic operation. */
692 enum BrigMemoryScope m_memoryscope;
694 private:
695 /* Make the default constructor inaccessible. */
696 hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
699 /* Report whether or not P is an atomic instruction. */
701 template <>
702 template <>
703 inline bool
704 is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
706 return (p->m_opcode == BRIG_OPCODE_ATOMIC
707 || p->m_opcode == BRIG_OPCODE_ATOMICNORET);
710 /* HSA instruction for signal operations. */
712 class hsa_insn_signal : public hsa_insn_basic
714 public:
715 hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
716 BrigType16_t t, BrigMemoryOrder memorder,
717 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
718 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
720 /* Things like acquire/release/aligned. */
721 enum BrigMemoryOrder m_memory_order;
723 /* The operation itself. */
724 enum BrigAtomicOperation m_signalop;
727 /* Report whether or not P is a signal instruction. */
729 template <>
730 template <>
731 inline bool
732 is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
734 return (p->m_opcode == BRIG_OPCODE_SIGNAL
735 || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
738 /* HSA instruction to convert between flat addressing and segments. */
740 class hsa_insn_seg : public hsa_insn_basic
742 public:
743 hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
744 BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
746 /* Source type. Depends on the source addressing/segment. */
747 BrigType16_t m_src_type;
748 /* The segment we are converting from or to. */
749 BrigSegment8_t m_segment;
750 private:
751 /* Make the default constructor inaccessible. */
752 hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
755 /* Report whether or not P is a segment conversion instruction. */
757 template <>
758 template <>
759 inline bool
760 is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
762 return (p->m_opcode == BRIG_OPCODE_STOF
763 || p->m_opcode == BRIG_OPCODE_FTOS);
766 /* Class for internal functions for purpose of HSA emission. */
768 class hsa_internal_fn
770 public:
771 hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
772 m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
774 hsa_internal_fn (const hsa_internal_fn *f):
775 m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
776 m_offset (f->m_offset) {}
778 /* Return arity of the internal function. */
779 unsigned get_arity ();
781 /* Return BRIG type of N-th argument, if -1 is passed, return value type
782 is received. */
783 BrigType16_t get_argument_type (int n);
785 /* Return function name. The memory must be released by a caller. */
786 char *name ();
788 /* Internal function. */
789 enum internal_fn m_fn;
791 /* Bit width of return type. */
792 unsigned m_type_bit_size;
794 /* BRIG offset of declaration of the function. */
795 BrigCodeOffset32_t m_offset;
798 /* HSA instruction for function call. */
800 class hsa_insn_call : public hsa_insn_basic
802 public:
803 hsa_insn_call (tree callee);
804 hsa_insn_call (hsa_internal_fn *fn);
806 /* Default destructor. */
807 ~hsa_insn_call ();
809 /* Called function. */
810 tree m_called_function;
812 /* Called internal function. */
813 hsa_internal_fn *m_called_internal_fn;
815 /* Input formal arguments. */
816 auto_vec <hsa_symbol *> m_input_args;
818 /* Input arguments store instructions. */
819 auto_vec <hsa_insn_mem *> m_input_arg_insns;
821 /* Output argument, can be NULL for void functions. */
822 hsa_symbol *m_output_arg;
824 /* Called function code reference. */
825 hsa_op_code_ref m_func;
827 /* Code list for arguments of the function. */
828 hsa_op_code_list *m_args_code_list;
830 /* Code list for result of the function. */
831 hsa_op_code_list *m_result_code_list;
832 private:
833 /* Make the default constructor inaccessible. */
834 hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
837 /* Report whether or not P is a call instruction. */
839 template <>
840 template <>
841 inline bool
842 is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
844 return (p->m_opcode == BRIG_OPCODE_CALL);
847 /* HSA call instruction block encapsulates definition of arguments,
848 result type, corresponding loads and a possible store.
849 Moreover, it contains a single call instruction.
850 Emission of the instruction will produce multiple
851 HSAIL instructions. */
853 class hsa_insn_arg_block : public hsa_insn_basic
855 public:
856 hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
858 /* Kind of argument block. */
859 BrigKind m_kind;
861 /* Call instruction. */
862 hsa_insn_call *m_call_insn;
865 /* Report whether or not P is a call block instruction. */
867 template <>
868 template <>
869 inline bool
870 is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
872 return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
875 /* HSA comment instruction. */
877 class hsa_insn_comment: public hsa_insn_basic
879 public:
880 /* Constructor of class representing the comment in HSAIL. */
881 hsa_insn_comment (const char *s);
883 /* Default destructor. */
884 ~hsa_insn_comment ();
886 char *m_comment;
889 /* Report whether or not P is a call block instruction. */
891 template <>
892 template <>
893 inline bool
894 is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
896 return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
899 /* HSA queue instruction. */
901 class hsa_insn_queue: public hsa_insn_basic
903 public:
904 hsa_insn_queue (int nops, int opcode, BrigSegment segment,
905 BrigMemoryOrder memory_order,
906 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
907 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
909 /* Destructor. */
910 ~hsa_insn_queue ();
912 /* Segment used to refer to the queue. Must be global or flat. */
913 BrigSegment m_segment;
914 /* Memory order used to specify synchronization. */
915 BrigMemoryOrder m_memory_order;
918 /* Report whether or not P is a queue instruction. */
920 template <>
921 template <>
922 inline bool
923 is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
925 return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX
926 || p->m_opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX
927 || p->m_opcode == BRIG_OPCODE_LDQUEUEREADINDEX
928 || p->m_opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
929 || p->m_opcode == BRIG_OPCODE_STQUEUEREADINDEX
930 || p->m_opcode == BRIG_OPCODE_STQUEUEWRITEINDEX);
933 /* HSA source type instruction. */
935 class hsa_insn_srctype: public hsa_insn_basic
937 public:
938 hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
939 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
940 hsa_op_base *arg2);
942 /* Source type. */
943 BrigType16_t m_source_type;
945 /* Destructor. */
946 ~hsa_insn_srctype ();
949 /* Report whether or not P is a source type instruction. */
951 template <>
952 template <>
953 inline bool
954 is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
956 return (p->m_opcode == BRIG_OPCODE_POPCOUNT
957 || p->m_opcode == BRIG_OPCODE_FIRSTBIT
958 || p->m_opcode == BRIG_OPCODE_LASTBIT);
961 /* HSA packed instruction. */
963 class hsa_insn_packed : public hsa_insn_srctype
965 public:
966 hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
967 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
968 hsa_op_base *arg2);
970 /* Operand list for an operand of the instruction. */
971 hsa_op_operand_list *m_operand_list;
973 /* Destructor. */
974 ~hsa_insn_packed ();
977 /* Report whether or not P is a combine instruction. */
979 template <>
980 template <>
981 inline bool
982 is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
984 return (p->m_opcode == BRIG_OPCODE_COMBINE
985 || p->m_opcode == BRIG_OPCODE_EXPAND);
988 /* HSA convert instruction. */
990 class hsa_insn_cvt: public hsa_insn_basic
992 public:
993 hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
996 /* Report whether or not P is a convert instruction. */
998 template <>
999 template <>
1000 inline bool
1001 is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
1003 return (p->m_opcode == BRIG_OPCODE_CVT);
1006 /* HSA alloca instruction. */
1008 class hsa_insn_alloca: public hsa_insn_basic
1010 public:
1011 hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
1012 unsigned alignment = 0);
1014 /* Required alignment of the allocation. */
1015 BrigAlignment8_t m_align;
1018 /* Report whether or not P is an alloca instruction. */
1020 template <>
1021 template <>
1022 inline bool
1023 is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
1025 return (p->m_opcode == BRIG_OPCODE_ALLOCA);
1028 /* Basic block of HSA instructions. */
1030 class hsa_bb
1032 public:
1033 hsa_bb (basic_block cfg_bb);
1034 hsa_bb (basic_block cfg_bb, int idx);
1036 /* Append an instruction INSN into the basic block. */
1037 void append_insn (hsa_insn_basic *insn);
1039 /* Add a PHI instruction. */
1040 void append_phi (hsa_insn_phi *phi);
1042 /* The real CFG BB that this HBB belongs to. */
1043 basic_block m_bb;
1045 /* The operand that refers to the label to this BB. */
1046 hsa_op_code_ref m_label_ref;
1048 /* The first and last instruction. */
1049 hsa_insn_basic *m_first_insn, *m_last_insn;
1050 /* The first and last phi node. */
1051 hsa_insn_phi *m_first_phi, *m_last_phi;
1053 /* Just a number to construct names from. */
1054 int m_index;
1056 auto_bitmap m_liveout, m_livein;
1057 private:
1058 /* Make the default constructor inaccessible. */
1059 hsa_bb ();
1060 /* All objects are deallocated by destroying their pool, so make delete
1061 inaccessible too. */
1062 void operator delete (void *) {}
1065 /* Return the corresponding HSA basic block structure for the given control
1066 flow basic_block BB. */
1068 static inline hsa_bb *
1069 hsa_bb_for_bb (basic_block bb)
1071 return (class hsa_bb *) bb->aux;
1074 /* Class for hashing local hsa_symbols. */
1076 struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
1078 static inline hashval_t hash (const value_type);
1079 static inline bool equal (const value_type, const compare_type);
1082 /* Hash hsa_symbol. */
1084 inline hashval_t
1085 hsa_noop_symbol_hasher::hash (const value_type item)
1087 return DECL_UID (item->m_decl);
1090 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1092 inline bool
1093 hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
1095 return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
1098 /* Structure that encapsulates intermediate representation of a HSA
1099 function. */
1101 class hsa_function_representation
1103 public:
1104 hsa_function_representation (tree fdecl, bool kernel_p,
1105 unsigned ssa_names_count,
1106 bool modified_cfg = false);
1107 hsa_function_representation (hsa_internal_fn *fn);
1108 ~hsa_function_representation ();
1110 /* Builds a shadow register that is utilized to a kernel dispatch. */
1111 hsa_op_reg *get_shadow_reg ();
1113 /* Return true if we are in a function that has kernel dispatch
1114 shadow register. */
1115 bool has_shadow_reg_p ();
1117 /* The entry/exit blocks don't contain incoming code,
1118 but the HSA generator might use them to put code into,
1119 so we need hsa_bb instances of them. */
1120 void init_extra_bbs ();
1122 /* Update CFG dominators if m_modified_cfg flag is set. */
1123 void update_dominance ();
1125 /* Return linkage of the representation. */
1126 BrigLinkage8_t get_linkage ();
1128 /* Create a private symbol of requested TYPE. */
1129 hsa_symbol *create_hsa_temporary (BrigType16_t type);
1131 /* Lookup or create a HSA pseudo register for a given gimple SSA name. */
1132 hsa_op_reg *reg_for_gimple_ssa (tree ssa);
1134 /* Name of the function. */
1135 char *m_name;
1137 /* Number of allocated register structures. */
1138 int m_reg_count;
1140 /* Input arguments. */
1141 vec <hsa_symbol *> m_input_args;
1143 /* Output argument or NULL if there is none. */
1144 hsa_symbol *m_output_arg;
1146 /* Hash table of local variable symbols. */
1147 hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
1149 /* Hash map for string constants. */
1150 hash_map <tree, hsa_symbol *> m_string_constants_map;
1152 /* Vector of pointers to spill symbols. */
1153 vec <class hsa_symbol *> m_spill_symbols;
1155 /* Vector of pointers to global variables and transformed string constants
1156 that are used by the function. */
1157 vec <class hsa_symbol *> m_global_symbols;
1159 /* Private function artificial variables. */
1160 vec <class hsa_symbol *> m_private_variables;
1162 /* Vector of called function declarations. */
1163 vec <tree> m_called_functions;
1165 /* Vector of used internal functions. */
1166 vec <hsa_internal_fn *> m_called_internal_fns;
1168 /* Number of HBB BBs. */
1169 int m_hbb_count;
1171 /* Whether or not we could check and enforce SSA properties. */
1172 bool m_in_ssa;
1174 /* True if the function is kernel function. */
1175 bool m_kern_p;
1177 /* True if the function representation is a declaration. */
1178 bool m_declaration_p;
1180 /* Function declaration tree. */
1181 tree m_decl;
1183 /* Internal function info is used for declarations of internal functions. */
1184 hsa_internal_fn *m_internal_fn;
1186 /* Runtime shadow register. */
1187 hsa_op_reg *m_shadow_reg;
1189 /* Number of kernel dispatched which take place in the function. */
1190 unsigned m_kernel_dispatch_count;
1192 /* If the function representation contains a kernel dispatch,
1193 OMP data size is necessary memory that is used for copying before
1194 a kernel dispatch. */
1195 unsigned m_maximum_omp_data_size;
1197 /* Return true if there's an HSA-specific warning already seen. */
1198 bool m_seen_error;
1200 /* Counter for temporary symbols created in the function representation. */
1201 unsigned m_temp_symbol_count;
1203 /* SSA names mapping. */
1204 vec <hsa_op_reg *> m_ssa_map;
1206 /* Flag whether a function needs update of dominators before RA. */
1207 bool m_modified_cfg;
1210 enum hsa_function_kind
1212 HSA_INVALID,
1213 HSA_KERNEL,
1214 HSA_FUNCTION
1217 class hsa_function_summary
1219 public:
1220 /* Default constructor. */
1221 hsa_function_summary ();
1223 /* Kind of GPU/host function. */
1224 hsa_function_kind m_kind;
1226 /* Pointer to a cgraph node which is a HSA implementation of the function.
1227 In case of the function is a HSA function, the bound function points
1228 to the host function. */
1229 cgraph_node *m_bound_function;
1231 /* Identifies if the function is an HSA function or a host function. */
1232 bool m_gpu_implementation_p;
1234 /* True if the function is a gridified kernel. */
1235 bool m_gridified_kernel_p;
1238 inline
1239 hsa_function_summary::hsa_function_summary (): m_kind (HSA_INVALID),
1240 m_bound_function (NULL), m_gpu_implementation_p (false)
1244 /* Function summary for HSA functions. */
1245 class hsa_summary_t: public function_summary <hsa_function_summary *>
1247 public:
1248 hsa_summary_t (symbol_table *table):
1249 function_summary<hsa_function_summary *> (table)
1251 disable_insertion_hook ();
1254 /* Couple GPU and HOST as gpu-specific and host-specific implementation of
1255 the same function. KIND determines whether GPU is a host-invokable kernel
1256 or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
1257 gridified in OMP. */
1259 void link_functions (cgraph_node *gpu, cgraph_node *host,
1260 hsa_function_kind kind, bool gridified_kernel_p);
1262 private:
1263 void process_gpu_implementation_attributes (tree gdecl);
1266 /* OMP simple builtin describes behavior that should be done for
1267 the routine. */
1268 class omp_simple_builtin
1270 public:
1271 omp_simple_builtin (const char *name, const char *warning_message,
1272 bool sorry, hsa_op_immed *return_value = NULL):
1273 m_name (name), m_warning_message (warning_message), m_sorry (sorry),
1274 m_return_value (return_value)
1277 /* Generate HSAIL instructions for the builtin or produce warning message. */
1278 void generate (gimple *stmt, hsa_bb *hbb);
1280 /* Name of function. */
1281 const char *m_name;
1283 /* Warning message. */
1284 const char *m_warning_message;
1286 /* Flag if we should sorry after the warning message is printed. */
1287 bool m_sorry;
1289 /* Return value of the function. */
1290 hsa_op_immed *m_return_value;
1292 /* Emission function. */
1293 void (*m_emit_func) (gimple *stmt, hsa_bb *);
1296 /* Class for hashing hsa_internal_fn. */
1298 struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
1300 static inline hashval_t hash (const value_type);
1301 static inline bool equal (const value_type, const compare_type);
1304 /* Hash hsa_symbol. */
1306 inline hashval_t
1307 hsa_internal_fn_hasher::hash (const value_type item)
1309 return item->m_fn;
1312 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1314 inline bool
1315 hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
1317 return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
1320 /* in hsa-common.c */
1321 extern class hsa_function_representation *hsa_cfun;
1322 extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
1323 extern hsa_summary_t *hsa_summaries;
1324 extern hsa_symbol *hsa_num_threads;
1325 extern unsigned hsa_kernel_calls_counter;
1326 extern hash_set <tree> *hsa_failed_functions;
1327 extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
1329 bool hsa_callable_function_p (tree fndecl);
1330 void hsa_init_compilation_unit_data (void);
1331 void hsa_deinit_compilation_unit_data (void);
1332 bool hsa_machine_large_p (void);
1333 bool hsa_full_profile_p (void);
1334 bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
1335 unsigned hsa_type_bit_size (BrigType16_t t);
1336 BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
1337 BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
1338 BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
1339 BrigType16_t hsa_bittype_for_type (BrigType16_t t);
1340 BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
1341 bool hsa_type_packed_p (BrigType16_t type);
1342 bool hsa_type_float_p (BrigType16_t type);
1343 bool hsa_type_integer_p (BrigType16_t type);
1344 bool hsa_btype_p (BrigType16_t type);
1345 BrigAlignment8_t hsa_alignment_encoding (unsigned n);
1346 BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
1347 BrigAlignment8_t hsa_object_alignment (tree t);
1348 unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
1349 void hsa_destroy_operand (hsa_op_base *op);
1350 void hsa_destroy_insn (hsa_insn_basic *insn);
1351 void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
1352 unsigned hsa_get_number_decl_kernel_mappings (void);
1353 tree hsa_get_decl_kernel_mapping_decl (unsigned i);
1354 char *hsa_get_decl_kernel_mapping_name (unsigned i);
1355 unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
1356 bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
1357 void hsa_free_decl_kernel_mapping (void);
1358 tree *hsa_get_ctor_statements (void);
1359 tree *hsa_get_dtor_statements (void);
1360 tree *hsa_get_kernel_dispatch_type (void);
1361 void hsa_add_kernel_dependency (tree caller, const char *called_function);
1362 void hsa_sanitize_name (char *p);
1363 char *hsa_brig_function_name (const char *p);
1364 const char *hsa_get_declaration_name (tree decl);
1365 void hsa_register_kernel (cgraph_node *host);
1366 void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
1367 bool hsa_seen_error (void);
1368 void hsa_fail_cfun (void);
1370 /* In hsa-gen.c. */
1371 void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
1372 hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
1373 hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
1374 hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1375 hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1376 hsa_bb *hsa_init_new_bb (basic_block);
1377 hsa_function_representation *hsa_generate_function_declaration (tree decl);
1378 hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
1379 tree hsa_get_host_function (tree decl);
1381 /* In hsa-regalloc.c. */
1382 void hsa_regalloc (void);
1384 /* In hsa-brig.c. */
1385 extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
1386 void hsa_brig_emit_function (void);
1387 void hsa_output_brig (void);
1388 unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
1389 void hsa_brig_emit_omp_symbols (void);
1391 /* In hsa-dump.c. */
1392 const char *hsa_seg_name (BrigSegment8_t);
1393 void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
1394 void dump_hsa_bb (FILE *, hsa_bb *);
1395 void dump_hsa_cfun (FILE *);
1396 DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
1397 DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
1399 union hsa_bytes
1401 uint8_t b8;
1402 uint16_t b16;
1403 uint32_t b32;
1404 uint64_t b64;
1407 /* Return true if a function DECL is an HSA implementation. */
1409 static inline bool
1410 hsa_gpu_implementation_p (tree decl)
1412 if (hsa_summaries == NULL)
1413 return false;
1415 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
1416 return s != NULL && s->m_gpu_implementation_p;
1419 #endif /* HSA_H */