annotate gcc/brig/brigfrontend/brig-to-generic.cc @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* brig2tree.cc -- brig to gcc generic/gimple tree conversion
kono
parents:
diff changeset
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
kono
parents:
diff changeset
4 for General Processor Tech.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 #include <cassert>
kono
parents:
diff changeset
23 #include <iostream>
kono
parents:
diff changeset
24 #include <iomanip>
kono
parents:
diff changeset
25 #include <sstream>
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 #include "config.h"
kono
parents:
diff changeset
28 #include "system.h"
kono
parents:
diff changeset
29 #include "coretypes.h"
kono
parents:
diff changeset
30 #include "target.h"
kono
parents:
diff changeset
31 #include "function.h"
kono
parents:
diff changeset
32 #include "brig-to-generic.h"
kono
parents:
diff changeset
33 #include "stringpool.h"
kono
parents:
diff changeset
34 #include "tree-iterator.h"
kono
parents:
diff changeset
35 #include "toplev.h"
kono
parents:
diff changeset
36 #include "gimplify.h"
kono
parents:
diff changeset
37 #include "gimple-expr.h"
kono
parents:
diff changeset
38 #include "print-tree.h"
kono
parents:
diff changeset
39 #include "hsa-brig-format.h"
kono
parents:
diff changeset
40 #include "stor-layout.h"
kono
parents:
diff changeset
41 #include "diagnostic-core.h"
kono
parents:
diff changeset
42 #include "brig-code-entry-handler.h"
kono
parents:
diff changeset
43 #include "brig-machine.h"
kono
parents:
diff changeset
44 #include "brig-util.h"
kono
parents:
diff changeset
45 #include "phsa.h"
kono
parents:
diff changeset
46 #include "tree-pretty-print.h"
kono
parents:
diff changeset
47 #include "dumpfile.h"
kono
parents:
diff changeset
48 #include "profile-count.h"
kono
parents:
diff changeset
49 #include "tree-cfg.h"
kono
parents:
diff changeset
50 #include "errors.h"
kono
parents:
diff changeset
51 #include "fold-const.h"
kono
parents:
diff changeset
52 #include "cgraph.h"
kono
parents:
diff changeset
53 #include "dumpfile.h"
kono
parents:
diff changeset
54 #include "tree-pretty-print.h"
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 extern int gccbrig_verbose;
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 tree brig_to_generic::s_fp16_type;
kono
parents:
diff changeset
59 tree brig_to_generic::s_fp32_type;
kono
parents:
diff changeset
60 tree brig_to_generic::s_fp64_type;
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 brig_to_generic::brig_to_generic ()
kono
parents:
diff changeset
63 : m_cf (NULL), m_analyzing (true), m_total_group_segment_usage (0),
kono
parents:
diff changeset
64 m_brig (NULL), m_next_private_offset (0)
kono
parents:
diff changeset
65 {
kono
parents:
diff changeset
66 m_globals = NULL_TREE;
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 /* Initialize the basic REAL types.
kono
parents:
diff changeset
69 This doesn't work straight away because most of the targets
kono
parents:
diff changeset
70 do not support fp16 natively. Let's by default convert
kono
parents:
diff changeset
71 to fp32 and back before and after each instruction (handle it as
kono
parents:
diff changeset
72 a storage format only), and later add an optimization pass
kono
parents:
diff changeset
73 that removes the extra converts (in case of multiple fp16 ops
kono
parents:
diff changeset
74 in a row). */
kono
parents:
diff changeset
75 s_fp16_type = make_node (REAL_TYPE);
kono
parents:
diff changeset
76 TYPE_PRECISION (s_fp16_type) = 16;
kono
parents:
diff changeset
77 TYPE_SIZE (s_fp16_type) = bitsize_int (16);
kono
parents:
diff changeset
78 TYPE_SIZE_UNIT (s_fp16_type) = size_int (2);
kono
parents:
diff changeset
79 SET_TYPE_ALIGN (s_fp16_type, 16);
kono
parents:
diff changeset
80 layout_type (s_fp16_type);
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 s_fp32_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_F32);
kono
parents:
diff changeset
83 s_fp64_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_F64);
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 /* TODO: (machine)query the preferred rounding mode that is set by
kono
parents:
diff changeset
86 the machine by default. This can be redefined by each BRIG module
kono
parents:
diff changeset
87 header. */
kono
parents:
diff changeset
88 m_default_float_rounding_mode = BRIG_ROUND_FLOAT_ZERO;
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 m_dump_file = dump_begin (TDI_original, &m_dump_flags);
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 class unimplemented_entry_handler : public brig_code_entry_handler
kono
parents:
diff changeset
94 {
kono
parents:
diff changeset
95 public:
kono
parents:
diff changeset
96 unimplemented_entry_handler (brig_to_generic &parent)
kono
parents:
diff changeset
97 : brig_code_entry_handler (parent)
kono
parents:
diff changeset
98 {
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 size_t
kono
parents:
diff changeset
102 operator () (const BrigBase *base)
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 gcc_unreachable ();
kono
parents:
diff changeset
105 return base->byteCount;
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107 };
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 /* Handler for entries that can be (and are) safely skipped for the purposes
kono
parents:
diff changeset
110 of GENERIC generation. */
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 class skipped_entry_handler : public brig_code_entry_handler
kono
parents:
diff changeset
113 {
kono
parents:
diff changeset
114 public:
kono
parents:
diff changeset
115 skipped_entry_handler (brig_to_generic &parent)
kono
parents:
diff changeset
116 : brig_code_entry_handler (parent)
kono
parents:
diff changeset
117 {
kono
parents:
diff changeset
118 }
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 size_t
kono
parents:
diff changeset
121 operator () (const BrigBase *base)
kono
parents:
diff changeset
122 {
kono
parents:
diff changeset
123 return base->byteCount;
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125 };
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 /* Helper struct for pairing a BrigKind and a BrigCodeEntryHandler that
kono
parents:
diff changeset
128 should handle its data. */
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 struct code_entry_handler_info
kono
parents:
diff changeset
131 {
kono
parents:
diff changeset
132 BrigKind kind;
kono
parents:
diff changeset
133 brig_code_entry_handler *handler;
kono
parents:
diff changeset
134 };
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 /* Finds the BRIG file sections in the currently processed file. */
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 void
kono
parents:
diff changeset
140 brig_to_generic::find_brig_sections ()
kono
parents:
diff changeset
141 {
kono
parents:
diff changeset
142 m_data = m_code = m_operand = NULL;
kono
parents:
diff changeset
143 const BrigModuleHeader *mheader = (const BrigModuleHeader *) m_brig;
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 /* Find the positions of the different sections. */
kono
parents:
diff changeset
146 for (uint32_t sec = 0; sec < mheader->sectionCount; ++sec)
kono
parents:
diff changeset
147 {
kono
parents:
diff changeset
148 uint64_t offset
kono
parents:
diff changeset
149 = ((const uint64_t *) (m_brig + mheader->sectionIndex))[sec];
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 const BrigSectionHeader *section_header
kono
parents:
diff changeset
152 = (const BrigSectionHeader *) (m_brig + offset);
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 std::string name ((const char *) (&section_header->name),
kono
parents:
diff changeset
155 section_header->nameLength);
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 if (sec == BRIG_SECTION_INDEX_DATA && name == "hsa_data")
kono
parents:
diff changeset
158 {
kono
parents:
diff changeset
159 m_data = (const char *) section_header;
kono
parents:
diff changeset
160 m_data_size = section_header->byteCount;
kono
parents:
diff changeset
161 }
kono
parents:
diff changeset
162 else if (sec == BRIG_SECTION_INDEX_CODE && name == "hsa_code")
kono
parents:
diff changeset
163 {
kono
parents:
diff changeset
164 m_code = (const char *) section_header;
kono
parents:
diff changeset
165 m_code_size = section_header->byteCount;
kono
parents:
diff changeset
166 }
kono
parents:
diff changeset
167 else if (sec == BRIG_SECTION_INDEX_OPERAND && name == "hsa_operand")
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 m_operand = (const char *) section_header;
kono
parents:
diff changeset
170 m_operand_size = section_header->byteCount;
kono
parents:
diff changeset
171 }
kono
parents:
diff changeset
172 else
kono
parents:
diff changeset
173 {
kono
parents:
diff changeset
174 gcc_unreachable ();
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176 }
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 if (m_code == NULL)
kono
parents:
diff changeset
179 gcc_unreachable ();
kono
parents:
diff changeset
180 if (m_data == NULL)
kono
parents:
diff changeset
181 gcc_unreachable ();
kono
parents:
diff changeset
182 if (m_operand == NULL)
kono
parents:
diff changeset
183 gcc_unreachable ();
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 }
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 /* Does a first pass over the given BRIG to collect data needed for the
kono
parents:
diff changeset
188 actual parsing. Currently this includes only collecting the
kono
parents:
diff changeset
189 group segment variable usage to support the experimental HSA PRM feature
kono
parents:
diff changeset
190 where group variables can be declared also in module and function scope
kono
parents:
diff changeset
191 (in addition to kernel scope).
kono
parents:
diff changeset
192 */
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 void
kono
parents:
diff changeset
195 brig_to_generic::analyze (const char *brig_blob)
kono
parents:
diff changeset
196 {
kono
parents:
diff changeset
197 const BrigModuleHeader *mheader = (const BrigModuleHeader *) brig_blob;
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 if (strncmp (mheader->identification, "HSA BRIG", 8) != 0)
kono
parents:
diff changeset
200 fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
kono
parents:
diff changeset
201 "Unrecognized file format.");
kono
parents:
diff changeset
202 if (mheader->brigMajor != 1 || mheader->brigMinor != 0)
kono
parents:
diff changeset
203 fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
kono
parents:
diff changeset
204 "BRIG version not supported. BRIG 1.0 required.");
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 m_brig = brig_blob;
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 find_brig_sections ();
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 brig_directive_variable_handler var_handler (*this);
kono
parents:
diff changeset
211 brig_directive_fbarrier_handler fbar_handler (*this);
kono
parents:
diff changeset
212 brig_directive_function_handler func_handler (*this);
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 /* Need this for grabbing the module names for mangling the
kono
parents:
diff changeset
215 group variable names. */
kono
parents:
diff changeset
216 brig_directive_module_handler module_handler (*this);
kono
parents:
diff changeset
217 skipped_entry_handler skipped_handler (*this);
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code;
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 code_entry_handler_info handlers[]
kono
parents:
diff changeset
222 = {{BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler},
kono
parents:
diff changeset
223 {BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler},
kono
parents:
diff changeset
224 {BRIG_KIND_DIRECTIVE_KERNEL, &func_handler},
kono
parents:
diff changeset
225 {BRIG_KIND_DIRECTIVE_MODULE, &module_handler},
kono
parents:
diff changeset
226 {BRIG_KIND_DIRECTIVE_FUNCTION, &func_handler}};
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 m_analyzing = true;
kono
parents:
diff changeset
229 for (size_t b = csection_header->headerByteCount; b < m_code_size;)
kono
parents:
diff changeset
230 {
kono
parents:
diff changeset
231 const BrigBase *entry = (const BrigBase *) (m_code + b);
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 brig_code_entry_handler *handler = &skipped_handler;
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 if (m_cf != NULL && b >= m_cf->m_brig_def->nextModuleEntry)
kono
parents:
diff changeset
236 {
kono
parents:
diff changeset
237 /* The function definition ended. We can just discard the place
kono
parents:
diff changeset
238 holder function. */
kono
parents:
diff changeset
239 m_total_group_segment_usage += m_cf->m_local_group_variables.size ();
kono
parents:
diff changeset
240 delete m_cf;
kono
parents:
diff changeset
241 m_cf = NULL;
kono
parents:
diff changeset
242 }
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 /* Find a handler. */
kono
parents:
diff changeset
245 for (size_t i = 0;
kono
parents:
diff changeset
246 i < sizeof (handlers) / sizeof (code_entry_handler_info); ++i)
kono
parents:
diff changeset
247 {
kono
parents:
diff changeset
248 if (handlers[i].kind == entry->kind)
kono
parents:
diff changeset
249 handler = handlers[i].handler;
kono
parents:
diff changeset
250 }
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 int bytes_processed = (*handler) (entry);
kono
parents:
diff changeset
253 if (bytes_processed == 0)
kono
parents:
diff changeset
254 fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_CORRUPTED_MODULE
kono
parents:
diff changeset
255 "Element with 0 bytes.");
kono
parents:
diff changeset
256 b += bytes_processed;
kono
parents:
diff changeset
257 }
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 if (m_cf != NULL)
kono
parents:
diff changeset
260 {
kono
parents:
diff changeset
261 m_total_group_segment_usage += m_cf->m_local_group_variables.size ();
kono
parents:
diff changeset
262 delete m_cf;
kono
parents:
diff changeset
263 m_cf = NULL;
kono
parents:
diff changeset
264 }
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 m_total_group_segment_usage += m_module_group_variables.size ();
kono
parents:
diff changeset
267 m_analyzing = false;
kono
parents:
diff changeset
268 }
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 /* Parses the given BRIG blob. */
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 void
kono
parents:
diff changeset
273 brig_to_generic::parse (const char *brig_blob)
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 m_brig = brig_blob;
kono
parents:
diff changeset
276 find_brig_sections ();
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 brig_basic_inst_handler inst_handler (*this);
kono
parents:
diff changeset
279 brig_branch_inst_handler branch_inst_handler (*this);
kono
parents:
diff changeset
280 brig_cvt_inst_handler cvt_inst_handler (*this);
kono
parents:
diff changeset
281 brig_seg_inst_handler seg_inst_handler (*this);
kono
parents:
diff changeset
282 brig_copy_move_inst_handler copy_move_inst_handler (*this);
kono
parents:
diff changeset
283 brig_signal_inst_handler signal_inst_handler (*this);
kono
parents:
diff changeset
284 brig_atomic_inst_handler atomic_inst_handler (*this);
kono
parents:
diff changeset
285 brig_cmp_inst_handler cmp_inst_handler (*this);
kono
parents:
diff changeset
286 brig_mem_inst_handler mem_inst_handler (*this);
kono
parents:
diff changeset
287 brig_inst_mod_handler inst_mod_handler (*this);
kono
parents:
diff changeset
288 brig_directive_label_handler label_handler (*this);
kono
parents:
diff changeset
289 brig_directive_variable_handler var_handler (*this);
kono
parents:
diff changeset
290 brig_directive_fbarrier_handler fbar_handler (*this);
kono
parents:
diff changeset
291 brig_directive_comment_handler comment_handler (*this);
kono
parents:
diff changeset
292 brig_directive_function_handler func_handler (*this);
kono
parents:
diff changeset
293 brig_directive_control_handler control_handler (*this);
kono
parents:
diff changeset
294 brig_directive_arg_block_handler arg_block_handler (*this);
kono
parents:
diff changeset
295 brig_directive_module_handler module_handler (*this);
kono
parents:
diff changeset
296 brig_lane_inst_handler lane_inst_handler (*this);
kono
parents:
diff changeset
297 brig_queue_inst_handler queue_inst_handler (*this);
kono
parents:
diff changeset
298 skipped_entry_handler skipped_handler (*this);
kono
parents:
diff changeset
299 unimplemented_entry_handler unimplemented_handler (*this);
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 struct code_entry_handler_info
kono
parents:
diff changeset
302 {
kono
parents:
diff changeset
303 BrigKind kind;
kono
parents:
diff changeset
304 brig_code_entry_handler *handler;
kono
parents:
diff changeset
305 };
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 /* TODO: Convert to a hash table / map. For now, put the more common
kono
parents:
diff changeset
308 entries to the top to keep the scan fast on average. */
kono
parents:
diff changeset
309 code_entry_handler_info handlers[]
kono
parents:
diff changeset
310 = {{BRIG_KIND_INST_BASIC, &inst_handler},
kono
parents:
diff changeset
311 {BRIG_KIND_INST_CMP, &cmp_inst_handler},
kono
parents:
diff changeset
312 {BRIG_KIND_INST_MEM, &mem_inst_handler},
kono
parents:
diff changeset
313 {BRIG_KIND_INST_MOD, &inst_mod_handler},
kono
parents:
diff changeset
314 {BRIG_KIND_INST_CVT, &cvt_inst_handler},
kono
parents:
diff changeset
315 {BRIG_KIND_INST_SEG_CVT, &seg_inst_handler},
kono
parents:
diff changeset
316 {BRIG_KIND_INST_SEG, &seg_inst_handler},
kono
parents:
diff changeset
317 {BRIG_KIND_INST_ADDR, &copy_move_inst_handler},
kono
parents:
diff changeset
318 {BRIG_KIND_INST_SOURCE_TYPE, &copy_move_inst_handler},
kono
parents:
diff changeset
319 {BRIG_KIND_INST_ATOMIC, &atomic_inst_handler},
kono
parents:
diff changeset
320 {BRIG_KIND_INST_SIGNAL, &signal_inst_handler},
kono
parents:
diff changeset
321 {BRIG_KIND_INST_BR, &branch_inst_handler},
kono
parents:
diff changeset
322 {BRIG_KIND_INST_LANE, &lane_inst_handler},
kono
parents:
diff changeset
323 {BRIG_KIND_INST_QUEUE, &queue_inst_handler},
kono
parents:
diff changeset
324 /* Assuming fences are not needed. FIXME: call builtins
kono
parents:
diff changeset
325 when porting to a platform where they are. */
kono
parents:
diff changeset
326 {BRIG_KIND_INST_MEM_FENCE, &skipped_handler},
kono
parents:
diff changeset
327 {BRIG_KIND_DIRECTIVE_LABEL, &label_handler},
kono
parents:
diff changeset
328 {BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler},
kono
parents:
diff changeset
329 {BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, &arg_block_handler},
kono
parents:
diff changeset
330 {BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, &arg_block_handler},
kono
parents:
diff changeset
331 {BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler},
kono
parents:
diff changeset
332 {BRIG_KIND_DIRECTIVE_COMMENT, &comment_handler},
kono
parents:
diff changeset
333 {BRIG_KIND_DIRECTIVE_KERNEL, &func_handler},
kono
parents:
diff changeset
334 {BRIG_KIND_DIRECTIVE_SIGNATURE, &func_handler},
kono
parents:
diff changeset
335 {BRIG_KIND_DIRECTIVE_FUNCTION, &func_handler},
kono
parents:
diff changeset
336 {BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION, &func_handler},
kono
parents:
diff changeset
337 {BRIG_KIND_DIRECTIVE_MODULE, &module_handler},
kono
parents:
diff changeset
338 /* Skipping debug locations for now as not needed for conformance. */
kono
parents:
diff changeset
339 {BRIG_KIND_DIRECTIVE_LOC, &skipped_handler},
kono
parents:
diff changeset
340 /* There are no supported pragmas at this moment. */
kono
parents:
diff changeset
341 {BRIG_KIND_DIRECTIVE_PRAGMA, &skipped_handler},
kono
parents:
diff changeset
342 {BRIG_KIND_DIRECTIVE_CONTROL, &control_handler},
kono
parents:
diff changeset
343 {BRIG_KIND_DIRECTIVE_EXTENSION, &skipped_handler},
kono
parents:
diff changeset
344 /* BRIG_KIND_NONE entries are valid anywhere. They can be used
kono
parents:
diff changeset
345 for patching BRIGs before finalization. */
kono
parents:
diff changeset
346 {BRIG_KIND_NONE, &skipped_handler}};
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code;
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 for (size_t b = csection_header->headerByteCount; b < m_code_size;)
kono
parents:
diff changeset
351 {
kono
parents:
diff changeset
352 const BrigBase *entry = (const BrigBase *) (m_code + b);
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 brig_code_entry_handler *handler = &unimplemented_handler;
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 if (m_cf != NULL && b >= m_cf->m_brig_def->nextModuleEntry)
kono
parents:
diff changeset
357 finish_function (); /* The function definition ended. */
kono
parents:
diff changeset
358
kono
parents:
diff changeset
359 /* Find a handler. */
kono
parents:
diff changeset
360 for (size_t i = 0;
kono
parents:
diff changeset
361 i < sizeof (handlers) / sizeof (code_entry_handler_info); ++i)
kono
parents:
diff changeset
362 {
kono
parents:
diff changeset
363 if (handlers[i].kind == entry->kind)
kono
parents:
diff changeset
364 handler = handlers[i].handler;
kono
parents:
diff changeset
365 }
kono
parents:
diff changeset
366 b += (*handler) (entry);
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 finish_function ();
kono
parents:
diff changeset
370 }
kono
parents:
diff changeset
371
kono
parents:
diff changeset
372 const BrigData *
kono
parents:
diff changeset
373 brig_to_generic::get_brig_data_entry (size_t entry_offset) const
kono
parents:
diff changeset
374 {
kono
parents:
diff changeset
375 return (const BrigData *) (m_data + entry_offset);
kono
parents:
diff changeset
376 }
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 const BrigBase *
kono
parents:
diff changeset
379 brig_to_generic::get_brig_operand_entry (size_t entry_offset) const
kono
parents:
diff changeset
380 {
kono
parents:
diff changeset
381 return (const BrigBase *) (m_operand + entry_offset);
kono
parents:
diff changeset
382 }
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384 const BrigBase *
kono
parents:
diff changeset
385 brig_to_generic::get_brig_code_entry (size_t entry_offset) const
kono
parents:
diff changeset
386 {
kono
parents:
diff changeset
387 return (const BrigBase *) (m_code + entry_offset);
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 void
kono
parents:
diff changeset
391 brig_to_generic::append_global (tree g)
kono
parents:
diff changeset
392 {
kono
parents:
diff changeset
393 if (m_globals == NULL_TREE)
kono
parents:
diff changeset
394 {
kono
parents:
diff changeset
395 m_globals = g;
kono
parents:
diff changeset
396 return;
kono
parents:
diff changeset
397 }
kono
parents:
diff changeset
398 else
kono
parents:
diff changeset
399 {
kono
parents:
diff changeset
400 tree last = tree_last (m_globals);
kono
parents:
diff changeset
401 TREE_CHAIN (last) = g;
kono
parents:
diff changeset
402 }
kono
parents:
diff changeset
403 }
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 tree
kono
parents:
diff changeset
406 brig_to_generic::global_variable (const std::string &name) const
kono
parents:
diff changeset
407 {
kono
parents:
diff changeset
408 label_index::const_iterator i = m_global_variables.find (name);
kono
parents:
diff changeset
409 if (i == m_global_variables.end ())
kono
parents:
diff changeset
410 return NULL_TREE;
kono
parents:
diff changeset
411 else
kono
parents:
diff changeset
412 return (*i).second;
kono
parents:
diff changeset
413 }
kono
parents:
diff changeset
414
kono
parents:
diff changeset
415 /* Returns a function declaration with the given name. Assumes it has been
kono
parents:
diff changeset
416 created previously via a DirectiveFunction or similar. */
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 tree
kono
parents:
diff changeset
419 brig_to_generic::function_decl (const std::string &name)
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 label_index::const_iterator i = m_function_index.find (name);
kono
parents:
diff changeset
422 if (i == m_function_index.end ())
kono
parents:
diff changeset
423 return NULL_TREE;
kono
parents:
diff changeset
424 return (*i).second;
kono
parents:
diff changeset
425 }
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 void
kono
parents:
diff changeset
428 brig_to_generic::add_function_decl (const std::string &name, tree func_decl)
kono
parents:
diff changeset
429 {
kono
parents:
diff changeset
430 m_function_index[name] = func_decl;
kono
parents:
diff changeset
431 }
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 /* Adds a GENERIC global variable VAR_DECL with the given NAME to the
kono
parents:
diff changeset
434 current module. If we have generated a host def var ptr (a place holder
kono
parents:
diff changeset
435 for variables that are defined by the HSA host code) for this global
kono
parents:
diff changeset
436 variable definition (because there was a declaration earlier which looked
kono
parents:
diff changeset
437 like it might have been a host defined variable), we now have
kono
parents:
diff changeset
438 to assign its address and make it private to allow the references to
kono
parents:
diff changeset
439 point to the defined variable instead. */
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 void
kono
parents:
diff changeset
442 brig_to_generic::add_global_variable (const std::string &name, tree var_decl)
kono
parents:
diff changeset
443 {
kono
parents:
diff changeset
444 append_global (var_decl);
kono
parents:
diff changeset
445 m_global_variables[name] = var_decl;
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 std::string host_def_var_name
kono
parents:
diff changeset
448 = std::string (PHSA_HOST_DEF_PTR_PREFIX) + name;
kono
parents:
diff changeset
449 tree host_def_var = global_variable (host_def_var_name);
kono
parents:
diff changeset
450 if (host_def_var == NULL_TREE)
kono
parents:
diff changeset
451 return;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 tree ptype = build_pointer_type (TREE_TYPE (var_decl));
kono
parents:
diff changeset
454 tree var_addr = build1 (ADDR_EXPR, ptype, var_decl);
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 DECL_INITIAL (host_def_var) = var_addr;
kono
parents:
diff changeset
457 TREE_PUBLIC (host_def_var) = 0;
kono
parents:
diff changeset
458 }
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460 /* Adds an indirection pointer for a potential host-defined program scope
kono
parents:
diff changeset
461 variable declaration. */
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 void
kono
parents:
diff changeset
464 brig_to_generic::add_host_def_var_ptr (const std::string &name, tree var_decl)
kono
parents:
diff changeset
465 {
kono
parents:
diff changeset
466 std::string var_name = std::string (PHSA_HOST_DEF_PTR_PREFIX) + name;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 tree name_identifier = get_identifier (var_name.c_str ());
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 tree ptr_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, name_identifier,
kono
parents:
diff changeset
471 build_pointer_type (TREE_TYPE (var_decl)));
kono
parents:
diff changeset
472 DECL_EXTERNAL (ptr_var) = 0;
kono
parents:
diff changeset
473 DECL_ARTIFICIAL (ptr_var) = 0;
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 TREE_PUBLIC (ptr_var) = 1;
kono
parents:
diff changeset
476 TREE_USED (ptr_var) = 1;
kono
parents:
diff changeset
477 TREE_ADDRESSABLE (ptr_var) = 1;
kono
parents:
diff changeset
478 TREE_STATIC (ptr_var) = 1;
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 append_global (ptr_var);
kono
parents:
diff changeset
481 m_global_variables[var_name] = ptr_var;
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 /* Produce a "mangled name" for the given brig function or kernel.
kono
parents:
diff changeset
485 The mangling is used to make unique global symbol name in case of
kono
parents:
diff changeset
486 module scope functions. Program scope functions are not mangled
kono
parents:
diff changeset
487 (except for dropping the leading &), which makes the functions
kono
parents:
diff changeset
488 directly visible for linking using the original function name. */
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 std::string
kono
parents:
diff changeset
491 brig_to_generic::get_mangled_name
kono
parents:
diff changeset
492 (const BrigDirectiveExecutable *func) const
kono
parents:
diff changeset
493 {
kono
parents:
diff changeset
494 /* Strip the leading &. */
kono
parents:
diff changeset
495 std::string func_name = get_string (func->name).substr (1);
kono
parents:
diff changeset
496 if (func->linkage == BRIG_LINKAGE_MODULE)
kono
parents:
diff changeset
497 {
kono
parents:
diff changeset
498 /* Mangle the module scope function names with the module name and
kono
parents:
diff changeset
499 make them public so they can be queried by the HSA runtime from
kono
parents:
diff changeset
500 the produced binary. Assume it's the currently processed function
kono
parents:
diff changeset
501 we are always referring to. */
kono
parents:
diff changeset
502 func_name = "gccbrig." + m_module_name + "." + func_name;
kono
parents:
diff changeset
503 }
kono
parents:
diff changeset
504 return func_name;
kono
parents:
diff changeset
505 }
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 std::string
kono
parents:
diff changeset
508 brig_to_generic::get_string (size_t entry_offset) const
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 const BrigData *data_item = get_brig_data_entry (entry_offset);
kono
parents:
diff changeset
511 return std::string ((const char *) &data_item->bytes, data_item->byteCount);
kono
parents:
diff changeset
512 }
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 /* Adapted from c-semantics.c. */
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 tree
kono
parents:
diff changeset
517 build_stmt (enum tree_code code, ...)
kono
parents:
diff changeset
518 {
kono
parents:
diff changeset
519 tree ret;
kono
parents:
diff changeset
520 int length, i;
kono
parents:
diff changeset
521 va_list p;
kono
parents:
diff changeset
522 bool side_effects;
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 /* This function cannot be used to construct variably-sized nodes. */
kono
parents:
diff changeset
525 gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 va_start (p, code);
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 ret = make_node (code);
kono
parents:
diff changeset
530 TREE_TYPE (ret) = void_type_node;
kono
parents:
diff changeset
531 length = TREE_CODE_LENGTH (code);
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 /* TREE_SIDE_EFFECTS will already be set for statements with
kono
parents:
diff changeset
534 implicit side effects. Here we make sure it is set for other
kono
parents:
diff changeset
535 expressions by checking whether the parameters have side
kono
parents:
diff changeset
536 effects. */
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 side_effects = false;
kono
parents:
diff changeset
539 for (i = 0; i < length; i++)
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 tree t = va_arg (p, tree);
kono
parents:
diff changeset
542 if (t && !TYPE_P (t))
kono
parents:
diff changeset
543 side_effects |= TREE_SIDE_EFFECTS (t);
kono
parents:
diff changeset
544 TREE_OPERAND (ret, i) = t;
kono
parents:
diff changeset
545 }
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 TREE_SIDE_EFFECTS (ret) |= side_effects;
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 va_end (p);
kono
parents:
diff changeset
550 return ret;
kono
parents:
diff changeset
551 }
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 /* BRIG regs are untyped, but GENERIC is not. We need to add implicit casts
kono
parents:
diff changeset
554 in case treating the operand with an instruction with a type different
kono
parents:
diff changeset
555 than the created reg var type in order to select correct instruction type
kono
parents:
diff changeset
556 later on. This function creates the necessary reinterpret type cast from
kono
parents:
diff changeset
557 a source variable to the destination type. In case no cast is needed to
kono
parents:
diff changeset
558 the same type, SOURCE is returned directly. */
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 tree
kono
parents:
diff changeset
561 build_reinterpret_cast (tree destination_type, tree source)
kono
parents:
diff changeset
562 {
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 gcc_assert (source && destination_type && TREE_TYPE (source) != NULL_TREE
kono
parents:
diff changeset
565 && destination_type != NULL_TREE);
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 tree source_type = TREE_TYPE (source);
kono
parents:
diff changeset
568 if (TREE_CODE (source) == CALL_EXPR)
kono
parents:
diff changeset
569 {
kono
parents:
diff changeset
570 tree func_decl = TREE_OPERAND (TREE_OPERAND (source, 1), 0);
kono
parents:
diff changeset
571 source_type = TREE_TYPE (TREE_TYPE (func_decl));
kono
parents:
diff changeset
572 }
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 if (destination_type == source_type)
kono
parents:
diff changeset
575 return source;
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 size_t src_size = int_size_in_bytes (source_type);
kono
parents:
diff changeset
578 size_t dst_size = int_size_in_bytes (destination_type);
kono
parents:
diff changeset
579 if (src_size == dst_size)
kono
parents:
diff changeset
580 return build1 (VIEW_CONVERT_EXPR, destination_type, source);
kono
parents:
diff changeset
581 else if (src_size < dst_size)
kono
parents:
diff changeset
582 {
kono
parents:
diff changeset
583 /* The src_size can be smaller at least with f16 scalars which are
kono
parents:
diff changeset
584 stored to 32b register variables. First convert to an equivalent
kono
parents:
diff changeset
585 size unsigned type, then extend to an unsigned type of the
kono
parents:
diff changeset
586 target width, after which VIEW_CONVERT_EXPR can be used to
kono
parents:
diff changeset
587 force to the target type. */
kono
parents:
diff changeset
588 tree unsigned_temp = build1 (VIEW_CONVERT_EXPR,
kono
parents:
diff changeset
589 get_unsigned_int_type (source_type),
kono
parents:
diff changeset
590 source);
kono
parents:
diff changeset
591 return build1 (VIEW_CONVERT_EXPR, destination_type,
kono
parents:
diff changeset
592 convert (get_unsigned_int_type (destination_type),
kono
parents:
diff changeset
593 unsigned_temp));
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595 else
kono
parents:
diff changeset
596 gcc_unreachable ();
kono
parents:
diff changeset
597 return NULL_TREE;
kono
parents:
diff changeset
598 }
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 /* Returns the finished brig_function for the given generic FUNC_DECL,
kono
parents:
diff changeset
601 or NULL, if not found. */
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 brig_function *
kono
parents:
diff changeset
604 brig_to_generic::get_finished_function (tree func_decl)
kono
parents:
diff changeset
605 {
kono
parents:
diff changeset
606 std::string func_name
kono
parents:
diff changeset
607 = identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (func_decl)));
kono
parents:
diff changeset
608 std::map<std::string, brig_function *>::iterator i
kono
parents:
diff changeset
609 = m_finished_functions.find (func_name);
kono
parents:
diff changeset
610 if (i != m_finished_functions.end ())
kono
parents:
diff changeset
611 return (*i).second;
kono
parents:
diff changeset
612 else
kono
parents:
diff changeset
613 return NULL;
kono
parents:
diff changeset
614 }
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 /* Adds a group variable to a correct book keeping structure depending
kono
parents:
diff changeset
617 on its segment. */
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 void
kono
parents:
diff changeset
620 brig_to_generic::add_group_variable (const std::string &name, size_t size,
kono
parents:
diff changeset
621 size_t alignment, bool function_scope)
kono
parents:
diff changeset
622 {
kono
parents:
diff changeset
623 /* Module and function scope group region variables are an experimental
kono
parents:
diff changeset
624 feature. We implement module scope group variables with a separate
kono
parents:
diff changeset
625 book keeping inside brig_to_generic which is populated in the 'analyze()'
kono
parents:
diff changeset
626 prepass. This is to ensure we know the group segment offsets when
kono
parents:
diff changeset
627 processing the functions that might refer to them. */
kono
parents:
diff changeset
628 if (!function_scope)
kono
parents:
diff changeset
629 {
kono
parents:
diff changeset
630 if (!m_module_group_variables.has_variable (name))
kono
parents:
diff changeset
631 m_module_group_variables.add (name, size, alignment);
kono
parents:
diff changeset
632 return;
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 if (!m_cf->m_local_group_variables.has_variable (name))
kono
parents:
diff changeset
636 m_cf->m_local_group_variables.add (name, size, alignment);
kono
parents:
diff changeset
637 }
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 /* Finalizes the currently handled function. Should be called before
kono
parents:
diff changeset
640 setting a new function. */
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 void
kono
parents:
diff changeset
643 brig_to_generic::finish_function ()
kono
parents:
diff changeset
644 {
kono
parents:
diff changeset
645 if (m_cf == NULL || m_cf->m_func_decl == NULL_TREE)
kono
parents:
diff changeset
646 {
kono
parents:
diff changeset
647 /* It can be a finished func declaration fingerprint, in that case we
kono
parents:
diff changeset
648 don't have m_func_decl. */
kono
parents:
diff changeset
649 m_cf = NULL;
kono
parents:
diff changeset
650 return;
kono
parents:
diff changeset
651 }
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 if (!m_cf->m_is_kernel)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 tree bind_expr = m_cf->m_current_bind_expr;
kono
parents:
diff changeset
656 tree stmts = BIND_EXPR_BODY (bind_expr);
kono
parents:
diff changeset
657 m_cf->finish ();
kono
parents:
diff changeset
658 m_cf->emit_metadata (stmts);
kono
parents:
diff changeset
659 dump_function (m_dump_file, m_cf);
kono
parents:
diff changeset
660 gimplify_function_tree (m_cf->m_func_decl);
kono
parents:
diff changeset
661 cgraph_node::finalize_function (m_cf->m_func_decl, true);
kono
parents:
diff changeset
662 }
kono
parents:
diff changeset
663 else
kono
parents:
diff changeset
664 /* Emit the kernel only at the very end so we can analyze the total
kono
parents:
diff changeset
665 group and private memory usage. */
kono
parents:
diff changeset
666 m_kernels.push_back (m_cf);
kono
parents:
diff changeset
667
kono
parents:
diff changeset
668 pop_cfun ();
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 m_finished_functions[m_cf->m_name] = m_cf;
kono
parents:
diff changeset
671 m_cf = NULL;
kono
parents:
diff changeset
672 }
kono
parents:
diff changeset
673
kono
parents:
diff changeset
674 /* Initializes a new currently handled function. */
kono
parents:
diff changeset
675
kono
parents:
diff changeset
676 void
kono
parents:
diff changeset
677 brig_to_generic::start_function (tree f)
kono
parents:
diff changeset
678 {
kono
parents:
diff changeset
679 if (DECL_STRUCT_FUNCTION (f) == NULL)
kono
parents:
diff changeset
680 push_struct_function (f);
kono
parents:
diff changeset
681 else
kono
parents:
diff changeset
682 push_cfun (DECL_STRUCT_FUNCTION (f));
kono
parents:
diff changeset
683
kono
parents:
diff changeset
684 m_cf->m_func_decl = f;
kono
parents:
diff changeset
685 }
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 /* Appends a new variable to the current kernel's private segment. */
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 void
kono
parents:
diff changeset
690 brig_to_generic::append_private_variable (const std::string &name,
kono
parents:
diff changeset
691 size_t size, size_t alignment)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 /* We need to take care of two cases of alignment with private
kono
parents:
diff changeset
694 variables because of the layout where the same variable for
kono
parents:
diff changeset
695 each work-item is laid out in successive addresses.
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 1) Ensure the first work-item's variable is in an aligned
kono
parents:
diff changeset
698 offset: */
kono
parents:
diff changeset
699 size_t align_padding = m_next_private_offset % alignment == 0 ?
kono
parents:
diff changeset
700 0 : (alignment - m_next_private_offset % alignment);
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 /* 2) Each successive per-work-item copy should be aligned.
kono
parents:
diff changeset
703 If the variable has wider alignment than size then we need
kono
parents:
diff changeset
704 to add extra padding to ensure it. The padding must be
kono
parents:
diff changeset
705 included in the size to allow per-work-item offset computation
kono
parents:
diff changeset
706 to find their own aligned copy. */
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 size_t per_var_padding = size % alignment == 0 ?
kono
parents:
diff changeset
709 0 : (alignment - size % alignment);
kono
parents:
diff changeset
710 m_private_data_sizes[name] = size + per_var_padding;
kono
parents:
diff changeset
711
kono
parents:
diff changeset
712 m_next_private_offset += align_padding;
kono
parents:
diff changeset
713 m_private_offsets[name] = m_next_private_offset;
kono
parents:
diff changeset
714 m_next_private_offset += size + per_var_padding;
kono
parents:
diff changeset
715 }
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 size_t
kono
parents:
diff changeset
718 brig_to_generic::private_variable_segment_offset
kono
parents:
diff changeset
719 (const std::string &name) const
kono
parents:
diff changeset
720 {
kono
parents:
diff changeset
721 var_offset_table::const_iterator i = m_private_offsets.find (name);
kono
parents:
diff changeset
722 gcc_assert (i != m_private_offsets.end ());
kono
parents:
diff changeset
723 return (*i).second;
kono
parents:
diff changeset
724 }
kono
parents:
diff changeset
725
kono
parents:
diff changeset
726 bool
kono
parents:
diff changeset
727 brig_to_generic::has_private_variable (const std::string &name) const
kono
parents:
diff changeset
728 {
kono
parents:
diff changeset
729 std::map<std::string, size_t>::const_iterator i
kono
parents:
diff changeset
730 = m_private_data_sizes.find (name);
kono
parents:
diff changeset
731 return i != m_private_data_sizes.end ();
kono
parents:
diff changeset
732 }
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 size_t
kono
parents:
diff changeset
735 brig_to_generic::private_variable_size (const std::string &name) const
kono
parents:
diff changeset
736 {
kono
parents:
diff changeset
737 std::map<std::string, size_t>::const_iterator i
kono
parents:
diff changeset
738 = m_private_data_sizes.find (name);
kono
parents:
diff changeset
739 gcc_assert (i != m_private_data_sizes.end ());
kono
parents:
diff changeset
740 return (*i).second;
kono
parents:
diff changeset
741 }
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 /* The size of private segment required by a single work-item executing
kono
parents:
diff changeset
745 the currently processed kernel. */
kono
parents:
diff changeset
746
kono
parents:
diff changeset
747 size_t
kono
parents:
diff changeset
748 brig_to_generic::private_segment_size () const
kono
parents:
diff changeset
749 {
kono
parents:
diff changeset
750 return m_next_private_offset;
kono
parents:
diff changeset
751 }
kono
parents:
diff changeset
752
kono
parents:
diff changeset
753 /* Cached builtins indexed by name. */
kono
parents:
diff changeset
754
kono
parents:
diff changeset
755 typedef std::map<std::string, tree> builtin_index;
kono
parents:
diff changeset
756 builtin_index builtin_cache_;
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 /* Build a call to a builtin function. PDECL is the builtin function to
kono
parents:
diff changeset
759 call. NARGS is the number of input arguments, RETTYPE the built-in
kono
parents:
diff changeset
760 functions return value type, and ... is the list of arguments passed to
kono
parents:
diff changeset
761 the call with type first, then the value. */
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 tree
kono
parents:
diff changeset
764 call_builtin (tree pdecl, int nargs, tree rettype, ...)
kono
parents:
diff changeset
765 {
kono
parents:
diff changeset
766 if (rettype == error_mark_node)
kono
parents:
diff changeset
767 return error_mark_node;
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 tree *types = new tree[nargs];
kono
parents:
diff changeset
770 tree *args = new tree[nargs];
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 va_list ap;
kono
parents:
diff changeset
773 va_start (ap, rettype);
kono
parents:
diff changeset
774 for (int i = 0; i < nargs; ++i)
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 types[i] = va_arg (ap, tree);
kono
parents:
diff changeset
777 tree arg = va_arg (ap, tree);
kono
parents:
diff changeset
778 args[i] = build_reinterpret_cast (types[i], arg);
kono
parents:
diff changeset
779 if (types[i] == error_mark_node || args[i] == error_mark_node)
kono
parents:
diff changeset
780 {
kono
parents:
diff changeset
781 delete[] types;
kono
parents:
diff changeset
782 delete[] args;
kono
parents:
diff changeset
783 va_end (ap);
kono
parents:
diff changeset
784 return error_mark_node;
kono
parents:
diff changeset
785 }
kono
parents:
diff changeset
786 }
kono
parents:
diff changeset
787 va_end (ap);
kono
parents:
diff changeset
788
kono
parents:
diff changeset
789 tree fnptr = build_fold_addr_expr (pdecl);
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 tree ret = build_call_array (rettype, fnptr, nargs, args);
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 delete[] types;
kono
parents:
diff changeset
794 delete[] args;
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 return ret;
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 /* Generate all global declarations. Should be called after the last
kono
parents:
diff changeset
800 BRIG has been fed in. */
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 void
kono
parents:
diff changeset
803 brig_to_generic::write_globals ()
kono
parents:
diff changeset
804 {
kono
parents:
diff changeset
805 /* Now that the whole BRIG module has been processed, build a launcher
kono
parents:
diff changeset
806 and a metadata section for each built kernel. */
kono
parents:
diff changeset
807 for (size_t i = 0; i < m_kernels.size (); ++i)
kono
parents:
diff changeset
808 {
kono
parents:
diff changeset
809 brig_function *f = m_kernels[i];
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 /* Finish kernels now that we know the call graphs and their barrier
kono
parents:
diff changeset
812 usage. */
kono
parents:
diff changeset
813 f->finish_kernel ();
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 dump_function (m_dump_file, f);
kono
parents:
diff changeset
816 gimplify_function_tree (f->m_func_decl);
kono
parents:
diff changeset
817 cgraph_node::finalize_function (f->m_func_decl, true);
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 f->m_descriptor.is_kernel = 1;
kono
parents:
diff changeset
820 /* TODO: analyze the kernel's actual private and group segment usage
kono
parents:
diff changeset
821 using call graph. Now the mem size is overly
kono
parents:
diff changeset
822 pessimistic in case of multiple kernels in the same module.
kono
parents:
diff changeset
823 */
kono
parents:
diff changeset
824 f->m_descriptor.group_segment_size = m_total_group_segment_usage;
kono
parents:
diff changeset
825 f->m_descriptor.private_segment_size = private_segment_size ();
kono
parents:
diff changeset
826
kono
parents:
diff changeset
827 /* The kernarg size is rounded up to a multiple of 16 according to
kono
parents:
diff changeset
828 the PRM specs. */
kono
parents:
diff changeset
829 f->m_descriptor.kernarg_segment_size = f->m_next_kernarg_offset;
kono
parents:
diff changeset
830 if (f->m_descriptor.kernarg_segment_size % 16 > 0)
kono
parents:
diff changeset
831 f->m_descriptor.kernarg_segment_size
kono
parents:
diff changeset
832 += 16 - f->m_next_kernarg_offset % 16;
kono
parents:
diff changeset
833 f->m_descriptor.kernarg_max_align = f->m_kernarg_max_align;
kono
parents:
diff changeset
834
kono
parents:
diff changeset
835 tree launcher = f->emit_launcher_and_metadata ();
kono
parents:
diff changeset
836
kono
parents:
diff changeset
837 append_global (launcher);
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 gimplify_function_tree (launcher);
kono
parents:
diff changeset
840 cgraph_node::finalize_function (launcher, true);
kono
parents:
diff changeset
841 pop_cfun ();
kono
parents:
diff changeset
842 }
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 int no_globals = list_length (m_globals);
kono
parents:
diff changeset
845 tree *vec = new tree[no_globals];
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 int i = 0;
kono
parents:
diff changeset
848 tree global = m_globals;
kono
parents:
diff changeset
849 while (global)
kono
parents:
diff changeset
850 {
kono
parents:
diff changeset
851 vec[i] = global;
kono
parents:
diff changeset
852 ++i;
kono
parents:
diff changeset
853 global = TREE_CHAIN (global);
kono
parents:
diff changeset
854 }
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 wrapup_global_declarations (vec, no_globals);
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 delete[] vec;
kono
parents:
diff changeset
859
kono
parents:
diff changeset
860 }
kono
parents:
diff changeset
861
kono
parents:
diff changeset
862 /* Returns an type with unsigned int elements corresponding to the
kono
parents:
diff changeset
863 size and element count of ORIGINAL_TYPE. */
kono
parents:
diff changeset
864
kono
parents:
diff changeset
865 tree
kono
parents:
diff changeset
866 get_unsigned_int_type (tree original_type)
kono
parents:
diff changeset
867 {
kono
parents:
diff changeset
868 if (VECTOR_TYPE_P (original_type))
kono
parents:
diff changeset
869 {
kono
parents:
diff changeset
870 size_t esize
kono
parents:
diff changeset
871 = int_size_in_bytes (TREE_TYPE (original_type)) * BITS_PER_UNIT;
kono
parents:
diff changeset
872 size_t ecount = TYPE_VECTOR_SUBPARTS (original_type);
kono
parents:
diff changeset
873 return build_vector_type (build_nonstandard_integer_type (esize, true),
kono
parents:
diff changeset
874 ecount);
kono
parents:
diff changeset
875 }
kono
parents:
diff changeset
876 else
kono
parents:
diff changeset
877 return build_nonstandard_integer_type (int_size_in_bytes (original_type)
kono
parents:
diff changeset
878 * BITS_PER_UNIT,
kono
parents:
diff changeset
879 true);
kono
parents:
diff changeset
880 }
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 void
kono
parents:
diff changeset
883 dump_function (FILE *dump_file, brig_function *f)
kono
parents:
diff changeset
884 {
kono
parents:
diff changeset
885 /* Dump the BRIG-specific tree IR. */
kono
parents:
diff changeset
886 if (dump_file)
kono
parents:
diff changeset
887 {
kono
parents:
diff changeset
888 fprintf (dump_file, "\n;; Function %s", f->m_name.c_str ());
kono
parents:
diff changeset
889 fprintf (dump_file, "\n;; enabled by -%s\n\n",
kono
parents:
diff changeset
890 dump_flag_name (TDI_original));
kono
parents:
diff changeset
891 print_generic_decl (dump_file, f->m_func_decl, 0);
kono
parents:
diff changeset
892 print_generic_expr (dump_file, f->m_current_bind_expr, 0);
kono
parents:
diff changeset
893 fprintf (dump_file, "\n");
kono
parents:
diff changeset
894 }
kono
parents:
diff changeset
895 }