1 /* brig-util.cc -- gccbrig utility functions
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
6 This file is part of GCC.
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
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
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/>. */
25 #include "hsa-brig-format.h"
26 #include "brig-util.h"
28 #include "diagnostic-core.h"
29 #include "print-tree.h"
32 group_variable_offset_index::has_variable (const std::string
&name
) const
34 varname_offset_table::const_iterator i
= m_group_offsets
.find (name
);
35 return i
!= m_group_offsets
.end ();
38 /* Adds a new group segment variable. */
41 group_variable_offset_index::add (const std::string
&name
, size_t size
,
44 size_t align_padding
= m_next_group_offset
% alignment
== 0 ?
45 0 : (alignment
- m_next_group_offset
% alignment
);
46 m_next_group_offset
+= align_padding
;
47 m_group_offsets
[name
] = m_next_group_offset
;
48 m_next_group_offset
+= size
;
52 group_variable_offset_index::segment_offset (const std::string
&name
) const
54 varname_offset_table::const_iterator i
= m_group_offsets
.find (name
);
55 gcc_assert (i
!= m_group_offsets
.end ());
59 /* Return true if operand number OPNUM of instruction with OPCODE is an output.
60 False if it is an input. Some code reused from Martin Jambor's gcc-hsa
64 gccbrig_hsa_opcode_op_output_p (BrigOpcode16_t opcode
, int opnum
)
72 case BRIG_OPCODE_ATOMICNORET
:
73 case BRIG_OPCODE_SIGNALNORET
:
74 case BRIG_OPCODE_INITFBAR
:
75 case BRIG_OPCODE_JOINFBAR
:
76 case BRIG_OPCODE_WAITFBAR
:
77 case BRIG_OPCODE_ARRIVEFBAR
:
78 case BRIG_OPCODE_LEAVEFBAR
:
79 case BRIG_OPCODE_RELEASEFBAR
:
80 case BRIG_OPCODE_DEBUGTRAP
:
88 gccbrig_hsa_type_bit_size (BrigType16_t t
)
91 unsigned pack_type
= t
& ~BRIG_TYPE_BASE_MASK
;
93 if (pack_type
== BRIG_TYPE_PACK_32
)
95 else if (pack_type
== BRIG_TYPE_PACK_64
)
97 else if (pack_type
== BRIG_TYPE_PACK_128
)
124 case BRIG_TYPE_U16X2
:
126 case BRIG_TYPE_S16X2
:
127 case BRIG_TYPE_F16X2
:
128 case BRIG_TYPE_SIG32
:
136 case BRIG_TYPE_U16X4
:
137 case BRIG_TYPE_U32X2
:
139 case BRIG_TYPE_S16X4
:
140 case BRIG_TYPE_S32X2
:
141 case BRIG_TYPE_F16X4
:
142 case BRIG_TYPE_F32X2
:
143 case BRIG_TYPE_SIG64
:
147 case BRIG_TYPE_U8X16
:
148 case BRIG_TYPE_U16X8
:
149 case BRIG_TYPE_U32X4
:
150 case BRIG_TYPE_U64X2
:
151 case BRIG_TYPE_S8X16
:
152 case BRIG_TYPE_S16X8
:
153 case BRIG_TYPE_S32X4
:
154 case BRIG_TYPE_S64X2
:
155 case BRIG_TYPE_F16X8
:
156 case BRIG_TYPE_F32X4
:
157 case BRIG_TYPE_F64X2
:
161 printf ("HMM %d %x\n", t
, t
);
166 /* gcc-hsa borrowed code ENDS. */
169 gccbrig_to_uint64_t (const BrigUInt64
&brig_type
)
171 return (uint64_t (brig_type
.hi
) << 32) | uint64_t (brig_type
.lo
);
175 gccbrig_reg_size (const BrigOperandRegister
*brig_reg
)
177 switch (brig_reg
->regKind
)
179 case BRIG_REGISTER_KIND_CONTROL
:
181 case BRIG_REGISTER_KIND_SINGLE
:
183 case BRIG_REGISTER_KIND_DOUBLE
:
185 case BRIG_REGISTER_KIND_QUAD
:
194 gccbrig_reg_name (const BrigOperandRegister
*reg
)
196 std::ostringstream strstr
;
197 switch (reg
->regKind
)
199 case BRIG_REGISTER_KIND_CONTROL
:
202 case BRIG_REGISTER_KIND_SINGLE
:
205 case BRIG_REGISTER_KIND_DOUBLE
:
208 case BRIG_REGISTER_KIND_QUAD
:
215 strstr
<< reg
->regNum
;
216 return strstr
.str ();
220 gccbrig_type_name (BrigType16_t type
)
247 gccbrig_segment_name (BrigSegment8_t segment
)
249 if (segment
== BRIG_SEGMENT_GLOBAL
)
251 else if (segment
== BRIG_SEGMENT_GROUP
)
253 else if (segment
== BRIG_SEGMENT_PRIVATE
)
260 gccbrig_is_float_type (BrigType16_t type
)
262 return (type
== BRIG_TYPE_F32
|| type
== BRIG_TYPE_F64
263 || type
== BRIG_TYPE_F16
);
267 gccbrig_tree_type_to_hsa_type (tree tree_type
)
269 if (INTEGRAL_TYPE_P (tree_type
))
271 if (TYPE_UNSIGNED (tree_type
))
273 switch (int_size_in_bytes (tree_type
))
278 return BRIG_TYPE_U16
;
280 return BRIG_TYPE_U32
;
282 return BRIG_TYPE_U64
;
289 switch (int_size_in_bytes (tree_type
))
294 return BRIG_TYPE_S16
;
296 return BRIG_TYPE_S32
;
298 return BRIG_TYPE_S64
;
304 else if (VECTOR_TYPE_P (tree_type
))
306 tree element_type
= TREE_TYPE (tree_type
);
307 size_t element_size
= int_size_in_bytes (element_type
) * 8;
308 BrigType16_t brig_element_type
;
309 switch (element_size
)
313 = TYPE_UNSIGNED (element_type
) ? BRIG_TYPE_U8
: BRIG_TYPE_S8
;
317 = TYPE_UNSIGNED (element_type
) ? BRIG_TYPE_U16
: BRIG_TYPE_S16
;
321 = TYPE_UNSIGNED (element_type
) ? BRIG_TYPE_U32
: BRIG_TYPE_S32
;
325 = TYPE_UNSIGNED (element_type
) ? BRIG_TYPE_U64
: BRIG_TYPE_S64
;
331 BrigType16_t pack_type
;
332 switch (int_size_in_bytes (tree_type
) * 8)
335 pack_type
= BRIG_TYPE_PACK_32
;
338 pack_type
= BRIG_TYPE_PACK_64
;
341 pack_type
= BRIG_TYPE_PACK_128
;
346 return brig_element_type
| pack_type
;
351 /* Returns true in case the operation is a "bit level" operation,
352 that is, not having operand type depending semantical differences. */
355 gccbrig_is_bit_operation (BrigOpcode16_t opcode
)
357 return opcode
== BRIG_OPCODE_CMOV
|| opcode
== BRIG_OPCODE_SHUFFLE
358 || opcode
== BRIG_OPCODE_UNPACK
|| opcode
== BRIG_OPCODE_UNPACKLO
359 || opcode
== BRIG_OPCODE_UNPACKHI
|| opcode
== BRIG_OPCODE_ST
360 || opcode
== BRIG_OPCODE_PACK
;
363 /* The program scope definition can be left external within the
364 kernel binary which means it must be defined by the host via
365 HSA runtime. For these we have special treatment:
366 Create additional pointer indirection when accessing the variable
367 value from kernel code through a generated pointer
368 __gccbrig_ptr_variable_name. The pointer value then can be set either
369 within the kernel binary (in case of a later linked in definition)
373 gccbrig_might_be_host_defined_var_p (const BrigDirectiveVariable
*brigVar
)
375 bool is_definition
= brigVar
->modifier
& BRIG_VARIABLE_DEFINITION
;
376 return (brigVar
->segment
== BRIG_SEGMENT_GLOBAL
377 || brigVar
->segment
== BRIG_SEGMENT_READONLY
) && !is_definition
378 && brigVar
->linkage
== BRIG_LINKAGE_PROGRAM
379 && (brigVar
->allocation
== BRIG_ALLOCATION_PROGRAM
380 || brigVar
->allocation
== BRIG_ALLOCATION_AGENT
);
383 /* Produce a GENERIC type for the given HSA/BRIG type. Returns the element
384 type in case of vector instructions. */
387 gccbrig_tree_type_for_hsa_type (BrigType16_t brig_type
)
389 tree tree_type
= NULL_TREE
;
391 if (hsa_type_packed_p (brig_type
))
393 /* The element type is encoded in the bottom 5 bits. */
394 BrigType16_t inner_brig_type
= brig_type
& BRIG_TYPE_BASE_MASK
;
396 unsigned full_size
= gccbrig_hsa_type_bit_size (brig_type
);
398 if (inner_brig_type
== BRIG_TYPE_F16
)
399 return build_vector_type (gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16
),
402 tree inner_type
= gccbrig_tree_type_for_hsa_type (inner_brig_type
);
404 unsigned inner_size
= gccbrig_hsa_type_bit_size (inner_brig_type
);
405 unsigned nunits
= full_size
/ inner_size
;
406 tree_type
= build_vector_type (inner_type
, nunits
);
413 tree_type
= void_type_node
;
416 tree_type
= boolean_type_node
;
422 /* Ensure a fixed width integer. */
424 = build_nonstandard_integer_type
425 (gccbrig_hsa_type_bit_size (brig_type
), false);
428 return unsigned_char_type_node
;
432 case BRIG_TYPE_B8
: /* Handle bit vectors as unsigned ints. */
437 case BRIG_TYPE_SIG32
: /* Handle signals as integers for now. */
438 case BRIG_TYPE_SIG64
:
439 tree_type
= build_nonstandard_integer_type
440 (gccbrig_hsa_type_bit_size (brig_type
), true);
443 tree_type
= uint16_type_node
;
446 /* TODO: make sure that the alignment of the float are at least as
447 strict than mandated by HSA, and conform to IEEE (like mandated
449 tree_type
= float_type_node
;
452 tree_type
= double_type_node
;
455 case BRIG_TYPE_ROIMG
:
456 case BRIG_TYPE_WOIMG
:
457 case BRIG_TYPE_RWIMG
:
459 /* Handle images and samplers as target-specific blobs of data
460 that should be allocated earlier on from the runtime side.
461 Create a void* that should be initialized to point to the blobs
462 by the kernel launcher. Images and samplers are accessed
463 via builtins that take void* as the reference. TODO: who and
464 how these arrays should be initialized? */
465 tree void_ptr
= build_pointer_type (void_type_node
);
474 /* Drop const qualifiers. */
478 /* Calculates numeric identifier for the HSA register REG.
480 Returned value is bound to [0, BRIG_2_TREE_HSAIL_TOTAL_REG_COUNT]. */
483 gccbrig_hsa_reg_id (const BrigOperandRegister
®
)
485 size_t offset
= reg
.regNum
;
488 case BRIG_REGISTER_KIND_QUAD
:
490 += BRIG_2_TREE_HSAIL_D_REG_COUNT
+ BRIG_2_TREE_HSAIL_S_REG_COUNT
491 + BRIG_2_TREE_HSAIL_C_REG_COUNT
;
493 case BRIG_REGISTER_KIND_DOUBLE
:
494 offset
+= BRIG_2_TREE_HSAIL_S_REG_COUNT
+ BRIG_2_TREE_HSAIL_C_REG_COUNT
;
496 case BRIG_REGISTER_KIND_SINGLE
:
497 offset
+= BRIG_2_TREE_HSAIL_C_REG_COUNT
;
498 case BRIG_REGISTER_KIND_CONTROL
:
508 gccbrig_hsa_reg_name_from_id (size_t reg_id
)
511 long unsigned int reg_hash
= (long unsigned int) reg_id
;
512 if (reg_hash
< BRIG_2_TREE_HSAIL_C_REG_COUNT
)
514 sprintf (reg_name
, "$c%lu", reg_hash
);
518 reg_hash
-= BRIG_2_TREE_HSAIL_C_REG_COUNT
;
519 if (reg_hash
< BRIG_2_TREE_HSAIL_S_REG_COUNT
)
521 sprintf (reg_name
, "$s%lu", reg_hash
);
525 reg_hash
-= BRIG_2_TREE_HSAIL_S_REG_COUNT
;
526 if (reg_hash
< BRIG_2_TREE_HSAIL_D_REG_COUNT
)
528 sprintf (reg_name
, "$d%lu", reg_hash
);
532 reg_hash
-= BRIG_2_TREE_HSAIL_D_REG_COUNT
;
533 if (reg_hash
< BRIG_2_TREE_HSAIL_Q_REG_COUNT
)
535 sprintf (reg_name
, "$q%lu", reg_hash
);
543 /* Prints statistics of register usage to stdout. */
546 gccbrig_print_reg_use_info (FILE *dump
, const regs_use_index
&info
)
548 regs_use_index::const_iterator begin_it
= info
.begin ();
549 regs_use_index::const_iterator end_it
= info
.end ();
550 for (regs_use_index::const_iterator it
= begin_it
; it
!= end_it
; it
++)
552 std::string hsa_reg
= gccbrig_hsa_reg_name_from_id (it
->first
);
553 printf ("%s:\n", hsa_reg
.c_str ());
554 const reg_use_info
&info
= it
->second
;
555 typedef std::vector
<std::pair
<tree
, size_t> >::const_iterator reg_use_it
;
556 reg_use_it begin_it2
= info
.m_type_refs
.begin ();
557 reg_use_it end_it2
= info
.m_type_refs
.end ();
558 for (reg_use_it it2
= begin_it2
; it2
!= end_it2
; it2
++)
560 fprintf (dump
, "(%lu) ", (long unsigned int) it2
->second
);
561 print_node_brief (dump
, "", it2
->first
, 0);
562 fprintf (dump
, "\n");