libstdc++/70940 Start fixing polymorphic memory resources
[official-gcc.git] / gcc / hsa.h
blob1b57a3c1c99b1f95285c0c2f4f61eeff3f7d81f4
1 /* HSAIL and BRIG related macros and definitions.
2 Copyright (C) 2013-2016 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"
32 /* Return true if the compiler should produce HSAIL. */
34 static inline bool
35 hsa_gen_requested_p (void)
37 #ifndef ENABLE_HSA
38 return false;
39 #endif
40 return !flag_disable_hsa;
43 /* Standard warning message if we failed to generate HSAIL for a function. */
45 #define HSA_SORRY_MSG "could not emit HSAIL for the function"
47 class hsa_op_immed;
48 class hsa_op_cst_list;
49 class hsa_insn_basic;
50 class hsa_op_address;
51 class hsa_op_reg;
52 class hsa_bb;
53 typedef hsa_insn_basic *hsa_insn_basic_p;
55 /* Class representing an input argument, output argument (result) or a
56 variable, that will eventually end up being a symbol directive. */
58 struct hsa_symbol
60 /* Constructor. */
61 hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
62 BrigLinkage8_t linkage, bool global_scope_p = false,
63 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
64 BrigAlignment8_t align = BRIG_ALIGNMENT_8);
66 /* Return total size of the symbol. */
67 unsigned HOST_WIDE_INT total_byte_size ();
69 /* Fill in those values into the symbol according to DECL, which are
70 determined independently from whether it is parameter, result,
71 or a variable, local or global. */
72 void fillup_for_decl (tree decl);
74 /* Pointer to the original tree, which is PARM_DECL for input parameters and
75 RESULT_DECL for the output parameters. */
76 tree m_decl;
78 /* Name of the symbol, that will be written into output and dumps. Can be
79 NULL, see name_number below. */
80 const char *m_name;
82 /* If name is NULL, artificial name will be formed from the segment name and
83 this number. */
84 int m_name_number;
86 /* Once written, this is the offset of the associated symbol directive. Zero
87 means the symbol has not been written yet. */
88 unsigned m_directive_offset;
90 /* HSA type of the parameter. */
91 BrigType16_t m_type;
93 /* The HSA segment this will eventually end up in. */
94 BrigSegment8_t m_segment;
96 /* The HSA kind of linkage. */
97 BrigLinkage8_t m_linkage;
99 /* Array dimension, if non-zero. */
100 unsigned HOST_WIDE_INT m_dim;
102 /* Constant value, used for string constants. */
103 hsa_op_immed *m_cst_value;
105 /* Is in global scope. */
106 bool m_global_scope_p;
108 /* True if an error has been seen for the symbol. */
109 bool m_seen_error;
111 /* Symbol allocation. */
112 BrigAllocation m_allocation;
114 /* Flag used for global variables if a variable is already emitted or not. */
115 bool m_emitted_to_brig;
117 /* Alignment of the symbol. */
118 BrigAlignment8_t m_align;
120 private:
121 /* Default constructor. */
122 hsa_symbol ();
125 /* Abstract class for HSA instruction operands. */
127 class hsa_op_base
129 public:
130 /* Next operand scheduled to be written when writing BRIG operand
131 section. */
132 hsa_op_base *m_next;
134 /* Offset to which the associated operand structure will be written. Zero if
135 yet not scheduled for writing. */
136 unsigned m_brig_op_offset;
138 /* The type of a particular operand. */
139 BrigKind16_t m_kind;
141 protected:
142 hsa_op_base (BrigKind16_t k);
143 private:
144 /* Make the default constructor inaccessible. */
145 hsa_op_base () {}
148 /* Common abstract ancestor for operands which have a type. */
150 class hsa_op_with_type : public hsa_op_base
152 public:
153 /* The type. */
154 BrigType16_t m_type;
156 /* Convert an operand to a destination type DTYPE and attach insns
157 to HBB if needed. */
158 hsa_op_with_type *get_in_type (BrigType16_t dtype, hsa_bb *hbb);
160 protected:
161 hsa_op_with_type (BrigKind16_t k, BrigType16_t t);
162 private:
163 /* Make the default constructor inaccessible. */
164 hsa_op_with_type () : hsa_op_base (BRIG_KIND_NONE) {}
167 /* An immediate HSA operand. */
169 class hsa_op_immed : public hsa_op_with_type
171 public:
172 hsa_op_immed (tree tree_val, bool min32int = true);
173 hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
174 void *operator new (size_t);
175 ~hsa_op_immed ();
176 void set_type (BrigKind16_t t);
178 /* Function returns pointer to a buffer that contains binary representation
179 of the immeadiate value. The buffer has length of BRIG_SIZE and
180 a caller is responsible for deallocation of the buffer. */
181 char *emit_to_buffer (unsigned *brig_size);
183 /* Value as represented by middle end. */
184 tree m_tree_value;
186 /* Integer value representation. */
187 HOST_WIDE_INT m_int_value;
189 private:
190 /* Make the default constructor inaccessible. */
191 hsa_op_immed ();
192 /* All objects are deallocated by destroying their pool, so make delete
193 inaccessible too. */
194 void operator delete (void *) {}
197 /* Report whether or not P is a an immediate operand. */
199 template <>
200 template <>
201 inline bool
202 is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
204 return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
207 /* Likewise, but for a more specified base. */
209 template <>
210 template <>
211 inline bool
212 is_a_helper <hsa_op_immed *>::test (hsa_op_with_type *p)
214 return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
218 /* HSA register operand. */
220 class hsa_op_reg : public hsa_op_with_type
222 friend class hsa_insn_basic;
223 friend class hsa_insn_phi;
224 public:
225 hsa_op_reg (BrigType16_t t);
226 void *operator new (size_t);
228 /* Verify register operand. */
229 void verify_ssa ();
231 /* If NON-NULL, gimple SSA that we come from. NULL if none. */
232 tree m_gimple_ssa;
234 /* Defining instruction while still in the SSA. */
235 hsa_insn_basic *m_def_insn;
237 /* If the register allocator decides to spill the register, this is the
238 appropriate spill symbol. */
239 hsa_symbol *m_spill_sym;
241 /* Number of this register structure in the order in which they were
242 allocated. */
243 int m_order;
244 int m_lr_begin, m_lr_end;
246 /* Zero if the register is not yet allocated. After, allocation, this must
247 be 'c', 's', 'd' or 'q'. */
248 char m_reg_class;
249 /* If allocated, the number of the HW register (within its HSA register
250 class). */
251 char m_hard_num;
253 private:
254 /* Make the default constructor inaccessible. */
255 hsa_op_reg () : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
256 /* All objects are deallocated by destroying their pool, so make delete
257 inaccessible too. */
258 void operator delete (void *) {}
259 /* Set definition where the register is defined. */
260 void set_definition (hsa_insn_basic *insn);
261 /* Uses of the value while still in SSA. */
262 auto_vec <hsa_insn_basic_p> m_uses;
265 typedef class hsa_op_reg *hsa_op_reg_p;
267 /* Report whether or not P is a register operand. */
269 template <>
270 template <>
271 inline bool
272 is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
274 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
277 /* Report whether or not P is a register operand. */
279 template <>
280 template <>
281 inline bool
282 is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
284 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
287 /* An address HSA operand. */
289 class hsa_op_address : public hsa_op_base
291 public:
292 /* set up a new address operand consisting of base symbol SYM, register R and
293 immediate OFFSET. If the machine model is not large and offset is 64 bit,
294 the upper, 32 bits have to be zero. */
295 hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
296 HOST_WIDE_INT offset = 0);
298 void *operator new (size_t);
300 /* Set up a new address operand consisting of base symbol SYM and
301 immediate OFFSET. If the machine model is not large and offset is 64 bit,
302 the upper, 32 bits have to be zero. */
303 hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
305 /* Set up a new address operand consisting of register R and
306 immediate OFFSET. If the machine model is not large and offset is 64 bit,
307 the upper, 32 bits have to be zero. */
308 hsa_op_address (hsa_op_reg *reg, HOST_WIDE_INT offset = 0);
310 /* Symbol base of the address. Can be NULL if there is none. */
311 hsa_symbol *m_symbol;
313 /* Register offset. Can be NULL if there is none. */
314 hsa_op_reg *m_reg;
316 /* Immediate byte offset. */
317 HOST_WIDE_INT m_imm_offset;
319 private:
320 /* Make the default constructor inaccessible. */
321 hsa_op_address () : hsa_op_base (BRIG_KIND_NONE) {}
322 /* All objects are deallocated by destroying their pool, so make delete
323 inaccessible too. */
324 void operator delete (void *) {}
327 /* Report whether or not P is an address operand. */
329 template <>
330 template <>
331 inline bool
332 is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
334 return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
337 /* A reference to code HSA operand. It can be either reference
338 to a start of a BB or a start of a function. */
340 class hsa_op_code_ref : public hsa_op_base
342 public:
343 hsa_op_code_ref ();
345 /* Offset in the code section that this refers to. */
346 unsigned m_directive_offset;
349 /* Report whether or not P is a code reference operand. */
351 template <>
352 template <>
353 inline bool
354 is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
356 return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
359 /* Code list HSA operand. */
361 class hsa_op_code_list: public hsa_op_base
363 public:
364 hsa_op_code_list (unsigned elements);
365 void *operator new (size_t);
367 /* Offset to variable-sized array in hsa_data section, where
368 are offsets to entries in the hsa_code section. */
369 auto_vec<unsigned> m_offsets;
370 private:
371 /* Make the default constructor inaccessible. */
372 hsa_op_code_list () : hsa_op_base (BRIG_KIND_NONE) {}
373 /* All objects are deallocated by destroying their pool, so make delete
374 inaccessible too. */
375 void operator delete (void *) {}
378 /* Report whether or not P is a code list operand. */
380 template <>
381 template <>
382 inline bool
383 is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
385 return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
388 /* Operand list HSA operand. */
390 class hsa_op_operand_list: public hsa_op_base
392 public:
393 hsa_op_operand_list (unsigned elements);
394 ~hsa_op_operand_list ();
395 void *operator new (size_t);
397 /* Offset to variable-sized array in hsa_data section, where
398 are offsets to entries in the hsa_code section. */
399 auto_vec<unsigned> m_offsets;
400 private:
401 /* Make the default constructor inaccessible. */
402 hsa_op_operand_list () : hsa_op_base (BRIG_KIND_NONE) {}
403 /* All objects are deallocated by destroying their pool, so make delete
404 inaccessible too. */
405 void operator delete (void *) {}
408 /* Report whether or not P is a code list operand. */
410 template <>
411 template <>
412 inline bool
413 is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
415 return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
418 /* Opcodes of instructions that are not part of HSA but that we use to
419 represent it nevertheless. */
421 #define HSA_OPCODE_PHI (-1)
422 #define HSA_OPCODE_ARG_BLOCK (-2)
424 /* The number of operand pointers we can directly in an instruction. */
425 #define HSA_BRIG_INT_STORAGE_OPERANDS 5
427 /* Class representing an HSA instruction. Unlike typical ancestors for
428 specialized classes, this one is also directly used for all instructions
429 that are then represented as BrigInstBasic. */
431 class hsa_insn_basic
433 public:
434 hsa_insn_basic (unsigned nops, int opc);
435 hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
436 hsa_op_base *arg0 = NULL,
437 hsa_op_base *arg1 = NULL,
438 hsa_op_base *arg2 = NULL,
439 hsa_op_base *arg3 = NULL);
441 void *operator new (size_t);
442 void set_op (int index, hsa_op_base *op);
443 hsa_op_base *get_op (int index);
444 hsa_op_base **get_op_addr (int index);
445 unsigned int operand_count ();
446 void verify ();
447 unsigned input_count ();
448 unsigned num_used_ops ();
449 void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
450 bool op_output_p (unsigned opnum);
452 /* The previous and next instruction in the basic block. */
453 hsa_insn_basic *m_prev, *m_next;
455 /* Basic block this instruction belongs to. */
456 basic_block m_bb;
458 /* Operand code distinguishing different types of instructions. Eventually
459 these should only be BRIG_INST_* values from the BrigOpcode16_t range but
460 initially we use negative values for PHI nodes and such. */
461 int m_opcode;
463 /* Linearized number assigned to the instruction by HSA RA. */
464 int m_number;
466 /* Type of the destination of the operations. */
467 BrigType16_t m_type;
469 /* BRIG offset of the instruction in code section. */
470 unsigned int m_brig_offset;
472 private:
473 /* Make the default constructor inaccessible. */
474 hsa_insn_basic () {}
475 /* All objects are deallocated by destroying their pool, so make delete
476 inaccessible too. */
477 void operator delete (void *) {}
478 /* The individual operands. All instructions but PHI nodes have five or
479 fewer instructions and so will fit the internal storage. */
480 /* TODO: Vast majority of instructions have three or fewer operands, so we
481 may actually try reducing it. */
482 auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands;
485 /* Class representing a PHI node of the SSA form of HSA virtual
486 registers. */
488 class hsa_insn_phi : public hsa_insn_basic
490 public:
491 hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
493 void *operator new (size_t);
495 /* Destination. */
496 hsa_op_reg *m_dest;
498 private:
499 /* Make the default constructor inaccessible. */
500 hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
501 /* All objects are deallocated by destroying their pool, so make delete
502 inaccessible too. */
503 void operator delete (void *) {}
506 /* Report whether or not P is a PHI node. */
508 template <>
509 template <>
510 inline bool
511 is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
513 return p->m_opcode == HSA_OPCODE_PHI;
516 /* HSA instruction for branches. Currently we explicitely represent only
517 conditional branches. */
519 class hsa_insn_br : public hsa_insn_basic
521 public:
522 hsa_insn_br (hsa_op_reg *ctrl);
524 void *operator new (size_t);
526 /* Width as described in HSA documentation. */
527 BrigWidth8_t m_width;
528 private:
529 /* Make the default constructor inaccessible. */
530 hsa_insn_br () : hsa_insn_basic (1, BRIG_OPCODE_CBR) {}
531 /* All objects are deallocated by destroying their pool, so make delete
532 inaccessible too. */
533 void operator delete (void *) {}
536 /* Report whether P is a branching instruction. */
538 template <>
539 template <>
540 inline bool
541 is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
543 return p->m_opcode == BRIG_OPCODE_BR
544 || p->m_opcode == BRIG_OPCODE_CBR;
547 /* HSA instruction for switch branches. */
549 class hsa_insn_sbr : public hsa_insn_basic
551 public:
552 hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
554 /* Default destructor. */
555 ~hsa_insn_sbr ();
557 void *operator new (size_t);
559 void replace_all_labels (basic_block old_bb, basic_block new_bb);
561 /* Width as described in HSA documentation. */
562 BrigWidth8_t m_width;
564 /* Jump table. */
565 vec <basic_block> m_jump_table;
567 /* Code list for label references. */
568 hsa_op_code_list *m_label_code_list;
570 private:
571 /* Make the default constructor inaccessible. */
572 hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
573 /* All objects are deallocated by destroying their pool, so make delete
574 inaccessible too. */
575 void operator delete (void *) {}
578 /* Report whether P is a switch branching instruction. */
580 template <>
581 template <>
582 inline bool
583 is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
585 return p->m_opcode == BRIG_OPCODE_SBR;
588 /* HSA instruction for comparisons. */
590 class hsa_insn_cmp : public hsa_insn_basic
592 public:
593 hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
594 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
595 hsa_op_base *arg2 = NULL);
597 void *operator new (size_t);
599 /* Source type should be derived from operand types. */
601 /* The comparison operation. */
602 BrigCompareOperation8_t m_compare;
604 /* TODO: Modifiers and packing control are missing but so are everywhere
605 else. */
606 private:
607 /* Make the default constructor inaccessible. */
608 hsa_insn_cmp () : hsa_insn_basic (1, BRIG_OPCODE_CMP) {}
609 /* All objects are deallocated by destroying their pool, so make delete
610 inaccessible too. */
611 void operator delete (void *) {}
614 /* Report whether or not P is a comparison instruction. */
616 template <>
617 template <>
618 inline bool
619 is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
621 return p->m_opcode == BRIG_OPCODE_CMP;
624 /* HSA instruction for memory operations. */
626 class hsa_insn_mem : public hsa_insn_basic
628 public:
629 hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
631 void *operator new (size_t);
633 /* Set alignment to VALUE. */
635 void set_align (BrigAlignment8_t value);
637 /* The segment is of the memory access is either the segment of the symbol in
638 the address operand or flat address is there is no symbol there. */
640 /* Required alignment of the memory operation. */
641 BrigAlignment8_t m_align;
643 /* HSA equiv class, basically an alias set number. */
644 uint8_t m_equiv_class;
646 /* TODO: Add width modifier, perhaps also other things. */
647 protected:
648 hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
649 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
650 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
652 private:
653 /* Make the default constructor inaccessible. */
654 hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
655 /* All objects are deallocated by destroying their pool, so make delete
656 inaccessible too. */
657 void operator delete (void *) {}
660 /* Report whether or not P is a memory instruction. */
662 template <>
663 template <>
664 inline bool
665 is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
667 return (p->m_opcode == BRIG_OPCODE_LD
668 || p->m_opcode == BRIG_OPCODE_ST);
671 /* HSA instruction for atomic operations. */
673 class hsa_insn_atomic : public hsa_insn_mem
675 public:
676 hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
677 BrigType16_t t, BrigMemoryOrder memorder,
678 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
679 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
680 void *operator new (size_t);
682 /* The operation itself. */
683 enum BrigAtomicOperation m_atomicop;
685 /* Things like acquire/release/aligned. */
686 enum BrigMemoryOrder m_memoryorder;
688 /* Scope of the atomic operation. */
689 enum BrigMemoryScope m_memoryscope;
691 private:
692 /* Make the default constructor inaccessible. */
693 hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
694 /* All objects are deallocated by destroying their pool, so make delete
695 inaccessible too. */
696 void operator delete (void *) {}
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_atomic
714 public:
715 hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
716 BrigType16_t t, hsa_op_base *arg0 = NULL,
717 hsa_op_base *arg1 = NULL,
718 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
720 void *operator new (size_t);
722 private:
723 /* All objects are deallocated by destroying their pool, so make delete
724 inaccessible too. */
725 void operator delete (void *) {}
728 /* Report whether or not P is a signal instruction. */
730 template <>
731 template <>
732 inline bool
733 is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
735 return (p->m_opcode == BRIG_OPCODE_SIGNAL
736 || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
739 /* HSA instruction to convert between flat addressing and segments. */
741 class hsa_insn_seg : public hsa_insn_basic
743 public:
744 hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
745 BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
747 void *operator new (size_t);
749 /* Source type. Depends on the source addressing/segment. */
750 BrigType16_t m_src_type;
751 /* The segment we are converting from or to. */
752 BrigSegment8_t m_segment;
753 private:
754 /* Make the default constructor inaccessible. */
755 hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
756 /* All objects are deallocated by destroying their pool, so make delete
757 inaccessible too. */
758 void operator delete (void *) {}
761 /* Report whether or not P is a segment conversion instruction. */
763 template <>
764 template <>
765 inline bool
766 is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
768 return (p->m_opcode == BRIG_OPCODE_STOF
769 || p->m_opcode == BRIG_OPCODE_FTOS);
772 /* Class for internal functions for purpose of HSA emission. */
774 class hsa_internal_fn
776 public:
777 hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
778 m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
780 hsa_internal_fn (const hsa_internal_fn *f):
781 m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
782 m_offset (f->m_offset) {}
784 /* Return arity of the internal function. */
785 unsigned get_arity ();
787 /* Return BRIG type of N-th argument, if -1 is passed, return value type
788 is received. */
789 BrigType16_t get_argument_type (int n);
791 /* Return function name. The memory must be released by a caller. */
792 char *name ();
794 /* Internal function. */
795 enum internal_fn m_fn;
797 /* Bit width of return type. */
798 unsigned m_type_bit_size;
800 /* BRIG offset of declaration of the function. */
801 BrigCodeOffset32_t m_offset;
804 /* HSA instruction for function call. */
806 class hsa_insn_call : public hsa_insn_basic
808 public:
809 hsa_insn_call (tree callee);
810 hsa_insn_call (hsa_internal_fn *fn);
812 /* Default destructor. */
813 ~hsa_insn_call ();
815 void *operator new (size_t);
817 /* Called function. */
818 tree m_called_function;
820 /* Called internal function. */
821 hsa_internal_fn *m_called_internal_fn;
823 /* Input formal arguments. */
824 auto_vec <hsa_symbol *> m_input_args;
826 /* Input arguments store instructions. */
827 auto_vec <hsa_insn_mem *> m_input_arg_insns;
829 /* Output argument, can be NULL for void functions. */
830 hsa_symbol *m_output_arg;
832 /* Called function code reference. */
833 hsa_op_code_ref m_func;
835 /* Code list for arguments of the function. */
836 hsa_op_code_list *m_args_code_list;
838 /* Code list for result of the function. */
839 hsa_op_code_list *m_result_code_list;
840 private:
841 /* Make the default constructor inaccessible. */
842 hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
843 /* All objects are deallocated by destroying their pool, so make delete
844 inaccessible too. */
845 void operator delete (void *) {}
848 /* Report whether or not P is a call instruction. */
850 template <>
851 template <>
852 inline bool
853 is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
855 return (p->m_opcode == BRIG_OPCODE_CALL);
858 /* HSA call instruction block encapsulates definition of arguments,
859 result type, corresponding loads and a possible store.
860 Moreover, it contains a single call instruction.
861 Emission of the instruction will produce multiple
862 HSAIL instructions. */
864 class hsa_insn_arg_block : public hsa_insn_basic
866 public:
867 hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
869 void *operator new (size_t);
871 /* Kind of argument block. */
872 BrigKind m_kind;
874 /* Call instruction. */
875 hsa_insn_call *m_call_insn;
876 private:
877 /* All objects are deallocated by destroying their pool, so make delete
878 inaccessible too. */
879 void operator delete (void *) {}
882 /* Report whether or not P is a call block instruction. */
884 template <>
885 template <>
886 inline bool
887 is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
889 return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
892 /* HSA comment instruction. */
894 class hsa_insn_comment: public hsa_insn_basic
896 public:
897 /* Constructor of class representing the comment in HSAIL. */
898 hsa_insn_comment (const char *s);
900 /* Default destructor. */
901 ~hsa_insn_comment ();
903 void *operator new (size_t);
905 char *m_comment;
908 /* Report whether or not P is a call block instruction. */
910 template <>
911 template <>
912 inline bool
913 is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
915 return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
918 /* HSA queue instruction. */
920 class hsa_insn_queue: public hsa_insn_basic
922 public:
923 hsa_insn_queue (int nops, BrigOpcode opcode);
925 /* Destructor. */
926 ~hsa_insn_queue ();
929 /* Report whether or not P is a queue instruction. */
931 template <>
932 template <>
933 inline bool
934 is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
936 return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX);
939 /* HSA source type instruction. */
941 class hsa_insn_srctype: public hsa_insn_basic
943 public:
944 hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
945 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
946 hsa_op_base *arg2);
948 /* Pool allocator. */
949 void *operator new (size_t);
951 /* Source type. */
952 BrigType16_t m_source_type;
954 /* Destructor. */
955 ~hsa_insn_srctype ();
958 /* Report whether or not P is a source type instruction. */
960 template <>
961 template <>
962 inline bool
963 is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
965 return (p->m_opcode == BRIG_OPCODE_POPCOUNT
966 || p->m_opcode == BRIG_OPCODE_FIRSTBIT
967 || p->m_opcode == BRIG_OPCODE_LASTBIT);
970 /* HSA packed instruction. */
972 class hsa_insn_packed : public hsa_insn_srctype
974 public:
975 hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
976 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
977 hsa_op_base *arg2);
979 /* Pool allocator. */
980 void *operator new (size_t);
982 /* Operand list for an operand of the instruction. */
983 hsa_op_operand_list *m_operand_list;
985 /* Destructor. */
986 ~hsa_insn_packed ();
989 /* Report whether or not P is a combine instruction. */
991 template <>
992 template <>
993 inline bool
994 is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
996 return (p->m_opcode == BRIG_OPCODE_COMBINE
997 || p->m_opcode == BRIG_OPCODE_EXPAND);
1000 /* HSA convert instruction. */
1002 class hsa_insn_cvt: public hsa_insn_basic
1004 public:
1005 hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
1007 /* Pool allocator. */
1008 void *operator new (size_t);
1011 /* Report whether or not P is a convert instruction. */
1013 template <>
1014 template <>
1015 inline bool
1016 is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
1018 return (p->m_opcode == BRIG_OPCODE_CVT);
1021 /* HSA alloca instruction. */
1023 class hsa_insn_alloca: public hsa_insn_basic
1025 public:
1026 hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
1027 unsigned alignment = 0);
1029 /* Required alignment of the allocation. */
1030 BrigAlignment8_t m_align;
1032 /* Pool allocator. */
1033 void *operator new (size_t);
1036 /* Report whether or not P is an alloca instruction. */
1038 template <>
1039 template <>
1040 inline bool
1041 is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
1043 return (p->m_opcode == BRIG_OPCODE_ALLOCA);
1046 /* Basic block of HSA instructions. */
1048 class hsa_bb
1050 public:
1051 hsa_bb (basic_block cfg_bb);
1052 hsa_bb (basic_block cfg_bb, int idx);
1053 ~hsa_bb ();
1055 /* Append an instruction INSN into the basic block. */
1056 void append_insn (hsa_insn_basic *insn);
1058 /* The real CFG BB that this HBB belongs to. */
1059 basic_block m_bb;
1061 /* The operand that refers to the label to this BB. */
1062 hsa_op_code_ref m_label_ref;
1064 /* The first and last instruction. */
1065 hsa_insn_basic *m_first_insn, *m_last_insn;
1066 /* The first and last phi node. */
1067 hsa_insn_phi *m_first_phi, *m_last_phi;
1069 /* Just a number to construct names from. */
1070 int m_index;
1072 bitmap m_liveout, m_livein;
1073 private:
1074 /* Make the default constructor inaccessible. */
1075 hsa_bb ();
1076 /* All objects are deallocated by destroying their pool, so make delete
1077 inaccessible too. */
1078 void operator delete (void *) {}
1081 /* Return the corresponding HSA basic block structure for the given control
1082 flow basic_block BB. */
1084 static inline hsa_bb *
1085 hsa_bb_for_bb (basic_block bb)
1087 return (struct hsa_bb *) bb->aux;
1090 /* Class for hashing local hsa_symbols. */
1092 struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
1094 static inline hashval_t hash (const value_type);
1095 static inline bool equal (const value_type, const compare_type);
1098 /* Hash hsa_symbol. */
1100 inline hashval_t
1101 hsa_noop_symbol_hasher::hash (const value_type item)
1103 return DECL_UID (item->m_decl);
1106 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1108 inline bool
1109 hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
1111 return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
1114 /* Structure that encapsulates intermediate representation of a HSA
1115 function. */
1117 class hsa_function_representation
1119 public:
1120 hsa_function_representation (tree fdecl, bool kernel_p,
1121 unsigned ssa_names_count,
1122 bool modified_cfg = false);
1123 hsa_function_representation (hsa_internal_fn *fn);
1124 ~hsa_function_representation ();
1126 /* Builds a shadow register that is utilized to a kernel dispatch. */
1127 hsa_op_reg *get_shadow_reg ();
1129 /* Return true if we are in a function that has kernel dispatch
1130 shadow register. */
1131 bool has_shadow_reg_p ();
1133 /* The entry/exit blocks don't contain incoming code,
1134 but the HSA generator might use them to put code into,
1135 so we need hsa_bb instances of them. */
1136 void init_extra_bbs ();
1138 /* Update CFG dominators if m_modified_cfg flag is set. */
1139 void update_dominance ();
1141 /* Return linkage of the representation. */
1142 BrigLinkage8_t get_linkage ();
1144 /* Create a private symbol of requested TYPE. */
1145 hsa_symbol *create_hsa_temporary (BrigType16_t type);
1147 /* Lookup or create a HSA pseudo register for a given gimple SSA name. */
1148 hsa_op_reg *reg_for_gimple_ssa (tree ssa);
1150 /* Name of the function. */
1151 char *m_name;
1153 /* Number of allocated register structures. */
1154 int m_reg_count;
1156 /* Input arguments. */
1157 vec <hsa_symbol *> m_input_args;
1159 /* Output argument or NULL if there is none. */
1160 hsa_symbol *m_output_arg;
1162 /* Hash table of local variable symbols. */
1163 hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
1165 /* Hash map for string constants. */
1166 hash_map <tree, hsa_symbol *> m_string_constants_map;
1168 /* Vector of pointers to spill symbols. */
1169 vec <struct hsa_symbol *> m_spill_symbols;
1171 /* Vector of pointers to global variables and transformed string constants
1172 that are used by the function. */
1173 vec <struct hsa_symbol *> m_global_symbols;
1175 /* Private function artificial variables. */
1176 vec <struct hsa_symbol *> m_private_variables;
1178 /* Vector of called function declarations. */
1179 vec <tree> m_called_functions;
1181 /* Vector of used internal functions. */
1182 vec <hsa_internal_fn *> m_called_internal_fns;
1184 /* Number of HBB BBs. */
1185 int m_hbb_count;
1187 /* Whether or not we could check and enforce SSA properties. */
1188 bool m_in_ssa;
1190 /* True if the function is kernel function. */
1191 bool m_kern_p;
1193 /* True if the function representation is a declaration. */
1194 bool m_declaration_p;
1196 /* Function declaration tree. */
1197 tree m_decl;
1199 /* Internal function info is used for declarations of internal functions. */
1200 hsa_internal_fn *m_internal_fn;
1202 /* Runtime shadow register. */
1203 hsa_op_reg *m_shadow_reg;
1205 /* Number of kernel dispatched which take place in the function. */
1206 unsigned m_kernel_dispatch_count;
1208 /* If the function representation contains a kernel dispatch,
1209 OMP data size is necessary memory that is used for copying before
1210 a kernel dispatch. */
1211 unsigned m_maximum_omp_data_size;
1213 /* Return true if there's an HSA-specific warning already seen. */
1214 bool m_seen_error;
1216 /* Counter for temporary symbols created in the function representation. */
1217 unsigned m_temp_symbol_count;
1219 /* SSA names mapping. */
1220 vec <hsa_op_reg_p> m_ssa_map;
1222 /* Flag whether a function needs update of dominators before RA. */
1223 bool m_modified_cfg;
1226 enum hsa_function_kind
1228 HSA_NONE,
1229 HSA_KERNEL,
1230 HSA_FUNCTION
1233 struct hsa_function_summary
1235 /* Default constructor. */
1236 hsa_function_summary ();
1238 /* Kind of GPU/host function. */
1239 hsa_function_kind m_kind;
1241 /* Pointer to a cgraph node which is a HSA implementation of the function.
1242 In case of the function is a HSA function, the binded function points
1243 to the host function. */
1244 cgraph_node *m_binded_function;
1246 /* Identifies if the function is an HSA function or a host function. */
1247 bool m_gpu_implementation_p;
1249 /* True if the function is a gridified kernel. */
1250 bool m_gridified_kernel_p;
1253 inline
1254 hsa_function_summary::hsa_function_summary (): m_kind (HSA_NONE),
1255 m_binded_function (NULL), m_gpu_implementation_p (false)
1259 /* Function summary for HSA functions. */
1260 class hsa_summary_t: public function_summary <hsa_function_summary *>
1262 public:
1263 hsa_summary_t (symbol_table *table):
1264 function_summary<hsa_function_summary *> (table) { }
1266 /* Couple GPU and HOST as gpu-specific and host-specific implementation of
1267 the same function. KIND determines whether GPU is a host-invokable kernel
1268 or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
1269 gridified in OMP. */
1271 void link_functions (cgraph_node *gpu, cgraph_node *host,
1272 hsa_function_kind kind, bool gridified_kernel_p);
1275 /* OMP simple builtin describes behavior that should be done for
1276 the routine. */
1277 class omp_simple_builtin
1279 public:
1280 omp_simple_builtin (const char *name, const char *warning_message,
1281 bool sorry, hsa_op_immed *return_value = NULL):
1282 m_name (name), m_warning_message (warning_message), m_sorry (sorry),
1283 m_return_value (return_value)
1286 /* Generate HSAIL instructions for the builtin or produce warning message. */
1287 void generate (gimple *stmt, hsa_bb *hbb);
1289 /* Name of function. */
1290 const char *m_name;
1292 /* Warning message. */
1293 const char *m_warning_message;
1295 /* Flag if we should sorry after the warning message is printed. */
1296 bool m_sorry;
1298 /* Return value of the function. */
1299 hsa_op_immed *m_return_value;
1301 /* Emission function. */
1302 void (*m_emit_func) (gimple *stmt, hsa_bb *);
1305 /* Class for hashing hsa_internal_fn. */
1307 struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
1309 static inline hashval_t hash (const value_type);
1310 static inline bool equal (const value_type, const compare_type);
1313 /* Hash hsa_symbol. */
1315 inline hashval_t
1316 hsa_internal_fn_hasher::hash (const value_type item)
1318 return item->m_fn;
1321 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1323 inline bool
1324 hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
1326 return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
1329 /* in hsa.c */
1330 extern struct hsa_function_representation *hsa_cfun;
1331 extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
1332 extern hsa_summary_t *hsa_summaries;
1333 extern hsa_symbol *hsa_num_threads;
1334 extern unsigned hsa_kernel_calls_counter;
1335 extern hash_set <tree> *hsa_failed_functions;
1336 extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
1338 bool hsa_callable_function_p (tree fndecl);
1339 void hsa_init_compilation_unit_data (void);
1340 void hsa_deinit_compilation_unit_data (void);
1341 bool hsa_machine_large_p (void);
1342 bool hsa_full_profile_p (void);
1343 bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
1344 unsigned hsa_type_bit_size (BrigType16_t t);
1345 BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
1346 BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
1347 BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
1348 BrigType16_t hsa_bittype_for_type (BrigType16_t t);
1349 BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
1350 bool hsa_type_packed_p (BrigType16_t type);
1351 bool hsa_type_float_p (BrigType16_t type);
1352 bool hsa_type_integer_p (BrigType16_t type);
1353 bool hsa_btype_p (BrigType16_t type);
1354 BrigAlignment8_t hsa_alignment_encoding (unsigned n);
1355 BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
1356 BrigAlignment8_t hsa_object_alignment (tree t);
1357 unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
1358 void hsa_destroy_operand (hsa_op_base *op);
1359 void hsa_destroy_insn (hsa_insn_basic *insn);
1360 void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
1361 unsigned hsa_get_number_decl_kernel_mappings (void);
1362 tree hsa_get_decl_kernel_mapping_decl (unsigned i);
1363 char *hsa_get_decl_kernel_mapping_name (unsigned i);
1364 unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
1365 bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
1366 void hsa_free_decl_kernel_mapping (void);
1367 tree *hsa_get_ctor_statements (void);
1368 tree *hsa_get_dtor_statements (void);
1369 tree *hsa_get_kernel_dispatch_type (void);
1370 void hsa_add_kernel_dependency (tree caller, const char *called_function);
1371 void hsa_sanitize_name (char *p);
1372 char *hsa_brig_function_name (const char *p);
1373 const char *hsa_get_declaration_name (tree decl);
1374 void hsa_register_kernel (cgraph_node *host);
1375 void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
1376 bool hsa_seen_error (void);
1377 void hsa_fail_cfun (void);
1379 /* In hsa-gen.c. */
1380 void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
1381 hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
1382 hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
1383 hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1384 hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1385 hsa_bb *hsa_init_new_bb (basic_block);
1386 hsa_function_representation *hsa_generate_function_declaration (tree decl);
1387 hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
1388 tree hsa_get_host_function (tree decl);
1390 /* In hsa-regalloc.c. */
1391 void hsa_regalloc (void);
1393 /* In hsa-brig.c. */
1394 extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
1395 void hsa_brig_emit_function (void);
1396 void hsa_output_brig (void);
1397 unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
1398 void hsa_brig_emit_omp_symbols (void);
1400 /* In hsa-dump.c. */
1401 const char *hsa_seg_name (BrigSegment8_t);
1402 void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
1403 void dump_hsa_bb (FILE *, hsa_bb *);
1404 void dump_hsa_cfun (FILE *);
1405 DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
1406 DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
1408 union hsa_bytes
1410 uint8_t b8;
1411 uint16_t b16;
1412 uint32_t b32;
1413 uint64_t b64;
1416 /* Return true if a function DECL is an HSA implementation. */
1418 static inline bool
1419 hsa_gpu_implementation_p (tree decl)
1421 if (hsa_summaries == NULL)
1422 return false;
1424 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
1426 return s->m_gpu_implementation_p;
1429 #endif /* HSA_H */