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