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