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