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