2017-05-01 Xi Ruoyao <ryxi@stu.xidian.edu.cn>
[official-gcc.git] / gcc / cilk-common.c
blob9cbe03f8e02abc010a399eb28ab5829aab1cd98a
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 "expr.h"
42 #include "tree-iterator.h"
43 #include "gimplify.h"
44 #include "cilk.h"
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];
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. */
59 tree
60 cilk_dot (tree frame, int field_number, bool volatil)
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;
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. */
75 tree
76 cilk_arrow (tree frame_ptr, int field_number, bool volatil)
78 return cilk_dot (build_simple_mem_ref (frame_ptr),
79 field_number, volatil);
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. */
86 static tree
87 add_field (const char *name, tree type, tree fields)
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;
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. */
100 static tree
101 install_builtin (const char *name, tree fntype, enum built_in_function code,
102 bool publish)
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)
109 tree t = lang_hooks.decls.pushdecl (fndecl);
110 if (t)
111 fndecl = t;
113 set_builtin_decl (code, fndecl, true);
114 return fndecl;
117 /* Returns a FUNCTION_DECL of type TYPE whose name is *NAME. */
119 static tree
120 declare_cilk_for_builtin (const char *name, tree type,
121 enum built_in_function code)
123 tree cb, ft, fn;
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;
135 return fn;
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. */
144 void
145 cilk_init_builtins (void)
147 /* Now build the following __cilkrts_pedigree struct:
148 struct __cilkrts_pedigree {
149 uint64_t rank;
150 struct __cilkrts_pedigree *parent;
151 } */
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;
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 }; */
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);
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);
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;
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");
214 cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr,
215 TYPE_QUAL_VOLATILE);
216 /* Now let's do the following worker struct:
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 } */
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);
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);
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);
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);
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);
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);
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);
285 /* void __cilkrts_sync (__cilkrts_stack_frame *); */
286 cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun,
287 BUILT_IN_CILK_SYNC, false);
289 /* void __cilkrts_detach (__cilkrts_stack_frame *); */
290 cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun,
291 BUILT_IN_CILK_DETACH, false);
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;
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);
312 /* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */
314 static tree
315 get_frame_arg (tree call)
317 tree arg, argtype;
319 gcc_assert (call_expr_nargs (call) >= 1);
321 arg = CALL_EXPR_ARG (call, 0);
322 argtype = TREE_TYPE (arg);
323 gcc_assert (TREE_CODE (argtype) == POINTER_TYPE);
325 argtype = TREE_TYPE (argtype);
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;
334 /* Expands the __cilkrts_pop_frame function call stored in EXP. */
336 void
337 expand_builtin_cilk_pop_frame (tree exp)
339 tree frame = get_frame_arg (exp);
340 tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
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);
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;
353 /* Expands the cilk_detach function call stored in EXP. */
355 void
356 expand_builtin_cilk_detach (tree exp)
358 rtx_insn *insn;
359 tree fptr = get_frame_arg (exp);
361 if (fptr == NULL_TREE)
362 return;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
422 /* TMP <- WORKER.TAIL
423 *TMP <- PARENT
424 TMP <- TMP + 1
425 WORKER.TAIL <- TMP */
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)));
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).
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);
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. */
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);
474 /* Returns a setjmp CALL_EXPR with FRAME->context as its parameter. */
476 tree
477 cilk_call_setjmp (tree frame)
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);
484 /* This function will expand the _Cilk_sync keyword. */
486 static tree
487 expand_cilk_sync (void)
489 tree frame = cfun->cilk_frame_decl;
491 /* Cilk_sync is converted to the following code:
493 sf.pedigree = sf.worker->pedigree;
494 if (frame.flags & CILK_FRAME_UNSYNCHED)
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);
503 sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1; */
505 tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
507 tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
508 build_int_cst (TREE_TYPE (flags),
509 CILK_FRAME_UNSYNCHED));
511 unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
512 build_int_cst (TREE_TYPE (unsynched), 0));
514 tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
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));
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)));
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));
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;
561 /* Gimplifies the cilk_sync expression passed in *EXPR_P. Returns GS_ALL_DONE
562 when finished. */
564 void
565 gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p)
567 tree sync_expr = expand_cilk_sync ();
568 *expr_p = NULL_TREE;
569 gimplify_and_add (sync_expr, pre_p);