Hello. In the following series, I enhance HSA BE to correctly support aggregate types (as function call arguments and return types). Apart from that, we should not ICE in situations where we have a non-trivial memory reference. Finally, many memory leaks were fixed and a lot of refactoring is included.
Martin
>From c5006ca75912bdab8256fe4670645d5f1ad54a14 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Mon, 26 Oct 2015 16:58:26 +0100 Subject: [PATCH 1/9] HSA: fix generation of address that end as SSA_NAME or VAR_DECL. gcc/ChangeLog: 2015-10-22 Martin Liska <mli...@suse.cz> * hsa-brig.c (emit_function_directives): Emit private variables. * hsa-gen.c (hsa_function_representation::~hsa_function_representation): Release the container. (hsa_function_representation::create_hsa_temporary): New function. (gen_hsa_addr): Handle properly SSA_NAMEs and VAR_DECLs. * hsa.h (hsa_function_representation::m_private_variables): Declare new variable. --- gcc/hsa-brig.c | 7 ++++++- gcc/hsa-gen.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- gcc/hsa.h | 14 ++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c index be7ef59..0c26b58 100644 --- a/gcc/hsa-brig.c +++ b/gcc/hsa-brig.c @@ -626,6 +626,7 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration) if (TREE_CODE ((*iter)->m_decl) == VAR_DECL) count++; count += f->m_spill_symbols.length (); + count += f->m_private_variables.length (); } next_toplev_off = scoped_off + count * sizeof (struct BrigDirectiveVariable); @@ -685,7 +686,11 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration) emit_directive_variable (sym); brig_insn_count++; } - + for (unsigned i = 0; i < f->m_private_variables.length (); i++) + { + emit_directive_variable (f->m_private_variables[i]); + brig_insn_count++; + } } return ptr_to_fndir; diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index c36c9e0..15f9050 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -228,10 +228,10 @@ hsa_function_representation::hsa_function_representation (tree fdecl, bool kernel_p): m_name (NULL), m_input_args_count (0), m_reg_count (0), m_input_args (NULL), m_output_arg (NULL), m_spill_symbols (vNULL), m_readonly_variables (vNULL), - m_called_functions (vNULL), m_hbb_count (0), m_in_ssa (true), - m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl), + m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0), + m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl), m_shadow_reg (NULL), m_kernel_dispatch_count (0), m_maximum_omp_data_size (0), - m_seen_error (false) + m_seen_error (false), m_temp_symbol_count (0) { int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;; m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len); @@ -251,6 +251,7 @@ hsa_function_representation::~hsa_function_representation () m_spill_symbols.release (); m_readonly_variables.release (); + m_private_variables.release (); m_called_functions.release (); } @@ -284,6 +285,24 @@ bool hsa_function_representation::has_shadow_reg_p () return m_shadow_reg != NULL; } +void +hsa_function_representation::init_extra_bbs () +{ + hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)); +} + +hsa_symbol * +hsa_function_representation::create_hsa_temporary (BrigType16_t type) +{ + hsa_symbol *s = new hsa_symbol (type, BRIG_SEGMENT_PRIVATE, + BRIG_LINKAGE_FUNCTION); + s->m_name_number = m_temp_symbol_count++; + + hsa_cfun->m_private_variables.safe_push (s); + return s; +} + /* Allocate HSA structures that we need only while generating with this. */ static void @@ -1711,6 +1730,13 @@ process_mem_base (tree base, hsa_symbol **symbol, BrigType16_t *addrtype, gcc_unreachable (); } +/* Forward declaration of a function. */ + +static void +gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb, + vec <hsa_op_reg_p> *ssa_map); + + /* Generate HSA address operand for a given tree memory reference REF. If instructions need to be created to calculate the address, they will be added to the end of HBB, SSA_MAP is an array mapping gimple SSA names to HSA @@ -1731,6 +1757,7 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map, tree varoffset = NULL_TREE; BrigType16_t addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT); HOST_WIDE_INT bitsize = 0, bitpos = 0; + BrigType16_t flat_addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT); if (TREE_CODE (ref) == STRING_CST) { @@ -1762,8 +1789,27 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map, switch (TREE_CODE (ref)) { case ADDR_EXPR: - gcc_unreachable (); + { + addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE); + symbol = hsa_cfun->create_hsa_temporary (flat_addrtype); + hsa_op_reg *r = new hsa_op_reg (flat_addrtype); + gen_hsa_addr_insns (ref, r, hbb, ssa_map); + hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type, + r, new hsa_op_address (symbol))); + + break; + } + case SSA_NAME: + { + addrtype = hsa_get_segment_addr_type (BRIG_SEGMENT_PRIVATE); + symbol = hsa_cfun->create_hsa_temporary (flat_addrtype); + hsa_op_reg *r = hsa_reg_for_gimple_ssa (ref, ssa_map); + + hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, r->m_type, + r, new hsa_op_address (symbol))); + break; + } case PARM_DECL: case VAR_DECL: case RESULT_DECL: @@ -1821,7 +1867,6 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map, HSA_SORRY_AT (EXPR_LOCATION (origref), "support for HSA does not implement function pointers"); goto out; - case SSA_NAME: default: HSA_SORRY_ATV (EXPR_LOCATION (origref), "support for HSA does " "not implement memory access to %E", origref); diff --git a/gcc/hsa.h b/gcc/hsa.h index 3c83d61..d38255f 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -940,6 +940,14 @@ public: 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 (); + + /* Create a private symbol of requested TYPE. */ + hsa_symbol *create_hsa_temporary (BrigType16_t type); + /* Name of the function. */ char *m_name; @@ -967,6 +975,9 @@ public: noni-addressable variables with a constructor). */ vec <struct hsa_symbol *> m_readonly_variables; + /* Private function artificial variables. */ + vec <struct hsa_symbol *> m_private_variables; + /* Vector of called function declarations. */ vec <tree> m_called_functions; @@ -998,6 +1009,9 @@ public: /* 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; }; enum hsa_function_kind -- 2.6.2
>From 592d9c22f378067002ffb6d852049e7ae7acb787 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Mon, 26 Oct 2015 17:04:28 +0100 Subject: [PATCH 2/9] HSA: Support aggregate type as a function return type. gcc/ChangeLog: 2015-10-22 Martin Liska <mli...@suse.cz> * hsa-gen.c (gen_hsa_insns_for_direct_call): Support aggregate type as a function return type. (gen_hsa_insns_for_return): Likewise. (hsa_symbol::total_byte_size): New function. * hsa.h (struct hsa_symbol): Declare it. --- gcc/hsa-gen.c | 82 +++++++++++++++++++++++++++++++++++------------------------ gcc/hsa.h | 6 +++++ 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 15f9050..94e50c8 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -221,6 +221,25 @@ hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment, { } +void * +hsa_symbol::operator new (size_t) +{ + return hsa_allocp_symbols->vallocate (); +} + +unsigned HOST_WIDE_INT +hsa_symbol::total_byte_size () +{ + unsigned HOST_WIDE_INT s = hsa_type_bit_size (~BRIG_TYPE_ARRAY_MASK & m_type); + gcc_assert (s % BITS_PER_UNIT == 0); + s /= BITS_PER_UNIT; + + if (m_dim) + s *= m_dim; + + return s; +} + /* Constructor of class representing global HSA function/kernel information and state. */ @@ -3243,14 +3262,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, hsa_insn_mem *result_insn = NULL; if (!VOID_TYPE_P (result_type)) { - if (AGGREGATE_TYPE_P (result_type)) - { - HSA_SORRY_ATV (gimple_location (stmt), - "support for HSA does not implement returning a value " - "which is of an aggregate type %T", result_type); - return; - } - hsa_op_address *addr = gen_hsa_addr_for_arg (result_type, -1); /* Even if result of a function call is unused, we have to emit @@ -3258,25 +3269,25 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, if (result) { tree lhs_type = TREE_TYPE (result); - if (AGGREGATE_TYPE_P (lhs_type)) - { - HSA_SORRY_ATV (gimple_location (stmt), "support for HSA does not " - "implement assignment of a returned value " - "which is of an aggregate type %T", lhs_type); - return; - } - - BrigType16_t mtype = mem_type_for_type - (hsa_type_for_scalar_tree_type (lhs_type, false)); if (hsa_seen_error ()) return; - hsa_op_reg *dst = hsa_reg_for_gimple_ssa (result, ssa_map); - - result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr); + if (AGGREGATE_TYPE_P (lhs_type)) + { + hsa_op_address *result_addr = gen_hsa_addr (result, hbb, ssa_map); + gen_hsa_memory_copy (hbb, result_addr, addr, + addr->m_symbol->total_byte_size ()); + } + else + { + BrigType16_t mtype = mem_type_for_type + (hsa_type_for_scalar_tree_type (lhs_type, false)); - hbb->append_insn (result_insn); + hsa_op_reg *dst = hsa_reg_for_gimple_ssa (result, ssa_map); + result_insn = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, dst, addr); + hbb->append_insn (result_insn); + } } call_insn->m_output_arg = addr->m_symbol; @@ -3314,21 +3325,26 @@ gen_hsa_insns_for_return (greturn *stmt, hsa_bb *hbb, tree retval = gimple_return_retval (stmt); if (retval) { + hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg); + if (AGGREGATE_TYPE_P (TREE_TYPE (retval))) { - HSA_SORRY_AT (gimple_location (stmt), - "HSA does not support return " - "statement with an aggregate value type"); - return; + hsa_op_address *retval_addr = gen_hsa_addr (retval, hbb, ssa_map); + gen_hsa_memory_copy (hbb, addr, retval_addr, + hsa_cfun->m_output_arg->total_byte_size ()); } + else + { + BrigType16_t mtype = mem_type_for_type + (hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false)); - /* Store of return value. */ - BrigType16_t mtype = mem_type_for_type - (hsa_type_for_scalar_tree_type (TREE_TYPE (retval), false)); - hsa_op_address *addr = new hsa_op_address (hsa_cfun->m_output_arg); - hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (retval, hbb, ssa_map); - hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr); - hbb->append_insn (mem); + /* Store of return value. */ + hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (retval, hbb, + ssa_map); + hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, + addr); + hbb->append_insn (mem); + } } /* HSAIL return instruction emission. */ diff --git a/gcc/hsa.h b/gcc/hsa.h index d38255f..f4184f9 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -60,6 +60,12 @@ struct hsa_symbol hsa_symbol (BrigType16_t type, BrigSegment8_t segment, BrigLinkage8_t linkage); + /* New operator to allocate HSA symbol from pool alloc. */ + void *operator new (size_t); + + /* Return total size of the symbol. */ + unsigned HOST_WIDE_INT total_byte_size (); + /* Pointer to the original tree, which is PARM_DECL for input parameters and RESULT_DECL for the output parameters. */ tree m_decl; -- 2.6.2
>From 5b148fbe1110bcc8a7c826163451e04743b84143 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Mon, 26 Oct 2015 17:05:09 +0100 Subject: [PATCH 3/9] HSA: convert actual argument types to formal types. gcc/ChangeLog: 2015-10-16 Martin Liska <mli...@suse.cz> * hsa-gen.c (gen_hsa_insns_for_direct_call): Convert types of actual arguments to formal types arguments. (get_format_argument_type): New function. (hsa_reg_for_gimple_ssa): Fix coding style. --- gcc/hsa-gen.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 94e50c8..050475c 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -1130,7 +1130,7 @@ hsa_reg_for_gimple_ssa (tree ssa, vec <hsa_op_reg_p> *ssa_map) if ((*ssa_map)[SSA_NAME_VERSION (ssa)]) return (*ssa_map)[SSA_NAME_VERSION (ssa)]; - hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa), + hreg = new hsa_op_reg (hsa_type_for_scalar_tree_type (TREE_TYPE (ssa), true)); hreg->m_gimple_ssa = ssa; (*ssa_map)[SSA_NAME_VERSION (ssa)] = hreg; @@ -3201,6 +3201,20 @@ verify_function_arguments (tree decl) } } +/* Return BRIG type for FORMAL_ARG_TYPE. If the formal argument type is NULL, + return ACTUAL_ARG_TYPE. */ + +static BrigType16_t +get_format_argument_type (tree formal_arg_type, BrigType16_t actual_arg_type) +{ + if (formal_arg_type == NULL) + return actual_arg_type; + + BrigType16_t decl_type = hsa_type_for_scalar_tree_type + (formal_arg_type, false); + return mem_type_for_type (decl_type); +} + /* Generate HSA instructions for a direct call instruction. Instructions will be appended to HBB, which also needs to be the corresponding structure to the basic_block of STMT. SSA_MAP maps gimple SSA @@ -3223,11 +3237,15 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, (BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, call_insn); hbb->append_insn (arg_start); + tree parm_type_chain = TYPE_ARG_TYPES (gimple_call_fntype (stmt)); + /* Preparation of arguments that will be passed to function. */ const unsigned args = gimple_call_num_args (stmt); for (unsigned i = 0; i < args; ++i) { tree parm = gimple_call_arg (stmt, (int)i); + tree parm_decl_type = parm_type_chain != NULL_TREE + ? TREE_VALUE (parm_type_chain) : NULL_TREE; if (AGGREGATE_TYPE_P (TREE_TYPE (parm))) { @@ -3237,20 +3255,36 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, return; } - BrigType16_t mtype = mem_type_for_type (hsa_type_for_scalar_tree_type - (TREE_TYPE (parm), false)); + hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, + ssa_map); + if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type)) + { + HSA_SORRY_AT (gimple_location (stmt), + "support for HSA does not implement an aggregate " + "formal argument in a function call, while actual " + "argument is not an aggregate"); + return; + } + BrigType16_t formal_arg_type = get_format_argument_type + (parm_decl_type, src->m_type); if (hsa_seen_error ()) return; - hsa_op_address *addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i); - hsa_op_base *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, ssa_map); - hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, mtype, src, addr); + if (src->m_type != formal_arg_type) + src = src->get_in_type (formal_arg_type, hbb); + + hsa_op_address *addr = gen_hsa_addr_for_arg + (parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i); + hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type, + src, addr); - call_insn->m_input_args.safe_push (addr->m_symbol); hbb->append_insn (mem); + call_insn->m_input_args.safe_push (addr->m_symbol); call_insn->m_args_symbols.safe_push (addr->m_symbol); + if (parm_type_chain) + parm_type_chain = TREE_CHAIN (parm_type_chain); } call_insn->m_args_code_list = new hsa_op_code_list (args); -- 2.6.2
>From 93f9684b50033e3c68e80ec0fbb25d992e1cafdf Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Thu, 22 Oct 2015 18:22:15 +0200 Subject: [PATCH 4/9] HSA: handle taking an address of an argument. gcc/ChangeLog: 2015-10-22 Martin Liska <mli...@suse.cz> * hsa-gen.c(gen_hsa_insns_for_direct_call): Support aggregate argument types. (gen_function_def_parameters): Copy function arguments to private symbols. --- gcc/hsa-gen.c | 88 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 050475c..ec0762e 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -3246,40 +3246,44 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, tree parm = gimple_call_arg (stmt, (int)i); tree parm_decl_type = parm_type_chain != NULL_TREE ? TREE_VALUE (parm_type_chain) : NULL_TREE; + hsa_op_address *addr; if (AGGREGATE_TYPE_P (TREE_TYPE (parm))) { - HSA_SORRY_AT (gimple_location (stmt), - "support for HSA does not " - "implement an aggregate argument in a function call"); - return; + addr = gen_hsa_addr_for_arg (TREE_TYPE (parm), i); + hsa_op_address *src = gen_hsa_addr (parm, hbb, ssa_map); + gen_hsa_memory_copy (hbb, addr, src, + addr->m_symbol->total_byte_size ()); } - - hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, - ssa_map); - if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type)) + else { - HSA_SORRY_AT (gimple_location (stmt), - "support for HSA does not implement an aggregate " - "formal argument in a function call, while actual " - "argument is not an aggregate"); - return; - } + hsa_op_with_type *src = hsa_reg_or_immed_for_gimple_op (parm, hbb, + ssa_map); - BrigType16_t formal_arg_type = get_format_argument_type - (parm_decl_type, src->m_type); - if (hsa_seen_error ()) - return; + if (parm_decl_type != NULL && AGGREGATE_TYPE_P (parm_decl_type)) + { + HSA_SORRY_AT (gimple_location (stmt), + "support for HSA does not implement an aggregate " + "formal argument in a function call, while actual " + "argument is not an aggregate"); + return; + } - if (src->m_type != formal_arg_type) - src = src->get_in_type (formal_arg_type, hbb); + BrigType16_t formal_arg_type = get_format_argument_type + (parm_decl_type, src->m_type); + if (hsa_seen_error ()) + return; - hsa_op_address *addr = gen_hsa_addr_for_arg - (parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i); - hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type, - src, addr); + if (src->m_type != formal_arg_type) + src = src->get_in_type (formal_arg_type, hbb); - hbb->append_insn (mem); + addr = gen_hsa_addr_for_arg + (parm_decl_type != NULL_TREE ? parm_decl_type: TREE_TYPE (parm), i); + hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_ST, formal_arg_type, + src, addr); + + hbb->append_insn (mem); + } call_insn->m_input_args.safe_push (addr->m_symbol); call_insn->m_args_symbols.safe_push (addr->m_symbol); @@ -4996,14 +5000,33 @@ gen_function_def_parameters (hsa_function_representation *f, f->m_input_args[i].m_segment = f->m_kern_p ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG; - f->m_input_args[i].m_linkage = BRIG_LINKAGE_FUNCTION; f->m_input_args[i].m_name = hsa_get_declaration_name (parm); + hsa_symbol *arg = &f->m_input_args[i]; + + /* Copy all input arguments and create corresponding private symbols + for them. */ + hsa_symbol *private_arg; + hsa_op_address *parm_addr = new hsa_op_address (arg); - slot = f->m_local_symbols->find_slot (&f->m_input_args[i], - INSERT); + if (TREE_ADDRESSABLE (parm) + || (!is_gimple_reg (parm) && !TREE_READONLY (parm))) + { + private_arg = hsa_cfun->create_hsa_temporary (arg->m_type); + hsa_cfun->m_private_variables.safe_push (private_arg); + fillup_sym_for_decl (parm, private_arg); + f->m_private_variables.safe_push (private_arg); + + hsa_op_address *private_arg_addr = new hsa_op_address (private_arg); + gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr, + arg->total_byte_size ()); + } + else + private_arg = arg; + + slot = f->m_local_symbols->find_slot (private_arg, INSERT); gcc_assert (!*slot); - *slot = &f->m_input_args[i]; + *slot = private_arg; if (is_gimple_reg (parm)) { @@ -5013,12 +5036,9 @@ gen_function_def_parameters (hsa_function_representation *f, BrigType16_t mtype = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (ddef), false)); hsa_op_reg *dest = hsa_reg_for_gimple_ssa (ddef, ssa_map); - hsa_op_address *addr; - - addr = gen_hsa_addr (parm, prologue, ssa_map); hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, mtype, - dest, addr); - gcc_assert (!addr->m_reg); + dest, parm_addr); + gcc_assert (!parm_addr->m_reg); prologue->append_insn (mem); } } -- 2.6.2
>From a34342ce566bba60b12a550496b747370938cc52 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Tue, 27 Oct 2015 11:58:12 +0100 Subject: [PATCH 5/9] HSA: hsa_symbol refactoring and memory allocation fix-up gcc/ChangeLog: * hsa-brig.c (emit_function_directives): Simplify emission of private symbols. (emit_arg_block_insn): Use different property of hsa_symbol. (emit_insn): Remove usage of comment_instructions. (hsa_brig_emit_function): Properly release comment_instructions vector. * hsa-dump.c (dump_hsa_insn_1): Use different property of hsa_symbol. * hsa-gen.c (hsa_symbol::operator new): (hsa_symbol::fillup_for_decl): New function. (hsa_function_representation::~hsa_function_representation): Release memory. (hsa_function_representation::get_shadow_reg): Use ctor of hsa_symbol. (hsa_init_data_for_cfun): Remove BB allocation. (hsa_deinit_data_for_cfun): Call ctor for all insns. (fillup_sym_for_decl): Remove. (get_symbol_for_decl): Use ctor of hsa_symbol. (hsa_insn_basic::hsa_insn_basic): Register newly allocated instance in hsa_instances. (hsa_insn_call::~hsa_insn_call): Likewise. (gen_hsa_addr_for_arg): Use ctor of hsa_symbol. (gen_hsa_insns_for_direct_call): Do not push to remove container. (gen_hsa_insns_for_call): Small code refactoring. (get_function_arg_count): Remove function. (gen_function_decl_parameters): Use vector instread of dynamically allocated memory array. (gen_function_def_parameters): Do it method of hsa_function_representation. (hsa_generate_function_declaration): Use ctor instread of XCNEW. (convert_switch_statements): Release leaked memory. (emit_hsa_module_variables): Use newly added function init_extra_bbs. (generate_hsa): Do not use removed argument. * hsa.c (hsa_deinit_compilation_unit_data): Release hsa_num_threads. (hsa_destroy_insn): Handle hsa_insn_sbr and hsa_insn_comment. (hsa_init_compilation_unit_data): Initialize hsa_global_variable_symbols. (hsa_deinit_compilation_unit_data): Do not release deleted container. (hsa_fail_cfun): Do not initialize hsa_failed_functions. * hsa.h (struct hsa_symbol): Declare new methods and remove unused properties. --- gcc/hsa-brig.c | 50 +++-------- gcc/hsa-dump.c | 6 +- gcc/hsa-gen.c | 279 +++++++++++++++++++++++++++------------------------------ gcc/hsa.c | 22 +++-- gcc/hsa.h | 45 +++++----- 5 files changed, 182 insertions(+), 220 deletions(-) diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c index 0c26b58..a09415c 100644 --- a/gcc/hsa-brig.c +++ b/gcc/hsa-brig.c @@ -137,9 +137,6 @@ static hash_map <tree, BrigDirectiveExecutable *> *emitted_declarations; /* List of sbr instructions. */ static vec <hsa_insn_sbr *> *switch_instructions; -/* List of comment instructions. */ -static vec <hsa_insn_comment *> *comment_instructions; - struct function_linkage_pair { function_linkage_pair (tree decl, unsigned int off): @@ -615,16 +612,10 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration) inarg_off = brig_code.total_size + sizeof(fndir) + (f->m_output_arg ? sizeof (struct BrigDirectiveVariable) : 0); scoped_off = inarg_off - + f->m_input_args_count * sizeof (struct BrigDirectiveVariable); + + f->m_input_args.length () * sizeof (struct BrigDirectiveVariable); if (!f->m_declaration_p) { - for (hash_table <hsa_noop_symbol_hasher>::iterator iter - = f->m_local_symbols->begin (); - iter != f->m_local_symbols->end (); - ++iter) - if (TREE_CODE ((*iter)->m_decl) == VAR_DECL) - count++; count += f->m_spill_symbols.length (); count += f->m_private_variables.length (); } @@ -636,7 +627,7 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration) fndir.base.kind = htole16 (f->m_kern_p ? BRIG_KIND_DIRECTIVE_KERNEL : BRIG_KIND_DIRECTIVE_FUNCTION); fndir.name = htole32 (name_offset); - fndir.inArgCount = htole16 (f->m_input_args_count); + fndir.inArgCount = htole16 (f->m_input_args.length ()); fndir.outArgCount = htole16 (f->m_output_arg ? 1 : 0); fndir.firstInArg = htole32 (inarg_off); fndir.firstCodeBlockEntry = htole32 (scoped_off); @@ -667,20 +658,11 @@ emit_function_directives (hsa_function_representation *f, bool is_declaration) if (f->m_output_arg) emit_directive_variable (f->m_output_arg); - for (unsigned i = 0; i < f->m_input_args_count; i++) - emit_directive_variable (&f->m_input_args[i]); + for (unsigned i = 0; i < f->m_input_args.length (); i++) + emit_directive_variable (f->m_input_args[i]); if (!f->m_declaration_p) { - for (hash_table <hsa_noop_symbol_hasher>::iterator iter - = f->m_local_symbols->begin (); - iter != f->m_local_symbols->end (); - ++iter) - { - if (TREE_CODE ((*iter)->m_decl) == VAR_DECL) - brig_insn_count++; - emit_directive_variable (*iter); - } for (int i = 0; f->m_spill_symbols.iterate (i, &sym); i++) { emit_directive_variable (sym); @@ -1526,7 +1508,7 @@ emit_cvt_insn (hsa_insn_basic *insn) within a call block instruction. */ static void -emit_m_call_insn (hsa_insn_basic *insn) +emit_call_insn (hsa_insn_basic *insn) { hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn); struct BrigInstBr repr; @@ -1584,7 +1566,7 @@ emit_arg_block_insn (hsa_insn_arg_block *insn) brig_insn_count++; } - if (insn->m_call_insn->m_result_symbol) + if (insn->m_call_insn->m_output_arg) { insn->m_call_insn->m_result_code_list->m_offsets[0] = htole32 (emit_directive_variable (insn->m_call_insn->m_output_arg)); @@ -1795,16 +1777,11 @@ emit_insn (hsa_insn_basic *insn) } if (hsa_insn_call *call = dyn_cast <hsa_insn_call *> (insn)) { - emit_m_call_insn (call); + emit_call_insn (call); return; } if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn)) { - if (comment_instructions == NULL) - comment_instructions = new vec <hsa_insn_comment *> (); - - comment_instructions->safe_push (comment); - emit_comment_insn (comment); return; } @@ -1915,6 +1892,10 @@ hsa_brig_emit_function (void) hbb->m_label_ref.m_directive_offset; } } + + switch_instructions->release (); + delete switch_instructions; + switch_instructions = NULL; } if (dump_file) @@ -1923,15 +1904,6 @@ hsa_brig_emit_function (void) dump_hsa_cfun (dump_file); } - if (comment_instructions) - for (unsigned i = 0; i < comment_instructions->length (); i++) - (*comment_instructions)[i]->release_string (); - - delete switch_instructions; - switch_instructions = NULL; - delete comment_instructions; - comment_instructions = NULL; - emit_queued_operands (); } diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c index f926e39..1a68bc2 100644 --- a/gcc/hsa-dump.c +++ b/gcc/hsa-dump.c @@ -954,15 +954,15 @@ dump_hsa_insn_1 (FILE *f, hsa_insn_basic *insn, int *indent) fprintf (f, "call &%s", name); - if (call->m_result_symbol) + if (call->m_output_arg) fprintf (f, "(%%res) "); fprintf (f, "("); - for (unsigned i = 0; i < call->m_args_symbols.length (); i++) + for (unsigned i = 0; i < call->m_input_args.length (); i++) { fprintf (f, "%%__arg_%u", i); - if (i != call->m_args_symbols.length () - 1) + if (i != call->m_input_args.length () - 1) fprintf (f, ", "); } fprintf (f, ")"); diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index ec0762e..4a30eb0 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -195,7 +195,9 @@ static object_allocator<hsa_insn_arg_block> *hsa_allocp_inst_arg_block; static object_allocator<hsa_insn_comment> *hsa_allocp_inst_comment; static object_allocator<hsa_insn_queue> *hsa_allocp_inst_queue; static object_allocator<hsa_bb> *hsa_allocp_bb; -static object_allocator<hsa_symbol> *hsa_allocp_symbols; + +/* List of pointers to all instructions that come from an object allocator. */ +static vec <hsa_insn_basic *> hsa_instructions; /* Vectors with selected instructions and operands that need a destruction. */ @@ -221,12 +223,6 @@ hsa_symbol::hsa_symbol (BrigType16_t type, BrigSegment8_t segment, { } -void * -hsa_symbol::operator new (size_t) -{ - return hsa_allocp_symbols->vallocate (); -} - unsigned HOST_WIDE_INT hsa_symbol::total_byte_size () { @@ -240,12 +236,28 @@ hsa_symbol::total_byte_size () return s; } +/* Forward declaration. */ + +static BrigType16_t +hsa_type_for_tree_type (const_tree type, unsigned HOST_WIDE_INT *dim_p, + bool min32int); + +void +hsa_symbol::fillup_for_decl (tree decl) +{ + m_decl = decl; + m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &m_dim, false); + + if (hsa_seen_error ()) + m_seen_error = true; +} + /* Constructor of class representing global HSA function/kernel information and state. */ hsa_function_representation::hsa_function_representation (tree fdecl, bool kernel_p): m_name (NULL), - m_input_args_count (0), m_reg_count (0), m_input_args (NULL), + m_reg_count (0), m_input_args (vNULL), m_output_arg (NULL), m_spill_symbols (vNULL), m_readonly_variables (vNULL), m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0), m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl), @@ -260,16 +272,28 @@ hsa_function_representation::hsa_function_representation hsa_function_representation::~hsa_function_representation () { - delete m_local_symbols; - free (m_input_args); - free (m_output_arg); /* Kernel names are deallocated at the end of BRIG output when deallocating hsa_decl_kernel_mapping. */ - if (!m_kern_p) + if (!m_kern_p || m_seen_error) free (m_name); + for (unsigned i = 0; i < m_input_args.length (); i++) + delete m_input_args[i]; + m_input_args.release (); + + delete m_output_arg; + delete m_local_symbols; + + for (unsigned i = 0; i < m_spill_symbols.length (); i++) + delete m_spill_symbols[i]; m_spill_symbols.release (); + + for (unsigned i = 0; i < m_readonly_variables.length (); i++) + delete m_readonly_variables[i]; m_readonly_variables.release (); + + for (unsigned i = 0; i < m_private_variables.length (); i++) + delete m_private_variables[i]; m_private_variables.release (); m_called_functions.release (); } @@ -283,10 +307,9 @@ hsa_function_representation::get_shadow_reg () return m_shadow_reg; /* Append the shadow argument. */ - hsa_symbol *shadow = &m_input_args[m_input_args_count++]; - shadow->m_type = BRIG_TYPE_U64; - shadow->m_segment = BRIG_SEGMENT_KERNARG; - shadow->m_linkage = BRIG_LINKAGE_FUNCTION; + hsa_symbol *shadow = new hsa_symbol (BRIG_TYPE_U64, BRIG_SEGMENT_KERNARG, + BRIG_LINKAGE_FUNCTION); + m_input_args.safe_push (shadow); shadow->m_name = "hsa_runtime_shadow"; hsa_op_reg *r = new hsa_op_reg (BRIG_TYPE_U64); @@ -363,13 +386,6 @@ hsa_init_data_for_cfun () hsa_allocp_inst_queue = new object_allocator<hsa_insn_queue> ("HSA queue instructions"); hsa_allocp_bb = new object_allocator<hsa_bb> ("HSA basic blocks"); - hsa_allocp_symbols = new object_allocator<hsa_symbol> ("HSA symbols"); - - /* 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. */ - hsa_init_new_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)); - hsa_init_new_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)); } /* Deinitialize HSA subsystem and free all allocated memory. */ @@ -383,14 +399,6 @@ hsa_deinit_data_for_cfun (void) if (bb->aux) { hsa_bb *hbb = hsa_bb_for_bb (bb); - hsa_insn_phi *phi; - for (phi = hbb->m_first_phi; - phi; - phi = phi->m_next ? as_a <hsa_insn_phi *> (phi->m_next): NULL) - phi->~hsa_insn_phi (); - for (hsa_insn_basic *insn = hbb->m_first_insn; insn; insn = insn->m_next) - hsa_destroy_insn (insn); - hbb->~hsa_bb (); bb->aux = NULL; } @@ -408,6 +416,11 @@ hsa_deinit_data_for_cfun (void) hsa_list_operand_reg.release (); hsa_list_operand_immed.release (); + for (unsigned i = 0; i < hsa_instructions.length (); i++) + hsa_destroy_insn (hsa_instructions[i]); + + hsa_instructions.release (); + delete hsa_allocp_operand_address; delete hsa_allocp_operand_immed; delete hsa_allocp_operand_reg; @@ -426,7 +439,6 @@ hsa_deinit_data_for_cfun (void) delete hsa_allocp_inst_comment; delete hsa_allocp_inst_queue; delete hsa_allocp_bb; - delete hsa_allocp_symbols; delete hsa_cfun; } @@ -694,28 +706,14 @@ hsa_needs_cvt (BrigType16_t dtype, BrigType16_t stype) return false; } -/* Fill in those values into SYM according to DECL, which are determined - independently from whether it is parameter, result, or a variable, local or - global. */ - -static void -fillup_sym_for_decl (tree decl, struct hsa_symbol *sym) -{ - sym->m_decl = decl; - sym->m_type = hsa_type_for_tree_type (TREE_TYPE (decl), &sym->m_dim); - - if (hsa_seen_error ()) - sym->m_seen_error = true; -} - /* Lookup or create the associated hsa_symbol structure with a given VAR_DECL or lookup the hsa_structure corresponding to a PARM_DECL. */ static hsa_symbol * get_symbol_for_decl (tree decl) { - struct hsa_symbol **slot; - struct hsa_symbol dummy, *sym; + hsa_symbol **slot, *sym; + hsa_symbol dummy (BRIG_TYPE_NONE, BRIG_SEGMENT_NONE, BRIG_LINKAGE_NONE); gcc_assert (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL @@ -723,51 +721,47 @@ get_symbol_for_decl (tree decl) dummy.m_decl = decl; - if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)) + slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT); + gcc_checking_assert (slot); + if (*slot) { - slot = hsa_global_variable_symbols->find_slot (&dummy, INSERT); - gcc_checking_assert (slot); - if (*slot) - { - sym = *slot; + sym = *slot; - /* If the symbol is problematic, mark current function also as - problematic. */ - if (sym->m_seen_error) - hsa_fail_cfun (); + /* If the symbol is problematic, mark current function also as + problematic. */ + if (sym->m_seen_error) + hsa_fail_cfun (); - return sym; - } - sym = XCNEW (struct hsa_symbol); - sym->m_segment = BRIG_SEGMENT_GLOBAL; - sym->m_linkage = BRIG_LINKAGE_FUNCTION; + return sym; + } + + if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)) + { + sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_READONLY, + BRIG_LINKAGE_MODULE); /* Following type of global variables can be handled. */ if (TREE_READONLY (decl) && !TREE_ADDRESSABLE (decl) && DECL_INITIAL (decl) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == INTEGER_TYPE) { - sym->m_segment = BRIG_SEGMENT_READONLY; - sym->m_linkage = BRIG_LINKAGE_MODULE; sym->m_cst_value = new hsa_op_immed (DECL_INITIAL (decl), false); - hsa_cfun->m_readonly_variables.safe_push (sym); } else HSA_SORRY_ATV (EXPR_LOCATION (decl), "referring to global symbol " "%q+D by name from HSA code won't work", decl); + + hsa_cfun->m_readonly_variables.safe_push (sym); } else { - slot = hsa_cfun->m_local_symbols->find_slot (&dummy, INSERT); - gcc_checking_assert (slot); - if (*slot) - return *slot; gcc_assert (TREE_CODE (decl) == VAR_DECL); sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_PRIVATE, BRIG_LINKAGE_FUNCTION); + hsa_cfun->m_private_variables.safe_push (sym); } - fillup_sym_for_decl (decl, sym); + sym->fillup_for_decl (decl); sym->m_name = hsa_get_declaration_name (decl); *slot = sym; return sym; @@ -1161,6 +1155,8 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc): m_prev (NULL), { if (nops > 0) operands.safe_grow_cleared (nops); + + hsa_instructions.safe_push (this); } /* Make OP the operand number INDEX of operands of this instuction. If OP is a @@ -1250,6 +1246,8 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t, gcc_checking_assert (nops >= 4); set_op (3, arg3); } + + hsa_instructions.safe_push (this); } /* New operator to allocate basic instruction from pool alloc. */ @@ -1366,6 +1364,11 @@ hsa_insn_sbr::replace_all_labels (basic_block old_bb, basic_block new_bb) m_jump_table[i] = new_bb; } +hsa_insn_sbr::~hsa_insn_sbr () +{ + m_jump_table.release (); +} + /* Constructor of comparison instructin. CMP is the comparison operation and T is the result type. */ @@ -1498,7 +1501,7 @@ hsa_insn_seg::operator new (size_t) hsa_insn_call::hsa_insn_call (tree callee) : hsa_insn_basic (0, BRIG_OPCODE_CALL), m_called_function (callee), - m_args_code_list (NULL), m_result_symbol (NULL), m_result_code_list (NULL) + m_output_arg (NULL), m_args_code_list (NULL), m_result_code_list (NULL) { } @@ -1510,6 +1513,17 @@ hsa_insn_call::operator new (size_t) return hsa_allocp_inst_call->vallocate (); } +hsa_insn_call::~hsa_insn_call () +{ + for (unsigned i = 0; i < m_input_args.length (); i++) + delete m_input_args[i]; + + delete m_output_arg; + + m_input_args.release (); + m_input_arg_insns.release (); +} + /* Constructor of class representing the argument block required to invoke a call in HSAIL. */ hsa_insn_arg_block::hsa_insn_arg_block (BrigKind brig_kind, @@ -1546,8 +1560,7 @@ hsa_insn_comment::operator new (size_t) return hsa_allocp_inst_comment->vallocate (); } -void -hsa_insn_comment::release_string () +hsa_insn_comment::~hsa_insn_comment () { gcc_checking_assert (m_comment); free (m_comment); @@ -1942,10 +1955,8 @@ out: static hsa_op_address * gen_hsa_addr_for_arg (tree tree_type, int index) { - hsa_symbol *sym = hsa_allocp_symbols->allocate (); - memset (sym, 0, sizeof (hsa_symbol)); - sym->m_segment = BRIG_SEGMENT_ARG; - sym->m_linkage = BRIG_LINKAGE_ARG; + hsa_symbol *sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG, + BRIG_LINKAGE_ARG); sym->m_type = hsa_type_for_tree_type (tree_type, &sym->m_dim); if (index == -1) /* Function result. */ @@ -3286,7 +3297,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, } call_insn->m_input_args.safe_push (addr->m_symbol); - call_insn->m_args_symbols.safe_push (addr->m_symbol); if (parm_type_chain) parm_type_chain = TREE_CHAIN (parm_type_chain); } @@ -3329,7 +3339,6 @@ gen_hsa_insns_for_direct_call (gimple *stmt, hsa_bb *hbb, } call_insn->m_output_arg = addr->m_symbol; - call_insn->m_result_symbol = addr->m_symbol; call_insn->m_result_code_list = new hsa_op_code_list (1); } else @@ -4537,9 +4546,9 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb, called = TREE_OPERAND (called, 0); gcc_checking_assert (TREE_CODE (called) == FUNCTION_DECL); - char *name = xstrdup (hsa_get_declaration_name (called)); hsa_add_kernel_dependency - (hsa_cfun->m_decl, hsa_brig_function_name (name)); + (hsa_cfun->m_decl, + hsa_brig_function_name (hsa_get_declaration_name (called))); gen_hsa_insns_for_kernel_call (hbb, as_a <gcall *> (stmt)); break; @@ -4913,21 +4922,6 @@ gen_body_from_gimple (vec <hsa_op_reg_p> *ssa_map) } } -/* For a function DECL, get number of arguments. */ - -static unsigned -get_function_arg_count (tree decl) -{ - unsigned count = 0; - - for (tree parm = TYPE_ARG_TYPES (TREE_TYPE (decl)); parm; - parm = TREE_CHAIN (parm)) - count++; - - /* Return type is the last element of tree list. */ - return count - 1; -} - static void gen_function_decl_parameters (hsa_function_representation *f, tree decl) @@ -4935,32 +4929,31 @@ gen_function_decl_parameters (hsa_function_representation *f, tree parm; unsigned i; - f->m_input_args_count = get_function_arg_count (decl); - f->m_input_args = XCNEWVEC (hsa_symbol, f->m_input_args_count); for (parm = TYPE_ARG_TYPES (TREE_TYPE (decl)), i = 0; parm; parm = TREE_CHAIN (parm), i++) { /* Result type if last in the tree list. */ - if (i == f->m_input_args_count) + if (TREE_CHAIN (parm) == NULL) break; tree v = TREE_VALUE (parm); - f->m_input_args[i].m_type = hsa_type_for_tree_type - (v, &f->m_input_args[i].m_dim); - f->m_input_args[i].m_segment = BRIG_SEGMENT_ARG; - f->m_input_args[i].m_linkage = BRIG_LINKAGE_NONE; - f->m_input_args[i].m_name_number = i; + + hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG, + BRIG_LINKAGE_NONE); + arg->m_type = hsa_type_for_tree_type (v, &arg->m_dim); + arg->m_name_number = i; + + f->m_input_args.safe_push (arg); } tree result_type = TREE_TYPE (TREE_TYPE (decl)); if (!VOID_TYPE_P (result_type)) { - f->m_output_arg = XCNEW (hsa_symbol); - f->m_output_arg->m_type = hsa_type_for_tree_type (result_type, - &f->m_output_arg->m_dim); - f->m_output_arg->m_segment = BRIG_SEGMENT_ARG; - f->m_output_arg->m_linkage = BRIG_LINKAGE_NONE; + f->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG, + BRIG_LINKAGE_NONE); + f->m_output_arg->m_type = hsa_type_for_tree_type + (result_type, &f->m_output_arg->m_dim); f->m_output_arg->m_name = "res"; } } @@ -4970,39 +4963,29 @@ gen_function_decl_parameters (hsa_function_representation *f, result. */ static void -gen_function_def_parameters (hsa_function_representation *f, - vec <hsa_op_reg_p> *ssa_map) +gen_function_def_parameters (vec <hsa_op_reg_p> *ssa_map) { tree parm; - int i, count = 0; - - for (parm = DECL_ARGUMENTS (cfun->decl); parm; parm = DECL_CHAIN (parm)) - count++; - - f->m_input_args_count = count; - - /* Allocate one more argument which can be potentially used for a kernel - dispatching. */ - f->m_input_args = XCNEWVEC (hsa_symbol, f->m_input_args_count + 1); hsa_bb *prologue = hsa_bb_for_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)); - for (parm = DECL_ARGUMENTS (cfun->decl), i = 0; - parm; - parm = DECL_CHAIN (parm), i++) + for (parm = DECL_ARGUMENTS (cfun->decl); parm; + parm = DECL_CHAIN (parm)) { struct hsa_symbol **slot; - fillup_sym_for_decl (parm, &f->m_input_args[i]); + hsa_symbol *arg = new hsa_symbol + (BRIG_TYPE_NONE, + hsa_cfun->m_kern_p ? BRIG_SEGMENT_KERNARG : BRIG_SEGMENT_ARG, + BRIG_LINKAGE_FUNCTION); + arg->fillup_for_decl (parm); + + hsa_cfun->m_input_args.safe_push (arg); if (hsa_seen_error ()) return; - f->m_input_args[i].m_segment = f->m_kern_p ? BRIG_SEGMENT_KERNARG : - BRIG_SEGMENT_ARG; - f->m_input_args[i].m_linkage = BRIG_LINKAGE_FUNCTION; - f->m_input_args[i].m_name = hsa_get_declaration_name (parm); - hsa_symbol *arg = &f->m_input_args[i]; + arg->m_name = hsa_get_declaration_name (parm); /* Copy all input arguments and create corresponding private symbols for them. */ @@ -5013,9 +4996,7 @@ gen_function_def_parameters (hsa_function_representation *f, || (!is_gimple_reg (parm) && !TREE_READONLY (parm))) { private_arg = hsa_cfun->create_hsa_temporary (arg->m_type); - hsa_cfun->m_private_variables.safe_push (private_arg); - fillup_sym_for_decl (parm, private_arg); - f->m_private_variables.safe_push (private_arg); + private_arg->fillup_for_decl (parm); hsa_op_address *private_arg_addr = new hsa_op_address (private_arg); gen_hsa_memory_copy (prologue, private_arg_addr, parm_addr, @@ -5024,7 +5005,7 @@ gen_function_def_parameters (hsa_function_representation *f, else private_arg = arg; - slot = f->m_local_symbols->find_slot (private_arg, INSERT); + slot = hsa_cfun->m_local_symbols->find_slot (private_arg, INSERT); gcc_assert (!*slot); *slot = private_arg; @@ -5048,18 +5029,18 @@ gen_function_def_parameters (hsa_function_representation *f, { struct hsa_symbol **slot; - f->m_output_arg = XCNEW (hsa_symbol); - fillup_sym_for_decl (DECL_RESULT (cfun->decl), f->m_output_arg); + hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG, + BRIG_LINKAGE_FUNCTION); + hsa_cfun->m_output_arg->fillup_for_decl (DECL_RESULT (cfun->decl)); if (hsa_seen_error ()) return; - f->m_output_arg->m_segment = BRIG_SEGMENT_ARG; - f->m_output_arg->m_linkage = BRIG_LINKAGE_FUNCTION; - f->m_output_arg->m_name = "res"; - slot = f->m_local_symbols->find_slot (f->m_output_arg, INSERT); + hsa_cfun->m_output_arg->m_name = "res"; + slot = hsa_cfun->m_local_symbols->find_slot (hsa_cfun->m_output_arg, + INSERT); gcc_assert (!*slot); - *slot = f->m_output_arg; + *slot = hsa_cfun->m_output_arg; } } @@ -5069,10 +5050,10 @@ gen_function_def_parameters (hsa_function_representation *f, hsa_function_representation * hsa_generate_function_declaration (tree decl) { - hsa_function_representation *fun = XCNEW (hsa_function_representation); + hsa_function_representation *fun = new hsa_function_representation + (decl, false); fun->m_declaration_p = true; - fun->m_decl = decl; fun->m_name = get_brig_function_name (decl); gen_function_decl_parameters (fun, decl); @@ -5320,6 +5301,7 @@ convert_switch_statements () gphi *phi = it.phi (); add_phi_arg (phi, phi_def->phi_value, new_edge, UNKNOWN_LOCATION); + delete phi_def; } /* Remove the original GIMPLE switch statement. */ @@ -5360,13 +5342,14 @@ static void generate_hsa (bool kernel) { vec <hsa_op_reg_p> ssa_map = vNULL; + hsa_init_data_for_cfun (); if (hsa_num_threads == NULL) emit_hsa_module_variables (); /* Initialize hsa_cfun. */ hsa_cfun = new hsa_function_representation (cfun->decl, kernel); - hsa_init_data_for_cfun (); + hsa_cfun->init_extra_bbs (); if (flag_tm) { @@ -5382,7 +5365,7 @@ generate_hsa (bool kernel) ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ()); hsa_cfun->m_name = get_brig_function_name (cfun->decl); - gen_function_def_parameters (hsa_cfun, &ssa_map); + gen_function_def_parameters (&ssa_map); if (hsa_seen_error ()) goto fail; @@ -5417,13 +5400,13 @@ generate_hsa (bool kernel) #endif - ssa_map.release (); - hsa_regalloc (); hsa_brig_emit_function (); fail: + ssa_map.release (); + hsa_deinit_data_for_cfun (); } diff --git a/gcc/hsa.c b/gcc/hsa.c index c4990e2..aca8bd4 100644 --- a/gcc/hsa.c +++ b/gcc/hsa.c @@ -131,7 +131,8 @@ hsa_init_compilation_unit_data (void) return; compilation_unit_data_initialized = true; - hsa_global_variable_symbols = new hash_table <hsa_free_symbol_hasher> (8); + + hsa_failed_functions = new hash_set <tree> (); } /* Free data structures that are used when dealing with different @@ -140,11 +141,11 @@ hsa_init_compilation_unit_data (void) void hsa_deinit_compilation_unit_data (void) { - if (compilation_unit_data_initialized) - delete hsa_global_variable_symbols; - if (hsa_failed_functions) delete hsa_failed_functions; + + if (hsa_num_threads) + delete hsa_num_threads; } /* Return true if we are generating large HSA machine model. */ @@ -547,6 +548,17 @@ hsa_destroy_insn (hsa_insn_basic *insn) block->~hsa_insn_arg_block (); return; } + if (hsa_insn_sbr *sbr = dyn_cast <hsa_insn_sbr *> (insn)) + { + sbr->~hsa_insn_sbr (); + return; + } + if (hsa_insn_comment *comment = dyn_cast <hsa_insn_comment *> (insn)) + { + comment->~hsa_insn_comment (); + return; + } + insn->~hsa_insn_basic (); return; } @@ -711,8 +723,6 @@ hsa_seen_error (void) void hsa_fail_cfun (void) { - if (hsa_failed_functions == NULL) - hsa_failed_functions = new hash_set <tree> (); hsa_failed_functions->add (hsa_cfun->m_decl); hsa_cfun->m_seen_error = true; } diff --git a/gcc/hsa.h b/gcc/hsa.h index f4184f9..dfa0d1f 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -53,19 +53,18 @@ typedef hsa_insn_basic *hsa_insn_basic_p; struct hsa_symbol { - /* Default constructor. */ - hsa_symbol (); - /* Constructor. */ hsa_symbol (BrigType16_t type, BrigSegment8_t segment, BrigLinkage8_t linkage); - /* New operator to allocate HSA symbol from pool alloc. */ - void *operator new (size_t); - /* 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. */ tree m_decl; @@ -102,6 +101,10 @@ struct hsa_symbol /* True if an error has been seen for the symbol. */ bool m_seen_error; + +private: + /* Default constructor. */ + hsa_symbol (); }; /* Abstract class for HSA instruction operands. */ @@ -483,6 +486,9 @@ 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 *operator new (size_t); void replace_all_labels (basic_block old_bb, basic_block new_bb); @@ -708,6 +714,9 @@ class hsa_insn_call : public hsa_insn_basic public: hsa_insn_call (tree callee); + /* Default destructor. */ + ~hsa_insn_call (); + void *operator new (size_t); /* Called function */ @@ -725,15 +734,9 @@ public: /* Called function code reference. */ hsa_op_code_ref m_func; - /* Argument symbols. */ - auto_vec <hsa_symbol *> m_args_symbols; - /* Code list for arguments of the function. */ hsa_op_code_list *m_args_code_list; - /* Result symbol. */ - hsa_symbol *m_result_symbol; - /* Code list for result of the function. */ hsa_op_code_list *m_result_code_list; private: @@ -796,13 +799,10 @@ public: /* Constructor of class representing the comment in HSAIL. */ hsa_insn_comment (const char *s); - void *operator new (size_t); - - /* Destructor. */ + /* Default destructor. */ ~hsa_insn_comment (); - /* Release memory for comment. */ - void release_string (); + void *operator new (size_t); char *m_comment; }; @@ -957,17 +957,15 @@ public: /* Name of the function. */ char *m_name; - /* Input arguments of the function. */ - /* FIXME: Normally we'd use a vector, however our C++ vectors seem to have - problems with derived classes, so for now we'll use a simple array. */ - unsigned m_input_args_count; - /* Number of allocated register structures. */ int m_reg_count; - hsa_symbol *m_input_args; + /* 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; @@ -1080,7 +1078,6 @@ hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host, /* in hsa.c */ extern struct hsa_function_representation *hsa_cfun; -extern hash_table <hsa_free_symbol_hasher> *hsa_global_variable_symbols; extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies; extern hsa_summary_t *hsa_summaries; extern hsa_symbol *hsa_num_threads; -- 2.6.2
>From 0d38552c5c84e54aa7b1cf7d6fa38c80b85b6108 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Tue, 27 Oct 2015 16:01:56 +0100 Subject: [PATCH 6/9] HSA: introduce hsa_debug_symbol and refact. hsa_function_representation. gcc/ChangeLog: 2015-10-27 Martin Liska <mli...@suse.cz> * hsa-dump.c (dump_hsa_symbol): New function. (debug_hsa_symbol): Likewise. * hsa-gen.c (hsa_function_representation::~hsa_function_representation): Release memory. (generate_hsa): Use hsa_cfun->m_map. * hsa.h: Declare hsa_function_representation::m_map. --- gcc/hsa-dump.c | 29 +++++++++++++++++++++++++++++ gcc/hsa-gen.c | 19 ++++++++----------- gcc/hsa.h | 3 +++ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c index 1a68bc2..6e58001 100644 --- a/gcc/hsa-dump.c +++ b/gcc/hsa-dump.c @@ -726,6 +726,26 @@ dump_hsa_address (FILE *f, hsa_op_address *addr) fprintf (f, "[" HOST_WIDE_INT_PRINT_DEC "]", addr->m_imm_offset); } +/* Dump textual representation of HSA IL symbol SYMBOL to file F. */ + +static void +dump_hsa_symbol (FILE *f, hsa_symbol *symbol) +{ + const char *name; + if (symbol->m_name) + name = symbol->m_name; + else + { + char buf[64]; + sprintf (buf, "__%s_%i", hsa_seg_name (symbol->m_segment), + symbol->m_name_number); + + name = buf; + } + + fprintf (f, "%s (%s)", name, hsa_type_name (symbol->m_type)); +} + /* Dump textual representation of HSA IL operand OP to file F. */ static void @@ -1127,3 +1147,12 @@ debug_hsa_operand (hsa_op_base *opc) dump_hsa_operand (stderr, opc, true); fprintf (stderr, "\n"); } + +/* Dump textual representation of as HSA symbol. */ + +DEBUG_FUNCTION void +debug_hsa_symbol (hsa_symbol *symbol) +{ + dump_hsa_symbol (stderr, symbol); + fprintf (stderr, "\n"); +} diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 4a30eb0..2139499 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -262,7 +262,7 @@ hsa_function_representation::hsa_function_representation m_private_variables (vNULL), m_called_functions (vNULL), m_hbb_count (0), m_in_ssa (true), m_kern_p (kernel_p), m_declaration_p (false), m_decl (fdecl), m_shadow_reg (NULL), m_kernel_dispatch_count (0), m_maximum_omp_data_size (0), - m_seen_error (false), m_temp_symbol_count (0) + m_seen_error (false), m_temp_symbol_count (0), m_ssa_map () { int sym_init_len = (vec_safe_length (cfun->local_decls) / 2) + 1;; m_local_symbols = new hash_table <hsa_noop_symbol_hasher> (sym_init_len); @@ -296,6 +296,7 @@ hsa_function_representation::~hsa_function_representation () delete m_private_variables[i]; m_private_variables.release (); m_called_functions.release (); + m_ssa_map.release (); } hsa_op_reg * @@ -5341,7 +5342,6 @@ emit_hsa_module_variables (void) static void generate_hsa (bool kernel) { - vec <hsa_op_reg_p> ssa_map = vNULL; hsa_init_data_for_cfun (); if (hsa_num_threads == NULL) @@ -5349,6 +5349,7 @@ generate_hsa (bool kernel) /* Initialize hsa_cfun. */ hsa_cfun = new hsa_function_representation (cfun->decl, kernel); + hsa_cfun->m_ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ()); hsa_cfun->init_extra_bbs (); if (flag_tm) @@ -5362,16 +5363,15 @@ generate_hsa (bool kernel) if (hsa_seen_error ()) goto fail; - ssa_map.safe_grow_cleared (SSANAMES (cfun)->length ()); hsa_cfun->m_name = get_brig_function_name (cfun->decl); - gen_function_def_parameters (&ssa_map); + gen_function_def_parameters (&hsa_cfun->m_ssa_map); if (hsa_seen_error ()) goto fail; init_prologue (); - gen_body_from_gimple (&ssa_map); + gen_body_from_gimple (&hsa_cfun->m_ssa_map); if (hsa_seen_error ()) goto fail; @@ -5385,9 +5385,9 @@ generate_hsa (bool kernel) } #ifdef ENABLE_CHECKING - for (unsigned i = 0; i < ssa_map.length (); i++) - if (ssa_map[i]) - ssa_map[i]->verify_ssa (); + for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++) + if (hsa_cfun->m_ssa_map[i]) + hsa_cfun->m_ssa_map[i]->verify_ssa (); basic_block bb; FOR_EACH_BB_FN (bb, cfun) @@ -5401,12 +5401,9 @@ generate_hsa (bool kernel) #endif hsa_regalloc (); - hsa_brig_emit_function (); fail: - ssa_map.release (); - hsa_deinit_data_for_cfun (); } diff --git a/gcc/hsa.h b/gcc/hsa.h index dfa0d1f..0bdd530 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -1016,6 +1016,9 @@ public: /* Counter for temporary symbols created in the function representation. */ unsigned m_temp_symbol_count; + + /* SSA names mapping. */ + vec <hsa_op_reg_p> m_ssa_map; }; enum hsa_function_kind -- 2.6.2
>From 1aad365cac3f81561bf0c9f819a4f9515300f347 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Fri, 30 Oct 2015 20:04:33 +0100 Subject: [PATCH 7/9] HSA: prepend _m to hsa_insn_basic::operands gcc/ChangeLog: 2015-10-30 Martin Liska <mli...@suse.cz> * hsa-gen.c (hsa_insn_basic::hsa_insn_basic): Rename operands to m_operands. (hsa_insn_basic::set_op): Likewise. (hsa_insn_basic::get_op): Likewise. (hsa_insn_basic::get_op_addr): Likewise. (hsa_insn_basic::operand_count): Likewise. * hsa.h: Likewise. --- gcc/hsa-gen.c | 12 ++++++------ gcc/hsa.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 2139499..3a0b99b7 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -1155,7 +1155,7 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc): m_prev (NULL), m_type (BRIG_TYPE_NONE), m_brig_offset (0) { if (nops > 0) - operands.safe_grow_cleared (nops); + m_operands.safe_grow_cleared (nops); hsa_instructions.safe_push (this); } @@ -1184,7 +1184,7 @@ hsa_insn_basic::set_op (int index, hsa_op_base *op) } } - operands[index] = op; + m_operands[index] = op; } /* Get INDEX-th operand of the instruction. */ @@ -1192,7 +1192,7 @@ hsa_insn_basic::set_op (int index, hsa_op_base *op) hsa_op_base * hsa_insn_basic::get_op (int index) { - return operands[index]; + return m_operands[index]; } /* Get address of INDEX-th operand of the instruction. */ @@ -1200,14 +1200,14 @@ hsa_insn_basic::get_op (int index) hsa_op_base ** hsa_insn_basic::get_op_addr (int index) { - return &operands[index]; + return &m_operands[index]; } /* Get number of operands of the instruction. */ unsigned int hsa_insn_basic::operand_count () { - return operands.length (); + return m_operands.length (); } /* Constructor of the class which is the bases of all instructions and directly @@ -1222,7 +1222,7 @@ hsa_insn_basic::hsa_insn_basic (unsigned nops, int opc, BrigType16_t t, m_type (t), m_brig_offset (0) { if (nops > 0) - operands.safe_grow_cleared (nops); + m_operands.safe_grow_cleared (nops); if (arg0 != NULL) { diff --git a/gcc/hsa.h b/gcc/hsa.h index 0bdd530..f08b12e 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -414,7 +414,7 @@ private: 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> operands; + auto_vec<hsa_op_base *, HSA_BRIG_INT_STORAGE_OPERANDS> m_operands; }; /* Class representing a PHI node of the SSA form of HSA virtual -- 2.6.2
>From 77d7f6ee98a46fa123394a5073f44ae591e26c76 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Tue, 27 Oct 2015 17:49:05 +0100 Subject: [PATCH 8/9] HSA: correctly handle memory order for atomic insns gcc/ChangeLog: 2015-10-27 Martin Liska <mli...@suse.cz> * hsa-gen.c (hsa_insn_signal::hsa_insn_signal): Use modified ctor of hsa_insn_atomic. (gen_hsa_insns_for_kernel_call): Likewise. (get_memory_order_name): New function. (get_memory_order): New function. (gen_hsa_ternary_atomic_for_builtin): Fill up memory order. (gen_hsa_insns_for_call): Likewise. * hsa.h: Declare new argument for hsa_insn_atomic::hsa_insn_atomic. --- gcc/hsa-gen.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- gcc/hsa.h | 2 +- 2 files changed, 108 insertions(+), 18 deletions(-) diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 3a0b99b7..856fdce 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -1429,11 +1429,12 @@ hsa_insn_mem::operator new (size_t) hsa_insn_atomic::hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop, - BrigType16_t t, hsa_op_base *arg0, + BrigType16_t t, BrigMemoryOrder memorder, + hsa_op_base *arg0, hsa_op_base *arg1, hsa_op_base *arg2, hsa_op_base *arg3) : hsa_insn_mem (nops, opc, t, arg0, arg1, arg2, arg3), m_atomicop (aop), - m_memoryorder (BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE), + m_memoryorder (memorder), m_memoryscope (BRIG_MEMORY_SCOPE_SYSTEM) { gcc_checking_assert (opc == BRIG_OPCODE_ATOMICNORET || @@ -1462,7 +1463,8 @@ hsa_insn_signal::hsa_insn_signal (int nops, int opc, BrigType16_t t, hsa_op_base *arg0, hsa_op_base *arg1, hsa_op_base *arg2, hsa_op_base *arg3) - : hsa_insn_atomic (nops, opc, sop, t, arg0, arg1, arg2, arg3) + : hsa_insn_atomic (nops, opc, sop, t, BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE, + arg0, arg1, arg2, arg3) { } @@ -4028,10 +4030,9 @@ gen_hsa_insns_for_kernel_call (hsa_bb *hbb, gcall *call) /* Store 5122 << 16 + 1 to packet->header. */ c = new hsa_op_immed (70658, BRIG_TYPE_U32); - hsa_insn_atomic *atomic = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMICNORET, - BRIG_ATOMIC_ST, BRIG_TYPE_B32, - addr, c); - atomic->m_memoryorder = BRIG_MEMORY_ORDER_SC_RELEASE; + hsa_insn_atomic *atomic = new hsa_insn_atomic + (2, BRIG_OPCODE_ATOMICNORET, BRIG_ATOMIC_ST, BRIG_TYPE_B32, + BRIG_MEMORY_ORDER_SC_RELEASE, addr, c); atomic->m_memoryscope = BRIG_MEMORY_SCOPE_SYSTEM; hbb->append_insn (atomic); @@ -4145,6 +4146,54 @@ get_address_from_value (tree val, hsa_bb *hbb, vec <hsa_op_reg_p> *ssa_map) } } +/* Return strign for MEMMODEL. */ + +static const char * +get_memory_order_name (unsigned memmodel) +{ + switch (memmodel) + { + case __ATOMIC_RELAXED: + return "__ATOMIC_RELAXED"; + case __ATOMIC_CONSUME: + return "__ATOMIC_CONSUME"; + case __ATOMIC_ACQUIRE: + return "__ATOMIC_ACQUIRE"; + case __ATOMIC_RELEASE: + return "__ATOMIC_RELEASE"; + case __ATOMIC_ACQ_REL: + return "__ATOMIC_ACQ_REL"; + case __ATOMIC_SEQ_CST: + return "__ATOMIC_SEQ_CST"; + default: + return NULL; + } +} + +/* Return memory order according to predefined __atomic memory model + constants. LOCATION is provided to locate the problemati statement. */ + +static BrigMemoryOrder +get_memory_order (unsigned memmodel, location_t location) +{ + switch (memmodel) + { + case __ATOMIC_RELAXED: + return BRIG_MEMORY_ORDER_RELAXED; + case __ATOMIC_ACQUIRE: + return BRIG_MEMORY_ORDER_SC_ACQUIRE; + case __ATOMIC_RELEASE: + return BRIG_MEMORY_ORDER_SC_RELEASE; + case __ATOMIC_ACQ_REL: + return BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE; + default: + HSA_SORRY_ATV (location, + "support for HSA does not implement memory model: %s", + get_memory_order_name (memmodel)); + return BRIG_MEMORY_ORDER_NONE; + } +} + /* Helper function to create an HSA atomic binary operation instruction out of calls to atomic builtins. RET_ORIG is true if the built-in is the variant that return s the value before applying operation, and false if it should @@ -4161,8 +4210,22 @@ gen_hsa_ternary_atomic_for_builtin (bool ret_orig, tree lhs = gimple_call_lhs (stmt); tree type = TREE_TYPE (gimple_call_arg (stmt, 1)); - BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false); + BrigType16_t hsa_type = hsa_type_for_scalar_tree_type (type, false); BrigType16_t mtype = mem_type_for_type (hsa_type); + tree model = gimple_call_arg (stmt, 2); + + if (!tree_fits_uhwi_p (model)) + { + HSA_SORRY_ATV + (gimple_location (stmt), + "support for HSA does not implement memory model %E", model); + return; + } + + unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model); + + BrigMemoryOrder memorder = get_memory_order + (mmodel, gimple_location (stmt)); /* Certain atomic insns must have Bx memory types. */ switch (acode) @@ -4193,12 +4256,19 @@ gen_hsa_ternary_atomic_for_builtin (bool ret_orig, nops = 2; } - hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype); - /* Overwrite default memory order for ATOMIC_ST insn which can have just RLX or SCREL memory order. */ - if (acode == BRIG_ATOMIC_ST) - atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_RELEASE; + if (acode == BRIG_ATOMIC_ST && memorder != BRIG_MEMORY_ORDER_RELAXED + && memorder != BRIG_MEMORY_ORDER_SC_RELEASE) + { + HSA_SORRY_ATV (gimple_location (stmt), + "support for HSA does not implement memory model for " + "ATOMIC_ST: %s", get_memory_order_name (mmodel)); + return; + } + + hsa_insn_atomic *atominsn = new hsa_insn_atomic (nops, opcode, acode, mtype, + memorder); hsa_op_address *addr; addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map); @@ -4369,6 +4439,28 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb, BrigType16_t mtype; hsa_op_address *addr; addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map); + tree model = gimple_call_arg (stmt, 1); + if (!tree_fits_uhwi_p (model)) + { + HSA_SORRY_ATV + (gimple_location (stmt), + "support for HSA does not implement memory model: %E", model); + return; + } + + unsigned HOST_WIDE_INT mmodel = tree_to_uhwi (model); + BrigMemoryOrder memorder = get_memory_order (mmodel, + gimple_location (stmt)); + + if (memorder != BRIG_MEMORY_ORDER_RELAXED + && memorder != BRIG_MEMORY_ORDER_SC_RELEASE) + { + HSA_SORRY_ATV + (gimple_location (stmt), + "support for HSA does not implement memory model for " + "ATOMIC_LD: %s", get_memory_order_name (mmodel)); + return; + } if (lhs) { @@ -4385,9 +4477,7 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb, hsa_insn_atomic *atominsn = new hsa_insn_atomic (2, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_LD, mtype, - dest, addr); - - atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE; + memorder, dest, addr); hbb->append_insn (atominsn); break; @@ -4515,7 +4605,8 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb, (hsa_type_for_scalar_tree_type (type, false)); hsa_insn_atomic *atominsn = new hsa_insn_atomic - (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype); + (4, BRIG_OPCODE_ATOMIC, BRIG_ATOMIC_CAS, atype, + BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE); hsa_op_address *addr; addr = get_address_from_value (gimple_call_arg (stmt, 0), hbb, ssa_map); @@ -4534,7 +4625,6 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb, atominsn->set_op (3, hsa_reg_or_immed_for_gimple_op (gimple_call_arg (stmt, 2), hbb, ssa_map)); - atominsn->m_memoryorder = BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE; hbb->append_insn (atominsn); break; diff --git a/gcc/hsa.h b/gcc/hsa.h index f08b12e..1081fb6 100644 --- a/gcc/hsa.h +++ b/gcc/hsa.h @@ -612,7 +612,7 @@ class hsa_insn_atomic : public hsa_insn_mem { public: hsa_insn_atomic (int nops, int opc, enum BrigAtomicOperation aop, - BrigType16_t t, + 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); void *operator new (size_t); -- 2.6.2