1 /* brig-code-entry-handler.h -- a gccbrig base class
2    Copyright (C) 2016-2019 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   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 
47 protected:
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 
89 private:
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 
100 class tree_element_unary_visitor
101 {
102 public:
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 
112 class tree_element_binary_visitor
113 {
114 public:
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 
128 class flush_to_zero : public tree_element_unary_visitor
129 {
130 public:
flush_to_zero(bool fp16)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 
137 private:
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 
146 class half_to_float : public tree_element_unary_visitor
147 {
148 public:
149   virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
150 };
151 
152 /* Visitor for converting F32 elements to F16.  */
153 
154 class float_to_half : public tree_element_unary_visitor
155 {
156 public:
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 
166 class brig_inst_mod_handler : public brig_code_entry_handler
167 {
168 public:
brig_inst_mod_handler(brig_to_generic & parent)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 
181 class brig_directive_function_handler : public brig_code_entry_handler
182 {
183 public:
brig_directive_function_handler(brig_to_generic & parent)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 
191 class brig_directive_control_handler : public brig_code_entry_handler
192 {
193 public:
brig_directive_control_handler(brig_to_generic & parent)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 
202 class brig_directive_variable_handler : public brig_code_entry_handler
203 {
204 public:
brig_directive_variable_handler(brig_to_generic & parent)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 
218 class brig_directive_fbarrier_handler : public brig_code_entry_handler
219 {
220 public:
brig_directive_fbarrier_handler(brig_to_generic & parent)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 
229 class brig_directive_label_handler : public brig_code_entry_handler
230 {
231 public:
brig_directive_label_handler(brig_to_generic & parent)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 
240 class brig_directive_comment_handler : public brig_code_entry_handler
241 {
242 public:
brig_directive_comment_handler(brig_to_generic & parent)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 
251 class brig_directive_arg_block_handler : public brig_code_entry_handler
252 {
253 public:
brig_directive_arg_block_handler(brig_to_generic & parent)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 
262 class brig_basic_inst_handler : public brig_code_entry_handler
263 {
264 public:
265   brig_basic_inst_handler (brig_to_generic &parent);
266 
267   size_t operator () (const BrigBase *base);
268 
269 private:
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 
286 class brig_cvt_inst_handler : public brig_inst_mod_handler
287 {
288 public:
brig_cvt_inst_handler(brig_to_generic & parent)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 
299 class brig_branch_inst_handler : public brig_code_entry_handler
300 {
301 public:
brig_branch_inst_handler(brig_to_generic & parent)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 
310 class brig_mem_inst_handler : public brig_code_entry_handler
311 {
312 public:
brig_mem_inst_handler(brig_to_generic & parent)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 
320 private:
321   tree build_mem_access (const BrigInstBase *brig_inst, tree addr, tree data);
322 };
323 
324 class brig_copy_move_inst_handler : public brig_code_entry_handler
325 {
326 public:
brig_copy_move_inst_handler(brig_to_generic & parent)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 
334 private:
335   size_t handle_lda (const BrigInstBase *base);
336 };
337 
338 class brig_atomic_inst_handler : public brig_code_entry_handler
339 {
340 private:
341   typedef std::map<std::string, tree> atomic_builtins_map;
342 
343 public:
344   brig_atomic_inst_handler (brig_to_generic &parent);
345 
346   size_t operator () (const BrigBase *base);
347 
348 protected:
349   size_t generate_tree (const BrigInstBase &inst,
350 			BrigAtomicOperation8_t atomic_opcode);
351 };
352 
353 class brig_signal_inst_handler : public brig_atomic_inst_handler
354 {
355 public:
brig_signal_inst_handler(brig_to_generic & parent)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 
363 class brig_cmp_inst_handler : public brig_code_entry_handler
364 {
365 public:
brig_cmp_inst_handler(brig_to_generic & parent)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 
374 class brig_seg_inst_handler : public brig_code_entry_handler
375 {
376 public:
377   brig_seg_inst_handler (brig_to_generic &parent);
378 
379   size_t operator () (const BrigBase *base);
380 };
381 
382 class brig_lane_inst_handler : public brig_code_entry_handler
383 {
384 public:
385   brig_lane_inst_handler (brig_to_generic &parent);
386 
387   size_t operator () (const BrigBase *base);
388 };
389 
390 class brig_queue_inst_handler : public brig_code_entry_handler
391 {
392 public:
393   brig_queue_inst_handler (brig_to_generic &parent);
394 
395   size_t operator () (const BrigBase *base);
396 };
397 
398 class brig_directive_module_handler : public brig_code_entry_handler
399 {
400 public:
brig_directive_module_handler(brig_to_generic & parent)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