Mercurial > hg > CbC > CbC_gcc
diff gcc/brig/brigfrontend/brig-code-entry-handler.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-code-entry-handler.cc Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/brig/brigfrontend/brig-code-entry-handler.cc Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* brig-code-entry-handler.cc -- a gccbrig base class - 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. @@ -41,24 +41,9 @@ #include "brig-builtins.h" #include "fold-const.h" -brig_code_entry_handler::builtin_map brig_code_entry_handler::s_custom_builtins; - brig_code_entry_handler::brig_code_entry_handler (brig_to_generic &parent) : brig_entry_handler (parent) { - if (s_custom_builtins.size () > 0) return; - - /* Populate the builtin index. */ -#undef DEF_HSAIL_ATOMIC_BUILTIN -#undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN -#undef DEF_HSAIL_INTR_BUILTIN -#undef DEF_HSAIL_SAT_BUILTIN -#undef DEF_HSAIL_BUILTIN -#define DEF_HSAIL_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, NAME, TYPE, ATTRS) \ - s_custom_builtins[std::make_pair (HSAIL_OPCODE, HSAIL_TYPE)] \ - = builtin_decl_explicit (ENUM); - -#include "brig-builtins.def" } /* Build a tree operand which is a reference to a piece of code. REF is the @@ -137,14 +122,7 @@ correct size here so we don't need a separate unpack/pack for it. fp16-fp32 conversion is done in build_operands (). */ if (is_input && TREE_TYPE (element) != operand_type) - { - if (int_size_in_bytes (TREE_TYPE (element)) - == int_size_in_bytes (operand_type) - && !INTEGRAL_TYPE_P (operand_type)) - element = build1 (VIEW_CONVERT_EXPR, operand_type, element); - else - element = convert (operand_type, element); - } + element = build_resize_convert_view (operand_type, element); CONSTRUCTOR_APPEND_ELT (constructor_vals, NULL_TREE, element); ++operand_ptr; @@ -308,18 +286,18 @@ tree local_size = build2 (MULT_EXPR, uint32_type_node, - expand_or_call_builtin (BRIG_OPCODE_WORKGROUPSIZE, - BRIG_TYPE_U32, - uint32_type_node, uint32_0), - expand_or_call_builtin (BRIG_OPCODE_WORKGROUPSIZE, - BRIG_TYPE_U32, - uint32_type_node, uint32_1)); + m_parent.m_cf->expand_or_call_builtin + (BRIG_OPCODE_WORKGROUPSIZE, BRIG_TYPE_U32, + uint32_type_node, uint32_0), + m_parent.m_cf->expand_or_call_builtin + (BRIG_OPCODE_WORKGROUPSIZE, BRIG_TYPE_U32, + uint32_type_node, uint32_1)); local_size = build2 (MULT_EXPR, uint32_type_node, - expand_or_call_builtin (BRIG_OPCODE_WORKGROUPSIZE, - BRIG_TYPE_U32, - uint32_type_node, uint32_2), + m_parent.m_cf->expand_or_call_builtin + (BRIG_OPCODE_WORKGROUPSIZE, BRIG_TYPE_U32, + uint32_type_node, uint32_2), local_size); tree var_region @@ -331,9 +309,9 @@ = build2 (MULT_EXPR, uint32_type_node, build_int_cst (uint32_type_node, m_parent.private_variable_size (var_name)), - expand_or_call_builtin (BRIG_OPCODE_WORKITEMFLATID, - BRIG_TYPE_U32, - uint32_type_node, operands)); + m_parent.m_cf->expand_or_call_builtin + (BRIG_OPCODE_WORKITEMFLATID, BRIG_TYPE_U32, + uint32_type_node, operands)); tree var_offset = build2 (PLUS_EXPR, uint32_type_node, var_region, pos); @@ -343,8 +321,9 @@ offset to a flat address by adding it as an offset to a (private or group) base pointer later on. Same applies to group_var_offset. */ symbol_base - = add_temp_var ("priv_var_offset", - convert (size_type_node, var_offset)); + = m_parent.m_cf->add_temp_var ("priv_var_offset", + convert (size_type_node, + var_offset)); } else if (segment == BRIG_SEGMENT_ARG) { @@ -368,7 +347,7 @@ to the array object. */ if (POINTER_TYPE_P (TREE_TYPE (arg_var_decl))) - symbol_base = build_reinterpret_cast (ptype, arg_var_decl); + symbol_base = build_resize_convert_view (ptype, arg_var_decl); else { /* In case we are referring to an array (the argument in @@ -436,7 +415,8 @@ = (const BrigOperandRegister *) m_parent.get_brig_operand_entry (addr_operand.reg); tree base_reg_var = m_parent.m_cf->get_m_var_declfor_reg (mem_base_reg); - var_offset = convert_to_pointer (ptr_type_node, base_reg_var); + tree as_uint = build_reinterpret_to_uint (base_reg_var); + var_offset = convert_to_pointer (ptr_type_node, as_uint); gcc_assert (var_offset != NULL_TREE); } @@ -527,7 +507,10 @@ = ((const uint32_t *) &operand_entries->bytes)[operand_index]; const BrigBase *operand_data = m_parent.get_brig_operand_entry (operand_offset); - return build_tree_operand (*brig_inst, *operand_data, operand_type); + + bool inputp = !gccbrig_hsa_opcode_op_output_p (brig_inst->opcode, + operand_index); + return build_tree_operand (*brig_inst, *operand_data, operand_type, inputp); } /* Builds a single (scalar) constant initialized element of type @@ -641,7 +624,8 @@ { /* In case of vector type elements (or sole vectors), create a vector ctor. */ - size_t element_count = TYPE_VECTOR_SUBPARTS (tree_element_type); + size_t element_count + = gccbrig_type_vector_subparts (tree_element_type); if (bytes_left < scalar_element_size * element_count) fatal_error (UNKNOWN_LOCATION, "Not enough bytes left for the initializer " @@ -701,138 +685,6 @@ return gccbrig_tree_type_for_hsa_type (brig_type); } -/* In case the HSA instruction must be implemented using a builtin, - this function is called to get the correct builtin function. - TYPE is the instruction tree type, BRIG_OPCODE the opcode of the - brig instruction and BRIG_TYPE the brig instruction's type. */ - -tree -brig_code_entry_handler::get_builtin_for_hsa_opcode - (tree type, BrigOpcode16_t brig_opcode, BrigType16_t brig_type) const -{ - tree builtin = NULL_TREE; - tree builtin_type = type; - - /* For vector types, first find the scalar version of the builtin. */ - if (type != NULL_TREE && VECTOR_TYPE_P (type)) - builtin_type = TREE_TYPE (type); - BrigType16_t brig_inner_type = brig_type & BRIG_TYPE_BASE_MASK; - - /* Some BRIG opcodes can use the same builtins for unsigned and - signed types. Force these cases to unsigned types. */ - - if (brig_opcode == BRIG_OPCODE_BORROW - || brig_opcode == BRIG_OPCODE_CARRY - || brig_opcode == BRIG_OPCODE_LASTBIT - || brig_opcode == BRIG_OPCODE_BITINSERT) - { - if (brig_type == BRIG_TYPE_S32) - brig_type = BRIG_TYPE_U32; - else if (brig_type == BRIG_TYPE_S64) - brig_type = BRIG_TYPE_U64; - } - - switch (brig_opcode) - { - case BRIG_OPCODE_FLOOR: - builtin = mathfn_built_in (builtin_type, BUILT_IN_FLOOR); - break; - case BRIG_OPCODE_CEIL: - builtin = mathfn_built_in (builtin_type, BUILT_IN_CEIL); - break; - case BRIG_OPCODE_SQRT: - case BRIG_OPCODE_NSQRT: - builtin = mathfn_built_in (builtin_type, BUILT_IN_SQRT); - break; - case BRIG_OPCODE_RINT: - builtin = mathfn_built_in (builtin_type, BUILT_IN_RINT); - break; - case BRIG_OPCODE_TRUNC: - builtin = mathfn_built_in (builtin_type, BUILT_IN_TRUNC); - break; - case BRIG_OPCODE_COPYSIGN: - builtin = mathfn_built_in (builtin_type, BUILT_IN_COPYSIGN); - break; - case BRIG_OPCODE_NSIN: - builtin = mathfn_built_in (builtin_type, BUILT_IN_SIN); - break; - case BRIG_OPCODE_NLOG2: - builtin = mathfn_built_in (builtin_type, BUILT_IN_LOG2); - break; - case BRIG_OPCODE_NEXP2: - builtin = mathfn_built_in (builtin_type, BUILT_IN_EXP2); - break; - case BRIG_OPCODE_NFMA: - builtin = mathfn_built_in (builtin_type, BUILT_IN_FMA); - break; - case BRIG_OPCODE_NCOS: - builtin = mathfn_built_in (builtin_type, BUILT_IN_COS); - break; - case BRIG_OPCODE_POPCOUNT: - /* Popcount should be typed by its argument type (the return value - is always u32). Let's use a b64 version for also for b32 for now. */ - return builtin_decl_explicit (BUILT_IN_POPCOUNTL); - case BRIG_OPCODE_BORROW: - /* Borrow uses the same builtin for unsigned and signed types. */ - if (brig_type == BRIG_TYPE_S32 || brig_type == BRIG_TYPE_U32) - return builtin_decl_explicit (BUILT_IN_HSAIL_BORROW_U32); - else - return builtin_decl_explicit (BUILT_IN_HSAIL_BORROW_U64); - case BRIG_OPCODE_CARRY: - /* Carry also uses the same builtin for unsigned and signed types. */ - if (brig_type == BRIG_TYPE_S32 || brig_type == BRIG_TYPE_U32) - return builtin_decl_explicit (BUILT_IN_HSAIL_CARRY_U32); - else - return builtin_decl_explicit (BUILT_IN_HSAIL_CARRY_U64); - default: - - /* Use our builtin index for finding a proper builtin for the BRIG - opcode and BRIG type. This takes care most of the builtin cases, - the special cases are handled in the separate 'case' statements - above. */ - builtin_map::const_iterator i - = s_custom_builtins.find (std::make_pair (brig_opcode, brig_type)); - if (i != s_custom_builtins.end ()) - return (*i).second; - - if (brig_inner_type != brig_type) - { - /* Try to find a scalar built-in we could use. */ - i = s_custom_builtins.find - (std::make_pair (brig_opcode, brig_inner_type)); - if (i != s_custom_builtins.end ()) - return (*i).second; - } - - /* In case this is an fp16 operation that is promoted to fp32, - try to find a fp32 scalar built-in. */ - if (brig_inner_type == BRIG_TYPE_F16) - { - i = s_custom_builtins.find - (std::make_pair (brig_opcode, BRIG_TYPE_F32)); - if (i != s_custom_builtins.end ()) - return (*i).second; - } - gcc_unreachable (); - } - - if (VECTOR_TYPE_P (type) && builtin != NULL_TREE) - { - /* Try to find a vectorized version of the built-in. - TODO: properly assert that builtin is a mathfn builtin? */ - tree vec_builtin - = targetm.vectorize.builtin_vectorized_function - (builtin_mathfn_code (builtin), type, type); - if (vec_builtin != NULL_TREE) - return vec_builtin; - else - return builtin; - } - if (builtin == NULL_TREE) - gcc_unreachable (); - return builtin; -} - /* Return the correct GENERIC type for storing comparison results of operand with the type given in SOURCE_TYPE. */ @@ -844,277 +696,12 @@ size_t element_size = int_size_in_bytes (TREE_TYPE (source_type)); return build_vector_type (build_nonstandard_boolean_type (element_size * BITS_PER_UNIT), - TYPE_VECTOR_SUBPARTS (source_type)); + gccbrig_type_vector_subparts (source_type)); } else return gccbrig_tree_type_for_hsa_type (BRIG_TYPE_B1); } -/* Returns true in case the given opcode needs to know about work-item context - data. In such case the context data is passed as a pointer to a work-item - context object, as the last argument in the builtin call. */ - -bool -brig_code_entry_handler::needs_workitem_context_data - (BrigOpcode16_t brig_opcode) const -{ - switch (brig_opcode) - { - case BRIG_OPCODE_WORKITEMABSID: - case BRIG_OPCODE_WORKITEMFLATABSID: - case BRIG_OPCODE_WORKITEMFLATID: - case BRIG_OPCODE_CURRENTWORKITEMFLATID: - case BRIG_OPCODE_WORKITEMID: - case BRIG_OPCODE_WORKGROUPID: - case BRIG_OPCODE_WORKGROUPSIZE: - case BRIG_OPCODE_CURRENTWORKGROUPSIZE: - case BRIG_OPCODE_GRIDGROUPS: - case BRIG_OPCODE_GRIDSIZE: - case BRIG_OPCODE_DIM: - case BRIG_OPCODE_PACKETID: - case BRIG_OPCODE_PACKETCOMPLETIONSIG: - case BRIG_OPCODE_BARRIER: - case BRIG_OPCODE_WAVEBARRIER: - case BRIG_OPCODE_ARRIVEFBAR: - case BRIG_OPCODE_INITFBAR: - case BRIG_OPCODE_JOINFBAR: - case BRIG_OPCODE_LEAVEFBAR: - case BRIG_OPCODE_RELEASEFBAR: - case BRIG_OPCODE_WAITFBAR: - case BRIG_OPCODE_CUID: - case BRIG_OPCODE_MAXCUID: - case BRIG_OPCODE_DEBUGTRAP: - case BRIG_OPCODE_GROUPBASEPTR: - case BRIG_OPCODE_KERNARGBASEPTR: - case BRIG_OPCODE_ALLOCA: - return true; - default: - return false; - }; -} - -/* Returns true in case the given opcode that would normally be generated - as a builtin call can be expanded to tree nodes. */ - -bool -brig_code_entry_handler::can_expand_builtin (BrigOpcode16_t brig_opcode) const -{ - switch (brig_opcode) - { - case BRIG_OPCODE_WORKITEMFLATABSID: - case BRIG_OPCODE_WORKITEMFLATID: - case BRIG_OPCODE_WORKITEMABSID: - case BRIG_OPCODE_WORKGROUPSIZE: - case BRIG_OPCODE_CURRENTWORKGROUPSIZE: - /* TODO: expand more builtins. */ - return true; - default: - return false; - }; -} - -/* Try to expand the given builtin call to reuse a previously generated - variable, if possible. If not, just call the given builtin. - BRIG_OPCODE and BRIG_TYPE identify the builtin's BRIG opcode/type, - ARITH_TYPE its GENERIC type, and OPERANDS contains the builtin's - input operands. */ - -tree -brig_code_entry_handler::expand_or_call_builtin (BrigOpcode16_t brig_opcode, - BrigType16_t brig_type, - tree arith_type, - tree_stl_vec &operands) -{ - if (m_parent.m_cf->m_is_kernel && can_expand_builtin (brig_opcode)) - return expand_builtin (brig_opcode, operands); - - tree built_in - = get_builtin_for_hsa_opcode (arith_type, brig_opcode, brig_type); - - if (!VECTOR_TYPE_P (TREE_TYPE (TREE_TYPE (built_in))) - && arith_type != NULL_TREE && VECTOR_TYPE_P (arith_type) - && brig_opcode != BRIG_OPCODE_LERP - && brig_opcode != BRIG_OPCODE_PACKCVT - && brig_opcode != BRIG_OPCODE_SAD - && brig_opcode != BRIG_OPCODE_SADHI) - { - /* Call the scalar built-in for all elements in the vector. */ - tree_stl_vec operand0_elements; - if (operands.size () > 0) - unpack (operands[0], operand0_elements); - - tree_stl_vec operand1_elements; - if (operands.size () > 1) - unpack (operands[1], operand1_elements); - - tree_stl_vec result_elements; - - for (size_t i = 0; i < TYPE_VECTOR_SUBPARTS (arith_type); ++i) - { - tree_stl_vec call_operands; - if (operand0_elements.size () > 0) - call_operands.push_back (operand0_elements.at (i)); - - if (operand1_elements.size () > 0) - call_operands.push_back (operand1_elements.at (i)); - - result_elements.push_back - (expand_or_call_builtin (brig_opcode, brig_type, - TREE_TYPE (arith_type), - call_operands)); - } - return pack (result_elements); - } - - tree_stl_vec call_operands; - tree_stl_vec operand_types; - - tree arg_type_chain = TYPE_ARG_TYPES (TREE_TYPE (built_in)); - - for (size_t i = 0; i < operands.size (); ++i) - { - tree operand_type = TREE_VALUE (arg_type_chain); - call_operands.push_back (convert (operand_type, operands[i])); - operand_types.push_back (operand_type); - arg_type_chain = TREE_CHAIN (arg_type_chain); - } - - if (needs_workitem_context_data (brig_opcode)) - { - call_operands.push_back (m_parent.m_cf->m_context_arg); - operand_types.push_back (ptr_type_node); - m_parent.m_cf->m_has_unexpanded_dp_builtins = true; - } - - size_t operand_count = call_operands.size (); - - call_operands.resize (4, NULL_TREE); - operand_types.resize (4, NULL_TREE); - for (size_t i = 0; i < operand_count; ++i) - call_operands.at (i) = build_reinterpret_cast (operand_types.at (i), - call_operands.at (i)); - - tree fnptr = build_fold_addr_expr (built_in); - return build_call_array (TREE_TYPE (TREE_TYPE (built_in)), fnptr, - operand_count, &call_operands[0]); -} - -/* Instead of calling a built-in, reuse a previously returned value known to - be still valid. This is beneficial especially for the work-item - identification related builtins as not having them as calls can lead to - more easily vectorizable parallel loops for multi work-item work-groups. - BRIG_OPCODE identifies the builtin and OPERANDS store the operands. */ - -tree -brig_code_entry_handler::expand_builtin (BrigOpcode16_t brig_opcode, - tree_stl_vec &operands) -{ - tree_stl_vec uint32_0 = tree_stl_vec (1, build_int_cst (uint32_type_node, 0)); - - tree_stl_vec uint32_1 = tree_stl_vec (1, build_int_cst (uint32_type_node, 1)); - - tree_stl_vec uint32_2 = tree_stl_vec (1, build_int_cst (uint32_type_node, 2)); - - if (brig_opcode == BRIG_OPCODE_WORKITEMFLATABSID) - { - tree id0 = expand_builtin (BRIG_OPCODE_WORKITEMABSID, uint32_0); - id0 = convert (uint64_type_node, id0); - - tree id1 = expand_builtin (BRIG_OPCODE_WORKITEMABSID, uint32_1); - id1 = convert (uint64_type_node, id1); - - tree id2 = expand_builtin (BRIG_OPCODE_WORKITEMABSID, uint32_2); - id2 = convert (uint64_type_node, id2); - - tree max0 = convert (uint64_type_node, - m_parent.m_cf->m_grid_size_vars[0]); - tree max1 = convert (uint64_type_node, - m_parent.m_cf->m_grid_size_vars[1]); - - tree id2_x_max0_x_max1 = build2 (MULT_EXPR, uint64_type_node, id2, max0); - id2_x_max0_x_max1 - = build2 (MULT_EXPR, uint64_type_node, id2_x_max0_x_max1, max1); - - tree id1_x_max0 = build2 (MULT_EXPR, uint64_type_node, id1, max0); - - tree sum = build2 (PLUS_EXPR, uint64_type_node, id0, id1_x_max0); - sum = build2 (PLUS_EXPR, uint64_type_node, sum, id2_x_max0_x_max1); - - return add_temp_var ("workitemflatabsid", sum); - } - else if (brig_opcode == BRIG_OPCODE_WORKITEMABSID) - { - HOST_WIDE_INT dim = int_constant_value (operands[0]); - - tree local_id_var = m_parent.m_cf->m_local_id_vars[dim]; - tree wg_id_var = m_parent.m_cf->m_wg_id_vars[dim]; - tree wg_size_var = m_parent.m_cf->m_wg_size_vars[dim]; - tree grid_size_var = m_parent.m_cf->m_grid_size_vars[dim]; - - tree wg_id_x_wg_size = build2 (MULT_EXPR, uint32_type_node, - convert (uint32_type_node, wg_id_var), - convert (uint32_type_node, wg_size_var)); - tree sum - = build2 (PLUS_EXPR, uint32_type_node, wg_id_x_wg_size, local_id_var); - - /* We need a modulo here because of work-groups which have dimensions - larger than the grid size :( TO CHECK: is this really allowed in the - specs? */ - tree modulo - = build2 (TRUNC_MOD_EXPR, uint32_type_node, sum, grid_size_var); - - return add_temp_var (std::string ("workitemabsid_") - + (char) ((int) 'x' + dim), - modulo); - } - else if (brig_opcode == BRIG_OPCODE_WORKITEMFLATID) - { - tree z_x_wgsx_wgsy - = build2 (MULT_EXPR, uint32_type_node, - m_parent.m_cf->m_local_id_vars[2], - m_parent.m_cf->m_wg_size_vars[0]); - z_x_wgsx_wgsy = build2 (MULT_EXPR, uint32_type_node, z_x_wgsx_wgsy, - m_parent.m_cf->m_wg_size_vars[1]); - - tree y_x_wgsx - = build2 (MULT_EXPR, uint32_type_node, - m_parent.m_cf->m_local_id_vars[1], - m_parent.m_cf->m_wg_size_vars[0]); - - tree sum = build2 (PLUS_EXPR, uint32_type_node, y_x_wgsx, z_x_wgsx_wgsy); - sum = build2 (PLUS_EXPR, uint32_type_node, - m_parent.m_cf->m_local_id_vars[0], - sum); - return add_temp_var ("workitemflatid", sum); - } - else if (brig_opcode == BRIG_OPCODE_WORKGROUPSIZE) - { - HOST_WIDE_INT dim = int_constant_value (operands[0]); - return m_parent.m_cf->m_wg_size_vars[dim]; - } - else if (brig_opcode == BRIG_OPCODE_CURRENTWORKGROUPSIZE) - { - HOST_WIDE_INT dim = int_constant_value (operands[0]); - return m_parent.m_cf->m_cur_wg_size_vars[dim]; - } - else - gcc_unreachable (); - - return NULL_TREE; -} - -/* Appends and returns a new temp variable and an accompanying assignment - statement that stores the value of the given EXPR and has the given NAME. */ - -tree -brig_code_entry_handler::add_temp_var (std::string name, tree expr) -{ - tree temp_var = create_tmp_var (TREE_TYPE (expr), name.c_str ()); - tree assign = build2 (MODIFY_EXPR, TREE_TYPE (temp_var), temp_var, expr); - m_parent.m_cf->append_statement (assign); - return temp_var; -} - /* Creates a FP32 to FP16 conversion call, assuming the source and destination are FP32 type variables. */ @@ -1141,6 +728,28 @@ tree_stl_vec brig_code_entry_handler::build_operands (const BrigInstBase &brig_inst) { + return build_or_analyze_operands (brig_inst, false); +} + +void +brig_code_entry_handler::analyze_operands (const BrigInstBase &brig_inst) +{ + build_or_analyze_operands (brig_inst, true); +} + +/* Implements both the build_operands () and analyze_operands () call + so changes go in tandem. Performs build_operands () when ANALYZE + is false. Otherwise, only analyze operands and return empty + list. + + If analyzing record each HSA register operand with the + corresponding resolved operand tree type to + brig_to_generic::m_fn_regs_use_index. */ + +tree_stl_vec +brig_code_entry_handler:: +build_or_analyze_operands (const BrigInstBase &brig_inst, bool analyze) +{ /* Flush to zero. */ bool ftz = false; const BrigBase *base = &brig_inst.base; @@ -1308,9 +917,19 @@ /* Treat the operands as the storage type at this point. */ operand_type = half_storage_type; + if (analyze) + { + if (operand_data->kind == BRIG_KIND_OPERAND_REGISTER) + { + const BrigOperandRegister &brig_reg + = (const BrigOperandRegister &) *operand_data; + m_parent.add_reg_used_as_type (brig_reg, operand_type); + } + continue; + } + tree operand = build_tree_operand (brig_inst, *operand_data, operand_type, !is_output); - gcc_assert (operand); /* Cast/convert the inputs to correct types as expected by the GENERIC @@ -1319,36 +938,17 @@ { if (half_to_float) operand = build_h2f_conversion - (build_reinterpret_cast (half_storage_type, operand)); + (build_resize_convert_view (half_storage_type, operand)); else if (TREE_CODE (operand) != LABEL_DECL && TREE_CODE (operand) != TREE_VEC && operand_data->kind != BRIG_KIND_OPERAND_ADDRESS - && !VECTOR_TYPE_P (TREE_TYPE (operand))) + && operand_data->kind != BRIG_KIND_OPERAND_OPERAND_LIST) { - size_t reg_width = int_size_in_bytes (TREE_TYPE (operand)); - size_t instr_width = int_size_in_bytes (operand_type); - if (reg_width == instr_width) - operand = build_reinterpret_cast (operand_type, operand); - else if (reg_width > instr_width) - { - /* Clip the operand because the instruction's bitwidth - is smaller than the HSAIL reg width. */ - if (INTEGRAL_TYPE_P (operand_type)) - operand - = convert_to_integer (signed_or_unsigned_type_for - (TYPE_UNSIGNED (operand_type), - operand_type), operand); - else - operand = build_reinterpret_cast (operand_type, operand); - } - else if (reg_width < instr_width) - /* At least shift amount operands can be read from smaller - registers than the data operands. */ - operand = convert (operand_type, operand); + operand = build_resize_convert_view (operand_type, operand); } else if (brig_inst.opcode == BRIG_OPCODE_SHUFFLE) /* Force the operand type to be treated as the raw type. */ - operand = build_reinterpret_cast (operand_type, operand); + operand = build_resize_convert_view (operand_type, operand); if (brig_inst.opcode == BRIG_OPCODE_CMOV && i == 1) { @@ -1379,10 +979,10 @@ brig_code_entry_handler::build_output_assignment (const BrigInstBase &brig_inst, tree output, tree inst_expr) { - /* The destination type might be different from the output register - variable type (which is always an unsigned integer type). */ + /* The result/input type might be different from the output register + variable type (can be any type; see get_m_var_declfor_reg @ + brig-function.cc). */ tree output_type = TREE_TYPE (output); - tree input_type = TREE_TYPE (inst_expr); bool is_fp16 = (brig_inst.type & BRIG_TYPE_BASE_MASK) == BRIG_TYPE_F16 && brig_inst.base.kind != BRIG_KIND_INST_MEM && !gccbrig_is_bit_operation (brig_inst.opcode); @@ -1391,6 +991,13 @@ bool ftz = false; const BrigBase *base = &brig_inst.base; + if (m_parent.m_cf->is_id_val (inst_expr)) + inst_expr = m_parent.m_cf->id_val (inst_expr); + + tree input_type = TREE_TYPE (inst_expr); + + m_parent.m_cf->add_reg_var_update (output, inst_expr); + if (base->kind == BRIG_KIND_INST_MOD) { const BrigInstMod *mod = (const BrigInstMod *) base; @@ -1413,20 +1020,20 @@ { /* Ensure we don't duplicate the arithmetics to the arguments of the bit field reference operators. */ - inst_expr = add_temp_var ("before_ftz", inst_expr); + inst_expr = m_parent.m_cf->add_temp_var ("before_ftz", inst_expr); inst_expr = flush_to_zero (is_fp16) (*this, inst_expr); } if (is_fp16) { - inst_expr = add_temp_var ("before_f2h", inst_expr); + inst_expr = m_parent.m_cf->add_temp_var ("before_f2h", inst_expr); tree f2h_output = build_f2h_conversion (inst_expr); - tree conv_int = convert_to_integer (output_type, f2h_output); - tree assign = build2 (MODIFY_EXPR, output_type, output, conv_int); + tree conv = build_resize_convert_view (output_type, f2h_output); + tree assign = build2 (MODIFY_EXPR, output_type, output, conv); m_parent.m_cf->append_statement (assign); return assign; } - else if (VECTOR_TYPE_P (TREE_TYPE (output))) + else if (VECTOR_TYPE_P (output_type) && TREE_CODE (output) == CONSTRUCTOR) { /* Expand/unpack the input value to the given vector elements. */ size_t i; @@ -1454,22 +1061,21 @@ bitwidths. */ size_t src_width = int_size_in_bytes (input_type); size_t dst_width = int_size_in_bytes (output_type); - - if (src_width == dst_width) + tree input = inst_expr; + /* Integer results are extended to the target register width, using + the same sign as the inst_expr. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (input)) && src_width != dst_width) { - /* A simple bitcast should do. */ - tree bitcast = build_reinterpret_cast (output_type, inst_expr); - tree assign = build2 (MODIFY_EXPR, output_type, output, bitcast); - m_parent.m_cf->append_statement (assign); - return assign; + bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (input)); + tree resized_type + = build_nonstandard_integer_type (dst_width * BITS_PER_UNIT, + unsigned_p); + input = convert_to_integer (resized_type, input); } - else - { - tree conv_int = convert_to_integer (output_type, inst_expr); - tree assign = build2 (MODIFY_EXPR, output_type, output, conv_int); - m_parent.m_cf->append_statement (assign); - return assign; - } + input = build_resize_convert_view (output_type, input); + tree assign = build2 (MODIFY_EXPR, output_type, output, input); + m_parent.m_cf->append_statement (assign); + return assign; } return NULL_TREE; } @@ -1482,62 +1088,6 @@ m_parent.m_cf->append_statement (stmt); } -/* Unpacks the elements of the vector in VALUE to scalars (bit field - references) in ELEMENTS. */ - -void -brig_code_entry_handler::unpack (tree value, tree_stl_vec &elements) -{ - size_t vec_size = int_size_in_bytes (TREE_TYPE (value)); - size_t element_size - = int_size_in_bytes (TREE_TYPE (TREE_TYPE (value))) * BITS_PER_UNIT; - size_t element_count - = vec_size * BITS_PER_UNIT / element_size; - - tree input_element_type = TREE_TYPE (TREE_TYPE (value)); - - value = add_temp_var ("unpack_input", value); - - for (size_t i = 0; i < element_count; ++i) - { - tree element - = build3 (BIT_FIELD_REF, input_element_type, value, - TYPE_SIZE (input_element_type), - bitsize_int(i * element_size)); - - element = add_temp_var ("scalar", element); - elements.push_back (element); - } -} - -/* Pack the elements of the scalars in ELEMENTS to the returned vector. */ - -tree -brig_code_entry_handler::pack (tree_stl_vec &elements) -{ - size_t element_count = elements.size (); - - gcc_assert (element_count > 1); - - tree output_element_type = TREE_TYPE (elements.at (0)); - - vec<constructor_elt, va_gc> *constructor_vals = NULL; - for (size_t i = 0; i < element_count; ++i) - CONSTRUCTOR_APPEND_ELT (constructor_vals, NULL_TREE, elements.at (i)); - - tree vec_type = build_vector_type (output_element_type, element_count); - - /* build_constructor creates a vector type which is not a vector_cst - that requires compile time constant elements. */ - tree vec = build_constructor (vec_type, constructor_vals); - - /* Add a temp variable for readability. */ - tree tmp_var = create_tmp_var (vec_type, "vec_out"); - tree vec_tmp_assign = build2 (MODIFY_EXPR, TREE_TYPE (tmp_var), tmp_var, vec); - m_parent.m_cf->append_statement (vec_tmp_assign); - return tmp_var; -} - /* Visits the element(s) in the OPERAND, calling HANDLER to each of them. */ tree @@ -1672,7 +1222,7 @@ { tree built_in = builtin_decl_explicit (BUILT_IN_HSAIL_F32_TO_F16); - tree casted_operand = build_reinterpret_cast (uint32_type_node, operand); + tree casted_operand = build_resize_convert_view (uint32_type_node, operand); tree call = call_builtin (built_in, 1, uint16_type_node, uint32_type_node, casted_operand); @@ -1701,7 +1251,7 @@ tree output = create_tmp_var (const_fp32_type, "fp32out"); tree casted_result - = build_reinterpret_cast (brig_to_generic::s_fp32_type, call); + = build_resize_convert_view (brig_to_generic::s_fp32_type, call); tree assign = build2 (MODIFY_EXPR, TREE_TYPE (output), output, casted_result); @@ -1753,4 +1303,3 @@ n = TREE_OPERAND (n, 0); return int_cst_value (n); } -