Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / 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-2015 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 "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.  */
69 tree 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
79 tree
80 cilk_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
95 tree
96 cilk_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
106 static tree
107 add_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
120 static tree
121 install_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
139 static tree
140 declare_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
164 void
165 cilk_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
334 static tree
335 get_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
356 void
357 expand_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
375 void
376 expand_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
447 tree
448 cilk_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
457 static tree
458 expand_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
535 void
536 gimplify_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 }