]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/brig/brigfrontend/brig-util.cc
tree-emutls.c (lower_emutls_data): Remove unused bb_freq.
[thirdparty/gcc.git] / gcc / brig / brigfrontend / brig-util.cc
CommitLineData
5fd1486c 1/* brig-util.cc -- gccbrig utility functions
68edb9ba 2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
5fd1486c
PJ
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22#include <sstream>
23
24#include "stdint.h"
25#include "hsa-brig-format.h"
26#include "brig-util.h"
27#include "errors.h"
28#include "diagnostic-core.h"
29
d4b7f2ee
PJ
30bool
31group_variable_offset_index::has_variable (const std::string &name) const
32{
33 varname_offset_table::const_iterator i = m_group_offsets.find (name);
34 return i != m_group_offsets.end ();
35}
36
37/* Adds a new group segment variable. */
38
39void
40group_variable_offset_index::add (const std::string &name, size_t size,
41 size_t alignment)
42{
43 size_t align_padding = m_next_group_offset % alignment == 0 ?
44 0 : (alignment - m_next_group_offset % alignment);
45 m_next_group_offset += align_padding;
46 m_group_offsets[name] = m_next_group_offset;
47 m_next_group_offset += size;
48}
49
50size_t
51group_variable_offset_index::segment_offset (const std::string &name) const
52{
53 varname_offset_table::const_iterator i = m_group_offsets.find (name);
54 gcc_assert (i != m_group_offsets.end ());
55 return (*i).second;
56}
57
5fd1486c
PJ
58/* Return true if operand number OPNUM of instruction with OPCODE is an output.
59 False if it is an input. Some code reused from Martin Jambor's gcc-hsa
60 tree. */
61
62bool
63gccbrig_hsa_opcode_op_output_p (BrigOpcode16_t opcode, int opnum)
64{
65 switch (opcode)
66 {
67 case BRIG_OPCODE_BR:
68 case BRIG_OPCODE_SBR:
69 case BRIG_OPCODE_CBR:
70 case BRIG_OPCODE_ST:
71 case BRIG_OPCODE_ATOMICNORET:
72 case BRIG_OPCODE_SIGNALNORET:
73 case BRIG_OPCODE_INITFBAR:
74 case BRIG_OPCODE_JOINFBAR:
75 case BRIG_OPCODE_WAITFBAR:
76 case BRIG_OPCODE_ARRIVEFBAR:
77 case BRIG_OPCODE_LEAVEFBAR:
78 case BRIG_OPCODE_RELEASEFBAR:
79 case BRIG_OPCODE_DEBUGTRAP:
80 return false;
81 default:
82 return opnum == 0;
83 }
84}
85
86unsigned
87gccbrig_hsa_type_bit_size (BrigType16_t t)
88{
89
90 unsigned pack_type = t & ~BRIG_TYPE_BASE_MASK;
91
92 if (pack_type == BRIG_TYPE_PACK_32)
93 return 32;
94 else if (pack_type == BRIG_TYPE_PACK_64)
95 return 64;
96 else if (pack_type == BRIG_TYPE_PACK_128)
97 return 128;
98
99 switch (t)
100 {
101 case BRIG_TYPE_NONE:
102 return 0;
103
104 case BRIG_TYPE_B1:
105 return 1;
106
107 case BRIG_TYPE_U8:
108 case BRIG_TYPE_S8:
109 case BRIG_TYPE_B8:
110 return 8;
111
112 case BRIG_TYPE_U16:
113 case BRIG_TYPE_S16:
114 case BRIG_TYPE_B16:
115 case BRIG_TYPE_F16:
116 return 16;
117
118 case BRIG_TYPE_U32:
119 case BRIG_TYPE_S32:
120 case BRIG_TYPE_B32:
121 case BRIG_TYPE_F32:
122 case BRIG_TYPE_U8X4:
123 case BRIG_TYPE_U16X2:
124 case BRIG_TYPE_S8X4:
125 case BRIG_TYPE_S16X2:
126 case BRIG_TYPE_F16X2:
127 case BRIG_TYPE_SIG32:
128 return 32;
129
130 case BRIG_TYPE_U64:
131 case BRIG_TYPE_S64:
132 case BRIG_TYPE_F64:
133 case BRIG_TYPE_B64:
134 case BRIG_TYPE_U8X8:
135 case BRIG_TYPE_U16X4:
136 case BRIG_TYPE_U32X2:
137 case BRIG_TYPE_S8X8:
138 case BRIG_TYPE_S16X4:
139 case BRIG_TYPE_S32X2:
140 case BRIG_TYPE_F16X4:
141 case BRIG_TYPE_F32X2:
142 case BRIG_TYPE_SIG64:
143 return 64;
144
145 case BRIG_TYPE_B128:
146 case BRIG_TYPE_U8X16:
147 case BRIG_TYPE_U16X8:
148 case BRIG_TYPE_U32X4:
149 case BRIG_TYPE_U64X2:
150 case BRIG_TYPE_S8X16:
151 case BRIG_TYPE_S16X8:
152 case BRIG_TYPE_S32X4:
153 case BRIG_TYPE_S64X2:
154 case BRIG_TYPE_F16X8:
155 case BRIG_TYPE_F32X4:
156 case BRIG_TYPE_F64X2:
157 return 128;
158
159 default:
160 printf ("HMM %d %x\n", t, t);
161 gcc_unreachable ();
162 }
163}
164
165/* gcc-hsa borrowed code ENDS. */
166
167uint64_t
168gccbrig_to_uint64_t (const BrigUInt64 &brig_type)
169{
170 return (uint64_t (brig_type.hi) << 32) | uint64_t (brig_type.lo);
171}
172
173int
174gccbrig_reg_size (const BrigOperandRegister *brig_reg)
175{
176 switch (brig_reg->regKind)
177 {
178 case BRIG_REGISTER_KIND_CONTROL:
179 return 1;
180 case BRIG_REGISTER_KIND_SINGLE:
181 return 32;
182 case BRIG_REGISTER_KIND_DOUBLE:
183 return 64;
184 case BRIG_REGISTER_KIND_QUAD:
185 return 128;
186 default:
187 gcc_unreachable ();
188 break;
189 }
190}
191
192std::string
193gccbrig_reg_name (const BrigOperandRegister *reg)
194{
195 std::ostringstream strstr;
196 switch (reg->regKind)
197 {
198 case BRIG_REGISTER_KIND_CONTROL:
199 strstr << 'c';
200 break;
201 case BRIG_REGISTER_KIND_SINGLE:
202 strstr << 's';
203 break;
204 case BRIG_REGISTER_KIND_DOUBLE:
205 strstr << 'd';
206 break;
207 case BRIG_REGISTER_KIND_QUAD:
208 strstr << 'q';
209 break;
210 default:
211 gcc_unreachable ();
212 return "";
213 }
214 strstr << reg->regNum;
215 return strstr.str ();
216}
217
218std::string
219gccbrig_type_name (BrigType16_t type)
220{
221 switch (type)
222 {
223 case BRIG_TYPE_U8:
224 return "u8";
225 case BRIG_TYPE_U16:
226 return "u16";
227 case BRIG_TYPE_U32:
228 return "u32";
229 case BRIG_TYPE_U64:
230 return "u64";
231 case BRIG_TYPE_S8:
232 return "s8";
233 case BRIG_TYPE_S16:
234 return "s16";
235 case BRIG_TYPE_S32:
236 return "s32";
237 case BRIG_TYPE_S64:
238 return "s64";
239 default:
240 gcc_unreachable ();
241 break;
242 }
243}
244
245std::string
246gccbrig_segment_name (BrigSegment8_t segment)
247{
248 if (segment == BRIG_SEGMENT_GLOBAL)
249 return "global";
250 else if (segment == BRIG_SEGMENT_GROUP)
251 return "group";
252 else if (segment == BRIG_SEGMENT_PRIVATE)
253 return "private";
254 else
255 gcc_unreachable ();
256}
257
258bool
259gccbrig_is_float_type (BrigType16_t type)
260{
261 return (type == BRIG_TYPE_F32 || type == BRIG_TYPE_F64
262 || type == BRIG_TYPE_F16);
263}
264
265BrigType16_t
266gccbrig_tree_type_to_hsa_type (tree tree_type)
267{
268 if (INTEGRAL_TYPE_P (tree_type))
269 {
270 if (TYPE_UNSIGNED (tree_type))
271 {
272 switch (int_size_in_bytes (tree_type))
273 {
274 case 1:
275 return BRIG_TYPE_U8;
276 case 2:
277 return BRIG_TYPE_U16;
278 case 4:
279 return BRIG_TYPE_U32;
280 case 8:
281 return BRIG_TYPE_U64;
282 default:
283 break;
284 }
285 }
286 else
287 {
288 switch (int_size_in_bytes (tree_type))
289 {
290 case 1:
291 return BRIG_TYPE_S8;
292 case 2:
293 return BRIG_TYPE_S16;
294 case 4:
295 return BRIG_TYPE_S32;
296 case 8:
297 return BRIG_TYPE_S64;
298 default:
299 break;
300 }
301 }
302 }
303 else if (VECTOR_TYPE_P (tree_type))
304 {
305 tree element_type = TREE_TYPE (tree_type);
306 size_t element_size = int_size_in_bytes (element_type) * 8;
307 BrigType16_t brig_element_type;
308 switch (element_size)
309 {
310 case 8:
311 brig_element_type
312 = TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U8 : BRIG_TYPE_S8;
313 break;
314 case 16:
315 brig_element_type
316 = TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U16 : BRIG_TYPE_S16;
317 break;
318 case 32:
319 brig_element_type
320 = TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U32 : BRIG_TYPE_S32;
321 break;
322 case 64:
323 brig_element_type
324 = TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U64 : BRIG_TYPE_S64;
325 break;
326 default:
327 gcc_unreachable ();
328 }
329
330 BrigType16_t pack_type;
331 switch (int_size_in_bytes (tree_type) * 8)
332 {
333 case 32:
334 pack_type = BRIG_TYPE_PACK_32;
335 break;
336 case 64:
337 pack_type = BRIG_TYPE_PACK_64;
338 break;
339 case 128:
340 pack_type = BRIG_TYPE_PACK_128;
341 break;
342 default:
343 gcc_unreachable ();
344 }
345 return brig_element_type | pack_type;
346 }
347 gcc_unreachable ();
348}
349
350/* Returns true in case the operation is a "bit level" operation,
351 that is, not having operand type depending semantical differences. */
352
353bool
354gccbrig_is_bit_operation (BrigOpcode16_t opcode)
355{
356 return opcode == BRIG_OPCODE_CMOV || opcode == BRIG_OPCODE_SHUFFLE
357 || opcode == BRIG_OPCODE_UNPACK || opcode == BRIG_OPCODE_UNPACKLO
358 || opcode == BRIG_OPCODE_UNPACKHI || opcode == BRIG_OPCODE_ST
359 || opcode == BRIG_OPCODE_PACK;
360}
361
362/* The program scope definition can be left external within the
363 kernel binary which means it must be defined by the host via
364 HSA runtime. For these we have special treatment:
365 Create additional pointer indirection when accessing the variable
366 value from kernel code through a generated pointer
367 __gccbrig_ptr_variable_name. The pointer value then can be set either
368 within the kernel binary (in case of a later linked in definition)
369 or from the host. */
370
371bool
372gccbrig_might_be_host_defined_var_p (const BrigDirectiveVariable *brigVar)
373{
374 bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
375 return (brigVar->segment == BRIG_SEGMENT_GLOBAL
376 || brigVar->segment == BRIG_SEGMENT_READONLY) && !is_definition
377 && brigVar->linkage == BRIG_LINKAGE_PROGRAM
378 && (brigVar->allocation == BRIG_ALLOCATION_PROGRAM
379 || brigVar->allocation == BRIG_ALLOCATION_AGENT);
380}
381
382/* Produce a GENERIC type for the given HSA/BRIG type. Returns the element
383 type in case of vector instructions. */
384
385tree
386gccbrig_tree_type_for_hsa_type (BrigType16_t brig_type)
387{
388 tree tree_type = NULL_TREE;
389
390 if (hsa_type_packed_p (brig_type))
391 {
392 /* The element type is encoded in the bottom 5 bits. */
393 BrigType16_t inner_brig_type = brig_type & BRIG_TYPE_BASE_MASK;
394
395 unsigned full_size = gccbrig_hsa_type_bit_size (brig_type);
396
397 if (inner_brig_type == BRIG_TYPE_F16)
398 return build_vector_type (gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16),
399 full_size / 16);
400
401 tree inner_type = gccbrig_tree_type_for_hsa_type (inner_brig_type);
402
403 unsigned inner_size = gccbrig_hsa_type_bit_size (inner_brig_type);
404 unsigned nunits = full_size / inner_size;
405 tree_type = build_vector_type (inner_type, nunits);
406 }
407 else
408 {
409 switch (brig_type)
410 {
411 case BRIG_TYPE_NONE:
412 tree_type = void_type_node;
413 break;
414 case BRIG_TYPE_B1:
415 tree_type = boolean_type_node;
416 break;
417 case BRIG_TYPE_S8:
418 case BRIG_TYPE_S16:
419 case BRIG_TYPE_S32:
420 case BRIG_TYPE_S64:
421 /* Ensure a fixed width integer. */
422 tree_type
423 = build_nonstandard_integer_type
424 (gccbrig_hsa_type_bit_size (brig_type), false);
425 break;
426 case BRIG_TYPE_U8:
427 return unsigned_char_type_node;
428 case BRIG_TYPE_U16:
429 case BRIG_TYPE_U32:
430 case BRIG_TYPE_U64:
431 case BRIG_TYPE_B8: /* Handle bit vectors as unsigned ints. */
432 case BRIG_TYPE_B16:
433 case BRIG_TYPE_B32:
434 case BRIG_TYPE_B64:
435 case BRIG_TYPE_B128:
436 case BRIG_TYPE_SIG32: /* Handle signals as integers for now. */
437 case BRIG_TYPE_SIG64:
438 tree_type = build_nonstandard_integer_type
439 (gccbrig_hsa_type_bit_size (brig_type), true);
440 break;
441 case BRIG_TYPE_F16:
442 tree_type = uint16_type_node;
443 break;
444 case BRIG_TYPE_F32:
445 /* TODO: make sure that the alignment of the float are at least as
446 strict than mandated by HSA, and conform to IEEE (like mandated
447 by HSA). */
448 tree_type = float_type_node;
449 break;
450 case BRIG_TYPE_F64:
451 tree_type = double_type_node;
452 break;
453 case BRIG_TYPE_SAMP:
454 case BRIG_TYPE_ROIMG:
455 case BRIG_TYPE_WOIMG:
456 case BRIG_TYPE_RWIMG:
457 {
458 /* Handle images and samplers as target-specific blobs of data
459 that should be allocated earlier on from the runtime side.
460 Create a void* that should be initialized to point to the blobs
461 by the kernel launcher. Images and samplers are accessed
462 via builtins that take void* as the reference. TODO: who and
463 how these arrays should be initialized? */
464 tree void_ptr = build_pointer_type (void_type_node);
465 return void_ptr;
466 }
467 default:
468 gcc_unreachable ();
469 break;
470 }
471 }
472
473 /* Drop const qualifiers. */
474 return tree_type;
475}