1/* brig-code-entry-handler.h -- a gccbrig base class 2 Copyright (C) 2016-2020 Free Software Foundation, Inc. 3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> 4 for General Processor Tech. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 3, or (at your option) any later 11 version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22#ifndef GCC_BRIG_CODE_ENTRY_HANDLER_H 23#define GCC_BRIG_CODE_ENTRY_HANDLER_H 24 25#include "brig-to-generic.h" 26 27#include <map> 28#include <vector> 29 30class tree_element_unary_visitor; 31 32/* An interface to organize the different types of element handlers 33 for the code section. */ 34 35class brig_code_entry_handler : public brig_entry_handler 36{ 37public: 38 brig_code_entry_handler (brig_to_generic &parent); 39 40 /* Handles the brig_code data at the given pointer and adds it to the 41 currently built tree. Returns the number of consumed bytes. */ 42 43 virtual size_t operator () (const BrigBase *base) = 0; 44 45 void append_statement (tree stmt); 46 47protected: 48 49 tree get_tree_expr_type_for_hsa_type (BrigType16_t brig_type) const; 50 tree get_tree_cst_for_hsa_operand (const BrigOperandConstantBytes *brigConst, 51 tree type) const; 52 tree get_comparison_result_type (tree source_type); 53 54 tree build_code_ref (const BrigBase &ref); 55 56 tree build_tree_operand (const BrigInstBase &brig_inst, 57 const BrigBase &operand, 58 tree operand_type = NULL_TREE, 59 bool is_input = false); 60 61 tree build_address_operand (const BrigInstBase &brig_inst, 62 const BrigOperandAddress &addr_operand); 63 64 tree build_tree_operand_from_brig (const BrigInstBase *brig_inst, 65 tree operand_type, size_t operand_index); 66 67 tree build_tree_cst_element (BrigType16_t element_type, 68 const unsigned char *next_data) const; 69 70 bool needs_workitem_context_data (BrigOpcode16_t brig_opcode) const; 71 72 tree add_temp_var (std::string name, tree expr); 73 74 tree build_f2h_conversion (tree source); 75 tree build_h2f_conversion (tree source); 76 77 tree_stl_vec build_operands (const BrigInstBase &brig_inst); 78 void analyze_operands (const BrigInstBase &brig_inst); 79 tree build_output_assignment (const BrigInstBase &brig_inst, tree output, 80 tree inst_expr); 81 82 tree apply_to_all_elements (tree_element_unary_visitor &visitor, 83 tree operand); 84 85 HOST_WIDE_INT int_constant_value (tree node); 86 87 tree extend_int (tree input, tree dest_type, tree src_type); 88 89private: 90 91 tree_stl_vec build_or_analyze_operands (const BrigInstBase &brig_inst, 92 bool analyze); 93}; 94 95/* Implement the Visitor software pattern for performing various actions on 96 elements of vector operands. This enables separating the vector element 97 traversal/extraction/packing code from whatever different actions are 98 performed to each element. */ 99 100class tree_element_unary_visitor 101{ 102public: 103 tree operator () (brig_code_entry_handler &handler, tree operand); 104 105 /* Performs an action to a single element, which can have originally 106 been a vector element or a scalar. */ 107 108 virtual tree visit_element (brig_code_entry_handler &handler, tree operand) 109 = 0; 110}; 111 112class tree_element_binary_visitor 113{ 114public: 115 tree operator () (brig_code_entry_handler &handler, tree operand0, 116 tree operand1); 117 118 /* Performs an action to a pair of elements, which can have originally 119 been a vector element or a scalar. */ 120 121 virtual tree visit_element (brig_code_entry_handler &handler, tree operand0, 122 tree operand1) 123 = 0; 124}; 125 126/* Visitor for flushing float elements to zero. */ 127 128class flush_to_zero : public tree_element_unary_visitor 129{ 130public: 131 flush_to_zero (bool fp16) : m_fp16 (fp16) 132 { 133 } 134 135 virtual tree visit_element (brig_code_entry_handler &caller, tree operand); 136 137private: 138 139 /* True if the value should be flushed according to fp16 limits. */ 140 141 bool m_fp16; 142}; 143 144/* Visitor for converting F16 elements to F32. */ 145 146class half_to_float : public tree_element_unary_visitor 147{ 148public: 149 virtual tree visit_element (brig_code_entry_handler &caller, tree operand); 150}; 151 152/* Visitor for converting F32 elements to F16. */ 153 154class float_to_half : public tree_element_unary_visitor 155{ 156public: 157 virtual tree visit_element (brig_code_entry_handler &caller, tree operand); 158}; 159 160/* A base class for instruction types that support floating point 161 modifiers. 162 163 operator () delegates to subclasses (template method pattern) in 164 type specific parts. */ 165 166class brig_inst_mod_handler : public brig_code_entry_handler 167{ 168public: 169 brig_inst_mod_handler (brig_to_generic &parent) 170 : brig_code_entry_handler (parent) 171 { 172 } 173 174 virtual size_t generate (const BrigBase *base); 175 virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const; 176 virtual const BrigRound8_t *round (const BrigBase *base) const; 177 178 size_t operator () (const BrigBase *base); 179}; 180 181class brig_directive_function_handler : public brig_code_entry_handler 182{ 183public: 184 brig_directive_function_handler (brig_to_generic &parent) 185 : brig_code_entry_handler (parent) 186 { 187 } 188 size_t operator () (const BrigBase *base); 189}; 190 191class brig_directive_control_handler : public brig_code_entry_handler 192{ 193public: 194 brig_directive_control_handler (brig_to_generic &parent) 195 : brig_code_entry_handler (parent) 196 { 197 } 198 199 size_t operator () (const BrigBase *base); 200}; 201 202class brig_directive_variable_handler : public brig_code_entry_handler 203{ 204public: 205 brig_directive_variable_handler (brig_to_generic &parent) 206 : brig_code_entry_handler (parent) 207 { 208 } 209 210 size_t operator () (const BrigBase *base); 211 212 tree build_variable (const BrigDirectiveVariable *brigVar, 213 tree_code var_decltype = VAR_DECL); 214 215 size_t get_brig_var_alignment (const BrigDirectiveVariable *brigVar); 216}; 217 218class brig_directive_fbarrier_handler : public brig_code_entry_handler 219{ 220public: 221 brig_directive_fbarrier_handler (brig_to_generic &parent) 222 : brig_code_entry_handler (parent) 223 { 224 } 225 226 size_t operator () (const BrigBase *base); 227}; 228 229class brig_directive_label_handler : public brig_code_entry_handler 230{ 231public: 232 brig_directive_label_handler (brig_to_generic &parent) 233 : brig_code_entry_handler (parent) 234 { 235 } 236 237 size_t operator () (const BrigBase *base); 238}; 239 240class brig_directive_comment_handler : public brig_code_entry_handler 241{ 242public: 243 brig_directive_comment_handler (brig_to_generic &parent) 244 : brig_code_entry_handler (parent) 245 { 246 } 247 248 size_t operator () (const BrigBase *base); 249}; 250 251class brig_directive_arg_block_handler : public brig_code_entry_handler 252{ 253public: 254 brig_directive_arg_block_handler (brig_to_generic &parent) 255 : brig_code_entry_handler (parent) 256 { 257 } 258 259 size_t operator () (const BrigBase *base); 260}; 261 262class brig_basic_inst_handler : public brig_code_entry_handler 263{ 264public: 265 brig_basic_inst_handler (brig_to_generic &parent); 266 267 size_t operator () (const BrigBase *base); 268 269private: 270 tree build_lower_element_broadcast (tree vec_operand); 271 272 bool must_be_scalarized (const BrigInstBase *brig_inst, 273 tree instr_type) const; 274 275 tree build_inst_expr (BrigOpcode16_t brig_opcode, BrigType16_t brig_type, 276 tree arith_type, tree_stl_vec &operands); 277 278 tree build_shuffle (tree arith_type, tree_stl_vec &operands); 279 tree build_unpack (tree_stl_vec &operands); 280 tree build_pack (tree_stl_vec &operands); 281 282 tree build_unpack_lo_or_hi (BrigOpcode16_t brig_opcode, tree arith_type, 283 tree_stl_vec &operands); 284}; 285 286class brig_cvt_inst_handler : public brig_inst_mod_handler 287{ 288public: 289 brig_cvt_inst_handler (brig_to_generic &parent) 290 : brig_inst_mod_handler (parent) 291 { 292 } 293 294 virtual size_t generate (const BrigBase *base); 295 virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const; 296 virtual const BrigRound8_t *round (const BrigBase *base) const; 297}; 298 299class brig_branch_inst_handler : public brig_code_entry_handler 300{ 301public: 302 brig_branch_inst_handler (brig_to_generic &parent) 303 : brig_code_entry_handler (parent) 304 { 305 } 306 307 size_t operator () (const BrigBase *base); 308}; 309 310class brig_mem_inst_handler : public brig_code_entry_handler 311{ 312public: 313 brig_mem_inst_handler (brig_to_generic &parent) 314 : brig_code_entry_handler (parent) 315 { 316 } 317 318 size_t operator () (const BrigBase *base); 319 320private: 321 tree build_mem_access (const BrigInstBase *brig_inst, tree addr, tree data); 322}; 323 324class brig_copy_move_inst_handler : public brig_code_entry_handler 325{ 326public: 327 brig_copy_move_inst_handler (brig_to_generic &parent) 328 : brig_code_entry_handler (parent) 329 { 330 } 331 332 size_t operator () (const BrigBase *base); 333 334private: 335 size_t handle_lda (const BrigInstBase *base); 336}; 337 338class brig_atomic_inst_handler : public brig_code_entry_handler 339{ 340private: 341 typedef std::map<std::string, tree> atomic_builtins_map; 342 343public: 344 brig_atomic_inst_handler (brig_to_generic &parent); 345 346 size_t operator () (const BrigBase *base); 347 348protected: 349 size_t generate_tree (const BrigInstBase &inst, 350 BrigAtomicOperation8_t atomic_opcode); 351}; 352 353class brig_signal_inst_handler : public brig_atomic_inst_handler 354{ 355public: 356 brig_signal_inst_handler (brig_to_generic &parent) 357 : brig_atomic_inst_handler (parent) 358 { 359 } 360 size_t operator () (const BrigBase *base); 361}; 362 363class brig_cmp_inst_handler : public brig_code_entry_handler 364{ 365public: 366 brig_cmp_inst_handler (brig_to_generic &parent) 367 : brig_code_entry_handler (parent) 368 { 369 } 370 371 size_t operator () (const BrigBase *base); 372}; 373 374class brig_seg_inst_handler : public brig_code_entry_handler 375{ 376public: 377 brig_seg_inst_handler (brig_to_generic &parent); 378 379 size_t operator () (const BrigBase *base); 380}; 381 382class brig_lane_inst_handler : public brig_code_entry_handler 383{ 384public: 385 brig_lane_inst_handler (brig_to_generic &parent); 386 387 size_t operator () (const BrigBase *base); 388}; 389 390class brig_queue_inst_handler : public brig_code_entry_handler 391{ 392public: 393 brig_queue_inst_handler (brig_to_generic &parent); 394 395 size_t operator () (const BrigBase *base); 396}; 397 398class brig_directive_module_handler : public brig_code_entry_handler 399{ 400public: 401 brig_directive_module_handler (brig_to_generic &parent) 402 : brig_code_entry_handler (parent) 403 { 404 } 405 406 size_t operator () (const BrigBase *base); 407}; 408 409 410#endif 411