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