compiler: add containing Bfunction to conditional_expression
[official-gcc.git] / gcc / hsa.h
bloba74f2d9553bb0b4743dfe2e94ead9805402e5497
1 /* HSAIL and BRIG related macros and definitions.
2 Copyright (C) 2013-2017 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;
54 /* Class representing an input argument, output argument (result) or a
55 variable, that will eventually end up being a symbol directive. */
57 struct hsa_symbol
59 /* Constructor. */
60 hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
61 BrigLinkage8_t linkage, bool global_scope_p = false,
62 BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
63 BrigAlignment8_t align = BRIG_ALIGNMENT_8);
65 /* Return total size of the symbol. */
66 unsigned HOST_WIDE_INT total_byte_size ();
68 /* Fill in those values into the symbol according to DECL, which are
69 determined independently from whether it is parameter, result,
70 or a variable, local or global. */
71 void fillup_for_decl (tree decl);
73 /* Pointer to the original tree, which is PARM_DECL for input parameters and
74 RESULT_DECL for the output parameters. Also can be CONST_DECL for Fortran
75 constants which need to be put into readonly segment. */
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 *> m_uses;
265 /* Report whether or not P is a register operand. */
267 template <>
268 template <>
269 inline bool
270 is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
272 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
275 /* Report whether or not P is a register operand. */
277 template <>
278 template <>
279 inline bool
280 is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
282 return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
285 /* An address HSA operand. */
287 class hsa_op_address : public hsa_op_base
289 public:
290 /* set up a new address operand consisting of base symbol SYM, register R and
291 immediate OFFSET. If the machine model is not large and offset is 64 bit,
292 the upper, 32 bits have to be zero. */
293 hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
294 HOST_WIDE_INT offset = 0);
296 void *operator new (size_t);
298 /* Set up a new address operand consisting of base symbol SYM and
299 immediate OFFSET. If the machine model is not large and offset is 64 bit,
300 the upper, 32 bits have to be zero. */
301 hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
303 /* Set up a new address operand consisting of register R 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_op_reg *reg, HOST_WIDE_INT offset = 0);
308 /* Symbol base of the address. Can be NULL if there is none. */
309 hsa_symbol *m_symbol;
311 /* Register offset. Can be NULL if there is none. */
312 hsa_op_reg *m_reg;
314 /* Immediate byte offset. */
315 HOST_WIDE_INT m_imm_offset;
317 private:
318 /* Make the default constructor inaccessible. */
319 hsa_op_address () : hsa_op_base (BRIG_KIND_NONE) {}
320 /* All objects are deallocated by destroying their pool, so make delete
321 inaccessible too. */
322 void operator delete (void *) {}
325 /* Report whether or not P is an address operand. */
327 template <>
328 template <>
329 inline bool
330 is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
332 return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
335 /* A reference to code HSA operand. It can be either reference
336 to a start of a BB or a start of a function. */
338 class hsa_op_code_ref : public hsa_op_base
340 public:
341 hsa_op_code_ref ();
343 /* Offset in the code section that this refers to. */
344 unsigned m_directive_offset;
347 /* Report whether or not P is a code reference operand. */
349 template <>
350 template <>
351 inline bool
352 is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
354 return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
357 /* Code list HSA operand. */
359 class hsa_op_code_list: public hsa_op_base
361 public:
362 hsa_op_code_list (unsigned elements);
363 void *operator new (size_t);
365 /* Offset to variable-sized array in hsa_data section, where
366 are offsets to entries in the hsa_code section. */
367 auto_vec<unsigned> m_offsets;
368 private:
369 /* Make the default constructor inaccessible. */
370 hsa_op_code_list () : hsa_op_base (BRIG_KIND_NONE) {}
371 /* All objects are deallocated by destroying their pool, so make delete
372 inaccessible too. */
373 void operator delete (void *) {}
376 /* Report whether or not P is a code list operand. */
378 template <>
379 template <>
380 inline bool
381 is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
383 return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
386 /* Operand list HSA operand. */
388 class hsa_op_operand_list: public hsa_op_base
390 public:
391 hsa_op_operand_list (unsigned elements);
392 ~hsa_op_operand_list ();
393 void *operator new (size_t);
395 /* Offset to variable-sized array in hsa_data section, where
396 are offsets to entries in the hsa_code section. */
397 auto_vec<unsigned> m_offsets;
398 private:
399 /* Make the default constructor inaccessible. */
400 hsa_op_operand_list () : hsa_op_base (BRIG_KIND_NONE) {}
401 /* All objects are deallocated by destroying their pool, so make delete
402 inaccessible too. */
403 void operator delete (void *) {}
406 /* Report whether or not P is a code list operand. */
408 template <>
409 template <>
410 inline bool
411 is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
413 return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
416 /* Opcodes of instructions that are not part of HSA but that we use to
417 represent it nevertheless. */
419 #define HSA_OPCODE_PHI (-1)
420 #define HSA_OPCODE_ARG_BLOCK (-2)
422 /* The number of operand pointers we can directly in an instruction. */
423 #define HSA_BRIG_INT_STORAGE_OPERANDS 5
425 /* Class representing an HSA instruction. Unlike typical ancestors for
426 specialized classes, this one is also directly used for all instructions
427 that are then represented as BrigInstBasic. */
429 class hsa_insn_basic
431 public:
432 hsa_insn_basic (unsigned nops, int opc);
433 hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
434 hsa_op_base *arg0 = NULL,
435 hsa_op_base *arg1 = NULL,
436 hsa_op_base *arg2 = NULL,
437 hsa_op_base *arg3 = NULL);
439 void *operator new (size_t);
440 void set_op (int index, hsa_op_base *op);
441 hsa_op_base *get_op (int index);
442 hsa_op_base **get_op_addr (int index);
443 unsigned int operand_count ();
444 void verify ();
445 unsigned input_count ();
446 unsigned num_used_ops ();
447 void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
448 bool op_output_p (unsigned opnum);
450 /* The previous and next instruction in the basic block. */
451 hsa_insn_basic *m_prev, *m_next;
453 /* Basic block this instruction belongs to. */
454 basic_block m_bb;
456 /* Operand code distinguishing different types of instructions. Eventually
457 these should only be BRIG_INST_* values from the BrigOpcode16_t range but
458 initially we use negative values for PHI nodes and such. */
459 int m_opcode;
461 /* Linearized number assigned to the instruction by HSA RA. */
462 int m_number;
464 /* Type of the destination of the operations. */
465 BrigType16_t m_type;
467 /* BRIG offset of the instruction in code section. */
468 unsigned int m_brig_offset;
470 private:
471 /* Make the default constructor inaccessible. */
472 hsa_insn_basic () {}
473 /* All objects are deallocated by destroying their pool, so make delete
474 inaccessible too. */
475 void operator delete (void *) {}
476 /* The individual operands. All instructions but PHI nodes have five or
477 fewer instructions and so will fit the internal storage. */
478 /* TODO: Vast majority of instructions have three or fewer operands, so we
479 may actually try reducing it. */
480 auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands;
483 /* Class representing a PHI node of the SSA form of HSA virtual
484 registers. */
486 class hsa_insn_phi : public hsa_insn_basic
488 public:
489 hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
491 /* Destination. */
492 hsa_op_reg *m_dest;
494 private:
495 /* Make the default constructor inaccessible. */
496 hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
499 /* Report whether or not P is a PHI node. */
501 template <>
502 template <>
503 inline bool
504 is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
506 return p->m_opcode == HSA_OPCODE_PHI;
509 /* HSA instruction for */
510 class hsa_insn_br : public hsa_insn_basic
512 public:
513 hsa_insn_br (unsigned nops, int opc, BrigType16_t t, BrigWidth8_t width,
514 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
515 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
517 /* Number of work-items affected in the same way by the instruction. */
518 BrigWidth8_t m_width;
520 private:
521 /* Make the default constructor inaccessible. */
522 hsa_insn_br () : hsa_insn_basic (0, BRIG_OPCODE_BR) {}
525 /* Return true if P is a branching/synchronization instruction. */
527 template <>
528 template <>
529 inline bool
530 is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
532 return p->m_opcode == BRIG_OPCODE_BARRIER
533 || p->m_opcode == BRIG_OPCODE_BR;
536 /* HSA instruction for conditional branches. Structurally the same as
537 hsa_insn_br but we represent it specially because of inherent control
538 flow it represents. */
540 class hsa_insn_cbr : public hsa_insn_br
542 public:
543 hsa_insn_cbr (hsa_op_reg *ctrl);
545 private:
546 /* Make the default constructor inaccessible. */
547 hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
548 BRIG_WIDTH_1) {}
551 /* Report whether P is a contitional branching instruction. */
553 template <>
554 template <>
555 inline bool
556 is_a_helper <hsa_insn_cbr *>::test (hsa_insn_basic *p)
558 return p->m_opcode == BRIG_OPCODE_CBR;
561 /* HSA instruction for switch branches. */
563 class hsa_insn_sbr : public hsa_insn_basic
565 public:
566 hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
568 /* Default destructor. */
569 ~hsa_insn_sbr ();
571 void replace_all_labels (basic_block old_bb, basic_block new_bb);
573 /* Width as described in HSA documentation. */
574 BrigWidth8_t m_width;
576 /* Jump table. */
577 vec <basic_block> m_jump_table;
579 /* Code list for label references. */
580 hsa_op_code_list *m_label_code_list;
582 private:
583 /* Make the default constructor inaccessible. */
584 hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
587 /* Report whether P is a switch branching instruction. */
589 template <>
590 template <>
591 inline bool
592 is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
594 return p->m_opcode == BRIG_OPCODE_SBR;
597 /* HSA instruction for comparisons. */
599 class hsa_insn_cmp : public hsa_insn_basic
601 public:
602 hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
603 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
604 hsa_op_base *arg2 = NULL);
606 /* Source type should be derived from operand types. */
608 /* The comparison operation. */
609 BrigCompareOperation8_t m_compare;
611 /* TODO: Modifiers and packing control are missing but so are everywhere
612 else. */
613 private:
614 /* Make the default constructor inaccessible. */
615 hsa_insn_cmp () : hsa_insn_basic (1, BRIG_OPCODE_CMP) {}
618 /* Report whether or not P is a comparison instruction. */
620 template <>
621 template <>
622 inline bool
623 is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
625 return p->m_opcode == BRIG_OPCODE_CMP;
628 /* HSA instruction for memory operations. */
630 class hsa_insn_mem : public hsa_insn_basic
632 public:
633 hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
635 /* Set alignment to VALUE. */
637 void set_align (BrigAlignment8_t value);
639 /* The segment is of the memory access is either the segment of the symbol in
640 the address operand or flat address is there is no symbol there. */
642 /* Required alignment of the memory operation. */
643 BrigAlignment8_t m_align;
645 /* HSA equiv class, basically an alias set number. */
646 uint8_t m_equiv_class;
648 /* TODO: Add width modifier, perhaps also other things. */
649 protected:
650 hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
651 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
652 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
654 private:
655 /* Make the default constructor inaccessible. */
656 hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
659 /* Report whether or not P is a memory instruction. */
661 template <>
662 template <>
663 inline bool
664 is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
666 return (p->m_opcode == BRIG_OPCODE_LD
667 || p->m_opcode == BRIG_OPCODE_ST);
670 /* HSA instruction for atomic operations. */
672 class hsa_insn_atomic : public hsa_insn_mem
674 public:
675 hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
676 BrigType16_t t, BrigMemoryOrder memorder,
677 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
678 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
680 /* The operation itself. */
681 enum BrigAtomicOperation m_atomicop;
683 /* Things like acquire/release/aligned. */
684 enum BrigMemoryOrder m_memoryorder;
686 /* Scope of the atomic operation. */
687 enum BrigMemoryScope m_memoryscope;
689 private:
690 /* Make the default constructor inaccessible. */
691 hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
694 /* Report whether or not P is an atomic instruction. */
696 template <>
697 template <>
698 inline bool
699 is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
701 return (p->m_opcode == BRIG_OPCODE_ATOMIC
702 || p->m_opcode == BRIG_OPCODE_ATOMICNORET);
705 /* HSA instruction for signal operations. */
707 class hsa_insn_signal : public hsa_insn_basic
709 public:
710 hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
711 BrigType16_t t, BrigMemoryOrder memorder,
712 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
713 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
715 /* Things like acquire/release/aligned. */
716 enum BrigMemoryOrder m_memory_order;
718 /* The operation itself. */
719 enum BrigAtomicOperation m_signalop;
722 /* Report whether or not P is a signal instruction. */
724 template <>
725 template <>
726 inline bool
727 is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
729 return (p->m_opcode == BRIG_OPCODE_SIGNAL
730 || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
733 /* HSA instruction to convert between flat addressing and segments. */
735 class hsa_insn_seg : public hsa_insn_basic
737 public:
738 hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
739 BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
741 /* Source type. Depends on the source addressing/segment. */
742 BrigType16_t m_src_type;
743 /* The segment we are converting from or to. */
744 BrigSegment8_t m_segment;
745 private:
746 /* Make the default constructor inaccessible. */
747 hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
750 /* Report whether or not P is a segment conversion instruction. */
752 template <>
753 template <>
754 inline bool
755 is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
757 return (p->m_opcode == BRIG_OPCODE_STOF
758 || p->m_opcode == BRIG_OPCODE_FTOS);
761 /* Class for internal functions for purpose of HSA emission. */
763 class hsa_internal_fn
765 public:
766 hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
767 m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
769 hsa_internal_fn (const hsa_internal_fn *f):
770 m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
771 m_offset (f->m_offset) {}
773 /* Return arity of the internal function. */
774 unsigned get_arity ();
776 /* Return BRIG type of N-th argument, if -1 is passed, return value type
777 is received. */
778 BrigType16_t get_argument_type (int n);
780 /* Return function name. The memory must be released by a caller. */
781 char *name ();
783 /* Internal function. */
784 enum internal_fn m_fn;
786 /* Bit width of return type. */
787 unsigned m_type_bit_size;
789 /* BRIG offset of declaration of the function. */
790 BrigCodeOffset32_t m_offset;
793 /* HSA instruction for function call. */
795 class hsa_insn_call : public hsa_insn_basic
797 public:
798 hsa_insn_call (tree callee);
799 hsa_insn_call (hsa_internal_fn *fn);
801 /* Default destructor. */
802 ~hsa_insn_call ();
804 /* Called function. */
805 tree m_called_function;
807 /* Called internal function. */
808 hsa_internal_fn *m_called_internal_fn;
810 /* Input formal arguments. */
811 auto_vec <hsa_symbol *> m_input_args;
813 /* Input arguments store instructions. */
814 auto_vec <hsa_insn_mem *> m_input_arg_insns;
816 /* Output argument, can be NULL for void functions. */
817 hsa_symbol *m_output_arg;
819 /* Called function code reference. */
820 hsa_op_code_ref m_func;
822 /* Code list for arguments of the function. */
823 hsa_op_code_list *m_args_code_list;
825 /* Code list for result of the function. */
826 hsa_op_code_list *m_result_code_list;
827 private:
828 /* Make the default constructor inaccessible. */
829 hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
832 /* Report whether or not P is a call instruction. */
834 template <>
835 template <>
836 inline bool
837 is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
839 return (p->m_opcode == BRIG_OPCODE_CALL);
842 /* HSA call instruction block encapsulates definition of arguments,
843 result type, corresponding loads and a possible store.
844 Moreover, it contains a single call instruction.
845 Emission of the instruction will produce multiple
846 HSAIL instructions. */
848 class hsa_insn_arg_block : public hsa_insn_basic
850 public:
851 hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
853 /* Kind of argument block. */
854 BrigKind m_kind;
856 /* Call instruction. */
857 hsa_insn_call *m_call_insn;
860 /* Report whether or not P is a call block instruction. */
862 template <>
863 template <>
864 inline bool
865 is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
867 return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
870 /* HSA comment instruction. */
872 class hsa_insn_comment: public hsa_insn_basic
874 public:
875 /* Constructor of class representing the comment in HSAIL. */
876 hsa_insn_comment (const char *s);
878 /* Default destructor. */
879 ~hsa_insn_comment ();
881 char *m_comment;
884 /* Report whether or not P is a call block instruction. */
886 template <>
887 template <>
888 inline bool
889 is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
891 return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
894 /* HSA queue instruction. */
896 class hsa_insn_queue: public hsa_insn_basic
898 public:
899 hsa_insn_queue (int nops, int opcode, BrigSegment segment,
900 BrigMemoryOrder memory_order,
901 hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
902 hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
904 /* Destructor. */
905 ~hsa_insn_queue ();
907 /* Segment used to refer to the queue. Must be global or flat. */
908 BrigSegment m_segment;
909 /* Memory order used to specify synchronization. */
910 BrigMemoryOrder m_memory_order;
913 /* Report whether or not P is a queue instruction. */
915 template <>
916 template <>
917 inline bool
918 is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
920 return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX
921 || p->m_opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX
922 || p->m_opcode == BRIG_OPCODE_LDQUEUEREADINDEX
923 || p->m_opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
924 || p->m_opcode == BRIG_OPCODE_STQUEUEREADINDEX
925 || p->m_opcode == BRIG_OPCODE_STQUEUEWRITEINDEX);
928 /* HSA source type instruction. */
930 class hsa_insn_srctype: public hsa_insn_basic
932 public:
933 hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
934 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
935 hsa_op_base *arg2);
937 /* Source type. */
938 BrigType16_t m_source_type;
940 /* Destructor. */
941 ~hsa_insn_srctype ();
944 /* Report whether or not P is a source type instruction. */
946 template <>
947 template <>
948 inline bool
949 is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
951 return (p->m_opcode == BRIG_OPCODE_POPCOUNT
952 || p->m_opcode == BRIG_OPCODE_FIRSTBIT
953 || p->m_opcode == BRIG_OPCODE_LASTBIT);
956 /* HSA packed instruction. */
958 class hsa_insn_packed : public hsa_insn_srctype
960 public:
961 hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
962 BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
963 hsa_op_base *arg2);
965 /* Operand list for an operand of the instruction. */
966 hsa_op_operand_list *m_operand_list;
968 /* Destructor. */
969 ~hsa_insn_packed ();
972 /* Report whether or not P is a combine instruction. */
974 template <>
975 template <>
976 inline bool
977 is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
979 return (p->m_opcode == BRIG_OPCODE_COMBINE
980 || p->m_opcode == BRIG_OPCODE_EXPAND);
983 /* HSA convert instruction. */
985 class hsa_insn_cvt: public hsa_insn_basic
987 public:
988 hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
991 /* Report whether or not P is a convert instruction. */
993 template <>
994 template <>
995 inline bool
996 is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
998 return (p->m_opcode == BRIG_OPCODE_CVT);
1001 /* HSA alloca instruction. */
1003 class hsa_insn_alloca: public hsa_insn_basic
1005 public:
1006 hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
1007 unsigned alignment = 0);
1009 /* Required alignment of the allocation. */
1010 BrigAlignment8_t m_align;
1013 /* Report whether or not P is an alloca instruction. */
1015 template <>
1016 template <>
1017 inline bool
1018 is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
1020 return (p->m_opcode == BRIG_OPCODE_ALLOCA);
1023 /* Basic block of HSA instructions. */
1025 class hsa_bb
1027 public:
1028 hsa_bb (basic_block cfg_bb);
1029 hsa_bb (basic_block cfg_bb, int idx);
1030 ~hsa_bb ();
1032 /* Append an instruction INSN into the basic block. */
1033 void append_insn (hsa_insn_basic *insn);
1035 /* Add a PHI instruction. */
1036 void append_phi (hsa_insn_phi *phi);
1038 /* The real CFG BB that this HBB belongs to. */
1039 basic_block m_bb;
1041 /* The operand that refers to the label to this BB. */
1042 hsa_op_code_ref m_label_ref;
1044 /* The first and last instruction. */
1045 hsa_insn_basic *m_first_insn, *m_last_insn;
1046 /* The first and last phi node. */
1047 hsa_insn_phi *m_first_phi, *m_last_phi;
1049 /* Just a number to construct names from. */
1050 int m_index;
1052 bitmap m_liveout, m_livein;
1053 private:
1054 /* Make the default constructor inaccessible. */
1055 hsa_bb ();
1056 /* All objects are deallocated by destroying their pool, so make delete
1057 inaccessible too. */
1058 void operator delete (void *) {}
1061 /* Return the corresponding HSA basic block structure for the given control
1062 flow basic_block BB. */
1064 static inline hsa_bb *
1065 hsa_bb_for_bb (basic_block bb)
1067 return (struct hsa_bb *) bb->aux;
1070 /* Class for hashing local hsa_symbols. */
1072 struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
1074 static inline hashval_t hash (const value_type);
1075 static inline bool equal (const value_type, const compare_type);
1078 /* Hash hsa_symbol. */
1080 inline hashval_t
1081 hsa_noop_symbol_hasher::hash (const value_type item)
1083 return DECL_UID (item->m_decl);
1086 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1088 inline bool
1089 hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
1091 return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
1094 /* Structure that encapsulates intermediate representation of a HSA
1095 function. */
1097 class hsa_function_representation
1099 public:
1100 hsa_function_representation (tree fdecl, bool kernel_p,
1101 unsigned ssa_names_count,
1102 bool modified_cfg = false);
1103 hsa_function_representation (hsa_internal_fn *fn);
1104 ~hsa_function_representation ();
1106 /* Builds a shadow register that is utilized to a kernel dispatch. */
1107 hsa_op_reg *get_shadow_reg ();
1109 /* Return true if we are in a function that has kernel dispatch
1110 shadow register. */
1111 bool has_shadow_reg_p ();
1113 /* The entry/exit blocks don't contain incoming code,
1114 but the HSA generator might use them to put code into,
1115 so we need hsa_bb instances of them. */
1116 void init_extra_bbs ();
1118 /* Update CFG dominators if m_modified_cfg flag is set. */
1119 void update_dominance ();
1121 /* Return linkage of the representation. */
1122 BrigLinkage8_t get_linkage ();
1124 /* Create a private symbol of requested TYPE. */
1125 hsa_symbol *create_hsa_temporary (BrigType16_t type);
1127 /* Lookup or create a HSA pseudo register for a given gimple SSA name. */
1128 hsa_op_reg *reg_for_gimple_ssa (tree ssa);
1130 /* Name of the function. */
1131 char *m_name;
1133 /* Number of allocated register structures. */
1134 int m_reg_count;
1136 /* Input arguments. */
1137 vec <hsa_symbol *> m_input_args;
1139 /* Output argument or NULL if there is none. */
1140 hsa_symbol *m_output_arg;
1142 /* Hash table of local variable symbols. */
1143 hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
1145 /* Hash map for string constants. */
1146 hash_map <tree, hsa_symbol *> m_string_constants_map;
1148 /* Vector of pointers to spill symbols. */
1149 vec <struct hsa_symbol *> m_spill_symbols;
1151 /* Vector of pointers to global variables and transformed string constants
1152 that are used by the function. */
1153 vec <struct hsa_symbol *> m_global_symbols;
1155 /* Private function artificial variables. */
1156 vec <struct hsa_symbol *> m_private_variables;
1158 /* Vector of called function declarations. */
1159 vec <tree> m_called_functions;
1161 /* Vector of used internal functions. */
1162 vec <hsa_internal_fn *> m_called_internal_fns;
1164 /* Number of HBB BBs. */
1165 int m_hbb_count;
1167 /* Whether or not we could check and enforce SSA properties. */
1168 bool m_in_ssa;
1170 /* True if the function is kernel function. */
1171 bool m_kern_p;
1173 /* True if the function representation is a declaration. */
1174 bool m_declaration_p;
1176 /* Function declaration tree. */
1177 tree m_decl;
1179 /* Internal function info is used for declarations of internal functions. */
1180 hsa_internal_fn *m_internal_fn;
1182 /* Runtime shadow register. */
1183 hsa_op_reg *m_shadow_reg;
1185 /* Number of kernel dispatched which take place in the function. */
1186 unsigned m_kernel_dispatch_count;
1188 /* If the function representation contains a kernel dispatch,
1189 OMP data size is necessary memory that is used for copying before
1190 a kernel dispatch. */
1191 unsigned m_maximum_omp_data_size;
1193 /* Return true if there's an HSA-specific warning already seen. */
1194 bool m_seen_error;
1196 /* Counter for temporary symbols created in the function representation. */
1197 unsigned m_temp_symbol_count;
1199 /* SSA names mapping. */
1200 vec <hsa_op_reg *> m_ssa_map;
1202 /* Flag whether a function needs update of dominators before RA. */
1203 bool m_modified_cfg;
1206 enum hsa_function_kind
1208 HSA_NONE,
1209 HSA_KERNEL,
1210 HSA_FUNCTION
1213 struct hsa_function_summary
1215 /* Default constructor. */
1216 hsa_function_summary ();
1218 /* Kind of GPU/host function. */
1219 hsa_function_kind m_kind;
1221 /* Pointer to a cgraph node which is a HSA implementation of the function.
1222 In case of the function is a HSA function, the bound function points
1223 to the host function. */
1224 cgraph_node *m_bound_function;
1226 /* Identifies if the function is an HSA function or a host function. */
1227 bool m_gpu_implementation_p;
1229 /* True if the function is a gridified kernel. */
1230 bool m_gridified_kernel_p;
1233 inline
1234 hsa_function_summary::hsa_function_summary (): m_kind (HSA_NONE),
1235 m_bound_function (NULL), m_gpu_implementation_p (false)
1239 /* Function summary for HSA functions. */
1240 class hsa_summary_t: public function_summary <hsa_function_summary *>
1242 public:
1243 hsa_summary_t (symbol_table *table):
1244 function_summary<hsa_function_summary *> (table) { }
1246 /* Couple GPU and HOST as gpu-specific and host-specific implementation of
1247 the same function. KIND determines whether GPU is a host-invokable kernel
1248 or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
1249 gridified in OMP. */
1251 void link_functions (cgraph_node *gpu, cgraph_node *host,
1252 hsa_function_kind kind, bool gridified_kernel_p);
1254 private:
1255 void process_gpu_implementation_attributes (tree gdecl);
1258 /* OMP simple builtin describes behavior that should be done for
1259 the routine. */
1260 class omp_simple_builtin
1262 public:
1263 omp_simple_builtin (const char *name, const char *warning_message,
1264 bool sorry, hsa_op_immed *return_value = NULL):
1265 m_name (name), m_warning_message (warning_message), m_sorry (sorry),
1266 m_return_value (return_value)
1269 /* Generate HSAIL instructions for the builtin or produce warning message. */
1270 void generate (gimple *stmt, hsa_bb *hbb);
1272 /* Name of function. */
1273 const char *m_name;
1275 /* Warning message. */
1276 const char *m_warning_message;
1278 /* Flag if we should sorry after the warning message is printed. */
1279 bool m_sorry;
1281 /* Return value of the function. */
1282 hsa_op_immed *m_return_value;
1284 /* Emission function. */
1285 void (*m_emit_func) (gimple *stmt, hsa_bb *);
1288 /* Class for hashing hsa_internal_fn. */
1290 struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
1292 static inline hashval_t hash (const value_type);
1293 static inline bool equal (const value_type, const compare_type);
1296 /* Hash hsa_symbol. */
1298 inline hashval_t
1299 hsa_internal_fn_hasher::hash (const value_type item)
1301 return item->m_fn;
1304 /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
1306 inline bool
1307 hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
1309 return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
1312 /* in hsa.c */
1313 extern struct hsa_function_representation *hsa_cfun;
1314 extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
1315 extern hsa_summary_t *hsa_summaries;
1316 extern hsa_symbol *hsa_num_threads;
1317 extern unsigned hsa_kernel_calls_counter;
1318 extern hash_set <tree> *hsa_failed_functions;
1319 extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
1321 bool hsa_callable_function_p (tree fndecl);
1322 void hsa_init_compilation_unit_data (void);
1323 void hsa_deinit_compilation_unit_data (void);
1324 bool hsa_machine_large_p (void);
1325 bool hsa_full_profile_p (void);
1326 bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
1327 unsigned hsa_type_bit_size (BrigType16_t t);
1328 BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
1329 BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
1330 BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
1331 BrigType16_t hsa_bittype_for_type (BrigType16_t t);
1332 BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
1333 bool hsa_type_packed_p (BrigType16_t type);
1334 bool hsa_type_float_p (BrigType16_t type);
1335 bool hsa_type_integer_p (BrigType16_t type);
1336 bool hsa_btype_p (BrigType16_t type);
1337 BrigAlignment8_t hsa_alignment_encoding (unsigned n);
1338 BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
1339 BrigAlignment8_t hsa_object_alignment (tree t);
1340 unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
1341 void hsa_destroy_operand (hsa_op_base *op);
1342 void hsa_destroy_insn (hsa_insn_basic *insn);
1343 void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
1344 unsigned hsa_get_number_decl_kernel_mappings (void);
1345 tree hsa_get_decl_kernel_mapping_decl (unsigned i);
1346 char *hsa_get_decl_kernel_mapping_name (unsigned i);
1347 unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
1348 bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
1349 void hsa_free_decl_kernel_mapping (void);
1350 tree *hsa_get_ctor_statements (void);
1351 tree *hsa_get_dtor_statements (void);
1352 tree *hsa_get_kernel_dispatch_type (void);
1353 void hsa_add_kernel_dependency (tree caller, const char *called_function);
1354 void hsa_sanitize_name (char *p);
1355 char *hsa_brig_function_name (const char *p);
1356 const char *hsa_get_declaration_name (tree decl);
1357 void hsa_register_kernel (cgraph_node *host);
1358 void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
1359 bool hsa_seen_error (void);
1360 void hsa_fail_cfun (void);
1362 /* In hsa-gen.c. */
1363 void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
1364 hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
1365 hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
1366 hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1367 hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
1368 hsa_bb *hsa_init_new_bb (basic_block);
1369 hsa_function_representation *hsa_generate_function_declaration (tree decl);
1370 hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
1371 tree hsa_get_host_function (tree decl);
1373 /* In hsa-regalloc.c. */
1374 void hsa_regalloc (void);
1376 /* In hsa-brig.c. */
1377 extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
1378 void hsa_brig_emit_function (void);
1379 void hsa_output_brig (void);
1380 unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
1381 void hsa_brig_emit_omp_symbols (void);
1383 /* In hsa-dump.c. */
1384 const char *hsa_seg_name (BrigSegment8_t);
1385 void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
1386 void dump_hsa_bb (FILE *, hsa_bb *);
1387 void dump_hsa_cfun (FILE *);
1388 DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
1389 DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
1391 union hsa_bytes
1393 uint8_t b8;
1394 uint16_t b16;
1395 uint32_t b32;
1396 uint64_t b64;
1399 /* Return true if a function DECL is an HSA implementation. */
1401 static inline bool
1402 hsa_gpu_implementation_p (tree decl)
1404 if (hsa_summaries == NULL)
1405 return false;
1407 hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
1409 return s->m_gpu_implementation_p;
1412 #endif /* HSA_H */