Added _Cilk_spawn and _Cilk_sync (2 cilk keywords) for C.

gcc/ChangeLog:
2013-10-29  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* builtins.c (is_builtin_name): Added a check for __cilkrts_detach and
	__cilkrts_pop_frame.  If matched, then return true for built-in
	function name.
	(expand_builtin): Added BUILT_IN_CILK_DETACH and
	BUILT_IN_CILK_POP_FRAME case.
	* langhooks-def.h (lhd_install_body_with_frame_cleanup): New prototype.
	(lhs_cilk_detect_spawn): Likewise.
	(LANG_HOOKS_DECLS): Added LANG_HOOKS_CILKPLUS.
	(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): New #define.
	(LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
	(LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): Likewise.
	(LANG_HOOKS_CILKPLUS): Likewise.
	* tree.h (CILK_SPAWN_FN): Likewise.
	* builtin.def (DEF_CILK_BUILTIN_STUB): Likewise.
	* Makefile.in (C_COMMON_OBJS): Added c-family/cilk.o.
	(OBJS): Added cilk-common.o.
	(CILK_H): Added a new define.
	(gimplify.o): Added CILK_H into dependency list.
	(builtins.o): Likewise.
	(ipa-inline.o): Likewise.
	(ipa-inline-analysis.o): Likewise.
	(BUILTINS_DEF): Added cilk-builtins.def.
	* langhooks.c (lhd_install_body_with_frame_cleanup): New function.
	(lhd_cilk_detect_spawn): Likewise.
	* langhooks.h (lang_hooks_for_cilkplus): New struct.
	(struct lang_hooks): Added new field called "cilkplus."
	* cilk-common.c: New file.
	* cilk.h: Likewise.
	* cilk-builtins.def: Likewise.
	* cppbuiltin.c (define_builtin_macros_for_compilation_flags): Added
	"__cilk" macro and set it to 200.
	* function.h (struct function::cilk_frame_decl): New field.
	(struct function::is_cilk_function): Likewise.
	(struct function::calls_cilk_spawn): Likewise.
	* gimplify.c (gimplify_call_expr): Added a check if the function call
	being gimplified is a spawn detach point.  If so, then add pop_frame
	and detach function calls.
	(gimplify_expr): Added a CILK_SPAWN_STMT and CILK_SYNC_STMT case
	for gimplifying _Cilk_spawn and _Cilk_sync statements.
	(gimplify_return_expr): Added a check for _Cilk_spawn usage in
	function.  If so, added a _Cilk_sync and gimplified it.
	(gimplify_modify_expr): Added a check for _Cilk_spawn in MODIFY and
	INIT_EXPRs.  If so, then call gimplify_cilk_spawn.
	* ipa-inline-analysis (initialize_inline_failed): Prevent inlining of
	spawner function.
	(can_inline_edge_p): Prevent inling of spawnee function.
	* ira.c (ira_setup_eliminable_regset): Force usage of frame pointer
	for functions that use Cilk keywords.
	* tree-inline.h (struct copy_body_data::remap_var_for_cilk): New field.
	* tree-pretty-print.c (dump_generic_node): Added CILK_SPAWN_STMT and
	CILK_SYNC_STMT cases.
	* tree.def (DEFTREECODE): Added CILK_SPAWN_STMT and CILK_SYNC_STMT
	trees.
	* generic.texi (CILK_SPAWN_STMT): Added documentation for _Cilk_spawn.
	(CILK_SYNC_STMT): Added documentation for _Cilk_sync.
	* passes.texi (Cilk Keywords): New section that describes the compiler
	code changes for handling Cilk Keywords.

gcc/c/ChangeLog:
2013-10-29  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-decl.c (finish_function): Added a call for insert_cilk_frame when
	a spawning function is found.
	* c-objc-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): New #define.
	(LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
	(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
	* c-parser.c (c_parser_statement_after_labels): Added RID_CILK_SYNC
	case.
	(c_parser_postfix_expression): Added RID_CILK_SPAWN case.
	* c-typeck.c (build_compound_expr): Reject _Cilk_spawn in a comma
	expr.
	(c_finish_return): Added a check to reject _Cilk_spawn in return
	expression.
	(build_cilk_spawn): New function.
	(build_cilk_sync): Likewise.
	* Makefile.in (c-decl.o): Added cilk.h in dependency list.

gcc/c-family/ChangeLog
2013-10-29  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-common.c (c_common_reswords[]): Added _Cilk_spawn and _Cilk_sync
	fields.
	(c_define_builtins): Called cilk_init_builtins if Cilk Plus is
	enabled.
	* c-common.h (enum rid): Added RID_CILK_SPAWN and RID_CILK_SYNC.
	(insert_cilk_frame): New prototype.
	(cilk_init_builtins): Likewise.
	(gimplify_cilk_spawn): Likewise.
	(c_cilk_install_body_w_frame_cleanup): Likewise.
	(cilk_detect_spawn_and_unwrap): Likewise.
	(cilk_set_spawn_marker): Likewise.
	(build_cilk_sync): Likewise.
	(build_cilk_spawn): Likewise.
	* cilk.c: New file.

gcc/lto/ChangeLog
2013-10-29  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* Make-lang.in (lto/lto-lang.o): Added cilk.h in dependency list.
	* lto-lang.c (lto_init): Added a call to cilk_init_builtins if Cilk
	Plus is enabled.

gcc/testsuite/ChangeLog
2013-10-29  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-c++-common/cilk-plus/CK/compound_cilk_spawn.c: New test.
	* c-c++-common/cilk-plus/CK/concec_cilk_spawn.c: Likewise.
	* c-c++-common/cilk-plus/CK/fib.c: Likewise.
	* c-c++-common/cilk-plus/CK/no_args_error.c: Likewise.
	* c-c++-common/cilk-plus/CK/spawnee_inline.c: Likewise.
	* c-c++-common/cilk-plus/CK/spawner_inline.c: Likewise.
	* c-c++-common/cilk-plus/CK/spawning_arg.c: Likewise.
	* c-c++-common/cilk-plus/CK/steal_check.c: Likewise.
	* c-c++-common/cilk-plus/CK/test__cilk.c: Likewise.
	* c-c++-common/cilk-plus/CK/varargs_test.c: Likewise.
	* c-c++-common/cilk-plus/CK/sync_wo_spawn.c: Likewise.
	* c-c++-common/cilk-plus/CK/invalid_spawn.c: Likewise.
	* c-c++-common/cilk-plus/CK/spawn_in_return.c: Likewise.
	* c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Likewise.
	* c-c++-common/cilk-plus/CK/fib_no_sync.c: Likewise.
	* c-c++-common/cilk-plus/CK/fib_no_return.c: Likewise.
	* gcc.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords
	test stored in c-c++-common.  Also, added the Cilk runtime's library
	to the ld_library_path.

From-SVN: r204172
This commit is contained in:
Balaji V. Iyer 2013-10-29 18:36:31 +00:00 committed by Balaji V. Iyer
parent 67348ccc9c
commit 939b37da6d
51 changed files with 3004 additions and 8 deletions

View File

@ -1,3 +1,58 @@
2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
* builtins.c (is_builtin_name): Added a check for __cilkrts_detach and
__cilkrts_pop_frame. If matched, then return true for built-in
function name.
(expand_builtin): Added BUILT_IN_CILK_DETACH and
BUILT_IN_CILK_POP_FRAME case.
* langhooks-def.h (lhd_install_body_with_frame_cleanup): New prototype.
(lhs_cilk_detect_spawn): Likewise.
(LANG_HOOKS_DECLS): Added LANG_HOOKS_CILKPLUS.
(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): New #define.
(LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
(LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): Likewise.
(LANG_HOOKS_CILKPLUS): Likewise.
* tree.h (CILK_SPAWN_FN): Likewise.
* builtin.def (DEF_CILK_BUILTIN_STUB): Likewise.
* Makefile.in (C_COMMON_OBJS): Added c-family/cilk.o.
(OBJS): Added cilk-common.o.
(BUILTINS_DEF): Added cilk-builtins.def.
* langhooks.c (lhd_install_body_with_frame_cleanup): New function.
(lhd_cilk_detect_spawn): Likewise.
* langhooks.h (lang_hooks_for_cilkplus): New struct.
(struct lang_hooks): Added new field called "cilkplus."
* cilk-common.c: New file.
* cilk.h: Likewise.
* cilk-builtins.def: Likewise.
* cppbuiltin.c (define_builtin_macros_for_compilation_flags): Added
"__cilk" macro and set it to 200.
* function.h (struct function::cilk_frame_decl): New field.
(struct function::is_cilk_function): Likewise.
(struct function::calls_cilk_spawn): Likewise.
* gimplify.c (gimplify_call_expr): Added a check if the function call
being gimplified is a spawn detach point. If so, then add pop_frame
and detach function calls.
(gimplify_expr): Added a CILK_SPAWN_STMT and CILK_SYNC_STMT case
for gimplifying _Cilk_spawn and _Cilk_sync statements.
(gimplify_return_expr): Added a check for _Cilk_spawn usage in
function. If so, added a _Cilk_sync and gimplified it.
(gimplify_modify_expr): Added a check for _Cilk_spawn in MODIFY and
INIT_EXPRs. If so, then call gimplify_cilk_spawn.
* ipa-inline-analysis (initialize_inline_failed): Prevent inlining of
spawner function.
(can_inline_edge_p): Prevent inling of spawnee function.
* ira.c (ira_setup_eliminable_regset): Force usage of frame pointer
for functions that use Cilk keywords.
* tree-inline.h (struct copy_body_data::remap_var_for_cilk): New field.
* tree-pretty-print.c (dump_generic_node): Added CILK_SPAWN_STMT and
CILK_SYNC_STMT cases.
* tree.def (DEFTREECODE): Added CILK_SPAWN_STMT and CILK_SYNC_STMT
trees.
* generic.texi (CILK_SPAWN_STMT): Added documentation for _Cilk_spawn.
(CILK_SYNC_STMT): Added documentation for _Cilk_sync.
* passes.texi (Cilk Keywords): New section that describes the compiler
code changes for handling Cilk Keywords.
2013-10-29 David Malcolm <dmalcolm@redhat.com>
Patch autogenerated by refactor_symtab.py from

View File

@ -872,7 +872,7 @@ RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
PARAMS_H = params.h params.def
BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
gtm-builtins.def sanitizer.def cilkplus.def
gtm-builtins.def sanitizer.def cilkplus.def cilk-builtins.def
INTERNAL_FN_DEF = internal-fn.def
INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
TREE_CORE_H = tree-core.h coretypes.h all-tree.def tree.def \
@ -1137,7 +1137,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
c-family/c-semantics.o c-family/c-ada-spec.o \
c-family/array-notation-common.o c-family/c-ubsan.o
c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o
# Language-independent object files.
# We put the insn-*.o files first so that a parallel make will build
@ -1182,6 +1182,7 @@ OBJS = \
cgraphbuild.o \
cgraphunit.o \
cgraphclones.o \
cilk-common.o \
combine.o \
combine-stack-adj.o \
compare-elim.o \

View File

@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "builtins.h"
#include "ubsan.h"
#include "cilk.h"
static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
@ -235,6 +236,10 @@ is_builtin_name (const char *name)
return true;
if (strncmp (name, "__atomic_", 9) == 0)
return true;
if (flag_enable_cilkplus
&& (!strcmp (name, "__cilkrts_detach")
|| !strcmp (name, "__cilkrts_pop_frame")))
return true;
return false;
}
@ -6685,6 +6690,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
expand_builtin_set_thread_pointer (exp);
return const0_rtx;
case BUILT_IN_CILK_DETACH:
expand_builtin_cilk_detach (exp);
return const0_rtx;
case BUILT_IN_CILK_POP_FRAME:
expand_builtin_cilk_pop_frame (exp);
return const0_rtx;
default: /* just do library call, if unknown builtin */
break;
}

View File

@ -147,6 +147,13 @@ along with GCC; see the file COPYING3. If not see
false, true, true, ATTRS, false, \
(flag_openmp || flag_tree_parallelize_loops))
/* Builtin used by implementation of Cilk Plus. Most of these are decomposed
by the compiler but a few are implemented in libcilkrts. */
#undef DEF_CILK_BUILTIN_STUB
#define DEF_CILK_BUILTIN_STUB(ENUM, NAME) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \
false, ATTR_LAST, false, false)
/* Builtin used by the implementation of GNU TM. These
functions are mapped to the actual implementation of the STM library. */
#undef DEF_TM_BUILTIN
@ -846,6 +853,9 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
/* OpenMP builtins. */
#include "omp-builtins.def"
/* Cilk keywords builtins. */
#include "cilk-builtins.def"
/* GTM builtins. */
#include "gtm-builtins.def"

View File

@ -1,3 +1,20 @@
2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-common.c (c_common_reswords[]): Added _Cilk_spawn and _Cilk_sync
fields.
(c_define_builtins): Called cilk_init_builtins if Cilk Plus is
enabled.
* c-common.h (enum rid): Added RID_CILK_SPAWN and RID_CILK_SYNC.
(insert_cilk_frame): New prototype.
(cilk_init_builtins): Likewise.
(gimplify_cilk_spawn): Likewise.
(c_cilk_install_body_w_frame_cleanup): Likewise.
(cilk_detect_spawn_and_unwrap): Likewise.
(cilk_set_spawn_marker): Likewise.
(build_cilk_sync): Likewise.
(build_cilk_spawn): Likewise.
* cilk.c: New file.
2013-10-29 David Malcolm <dmalcolm@redhat.com>
Patch autogenerated by refactor_symtab.py from

View File

@ -409,6 +409,8 @@ const struct c_common_resword c_common_reswords[] =
{ "_Alignof", RID_ALIGNOF, D_CONLY },
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
{ "_Cilk_spawn", RID_CILK_SPAWN, 0 },
{ "_Cilk_sync", RID_CILK_SYNC, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
{ "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
@ -5219,6 +5221,9 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
targetm.init_builtins ();
build_common_builtin_nodes ();
if (flag_enable_cilkplus)
cilk_init_builtins ();
}
/* Like get_identifier, but avoid warnings about null arguments when

View File

@ -148,6 +148,9 @@ enum rid
/* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
/* Cilk Plus keywords. */
RID_CILK_SPAWN, RID_CILK_SYNC,
/* Objective-C ("AT" reserved words - they are only keywords when
they follow '@') */
RID_AT_ENCODE, RID_AT_END,
@ -1356,4 +1359,18 @@ extern void cilkplus_extract_an_triplets (vec<tree, va_gc> *, size_t, size_t,
vec<vec<an_parts> > *);
extern vec <tree, va_gc> *fix_sec_implicit_args
(location_t, vec <tree, va_gc> *, vec<an_loop_parts>, size_t, tree);
/* In cilk.c. */
extern tree insert_cilk_frame (tree);
extern void cilk_init_builtins (void);
extern int gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *);
extern void c_cilk_install_body_w_frame_cleanup (tree, tree);
extern bool cilk_detect_spawn_and_unwrap (tree *);
extern bool cilk_set_spawn_marker (location_t, tree);
extern tree build_cilk_sync (void);
extern tree build_cilk_spawn (location_t, tree);
extern tree make_cilk_frame (tree);
extern tree create_cilk_function_exit (tree, bool, bool);
extern tree cilk_install_body_pedigree_operations (tree);
#endif /* ! GCC_C_COMMON_H */

1305
gcc/c-family/cilk.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,21 @@
2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-decl.c (finish_function): Added a call for insert_cilk_frame when
a spawning function is found.
* c-objc-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): New #define.
(LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
* c-parser.c (c_parser_statement_after_labels): Added RID_CILK_SYNC
case.
(c_parser_postfix_expression): Added RID_CILK_SPAWN case.
* c-typeck.c (build_compound_expr): Reject _Cilk_spawn in a comma
expr.
(c_finish_return): Added a check to reject _Cilk_spawn in return
expression.
(build_cilk_spawn): New function.
(build_cilk_sync): Likewise.
* Makefile.in (c-decl.o): Added cilk.h in dependency list.
2013-10-27 Tobias Burnus <burnus@net-b.de>
PR other/33426

View File

@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "pointer-set.h"
#include "plugin.h"
#include "c-family/c-ada-spec.h"
#include "cilk.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@ -8447,6 +8448,12 @@ finish_function (void)
/* Tie off the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
/* If the function has _Cilk_spawn in front of a function call inside it
i.e. it is a spawning function, then add the appropriate Cilk plus
functions inside. */
if (fn_contains_cilk_spawn_p (cfun))
cfun->cilk_frame_decl = insert_cilk_frame (fndecl);
finish_fname_decls ();
/* Complain if there's just no return statement. */

View File

@ -105,4 +105,13 @@ along with GCC; see the file COPYING3. If not see
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
#undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN
#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn
#undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP
#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP c_cilk_install_body_w_frame_cleanup
#undef LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP
#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP \
cilk_detect_spawn_and_unwrap
#endif /* GCC_C_OBJC_COMMON */

View File

@ -4587,6 +4587,14 @@ c_parser_statement_after_labels (c_parser *parser)
case RID_FOR:
c_parser_for_statement (parser, false);
break;
case RID_CILK_SYNC:
c_parser_consume_token (parser);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
if (!flag_enable_cilkplus)
error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>");
else
add_stmt (build_cilk_sync ());
break;
case RID_GOTO:
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
@ -7174,6 +7182,30 @@ c_parser_postfix_expression (c_parser *parser)
case RID_GENERIC:
expr = c_parser_generic_selection (parser);
break;
case RID_CILK_SPAWN:
c_parser_consume_token (parser);
if (!flag_enable_cilkplus)
{
error_at (loc, "-fcilkplus must be enabled to use "
"%<_Cilk_spawn%>");
expr = c_parser_postfix_expression (parser);
expr.value = error_mark_node;
}
if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
{
error_at (loc, "consecutive %<_Cilk_spawn%> keywords "
"are not permitted");
/* Now flush out all the _Cilk_spawns. */
while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
c_parser_consume_token (parser);
expr = c_parser_postfix_expression (parser);
}
else
{
expr = c_parser_postfix_expression (parser);
expr.value = build_cilk_spawn (loc, expr.value);
}
break;
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;

View File

@ -4387,6 +4387,14 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
tree eptype = NULL_TREE;
tree ret;
if (flag_enable_cilkplus
&& (TREE_CODE (expr1) == CILK_SPAWN_STMT
|| TREE_CODE (expr2) == CILK_SPAWN_STMT))
{
error_at (loc,
"spawned function call cannot be part of a comma expression");
return error_mark_node;
}
expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1);
if (expr1_int_operands)
expr1 = remove_c_maybe_const_expr (expr1);
@ -8694,6 +8702,12 @@ c_finish_return (location_t loc, tree retval, tree origtype)
return error_mark_node;
}
}
if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
{
error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
"allowed");
return error_mark_node;
}
if (retval)
{
tree semantic_type = NULL_TREE;

33
gcc/cilk-builtins.def Normal file
View File

@ -0,0 +1,33 @@
/* This file contains the definitions and documentation for the
Cilk Plus builtins used in the GNU compiler.
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>
Intel Corporation.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME, "__cilkrts_enter_frame_1")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME_FAST,
"__cilkrts_enter_frame_fast_1")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_DETACH, "__cilkrts_detach")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_RETHROW, "__cilkrts_rethrow")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNCHED, "__cilkrts_synched")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNC, "__cilkrts_sync")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_LEAVE_FRAME, "__cilkrts_leave_frame")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_POP_FRAME, "__cilkrts_pop_frame")
DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SAVE_FP, "__cilkrts_save_fp_ctrl_state")

484
gcc/cilk-common.c Normal file
View File

@ -0,0 +1,484 @@
/* This file is part of the Intel(R) Cilk(TM) Plus support
This file contains the CilkPlus Intrinsics
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
Intel Corporation
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "langhooks.h"
#include "expr.h"
#include "optabs.h"
#include "recog.h"
#include "tree-iterator.h"
#include "gimple.h"
#include "cilk.h"
/* This structure holds all the important fields of the internal structures,
internal built-in functions, and Cilk-specific data types. Explanation of
all the these fielsd are given in cilk.h. */
tree cilk_trees[(int) CILK_TI_MAX];
/* Returns the value in structure FRAME pointed by the FIELD_NUMBER
(e.g. X.y).
FIELD_NUMBER is an index to the structure FRAME_PTR. For details
about these fields, refer to cilk_trees structure in cilk.h and
cilk_init_builtins function in this file. Returns a TREE that is the type
of the field represented by FIELD_NUMBER. If VOLATIL parameter is set
to true then the returning field is set as volatile. */
tree
cilk_dot (tree frame, int field_number, bool volatil)
{
tree field = cilk_trees[field_number];
field = fold_build3 (COMPONENT_REF, TREE_TYPE (field), frame, field,
NULL_TREE);
TREE_THIS_VOLATILE (field) = volatil;
return field;
}
/* Returns the address of a field in FRAME_PTR, pointed by FIELD_NUMBER.
(e.g. (&X)->y). Please see cilk_dot function for explanation of the
FIELD_NUMBER. Returns a tree that is the type of the field represented
by FIELD_NUMBER. If VOLATIL parameter is set to true then the returning
field is set as volatile. */
tree
cilk_arrow (tree frame_ptr, int field_number, bool volatil)
{
return cilk_dot (fold_build1 (INDIRECT_REF,
TREE_TYPE (TREE_TYPE (frame_ptr)), frame_ptr),
field_number, volatil);
}
/* This function will add FIELD of type TYPE to a defined built-in
structure. *NAME is the name of the field to be added. */
static tree
add_field (const char *name, tree type, tree fields)
{
tree t = get_identifier (name);
tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, t, type);
TREE_CHAIN (field) = fields;
return field;
}
/* This function will define a built-in function of NAME, of type FNTYPE and
register it under the built-in function code CODE. If PUBLISH is set then
the declaration is pushed into the declaration list. CODE is the index
to the cilk_trees array. *NAME is the name of the function to be added. */
static tree
install_builtin (const char *name, tree fntype, enum built_in_function code,
bool publish)
{
tree fndecl = build_fn_decl (name, fntype);
DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL;
DECL_FUNCTION_CODE (fndecl) = code;
if (publish)
{
tree t = lang_hooks.decls.pushdecl (fndecl);
if (t)
fndecl = t;
}
set_builtin_decl (code, fndecl, true);
return fndecl;
}
/* Creates and initializes all the built-in Cilk keywords functions and three
structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker.
Detailed information about __cilkrts_stack_frame and
__cilkrts_worker structures are given in libcilkrts/include/internal/abi.h.
__cilkrts_pedigree is described in libcilkrts/include/cilk/common.h. */
void
cilk_init_builtins (void)
{
/* Now build the following __cilkrts_pedigree struct:
struct __cilkrts_pedigree {
uint64_t rank;
struct __cilkrts_pedigree *parent;
} */
tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE);
tree pedigree_ptr = build_pointer_type (pedigree_type);
tree field = add_field ("rank", uint64_type_node, NULL_TREE);
cilk_trees[CILK_TI_PEDIGREE_RANK] = field;
field = add_field ("parent", pedigree_ptr, field);
cilk_trees[CILK_TI_PEDIGREE_PARENT] = field;
finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field,
NULL_TREE);
lang_hooks.types.register_builtin_type (pedigree_type,
"__cilkrts_pedigree_t");
cilk_pedigree_type_decl = pedigree_type;
/* Build the Cilk Stack Frame:
struct __cilkrts_stack_frame {
uint32_t flags;
uint32_t size;
struct __cilkrts_stack_frame *call_parent;
__cilkrts_worker *worker;
void *except_data;
void *ctx[4];
uint32_t mxcsr;
uint16_t fpcsr;
uint16_t reserved;
__cilkrts_pedigree pedigree;
}; */
tree frame = lang_hooks.types.make_type (RECORD_TYPE);
tree frame_ptr = build_pointer_type (frame);
tree worker_type = lang_hooks.types.make_type (RECORD_TYPE);
tree worker_ptr = build_pointer_type (worker_type);
tree s_type_node = build_int_cst (size_type_node, 4);
tree flags = add_field ("flags", uint32_type_node, NULL_TREE);
tree size = add_field ("size", uint32_type_node, flags);
tree parent = add_field ("call_parent", frame_ptr, size);
tree worker = add_field ("worker", worker_ptr, parent);
tree except = add_field ("except_data", frame_ptr, worker);
tree context = add_field ("ctx",
build_array_type (ptr_type_node,
build_index_type (s_type_node)),
except);
tree mxcsr = add_field ("mxcsr", uint32_type_node, context);
tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr);
tree reserved = add_field ("reserved", uint16_type_node, fpcsr);
tree pedigree = add_field ("pedigree", pedigree_type, reserved);
/* Now add them to a common structure whose fields are #defined to something
that is used at a later stage. */
cilk_trees[CILK_TI_FRAME_FLAGS] = flags;
cilk_trees[CILK_TI_FRAME_PARENT] = parent;
cilk_trees[CILK_TI_FRAME_WORKER] = worker;
cilk_trees[CILK_TI_FRAME_EXCEPTION] = except;
cilk_trees[CILK_TI_FRAME_CONTEXT] = context;
/* We don't care about reserved, so no need to store it in cilk_trees. */
cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree;
TREE_ADDRESSABLE (frame) = 1;
finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE);
cilk_frame_type_decl = frame;
lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t");
cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr,
TYPE_QUAL_VOLATILE);
/* Now let's do the following worker struct:
struct __cilkrts_worker {
__cilkrts_stack_frame *volatile *volatile tail;
__cilkrts_stack_frame *volatile *volatile head;
__cilkrts_stack_frame *volatile *volatile exc;
__cilkrts_stack_frame *volatile *volatile protected_tail;
__cilkrts_stack_frame *volatile *ltq_limit;
int32_t self;
global_state_t *g;
local_state *l;
cilkred_map *reducer_map;
__cilkrts_stack_frame *current_stack_frame;
void *reserved;
__cilkrts_worker_sysdep_state *sysdep;
__cilkrts_pedigree pedigree;
} */
tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE);
tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type);
tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr,
TYPE_QUAL_VOLATILE);
tree g = lang_hooks.types.make_type (RECORD_TYPE);
finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE);
tree l = lang_hooks.types.make_type (RECORD_TYPE);
finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE);
tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE);
finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE,
NULL_TREE);
field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE);
cilk_trees[CILK_TI_WORKER_TAIL] = field;
field = add_field ("head", fptr_vol_ptr_vol, field);
field = add_field ("exc", fptr_vol_ptr_vol, field);
field = add_field ("protected_tail", fptr_vol_ptr_vol, field);
field = add_field ("ltq_limit", fptr_volatile_ptr, field);
field = add_field ("self", integer_type_node, field);
field = add_field ("g", build_pointer_type (g), field);
field = add_field ("l", build_pointer_type (g), field);
field = add_field ("reducer_map", ptr_type_node, field);
field = add_field ("current_stack_frame", frame_ptr, field);
cilk_trees[CILK_TI_WORKER_CUR] = field;
field = add_field ("saved_protected_tail", fptr_volatile_ptr, field);
field = add_field ("sysdep", build_pointer_type (sysdep_t), field);
field = add_field ("pedigree", pedigree_type, field);
cilk_trees[CILK_TI_WORKER_PEDIGREE] = field;
finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field,
NULL_TREE);
tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node);
tree fptr_fun = build_function_type (void_type_node, fptr_arglist);
/* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */
cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun,
BUILT_IN_CILK_ENTER_FRAME, false);
/* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */
cilk_enter_fast_fndecl =
install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun,
BUILT_IN_CILK_ENTER_FRAME_FAST, false);
/* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */
cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
BUILT_IN_CILK_POP_FRAME, false);
/* void __cilkrts_leave_frame (__cilkrts_stack_frame *); */
cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun,
BUILT_IN_CILK_LEAVE_FRAME, false);
/* void __cilkrts_sync (__cilkrts_stack_frame *); */
cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun,
BUILT_IN_CILK_SYNC, false);
/* void __cilkrts_detach (__cilkrts_stack_frame *); */
cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun,
BUILT_IN_CILK_DETACH, false);
/* __cilkrts_rethrow (struct stack_frame *); */
cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun,
BUILT_IN_CILK_RETHROW, false);
/* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */
cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state",
fptr_fun, BUILT_IN_CILK_SAVE_FP,
false);
}
/* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */
static tree
get_frame_arg (tree call)
{
tree arg, argtype;
gcc_assert (call_expr_nargs (call) >= 1);
arg = CALL_EXPR_ARG (call, 0);
argtype = TREE_TYPE (arg);
gcc_assert (TREE_CODE (argtype) == POINTER_TYPE);
argtype = TREE_TYPE (argtype);
gcc_assert (!lang_hooks.types_compatible_p
|| lang_hooks.types_compatible_p (argtype, cilk_frame_type_decl));
/* If it is passed in as an address, then just use the value directly
since the function is inlined. */
if (TREE_CODE (arg) == INDIRECT_REF || TREE_CODE (arg) == ADDR_EXPR)
return TREE_OPERAND (arg, 0);
return arg;
}
/* Expands the __cilkrts_pop_frame function call stored in EXP. */
void
expand_builtin_cilk_pop_frame (tree exp)
{
tree frame = get_frame_arg (exp);
tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
tree clear_parent = build2 (MODIFY_EXPR, void_type_node, parent,
build_int_cst (TREE_TYPE (parent), 0));
expand_expr (clear_parent, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* During LTO, the is_cilk_function flag gets cleared.
If __cilkrts_pop_frame is called, then this definitely must be a
cilk function. */
if (cfun)
cfun->is_cilk_function = 1;
}
/* Expands the cilk_detach function call stored in EXP. */
void
expand_builtin_cilk_detach (tree exp)
{
rtx insn;
tree fptr = get_frame_arg (exp);
if (fptr == NULL_TREE)
return;
tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0);
tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0);
tree tail = cilk_dot (worker, CILK_TI_WORKER_TAIL, 1);
rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL);
if (GET_CODE (wreg) != REG)
wreg = copy_to_reg (wreg);
rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL);
/* TMP <- WORKER.TAIL
*TMP <- PARENT
TMP <- TMP + 1
WORKER.TAIL <- TMP */
HOST_WIDE_INT worker_tail_offset =
tree_low_cst (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) +
tree_low_cst (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) /
BITS_PER_UNIT;
rtx tmem0 = gen_rtx_MEM (Pmode,
plus_constant (Pmode, wreg, worker_tail_offset));
set_mem_attributes (tmem0, tail, 0);
MEM_NOTRAP_P (tmem0) = 1;
gcc_assert (MEM_VOLATILE_P (tmem0));
rtx treg = copy_to_mode_reg (Pmode, tmem0);
rtx tmem1 = gen_rtx_MEM (Pmode, treg);
set_mem_attributes (tmem1, TREE_TYPE (TREE_TYPE (tail)), 0);
MEM_NOTRAP_P (tmem1) = 1;
emit_move_insn (tmem1, preg);
emit_move_insn (treg, plus_constant (Pmode, treg, GET_MODE_SIZE (Pmode)));
/* There is a release barrier (st8.rel, membar #StoreStore,
sfence, lwsync, etc.) between the two stores. On x86
normal volatile stores have proper semantics; the sfence
would only be needed for nontemporal stores (which we
could generate using the storent optab, for no benefit
in this case).
The predicate may return false even for a REG if this is
the limited release operation that only stores 0. */
enum insn_code icode = direct_optab_handler (sync_lock_release_optab, Pmode);
if (icode != CODE_FOR_nothing
&& insn_data[icode].operand[1].predicate (treg, Pmode)
&& (insn = GEN_FCN (icode) (tmem0, treg)) != NULL_RTX)
emit_insn (insn);
else
emit_move_insn (tmem0, treg);
/* The memory barrier inserted above should not prevent
the load of flags from being moved before the stores,
but in practice it does because it is implemented with
unspec_volatile. In-order RISC machines should
explicitly load flags earlier. */
tree flags = cilk_dot (fptr, CILK_TI_FRAME_FLAGS, 0);
expand_expr (build2 (MODIFY_EXPR, void_type_node, flags,
build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
build_int_cst (TREE_TYPE (flags),
CILK_FRAME_DETACHED))),
const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Returns a setjmp CALL_EXPR with FRAME->context as its parameter. */
tree
cilk_call_setjmp (tree frame)
{
tree c = cilk_dot (frame, CILK_TI_FRAME_CONTEXT, false);
c = build1 (ADDR_EXPR, build_pointer_type (ptr_type_node), c);
return build_call_expr (builtin_decl_implicit (BUILT_IN_SETJMP), 1, c);
}
/* This function will expand the _Cilk_sync keyword. */
static tree
expand_cilk_sync (void)
{
tree frame = cfun->cilk_frame_decl;
/* Cilk_sync is converted to the following code:
sf.pedigree = sf.worker->pedigree;
if (frame.flags & CILK_FRAME_UNSYNCHED)
{
__cilkrts_save_fp_state (&sf);
if (!builtin_setjmp (sf.ctx)
__cilkrts_sync (&sf);
else
if (sf.flags & CILK_FRAME_EXCEPTING)
__cilkrts_rethrow (&sf);
}
sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1; */
tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
build_int_cst (TREE_TYPE (flags),
CILK_FRAME_UNSYNCHED));
unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
build_int_cst (TREE_TYPE (unsynched), 0));
tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
/* Check if exception (0x10) bit is set in the sf->flags. */
tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
build_int_cst (TREE_TYPE (flags),
CILK_FRAME_EXCEPTING));
except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
build_int_cst (TREE_TYPE (except_flag), 0));
/* If the exception flag is set then call the __cilkrts_rethrow (&sf). */
tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
build_call_expr (cilk_rethrow_fndecl, 1,
frame_addr),
build_empty_stmt (EXPR_LOCATION (unsynched)));
tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
tree setjmp_expr = cilk_call_setjmp (frame);
setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
build_int_cst (TREE_TYPE (setjmp_expr), 0));
setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
sync_expr, except_cond);
tree sync_list = alloc_stmt_list ();
append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1,
frame_addr), &sync_list);
append_to_statement_list (setjmp_expr, &sync_list);
tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list,
build_empty_stmt (EXPR_LOCATION (unsynched)));
tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false);
tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false);
tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false);
tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node,
parent_pedigree, worker_pedigree);
tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree),
CILK_TI_PEDIGREE_RANK, false);
tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank),
w_ped_rank,
build_one_cst (TREE_TYPE (w_ped_rank)));
incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank,
incr_ped_rank);
tree ret_sync_exp = alloc_stmt_list ();
append_to_statement_list (assign_pedigree, &ret_sync_exp);
append_to_statement_list (sync, &ret_sync_exp);
append_to_statement_list (incr_ped_rank, &ret_sync_exp);
return ret_sync_exp;
}
/* Gimplifies the cilk_sync expression passed in *EXPR_P. Returns GS_ALL_DONE
when finished. */
void
gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p)
{
tree sync_expr = expand_cilk_sync ();
*expr_p = NULL_TREE;
gimplify_and_add (sync_expr, pre_p);
}

102
gcc/cilk.h Normal file
View File

@ -0,0 +1,102 @@
/* This file is part of the Intel(R) Cilk(TM) Plus support
This file contains Cilk Support files.
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
Intel Corporation
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_CILK_H
#define GCC_CILK_H
/* Frame status bits known to compiler. */
#define CILK_FRAME_UNSYNCHED 0x02
#define CILK_FRAME_DETACHED 0x04
#define CILK_FRAME_EXCEPTING 0x10
#define CILK_FRAME_VERSION (1 << 24)
enum cilk_tree_index {
/* All the built-in functions for Cilk keywords. */
CILK_TI_F_WORKER = 0, /* __cilkrts_get_worker (). */
CILK_TI_F_SYNC, /* __cilkrts_sync (). */
CILK_TI_F_DETACH, /* __cilkrts_detach (...). */
CILK_TI_F_ENTER, /* __cilkrts_enter_frame (...). */
CILK_TI_F_ENTER_FAST, /* __cilkrts_enter_frame_fast (.). */
CILK_TI_F_LEAVE, /* __cilkrts_leave_frame (...). */
CILK_TI_F_POP, /* __cilkrts_pop_frame (...). */
CILK_TI_F_RETHROW, /* __cilkrts_rethrow (...). */
CILK_TI_F_SAVE_FP, /* __cilkrts_save_fp_ctrl_state (...). */
/* __cilkrts_stack_frame struct fields. */
CILK_TI_FRAME_FLAGS, /* stack_frame->flags. */
CILK_TI_FRAME_PARENT, /* stack_frame->parent. */
CILK_TI_FRAME_WORKER, /* stack_frame->worker. */
CILK_TI_FRAME_EXCEPTION, /* stack_frame->except_data. */
CILK_TI_FRAME_CONTEXT, /* stack_frame->context[4]. */
CILK_TI_FRAME_PEDIGREE, /* stack_frame->pedigree. */
/* __cilkrts_worker struct fields. */
CILK_TI_WORKER_CUR, /* worker->current_stack_frame. */
CILK_TI_WORKER_TAIL, /* worker->tail. */
CILK_TI_WORKER_PEDIGREE, /* worker->pedigree. */
/* __cilkrts_pedigree struct fields. */
CILK_TI_PEDIGREE_RANK, /* pedigree->rank. */
CILK_TI_PEDIGREE_PARENT, /* pedigree->parent. */
/* Types. */
CILK_TI_FRAME_TYPE, /* struct __cilkrts_stack_frame. */
CILK_TI_FRAME_PTR, /* __cilkrts_stack_frame *. */
CILK_TI_WORKER_TYPE, /* struct __cilkrts_worker. */
CILK_TI_PEDIGREE_TYPE, /* struct __cilkrts_pedigree. */
CILK_TI_MAX
};
extern GTY (()) tree cilk_trees[CILK_TI_MAX];
#define cilk_worker_fndecl cilk_trees[CILK_TI_F_WORKER]
#define cilk_sync_fndecl cilk_trees[CILK_TI_F_SYNC]
#define cilk_synched_fndecl cilk_trees[CILK_TI_F_SYNCED]
#define cilk_detach_fndecl cilk_trees[CILK_TI_F_DETACH]
#define cilk_enter_fndecl cilk_trees[CILK_TI_F_ENTER]
#define cilk_enter_fast_fndecl cilk_trees[CILK_TI_F_ENTER_FAST]
#define cilk_leave_fndecl cilk_trees[CILK_TI_F_LEAVE]
#define cilk_rethrow_fndecl cilk_trees[CILK_TI_F_RETHROW]
#define cilk_pop_fndecl cilk_trees[CILK_TI_F_POP]
#define cilk_save_fp_fndecl cilk_trees[CILK_TI_F_SAVE_FP]
#define cilk_worker_type_fndecl cilk_trees[CILK_TI_WORKER_TYPE]
#define cilk_frame_type_decl cilk_trees[CILK_TI_FRAME_TYPE]
#define cilk_frame_ptr_type_decl cilk_trees[CILK_TI_FRAME_PTR]
#define cilk_pedigree_type_decl cilk_trees[CILK_TI_PEDIGREE_TYPE]
extern void expand_builtin_cilk_detach (tree);
extern void expand_builtin_cilk_pop_frame (tree);
extern tree cilk_arrow (tree, int, bool);
extern tree cilk_dot (tree, int, bool);
extern void cilk_init_builtins (void);
extern void gimplify_cilk_sync (tree *, gimple_seq *);
extern tree cilk_call_setjmp (tree);
/* Returns true if Cilk Plus is enabled and if F->cilk_frame_decl is not
NULL_TREE. */
inline bool
fn_contains_cilk_spawn_p (function *f)
{
return (flag_enable_cilkplus
&& (f->calls_cilk_spawn || f->cilk_frame_decl != NULL_TREE));
}
#endif

View File

@ -105,6 +105,8 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile)
cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d",
flag_finite_math_only);
if (flag_enable_cilkplus)
cpp_define (pfile, "__cilk=200");
}

View File

@ -3166,6 +3166,30 @@ several statements chained together.
Used to represent a @code{break} statement. There are no additional
fields.
@item CILK_SPAWN_STMT
Used to represent a spawning function in the Cilk Plus language extension.
This tree has one field that holds the name of the spawning function.
@code{_Cilk_spawn} can be written in C in the following way:
@smallexample
@code{_Cilk_spawn} <function_name> (<parameters>);
@end smallexample
Detailed description for usage and functionality of @code{_Cilk_spawn} can be
found at http://www.cilkplus.org
@item CILK_SYNC_STMT
This statement is part of the Cilk Plus language extension. It indicates that
the current function cannot continue in parallel with its spawned children.
There are no additional fields. @code{_Cilk_sync} can be written in C in the
following way:
@smallexample
@code{_Cilk_sync};
@end smallexample
@item CLEANUP_STMT
Used to represent an action that should take place upon exit from the

View File

@ -124,13 +124,45 @@ true, then we expand them using either @code{expand_array_notation_exprs} or
inside conditions, they are transformed using the function
@code{fix_conditional_array_notations}. The C language-specific routines are
located in @file{c/c-array-notation.c} and the equivalent C++ routines are in
file @file{cp/cp-array-notation.c}. Common routines such as functions to
initialize builtin functions are stored in @file{array-notation-common.c}.
the file @file{cp/cp-array-notation.c}. Common routines such as functions to
initialize built-in functions are stored in @file{array-notation-common.c}.
@item Cilk keywords:
@itemize @bullet
@item @code{_Cilk_spawn}:
The @code{_Cilk_spawn} keyword is parsed and the function it contains is marked
as a spawning function. The spawning function is called the spawner. At
the end of the parsing phase, appropriate built-in functions are
added to the spawner that are defined in the Cilk runtime. The appropriate
locations of these functions, and the internal structures are detailed in
@code{cilk_init_builtins} in the file @file{cilk-common.c}. The pointers to
Cilk functions and fields of internal structures are described
in @file{cilk.h}. The built-in functions are described in
@file{cilk-builtins.def}.
During gimplification, a new "spawn-helper" function is created.
The spawned function is replaced with a spawn helper function in the spawner.
The spawned function-call is moved into the spawn helper. The main function
that does these transformations is @code{gimplify_cilk_spawn} in
@file{c-family/cilk.c}. In the spawn-helper, the gimplification function
@code{gimplify_call_expr}, inserts a function call @code{__cilkrts_detach}.
This function is expanded by @code{builtin_expand_cilk_detach} located in
@file{c-family/cilk.c}.
@item @code{_Cilk_sync}:
@code{_Cilk_sync} is parsed like a keyword. During gimplification,
the function @code{gimplify_cilk_sync} in @file{c-family/cilk.c}, will replace
this keyword with a set of functions that are stored in the Cilk runtime.
One of the internal functions inserted during gimplification,
@code{__cilkrts_pop_frame} must be expanded by the compiler and is
done by @code{builtin_expand_cilk_pop_frame} in @file{cilk-common.c}.
@end itemize
@end itemize
Detailed information about Cilk Plus and language specification is provided in
@w{@uref{http://www.cilkplus.org/}}. It is worth mentioning that the current
implementation follows ABI 0.9.
Documentation about Cilk Plus and language specification is provided under the
"Learn" section in @w{@uref{http://www.cilkplus.org/}}. It is worth mentioning
that the current implementation follows ABI 1.1.
@node Gimplification pass
@section Gimplification pass

View File

@ -552,6 +552,9 @@ struct GTY(()) function {
/* Vector of function local variables, functions, types and constants. */
vec<tree, va_gc> *local_decls;
/* In a Cilk function, the VAR_DECL for the frame descriptor. */
tree cilk_frame_decl;
/* For md files. */
/* tm.h can use this to store whatever it likes. */
@ -607,6 +610,12 @@ struct GTY(()) function {
either as a subroutine or builtin. */
unsigned int calls_alloca : 1;
/* This will indicate whether a function is a cilk function */
unsigned int is_cilk_function : 1;
/* Nonzero if this is a Cilk function that spawns. */
unsigned int calls_cilk_spawn : 1;
/* Nonzero if function being compiled receives nonlocal gotos
from nested functions. */
unsigned int has_nonlocal_label : 1;

View File

@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h"
#include "omp-low.h"
#include "gimple-low.h"
#include "cilk.h"
#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
#include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
@ -1309,6 +1310,15 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
if (ret_expr == error_mark_node)
return GS_ERROR;
/* Implicit _Cilk_sync must be inserted right before any return statement
if there is a _Cilk_spawn in the function. If the user has provided a
_Cilk_sync, the optimizer should remove this duplicate one. */
if (fn_contains_cilk_spawn_p (cfun))
{
tree impl_sync = build0 (CILK_SYNC_STMT, void_type_node);
gimplify_and_add (impl_sync, pre_p);
}
if (!ret_expr
|| TREE_CODE (ret_expr) == RESULT_DECL
|| ret_expr == error_mark_node)
@ -2498,6 +2508,12 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
if (! EXPR_HAS_LOCATION (*expr_p))
SET_EXPR_LOCATION (*expr_p, input_location);
if (fn_contains_cilk_spawn_p (cfun)
&& lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)
&& !seen_error ())
return (enum gimplify_status)
lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, NULL);
/* This may be a call to a builtin function.
Builtin function calls may be transformed into different
@ -4714,6 +4730,12 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
if (fn_contains_cilk_spawn_p (cfun)
&& lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)
&& !seen_error ())
return (enum gimplify_status)
lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, post_p);
/* Trying to simplify a clobber using normal logic doesn't work,
so handle it here. */
@ -7660,6 +7682,19 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
break;
case CILK_SPAWN_STMT:
gcc_assert
(fn_contains_cilk_spawn_p (cfun)
&& lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p));
if (!seen_error ())
{
ret = (enum gimplify_status)
lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p,
post_p);
break;
}
/* If errors are seen, then just process it as a CALL_EXPR. */
case CALL_EXPR:
ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
@ -8295,6 +8330,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
break;
}
case CILK_SYNC_STMT:
{
if (!fn_contains_cilk_spawn_p (cfun))
{
error_at (EXPR_LOCATION (*expr_p),
"expected %<_Cilk_spawn%> before %<_Cilk_sync%>");
ret = GS_ERROR;
}
else
{
gimplify_cilk_sync (expr_p, pre_p);
ret = GS_ALL_DONE;
}
break;
}
default:
switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
{

View File

@ -95,6 +95,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "ipa-utils.h"
#include "cilk.h"
/* Estimate runtime of function can easilly run into huge numbers with many
nested loops. Be sure we can compute time * INLINE_SIZE_SCALE * 2 in an
@ -1440,6 +1441,9 @@ initialize_inline_failed (struct cgraph_edge *e)
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
else if (e->call_stmt_cannot_inline_p)
e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
else if (cfun && fn_contains_cilk_spawn_p (cfun))
/* We can't inline if the function is spawing a function. */
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
else
e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
}

View File

@ -115,6 +115,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-inline.h"
#include "ipa-utils.h"
#include "sreal.h"
#include "cilk.h"
/* Statistics we collect about inlining algorithm. */
static int overall_size;
@ -264,7 +265,8 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
inlinable = false;
}
else if (!inline_summary (callee)->inlinable)
else if (!inline_summary (callee)->inlinable
|| (caller_cfun && fn_contains_cilk_spawn_p (caller_cfun)))
{
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
inlinable = false;

View File

@ -1874,6 +1874,9 @@ ira_setup_eliminable_regset (bool from_ira_p)
|| (flag_stack_check && STACK_CHECK_MOVING_SP)
|| crtl->accesses_prior_frames
|| crtl->stack_realign_needed
/* We need a frame pointer for all Cilk Plus functions that use
Cilk keywords. */
|| (flag_enable_cilkplus && cfun->is_cilk_function)
|| targetm.frame_pointer_required ());
if (from_ira_p && ira_use_lra_p)

View File

@ -214,6 +214,18 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
#define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree
extern void lhd_install_body_with_frame_cleanup (tree, tree);
extern bool lhd_cilk_detect_spawn (tree *);
#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP lhd_cilk_detect_spawn
#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup
#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr
#define LANG_HOOKS_CILKPLUS { \
LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP, \
LANG_HOOKS_CILKPLUS_FRAME_CLEANUP, \
LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN \
}
#define LANG_HOOKS_DECLS { \
LANG_HOOKS_GLOBAL_BINDINGS_P, \
LANG_HOOKS_PUSHDECL, \
@ -291,6 +303,7 @@ extern void lhd_end_section (void);
LANG_HOOKS_TREE_DUMP_INITIALIZER, \
LANG_HOOKS_DECLS, \
LANG_HOOKS_FOR_TYPES_INITIALIZER, \
LANG_HOOKS_CILKPLUS, \
LANG_HOOKS_LTO, \
LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \

View File

@ -675,3 +675,18 @@ lhd_end_section (void)
saved_section = NULL;
}
}
/* Empty function that is replaced with appropriate language dependent
frame cleanup function for _Cilk_spawn. */
void
lhd_install_body_with_frame_cleanup (tree, tree)
{
}
/* Empty function to handle cilk_valid_spawn. */
bool
lhd_cilk_detect_spawn (tree *)
{
return false;
}

View File

@ -139,6 +139,23 @@ struct lang_hooks_for_types
tree (*reconstruct_complex_type) (tree, tree);
};
/* Language hooks related to Cilk Plus. */
struct lang_hooks_for_cilkplus
{
/* Returns true if the expression passed in has a spawned function call. */
bool (*cilk_detect_spawn_and_unwrap) (tree *);
/* Function to add the clean up functions after spawn. The reason why it is
language dependent is because in C++, it must handle exceptions. */
void (*install_body_with_frame_cleanup) (tree, tree);
/* Function to gimplify a spawned function call. Returns enum gimplify
status, but as mentioned in a previous comment, we can't see that type
here, so just return an int. */
int (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *);
};
/* Language hooks related to decls and the symbol table. */
struct lang_hooks_for_decls
@ -408,6 +425,8 @@ struct lang_hooks
struct lang_hooks_for_types types;
struct lang_hooks_for_cilkplus cilkplus;
struct lang_hooks_for_lto lto;
/* Returns a TREE_VEC of the generic parameters of an instantiation of

View File

@ -1,3 +1,9 @@
2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
* Make-lang.in (lto/lto-lang.o): Added cilk.h in dependency list.
* lto-lang.c (lto_init): Added a call to cilk_init_builtins if Cilk
Plus is enabled.
2013-10-29 David Malcolm <dmalcolm@redhat.com>
Patch autogenerated by refactor_symtab.py from

View File

@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "toplev.h"
#include "lto-streamer.h"
#include "cilk.h"
static tree lto_type_for_size (unsigned, int);
@ -1174,6 +1175,9 @@ lto_init (void)
lto_define_builtins (va_list_type_node,
build_reference_type (va_list_type_node));
}
if (flag_enable_cilkplus)
cilk_init_builtins ();
targetm.init_builtins ();
build_common_builtin_nodes ();

View File

@ -1,3 +1,25 @@
2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-c++-common/cilk-plus/CK/compound_cilk_spawn.c: New test.
* c-c++-common/cilk-plus/CK/concec_cilk_spawn.c: Likewise.
* c-c++-common/cilk-plus/CK/fib.c: Likewise.
* c-c++-common/cilk-plus/CK/no_args_error.c: Likewise.
* c-c++-common/cilk-plus/CK/spawnee_inline.c: Likewise.
* c-c++-common/cilk-plus/CK/spawner_inline.c: Likewise.
* c-c++-common/cilk-plus/CK/spawning_arg.c: Likewise.
* c-c++-common/cilk-plus/CK/steal_check.c: Likewise.
* c-c++-common/cilk-plus/CK/test__cilk.c: Likewise.
* c-c++-common/cilk-plus/CK/varargs_test.c: Likewise.
* c-c++-common/cilk-plus/CK/sync_wo_spawn.c: Likewise.
* c-c++-common/cilk-plus/CK/invalid_spawn.c: Likewise.
* c-c++-common/cilk-plus/CK/spawn_in_return.c: Likewise.
* c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Likewise.
* c-c++-common/cilk-plus/CK/fib_no_sync.c: Likewise.
* c-c++-common/cilk-plus/CK/fib_no_return.c: Likewise.
* gcc.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords
test stored in c-c++-common. Also, added the Cilk runtime's library
to the ld_library_path.
2013-10-29 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58888

View File

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
/* <feature>
A program is considered ill formed if the _Cilk_spawn form of this
expression appears other than in one of the following contexts:
as the entire body of an expression statement,
as the entire right hand side of an assignment expression that is the entire
body of an expression statement, or as the entire initializer-clause in a
simple declaration.
</feature>
*/
int spawn_func (int arg)
{
return arg + 1;
}
int check()
{
int z;
z = 23, _Cilk_spawn spawn_func (3), 3424; /* { dg-error "spawned function call cannot be part of a comma expression" } */
23, spawn_func (5), _Cilk_spawn spawn_func (3); /* { dg-error "spawned function call cannot be part of a comma expression" } */
_Cilk_spawn spawn_func (0), _Cilk_spawn spawn_func (3), 3, spawn_func (0); /* { dg-error "spawned function call cannot be part of a comma expression" } */
return 23;
}

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
/* <feature> Consecutive _Cilk_spawn tokens are not permitted
</feature>
*/
int spawn_func (int arg)
{
return arg + 1;
}
void func ()
{
int a;
a = _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
a = _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
a = _Cilk_spawn _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
return;
}

View File

@ -0,0 +1,61 @@
/* { dg-options "-fcilkplus" } */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#if HAVE_IO
#include <stdio.h>
#endif
int fib (int);
int fib_serial (int);
int main(void)
{
int ii = 0, error = 0;
int fib_result[41], fib_serial_result[41];
#if HAVE_IO
for (ii = 0; ii <= 40; ii++)
printf("fib (%2d) = %10d\n", ii, fib (ii));
#else
for (ii = 0; ii <= 40; ii++)
{
fib_result[ii] = fib (ii);
fib_serial_result[ii] = fib_serial (ii);
}
for (ii = 0; ii <= 40; ii++)
{
if (fib_result[ii] != fib_serial_result[ii])
error = 1;
}
#endif
return error;
}
int fib_serial (int n)
{
int x = 0, y = 0;
if (n < 2)
return n;
else
{
x = fib (n-1);
y = fib (n-2);
return (x+y);
}
}
int fib(int n)
{
int x = 0, y = 0;
if (n < 2)
return n;
else
{
x = _Cilk_spawn fib(n-1);
y = fib(n-2);
_Cilk_sync;
return (x+y);
}
}

View File

@ -0,0 +1,60 @@
/* { dg-options "-fcilkplus" } */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#if HAVE_IO
#include <stdio.h>
#endif
int fib (int);
int fib_serial (int);
int main(void)
{
int ii = 0, error = 0;
int fib_result[41], fib_serial_result[41];
#if HAVE_IO
for (ii = 0; ii <= 40; ii++)
printf("fib (%2d) = %10d\n", ii, fib (ii));
#else
for (ii = 0; ii <= 40; ii++)
{
fib_result[ii] = fib (ii);
fib_serial_result[ii] = fib_serial (ii);
}
for (ii = 0; ii <= 40; ii++)
{
if (fib_result[ii] != fib_serial_result[ii])
error = 1;
}
#endif
return error;
}
int fib_serial (int n)
{
int x = 0, y = 0;
if (n < 2)
return n;
else
{
x = fib (n-1);
y = fib (n-2);
return (x+y);
}
}
int fib(int n)
{
if (n < 2)
return n;
else
{
int x = _Cilk_spawn fib(n-1);
int y = fib(n-2);
_Cilk_sync;
return (x+y);
}
}

View File

@ -0,0 +1,65 @@
/* { dg-options "-fcilkplus" } */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#if HAVE_IO
#include <stdio.h>
#endif
void fib (int *, int);
int fib_serial (int);
int main(void)
{
int ii = 0, error = 0;
int fib_result[41], fib_serial_result[41];
#if HAVE_IO
for (ii = 0; ii <= 40; ii++)
{
int result = 0;
fib (&result, ii);
printf("fib (%2d) = %10d\n", ii, result);
}
#else
for (ii = 0; ii <= 40; ii++)
{
fib (&fib_result[ii], ii);
fib_serial_result[ii] = fib_serial (ii);
}
for (ii = 0; ii <= 40; ii++)
{
if (fib_result[ii] != fib_serial_result[ii])
error = 1;
}
#endif
return error;
}
int fib_serial (int n)
{
int x = 0, y = 0;
if (n < 2)
return n;
else
{
fib (&x, n-1);
fib (&y, n-2);
return (x+y);
}
}
void fib(int *result, int n)
{
int x = 0, y = 0;
if (n < 2)
x = n;
else
{
_Cilk_spawn fib(&x, n-1);
fib(&y, n-2);
_Cilk_sync;
}
*result = (x+y);
}

View File

@ -0,0 +1,59 @@
/* { dg-options "-fcilkplus" } */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#if HAVE_IO
#include <stdio.h>
#endif
int fib (int);
int fib_serial (int);
int main(void)
{
int ii = 0, error = 0;
int fib_result[41], fib_serial_result[41];
#if HAVE_IO
for (ii = 0; ii <= 40; ii++)
printf("fib (%2d) = %10d\n", ii, fib (ii));
#else
for (ii = 0; ii <= 40; ii++)
{
fib_result[ii] = fib (ii);
fib_serial_result[ii] = fib_serial (ii);
}
for (ii = 0; ii <= 40; ii++)
{
if (fib_result[ii] != fib_serial_result[ii])
error = 1;
}
#endif
return error;
}
int fib_serial (int n)
{
int x = 0, y = 0;
if (n < 2)
return n;
else
{
x = fib (n-1);
y = fib (n-2);
return (x+y);
}
}
int fib(int n)
{
if (n < 2)
return n;
else
{
int x = _Cilk_spawn fib(n-1);
int y = fib(n-2);
return (x+y);
}
}

View File

@ -0,0 +1,11 @@
extern int foo ();
int bar = _Cilk_spawn foo (); /* { dg-error "may only be used inside a function" } */
int main (void)
{
int x;
_Cilk_spawn x; /* { dg-error "only function calls can be spawned" } */
return x;
}

View File

@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int spawn_1 ();
typedef int(*func) (int);
void check () {
func var = spawn_1; /* { dg-error "invalid conversion from" "" { target c++ } 8 } */
_Cilk_spawn var (); /* { dg-error "too few arguments to function" } */
}

View File

@ -0,0 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int main (void)
{
extern int foo ();
return _Cilk_spawn foo (); /* { dg-error "return statement is not allowed" } */
}

View File

@ -0,0 +1,80 @@
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus -w" } */
/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_VALUE "30"
int fib (char *n_char)
{
int n;
char n_char_minus_one[20], n_char_minus_two[20];
if (n_char)
n = atoi (n_char);
else
n = atoi(DEFAULT_VALUE);
if (n < 2)
return n;
else
{
int x, y;
sprintf (n_char_minus_one,"%d", n-1);
sprintf (n_char_minus_two,"%d", n-2);
x = _Cilk_spawn fib (n_char_minus_one);
y = _Cilk_spawn fib (n_char_minus_two);
_Cilk_sync;
return (x+y);
}
}
int fib_serial (int n)
{
int x, y;
if (n < 2)
return n;
else
{
x = fib_serial (n-1);
y = fib_serial (n-2);
return (x+y);
}
return 0;
}
int main2_parallel (int argc, char *argv[])
{
int n, result_parallel = 0;
if (argc == 2)
{
result_parallel = _Cilk_spawn fib (argv[1]);
_Cilk_sync;
}
else
{
result_parallel = _Cilk_spawn fib((char *)"30");
_Cilk_sync;
}
return result_parallel;
}
int main2_serial (int argc, char *argv[])
{
int n, result_serial = 0;
if (argc == 2)
result_serial = fib_serial (atoi (argv[1]));
else
result_serial = fib_serial (atoi (DEFAULT_VALUE));
return result_serial;
}
int main (void)
{
if (main2_serial (1, 0) != main2_parallel (1,0))
return 1;
return 0;
}

View File

@ -0,0 +1,67 @@
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus" } */
/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
#define DEFAULT_VALUE 30
int fib (int n)
{
if (n<2)
return n;
else
{
int x, y;
x = _Cilk_spawn fib (n-1);
y = _Cilk_spawn fib (n-2);
_Cilk_sync;
return (x+y);
return 5;
}
}
int main_parallel (int argc, char *argv[])
{
int n, result;
if (argc == 2)
n = atoi(argv[1]);
else
n = DEFAULT_VALUE;
result = _Cilk_spawn fib(n);
_Cilk_sync;
return result;
}
int fib_serial (int n)
{
int x, y;
if (n < 2)
return n;
else
{
x = fib (n-1);
y = fib (n-2);
return (x+y);
}
}
int main_serial (int argc, char *argv[])
{
int n, result;
if (argc == 2)
n = atoi (argv[1]);
else
n = DEFAULT_VALUE;
result = fib_serial (n);
return result;
}
int main (void)
{
if (main_serial (1, 0) != main_parallel (1,0))
return 1;
else
return 0;
}

View File

@ -0,0 +1,37 @@
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus" } */
/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
void f0(volatile int *steal_flag)
{
int i = 0;
/* Wait for steal_flag to be set */
while (!*steal_flag)
;
}
int f1()
{
volatile int steal_flag = 0;
_Cilk_spawn f0(&steal_flag);
steal_flag = 1; // Indicate stolen
_Cilk_sync;
return 0;
}
void f2(int q)
{
q = 5;
}
void f3()
{
_Cilk_spawn f2(f1());
}
int main()
{
f3();
return 0;
}

View File

@ -0,0 +1,43 @@
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus" } */
/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
// #include <cilk/cilk_api.h>
extern void __cilkrts_set_param (char *, char *);
void foo(volatile int *);
void main2(void);
int main(void)
{
// __cilkrts_set_param ((char *)"nworkers", (char *)"2");
main2();
return 0;
}
void main2(void)
{
int some_var = 0;
_Cilk_spawn foo(&some_var);
some_var=1;
some_var=5;
some_var=3;
some_var=4;
_Cilk_sync;
return;
}
void foo(volatile int *some_other_var)
{
while (*some_other_var == 0)
{
;
}
}

View File

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int main (void)
{
_Cilk_sync; /* { dg-error "expected '_Cilk_spawn' before '_Cilk_sync'" } */
return 0;
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus" } */
int main (void)
{
if (__cilk == 200)
return 0;
return 1;
}

View File

@ -0,0 +1,47 @@
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus" } */
/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
#include <stdarg.h>
#include <stdlib.h>
double compute_total (int no_elements, ...);
int main(void)
{
double array[5] = {5.0, 4.0, 9.0, 3.0, 4.0};
double array2[5] = {5.0, 6.0, 8.0, 6.0};
double yy=0, xx=0, xx_serial, yy_serial;
yy = _Cilk_spawn compute_total(5,array[0],array[1],array[2],
array[3], array[4]);
xx= compute_total(4,array2[0],array2[1],array2[2], array2[3]);
_Cilk_sync;
yy_serial = compute_total(5,array[0],array[1],array[2], array[3], array[4]);
xx_serial = compute_total(4,array2[0],array2[1],array2[2], array2[3]);
if ((xx + yy) != (xx_serial + yy_serial))
return 1;
return 0;
}
double compute_total (int no_elements, ...)
{
double total = 0;
va_list args;
va_start(args, no_elements);
int ii = 0;
for (ii = 0; ii < no_elements; ii++)
{
total += va_arg(args,double);
}
va_end(args);
return total;
}

View File

@ -23,6 +23,11 @@ if { ![check_effective_target_cilkplus] } {
return;
}
verbose "$tool $libdir" 1
set library_var [get_multilibs]
# Pointing the ld_library_path to the Cilk Runtime library binaries.
set ld_library_path "${library_var}/libcilkrts/.libs"
dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
@ -46,4 +51,31 @@ dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -f
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O3 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O0 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O0 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O1 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O0 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O1 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O2 -ftree-vectorize -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O3 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O0 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O1 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O3 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O0 -flto -g -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -flto -g -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus" " "
dg-finish

View File

@ -131,6 +131,10 @@ typedef struct copy_body_data
the originals have been mapped to a value rather than to a
variable. */
struct pointer_map_t *debug_map;
/* Cilk keywords currently need to replace some variables that
ordinary nested functions do not. */
bool remap_var_for_cilk;
} copy_body_data;
/* Weights of constructions for estimate_num_insns. */

View File

@ -2644,6 +2644,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
dump_block_node (buffer, node, spc, flags);
break;
case CILK_SPAWN_STMT:
pp_string (buffer, "_Cilk_spawn ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
break;
case CILK_SYNC_STMT:
pp_string (buffer, "_Cilk_sync");
break;
default:
NIY;
}

View File

@ -1271,6 +1271,12 @@ DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0)
Operand 1 is the annotation id. */
DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2)
/* Cilk spawn statement
Operand 0 is the CALL_EXPR. */
DEFTREECODE (CILK_SPAWN_STMT, "cilk_spawn_stmt", tcc_statement, 1)
/* Cilk Sync statement: Does not have any operands. */
DEFTREECODE (CILK_SYNC_STMT, "cilk_sync_stmt", tcc_statement, 0)
/*
Local variables:

View File

@ -790,6 +790,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define CALL_EXPR_RETURN_SLOT_OPT(NODE) \
(CALL_EXPR_CHECK (NODE)->base.private_flag)
/* Cilk keywords accessors. */
#define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0)
/* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
passed by invisible reference (and the TREE_TYPE is a pointer to the true
type). */