comparison gcc/brig/brigfrontend/brig-function-handler.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* brig-code-entry-handler.cc -- brig function directive handling 1 /* brig-code-entry-handler.cc -- brig function directive handling
2 Copyright (C) 2016-2017 Free Software Foundation, Inc. 2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> 3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech. 4 for General Processor Tech.
5 5
6 This file is part of GCC. 6 This file is part of GCC.
7 7
78 /* During the analyze step, the above information is all we need per 78 /* During the analyze step, the above information is all we need per
79 function. */ 79 function. */
80 if (m_parent.m_analyzing) 80 if (m_parent.m_analyzing)
81 return bytes_consumed; 81 return bytes_consumed;
82 82
83 /* There can be multiple forward declarations of the same function.
84 Skip all but the first one. */
85 if (!is_definition && m_parent.function_decl (func_name) != NULL_TREE)
86 return bytes_consumed;
83 tree fndecl; 87 tree fndecl;
84 tree ret_value = NULL_TREE; 88 tree ret_value = NULL_TREE;
85 89
86 tree stmt_list = alloc_stmt_list (); 90 tree stmt_list = alloc_stmt_list ();
87 91
88 /* Add a function scope BIND_EXPR using which we can push local variables that 92 /* Add a function scope BIND_EXPR using which we can push local variables that
89 represent HSAIL registers. */ 93 represent HSAIL registers. */
90 tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, NULL); 94 tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, NULL);
95
96 tree restrict_char_ptr
97 = build_qualified_type (build_pointer_type (char_type_node),
98 TYPE_QUAL_RESTRICT);
99 tree restrict_void_ptr
100 = build_qualified_type (build_pointer_type (void_type_node),
101 TYPE_QUAL_RESTRICT);
102
103 tree restrict_const_char_ptr
104 = build_qualified_type (build_pointer_type
105 (build_qualified_type (char_type_node,
106 TYPE_QUAL_CONST)),
107 TYPE_QUAL_RESTRICT);
108
109 tree restrict_const_void_ptr
110 = build_qualified_type (build_pointer_type
111 (build_qualified_type (void_type_node,
112 TYPE_QUAL_CONST)),
113 TYPE_QUAL_RESTRICT);
91 114
92 if (is_kernel) 115 if (is_kernel)
93 { 116 {
94 tree name_identifier 117 tree name_identifier
95 = get_identifier_with_length (func_name.c_str (), func_name.size ()); 118 = get_identifier_with_length (func_name.c_str (), func_name.size ());
101 2) a void* parameter that points to a phsail-finalizer context object 124 2) a void* parameter that points to a phsail-finalizer context object
102 which passes the hsa kernel packet etc. 125 which passes the hsa kernel packet etc.
103 3) a void* parameter that contains the first flat address of the group 126 3) a void* parameter that contains the first flat address of the group
104 region allocated to the current work-group. */ 127 region allocated to the current work-group. */
105 128
106 tree char_ptr_type_node = build_pointer_type (char_type_node);
107 fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier, 129 fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier,
108 build_function_type_list (void_type_node, 130 build_function_type_list (void_type_node,
109 char_ptr_type_node, 131 restrict_const_char_ptr,
110 ptr_type_node, 132 restrict_void_ptr,
111 ptr_type_node, NULL_TREE)); 133 restrict_char_ptr, NULL_TREE));
112 134
113 SET_DECL_ASSEMBLER_NAME (fndecl, name_identifier); 135 SET_DECL_ASSEMBLER_NAME (fndecl, name_identifier);
114 136
115 tree resdecl 137 tree resdecl
116 = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, void_type_node); 138 = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, void_type_node);
119 tree argtype = TREE_VALUE (typelist); 141 tree argtype = TREE_VALUE (typelist);
120 TYPE_ADDR_SPACE (argtype) 142 TYPE_ADDR_SPACE (argtype)
121 = gccbrig_get_target_addr_space_id (BRIG_SEGMENT_KERNARG); 143 = gccbrig_get_target_addr_space_id (BRIG_SEGMENT_KERNARG);
122 144
123 tree arg_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL, 145 tree arg_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL,
124 get_identifier ("__args"), char_ptr_type_node); 146 get_identifier ("__args"),
147 restrict_const_char_ptr);
125 DECL_ARGUMENTS (fndecl) = arg_arg; 148 DECL_ARGUMENTS (fndecl) = arg_arg;
126 DECL_ARG_TYPE (arg_arg) = char_ptr_type_node; 149 DECL_ARG_TYPE (arg_arg) = restrict_const_char_ptr;
127 DECL_CONTEXT (arg_arg) = fndecl; 150 DECL_CONTEXT (arg_arg) = fndecl;
128 DECL_ARTIFICIAL (arg_arg) = 1; 151 DECL_ARTIFICIAL (arg_arg) = 1;
129 TREE_READONLY (arg_arg) = 1; 152 TREE_READONLY (arg_arg) = 1;
130 TREE_USED (arg_arg) = 1; 153 TREE_USED (arg_arg) = 1;
131 154
132 DECL_RESULT (fndecl) = resdecl; 155 DECL_RESULT (fndecl) = resdecl;
133 DECL_CONTEXT (resdecl) = fndecl; 156 DECL_CONTEXT (resdecl) = fndecl;
134 DECL_EXTERNAL (fndecl) = 0; 157 DECL_EXTERNAL (fndecl) = 0;
158
159 /* Aggressive inlining to the kernel function is usually a good
160 idea with offlined functionality to enchance SIMD execution on
161 GPUs and vector units. */
162
163 DECL_ATTRIBUTES (fndecl)
164 = tree_cons (get_identifier ("flatten"), NULL,
165 DECL_ATTRIBUTES (fndecl));
135 } 166 }
136 else 167 else
137 { 168 {
138 /* Build a regular function fingerprint to enable targets to optimize 169 /* Build a regular function fingerprint to enable targets to optimize
139 the calling convention as they see fit. */ 170 the calling convention as they see fit. */
175 m_parent.m_cf->add_arg_variable (brigVar, arg_var); 206 m_parent.m_cf->add_arg_variable (brigVar, arg_var);
176 207
177 if (arg_decls == NULL_TREE) 208 if (arg_decls == NULL_TREE)
178 arg_decls = arg_var; 209 arg_decls = arg_var;
179 else 210 else
180 chainon (arg_decls, arg_var); 211 arg_decls = chainon (arg_decls, arg_var);
181 212
182 m_parent.m_cf->add_arg_variable (brigVar, arg_var); 213 m_parent.m_cf->add_arg_variable (brigVar, arg_var);
183 214
184 ret_value = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, 215 ret_value = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
185 void_type_node); 216 void_type_node);
216 tree arg_var = varhandler.build_variable (brigVar, PARM_DECL); 247 tree arg_var = varhandler.build_variable (brigVar, PARM_DECL);
217 arg_offset += brigVar->base.byteCount; 248 arg_offset += brigVar->base.byteCount;
218 vec_safe_push (args, TREE_TYPE (arg_var)); 249 vec_safe_push (args, TREE_TYPE (arg_var));
219 250
220 m_parent.m_cf->add_arg_variable (brigVar, arg_var); 251 m_parent.m_cf->add_arg_variable (brigVar, arg_var);
221 252 arg_decls = chainon (arg_decls, arg_var);
222 if (arg_decls == NULL_TREE)
223 arg_decls = arg_var;
224 else
225 chainon (arg_decls, arg_var);
226 } 253 }
227 } 254 }
228 255 vec_safe_push (args, restrict_void_ptr);
229 vec_safe_push (args, ptr_type_node); 256 vec_safe_push (args, restrict_char_ptr);
230 vec_safe_push (args, ptr_type_node); 257 vec_safe_push (args, uint32_type_node);
258 vec_safe_push (args, restrict_char_ptr);
231 259
232 fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier, 260 fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier,
233 build_function_type_vec (ret_type, args)); 261 build_function_type_vec (ret_type, args));
234 262
235 DECL_RESULT (fndecl) = ret_value; 263 DECL_RESULT (fndecl) = ret_value;
238 DECL_ARGUMENTS (fndecl) = arg_decls; 266 DECL_ARGUMENTS (fndecl) = arg_decls;
239 } 267 }
240 268
241 /* All functions need the hidden __context argument passed on 269 /* All functions need the hidden __context argument passed on
242 because they might call WI-specific functions which need 270 because they might call WI-specific functions which need
243 the context info. */ 271 the context info. Only kernels can write it, if they need
272 to update the local ids in the work-item loop. */
273
274 tree context_arg_type
275 = true ? restrict_void_ptr : restrict_const_void_ptr;
244 tree context_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL, 276 tree context_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL,
245 get_identifier ("__context"), ptr_type_node); 277 get_identifier ("__context"),
246 if (DECL_ARGUMENTS (fndecl) == NULL_TREE) 278 context_arg_type);
247 DECL_ARGUMENTS (fndecl) = context_arg; 279 DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), context_arg);
248 else
249 chainon (DECL_ARGUMENTS (fndecl), context_arg);
250 DECL_CONTEXT (context_arg) = fndecl; 280 DECL_CONTEXT (context_arg) = fndecl;
251 DECL_ARG_TYPE (context_arg) = ptr_type_node; 281 DECL_ARG_TYPE (context_arg) = context_arg_type;
252 DECL_ARTIFICIAL (context_arg) = 1; 282 DECL_ARTIFICIAL (context_arg) = 1;
253 TREE_READONLY (context_arg) = 1; 283 TREE_READONLY (context_arg) = 1;
254 TREE_USED (context_arg) = 1; 284 TREE_USED (context_arg) = 1;
285 m_parent.m_cf->m_context_arg = context_arg;
255 286
256 /* They can also access group memory, so we need to pass the 287 /* They can also access group memory, so we need to pass the
257 group pointer along too. */ 288 group pointer along too. */
258 tree group_base_arg 289 tree group_base_arg
259 = build_decl (UNKNOWN_LOCATION, PARM_DECL, 290 = build_decl (UNKNOWN_LOCATION, PARM_DECL,
260 get_identifier ("__group_base_addr"), ptr_type_node); 291 get_identifier ("__group_base_addr"),
261 chainon (DECL_ARGUMENTS (fndecl), group_base_arg); 292 restrict_char_ptr);
262 DECL_ARG_TYPE (group_base_arg) = ptr_type_node; 293 DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), group_base_arg);
294 DECL_ARG_TYPE (group_base_arg) = restrict_char_ptr;
263 DECL_CONTEXT (group_base_arg) = fndecl; 295 DECL_CONTEXT (group_base_arg) = fndecl;
264 DECL_ARTIFICIAL (group_base_arg) = 1; 296 DECL_ARTIFICIAL (group_base_arg) = 1;
265 TREE_READONLY (group_base_arg) = 1; 297 TREE_READONLY (group_base_arg) = 1;
266 TREE_USED (group_base_arg) = 1; 298 TREE_USED (group_base_arg) = 1;
267 m_parent.m_cf->m_group_base_arg = group_base_arg; 299 m_parent.m_cf->m_group_base_arg = group_base_arg;
272 That must be substracted from any function local group variable offsets to 304 That must be substracted from any function local group variable offsets to
273 get the address related to the bottom of the group memory chunk. */ 305 get the address related to the bottom of the group memory chunk. */
274 tree group_local_offset_arg 306 tree group_local_offset_arg
275 = build_decl (UNKNOWN_LOCATION, PARM_DECL, 307 = build_decl (UNKNOWN_LOCATION, PARM_DECL,
276 get_identifier ("__group_local_offset"), uint32_type_node); 308 get_identifier ("__group_local_offset"), uint32_type_node);
277 chainon (DECL_ARGUMENTS (fndecl), group_local_offset_arg); 309 DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), group_local_offset_arg);
278 DECL_ARG_TYPE (group_local_offset_arg) = uint32_type_node; 310 DECL_ARG_TYPE (group_local_offset_arg) = uint32_type_node;
279 DECL_CONTEXT (group_local_offset_arg) = fndecl; 311 DECL_CONTEXT (group_local_offset_arg) = fndecl;
280 DECL_ARTIFICIAL (group_local_offset_arg) = 1; 312 DECL_ARTIFICIAL (group_local_offset_arg) = 1;
281 TREE_READONLY (group_local_offset_arg) = 1; 313 TREE_READONLY (group_local_offset_arg) = 1;
282 TREE_USED (group_local_offset_arg) = 1; 314 TREE_USED (group_local_offset_arg) = 1;
283 m_parent.m_cf->m_group_local_offset_arg = group_local_offset_arg; 315 m_parent.m_cf->m_group_local_offset_arg = group_local_offset_arg;
284 316
285 /* Same for private. */ 317 /* Same for private. */
286 tree private_base_arg 318 tree private_base_arg
287 = build_decl (UNKNOWN_LOCATION, PARM_DECL, 319 = build_decl (UNKNOWN_LOCATION, PARM_DECL,
288 get_identifier ("__private_base_addr"), ptr_type_node); 320 get_identifier ("__private_base_addr"), restrict_char_ptr);
289 chainon (DECL_ARGUMENTS (fndecl), private_base_arg); 321 DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), private_base_arg);
290 DECL_ARG_TYPE (private_base_arg) = ptr_type_node; 322 DECL_ARG_TYPE (private_base_arg) = restrict_char_ptr;
291 DECL_CONTEXT (private_base_arg) = fndecl; 323 DECL_CONTEXT (private_base_arg) = fndecl;
292 DECL_ARTIFICIAL (private_base_arg) = 1; 324 DECL_ARTIFICIAL (private_base_arg) = 1;
293 TREE_READONLY (private_base_arg) = 1; 325 TREE_READONLY (private_base_arg) = 1;
294 TREE_USED (private_base_arg) = 1; 326 TREE_USED (private_base_arg) = 1;
327 m_parent.m_cf->m_private_base_arg = private_base_arg;
295 328
296 DECL_SAVED_TREE (fndecl) = bind_expr; 329 DECL_SAVED_TREE (fndecl) = bind_expr;
297 330
298 /* Try to preserve the functions across IPA. */
299 DECL_PRESERVE_P (fndecl) = 1;
300 TREE_SIDE_EFFECTS (fndecl) = 1;
301
302 TREE_ADDRESSABLE (fndecl) = 1;
303
304 if (base->kind == BRIG_KIND_DIRECTIVE_FUNCTION) 331 if (base->kind == BRIG_KIND_DIRECTIVE_FUNCTION)
305 { 332 {
306 TREE_STATIC (fndecl) = 1; 333 TREE_STATIC (fndecl) = 0;
307 TREE_PUBLIC (fndecl) = 1; 334 TREE_PUBLIC (fndecl) = 1;
335 DECL_EXTERNAL (fndecl) = 0;
336 DECL_DECLARED_INLINE_P (fndecl) = 1;
337 set_inline (fndecl);
338 set_externally_visible (fndecl);
308 } 339 }
309 else if (base->kind == BRIG_KIND_DIRECTIVE_KERNEL) 340 else if (base->kind == BRIG_KIND_DIRECTIVE_KERNEL)
310 { 341 {
311 TREE_STATIC (fndecl) = 1; 342 TREE_STATIC (fndecl) = 0;
312 TREE_PUBLIC (fndecl) = 1; 343 TREE_PUBLIC (fndecl) = 1;
344 DECL_EXTERNAL (fndecl) = 0;
345 set_externally_visible (fndecl);
313 } 346 }
314 else if (base->kind == BRIG_KIND_DIRECTIVE_SIGNATURE) 347 else if (base->kind == BRIG_KIND_DIRECTIVE_SIGNATURE)
315 { 348 {
316 TREE_STATIC (fndecl) = 0; 349 TREE_STATIC (fndecl) = 0;
317 TREE_PUBLIC (fndecl) = 1; 350 TREE_PUBLIC (fndecl) = 1;
318 DECL_EXTERNAL (fndecl) = 1; 351 DECL_EXTERNAL (fndecl) = 1;
352 set_inline (fndecl);
319 } 353 }
320 else if (base->kind == BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION) 354 else if (base->kind == BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION)
321 { 355 {
322 TREE_STATIC (fndecl) = 0; 356 TREE_STATIC (fndecl) = 0;
323 TREE_PUBLIC (fndecl) = 1; 357 TREE_PUBLIC (fndecl) = 1;
347 } 381 }
348 382
349 m_parent.add_function_decl (func_name, fndecl); 383 m_parent.add_function_decl (func_name, fndecl);
350 m_parent.append_global (fndecl); 384 m_parent.append_global (fndecl);
351 385
386
352 if (!is_definition) 387 if (!is_definition)
353 return bytes_consumed; 388 {
389 DECL_EXTERNAL (fndecl) = 1;
390 return bytes_consumed;
391 }
354 392
355 m_parent.start_function (fndecl); 393 m_parent.start_function (fndecl);
356
357 m_parent.m_cf->m_func_decl = fndecl; 394 m_parent.m_cf->m_func_decl = fndecl;
358 m_parent.m_cf->m_current_bind_expr = bind_expr; 395 m_parent.m_cf->m_current_bind_expr = bind_expr;
359 m_parent.m_cf->m_context_arg = context_arg;
360 m_parent.m_cf->m_private_base_arg = private_base_arg;
361 396
362 if (ret_value != NULL_TREE && TREE_TYPE (ret_value) != void_type_node) 397 if (ret_value != NULL_TREE && TREE_TYPE (ret_value) != void_type_node)
363 { 398 {
364 /* We cannot assign to <<retval>> directly in gcc trunk. We need to 399 /* We cannot assign to <<retval>> directly in gcc trunk. We need to
365 create a local temporary variable which can be stored to and when 400 create a local temporary variable which can be stored to and when