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