1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417 |
- /* HSAIL and BRIG related macros and definitions.
- Copyright (C) 2013-2019 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #ifndef HSA_H
- #define HSA_H
- #include "hsa-brig-format.h"
- #include "is-a.h"
- #include "predict.h"
- #include "tree.h"
- #include "vec.h"
- #include "hash-table.h"
- #include "basic-block.h"
- #include "bitmap.h"
- /* Return true if the compiler should produce HSAIL. */
- static inline bool
- hsa_gen_requested_p (void)
- {
- #ifndef ENABLE_HSA
- return false;
- #endif
- return !flag_disable_hsa;
- }
- /* Standard warning message if we failed to generate HSAIL for a function. */
- #define HSA_SORRY_MSG "could not emit HSAIL for the function"
- class hsa_op_immed;
- class hsa_op_cst_list;
- class hsa_insn_basic;
- class hsa_op_address;
- class hsa_op_reg;
- class hsa_bb;
- /* Class representing an input argument, output argument (result) or a
- variable, that will eventually end up being a symbol directive. */
- struct hsa_symbol
- {
- /* Constructor. */
- hsa_symbol (BrigType16_t type, BrigSegment8_t segment,
- BrigLinkage8_t linkage, bool global_scope_p = false,
- BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC,
- BrigAlignment8_t align = BRIG_ALIGNMENT_8);
- /* Return total size of the symbol. */
- unsigned HOST_WIDE_INT total_byte_size ();
- /* Fill in those values into the symbol according to DECL, which are
- determined independently from whether it is parameter, result,
- or a variable, local or global. */
- void fillup_for_decl (tree decl);
- /* Pointer to the original tree, which is PARM_DECL for input parameters and
- RESULT_DECL for the output parameters. Also can be CONST_DECL for Fortran
- constants which need to be put into readonly segment. */
- tree m_decl;
- /* Name of the symbol, that will be written into output and dumps. Can be
- NULL, see name_number below. */
- const char *m_name;
- /* If name is NULL, artificial name will be formed from the segment name and
- this number. */
- int m_name_number;
- /* Once written, this is the offset of the associated symbol directive. Zero
- means the symbol has not been written yet. */
- unsigned m_directive_offset;
- /* HSA type of the parameter. */
- BrigType16_t m_type;
- /* The HSA segment this will eventually end up in. */
- BrigSegment8_t m_segment;
- /* The HSA kind of linkage. */
- BrigLinkage8_t m_linkage;
- /* Array dimension, if non-zero. */
- unsigned HOST_WIDE_INT m_dim;
- /* Constant value, used for string constants. */
- hsa_op_immed *m_cst_value;
- /* Is in global scope. */
- bool m_global_scope_p;
- /* True if an error has been seen for the symbol. */
- bool m_seen_error;
- /* Symbol allocation. */
- BrigAllocation m_allocation;
- /* Flag used for global variables if a variable is already emitted or not. */
- bool m_emitted_to_brig;
- /* Alignment of the symbol. */
- BrigAlignment8_t m_align;
- private:
- /* Default constructor. */
- hsa_symbol ();
- };
- /* Abstract class for HSA instruction operands. */
- class hsa_op_base
- {
- public:
- /* Next operand scheduled to be written when writing BRIG operand
- section. */
- hsa_op_base *m_next;
- /* Offset to which the associated operand structure will be written. Zero if
- yet not scheduled for writing. */
- unsigned m_brig_op_offset;
- /* The type of a particular operand. */
- BrigKind16_t m_kind;
- protected:
- hsa_op_base (BrigKind16_t k);
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_base () {}
- };
- /* Common abstract ancestor for operands which have a type. */
- class hsa_op_with_type : public hsa_op_base
- {
- public:
- /* The type. */
- BrigType16_t m_type;
- /* Convert an operand to a destination type DTYPE and attach insns
- to HBB if needed. */
- hsa_op_with_type *get_in_type (BrigType16_t dtype, hsa_bb *hbb);
- /* If this operand has integer type smaller than 32 bits, extend it to 32
- bits, adding instructions to HBB if needed. */
- hsa_op_with_type *extend_int_to_32bit (hsa_bb *hbb);
- protected:
- hsa_op_with_type (BrigKind16_t k, BrigType16_t t);
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_with_type () : hsa_op_base (BRIG_KIND_NONE) {}
- };
- /* An immediate HSA operand. */
- class hsa_op_immed : public hsa_op_with_type
- {
- public:
- hsa_op_immed (tree tree_val, bool min32int = true);
- hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
- void *operator new (size_t);
- ~hsa_op_immed ();
- void set_type (BrigKind16_t t);
- /* Function returns pointer to a buffer that contains binary representation
- of the immeadiate value. The buffer has length of BRIG_SIZE and
- a caller is responsible for deallocation of the buffer. */
- char *emit_to_buffer (unsigned *brig_size);
- /* Value as represented by middle end. */
- tree m_tree_value;
- /* Integer value representation. */
- HOST_WIDE_INT m_int_value;
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_immed ();
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- };
- /* Report whether or not P is a an immediate operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_immed *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
- }
- /* Likewise, but for a more specified base. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_immed *>::test (hsa_op_with_type *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_CONSTANT_BYTES;
- }
- /* HSA register operand. */
- class hsa_op_reg : public hsa_op_with_type
- {
- friend class hsa_insn_basic;
- friend class hsa_insn_phi;
- public:
- hsa_op_reg (BrigType16_t t);
- void *operator new (size_t);
- /* Verify register operand. */
- void verify_ssa ();
- /* If NON-NULL, gimple SSA that we come from. NULL if none. */
- tree m_gimple_ssa;
- /* Defining instruction while still in the SSA. */
- hsa_insn_basic *m_def_insn;
- /* If the register allocator decides to spill the register, this is the
- appropriate spill symbol. */
- hsa_symbol *m_spill_sym;
- /* Number of this register structure in the order in which they were
- allocated. */
- int m_order;
- int m_lr_begin, m_lr_end;
- /* Zero if the register is not yet allocated. After, allocation, this must
- be 'c', 's', 'd' or 'q'. */
- char m_reg_class;
- /* If allocated, the number of the HW register (within its HSA register
- class). */
- char m_hard_num;
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_reg () : hsa_op_with_type (BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- /* Set definition where the register is defined. */
- void set_definition (hsa_insn_basic *insn);
- /* Uses of the value while still in SSA. */
- auto_vec <hsa_insn_basic *> m_uses;
- };
- /* Report whether or not P is a register operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_reg *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
- }
- /* Report whether or not P is a register operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_reg *>::test (hsa_op_with_type *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_REGISTER;
- }
- /* An address HSA operand. */
- class hsa_op_address : public hsa_op_base
- {
- public:
- /* set up a new address operand consisting of base symbol SYM, register R and
- immediate OFFSET. If the machine model is not large and offset is 64 bit,
- the upper, 32 bits have to be zero. */
- hsa_op_address (hsa_symbol *sym, hsa_op_reg *reg,
- HOST_WIDE_INT offset = 0);
- void *operator new (size_t);
- /* Set up a new address operand consisting of base symbol SYM and
- immediate OFFSET. If the machine model is not large and offset is 64 bit,
- the upper, 32 bits have to be zero. */
- hsa_op_address (hsa_symbol *sym, HOST_WIDE_INT offset = 0);
- /* Set up a new address operand consisting of register R and
- immediate OFFSET. If the machine model is not large and offset is 64 bit,
- the upper, 32 bits have to be zero. */
- hsa_op_address (hsa_op_reg *reg, HOST_WIDE_INT offset = 0);
- /* Symbol base of the address. Can be NULL if there is none. */
- hsa_symbol *m_symbol;
- /* Register offset. Can be NULL if there is none. */
- hsa_op_reg *m_reg;
- /* Immediate byte offset. */
- HOST_WIDE_INT m_imm_offset;
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_address () : hsa_op_base (BRIG_KIND_NONE) {}
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- };
- /* Report whether or not P is an address operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_address *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_ADDRESS;
- }
- /* A reference to code HSA operand. It can be either reference
- to a start of a BB or a start of a function. */
- class hsa_op_code_ref : public hsa_op_base
- {
- public:
- hsa_op_code_ref ();
- /* Offset in the code section that this refers to. */
- unsigned m_directive_offset;
- };
- /* Report whether or not P is a code reference operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_code_ref *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_CODE_REF;
- }
- /* Code list HSA operand. */
- class hsa_op_code_list: public hsa_op_base
- {
- public:
- hsa_op_code_list (unsigned elements);
- void *operator new (size_t);
- /* Offset to variable-sized array in hsa_data section, where
- are offsets to entries in the hsa_code section. */
- auto_vec<unsigned> m_offsets;
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_code_list () : hsa_op_base (BRIG_KIND_NONE) {}
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- };
- /* Report whether or not P is a code list operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_code_list *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_CODE_LIST;
- }
- /* Operand list HSA operand. */
- class hsa_op_operand_list: public hsa_op_base
- {
- public:
- hsa_op_operand_list (unsigned elements);
- ~hsa_op_operand_list ();
- void *operator new (size_t);
- /* Offset to variable-sized array in hsa_data section, where
- are offsets to entries in the hsa_code section. */
- auto_vec<unsigned> m_offsets;
- private:
- /* Make the default constructor inaccessible. */
- hsa_op_operand_list () : hsa_op_base (BRIG_KIND_NONE) {}
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- };
- /* Report whether or not P is a code list operand. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_op_operand_list *>::test (hsa_op_base *p)
- {
- return p->m_kind == BRIG_KIND_OPERAND_OPERAND_LIST;
- }
- /* Opcodes of instructions that are not part of HSA but that we use to
- represent it nevertheless. */
- #define HSA_OPCODE_PHI (-1)
- #define HSA_OPCODE_ARG_BLOCK (-2)
- /* The number of operand pointers we can directly in an instruction. */
- #define HSA_BRIG_INT_STORAGE_OPERANDS 5
- /* Class representing an HSA instruction. Unlike typical ancestors for
- specialized classes, this one is also directly used for all instructions
- that are then represented as BrigInstBasic. */
- class hsa_insn_basic
- {
- public:
- hsa_insn_basic (unsigned nops, int opc);
- hsa_insn_basic (unsigned nops, int opc, BrigType16_t t,
- hsa_op_base *arg0 = NULL,
- hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL,
- hsa_op_base *arg3 = NULL);
- void *operator new (size_t);
- void set_op (int index, hsa_op_base *op);
- hsa_op_base *get_op (int index);
- hsa_op_base **get_op_addr (int index);
- unsigned int operand_count ();
- void verify ();
- unsigned input_count ();
- unsigned num_used_ops ();
- void set_output_in_type (hsa_op_reg *dest, unsigned op_index, hsa_bb *hbb);
- bool op_output_p (unsigned opnum);
- /* The previous and next instruction in the basic block. */
- hsa_insn_basic *m_prev, *m_next;
- /* Basic block this instruction belongs to. */
- basic_block m_bb;
- /* Operand code distinguishing different types of instructions. Eventually
- these should only be BRIG_INST_* values from the BrigOpcode16_t range but
- initially we use negative values for PHI nodes and such. */
- int m_opcode;
- /* Linearized number assigned to the instruction by HSA RA. */
- int m_number;
- /* Type of the destination of the operations. */
- BrigType16_t m_type;
- /* BRIG offset of the instruction in code section. */
- unsigned int m_brig_offset;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_basic () {}
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- /* The individual operands. All instructions but PHI nodes have five or
- fewer instructions and so will fit the internal storage. */
- /* TODO: Vast majority of instructions have three or fewer operands, so we
- may actually try reducing it. */
- auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands;
- };
- /* Class representing a PHI node of the SSA form of HSA virtual
- registers. */
- class hsa_insn_phi : public hsa_insn_basic
- {
- public:
- hsa_insn_phi (unsigned nops, hsa_op_reg *dst);
- /* Destination. */
- hsa_op_reg *m_dest;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_phi () : hsa_insn_basic (1, HSA_OPCODE_PHI) {}
- };
- /* Report whether or not P is a PHI node. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_phi *>::test (hsa_insn_basic *p)
- {
- return p->m_opcode == HSA_OPCODE_PHI;
- }
- /* HSA instruction for */
- class hsa_insn_br : public hsa_insn_basic
- {
- public:
- hsa_insn_br (unsigned nops, int opc, BrigType16_t t, BrigWidth8_t width,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
- /* Number of work-items affected in the same way by the instruction. */
- BrigWidth8_t m_width;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_br () : hsa_insn_basic (0, BRIG_OPCODE_BR) {}
- };
- /* Return true if P is a branching/synchronization instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_br *>::test (hsa_insn_basic *p)
- {
- return p->m_opcode == BRIG_OPCODE_BARRIER
- || p->m_opcode == BRIG_OPCODE_BR;
- }
- /* HSA instruction for conditional branches. Structurally the same as
- hsa_insn_br but we represent it specially because of inherent control
- flow it represents. */
- class hsa_insn_cbr : public hsa_insn_br
- {
- public:
- hsa_insn_cbr (hsa_op_reg *ctrl);
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_cbr () : hsa_insn_br (0, BRIG_OPCODE_CBR, BRIG_TYPE_B1,
- BRIG_WIDTH_1) {}
- };
- /* Report whether P is a contitional branching instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_cbr *>::test (hsa_insn_basic *p)
- {
- return p->m_opcode == BRIG_OPCODE_CBR;
- }
- /* HSA instruction for switch branches. */
- class hsa_insn_sbr : public hsa_insn_basic
- {
- public:
- hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count);
- /* Default destructor. */
- ~hsa_insn_sbr ();
- void replace_all_labels (basic_block old_bb, basic_block new_bb);
- /* Width as described in HSA documentation. */
- BrigWidth8_t m_width;
- /* Jump table. */
- vec <basic_block> m_jump_table;
- /* Code list for label references. */
- hsa_op_code_list *m_label_code_list;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_sbr () : hsa_insn_basic (1, BRIG_OPCODE_SBR) {}
- };
- /* Report whether P is a switch branching instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_sbr *>::test (hsa_insn_basic *p)
- {
- return p->m_opcode == BRIG_OPCODE_SBR;
- }
- /* HSA instruction for comparisons. */
- class hsa_insn_cmp : public hsa_insn_basic
- {
- public:
- hsa_insn_cmp (BrigCompareOperation8_t cmp, BrigType16_t t,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL);
- /* Source type should be derived from operand types. */
- /* The comparison operation. */
- BrigCompareOperation8_t m_compare;
- /* TODO: Modifiers and packing control are missing but so are everywhere
- else. */
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_cmp () : hsa_insn_basic (1, BRIG_OPCODE_CMP) {}
- };
- /* Report whether or not P is a comparison instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_cmp *>::test (hsa_insn_basic *p)
- {
- return p->m_opcode == BRIG_OPCODE_CMP;
- }
- /* HSA instruction for memory operations. */
- class hsa_insn_mem : public hsa_insn_basic
- {
- public:
- hsa_insn_mem (int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1);
- /* Set alignment to VALUE. */
- void set_align (BrigAlignment8_t value);
- /* The segment is of the memory access is either the segment of the symbol in
- the address operand or flat address is there is no symbol there. */
- /* Required alignment of the memory operation. */
- BrigAlignment8_t m_align;
- /* HSA equiv class, basically an alias set number. */
- uint8_t m_equiv_class;
- /* TODO: Add width modifier, perhaps also other things. */
- protected:
- hsa_insn_mem (unsigned nops, int opc, BrigType16_t t,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_mem () : hsa_insn_basic (1, BRIG_OPCODE_LD) {}
- };
- /* Report whether or not P is a memory instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_mem *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_LD
- || p->m_opcode == BRIG_OPCODE_ST);
- }
- /* HSA instruction for atomic operations. */
- class hsa_insn_atomic : public hsa_insn_mem
- {
- public:
- hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop,
- BrigType16_t t, BrigMemoryOrder memorder,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
- /* The operation itself. */
- enum BrigAtomicOperation m_atomicop;
- /* Things like acquire/release/aligned. */
- enum BrigMemoryOrder m_memoryorder;
- /* Scope of the atomic operation. */
- enum BrigMemoryScope m_memoryscope;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_atomic () : hsa_insn_mem (1, BRIG_KIND_NONE, BRIG_TYPE_NONE) {}
- };
- /* Report whether or not P is an atomic instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_atomic *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_ATOMIC
- || p->m_opcode == BRIG_OPCODE_ATOMICNORET);
- }
- /* HSA instruction for signal operations. */
- class hsa_insn_signal : public hsa_insn_basic
- {
- public:
- hsa_insn_signal (int nops, int opc, enum BrigAtomicOperation sop,
- BrigType16_t t, BrigMemoryOrder memorder,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
- /* Things like acquire/release/aligned. */
- enum BrigMemoryOrder m_memory_order;
- /* The operation itself. */
- enum BrigAtomicOperation m_signalop;
- };
- /* Report whether or not P is a signal instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_signal *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_SIGNAL
- || p->m_opcode == BRIG_OPCODE_SIGNALNORET);
- }
- /* HSA instruction to convert between flat addressing and segments. */
- class hsa_insn_seg : public hsa_insn_basic
- {
- public:
- hsa_insn_seg (int opc, BrigType16_t destt, BrigType16_t srct,
- BrigSegment8_t seg, hsa_op_base *arg0, hsa_op_base *arg1);
- /* Source type. Depends on the source addressing/segment. */
- BrigType16_t m_src_type;
- /* The segment we are converting from or to. */
- BrigSegment8_t m_segment;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_seg () : hsa_insn_basic (1, BRIG_OPCODE_STOF) {}
- };
- /* Report whether or not P is a segment conversion instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_seg *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_STOF
- || p->m_opcode == BRIG_OPCODE_FTOS);
- }
- /* Class for internal functions for purpose of HSA emission. */
- class hsa_internal_fn
- {
- public:
- hsa_internal_fn (enum internal_fn fn, unsigned type_bit_size):
- m_fn (fn), m_type_bit_size (type_bit_size), m_offset (0) {}
- hsa_internal_fn (const hsa_internal_fn *f):
- m_fn (f->m_fn), m_type_bit_size (f->m_type_bit_size),
- m_offset (f->m_offset) {}
- /* Return arity of the internal function. */
- unsigned get_arity ();
- /* Return BRIG type of N-th argument, if -1 is passed, return value type
- is received. */
- BrigType16_t get_argument_type (int n);
- /* Return function name. The memory must be released by a caller. */
- char *name ();
- /* Internal function. */
- enum internal_fn m_fn;
- /* Bit width of return type. */
- unsigned m_type_bit_size;
- /* BRIG offset of declaration of the function. */
- BrigCodeOffset32_t m_offset;
- };
- /* HSA instruction for function call. */
- class hsa_insn_call : public hsa_insn_basic
- {
- public:
- hsa_insn_call (tree callee);
- hsa_insn_call (hsa_internal_fn *fn);
- /* Default destructor. */
- ~hsa_insn_call ();
- /* Called function. */
- tree m_called_function;
- /* Called internal function. */
- hsa_internal_fn *m_called_internal_fn;
- /* Input formal arguments. */
- auto_vec <hsa_symbol *> m_input_args;
- /* Input arguments store instructions. */
- auto_vec <hsa_insn_mem *> m_input_arg_insns;
- /* Output argument, can be NULL for void functions. */
- hsa_symbol *m_output_arg;
- /* Called function code reference. */
- hsa_op_code_ref m_func;
- /* Code list for arguments of the function. */
- hsa_op_code_list *m_args_code_list;
- /* Code list for result of the function. */
- hsa_op_code_list *m_result_code_list;
- private:
- /* Make the default constructor inaccessible. */
- hsa_insn_call () : hsa_insn_basic (0, BRIG_OPCODE_CALL) {}
- };
- /* Report whether or not P is a call instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_call *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_CALL);
- }
- /* HSA call instruction block encapsulates definition of arguments,
- result type, corresponding loads and a possible store.
- Moreover, it contains a single call instruction.
- Emission of the instruction will produce multiple
- HSAIL instructions. */
- class hsa_insn_arg_block : public hsa_insn_basic
- {
- public:
- hsa_insn_arg_block (BrigKind brig_kind, hsa_insn_call * call);
- /* Kind of argument block. */
- BrigKind m_kind;
- /* Call instruction. */
- hsa_insn_call *m_call_insn;
- };
- /* Report whether or not P is a call block instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_arg_block *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == HSA_OPCODE_ARG_BLOCK);
- }
- /* HSA comment instruction. */
- class hsa_insn_comment: public hsa_insn_basic
- {
- public:
- /* Constructor of class representing the comment in HSAIL. */
- hsa_insn_comment (const char *s);
- /* Default destructor. */
- ~hsa_insn_comment ();
- char *m_comment;
- };
- /* Report whether or not P is a call block instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_comment *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_KIND_DIRECTIVE_COMMENT);
- }
- /* HSA queue instruction. */
- class hsa_insn_queue: public hsa_insn_basic
- {
- public:
- hsa_insn_queue (int nops, int opcode, BrigSegment segment,
- BrigMemoryOrder memory_order,
- hsa_op_base *arg0 = NULL, hsa_op_base *arg1 = NULL,
- hsa_op_base *arg2 = NULL, hsa_op_base *arg3 = NULL);
- /* Destructor. */
- ~hsa_insn_queue ();
- /* Segment used to refer to the queue. Must be global or flat. */
- BrigSegment m_segment;
- /* Memory order used to specify synchronization. */
- BrigMemoryOrder m_memory_order;
- };
- /* Report whether or not P is a queue instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_queue *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX
- || p->m_opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX
- || p->m_opcode == BRIG_OPCODE_LDQUEUEREADINDEX
- || p->m_opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
- || p->m_opcode == BRIG_OPCODE_STQUEUEREADINDEX
- || p->m_opcode == BRIG_OPCODE_STQUEUEWRITEINDEX);
- }
- /* HSA source type instruction. */
- class hsa_insn_srctype: public hsa_insn_basic
- {
- public:
- hsa_insn_srctype (int nops, BrigOpcode opcode, BrigType16_t destt,
- BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
- hsa_op_base *arg2);
- /* Source type. */
- BrigType16_t m_source_type;
- /* Destructor. */
- ~hsa_insn_srctype ();
- };
- /* Report whether or not P is a source type instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_srctype *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_POPCOUNT
- || p->m_opcode == BRIG_OPCODE_FIRSTBIT
- || p->m_opcode == BRIG_OPCODE_LASTBIT);
- }
- /* HSA packed instruction. */
- class hsa_insn_packed : public hsa_insn_srctype
- {
- public:
- hsa_insn_packed (int nops, BrigOpcode opcode, BrigType16_t destt,
- BrigType16_t srct, hsa_op_base *arg0, hsa_op_base *arg1,
- hsa_op_base *arg2);
- /* Operand list for an operand of the instruction. */
- hsa_op_operand_list *m_operand_list;
- /* Destructor. */
- ~hsa_insn_packed ();
- };
- /* Report whether or not P is a combine instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_packed *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_COMBINE
- || p->m_opcode == BRIG_OPCODE_EXPAND);
- }
- /* HSA convert instruction. */
- class hsa_insn_cvt: public hsa_insn_basic
- {
- public:
- hsa_insn_cvt (hsa_op_with_type *dest, hsa_op_with_type *src);
- };
- /* Report whether or not P is a convert instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_cvt *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_CVT);
- }
- /* HSA alloca instruction. */
- class hsa_insn_alloca: public hsa_insn_basic
- {
- public:
- hsa_insn_alloca (hsa_op_with_type *dest, hsa_op_with_type *size,
- unsigned alignment = 0);
- /* Required alignment of the allocation. */
- BrigAlignment8_t m_align;
- };
- /* Report whether or not P is an alloca instruction. */
- template <>
- template <>
- inline bool
- is_a_helper <hsa_insn_alloca *>::test (hsa_insn_basic *p)
- {
- return (p->m_opcode == BRIG_OPCODE_ALLOCA);
- }
- /* Basic block of HSA instructions. */
- class hsa_bb
- {
- public:
- hsa_bb (basic_block cfg_bb);
- hsa_bb (basic_block cfg_bb, int idx);
- /* Append an instruction INSN into the basic block. */
- void append_insn (hsa_insn_basic *insn);
- /* Add a PHI instruction. */
- void append_phi (hsa_insn_phi *phi);
- /* The real CFG BB that this HBB belongs to. */
- basic_block m_bb;
- /* The operand that refers to the label to this BB. */
- hsa_op_code_ref m_label_ref;
- /* The first and last instruction. */
- hsa_insn_basic *m_first_insn, *m_last_insn;
- /* The first and last phi node. */
- hsa_insn_phi *m_first_phi, *m_last_phi;
- /* Just a number to construct names from. */
- int m_index;
- auto_bitmap m_liveout, m_livein;
- private:
- /* Make the default constructor inaccessible. */
- hsa_bb ();
- /* All objects are deallocated by destroying their pool, so make delete
- inaccessible too. */
- void operator delete (void *) {}
- };
- /* Return the corresponding HSA basic block structure for the given control
- flow basic_block BB. */
- static inline hsa_bb *
- hsa_bb_for_bb (basic_block bb)
- {
- return (struct hsa_bb *) bb->aux;
- }
- /* Class for hashing local hsa_symbols. */
- struct hsa_noop_symbol_hasher : nofree_ptr_hash <hsa_symbol>
- {
- static inline hashval_t hash (const value_type);
- static inline bool equal (const value_type, const compare_type);
- };
- /* Hash hsa_symbol. */
- inline hashval_t
- hsa_noop_symbol_hasher::hash (const value_type item)
- {
- return DECL_UID (item->m_decl);
- }
- /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
- inline bool
- hsa_noop_symbol_hasher::equal (const value_type a, const compare_type b)
- {
- return (DECL_UID (a->m_decl) == DECL_UID (b->m_decl));
- }
- /* Structure that encapsulates intermediate representation of a HSA
- function. */
- class hsa_function_representation
- {
- public:
- hsa_function_representation (tree fdecl, bool kernel_p,
- unsigned ssa_names_count,
- bool modified_cfg = false);
- hsa_function_representation (hsa_internal_fn *fn);
- ~hsa_function_representation ();
- /* Builds a shadow register that is utilized to a kernel dispatch. */
- hsa_op_reg *get_shadow_reg ();
- /* Return true if we are in a function that has kernel dispatch
- shadow register. */
- bool has_shadow_reg_p ();
- /* The entry/exit blocks don't contain incoming code,
- but the HSA generator might use them to put code into,
- so we need hsa_bb instances of them. */
- void init_extra_bbs ();
- /* Update CFG dominators if m_modified_cfg flag is set. */
- void update_dominance ();
- /* Return linkage of the representation. */
- BrigLinkage8_t get_linkage ();
- /* Create a private symbol of requested TYPE. */
- hsa_symbol *create_hsa_temporary (BrigType16_t type);
- /* Lookup or create a HSA pseudo register for a given gimple SSA name. */
- hsa_op_reg *reg_for_gimple_ssa (tree ssa);
- /* Name of the function. */
- char *m_name;
- /* Number of allocated register structures. */
- int m_reg_count;
- /* Input arguments. */
- vec <hsa_symbol *> m_input_args;
- /* Output argument or NULL if there is none. */
- hsa_symbol *m_output_arg;
- /* Hash table of local variable symbols. */
- hash_table <hsa_noop_symbol_hasher> *m_local_symbols;
- /* Hash map for string constants. */
- hash_map <tree, hsa_symbol *> m_string_constants_map;
- /* Vector of pointers to spill symbols. */
- vec <struct hsa_symbol *> m_spill_symbols;
- /* Vector of pointers to global variables and transformed string constants
- that are used by the function. */
- vec <struct hsa_symbol *> m_global_symbols;
- /* Private function artificial variables. */
- vec <struct hsa_symbol *> m_private_variables;
- /* Vector of called function declarations. */
- vec <tree> m_called_functions;
- /* Vector of used internal functions. */
- vec <hsa_internal_fn *> m_called_internal_fns;
- /* Number of HBB BBs. */
- int m_hbb_count;
- /* Whether or not we could check and enforce SSA properties. */
- bool m_in_ssa;
- /* True if the function is kernel function. */
- bool m_kern_p;
- /* True if the function representation is a declaration. */
- bool m_declaration_p;
- /* Function declaration tree. */
- tree m_decl;
- /* Internal function info is used for declarations of internal functions. */
- hsa_internal_fn *m_internal_fn;
- /* Runtime shadow register. */
- hsa_op_reg *m_shadow_reg;
- /* Number of kernel dispatched which take place in the function. */
- unsigned m_kernel_dispatch_count;
- /* If the function representation contains a kernel dispatch,
- OMP data size is necessary memory that is used for copying before
- a kernel dispatch. */
- unsigned m_maximum_omp_data_size;
- /* Return true if there's an HSA-specific warning already seen. */
- bool m_seen_error;
- /* Counter for temporary symbols created in the function representation. */
- unsigned m_temp_symbol_count;
- /* SSA names mapping. */
- vec <hsa_op_reg *> m_ssa_map;
- /* Flag whether a function needs update of dominators before RA. */
- bool m_modified_cfg;
- };
- enum hsa_function_kind
- {
- HSA_INVALID,
- HSA_KERNEL,
- HSA_FUNCTION
- };
- struct hsa_function_summary
- {
- /* Default constructor. */
- hsa_function_summary ();
- /* Kind of GPU/host function. */
- hsa_function_kind m_kind;
- /* Pointer to a cgraph node which is a HSA implementation of the function.
- In case of the function is a HSA function, the bound function points
- to the host function. */
- cgraph_node *m_bound_function;
- /* Identifies if the function is an HSA function or a host function. */
- bool m_gpu_implementation_p;
- /* True if the function is a gridified kernel. */
- bool m_gridified_kernel_p;
- };
- inline
- hsa_function_summary::hsa_function_summary (): m_kind (HSA_INVALID),
- m_bound_function (NULL), m_gpu_implementation_p (false)
- {
- }
- /* Function summary for HSA functions. */
- class hsa_summary_t: public function_summary <hsa_function_summary *>
- {
- public:
- hsa_summary_t (symbol_table *table):
- function_summary<hsa_function_summary *> (table)
- {
- disable_insertion_hook ();
- }
- /* Couple GPU and HOST as gpu-specific and host-specific implementation of
- the same function. KIND determines whether GPU is a host-invokable kernel
- or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
- gridified in OMP. */
- void link_functions (cgraph_node *gpu, cgraph_node *host,
- hsa_function_kind kind, bool gridified_kernel_p);
- private:
- void process_gpu_implementation_attributes (tree gdecl);
- };
- /* OMP simple builtin describes behavior that should be done for
- the routine. */
- class omp_simple_builtin
- {
- public:
- omp_simple_builtin (const char *name, const char *warning_message,
- bool sorry, hsa_op_immed *return_value = NULL):
- m_name (name), m_warning_message (warning_message), m_sorry (sorry),
- m_return_value (return_value)
- {}
- /* Generate HSAIL instructions for the builtin or produce warning message. */
- void generate (gimple *stmt, hsa_bb *hbb);
- /* Name of function. */
- const char *m_name;
- /* Warning message. */
- const char *m_warning_message;
- /* Flag if we should sorry after the warning message is printed. */
- bool m_sorry;
- /* Return value of the function. */
- hsa_op_immed *m_return_value;
- /* Emission function. */
- void (*m_emit_func) (gimple *stmt, hsa_bb *);
- };
- /* Class for hashing hsa_internal_fn. */
- struct hsa_internal_fn_hasher: free_ptr_hash <hsa_internal_fn>
- {
- static inline hashval_t hash (const value_type);
- static inline bool equal (const value_type, const compare_type);
- };
- /* Hash hsa_symbol. */
- inline hashval_t
- hsa_internal_fn_hasher::hash (const value_type item)
- {
- return item->m_fn;
- }
- /* Return true if the DECL_UIDs of decls both symbols refer to are equal. */
- inline bool
- hsa_internal_fn_hasher::equal (const value_type a, const compare_type b)
- {
- return a->m_fn == b->m_fn && a->m_type_bit_size == b->m_type_bit_size;
- }
- /* in hsa-common.c */
- extern struct hsa_function_representation *hsa_cfun;
- extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
- extern hsa_summary_t *hsa_summaries;
- extern hsa_symbol *hsa_num_threads;
- extern unsigned hsa_kernel_calls_counter;
- extern hash_set <tree> *hsa_failed_functions;
- extern hash_table <hsa_noop_symbol_hasher> *hsa_global_variable_symbols;
- bool hsa_callable_function_p (tree fndecl);
- void hsa_init_compilation_unit_data (void);
- void hsa_deinit_compilation_unit_data (void);
- bool hsa_machine_large_p (void);
- bool hsa_full_profile_p (void);
- bool hsa_opcode_floating_bit_insn_p (BrigOpcode16_t);
- unsigned hsa_type_bit_size (BrigType16_t t);
- BrigType16_t hsa_bittype_for_bitsize (unsigned bitsize);
- BrigType16_t hsa_uint_for_bitsize (unsigned bitsize);
- BrigType16_t hsa_float_for_bitsize (unsigned bitsize);
- BrigType16_t hsa_bittype_for_type (BrigType16_t t);
- BrigType16_t hsa_unsigned_type_for_type (BrigType16_t t);
- bool hsa_type_packed_p (BrigType16_t type);
- bool hsa_type_float_p (BrigType16_t type);
- bool hsa_type_integer_p (BrigType16_t type);
- bool hsa_btype_p (BrigType16_t type);
- BrigAlignment8_t hsa_alignment_encoding (unsigned n);
- BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
- BrigAlignment8_t hsa_object_alignment (tree t);
- unsigned hsa_byte_alignment (BrigAlignment8_t alignment);
- void hsa_destroy_operand (hsa_op_base *op);
- void hsa_destroy_insn (hsa_insn_basic *insn);
- void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
- unsigned hsa_get_number_decl_kernel_mappings (void);
- tree hsa_get_decl_kernel_mapping_decl (unsigned i);
- char *hsa_get_decl_kernel_mapping_name (unsigned i);
- unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
- bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
- void hsa_free_decl_kernel_mapping (void);
- tree *hsa_get_ctor_statements (void);
- tree *hsa_get_dtor_statements (void);
- tree *hsa_get_kernel_dispatch_type (void);
- void hsa_add_kernel_dependency (tree caller, const char *called_function);
- void hsa_sanitize_name (char *p);
- char *hsa_brig_function_name (const char *p);
- const char *hsa_get_declaration_name (tree decl);
- void hsa_register_kernel (cgraph_node *host);
- void hsa_register_kernel (cgraph_node *gpu, cgraph_node *host);
- bool hsa_seen_error (void);
- void hsa_fail_cfun (void);
- /* In hsa-gen.c. */
- void hsa_build_append_simple_mov (hsa_op_reg *, hsa_op_base *, hsa_bb *);
- hsa_symbol *hsa_get_spill_symbol (BrigType16_t);
- hsa_symbol *hsa_get_string_cst_symbol (BrigType16_t);
- hsa_op_reg *hsa_spill_in (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
- hsa_op_reg *hsa_spill_out (hsa_insn_basic *, hsa_op_reg *, hsa_op_reg **);
- hsa_bb *hsa_init_new_bb (basic_block);
- hsa_function_representation *hsa_generate_function_declaration (tree decl);
- hsa_function_representation *hsa_generate_internal_fn_decl (hsa_internal_fn *);
- tree hsa_get_host_function (tree decl);
- /* In hsa-regalloc.c. */
- void hsa_regalloc (void);
- /* In hsa-brig.c. */
- extern hash_table <hsa_internal_fn_hasher> *hsa_emitted_internal_decls;
- void hsa_brig_emit_function (void);
- void hsa_output_brig (void);
- unsigned hsa_get_imm_brig_type_len (BrigType16_t type);
- void hsa_brig_emit_omp_symbols (void);
- /* In hsa-dump.c. */
- const char *hsa_seg_name (BrigSegment8_t);
- void dump_hsa_insn (FILE *f, hsa_insn_basic *insn);
- void dump_hsa_bb (FILE *, hsa_bb *);
- void dump_hsa_cfun (FILE *);
- DEBUG_FUNCTION void debug_hsa_operand (hsa_op_base *opc);
- DEBUG_FUNCTION void debug_hsa_insn (hsa_insn_basic *insn);
- union hsa_bytes
- {
- uint8_t b8;
- uint16_t b16;
- uint32_t b32;
- uint64_t b64;
- };
- /* Return true if a function DECL is an HSA implementation. */
- static inline bool
- hsa_gpu_implementation_p (tree decl)
- {
- if (hsa_summaries == NULL)
- return false;
- hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
- return s != NULL && s->m_gpu_implementation_p;
- }
- #endif /* HSA_H */
|