PR c++/80891 (#1)
[gcc.git] / gcc / cilk-common.c
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the CilkPlus Intrinsics
3 Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
5 Intel Corporation
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "function.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "expmed.h"
32 #include "optabs-query.h"
33 #include "insn-config.h"
34 #include "memmodel.h"
35 #include "emit-rtl.h"
36 #include "recog.h"
37 #include "fold-const.h"
38 #include "stor-layout.h"
39 #include "langhooks.h"
40 #include "explow.h"
41 #include "expr.h"
42 #include "tree-iterator.h"
43 #include "gimplify.h"
44 #include "cilk.h"
45
46 /* This structure holds all the important fields of the internal structures,
47 internal built-in functions, and Cilk-specific data types. Explanation of
48 all the these fielsd are given in cilk.h. */
49 tree cilk_trees[(int) CILK_TI_MAX];
50
51 /* Returns the value in structure FRAME pointed by the FIELD_NUMBER
52 (e.g. X.y).
53 FIELD_NUMBER is an index to the structure FRAME_PTR. For details
54 about these fields, refer to cilk_trees structure in cilk.h and
55 cilk_init_builtins function in this file. Returns a TREE that is the type
56 of the field represented by FIELD_NUMBER. If VOLATIL parameter is set
57 to true then the returning field is set as volatile. */
58
59 tree
60 cilk_dot (tree frame, int field_number, bool volatil)
61 {
62 tree field = cilk_trees[field_number];
63 field = fold_build3 (COMPONENT_REF, TREE_TYPE (field), frame, field,
64 NULL_TREE);
65 TREE_THIS_VOLATILE (field) = volatil;
66 return field;
67 }
68
69 /* Returns the address of a field in FRAME_PTR, pointed by FIELD_NUMBER.
70 (e.g. (&X)->y). Please see cilk_dot function for explanation of the
71 FIELD_NUMBER. Returns a tree that is the type of the field represented
72 by FIELD_NUMBER. If VOLATIL parameter is set to true then the returning
73 field is set as volatile. */
74
75 tree
76 cilk_arrow (tree frame_ptr, int field_number, bool volatil)
77 {
78 return cilk_dot (build_simple_mem_ref (frame_ptr),
79 field_number, volatil);
80 }
81
82
83 /* This function will add FIELD of type TYPE to a defined built-in
84 structure. *NAME is the name of the field to be added. */
85
86 static tree
87 add_field (const char *name, tree type, tree fields)
88 {
89 tree t = get_identifier (name);
90 tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, t, type);
91 TREE_CHAIN (field) = fields;
92 return field;
93 }
94
95 /* This function will define a built-in function of NAME, of type FNTYPE and
96 register it under the built-in function code CODE. If PUBLISH is set then
97 the declaration is pushed into the declaration list. CODE is the index
98 to the cilk_trees array. *NAME is the name of the function to be added. */
99
100 static tree
101 install_builtin (const char *name, tree fntype, enum built_in_function code,
102 bool publish)
103 {
104 tree fndecl = build_fn_decl (name, fntype);
105 DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL;
106 DECL_FUNCTION_CODE (fndecl) = code;
107 if (publish)
108 {
109 tree t = lang_hooks.decls.pushdecl (fndecl);
110 if (t)
111 fndecl = t;
112 }
113 set_builtin_decl (code, fndecl, true);
114 return fndecl;
115 }
116
117 /* Returns a FUNCTION_DECL of type TYPE whose name is *NAME. */
118
119 static tree
120 declare_cilk_for_builtin (const char *name, tree type,
121 enum built_in_function code)
122 {
123 tree cb, ft, fn;
124
125 cb = build_function_type_list (void_type_node,
126 ptr_type_node, type, type,
127 NULL_TREE);
128 cb = build_pointer_type (cb);
129 ft = build_function_type_list (void_type_node,
130 cb, ptr_type_node, type,
131 integer_type_node, NULL_TREE);
132 fn = install_builtin (name, ft, code, false);
133 TREE_NOTHROW (fn) = 0;
134
135 return fn;
136 }
137
138 /* Creates and initializes all the built-in Cilk keywords functions and three
139 structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker.
140 Detailed information about __cilkrts_stack_frame and
141 __cilkrts_worker structures are given in libcilkrts/include/internal/abi.h.
142 __cilkrts_pedigree is described in libcilkrts/include/cilk/common.h. */
143
144 void
145 cilk_init_builtins (void)
146 {
147 /* Now build the following __cilkrts_pedigree struct:
148 struct __cilkrts_pedigree {
149 uint64_t rank;
150 struct __cilkrts_pedigree *parent;
151 } */
152
153 tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE);
154 tree pedigree_ptr = build_pointer_type (pedigree_type);
155 tree field = add_field ("rank", uint64_type_node, NULL_TREE);
156 cilk_trees[CILK_TI_PEDIGREE_RANK] = field;
157 field = add_field ("parent", pedigree_ptr, field);
158 cilk_trees[CILK_TI_PEDIGREE_PARENT] = field;
159 finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field,
160 NULL_TREE);
161 lang_hooks.types.register_builtin_type (pedigree_type,
162 "__cilkrts_pedigree_t");
163 cilk_pedigree_type_decl = pedigree_type;
164
165 /* Build the Cilk Stack Frame:
166 struct __cilkrts_stack_frame {
167 uint32_t flags;
168 uint32_t size;
169 struct __cilkrts_stack_frame *call_parent;
170 __cilkrts_worker *worker;
171 void *except_data;
172 void *ctx[4];
173 uint32_t mxcsr;
174 uint16_t fpcsr;
175 uint16_t reserved;
176 __cilkrts_pedigree pedigree;
177 }; */
178
179 tree frame = lang_hooks.types.make_type (RECORD_TYPE);
180 tree frame_ptr = build_pointer_type (frame);
181 tree worker_type = lang_hooks.types.make_type (RECORD_TYPE);
182 tree worker_ptr = build_pointer_type (worker_type);
183 tree s_type_node = build_int_cst (size_type_node, 4);
184
185 tree flags = add_field ("flags", uint32_type_node, NULL_TREE);
186 tree size = add_field ("size", uint32_type_node, flags);
187 tree parent = add_field ("call_parent", frame_ptr, size);
188 tree worker = add_field ("worker", worker_ptr, parent);
189 tree except = add_field ("except_data", frame_ptr, worker);
190 tree context = add_field ("ctx",
191 build_array_type (ptr_type_node,
192 build_index_type (s_type_node)),
193 except);
194 tree mxcsr = add_field ("mxcsr", uint32_type_node, context);
195 tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr);
196 tree reserved = add_field ("reserved", uint16_type_node, fpcsr);
197 tree pedigree = add_field ("pedigree", pedigree_type, reserved);
198
199 /* Now add them to a common structure whose fields are #defined to something
200 that is used at a later stage. */
201 cilk_trees[CILK_TI_FRAME_FLAGS] = flags;
202 cilk_trees[CILK_TI_FRAME_PARENT] = parent;
203 cilk_trees[CILK_TI_FRAME_WORKER] = worker;
204 cilk_trees[CILK_TI_FRAME_EXCEPTION] = except;
205 cilk_trees[CILK_TI_FRAME_CONTEXT] = context;
206 /* We don't care about reserved, so no need to store it in cilk_trees. */
207 cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree;
208 TREE_ADDRESSABLE (frame) = 1;
209
210 finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE);
211 cilk_frame_type_decl = frame;
212 lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t");
213
214 cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr,
215 TYPE_QUAL_VOLATILE);
216 /* Now let's do the following worker struct:
217
218 struct __cilkrts_worker {
219 __cilkrts_stack_frame *volatile *volatile tail;
220 __cilkrts_stack_frame *volatile *volatile head;
221 __cilkrts_stack_frame *volatile *volatile exc;
222 __cilkrts_stack_frame *volatile *volatile protected_tail;
223 __cilkrts_stack_frame *volatile *ltq_limit;
224 int32_t self;
225 global_state_t *g;
226 local_state *l;
227 cilkred_map *reducer_map;
228 __cilkrts_stack_frame *current_stack_frame;
229 void *reserved;
230 __cilkrts_worker_sysdep_state *sysdep;
231 __cilkrts_pedigree pedigree;
232 } */
233
234 tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE);
235 tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type);
236 tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr,
237 TYPE_QUAL_VOLATILE);
238 tree g = lang_hooks.types.make_type (RECORD_TYPE);
239 finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE);
240 tree l = lang_hooks.types.make_type (RECORD_TYPE);
241 finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE);
242 tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE);
243 finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE,
244 NULL_TREE);
245
246 field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE);
247 cilk_trees[CILK_TI_WORKER_TAIL] = field;
248 field = add_field ("head", fptr_vol_ptr_vol, field);
249 field = add_field ("exc", fptr_vol_ptr_vol, field);
250 field = add_field ("protected_tail", fptr_vol_ptr_vol, field);
251 field = add_field ("ltq_limit", fptr_volatile_ptr, field);
252 field = add_field ("self", integer_type_node, field);
253 field = add_field ("g", build_pointer_type (g), field);
254 field = add_field ("l", build_pointer_type (g), field);
255 field = add_field ("reducer_map", ptr_type_node, field);
256 field = add_field ("current_stack_frame", frame_ptr, field);
257 cilk_trees[CILK_TI_WORKER_CUR] = field;
258 field = add_field ("saved_protected_tail", fptr_volatile_ptr, field);
259 field = add_field ("sysdep", build_pointer_type (sysdep_t), field);
260 field = add_field ("pedigree", pedigree_type, field);
261 cilk_trees[CILK_TI_WORKER_PEDIGREE] = field;
262 finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field,
263 NULL_TREE);
264
265 tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node);
266 tree fptr_fun = build_function_type (void_type_node, fptr_arglist);
267
268 /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */
269 cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun,
270 BUILT_IN_CILK_ENTER_FRAME, false);
271
272 /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */
273 cilk_enter_fast_fndecl =
274 install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun,
275 BUILT_IN_CILK_ENTER_FRAME_FAST, false);
276
277 /* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */
278 cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
279 BUILT_IN_CILK_POP_FRAME, false);
280
281 /* void __cilkrts_leave_frame (__cilkrts_stack_frame *); */
282 cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun,
283 BUILT_IN_CILK_LEAVE_FRAME, false);
284
285 /* void __cilkrts_sync (__cilkrts_stack_frame *); */
286 cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun,
287 BUILT_IN_CILK_SYNC, false);
288
289 /* void __cilkrts_detach (__cilkrts_stack_frame *); */
290 cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun,
291 BUILT_IN_CILK_DETACH, false);
292
293 /* __cilkrts_rethrow (struct stack_frame *); */
294 cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun,
295 BUILT_IN_CILK_RETHROW, false);
296 TREE_NOTHROW (cilk_rethrow_fndecl) = 0;
297
298 /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */
299 cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state",
300 fptr_fun, BUILT_IN_CILK_SAVE_FP,
301 false);
302 /* __cilkrts_cilk_for_32 (...); */
303 cilk_for_32_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_32",
304 unsigned_intSI_type_node,
305 BUILT_IN_CILK_FOR_32);
306 /* __cilkrts_cilk_for_64 (...); */
307 cilk_for_64_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_64",
308 unsigned_intDI_type_node,
309 BUILT_IN_CILK_FOR_64);
310 }
311
312 /* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */
313
314 static tree
315 get_frame_arg (tree call)
316 {
317 tree arg, argtype;
318
319 gcc_assert (call_expr_nargs (call) >= 1);
320
321 arg = CALL_EXPR_ARG (call, 0);
322 argtype = TREE_TYPE (arg);
323 gcc_assert (TREE_CODE (argtype) == POINTER_TYPE);
324
325 argtype = TREE_TYPE (argtype);
326
327 /* If it is passed in as an address, then just use the value directly
328 since the function is inlined. */
329 if (TREE_CODE (arg) == ADDR_EXPR)
330 return TREE_OPERAND (arg, 0);
331 return arg;
332 }
333
334 /* Expands the __cilkrts_pop_frame function call stored in EXP. */
335
336 void
337 expand_builtin_cilk_pop_frame (tree exp)
338 {
339 tree frame = get_frame_arg (exp);
340 tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
341
342 tree clear_parent = build2 (MODIFY_EXPR, void_type_node, parent,
343 build_int_cst (TREE_TYPE (parent), 0));
344 expand_expr (clear_parent, const0_rtx, VOIDmode, EXPAND_NORMAL);
345
346 /* During LTO, the is_cilk_function flag gets cleared.
347 If __cilkrts_pop_frame is called, then this definitely must be a
348 cilk function. */
349 if (cfun)
350 cfun->is_cilk_function = 1;
351 }
352
353 /* Expands the cilk_detach function call stored in EXP. */
354
355 void
356 expand_builtin_cilk_detach (tree exp)
357 {
358 rtx_insn *insn;
359 tree fptr = get_frame_arg (exp);
360
361 if (fptr == NULL_TREE)
362 return;
363
364 tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0);
365 tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0);
366 tree tail = cilk_arrow (worker, CILK_TI_WORKER_TAIL, 1);
367
368 tree faddr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, fptr);
369 tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, faddr);
370 expand_expr (enter_frame, const0_rtx, VOIDmode, EXPAND_NORMAL);
371
372 tree pedigree = cilk_dot (fptr, CILK_TI_FRAME_PEDIGREE, 0);
373 tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
374 tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
375 tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
376 tree pedigree_parent_rank = cilk_dot (pedigree_parent,
377 CILK_TI_PEDIGREE_RANK, 0);
378 tree pedigree_parent_parent = cilk_dot (pedigree_parent,
379 CILK_TI_PEDIGREE_PARENT, 0);
380 tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
381 tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
382 tree w_pedigree_parent = cilk_dot (worker_pedigree,
383 CILK_TI_PEDIGREE_PARENT, 0);
384
385 rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL);
386 if (GET_CODE (wreg) != REG)
387 wreg = copy_to_reg (wreg);
388 rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL);
389
390 /* sf.pedigree.rank = worker->pedigree.rank. */
391 tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
392 w_pedigree_rank);
393 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
394
395 /* sf.pedigree.parent = worker->pedigree.parent. */
396 exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
397 w_pedigree_parent);
398 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
399
400 /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */
401 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
402 w_pedigree_rank);
403 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
404
405 /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */
406 exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
407 w_pedigree_parent);
408 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
409
410 /* sf->worker.pedigree.rank = 0. */
411 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
412 build_zero_cst (uint64_type_node));
413 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
414
415 /* sf->pedigree.parent = &sf->pedigree. */
416 exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
417 build1 (ADDR_EXPR,
418 build_pointer_type (cilk_pedigree_type_decl),
419 pedigree));
420 expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL);
421
422 /* TMP <- WORKER.TAIL
423 *TMP <- PARENT
424 TMP <- TMP + 1
425 WORKER.TAIL <- TMP */
426
427 HOST_WIDE_INT worker_tail_offset =
428 tree_to_shwi (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) +
429 tree_to_shwi (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) /
430 BITS_PER_UNIT;
431 rtx tmem0 = gen_rtx_MEM (Pmode,
432 plus_constant (Pmode, wreg, worker_tail_offset));
433 set_mem_attributes (tmem0, tail, 0);
434 MEM_NOTRAP_P (tmem0) = 1;
435 gcc_assert (MEM_VOLATILE_P (tmem0));
436 rtx treg = copy_to_mode_reg (Pmode, tmem0);
437 rtx tmem1 = gen_rtx_MEM (Pmode, treg);
438 set_mem_attributes (tmem1, TREE_TYPE (TREE_TYPE (tail)), 0);
439 MEM_NOTRAP_P (tmem1) = 1;
440 emit_move_insn (tmem1, preg);
441 emit_move_insn (treg, plus_constant (Pmode, treg, GET_MODE_SIZE (Pmode)));
442
443 /* There is a release barrier (st8.rel, membar #StoreStore,
444 sfence, lwsync, etc.) between the two stores. On x86
445 normal volatile stores have proper semantics; the sfence
446 would only be needed for nontemporal stores (which we
447 could generate using the storent optab, for no benefit
448 in this case).
449
450 The predicate may return false even for a REG if this is
451 the limited release operation that only stores 0. */
452 enum insn_code icode = direct_optab_handler (sync_lock_release_optab, Pmode);
453 if (icode != CODE_FOR_nothing
454 && insn_data[icode].operand[1].predicate (treg, Pmode)
455 && (insn = GEN_FCN (icode) (tmem0, treg)) != NULL_RTX)
456 emit_insn (insn);
457 else
458 emit_move_insn (tmem0, treg);
459
460 /* The memory barrier inserted above should not prevent
461 the load of flags from being moved before the stores,
462 but in practice it does because it is implemented with
463 unspec_volatile. In-order RISC machines should
464 explicitly load flags earlier. */
465
466 tree flags = cilk_dot (fptr, CILK_TI_FRAME_FLAGS, 0);
467 expand_expr (build2 (MODIFY_EXPR, void_type_node, flags,
468 build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
469 build_int_cst (TREE_TYPE (flags),
470 CILK_FRAME_DETACHED))),
471 const0_rtx, VOIDmode, EXPAND_NORMAL);
472 }
473
474 /* Returns a setjmp CALL_EXPR with FRAME->context as its parameter. */
475
476 tree
477 cilk_call_setjmp (tree frame)
478 {
479 tree c = cilk_dot (frame, CILK_TI_FRAME_CONTEXT, false);
480 c = build1 (ADDR_EXPR, build_pointer_type (ptr_type_node), c);
481 return build_call_expr (builtin_decl_implicit (BUILT_IN_SETJMP), 1, c);
482 }
483
484 /* This function will expand the _Cilk_sync keyword. */
485
486 static tree
487 expand_cilk_sync (void)
488 {
489 tree frame = cfun->cilk_frame_decl;
490
491 /* Cilk_sync is converted to the following code:
492
493 sf.pedigree = sf.worker->pedigree;
494 if (frame.flags & CILK_FRAME_UNSYNCHED)
495 {
496 __cilkrts_save_fp_state (&sf);
497 if (!builtin_setjmp (sf.ctx)
498 __cilkrts_sync (&sf);
499 else
500 if (sf.flags & CILK_FRAME_EXCEPTING)
501 __cilkrts_rethrow (&sf);
502 }
503 sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1; */
504
505 tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
506
507 tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
508 build_int_cst (TREE_TYPE (flags),
509 CILK_FRAME_UNSYNCHED));
510
511 unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
512 build_int_cst (TREE_TYPE (unsynched), 0));
513
514 tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
515
516 /* Check if exception (0x10) bit is set in the sf->flags. */
517 tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
518 build_int_cst (TREE_TYPE (flags),
519 CILK_FRAME_EXCEPTING));
520 except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
521 build_int_cst (TREE_TYPE (except_flag), 0));
522
523 /* If the exception flag is set then call the __cilkrts_rethrow (&sf). */
524 tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
525 build_call_expr (cilk_rethrow_fndecl, 1,
526 frame_addr),
527 build_empty_stmt (EXPR_LOCATION (unsynched)));
528
529 tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
530 tree setjmp_expr = cilk_call_setjmp (frame);
531 setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
532 build_int_cst (TREE_TYPE (setjmp_expr), 0));
533
534 setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
535 sync_expr, except_cond);
536 tree sync_list = alloc_stmt_list ();
537 append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1,
538 frame_addr), &sync_list);
539 append_to_statement_list (setjmp_expr, &sync_list);
540 tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list,
541 build_empty_stmt (EXPR_LOCATION (unsynched)));
542 tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false);
543 tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false);
544 tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false);
545 tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node,
546 parent_pedigree, worker_pedigree);
547 tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree),
548 CILK_TI_PEDIGREE_RANK, false);
549 tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank),
550 w_ped_rank,
551 build_one_cst (TREE_TYPE (w_ped_rank)));
552 incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank,
553 incr_ped_rank);
554 tree ret_sync_exp = alloc_stmt_list ();
555 append_to_statement_list (assign_pedigree, &ret_sync_exp);
556 append_to_statement_list (sync, &ret_sync_exp);
557 append_to_statement_list (incr_ped_rank, &ret_sync_exp);
558 return ret_sync_exp;
559 }
560
561 /* Gimplifies the cilk_sync expression passed in *EXPR_P. Returns GS_ALL_DONE
562 when finished. */
563
564 void
565 gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p)
566 {
567 tree sync_expr = expand_cilk_sync ();
568 *expr_p = NULL_TREE;
569 gimplify_and_add (sync_expr, pre_p);
570 }