Mercurial > hg > CbC > CbC_gcc
diff gcc/brig/brigfrontend/brig-to-generic.cc @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/brig/brigfrontend/brig-to-generic.cc Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/brig/brigfrontend/brig-to-generic.cc Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* brig2tree.cc -- brig to gcc generic/gimple tree conversion - Copyright (C) 2016-2017 Free Software Foundation, Inc. + Copyright (C) 2016-2018 Free Software Foundation, Inc. Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> for General Processor Tech. @@ -52,6 +52,7 @@ #include "cgraph.h" #include "dumpfile.h" #include "tree-pretty-print.h" +#include "attribs.h" extern int gccbrig_verbose; @@ -124,6 +125,24 @@ } }; +class brig_reg_use_analyzer : public brig_code_entry_handler +{ +public: + brig_reg_use_analyzer (brig_to_generic &parent) + : brig_code_entry_handler (parent) + { + } + + size_t + operator () (const BrigBase *base) + { + const BrigInstBase *brig_inst = (const BrigInstBase *) base; + analyze_operands (*brig_inst); + return base->byteCount; + } + +}; + /* Helper struct for pairing a BrigKind and a BrigCodeEntryHandler that should handle its data. */ @@ -210,6 +229,7 @@ brig_directive_variable_handler var_handler (*this); brig_directive_fbarrier_handler fbar_handler (*this); brig_directive_function_handler func_handler (*this); + brig_reg_use_analyzer reg_use_analyzer (*this); /* Need this for grabbing the module names for mangling the group variable names. */ @@ -219,7 +239,21 @@ const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code; code_entry_handler_info handlers[] - = {{BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler}, + = {{BRIG_KIND_INST_BASIC, ®_use_analyzer}, + {BRIG_KIND_INST_MOD, ®_use_analyzer}, + {BRIG_KIND_INST_CMP, ®_use_analyzer}, + {BRIG_KIND_INST_MEM, ®_use_analyzer}, + {BRIG_KIND_INST_CVT, ®_use_analyzer}, + {BRIG_KIND_INST_SEG_CVT, ®_use_analyzer}, + {BRIG_KIND_INST_SEG, ®_use_analyzer}, + {BRIG_KIND_INST_ADDR, ®_use_analyzer}, + {BRIG_KIND_INST_SOURCE_TYPE, ®_use_analyzer}, + {BRIG_KIND_INST_ATOMIC, ®_use_analyzer}, + {BRIG_KIND_INST_SIGNAL, ®_use_analyzer}, + {BRIG_KIND_INST_BR, ®_use_analyzer}, + {BRIG_KIND_INST_LANE, ®_use_analyzer}, + {BRIG_KIND_INST_QUEUE, ®_use_analyzer}, + {BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler}, {BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler}, {BRIG_KIND_DIRECTIVE_KERNEL, &func_handler}, {BRIG_KIND_DIRECTIVE_MODULE, &module_handler}, @@ -454,7 +488,9 @@ tree var_addr = build1 (ADDR_EXPR, ptype, var_decl); DECL_INITIAL (host_def_var) = var_addr; - TREE_PUBLIC (host_def_var) = 0; + TREE_PUBLIC (host_def_var) = 1; + + set_externally_visible (host_def_var); } /* Adds an indirection pointer for a potential host-defined program scope @@ -477,10 +513,18 @@ TREE_ADDRESSABLE (ptr_var) = 1; TREE_STATIC (ptr_var) = 1; + set_externally_visible (ptr_var); + append_global (ptr_var); m_global_variables[var_name] = ptr_var; } +void +brig_to_generic::add_decl_call (tree call) +{ + m_decl_call.push_back (call); +} + /* Produce a "mangled name" for the given brig function or kernel. The mangling is used to make unique global symbol name in case of module scope functions. Program scope functions are not mangled @@ -555,10 +599,14 @@ than the created reg var type in order to select correct instruction type later on. This function creates the necessary reinterpret type cast from a source variable to the destination type. In case no cast is needed to - the same type, SOURCE is returned directly. */ + the same type, SOURCE is returned directly. + + In case of mismatched type sizes, casting: + - to narrower type the upper bits are clipped and + - to wider type the source value is zero extended. */ tree -build_reinterpret_cast (tree destination_type, tree source) +build_resize_convert_view (tree destination_type, tree source) { gcc_assert (source && destination_type && TREE_TYPE (source) != NULL_TREE @@ -578,23 +626,30 @@ size_t dst_size = int_size_in_bytes (destination_type); if (src_size == dst_size) return build1 (VIEW_CONVERT_EXPR, destination_type, source); - else if (src_size < dst_size) + else /* src_size != dst_size */ { /* The src_size can be smaller at least with f16 scalars which are stored to 32b register variables. First convert to an equivalent size unsigned type, then extend to an unsigned type of the target width, after which VIEW_CONVERT_EXPR can be used to force to the target type. */ - tree unsigned_temp = build1 (VIEW_CONVERT_EXPR, - get_unsigned_int_type (source_type), - source); - return build1 (VIEW_CONVERT_EXPR, destination_type, - convert (get_unsigned_int_type (destination_type), - unsigned_temp)); + tree resized = convert (get_scalar_unsigned_int_type (destination_type), + build_reinterpret_to_uint (source)); + gcc_assert ((size_t)int_size_in_bytes (TREE_TYPE (resized)) == dst_size); + return build_resize_convert_view (destination_type, resized); } - else - gcc_unreachable (); - return NULL_TREE; +} + +/* Reinterprets SOURCE as a scalar unsigned int with the size + corresponding to the orignal. */ + +tree build_reinterpret_to_uint (tree source) +{ + tree src_type = TREE_TYPE (source); + if (INTEGRAL_TYPE_P (src_type) && TYPE_UNSIGNED (src_type)) + return source; + tree dest_type = get_scalar_unsigned_int_type (src_type); + return build1 (VIEW_CONVERT_EXPR, dest_type, source); } /* Returns the finished brig_function for the given generic FUNC_DECL, @@ -657,8 +712,6 @@ m_cf->finish (); m_cf->emit_metadata (stmts); dump_function (m_dump_file, m_cf); - gimplify_function_tree (m_cf->m_func_decl); - cgraph_node::finalize_function (m_cf->m_func_decl, true); } else /* Emit the kernel only at the very end so we can analyze the total @@ -775,7 +828,7 @@ { types[i] = va_arg (ap, tree); tree arg = va_arg (ap, tree); - args[i] = build_reinterpret_cast (types[i], arg); + args[i] = build_resize_convert_view (types[i], arg); if (types[i] == error_mark_node || args[i] == error_mark_node) { delete[] types; @@ -802,6 +855,43 @@ void brig_to_generic::write_globals () { + + /* Replace calls to declarations with calls to definitions. Otherwise + inlining will fail to find the definition to inline from. */ + + for (size_t i = 0; i < m_decl_call.size(); ++i) + { + tree decl_call = m_decl_call.at(i); + tree func_decl = get_callee_fndecl (decl_call); + brig_function *brig_function = get_finished_function (func_decl); + + if (brig_function && brig_function->m_func_decl + && DECL_EXTERNAL (brig_function->m_func_decl) == 0 + && brig_function->m_func_decl != func_decl) + { + + decl_call = CALL_EXPR_FN (decl_call); + STRIP_NOPS (decl_call); + if (TREE_CODE (decl_call) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (decl_call, 0)) == FUNCTION_DECL) + TREE_OPERAND (decl_call, 0) = brig_function->m_func_decl; + } + } + + for (std::map<std::string, brig_function *>::iterator i + = m_finished_functions.begin(), e = m_finished_functions.end(); + i != e; ++i) + { + brig_function *brig_f = (*i).second; + if (brig_f->m_is_kernel) + continue; + + /* Finalize only at this point to allow the cgraph analysis to + see definitions to calls to later functions. */ + gimplify_function_tree (brig_f->m_func_decl); + cgraph_node::finalize_function (brig_f->m_func_decl, true); + } + /* Now that the whole BRIG module has been processed, build a launcher and a metadata section for each built kernel. */ for (size_t i = 0; i < m_kernels.size (); ++i) @@ -836,6 +926,18 @@ append_global (launcher); + if (m_dump_file) + { + std::string kern_name = f->m_name.substr (1); + fprintf (m_dump_file, "\n;; Function %s", kern_name.c_str()); + fprintf (m_dump_file, "\n;; enabled by -%s\n\n", + dump_flag_name (TDI_original)); + print_generic_decl (m_dump_file, launcher, TDF_NONE); + print_generic_expr (m_dump_file, DECL_SAVED_TREE (launcher), + TDF_NONE); + fprintf (m_dump_file, "\n"); + } + gimplify_function_tree (launcher); cgraph_node::finalize_function (launcher, true); pop_cfun (); @@ -869,7 +971,7 @@ { size_t esize = int_size_in_bytes (TREE_TYPE (original_type)) * BITS_PER_UNIT; - size_t ecount = TYPE_VECTOR_SUBPARTS (original_type); + poly_uint64 ecount = TYPE_VECTOR_SUBPARTS (original_type); return build_vector_type (build_nonstandard_integer_type (esize, true), ecount); } @@ -879,6 +981,35 @@ true); } +/* Returns a type with unsigned int corresponding to the size + ORIGINAL_TYPE. */ + +tree +get_scalar_unsigned_int_type (tree original_type) +{ + return build_nonstandard_integer_type (int_size_in_bytes (original_type) + * BITS_PER_UNIT, true); +} + +/* Set the declaration externally visible so it won't get removed by + whole program optimizations. */ + +void +set_externally_visible (tree decl) +{ + if (!lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("externally_visible"), + NULL, DECL_ATTRIBUTES (decl)); +} + +void +set_inline (tree decl) +{ + if (!lookup_attribute ("inline", DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("inline"), + NULL, DECL_ATTRIBUTES (decl)); +} + void dump_function (FILE *dump_file, brig_function *f) { @@ -888,8 +1019,27 @@ fprintf (dump_file, "\n;; Function %s", f->m_name.c_str ()); fprintf (dump_file, "\n;; enabled by -%s\n\n", dump_flag_name (TDI_original)); - print_generic_decl (dump_file, f->m_func_decl, 0); - print_generic_expr (dump_file, f->m_current_bind_expr, 0); + print_generic_decl (dump_file, f->m_func_decl, TDF_NONE); + print_generic_expr (dump_file, f->m_current_bind_expr, TDF_NONE); fprintf (dump_file, "\n"); } } + +/* Records use of the BRIG_REG as a TYPE in the current function. */ + +void +brig_to_generic::add_reg_used_as_type (const BrigOperandRegister &brig_reg, + tree type) +{ + gcc_assert (m_cf); + reg_use_info &info + = m_fn_regs_use_index[m_cf->m_name][gccbrig_hsa_reg_id (brig_reg)]; + + if (info.m_type_refs_lookup.count (type)) + info.m_type_refs[info.m_type_refs_lookup[type]].second++; + else + { + info.m_type_refs.push_back (std::make_pair (type, 1)); + info.m_type_refs_lookup[type] = info.m_type_refs.size () - 1; + } +}