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:
parent
e19eea7164
commit
c02065fca1
50 changed files with 1912 additions and 263 deletions
|
@ -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):
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
93
gcc/c-family/c-cilkplus.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
264
gcc/c/c-parser.c
264
gcc/c/c-parser.c
|
@ -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:
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
77
gcc/cp/cp-cilkplus.c
Normal 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;
|
||||
}
|
|
@ -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,
|
||||
|
|
619
gcc/cp/parser.c
619
gcc/cp/parser.c
|
@ -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). */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
11
gcc/gimple.h
11
gcc/gimple.h
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
116
gcc/omp-low.c
116
gcc/omp-low.c
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
33
gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
Normal file
33
gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
Normal 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];
|
||||
}
|
||||
}
|
80
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c
Normal file
80
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c
Normal 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];
|
||||
}
|
18
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c
Normal file
18
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c
Normal 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" } } */
|
39
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c
Normal file
39
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c
Normal 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;
|
||||
}
|
132
gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c
Normal file
132
gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c
Normal 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;
|
||||
}
|
8
gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
Normal file
8
gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -fcilkplus" } */
|
||||
|
||||
#pragma simd /* { dg-error "must be inside a function" } */
|
||||
|
||||
void foo()
|
||||
{
|
||||
}
|
14
gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c
Normal file
14
gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c
Normal 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';
|
||||
}
|
38
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c
Normal file
38
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c
Normal 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;
|
||||
}
|
||||
|
36
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c
Normal file
36
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c
Normal 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;
|
||||
}
|
43
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c
Normal file
43
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c
Normal 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;
|
||||
}
|
28
gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c
Normal file
28
gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c
Normal 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;
|
||||
}
|
14
gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c
Normal file
14
gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c
Normal 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" } } */
|
21
gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c
Normal file
21
gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c
Normal 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];
|
||||
}
|
|
@ -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" " "
|
||||
|
|
26
gcc/testsuite/g++.dg/cilk-plus/for.C
Normal file
26
gcc/testsuite/g++.dg/cilk-plus/for.C
Normal 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];
|
||||
}
|
43
gcc/testsuite/g++.dg/cilk-plus/for2.C
Normal file
43
gcc/testsuite/g++.dg/cilk-plus/for2.C
Normal 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();
|
||||
}
|
||||
}
|
18
gcc/testsuite/g++.dg/cilk-plus/for3.C
Normal file
18
gcc/testsuite/g++.dg/cilk-plus/for3.C
Normal 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" } */
|
||||
}
|
||||
}
|
22
gcc/testsuite/g++.dg/cilk-plus/for4.C
Normal file
22
gcc/testsuite/g++.dg/cilk-plus/for4.C
Normal 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);
|
||||
}
|
|
@ -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/*]
|
||||
|
|
|
@ -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" " "
|
||||
|
|
12
gcc/testsuite/gcc.dg/cilk-plus/for1.c
Normal file
12
gcc/testsuite/gcc.dg/cilk-plus/for1.c
Normal 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];
|
||||
}
|
11
gcc/testsuite/gcc.dg/cilk-plus/for2.c
Normal file
11
gcc/testsuite/gcc.dg/cilk-plus/for2.c
Normal 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];
|
||||
}
|
27
gcc/testsuite/gcc.dg/cilk-plus/jump.c
Normal file
27
gcc/testsuite/gcc.dg/cilk-plus/jump.c
Normal 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" } */
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue