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