Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.

* Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.
	* gimple-pretty-print.c (dump_omp_for): Add case for
	GF_OMP_FOR_KIND_CILKSIMD.
	* gimple.h (enum gf_mask): Restructure entries to add
	GF_OMP_FOR_KIND_CILKSIMD.
	* gimplify.c (is_gimple_stmt): Add case for CILK_SIMD.
	(gimplify_omp_for): Handle CILK_SIMD.
	(gimplify_expr): Add ccase for CILK_SIMD.
	* omp-low.c (extract_omp_for_data): Handle CILK_SIMD.
	(build_outer_var_ref): Same.
	(check_omp_nesting_restrictions): Same.
	(lower_rec_input_clauses): Same.
	(lower_lastprivate_clauses): Same.
	(expand_omp_for): Same.
	(execute_expand_omp): Check flag_enable_cilkplus.
	(execute_lower_omp): Same.
	(diagnose_sb_0): Handle CILK_SIMD.
	(diagnose_omp_structured_block_errors): Check
	flag_enable_cilkplus.
	(setjmp_or_longjmp_p): New.
	(scan_omp_1_stmt): Error on setjmp/longjmp in a simd construct.
	* tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
	* tree.def: Add tree code for CILK_SIMD.

testsuite/
	* c-c++-common/cilk-plus/PS: New directory.
	* g++.dg/cilk-plus/cilk-plus.exp: Run shared tests.
	* g++.dg/dg.exp: Run Cilk Plus tests.
	* gcc.dg/cilk-plus/cilk-plus.exp: Run shared tests.

c-family/
	* c-cilkplus.c: New file.
	* c-common.c (readonly_error): Add location argument.
	* c-common.h (readonly_error): Same.
	(c_finish_cilk_clauses): Protoize.
	(c_check_cilk_loop): Same.
	c-omp.c (c_finish_omp_for): Handle CILK_SIMD nodes.
	Do not fail on error_mark_node.
	Abstract increment canonicalization to here...
	(c_omp_for_incr_canonicalize_ptr): New.
	c-pragma.c (init_pragma): Register "simd" pragma.
	c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD.
	(enum pragma_cilk_clause): New.

c/
	* c-parser.c (c_parser_cilk_simd): New.
	(c_parser_cilk_verify_simd): New.
	(c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
	(c_parser_omp_for_loop): Add case for NE_EXPR.
	Set c_break_label for CILK_SIMD.
	(c_parser_cilk_clause_vectorlength): New.
	(c_parser_cilk_clause_linear): New.
	(c_parser_cilk_clause_name): New.
	(c_parser_cilk_all_clauses): New.
	* c-typeck.c (build_unary_op): Pass location argument to
	readonly_error.
	(build_modify_expr): Same.
	(build_asm_expr): Same.
	(c_finish_bc_stmt): Error on break/continue in loops.

cp/
	* Make-lang.in (CXX_AND_OBJCXX_OBJS): Depend on cp/cp-cilkplus.o.
	* cp-cilkplus.c: New file.
	* cp-tree.h (cpp_validate_cilk_plus_loop): Protoize.
	* parser.c (cp_parser_cilk_simd): New.
	(cp_debug_parser): Add case for IN_CILK_SIMD_FOR.
	(cp_parser_jump_statement): Same.
	(cp_parser_omp_for_cond): Add new argument.
	Add case for NE_EXPR.
	(cp_parser_omp_for_loop): Pass new argument to
	cp_parser_omp_for_cond.
	Handle CILK_SIMD nodes.
	Abstract initilization code to..
	(cp_parser_omp_for_loop_init): ...here.
	(cp_parser_pragma): Add case for PRAGMA_CILK_SIMD.
	(cp_parser_cilk_simd_vectorlength): New.
	(cp_parser_cilk_simd_linear): New.
	(cp_parser_cilk_simd_clause_name): New.
	(cp_parser_cilk_simd_all_clauses): New.
	(cp_parser_cilk_simd): New.
	* parser.h (IN_CILK_SIMD_FOR): New macro.
	* pt.c (tsubst_expr): Add case for CILK_SIMD.
	* typeck2.c (cxx_readonly_error): Pass location argument to
	readonly_error.

From-SVN: r204863
This commit is contained in:
Aldy Hernandez 2013-11-15 21:43:59 +00:00 committed by Aldy Hernandez
parent e19eea7164
commit c02065fca1
50 changed files with 1912 additions and 263 deletions

View File

@ -1,3 +1,29 @@
2013-11-15 Aldy Hernandez <aldyh@redhat.com>
* Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.
* gimple-pretty-print.c (dump_omp_for): Add case for
GF_OMP_FOR_KIND_CILKSIMD.
* gimple.h (enum gf_mask): Restructure entries to add
GF_OMP_FOR_KIND_CILKSIMD.
* gimplify.c (is_gimple_stmt): Add case for CILK_SIMD.
(gimplify_omp_for): Handle CILK_SIMD.
(gimplify_expr): Add ccase for CILK_SIMD.
* omp-low.c (extract_omp_for_data): Handle CILK_SIMD.
(build_outer_var_ref): Same.
(check_omp_nesting_restrictions): Same.
(lower_rec_input_clauses): Same.
(lower_lastprivate_clauses): Same.
(expand_omp_for): Same.
(execute_expand_omp): Check flag_enable_cilkplus.
(execute_lower_omp): Same.
(diagnose_sb_0): Handle CILK_SIMD.
(diagnose_omp_structured_block_errors): Check
flag_enable_cilkplus.
(setjmp_or_longjmp_p): New.
(scan_omp_1_stmt): Error on setjmp/longjmp in a simd construct.
* tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
* tree.def: Add tree code for CILK_SIMD.
2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/altivec.md (UNSPEC_VPERM_X, UNSPEC_VPERM_UNS_X):

View File

@ -1138,6 +1138,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/c-cilkplus.o \
c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o
# Language-independent object files.

View File

@ -1,3 +1,18 @@
2013-11-15 Aldy Hernandez <aldyh@redhat.com>
* c-cilkplus.c: New file.
* c-common.c (readonly_error): Add location argument.
* c-common.h (readonly_error): Same.
(c_finish_cilk_clauses): Protoize.
(c_check_cilk_loop): Same.
c-omp.c (c_finish_omp_for): Handle CILK_SIMD nodes.
Do not fail on error_mark_node.
Abstract increment canonicalization to here...
(c_omp_for_incr_canonicalize_ptr): New.
c-pragma.c (init_pragma): Register "simd" pragma.
c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD.
(enum pragma_cilk_clause): New.
2013-11-15 Richard Sandiford <rdsandiford@googlemail.com>
* c-pretty-print.c (pp_c_character_constant): Remove unnecessary

93
gcc/c-family/c-cilkplus.c Normal file
View File

@ -0,0 +1,93 @@
/* This file contains routines to construct and validate Cilk Plus
constructs within the C and C++ front ends.
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldyh@redhat.com>.
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 "c-common.h"
/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
loop.
Returns true if there were no errors, false otherwise. */
bool
c_check_cilk_loop (location_t loc, tree decl)
{
if (TREE_THIS_VOLATILE (decl))
{
error_at (loc, "iteration variable cannot be volatile");
return false;
}
return true;
}
/* Validate and emit code for <#pragma simd> clauses. */
tree
c_finish_cilk_clauses (tree clauses)
{
for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
{
tree prev = clauses;
/* If a variable appears in a linear clause it cannot appear in
any other OMP clause. */
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
for (tree c2 = clauses; c2; c2 = OMP_CLAUSE_CHAIN (c2))
{
if (c == c2)
continue;
enum omp_clause_code code = OMP_CLAUSE_CODE (c2);
switch (code)
{
case OMP_CLAUSE_LINEAR:
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
break;
case OMP_CLAUSE_SAFELEN:
goto next;
default:
gcc_unreachable ();
}
if (OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (c2))
{
error_at (OMP_CLAUSE_LOCATION (c2),
"variable appears in more than one clause");
inform (OMP_CLAUSE_LOCATION (c),
"other clause defined here");
// Remove problematic clauses.
OMP_CLAUSE_CHAIN (prev) = OMP_CLAUSE_CHAIN (c2);
}
next:
prev = c2;
}
}
return clauses;
}

View File

@ -9816,7 +9816,7 @@ warn_for_omitted_condop (location_t location, tree cond)
how ARG was being used. */
void
readonly_error (tree arg, enum lvalue_use use)
readonly_error (location_t loc, tree arg, enum lvalue_use use)
{
gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
|| use == lv_asm);
@ -9829,59 +9829,59 @@ readonly_error (tree arg, enum lvalue_use use)
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
error (READONLY_MSG (G_("assignment of member "
"%qD in read-only object"),
G_("increment of member "
"%qD in read-only object"),
G_("decrement of member "
"%qD in read-only object"),
G_("member %qD in read-only object "
"used as %<asm%> output")),
TREE_OPERAND (arg, 1));
error_at (loc, READONLY_MSG (G_("assignment of member "
"%qD in read-only object"),
G_("increment of member "
"%qD in read-only object"),
G_("decrement of member "
"%qD in read-only object"),
G_("member %qD in read-only object "
"used as %<asm%> output")),
TREE_OPERAND (arg, 1));
else
error (READONLY_MSG (G_("assignment of read-only member %qD"),
G_("increment of read-only member %qD"),
G_("decrement of read-only member %qD"),
G_("read-only member %qD used as %<asm%> output")),
TREE_OPERAND (arg, 1));
error_at (loc, READONLY_MSG (G_("assignment of read-only member %qD"),
G_("increment of read-only member %qD"),
G_("decrement of read-only member %qD"),
G_("read-only member %qD used as %<asm%> output")),
TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
error (READONLY_MSG (G_("assignment of read-only variable %qD"),
G_("increment of read-only variable %qD"),
G_("decrement of read-only variable %qD"),
G_("read-only variable %qD used as %<asm%> output")),
arg);
error_at (loc, READONLY_MSG (G_("assignment of read-only variable %qD"),
G_("increment of read-only variable %qD"),
G_("decrement of read-only variable %qD"),
G_("read-only variable %qD used as %<asm%> output")),
arg);
else if (TREE_CODE (arg) == PARM_DECL)
error (READONLY_MSG (G_("assignment of read-only parameter %qD"),
G_("increment of read-only parameter %qD"),
G_("decrement of read-only parameter %qD"),
G_("read-only parameter %qD use as %<asm%> output")),
arg);
error_at (loc, READONLY_MSG (G_("assignment of read-only parameter %qD"),
G_("increment of read-only parameter %qD"),
G_("decrement of read-only parameter %qD"),
G_("read-only parameter %qD use as %<asm%> output")),
arg);
else if (TREE_CODE (arg) == RESULT_DECL)
{
gcc_assert (c_dialect_cxx ());
error (READONLY_MSG (G_("assignment of "
"read-only named return value %qD"),
G_("increment of "
"read-only named return value %qD"),
G_("decrement of "
"read-only named return value %qD"),
G_("read-only named return value %qD "
"used as %<asm%>output")),
arg);
error_at (loc, READONLY_MSG (G_("assignment of "
"read-only named return value %qD"),
G_("increment of "
"read-only named return value %qD"),
G_("decrement of "
"read-only named return value %qD"),
G_("read-only named return value %qD "
"used as %<asm%>output")),
arg);
}
else if (TREE_CODE (arg) == FUNCTION_DECL)
error (READONLY_MSG (G_("assignment of function %qD"),
G_("increment of function %qD"),
G_("decrement of function %qD"),
G_("function %qD used as %<asm%> output")),
arg);
error_at (loc, READONLY_MSG (G_("assignment of function %qD"),
G_("increment of function %qD"),
G_("decrement of function %qD"),
G_("function %qD used as %<asm%> output")),
arg);
else
error (READONLY_MSG (G_("assignment of read-only location %qE"),
G_("increment of read-only location %qE"),
G_("decrement of read-only location %qE"),
G_("read-only location %qE used as %<asm%> output")),
arg);
error_at (loc, READONLY_MSG (G_("assignment of read-only location %qE"),
G_("increment of read-only location %qE"),
G_("decrement of read-only location %qE"),
G_("read-only location %qE used as %<asm%> output")),
arg);
}
/* Print an error message for an invalid lvalue. USE says

View File

@ -970,7 +970,7 @@ enum lvalue_use {
lv_asm
};
extern void readonly_error (tree, enum lvalue_use);
extern void readonly_error (location_t, tree, enum lvalue_use);
extern void lvalue_error (location_t, enum lvalue_use);
extern void invalid_indirection_error (location_t, tree, ref_operator);
@ -1289,6 +1289,11 @@ enum stv_conv {
extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
tree op0, tree op1, bool);
/* In c-cilkplus.c */
extern tree c_finish_cilk_clauses (tree);
extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
extern bool c_check_cilk_loop (location_t, tree);
/* These #defines allow users to access different operands of the
array notation tree. */

View File

@ -349,6 +349,28 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
return error_mark_node;
}
/* If the OMP_FOR increment expression in INCR is of pointer type,
canonicalize it into an expression handled by gimplify_omp_for()
and return it. DECL is the iteration variable. */
static tree
c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
{
if (POINTER_TYPE_P (TREE_TYPE (decl))
&& TREE_OPERAND (incr, 1))
{
tree t = fold_convert_loc (loc,
sizetype, TREE_OPERAND (incr, 1));
if (TREE_CODE (incr) == POSTDECREMENT_EXPR
|| TREE_CODE (incr) == PREDECREMENT_EXPR)
t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
t = fold_build_pointer_plus (decl, t);
incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
}
return incr;
}
/* Validate and emit code for the OpenMP directive #pragma omp for.
DECLV is a vector of iteration variables, for each collapsed loop.
INITV, CONDV and INCRV are vectors containing initialization
@ -364,6 +386,10 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
bool fail = false;
int i;
if (code == CILK_SIMD
&& !c_check_cilk_loop (locus, TREE_VEC_ELT (declv, 0)))
fail = true;
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
@ -407,8 +433,11 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
init,
NULL_TREE);
}
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
gcc_assert (TREE_OPERAND (init, 0) == decl);
if (init != error_mark_node)
{
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
gcc_assert (TREE_OPERAND (init, 0) == decl);
}
if (cond == NULL_TREE)
{
@ -487,7 +516,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
0))
TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
? LT_EXPR : GE_EXPR);
else
else if (code != CILK_SIMD)
cond_ok = false;
}
}
@ -523,18 +552,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
break;
incr_ok = true;
if (POINTER_TYPE_P (TREE_TYPE (decl))
&& TREE_OPERAND (incr, 1))
{
tree t = fold_convert_loc (elocus,
sizetype, TREE_OPERAND (incr, 1));
if (TREE_CODE (incr) == POSTDECREMENT_EXPR
|| TREE_CODE (incr) == PREDECREMENT_EXPR)
t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
t = fold_build_pointer_plus (decl, t);
incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
}
incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
break;
case MODIFY_EXPR:

View File

@ -1380,6 +1380,10 @@ init_pragma (void)
omp_pragmas_simd[i].id, true, true);
}
if (flag_enable_cilkplus && !flag_preprocess_only)
cpp_register_deferred_pragma (parse_in, NULL, "simd", PRAGMA_CILK_SIMD,
true, false);
if (!flag_preprocess_only)
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
PRAGMA_GCC_PCH_PREPROCESS, false, false);

View File

@ -52,6 +52,9 @@ typedef enum pragma_kind {
PRAGMA_OMP_THREADPRIVATE,
PRAGMA_OMP_TEAMS,
/* Top level clause to handle all Cilk Plus pragma simd clauses. */
PRAGMA_CILK_SIMD,
PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_IVDEP,
@ -103,6 +106,17 @@ typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_UNTIED
} pragma_omp_clause;
/* All Cilk Plus #pragma omp clauses. */
typedef enum pragma_cilk_clause {
PRAGMA_CILK_CLAUSE_NONE = 0,
PRAGMA_CILK_CLAUSE_VECTORLENGTH,
PRAGMA_CILK_CLAUSE_LINEAR,
PRAGMA_CILK_CLAUSE_PRIVATE,
PRAGMA_CILK_CLAUSE_FIRSTPRIVATE,
PRAGMA_CILK_CLAUSE_LASTPRIVATE,
PRAGMA_CILK_CLAUSE_REDUCTION
} pragma_cilk_clause;
extern struct cpp_reader* parse_in;
/* It's safe to always leave visibility pragma enabled as if

View File

@ -1,3 +1,20 @@
2013-11-15 Aldy Hernandez <aldyh@redhat.com>
* c-parser.c (c_parser_cilk_simd): New.
(c_parser_cilk_verify_simd): New.
(c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
(c_parser_omp_for_loop): Add case for NE_EXPR.
Set c_break_label for CILK_SIMD.
(c_parser_cilk_clause_vectorlength): New.
(c_parser_cilk_clause_linear): New.
(c_parser_cilk_clause_name): New.
(c_parser_cilk_all_clauses): New.
* c-typeck.c (build_unary_op): Pass location argument to
readonly_error.
(build_modify_expr): Same.
(build_asm_expr): Same.
(c_finish_bc_stmt): Error on break/continue in loops.
2013-11-14 Andrew MacLeod <amacleod@redhat.com>
* c-typeck.c: Include only gimplify.h and gimple.h as needed.

View File

@ -1237,6 +1237,9 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
/* Cilk Plus supporting routines. */
static void c_parser_cilk_simd (c_parser *);
static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
/* Parse a translation unit (C90 6.7, C99 6.9).
@ -9371,6 +9374,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
case PRAGMA_CILK_SIMD:
if (!c_parser_cilk_verify_simd (parser, context))
return false;
c_parser_consume_pragma (parser);
c_parser_cilk_simd (parser);
return false;
default:
if (id < PRAGMA_FIRST_EXTERNAL)
{
@ -11543,6 +11553,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
case LT_EXPR:
case LE_EXPR:
break;
case NE_EXPR:
if (code == CILK_SIMD)
break;
/* FALLTHRU. */
default:
/* Can't be cond = error_mark_node, because we want to preserve
the location until c_finish_omp_for. */
@ -11616,7 +11630,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
}
save_break = c_break_label;
c_break_label = size_one_node;
if (code == CILK_SIMD)
c_break_label = build_int_cst (size_type_node, 2);
else
c_break_label = size_one_node;
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
body = push_stmt_list ();
@ -13311,7 +13328,252 @@ c_parser_omp_threadprivate (c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
}
/* Cilk Plus <#pragma simd> parsing routines. */
/* Helper function for c_parser_pragma. Perform some sanity checking
for <#pragma simd> constructs. Returns FALSE if there was a
problem. */
static bool
c_parser_cilk_verify_simd (c_parser *parser,
enum pragma_context context)
{
if (!flag_enable_cilkplus)
{
warning (0, "pragma simd ignored because -fcilkplus is not enabled");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
if (context == pragma_external)
{
c_parser_error (parser,"pragma simd must be inside a function");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
return true;
}
/* Cilk Plus:
vectorlength ( constant-expression ) */
static tree
c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
{
/* The vectorlength clause behaves exactly like OpenMP's safelen
clause. Represent it in OpenMP terms. */
check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return clauses;
location_t loc = c_parser_peek_token (parser)->location;
tree expr = c_parser_expr_no_commas (parser, NULL).value;
expr = c_fully_fold (expr, false, NULL);
if (!TREE_TYPE (expr)
|| !TREE_CONSTANT (expr)
|| !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
error_at (loc, "vectorlength must be an integer constant");
else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
error_at (loc, "vectorlength must be a power of 2");
else
{
tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
OMP_CLAUSE_CHAIN (u) = clauses;
clauses = u;
}
c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
return clauses;
}
/* Cilk Plus:
linear ( simd-linear-variable-list )
simd-linear-variable-list:
simd-linear-variable
simd-linear-variable-list , simd-linear-variable
simd-linear-variable:
id-expression
id-expression : simd-linear-step
simd-linear-step:
conditional-expression */
static tree
c_parser_cilk_clause_linear (c_parser *parser, tree clauses)
{
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return clauses;
location_t loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is_not (parser, CPP_NAME)
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
c_parser_error (parser, "expected identifier");
while (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_token (parser)->id_kind == C_ID_ID)
{
tree var = lookup_name (c_parser_peek_token (parser)->value);
if (var == NULL)
{
undeclared_variable (c_parser_peek_token (parser)->location,
c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
}
else if (var == error_mark_node)
c_parser_consume_token (parser);
else
{
tree step = integer_one_node;
/* Parse the linear step if present. */
if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
{
c_parser_consume_token (parser);
c_parser_consume_token (parser);
tree expr = c_parser_expr_no_commas (parser, NULL).value;
expr = c_fully_fold (expr, false, NULL);
if (TREE_TYPE (expr)
&& INTEGRAL_TYPE_P (TREE_TYPE (expr))
&& (TREE_CONSTANT (expr)
|| DECL_P (expr)))
step = expr;
else
c_parser_error (parser,
"step size must be an integer constant "
"expression or an integer variable");
}
else
c_parser_consume_token (parser);
/* Use OMP_CLAUSE_LINEAR, which has the same semantics. */
tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
OMP_CLAUSE_DECL (u) = var;
OMP_CLAUSE_LINEAR_STEP (u) = step;
OMP_CLAUSE_CHAIN (u) = clauses;
clauses = u;
}
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;
c_parser_consume_token (parser);
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
return clauses;
}
/* Returns the name of the next clause. If the clause is not
recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is
not consumed. Otherwise, the appropriate pragma_simd_clause is
returned and the token is consumed. */
static pragma_cilk_clause
c_parser_cilk_clause_name (c_parser *parser)
{
pragma_cilk_clause result;
c_token *token = c_parser_peek_token (parser);
if (!token->value || token->type != CPP_NAME)
return PRAGMA_CILK_CLAUSE_NONE;
const char *p = IDENTIFIER_POINTER (token->value);
if (!strcmp (p, "vectorlength"))
result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
else if (!strcmp (p, "linear"))
result = PRAGMA_CILK_CLAUSE_LINEAR;
else if (!strcmp (p, "private"))
result = PRAGMA_CILK_CLAUSE_PRIVATE;
else if (!strcmp (p, "firstprivate"))
result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
else if (!strcmp (p, "lastprivate"))
result = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
else if (!strcmp (p, "reduction"))
result = PRAGMA_CILK_CLAUSE_REDUCTION;
else
return PRAGMA_CILK_CLAUSE_NONE;
c_parser_consume_token (parser);
return result;
}
/* Parse all #<pragma simd> clauses. Return the list of clauses
found. */
static tree
c_parser_cilk_all_clauses (c_parser *parser)
{
tree clauses = NULL;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
pragma_cilk_clause c_kind;
c_kind = c_parser_cilk_clause_name (parser);
switch (c_kind)
{
case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_LINEAR:
clauses = c_parser_cilk_clause_linear (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_PRIVATE:
/* Use the OpenMP counterpart. */
clauses = c_parser_omp_clause_private (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE:
/* Use the OpenMP counterpart. */
clauses = c_parser_omp_clause_firstprivate (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_LASTPRIVATE:
/* Use the OpenMP counterpart. */
clauses = c_parser_omp_clause_lastprivate (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_REDUCTION:
/* Use the OpenMP counterpart. */
clauses = c_parser_omp_clause_reduction (parser, clauses);
break;
default:
c_parser_error (parser, "expected %<#pragma simd%> clause");
goto saw_error;
}
}
saw_error:
c_parser_skip_to_pragma_eol (parser);
return c_finish_cilk_clauses (clauses);
}
/* Main entry point for parsing Cilk Plus <#pragma simd> for
loops. */
static void
c_parser_cilk_simd (c_parser *parser ATTRIBUTE_UNUSED)
{
char p_name[100];
strcpy (p_name, "#pragma omp");
tree clauses = c_parser_cilk_all_clauses (parser);
tree block = c_begin_compound_stmt (true);
location_t loc = c_parser_peek_token (parser)->location;
c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
}
/* Parse a transaction attribute (GCC Extension).
transaction-attribute:

View File

@ -4055,7 +4055,7 @@ build_unary_op (location_t location,
/* Report a read-only lvalue. */
if (TYPE_READONLY (argtype))
{
readonly_error (arg,
readonly_error (location, arg,
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? lv_increment : lv_decrement));
@ -5266,7 +5266,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype)))
{
readonly_error (lhs, lv_assign);
readonly_error (location, lhs, lv_assign);
return error_mark_node;
}
else if (TREE_READONLY (lhs))
@ -8949,7 +8949,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
|| ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
readonly_error (output, lv_asm);
readonly_error (loc, output, lv_asm);
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
oconstraints[i] = constraint;
@ -9576,6 +9576,13 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
error_at (loc, "break statement used with OpenMP for loop");
return NULL_TREE;
case 2:
if (is_break)
error ("break statement within %<#pragma simd%> loop body");
else
error ("continue statement within %<#pragma simd%> loop body");
return NULL_TREE;
default:
gcc_unreachable ();
}

View File

@ -1,3 +1,29 @@
2013-11-15 Aldy Hernandez <aldyh@redhat.com>
* Make-lang.in (CXX_AND_OBJCXX_OBJS): Depend on cp/cp-cilkplus.o.
* cp-cilkplus.c: New file.
* cp-tree.h (cpp_validate_cilk_plus_loop): Protoize.
* parser.c (cp_parser_cilk_simd): New.
(cp_debug_parser): Add case for IN_CILK_SIMD_FOR.
(cp_parser_jump_statement): Same.
(cp_parser_omp_for_cond): Add new argument.
Add case for NE_EXPR.
(cp_parser_omp_for_loop): Pass new argument to
cp_parser_omp_for_cond.
Handle CILK_SIMD nodes.
Abstract initilization code to..
(cp_parser_omp_for_loop_init): ...here.
(cp_parser_pragma): Add case for PRAGMA_CILK_SIMD.
(cp_parser_cilk_simd_vectorlength): New.
(cp_parser_cilk_simd_linear): New.
(cp_parser_cilk_simd_clause_name): New.
(cp_parser_cilk_simd_all_clauses): New.
(cp_parser_cilk_simd): New.
* parser.h (IN_CILK_SIMD_FOR): New macro.
* pt.c (tsubst_expr): Add case for CILK_SIMD.
* typeck2.c (cxx_readonly_error): Pass location argument to
readonly_error.
2013-11-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/57887

View File

@ -76,6 +76,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
cp/cp-cilkplus.o \
cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o \
cp/vtable-class-hierarchy.o $(CXX_C_OBJS)

77
gcc/cp/cp-cilkplus.c Normal file
View File

@ -0,0 +1,77 @@
/* This file is part of the Intel(R) Cilk(TM) Plus support
This file contains routines to handle Cilk Plus specific
routines for the C++ Compiler.
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldyh@redhat.com>.
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 "cp-tree.h"
#include "diagnostic-core.h"
/* Callback for cp_walk_tree to validate the body of a pragma simd loop
or _cilk_for loop.
This function is passed in as a function pointer to walk_tree. *TP is
the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
is set to false if an error has occured. */
static tree
cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
{
bool *valid = (bool *) data;
location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
UNKNOWN_LOCATION;
if (!tp || !*tp)
return NULL_TREE;
if (TREE_CODE (*tp) == THROW_EXPR)
{
error_at (loc, "throw expressions are not allowed inside loops "
"marked with pragma simd");
*walk_subtrees = 0;
*valid = false;
}
else if (TREE_CODE (*tp) == TRY_BLOCK)
{
error_at (loc, "try statements are not allowed inside loops marked "
"with #pragma simd");
*valid = false;
*walk_subtrees = 0;
}
return NULL_TREE;
}
/* Walks through all the subtrees of BODY using walk_tree to make sure
invalid statements/expressions are not found inside BODY. Returns
false if any invalid statements are found. */
bool
cpp_validate_cilk_plus_loop (tree body)
{
bool valid = true;
cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux,
(void *) &valid, NULL);
return valid;
}

View File

@ -6177,6 +6177,9 @@ extern void vtv_save_class_info (tree);
extern void vtv_recover_class_info (void);
extern void vtv_build_vtable_verify_fndecl (void);
/* In cp-cilkplus.c. */
extern bool cpp_validate_cilk_plus_loop (tree);
/* In cp/cp-array-notations.c */
extern tree expand_array_notation_exprs (tree);
bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree,

View File

@ -233,6 +233,8 @@ static void cp_parser_initial_pragma
static tree cp_literal_operator_id
(const char *);
static void cp_parser_cilk_simd
(cp_parser *, cp_token *);
static bool cp_parser_omp_declare_reduction_exprs
(tree, cp_parser *);
@ -531,6 +533,8 @@ cp_debug_parser (FILE *file, cp_parser *parser)
parser->in_statement & IN_SWITCH_STMT);
cp_debug_print_flag (file, "Parsing a structured OpenMP block",
parser->in_statement & IN_OMP_BLOCK);
cp_debug_print_flag (file, "Parsing a Cilk Plus for loop",
parser->in_statement & IN_CILK_SIMD_FOR);
cp_debug_print_flag (file, "Parsing a an OpenMP loop",
parser->in_statement & IN_OMP_FOR);
cp_debug_print_flag (file, "Parsing an if statement",
@ -10558,6 +10562,9 @@ cp_parser_jump_statement (cp_parser* parser)
case IN_OMP_FOR:
error_at (token->location, "break statement used with OpenMP for loop");
break;
case IN_CILK_SIMD_FOR:
error_at (token->location, "break statement used with Cilk Plus for loop");
break;
}
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
break;
@ -10568,6 +10575,10 @@ cp_parser_jump_statement (cp_parser* parser)
case 0:
error_at (token->location, "continue statement not within a loop");
break;
case IN_CILK_SIMD_FOR:
error_at (token->location,
"continue statement within %<#pragma simd%> loop body");
/* Fall through. */
case IN_ITERATION_STMT:
case IN_OMP_FOR:
statement = finish_continue_stmt ();
@ -28591,7 +28602,7 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
/* Helper function, to parse omp for increment expression. */
static tree
cp_parser_omp_for_cond (cp_parser *parser, tree decl)
cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
{
tree cond = cp_parser_binary_expression (parser, false, true,
PREC_NOT_OPERATOR, NULL);
@ -28609,6 +28620,10 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
case LT_EXPR:
case LE_EXPR:
break;
case NE_EXPR:
if (code == CILK_SIMD)
break;
/* Fall through: OpenMP disallows NE_EXPR. */
default:
return error_mark_node;
}
@ -28718,6 +28733,186 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
}
/* Parse the initialization statement of either an OpenMP for loop or
a Cilk Plus for loop.
PARSING_OPENMP is true if parsing OpenMP, or false if parsing Cilk
Plus.
Return true if the resulting construct should have an
OMP_CLAUSE_PRIVATE added to it. */
static bool
cp_parser_omp_for_loop_init (cp_parser *parser,
bool parsing_openmp,
tree &this_pre_body,
vec<tree, va_gc> *for_block,
tree &init,
tree &decl,
tree &real_decl)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
return false;
bool add_private_clause = false;
/* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
init-expr:
var = lb
integer-type var = lb
random-access-iterator-type var = lb
pointer-type var = lb
*/
cp_decl_specifier_seq type_specifiers;
/* First, try to parse as an initialized declaration. See
cp_parser_condition, from whence the bulk of this is copied. */
cp_parser_parse_tentatively (parser);
cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
if (cp_parser_parse_definitely (parser))
{
/* If parsing a type specifier seq succeeded, then this
MUST be a initialized declaration. */
tree asm_specification, attributes;
cp_declarator *declarator;
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false);
attributes = cp_parser_attributes_opt (parser);
asm_specification = cp_parser_asm_specification_opt (parser);
if (declarator == cp_error_declarator)
cp_parser_skip_to_end_of_statement (parser);
else
{
tree pushed_scope, auto_node;
decl = start_decl (declarator, &type_specifiers,
SD_INITIALIZED, attributes,
/*prefix_attributes=*/NULL_TREE,
&pushed_scope);
auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
if (cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN))
{
if (parsing_openmp)
error ("parenthesized initialization is not allowed in "
"OpenMP %<for%> loop");
else
error ("parenthesized initialization is "
"not allowed in for-loop");
}
else
/* Trigger an error. */
cp_parser_require (parser, CPP_EQ, RT_EQ);
init = error_mark_node;
cp_parser_skip_to_end_of_statement (parser);
}
else if (CLASS_TYPE_P (TREE_TYPE (decl))
|| type_dependent_expression_p (decl)
|| auto_node)
{
bool is_direct_init, is_non_constant_init;
init = cp_parser_initializer (parser,
&is_direct_init,
&is_non_constant_init);
if (auto_node)
{
TREE_TYPE (decl)
= do_auto_deduction (TREE_TYPE (decl), init,
auto_node);
if (!CLASS_TYPE_P (TREE_TYPE (decl))
&& !type_dependent_expression_p (decl))
goto non_class;
}
cp_finish_decl (decl, init, !is_non_constant_init,
asm_specification,
LOOKUP_ONLYCONVERTING);
if (CLASS_TYPE_P (TREE_TYPE (decl)))
{
vec_safe_push (for_block, this_pre_body);
init = NULL_TREE;
}
else
init = pop_stmt_list (this_pre_body);
this_pre_body = NULL_TREE;
}
else
{
/* Consume '='. */
cp_lexer_consume_token (parser->lexer);
init = cp_parser_assignment_expression (parser, false, NULL);
non_class:
if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
init = error_mark_node;
else
cp_finish_decl (decl, NULL_TREE,
/*init_const_expr_p=*/false,
asm_specification,
LOOKUP_ONLYCONVERTING);
}
if (pushed_scope)
pop_scope (pushed_scope);
}
}
else
{
cp_id_kind idk;
/* If parsing a type specifier sequence failed, then
this MUST be a simple expression. */
cp_parser_parse_tentatively (parser);
decl = cp_parser_primary_expression (parser, false, false,
false, &idk);
if (!cp_parser_error_occurred (parser)
&& decl
&& DECL_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
{
tree rhs;
cp_parser_parse_definitely (parser);
cp_parser_require (parser, CPP_EQ, RT_EQ);
rhs = cp_parser_assignment_expression (parser, false, NULL);
finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
decl, NOP_EXPR,
rhs,
tf_warning_or_error));
add_private_clause = true;
}
else
{
decl = NULL;
cp_parser_abort_tentative_parse (parser);
init = cp_parser_expression (parser, false, NULL);
if (init)
{
if (TREE_CODE (init) == MODIFY_EXPR
|| TREE_CODE (init) == MODOP_EXPR)
real_decl = TREE_OPERAND (init, 0);
}
}
}
return add_private_clause;
}
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
@ -28763,157 +28958,13 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
init = decl = real_decl = NULL;
this_pre_body = push_stmt_list ();
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
{
/* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
init-expr:
var = lb
integer-type var = lb
random-access-iterator-type var = lb
pointer-type var = lb
*/
cp_decl_specifier_seq type_specifiers;
add_private_clause
|= cp_parser_omp_for_loop_init (parser,
/*parsing_openmp=*/code != CILK_SIMD,
this_pre_body, for_block,
init, decl, real_decl);
/* First, try to parse as an initialized declaration. See
cp_parser_condition, from whence the bulk of this is copied. */
cp_parser_parse_tentatively (parser);
cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
if (cp_parser_parse_definitely (parser))
{
/* If parsing a type specifier seq succeeded, then this
MUST be a initialized declaration. */
tree asm_specification, attributes;
cp_declarator *declarator;
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false);
attributes = cp_parser_attributes_opt (parser);
asm_specification = cp_parser_asm_specification_opt (parser);
if (declarator == cp_error_declarator)
cp_parser_skip_to_end_of_statement (parser);
else
{
tree pushed_scope, auto_node;
decl = start_decl (declarator, &type_specifiers,
SD_INITIALIZED, attributes,
/*prefix_attributes=*/NULL_TREE,
&pushed_scope);
auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
if (cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN))
error ("parenthesized initialization is not allowed in "
"OpenMP %<for%> loop");
else
/* Trigger an error. */
cp_parser_require (parser, CPP_EQ, RT_EQ);
init = error_mark_node;
cp_parser_skip_to_end_of_statement (parser);
}
else if (CLASS_TYPE_P (TREE_TYPE (decl))
|| type_dependent_expression_p (decl)
|| auto_node)
{
bool is_direct_init, is_non_constant_init;
init = cp_parser_initializer (parser,
&is_direct_init,
&is_non_constant_init);
if (auto_node)
{
TREE_TYPE (decl)
= do_auto_deduction (TREE_TYPE (decl), init,
auto_node);
if (!CLASS_TYPE_P (TREE_TYPE (decl))
&& !type_dependent_expression_p (decl))
goto non_class;
}
cp_finish_decl (decl, init, !is_non_constant_init,
asm_specification,
LOOKUP_ONLYCONVERTING);
if (CLASS_TYPE_P (TREE_TYPE (decl)))
{
vec_safe_push (for_block, this_pre_body);
init = NULL_TREE;
}
else
init = pop_stmt_list (this_pre_body);
this_pre_body = NULL_TREE;
}
else
{
/* Consume '='. */
cp_lexer_consume_token (parser->lexer);
init = cp_parser_assignment_expression (parser, false, NULL);
non_class:
if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
init = error_mark_node;
else
cp_finish_decl (decl, NULL_TREE,
/*init_const_expr_p=*/false,
asm_specification,
LOOKUP_ONLYCONVERTING);
}
if (pushed_scope)
pop_scope (pushed_scope);
}
}
else
{
cp_id_kind idk;
/* If parsing a type specifier sequence failed, then
this MUST be a simple expression. */
cp_parser_parse_tentatively (parser);
decl = cp_parser_primary_expression (parser, false, false,
false, &idk);
if (!cp_parser_error_occurred (parser)
&& decl
&& DECL_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
{
tree rhs;
cp_parser_parse_definitely (parser);
cp_parser_require (parser, CPP_EQ, RT_EQ);
rhs = cp_parser_assignment_expression (parser, false, NULL);
finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
decl, NOP_EXPR,
rhs,
tf_warning_or_error));
add_private_clause = true;
}
else
{
decl = NULL;
cp_parser_abort_tentative_parse (parser);
init = cp_parser_expression (parser, false, NULL);
if (init)
{
if (TREE_CODE (init) == MODIFY_EXPR
|| TREE_CODE (init) == MODOP_EXPR)
real_decl = TREE_OPERAND (init, 0);
}
}
}
}
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
if (this_pre_body)
{
@ -29002,7 +29053,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
cond = NULL;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
cond = cp_parser_omp_for_cond (parser, decl);
cond = cp_parser_omp_for_cond (parser, decl, code);
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
incr = NULL;
@ -29072,7 +29123,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
/* Note that we saved the original contents of this flag when we entered
the structured block, and so we don't need to re-save it here. */
parser->in_statement = IN_OMP_FOR;
if (code == CILK_SIMD)
parser->in_statement = IN_CILK_SIMD_FOR;
else
parser->in_statement = IN_OMP_FOR;
/* Note that the grammar doesn't call for a structured block here,
though the loop as a whole is a structured block. */
@ -31127,6 +31181,16 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
return true;
}
case PRAGMA_CILK_SIMD:
if (context == pragma_external)
{
error_at (pragma_tok->location,
"%<#pragma simd%> must be inside a function");
break;
}
cp_parser_cilk_simd (parser, pragma_tok);
return true;
default:
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
c_invoke_pragma_handler (id);
@ -31192,6 +31256,257 @@ c_parse_file (void)
the_parser = NULL;
}
/* Parses the Cilk Plus #pragma simd vectorlength clause:
Syntax:
vectorlength ( constant-expression ) */
static tree
cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
{
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
tree expr;
/* The vectorlength clause behaves exactly like OpenMP's safelen
clause. Thus, vectorlength is represented as OMP 4.0
safelen. */
check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return error_mark_node;
expr = cp_parser_constant_expression (parser, false, NULL);
expr = maybe_constant_value (expr);
if (TREE_CONSTANT (expr)
&& exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
error_at (loc, "vectorlength must be a power of 2");
else if (expr != error_mark_node)
{
tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
OMP_CLAUSE_CHAIN (c) = clauses;
clauses = c;
}
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
return error_mark_node;
return clauses;
}
/* Handles the Cilk Plus #pragma simd linear clause.
Syntax:
linear ( simd-linear-variable-list )
simd-linear-variable-list:
simd-linear-variable
simd-linear-variable-list , simd-linear-variable
simd-linear-variable:
id-expression
id-expression : simd-linear-step
simd-linear-step:
conditional-expression */
static tree
cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
{
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return clauses;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
{
cp_parser_error (parser, "expected identifier");
cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
return error_mark_node;
}
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
while (1)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
{
cp_parser_error (parser, "expected variable-name");
clauses = error_mark_node;
break;
}
tree var_name = cp_parser_id_expression (parser, false, true, NULL,
false, false);
tree decl = cp_parser_lookup_name_simple (parser, var_name,
token->location);
if (decl == error_mark_node)
{
cp_parser_name_lookup_error (parser, var_name, decl, NLE_NULL,
token->location);
clauses = error_mark_node;
}
else
{
tree e = NULL_TREE;
tree step_size = integer_one_node;
/* If present, parse the linear step. Otherwise, assume the default
value of 1. */
if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
{
cp_lexer_consume_token (parser->lexer);
e = cp_parser_assignment_expression (parser, false, NULL);
e = maybe_constant_value (e);
if (e == error_mark_node)
{
/* If an error has occurred, then the whole pragma is
considered ill-formed. Thus, no reason to keep
parsing. */
clauses = error_mark_node;
break;
}
else if (type_dependent_expression_p (e)
|| value_dependent_expression_p (e)
|| (TREE_TYPE (e)
&& INTEGRAL_TYPE_P (TREE_TYPE (e))
&& (TREE_CONSTANT (e)
|| DECL_P (e))))
step_size = e;
else
cp_parser_error (parser,
"step size must be an integer constant "
"expression or an integer variable");
}
/* Use the OMP_CLAUSE_LINEAR, which has the same semantics. */
tree l = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
OMP_CLAUSE_DECL (l) = decl;
OMP_CLAUSE_LINEAR_STEP (l) = step_size;
OMP_CLAUSE_CHAIN (l) = clauses;
clauses = l;
}
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
break;
else
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
"expected %<,%> or %<)%> after %qE", decl);
clauses = error_mark_node;
break;
}
}
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
return clauses;
}
/* Returns the name of the next clause. If the clause is not
recognized, then PRAGMA_CILK_CLAUSE_NONE is returned and the next
token is not consumed. Otherwise, the appropriate enum from the
pragma_simd_clause is returned and the token is consumed. */
static pragma_cilk_clause
cp_parser_cilk_simd_clause_name (cp_parser *parser)
{
pragma_cilk_clause clause_type;
cp_token *token = cp_lexer_peek_token (parser->lexer);
if (token->keyword == RID_PRIVATE)
clause_type = PRAGMA_CILK_CLAUSE_PRIVATE;
else if (!token->u.value || token->type != CPP_NAME)
return PRAGMA_CILK_CLAUSE_NONE;
else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "vectorlength"))
clause_type = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "linear"))
clause_type = PRAGMA_CILK_CLAUSE_LINEAR;
else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "firstprivate"))
clause_type = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "lastprivate"))
clause_type = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "reduction"))
clause_type = PRAGMA_CILK_CLAUSE_REDUCTION;
else
return PRAGMA_CILK_CLAUSE_NONE;
cp_lexer_consume_token (parser->lexer);
return clause_type;
}
/* Parses all the #pragma simd clauses. Returns a list of clauses found. */
static tree
cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
{
tree clauses = NULL_TREE;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
&& clauses != error_mark_node)
{
pragma_cilk_clause c_kind;
c_kind = cp_parser_cilk_simd_clause_name (parser);
if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);
else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
clauses = cp_parser_cilk_simd_linear (parser, clauses);
else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
/* Use the OpenMP 4.0 equivalent function. */
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses);
else if (c_kind == PRAGMA_CILK_CLAUSE_FIRSTPRIVATE)
/* Use the OpenMP 4.0 equivalent function. */
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
clauses);
else if (c_kind == PRAGMA_CILK_CLAUSE_LASTPRIVATE)
/* Use the OMP 4.0 equivalent function. */
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
clauses);
else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION)
/* Use the OMP 4.0 equivalent function. */
clauses = cp_parser_omp_clause_reduction (parser, clauses);
else
{
clauses = error_mark_node;
cp_parser_error (parser, "expected %<#pragma simd%> clause");
break;
}
}
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (clauses == error_mark_node)
return error_mark_node;
else
return c_finish_cilk_clauses (clauses);
}
/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops. */
static void
cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
{
tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
if (clauses == error_mark_node)
return;
if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
"for statement expected");
return;
}
tree sb = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL);
if (ret)
cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret));
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
return;
}
/* Create an identifier for a generic parameter type (a synthesized
template parameter implied by `auto' or a concept identifier). */

View File

@ -300,6 +300,7 @@ typedef struct GTY(()) cp_parser {
#define IN_OMP_BLOCK 4
#define IN_OMP_FOR 8
#define IN_IF_STMT 16
#define IN_CILK_SIMD_FOR 32
unsigned char in_statement;
/* TRUE if we are presently parsing the body of a switch statement.

View File

@ -13566,6 +13566,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_FOR:
case OMP_SIMD:
case CILK_SIMD:
case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;

View File

@ -125,7 +125,7 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring)
"read-only reference %qD"),
TREE_OPERAND (arg, 0));
else
readonly_error (arg, errstring);
readonly_error (input_location, arg, errstring);
}

View File

@ -1118,6 +1118,8 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
case GF_OMP_FOR_KIND_SIMD:
kind = " simd";
break;
case GF_OMP_FOR_KIND_CILKSIMD:
kind = " cilksimd";
case GF_OMP_FOR_KIND_DISTRIBUTE:
kind = " distribute";
break;
@ -1149,6 +1151,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
case GF_OMP_FOR_KIND_SIMD:
pp_string (buffer, "#pragma omp simd");
break;
case GF_OMP_FOR_KIND_CILKSIMD:
pp_string (buffer, "#pragma simd");
break;
case GF_OMP_FOR_KIND_DISTRIBUTE:
pp_string (buffer, "#pragma omp distribute");
break;

View File

@ -102,12 +102,13 @@ enum gf_mask {
GF_CALL_ALLOCA_FOR_VAR = 1 << 5,
GF_CALL_INTERNAL = 1 << 6,
GF_OMP_PARALLEL_COMBINED = 1 << 0,
GF_OMP_FOR_KIND_MASK = 3 << 0,
GF_OMP_FOR_KIND_MASK = 7,
GF_OMP_FOR_KIND_FOR = 0 << 0,
GF_OMP_FOR_KIND_SIMD = 1 << 0,
GF_OMP_FOR_KIND_DISTRIBUTE = 2 << 0,
GF_OMP_FOR_COMBINED = 1 << 2,
GF_OMP_FOR_COMBINED_INTO = 1 << 3,
GF_OMP_FOR_KIND_SIMD = 2 << 0,
GF_OMP_FOR_KIND_CILKSIMD = 3 << 0,
GF_OMP_FOR_KIND_DISTRIBUTE = 1 << 2,
GF_OMP_FOR_COMBINED = 1 << 3,
GF_OMP_FOR_COMBINED_INTO = 1 << 4,
GF_OMP_TARGET_KIND_MASK = 3 << 0,
GF_OMP_TARGET_KIND_REGION = 0 << 0,
GF_OMP_TARGET_KIND_DATA = 1 << 0,

View File

@ -4189,6 +4189,7 @@ is_gimple_stmt (tree t)
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SIMD:
case CILK_SIMD:
case OMP_DISTRIBUTE:
case OMP_SECTIONS:
case OMP_SECTION:
@ -6406,7 +6407,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
orig_for_stmt = for_stmt = *expr_p;
simd = TREE_CODE (for_stmt) == OMP_SIMD;
simd = TREE_CODE (for_stmt) == OMP_SIMD
|| TREE_CODE (for_stmt) == CILK_SIMD;
gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
simd ? ORT_SIMD : ORT_WORKSHARE);
@ -6543,15 +6545,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
{
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
if (orig_for_stmt != for_stmt)
{
tree decl = TREE_OPERAND (t, 0);
// c_omp_for_incr_canonicalize_ptr() should have been
// called to massage things appropriately.
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
if (orig_for_stmt != for_stmt)
break;
t = build_int_cst (TREE_TYPE (decl), 1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
break;
t = build_int_cst (TREE_TYPE (decl), 1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
break;
}
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
@ -6661,6 +6670,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
{
case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
case CILK_SIMD: kind = GF_OMP_FOR_KIND_CILKSIMD; break;
case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
default:
gcc_unreachable ();
@ -7730,6 +7740,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_FOR:
case OMP_SIMD:
case CILK_SIMD:
case OMP_DISTRIBUTE:
ret = gimplify_omp_for (expr_p, pre_p);
break;

View File

@ -285,7 +285,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
int i;
struct omp_for_data_loop dummy_loop;
location_t loc = gimple_location (for_stmt);
bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
bool distribute = gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_DISTRIBUTE;
@ -377,6 +377,10 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
case LT_EXPR:
case GT_EXPR:
break;
case NE_EXPR:
gcc_assert (gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_CILKSIMD);
break;
case LE_EXPR:
if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
@ -1003,7 +1007,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
x = build_receiver_ref (var, by_ref, ctx);
}
else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
{
/* #pragma omp simd isn't a worksharing construct, and can reference even
private vars in its linear etc. clauses. */
@ -2230,7 +2234,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
if (ctx != NULL)
{
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
{
error_at (gimple_location (stmt),
"OpenMP constructs may not be nested inside simd region");
@ -2253,7 +2257,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
switch (gimple_code (stmt))
{
case GIMPLE_OMP_FOR:
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
return true;
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
{
@ -2536,6 +2540,23 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
/* Return true if FNDECL is a setjmp or a longjmp. */
static bool
setjmp_or_longjmp_p (const_tree fndecl)
{
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
return true;
tree declname = DECL_NAME (fndecl);
if (!declname)
return false;
const char *name = IDENTIFIER_POINTER (declname);
return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
}
/* Helper function for scan_omp.
@ -2559,22 +2580,33 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
else if (is_gimple_call (stmt))
{
tree fndecl = gimple_call_fndecl (stmt);
if (fndecl
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_GOMP_BARRIER:
case BUILT_IN_GOMP_CANCEL:
case BUILT_IN_GOMP_CANCELLATION_POINT:
case BUILT_IN_GOMP_TASKYIELD:
case BUILT_IN_GOMP_TASKWAIT:
case BUILT_IN_GOMP_TASKGROUP_START:
case BUILT_IN_GOMP_TASKGROUP_END:
remove = !check_omp_nesting_restrictions (stmt, ctx);
break;
default:
break;
}
if (fndecl)
{
if (setjmp_or_longjmp_p (fndecl)
&& ctx
&& gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
{
remove = true;
error_at (gimple_location (stmt),
"setjmp/longjmp inside simd construct");
}
else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_GOMP_BARRIER:
case BUILT_IN_GOMP_CANCEL:
case BUILT_IN_GOMP_CANCELLATION_POINT:
case BUILT_IN_GOMP_TASKYIELD:
case BUILT_IN_GOMP_TASKWAIT:
case BUILT_IN_GOMP_TASKGROUP_START:
case BUILT_IN_GOMP_TASKGROUP_END:
remove = !check_omp_nesting_restrictions (stmt, ctx);
break;
default:
break;
}
}
}
if (remove)
{
@ -2967,7 +2999,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bool reduction_omp_orig_ref = false;
int pass;
bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
int max_vf = 0;
tree lane = NULL_TREE, idx = NULL_TREE;
tree ivar = NULL_TREE, lvar = NULL_TREE;
@ -3587,7 +3619,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
/* Don't add any barrier for #pragma omp simd or
#pragma omp distribute. */
if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
|| gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
|| gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
}
@ -3666,7 +3698,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
}
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
{
simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
if (simduid)
@ -3761,7 +3793,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
/* SIMD reductions are handled in lower_rec_input_clauses. */
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
return;
/* First see if there is exactly one reduction clause. Use OMP_ATOMIC
@ -6794,7 +6826,7 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt)
original loops from being detected. Fix that up. */
loops_state_set (LOOPS_NEED_FIXUP);
if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
expand_omp_simd (region, &fd);
else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
&& !fd.have_ordered)
@ -8236,7 +8268,8 @@ execute_expand_omp (void)
static bool
gate_expand_omp (void)
{
return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
return ((flag_openmp != 0 || flag_openmp_simd != 0
|| flag_enable_cilkplus != 0) && !seen_error ());
}
namespace {
@ -10057,7 +10090,7 @@ execute_lower_omp (void)
/* This pass always runs, to provide PROP_gimple_lomp.
But there is nothing to do unless -fopenmp is given. */
if (flag_openmp == 0 && flag_openmp_simd == 0)
if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
return 0;
all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@ -10177,12 +10210,33 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
error ("invalid entry to OpenMP structured block");
#endif
bool cilkplus_block = false;
if (flag_enable_cilkplus)
{
if ((branch_ctx
&& gimple_code (branch_ctx) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
|| (gimple_code (label_ctx) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
cilkplus_block = true;
}
/* If it's obvious we have an invalid entry, be specific about the error. */
if (branch_ctx == NULL)
error ("invalid entry to OpenMP structured block");
{
if (cilkplus_block)
error ("invalid entry to Cilk Plus structured block");
else
error ("invalid entry to OpenMP structured block");
}
else
/* Otherwise, be vague and lazy, but efficient. */
error ("invalid branch to/from an OpenMP structured block");
{
/* Otherwise, be vague and lazy, but efficient. */
if (cilkplus_block)
error ("invalid branch to/from a Cilk Plus structured block");
else
error ("invalid branch to/from an OpenMP structured block");
}
gsi_replace (gsi_p, gimple_build_nop (), false);
return true;
@ -10486,7 +10540,7 @@ diagnose_omp_structured_block_errors (void)
static bool
gate_diagnose_omp_blocks (void)
{
return flag_openmp != 0;
return flag_openmp || flag_enable_cilkplus;
}
namespace {

View File

@ -1,3 +1,10 @@
2013-11-15 Aldy Hernandez <aldyh@redhat.com>
* c-c++-common/cilk-plus/PS: New directory.
* g++.dg/cilk-plus/cilk-plus.exp: Run shared tests.
* g++.dg/dg.exp: Run Cilk Plus tests.
* gcc.dg/cilk-plus/cilk-plus.exp: Run shared tests.
2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* gcc.dg/vmx/3b-15.c: Revise for little endian.

View File

@ -0,0 +1,33 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus -fopenmp" } */
int *a, *b, c;
void *jmpbuf[10];
void foo()
{
int j;
#pragma simd
for (int i=0; i < 1000; ++i)
{
if (c == 6)
__builtin_setjmp (jmpbuf); /* { dg-error "setjmp" } */
a[i] = b[i];
}
#pragma simd
for (int i=0; i < 1000; ++i)
{
if (c==5)
break; /* { dg-error "break statement " } */
}
#pragma simd
for (int i=0; i < 1000; ++i)
{
#pragma omp for /* { dg-error "OpenMP constructs may not" } */
for (j=0; j < 1000; ++j)
a[i] = b[i];
}
}

View File

@ -0,0 +1,80 @@
/* { dg-do compile } */
/* { dg-options "-O3 -Werror -Wunknown-pragmas -fcilkplus" } */
volatile int *a, *b;
void foo()
{
int i, j, k;
#pragma simd assert /* { dg-error "expected '#pragma simd' clause" } */
for (i=0; i < 100; ++i)
a[i] = b[i];
#pragma simd vectorlength /* { dg-error "expected '\\('" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd vectorlength /* { dg-error "expected '\\('" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd vectorlength(sizeof (a) == sizeof (float) ? 4 : 8)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd vectorlength(4,8) /* { dg-error "expected '\\)'" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd vectorlength(i) /* { dg-error "\(vectorlength must be an integer\|in a constant\)" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(35) /* { dg-error "expected identifier" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(blah) /* { dg-error "'blah' \(undeclared\|has not been\)" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(j, 36, k) /* { dg-error "expected" } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(i, j)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(i)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(i : 4)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(i : 2, j : 4, k)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(j : sizeof (a) == sizeof (float) ? 4 : 8)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
// And now everyone in unison!
#pragma simd linear(j : 4) vectorlength(4)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(blah2, 36)
/* { dg-error "'blah2' \(undeclared\|has not been\)" "undeclared" { target *-*-* } 71 } */
/* { dg-error "expected" "expected" { target *-*-* } 71 } */
for (int i=0; i < 1000; ++i)
a[i] = b[j];
#pragma simd linear(j : k)
for (int i=0; i < 1234; ++i)
a[i] = b[j];
}

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-original -fcilkplus" } */
volatile int *a, *b;
void foo()
{
int j, k;
#pragma simd linear(j : 4, k) vectorlength(4)
for (int i=0; i < 1000; ++i)
a[i] = b[j];
}
/* { dg-final { scan-tree-dump-times "linear\\(j:4\\)" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "linear\\(k:1\\)" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "safelen\\(4\\)" 1 "original" } } */
/* { dg-final { cleanup-tree-dump "original" } } */

View File

@ -0,0 +1,39 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
#define N 1000
int A[N], B[N], C[N];
int main (void)
{
#pragma simd private (B) linear(B:1) /* { dg-error "more than one clause" } */
for (int ii = 0; ii < N; ii++)
{
A[ii] = B[ii] + C[ii];
}
#pragma simd private (B, C) linear(B:1) /* { dg-error "more than one clause" } */
for (int ii = 0; ii < N; ii++)
{
A[ii] = B[ii] + C[ii];
}
#pragma simd private (B) linear(C:2, B:1) /* { dg-error "more than one clause" } */
for (int ii = 0; ii < N; ii++)
{
A[ii] = B[ii] + C[ii];
}
#pragma simd reduction (+:B) linear(B:1) /* { dg-error "more than one clause" } */
for (int ii = 0; ii < N; ii++)
{
A[ii] = B[ii] + C[ii];
}
#pragma simd reduction (+:B) linear(B) /* { dg-error "more than one clause" } */
for (int ii = 0; ii < N; ii++)
{
A[ii] = B[ii] + C[ii];
}
return 0;
}

View File

@ -0,0 +1,132 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
int *a, *b, *c;
int something;
void foo()
{
int i, j;
// Declaration and initialization is allowed.
#pragma simd
for (int i=0; i < 1000; i++)
a[i] = b[j];
// Empty initialization is not allowed.
#pragma simd
for (; i < 5; ++i) // { dg-error "expected iteration" }
a[i] = i;
// Empty condition is not allowed.
#pragma simd
for (int i=0; ; ++i) /* { dg-error "missing controlling" } */
a[i] = i;
// Empty increment is not allowed.
#pragma simd
for (int i=0; i < 1234; ) /* { dg-error "missing increment" } */
a[i] = i*2;
#pragma simd
i = 5; /* { dg-error "for statement expected" } */
// Initialization variables must be either integral or pointer types.
struct S {
int i;
};
#pragma simd
for (struct S ss = { 0 }; ss.i <= 1000; ++ss.i) /* { dg-error "invalid controlling\|invalid type for iteration\|invalid increment" } */
a[ss.i] = b[ss.i];
#pragma simd
for (float f=0.0; f < 15.0; ++f) /* { dg-error "invalid type" } */
a[(int)f] = (int) f;
// Pointers are OK.
#pragma simd
for (int *i=c; i < &c[100]; ++i)
*a = '5';
// Condition of '==' is not allowed.
#pragma simd
for (int i=j; i == 5; ++i) /* { dg-error "invalid controlling predicate" } */
a[i] = b[i];
// The LHS or RHS of the condition must be the initialization variable.
#pragma simd
for (int i=0; i+j < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
a[i] = b[i];
// Likewise.
#pragma simd
for (int i=0; 1234 < i + j; ++i) /* { dg-error "invalid controlling predicate" } */
a[i] = b[i];
// Likewise, this is ok.
#pragma simd
for (int i=0; 1234 + j < i; ++i)
a[i] = b[i];
// According to the CilkPlus forum, casts are not allowed, even if
// they are no-ops.
#pragma simd
for (int i=0; (char)i < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
a[i] = b[i];
#pragma simd
for (int i=255; i != something; --i)
a[i] = b[i];
#pragma simd
for (int i=100; i != 5; i += something)
a[i] = b[i];
// Increment must be on the induction variable.
#pragma simd
for (int i=0; i < 100; j++) /* { dg-error "invalid increment expression" } */
a[i] = b[i];
// Likewise.
#pragma simd
for (int i=0; i < 100; j = i + 1) /* { dg-error "invalid increment expression" } */
a[i] = b[i];
// Likewise.
#pragma simd
for (int i=0; i < 100; i = j + 1) /* { dg-error "invalid increment expression" } */
a[i] = b[i];
#pragma simd
for (int i=0; i < 100; i = i + 5)
a[i] = b[i];
// Only PLUS and MINUS increments are allowed.
#pragma simd
for (int i=0; i < 100; i *= 5) /* { dg-error "invalid increment expression" } */
a[i] = b[i];
#pragma simd
for (int i=0; i < 100; i -= j)
a[i] = b[i];
#pragma simd
for (int i=0; i < 100; i = i + j)
a[i] = b[i];
#pragma simd
for (int i=0; i < 100; i = j + i)
a[i] = b[i];
#pragma simd
for (int i=0; i < 100; ++i, ++j) /* { dg-error "invalid increment expression" } */
a[i] = b[i];
#pragma simd
for (int *point=0; point < b; ++point)
*point = 555;
#pragma simd
for (int *point=0; point > b; --point)
*point = 555;
}

View File

@ -0,0 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
#pragma simd /* { dg-error "must be inside a function" } */
void foo()
{
}

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
int *a, *c;
void foo()
{
int i, j;
// Pointers are OK.
#pragma simd
for (int *i=c; i < c; ++i)
*a = '5';
}

View File

@ -0,0 +1,38 @@
/* { dg-do run } */
/* { dg-options "-O3 -fcilkplus" } */
/* FIXME: This test has been xfailed until reductions are fixed. */
int argc = 1;
/* This is a simple vectorization test. It tests if reduction works
and if it can vectorize the loop in func correctly. */
#define N 1000
int func (int *p, int *q) {
int x = 0;
#pragma simd reduction (+:x)
for (int ii = 0; ii < N; ii++) {
x += (q[ii] + p[ii]);
}
return x;
}
int main ()
{
int ii = 0, x;
int Array[N], Array2[N];
for (ii = 0; ii < N; ii++)
{
Array[ii] = 5 + argc;
Array2[ii] = argc;
}
x = func (Array, Array2);
if (x != N * 7)
return 1;
return 0;
}

View File

@ -0,0 +1,36 @@
/* { dg-do run } */
/* { dg-options "-O3 -fcilkplus" } */
/* FIXME: This test has been xfailed until reductions are fixed. */
#include <stdio.h>
#define ARRAY_SIZE (256)
int a[ARRAY_SIZE];
__attribute__((noinline))
int addit (int *arr, int N)
{
int s=0;
#pragma simd reduction (+:s)
for (int i = 0; i < N; i++)
s += arr[i];
return s;
}
int main () {
int i, s = 0, r = 0;
for (i = 0; i < ARRAY_SIZE; i++)
{
a[i] = i;
}
s = addit (a, ARRAY_SIZE);
for (i = 0; i < ARRAY_SIZE; i++)
r += i;
if (s == r)
return 0;
return 1;
}

View File

@ -0,0 +1,43 @@
/* { dg-do run } */
/* { dg-options "-O3 -fcilkplus" } */
/* FIXME: This test has been xfailed until reductions are fixed. */
#define N 256
#if HAVE_IO
#include <stdio.h>
#endif
#include <malloc.h>
int
reduction_simd (int *a)
{
int s = 0;
#pragma simd reduction (+:s)
for (int i = 0; i < N; i++)
{
s += a[i];
}
return s;
}
int
main ()
{
int *a = (int *) malloc (N * sizeof (int));
int i, s = (N - 1) * N / 2;
for (i = 0; i < N; i++)
{
a[i] = i;
}
#if HAVE_IO
printf ("%d, %d\n", s, reduction_simd (a));
#endif
if (s == reduction_simd (a))
return 0;
else
return 1;
}

View File

@ -0,0 +1,28 @@
/* { dg-do run } */
/* { dg-options "-fcilkplus -O3" } */
#include <stdlib.h>
#define N 4
float f1[] = { 2.0, 3.0, 4.0, 5.0 };
float f2[] = { 1.0, 6.0, -1.0, -2.0 };
float res[] = { 3.0, 9.0, 3.0, 3.0 };
__attribute__((noinline))
void verify (float *sum)
{
for (int i=0; i < N; ++i)
if (sum[i] != res[i])
abort ();
}
int main()
{
float sum[N];
#pragma simd
for (int i=0; i < N; ++i)
sum[i] = f1[i] + f2[i];
verify (sum);
return 0;
}

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-gimple -fcilkplus" } */
int *a, *b;
void foo()
{
#pragma simd vectorlength(8)
for (int i=0; i < 1000; ++i)
a[i] = b[i];
}
/* { dg-final { scan-tree-dump-times "safelen\\(8\\)" 1 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
volatile int *a, *b, N;
typedef int tint;
struct someclass {
int a;
char b;
int *p;
};
void foo()
{
#pragma simd vectorlength(4) vectorlength(8) /* { dg-error "too many 'vectorlength' clauses" } */
for (int i=0; i < N; ++i)
a[i] = b[i];
#pragma simd vectorlength(3) /* { dg-error "must be a power of 2" } */
for (int i=0; i < N; ++i)
a[i] = b[i];
}

View File

@ -16,13 +16,19 @@
# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
load_lib g++-dg.exp
if { ![check_effective_target_cilkplus] } {
return;
}
dg-init
# Run the tests that are shared with C.
g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
# Run the C++ only tests.
g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
dg-finish
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" " "

View File

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
// Test storage classes in the initialization of a <#pragma simd> for
// loop.
int *a, *b;
void foo()
{
#pragma simd
for (static int tt=5; tt < 10; ++tt) /* { dg-error "before 'static'\|not declared\|expected" } */
a[tt] = b[tt];
#pragma simd
for (extern int var=0; var < 1000; ++var) /* { dg-error "before 'extern'\|not declared\|expected" } */
a[var] = var;
#pragma simd
for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "before 'register'\|not declared\|expected" } */
b[regj] = a[regj] * 2;
#pragma simd
for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "iteration variable cannot be volatile" } */
a[vj] = b[vj];
}

View File

@ -0,0 +1,43 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int *p;
extern int stuff();
template <int value>
void foobar(int a)
{
#pragma simd
for (int i=0; i < a; ++i)
p[i] = value;
}
template <int value>
void foobar2(int a)
{
int j = 123;
#pragma simd linear(j : value)
for (int i=0; i < a; ++i)
{
p[i] = value;
j += stuff();
}
}
void funky()
{
foobar <69> (1000);
foobar2 <123> (2000);
}
void foobar3(int a)
{
int j = 123;
#pragma simd linear(j : a + a) /* { dg-error "step size must be an integer" } */
for (int i=0; i < a; ++i)
{
p[i] = 1234;
extern int bar();
j += bar();
}
}

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
// Test storage classes in the initialization of a <#pragma simd> for
// loop.
int *a, *b;
void foo()
{
#pragma simd
for (int tt=5; tt < 10; ++tt)
{
a[tt] = b[tt];
if (tt == 8)
throw 1; /* { dg-error "throw expressions are not allowed" } */
}
}

View File

@ -0,0 +1,22 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int *p;
extern int stuff();
template <int value>
void foobar(int a)
{
int j = 123;
#pragma simd linear(j : value + 1)
for (int i=0; i < a; ++i)
{
p[i] = value;
j += stuff();
}
}
void funky()
{
foobar <69> (1000);
}

View File

@ -49,6 +49,7 @@ set tests [prune $tests $srcdir/$subdir/tree-prof/*]
set tests [prune $tests $srcdir/$subdir/torture/*]
set tests [prune $tests $srcdir/$subdir/graphite/*]
set tests [prune $tests $srcdir/$subdir/tm/*]
set tests [prune $tests $srcdir/$subdir/cilk-plus/*]
set tests [prune $tests $srcdir/$subdir/guality/*]
set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
set tests [prune $tests $srcdir/$subdir/asan/*]

View File

@ -33,6 +33,13 @@ set ALWAYS_CFLAGS ""
lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs"
dg-init
# Run the tests that are shared with C++.
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] " -ftree-vectorize -fcilkplus -std=c99" " "
# Run the C-only tests.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
"-ftree-vectorize -fcilkplus -std=c99" " "
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]] " -O1 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -fcilkplus" " "

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
int *a, *b, *c;
void foo()
{
int i, j;
// The initialization shall declare or initialize a *SINGLE* variable.
#pragma simd
for (i=0, j=5; i < 1000; i++) // { dg-error "expected ';' before ','" }
a[i] = b[j];
}

View File

@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fcilkplus" } */
int *a, *b;
void foo()
{
#pragma simd
for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var\|invalid controlling\|invalid increment\|assignment of read" } */
a[ci] = b[ci];
}

View File

@ -0,0 +1,27 @@
/* { dg-do compile } */
/* { dg-options "-fcilkplus" } */
int *a, *b, c;
void foo()
{
#pragma simd
for (int i=0; i < 1000; ++i)
{
a[i] = b[i];
if (c == 5)
return; /* { dg-error "invalid branch to.from a Cilk" } */
}
}
void bar()
{
#pragma simd
for (int i=0; i < 1000; ++i)
{
lab:
a[i] = b[i];
}
if (c == 6)
goto lab; /* { dg-error "invalid entry to Cilk Plus" } */
}

View File

@ -2380,6 +2380,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, "#pragma omp simd");
goto dump_omp_loop;
case CILK_SIMD:
pp_string (buffer, "#pragma simd");
goto dump_omp_loop;
case OMP_DISTRIBUTE:
pp_string (buffer, "#pragma omp distribute");
goto dump_omp_loop;

View File

@ -1042,6 +1042,10 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
Operands like for OMP_FOR. */
DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
/* Cilk Plus - #pragma simd [clause1 ... clauseN]
Operands like for OMP_FOR. */
DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)
/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
Operands like for OMP_FOR. */
DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)