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