123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419 |
- /* HSAIL and BRIG related macros and definitions.
- Copyright (C) 2013-2020 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. */
- class hsa_symbol
- {
- public:
- /* 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 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 (class 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 <class hsa_symbol *> m_spill_symbols;
- /* Vector of pointers to global variables and transformed string constants
- that are used by the function. */
- vec <class hsa_symbol *> m_global_symbols;
- /* Private function artificial variables. */
- vec <class 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
- };
- class hsa_function_summary
- {
- public:
- /* 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 class 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 */
|