1418 lines
38 KiB
C++
1418 lines
38 KiB
C++
/* 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 */
|