From patchwork Wed Jun 5 19:31:15 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 249170 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 841542C02A9 for ; Thu, 6 Jun 2013 05:31:33 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=Ojnk6+oYS5pkZ5BBS ec3l6QuZyVlGbVNx3JXO+OWtqXssYjqcpAE5F2Y/RmPIOdLl0afGmi1cVBz8KYm6 OGPLNJleO+S//aSxlZMQXa/R3egQGVLzewnxYn7EJonsBcj+nbi3LDWTykby6MKu BSo6QikSdeLNON5cj39SQzKBx8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=rhLY0LaWn/dW4NeSnWk2lRZ jOYU=; b=hpnz+hAY+aDvmyTYoecowcStaUH6hcQTyjArRpwV5yEhyn7M7xQrcyi Pdah2Io6CzUhIBRQNLcX9NQmPULRd0dysi9B5XaTsAj3rKkFLKRNSZU/mOEs/4KO iL74HeIZdyjulvUkzJhFIvJxmxEQ5IZs1P2GOncUXCcwKzINXKRE= Received: (qmail 1380 invoked by alias); 5 Jun 2013 19:31:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 1353 invoked by uid 89); 5 Jun 2013 19:31:24 -0000 X-Spam-SWARE-Status: No, score=-5.8 required=5.0 tests=AWL, BAYES_50, KHOP_THREADED, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS, TW_BJ, TW_EG, TW_JC, TW_TJ, TW_TM, TW_XT autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 05 Jun 2013 19:31:19 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r55JVHa9015660 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 5 Jun 2013 15:31:17 -0400 Received: from houston.quesejoda.com (vpn-50-213.rdu2.redhat.com [10.10.50.213]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r55JVFAg020753; Wed, 5 Jun 2013 15:31:16 -0400 Message-ID: <51AF9203.5080901@redhat.com> Date: Wed, 05 Jun 2013 14:31:15 -0500 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130311 Thunderbird/17.0.4 MIME-Version: 1.0 To: "Iyer, Balaji V" CC: "gcc-patches@gcc.gnu.org" , Jakub Jelinek Subject: Re: [gomp4/cilk-in-gomp/cilkplus] C++ parsing for Cilk plus <#pragma simd> References: In-Reply-To: X-Virus-Found: No On 05/21/13 10:46, Iyer, Balaji V wrote: > Hello Aldy et al., Attached, please find a patch on top of gomp4 > branch that implements Cilk's <#pragma simd> for C++. This is done in > the same fashion as Aldy did in: > http://gcc.gnu.org/ml/gcc-patches/2013-05/msg00678.html (It creates > OMP_SIMD trees and let omp-low do the rest). > > This patch should be applied on Aldy's branch aldyh/cilk-in-gomp. I > have also included testsuite code that will catch several errors. Hi Balaji. As promised, I have taken over your C++ FE changes and fixed everything I pointed out in my review. I replaced the tests you provided in your patch with my more comprehensive ones, after moving mine to the c-c++-common infrastructure. I moved all the C specific tests to testsuite/gcc.dg/cilk-plus/ and all the C++ specific tests to testsuite/g++.dg/cilk-plus. I changed some of the C++ FE errors to match the C front-end, and when not possible, have adapted the tests to match either the C or the C++ error messages. When the dust settles, I will see if your tests stress any cases that mine didn't and incorporate them if necessary. I cleaned up a lot of stuff, fixed buglets and ICEs that I found while running the tests. However, there are still a handful of failures that need to be fixed. For now I am testing with: make check RUNTESTFLAGS="cilk-plus.exp" which yields the following on x86-64 Linux: === gcc Summary === # of expected passes 65 === g++ Summary === # of expected passes 70 # of unexpected failures 60 The distinct failures are: c-c++-common/cilk-plus/PS/body.c c-c++-common/cilk-plus/PS/for1.c c-c++-common/cilk-plus/PS/for2.c c-c++-common/cilk-plus/PS/for3.c Attached is the patch I am committing to the branch. I will start looking at the remaining failures next, unless you get bored and want to look at them as well :). Thanks again for your patch. diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus index 5e9fb79..96a02c6 100644 --- a/gcc/ChangeLog.cilkplus +++ b/gcc/ChangeLog.cilkplus @@ -1,4 +1,5 @@ 2013-05-13 Aldy Hernandez + Balaji V. Iyer * Makefile.in (C_COMMON_OBJS): Depend on c-family/c-cilkplus.o. (c-cilkplus.o): New dependency. @@ -9,6 +10,8 @@ c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD enum. (enum pragma_cilk_clause): New. * c.opt (fcilkplus): New flag. + * c-common.h (c_finish_cilk_simd_loop): Protoize. + (c_finish_cilk_clauses): Same. c/ * c-parser.c (c_parser_pragma): Add case for PRAGMA_CILK_SIMD. @@ -19,8 +22,6 @@ c/ (c_parser_cilk_all_clauses): New. (c_parser_cilk_for_statement): New. (c_parser_cilk_simd_construct): New. - * c-tree.h (c_finish_cilk_simd_loop): Protoize. - (c_finish_cilk_clauses): Same. * c-typeck.c (c_finish_bc_stmt): Add case for _Cilk_for loops. testsuite/ diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c index 40284fe..84f1645 100644 --- a/gcc/c-family/c-cilkplus.c +++ b/gcc/c-family/c-cilkplus.c @@ -104,27 +104,22 @@ c_check_cilk_loop_incr (location_t loc, tree decl, tree incr) return error_mark_node; } -/* Callback for walk_tree. +/* Callback for 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 -find_invalid_stmts_in_loops (tree *tp, int *walk_subtrees, void *data) +tree +c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data) { if (!tp || !*tp) return NULL_TREE; bool *valid = (bool *) data; - // FIXME: Disallow the following constructs within a SIMD loop: - // - // _Cilk_spawn - // _Cilk_for - // try - /* FIXME: Jumps are disallowed into or out of the body of a _Cilk_for. We can't just check for GOTO_EXPR here, since GOTO_EXPR's can also be generated by switches and loops. @@ -205,7 +200,7 @@ static bool c_check_cilk_loop_body (tree body) { bool valid = true; - walk_tree (&body, find_invalid_stmts_in_loops, (void *) &valid, NULL); + walk_tree (&body, c_validate_cilk_plus_loop, (void *) &valid, NULL); return valid; } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 78ace77..f0a488e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1046,6 +1046,12 @@ extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree); extern void c_omp_declare_simd_clauses_to_decls (tree, tree); extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); +/* In c-cilkplus.c */ +extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree, + tree, tree); +extern tree c_finish_cilk_clauses (tree); +extern tree c_validate_cilk_plus_loop (tree *, int *, void *); + /* Not in c-omp.c; provided by the front end. */ extern bool c_omp_sharing_predetermined (tree); extern tree c_omp_remap_decl (tree, bool); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 84471db..93516da 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -647,11 +647,6 @@ extern tree c_build_va_arg (location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); -/* In c-cilkplus.c */ -extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree, - tree, tree); -extern tree c_finish_cilk_clauses (tree); - /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index ea4ec3d..fb7ffc5 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -9095,9 +9095,9 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break) case 2: if (is_break) - error ("break statement within _Cilk_for loop"); + error ("break statement within <#pragma simd> loop body"); else - error ("continue statement within _Cilk_for loop"); + error ("continue statement within <#pragma simd> loop loop"); return NULL_TREE; default: diff --git a/gcc/cp/ChangeLog.cilkplus b/gcc/cp/ChangeLog.cilkplus new file mode 100644 index 0000000..7254b81 --- /dev/null +++ b/gcc/cp/ChangeLog.cilkplus @@ -0,0 +1,18 @@ +2013-05-21 Balaji V. Iyer + + * cp-tree.h (p_simd_valid_stmts_in_body_p): New prototype. + * parser.h (IN_CILK_P_SIMD_FOR): New #define. + * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added new obj-file cp-cilkplus.o + * cp-cilkplus.c: New file. + * parser.c (cp_parser_pragma): Added a PRAGMA_CILK_SIMD case. + (cp_parser_cilk_simd_vectorlength): New function. + (cp_parser_cilk_simd_linear): Likewise. + (cp_parser_cilk_simd_clause_name): Likewise. + (cp_parser_cilk_simd_all_clauses): Likewise. + (cp_parser_cilk_simd_construct): Likewise. + (cp_parser_simd_for_init_statement): Likewise. + (cp_parser_cilk_for_expression_iterator): Likewise. + (cp_parser_cilk_for_condition): Likewise. + (cp_parser_cilk_for): Likewise. + (cp_parser_jump_statement): Added a IN_CILK_P_SIMD_FOR case. + diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index df8ed3e..0e40246 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -80,7 +80,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-gimplify.o $(CXX_C_OBJS) + cp/cp-gimplify.o cp/cp-cilkplus.o $(CXX_C_OBJS) # Language-specific object files for C++. CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS) @@ -345,3 +345,5 @@ cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h +cp/cp-cilkplus.o: cp/cp-cilkplus.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(CXX_TREE_H) $(DIAGNOSTIC_CORE_H) diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c new file mode 100644 index 0000000..f387e2f --- /dev/null +++ b/gcc/cp/cp-cilkplus.c @@ -0,0 +1,83 @@ +/* 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 Balaji V. Iyer , + Aldy Hernandez . + + 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 + . */ + +#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; + + // Call generic C version. + (void) c_validate_cilk_plus_loop (tp, walk_subtrees, data); + + 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; + } + /* FIXME: Add a check for TREE_CODE (*tp) == CILK_FOR_STMT and + flag them as invalid when cilk keywords are adopted. */ + 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; +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7046713..97e4e3c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6144,6 +6144,9 @@ extern bool cxx_omp_privatize_by_reference (const_tree); extern void suggest_alternatives_for (location_t, tree); extern tree strip_using_decl (tree); +/* in cp-cilkplus.c */ +extern bool cpp_validate_cilk_plus_loop (tree); + /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a30f52a..b4c6ba3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -231,6 +231,11 @@ static void cp_parser_initial_pragma static tree cp_literal_operator_id (const char *); +static void cp_parser_cilk_simd_construct + (cp_parser *, cp_token *); +static tree cp_parser_cilk_for + (cp_parser *, enum rid, tree); + /* Manifest constants. */ #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) #define CP_SAVED_TOKEN_STACK 5 @@ -10297,6 +10302,10 @@ 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_P_SIMD_FOR: + error_at (token->location, + "break statement within <#pragma simd> loop body"); + break; } cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); break; @@ -10314,6 +10323,10 @@ cp_parser_jump_statement (cp_parser* parser) case IN_OMP_BLOCK: error_at (token->location, "invalid exit from OpenMP structured block"); break; + case IN_CILK_P_SIMD_FOR: + error_at (token->location, + "continue statement within <#pragma simd> loop loop"); + break; default: gcc_unreachable (); } @@ -29851,6 +29864,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) "%<#pragma omp sections%> construct"); break; + case PRAGMA_CILK_SIMD: + if (context == pragma_external) + goto bad_stmt; + cp_parser_cilk_simd_construct (parser, pragma_tok); + return true; + default: gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); c_invoke_pragma_handler (id); @@ -29916,4 +29935,659 @@ 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; + } + + 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_constant_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 (!TREE_TYPE (e) || !TREE_CONSTANT (e) + || !INTEGRAL_TYPE_P (TREE_TYPE (e))) + cp_parser_error (parser, + "step size must be an integer constant"); + else + step_size = e; + } + + /* 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; + } + } + 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_construct (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, + "expected for-statement after %<#pragma simd%> clauses"); + return; + } + + /* #pragma simd is built on top of OpenMP 4.0's OMP_SIMD trees. */ + if (!flag_openmp) + flag_openmp = true; + + tree sb = begin_omp_structured_block (); + int save = cp_parser_begin_omp_structured_block (parser); + cp_parser_cilk_for (parser, RID_FOR, clauses); + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + return; +} + +/* Parses the initializer of a for/_Cilk_for statement. The initial + value is stored in *INIT, and the inital value's declaration is + stored as DECL_EXPR in *PRE_BODY. */ + +static tree +cp_parser_simd_for_init_statement (cp_parser *parser, tree *init, + tree *pre_body) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + tree decl = NULL_TREE; + cp_decl_specifier_seq type_specifiers; + tree this_pre_body = push_stmt_list (); + if (token->type == CPP_SEMICOLON) + { + error_at (loc, "for-loop initializer must declare variable"); + return error_mark_node; + } + cp_parser_parse_tentatively (parser); + cp_parser_type_specifier_seq (parser, true, false, &type_specifiers); + if (cp_parser_parse_definitely (parser)) + { + cp_declarator *cp_decl; + tree asm_spec, attr; + cp_decl = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, + NULL, NULL, false); + attr = cp_parser_attributes_opt (parser); + asm_spec = cp_parser_asm_specification_opt (parser); + if (cp_decl == cp_error_declarator) + cp_parser_skip_to_end_of_statement (parser); + else + { + tree pushed_scope, auto_node; + decl = start_decl (cp_decl, &type_specifiers, SD_INITIALIZED, attr, + 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_at (loc, "parenthesized initialization is " + "not allowed in for-loop"); + else + { + if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) + decl = error_mark_node; + } + + *init = error_mark_node; + cp_parser_skip_to_end_of_statement (parser); + } + else if (CLASS_TYPE_P (TREE_TYPE (decl)) || auto_node + || type_dependent_expression_p (decl)) + { + 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_spec, + LOOKUP_ONLYCONVERTING); + if (CLASS_TYPE_P (TREE_TYPE (decl))) + *init = NULL_TREE; + else + *init = pop_stmt_list (this_pre_body); + this_pre_body = NULL_TREE; + } + else + { + /* Consume the '='. */ + 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, false, asm_spec, + LOOKUP_ONLYCONVERTING); + if (decl != error_mark_node) + DECL_INITIAL (decl) = (*init || *init != error_mark_node) ? + *init : NULL_TREE; + } + if (pushed_scope) + pop_scope (pushed_scope); + } + } + else + { + cp_id_kind idk; + 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, new_expr; + cp_parser_parse_definitely (parser); + cp_parser_require (parser, CPP_EQ, RT_EQ); + rhs = cp_parser_assignment_expression (parser, false, NULL); + new_expr = build_x_modify_expr (EXPR_LOCATION (rhs), decl, + NOP_EXPR, rhs, + tf_warning_or_error); + finish_expr_stmt (new_expr); + } + else + { + decl = NULL_TREE; + cp_parser_abort_tentative_parse (parser); + *init = cp_parser_expression (parser, false, NULL); + } + } + + if (this_pre_body) + this_pre_body = pop_stmt_list (this_pre_body); + + *pre_body = this_pre_body; + return decl; +} + + +/* Parses the increment expresion for a cilk_for or for statement with + #pragma simd. */ + +static tree +cp_parser_cilk_for_expression_iterator (cp_parser *parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + tree name = NULL_TREE, expr = NULL_TREE; + enum tree_code t_code = NOP_EXPR; + + if (token->type == CPP_SEMICOLON) + { + error_at (token->location, "missing loop expression"); + return error_mark_node; + } + if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) + { + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + t_code = token->type == CPP_PLUS_PLUS ? PREINCREMENT_EXPR + : PREDECREMENT_EXPR; + } + + if (token->type != CPP_NAME) + { + error_at (token->location, "invalid loop expression"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + + name = cp_parser_lookup_name (parser, token->u.value, none_type, false, false, + false, NULL, token->location); + if (name == error_mark_node) + return error_mark_node; + + /* If name is not a declaration, then the loop is not valid. */ + if (!DECL_P (name)) + { + error_at (token->location, "invalid loop increment expression"); + return error_mark_node; + } + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + + if (t_code != NOP_EXPR) + { + if (token->type != CPP_CLOSE_PAREN) + { + error_at (token->location, "invalid loop expression"); + return error_mark_node; + } + return build2 (t_code, void_type_node, name, NULL_TREE); + } + + if (token->type == CPP_CLOSE_PAREN) + { + error_at (token->location, + "loop expression must modify control variable"); + return error_mark_node; + } + + cp_lexer_consume_token (parser->lexer); + if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) + return build2 (token->type == CPP_PLUS_PLUS ? POSTINCREMENT_EXPR + : POSTDECREMENT_EXPR, void_type_node, name, NULL_TREE); + else if (token->type == CPP_EQ) + { + sorry ("loop with = operator"); + return error_mark_node; + } + else if (token->type == CPP_PLUS_EQ || token->type == CPP_MINUS_EQ) + t_code = token->type == CPP_PLUS_EQ ? PLUS_EXPR : MINUS_EXPR; + else if (token->type == CPP_MOD_EQ || token->type == CPP_XOR_EQ + || token->type == CPP_DIV_EQ || token->type == CPP_AND_EQ + || token->type == CPP_OR_EQ || token->type == CPP_AND_EQ + || token->type == CPP_LSHIFT_EQ || token->type == CPP_RSHIFT_EQ) + { + error_at (token->location, "invalid loop increment operation"); + return error_mark_node; + } + else + { + error_at (token->location, "invalid loop expression"); + return error_mark_node; + } + expr = cp_parser_binary_expression (parser, false, false, PREC_NOT_OPERATOR, + NULL); + if (expr == error_mark_node) + return expr; + + return build2 (MODIFY_EXPR, void_type_node, name, + build2 (t_code, TREE_TYPE (name), name, expr)); +} + +/* Parses the condition for a for-loop with pragma simd or _Cilk_for + loop. */ + +static tree +cp_parser_cilk_for_condition (cp_parser *parser) +{ + tree lhs, rhs; + enum tree_code code = ERROR_MARK; + + lhs = cp_parser_binary_expression (parser, false, false, + PREC_SHIFT_EXPRESSION, NULL); + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_NOT_EQ: + code = NE_EXPR; + break; + case CPP_LESS: + code = LT_EXPR; + break; + case CPP_LESS_EQ: + code = LE_EXPR; + break; + case CPP_GREATER_EQ: + code = GE_EXPR; + break; + case CPP_GREATER: + code = GT_EXPR; + break; + case CPP_EQ_EQ: + error_at (cp_lexer_peek_token (parser->lexer)->location, + "equality test not permitted in the Cilk_for loop"); + break; + default: + error_at (cp_lexer_peek_token (parser->lexer)->location, + "missing comparison operator in the loop condition"); + } + cp_lexer_consume_token (parser->lexer); + + rhs = cp_parser_binary_expression (parser, false, false, + PREC_SHIFT_EXPRESSION, NULL); + parser->scope = NULL_TREE; + parser->qualifying_scope = NULL_TREE; + parser->object_scope = NULL_TREE; + + if (code == ERROR_MARK || lhs == error_mark_node || rhs == error_mark_node) + return error_mark_node; + + return build2 (code, boolean_type_node, lhs, rhs); +} + +/* Top-level function to parse _Cilk_for and for statements. */ + +static tree +cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses) +{ + bool valid = true; + tree cond = NULL_TREE; + tree incr_expr = NULL_TREE; + tree init = NULL_TREE, pre_body = NULL_TREE, decl; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + /* FIXME: Allow CILK_FOR into this function. That is, use this + function to parse _Cilk_for statments also. To do this + correctly, add another param. called "grain" to hold the + grainsize. */ + + gcc_assert (for_keyword == RID_FOR); + + if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword)) + { + if (for_keyword == RID_FOR) + cp_parser_error (parser, "for statement expected"); + else + cp_parser_error (parser, "_Cilk_for statement expected"); + return error_mark_node; + } + cp_lexer_consume_token (parser->lexer); + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + + if (for_keyword == RID_FOR) + decl = cp_parser_simd_for_init_statement (parser, &init, &pre_body); + + if (decl == error_mark_node) + valid = false; + else if (!decl || (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != DECL_EXPR)) + { + error_at (loc, "%s-loop initializer does not declare a variable", + for_keyword == RID_FOR ? "for" : "_Cilk_for"); + valid = false; + decl = error_mark_node; + } + else if (!processing_template_decl + && !DECL_NONTRIVIALLY_INITIALIZED_P (decl) + && !DECL_INITIAL (decl) + && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + { + error_at (loc, "control variable for the %s-loop needs to " + "be initialized", + for_keyword == RID_FOR ? "for" : "_Cilk_for"); + valid = false; + } + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + { + error_at (loc, "%s-loop initializer cannot have multiple variable " + "declarations", for_keyword == RID_FOR ? "for" : "_Cilk_for"); + cp_parser_skip_to_end_of_statement (parser); + valid = false; + } + + if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) + return error_mark_node; + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + error_at (loc, "%s-loop requires a condition", + for_keyword == RID_FOR ? "for" : "_Cilk_for"); + cond = error_mark_node; + } + else + cond = cp_parser_cilk_for_condition (parser); + + if (cond == error_mark_node) + valid = false; + cp_parser_consume_semicolon_at_end_of_statement (parser); + + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) + { + error_at (loc, "%s-loop requires an increment expression", + for_keyword == RID_FOR ? "for" : "_Cilk_for"); + incr_expr = error_mark_node; + } + else + incr_expr = cp_parser_cilk_for_expression_iterator (parser); + + if (incr_expr == error_mark_node) + { + cp_parser_skip_to_closing_parenthesis (parser, true, false, false); + valid = false; + } + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + { + cp_parser_skip_to_end_of_statement (parser); + valid = false; + } + + if (!valid) + { + gcc_assert (sorrycount || errorcount); + return error_mark_node; + } + + if (for_keyword == RID_FOR) + { + tree initv, incrv, condv, declv, omp_simd_node, body = NULL_TREE; + + parser->in_statement = IN_CILK_P_SIMD_FOR; + body = push_stmt_list (); + cp_parser_statement (parser, NULL_TREE, false, NULL); + body = pop_stmt_list (body); + + /* Check if the body satisfies all the requirement of a #pragma + simd for body. If it is invalid, then do not make the OpenMP + nodes, just return an error mark node. */ + if (!cpp_validate_cilk_plus_loop (body)) + return error_mark_node; + + /* Now pass all the information into finish_omp_for. */ + initv = make_tree_vec (1); + condv = make_tree_vec (1); + incrv = make_tree_vec (1); + declv = make_tree_vec (1); + TREE_VEC_ELT (initv, 0) = init; + TREE_VEC_ELT (condv, 0) = cond; + TREE_VEC_ELT (incrv, 0) = incr_expr; + TREE_VEC_ELT (declv, 0) = decl; + omp_simd_node = finish_omp_for (loc, OMP_SIMD, declv, initv, condv, + incrv, body, pre_body, clauses); + return omp_simd_node; + } + else + /* Fix this when _Cilk_for is added into the mix. */ + return NULL_TREE; +} + #include "gt-cp-parser.h" diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 6d9f1fb..48ec8dd 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -292,6 +292,7 @@ typedef struct GTY(()) cp_parser { #define IN_OMP_BLOCK 4 #define IN_OMP_FOR 8 #define IN_IF_STMT 16 +#define IN_CILK_P_SIMD_FOR 32 unsigned char in_statement; /* TRUE if we are presently parsing the body of a switch statement. diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c new file mode 100644 index 0000000..5ecefd5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c @@ -0,0 +1,35 @@ +/* { 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 == 5) + return; /* { dg-error "return statments are not allowed" } */ + if (c == 6) + __builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not allowed" } */ + a[i] = b[i]; + } + +#pragma simd + for (int i=0; i < 1000; ++i) + { + if (c==5) + break; /* { dg-error "break statement within" } */ + } + +#pragma simd + for (int i=0; i < 1000; ++i) + { +#pragma omp for /* { dg-error "OpenMP statements are not allowed" } */ + for (j=0; j < 1000; ++j) + a[i] = b[i]; + } +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c new file mode 100644 index 0000000..6d84791 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c @@ -0,0 +1,76 @@ +/* { 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]; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c new file mode 100644 index 0000000..71589c2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c @@ -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" } } */ diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c new file mode 100644 index 0000000..579b718 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c @@ -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; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c new file mode 100644 index 0000000..04773d1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c @@ -0,0 +1,139 @@ +/* { 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 decl" } + a[i] = i; + + // Empty condition is not allowed. +#pragma simd + for (int i=0; ; ++i) /* { dg-error "missing condition" } */ + 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 "initialization variable must be of integral or pointer type" } */ + a[ss.i] = b[ss.i]; + + #pragma simd + for (float f=0.0; f < 15.0; ++f) /* { dg-error "must be of integral" } */ + 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]; + + // This condition gets folded into "i != 0" by + // c_parser_cilk_for_statement(). This is allowed as per the "!=" + // allowance above. +#pragma simd + for (int i=100; i; --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; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c new file mode 100644 index 0000000..dc0a41e --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c @@ -0,0 +1,66 @@ +/* { 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 foo=5; foo < 10; ++foo) + a[foo] = b[foo]; + /* { dg-error "declaration of static variable" "storage class1" { target *-*-* } 12 } */ + /* { dg-error "induction variable cannot be static" "storage class2" { target *-*-* } 12 } */ + + static int bar; +#pragma simd + for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be static" } */ + a[bar] = bar; + +#pragma simd + for (extern int var=0; var < 1000; ++var) + a[var] = var; + /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* } 23 } */ + /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */ + /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 } */ + + extern int extvar; +#pragma simd + for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable cannot be extern" } */ + b[extvar] = a[extvar]; + + // This seems like it should be ok. + // Must check with standards people. +#pragma simd + for (auto int autoi = 0; autoi < 1000; ++autoi) + b[autoi] = a[autoi] * 2; + // Similarly here. + auto int autoj; +#pragma simd + for (auto int autoj = 0; autoj < 1000; ++autoj) + b[autoj] = a[autoj] * 2; + + register int regi; +#pragma simd + for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot be declared register" } */ + b[regi] = a[regi] * 2; + +#pragma simd + for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction variable cannot be declared register" } */ + b[regj] = a[regj] * 2; + + volatile int vi; +#pragma simd + for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be volatile" } */ + a[vi] = b[vi]; + +#pragma simd + for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable cannot be volatile" } */ + a[vj] = b[vj]; + +#pragma simd + for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var" } */ + a[ci] = b[ci]; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c new file mode 100644 index 0000000..8660627 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fcilkplus" } */ + +#pragma simd /* { dg-error "must be inside a function" } */ + +void foo() +{ +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c new file mode 100644 index 0000000..2c59de9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c @@ -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" } } */ diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c new file mode 100644 index 0000000..9aa4a68 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c @@ -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]; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp new file mode 100644 index 0000000..ab38903 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -0,0 +1,30 @@ +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . + +# Written by Balaji V. Iyer + +# Load support procs. +load_lib g++-dg.exp + +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 diff --git a/gcc/testsuite/g++.dg/cilk-plus/for.C b/gcc/testsuite/g++.dg/cilk-plus/for.C new file mode 100644 index 0000000..2295d21 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/for.C @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-ftree-vectorize -fcilkplus" } */ + +int *a, *b; + +void foo() +{ + int i; +#pragma simd + for (i=0; i < 10000; ++i) /* { dg-error "initializer does not declare a var" } */ + a[i] = b[i]; +} diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp index 7201359..a3e9c1f 100644 --- a/gcc/testsuite/g++.dg/dg.exp +++ b/gcc/testsuite/g++.dg/dg.exp @@ -48,6 +48,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/*] diff --git a/gcc/testsuite/gcc.dg/cilk-plus/auto.c b/gcc/testsuite/gcc.dg/cilk-plus/auto.c new file mode 100644 index 0000000..253acee --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/auto.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +int *a, *b; + +void foo() +{ + // This seems like it should be ok. + // Must check with standards people. +#pragma simd + for (auto int autoi = 0; autoi < 1000; ++autoi) + b[autoi] = a[autoi] * 2; + // Similarly here. + auto int autoj; +#pragma simd + for (auto int autoj = 0; autoj < 1000; ++autoj) + b[autoj] = a[autoj] * 2; +} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp new file mode 100644 index 0000000..623c3b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp @@ -0,0 +1,55 @@ +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . + +# Written by Balaji V. Iyer + + +load_lib gcc-dg.exp + +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" " " + +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" " " +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 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O0 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O1 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O2 -ftree-vectorize -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O3 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O0 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O1 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O3 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " " + +# Run the C-only tests. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \ + "-ftree-vectorize -fcilkplus -std=c99" " " + +dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c deleted file mode 100644 index 50b3ab1..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c +++ /dev/null @@ -1,35 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -fcilkplus -fopenmp" } */ - -int *a, *b, c; -void *jmpbuf[10]; - -void foo() -{ - int i, j; - -#pragma simd - for (i=0; i < 1000; ++i) - { - if (c == 5) - return; /* { dg-error "return statments are not allowed" } */ - if (c == 6) - __builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not allowed" } */ - a[i] = b[i]; - } - -#pragma simd - for (i=0; i < 1000; ++i) - { - if (c==5) - break; /* { dg-error "break statement within" } */ - } - -#pragma simd - for (i=0; i < 1000; ++i) - { -#pragma omp for /* { dg-error "OpenMP statements are not allowed" } */ - for (j=0; j < 1000; ++j) - a[i] = b[i]; - } -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp deleted file mode 100644 index 154bb8c..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2013 Free Software Foundation, Inc. - -# This program 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 of the License, or -# (at your option) any later version. -# -# This program 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 -# . - -load_lib gcc-dg.exp - -set OPTS "-fcilkplus -c -ftree-vectorize" - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " $OPTS" " " -dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c deleted file mode 100644 index d0a2f79..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c +++ /dev/null @@ -1,76 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -std=c99 -fcilkplus -Werror -Wunknown-pragmas" } */ - -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" } */ - 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" } */ - 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 (i=0; i < 1000; ++i) - a[i] = b[j]; - -#pragma simd linear(blah2, 36) - /* { dg-error "'blah2' undeclared" "undeclared" { target *-*-* } 71 } */ - /* { dg-error "expected '\\)'" "expected" { target *-*-* } 71 } */ - for (int i=0; i < 1000; ++i) - a[i] = b[j]; -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c deleted file mode 100644 index ca99ca8..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -std=c99 -fcilkplus -fdump-tree-original" } */ - -volatile int *a, *b; - -void foo() -{ - int i, j, k; - -#pragma simd linear(j : 4, k) vectorlength(4) - for (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" } } */ diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c deleted file mode 100644 index 5536884..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c +++ /dev/null @@ -1,41 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -std=c99 -fcilkplus" } */ - -#define N 1000 - -int A[N], B[N], C[N]; -int main (void) -{ - int ii = 0; - -#pragma simd private (B) linear(B:1) /* { dg-error "more than one clause" } */ - for (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 (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 (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 (ii = 0; ii < N; ii++) - { - A[ii] = B[ii] + C[ii]; - } - -#pragma simd reduction (+:B) linear(B) /* { dg-error "more than one clause" } */ - for (ii = 0; ii < N; ii++) - { - A[ii] = B[ii] + C[ii]; - } - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c deleted file mode 100644 index f8cc558..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c +++ /dev/null @@ -1,144 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -std=c99 -fcilkplus" } */ - -int *a, *b, *c; -int something; - -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]; - - // 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 decl" } - a[i] = i; - - // Empty condition is not allowed. -#pragma simd - for (i=0; ; ++i) /* { dg-error "missing condition" } */ - a[i] = i; - - // Empty increment is not allowed. -#pragma simd - for (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 "initialization variable must be of integral or pointer type" } */ - a[ss.i] = b[ss.i]; - - #pragma simd - for (float f=0.0; f < 15.0; ++f) /* { dg-error "must be of integral" } */ - 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 (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 (i=0; i+j < 1234; ++i) /* { dg-error "invalid controlling predicate" } */ - a[i] = b[i]; - - // Likewise. -#pragma simd - for (i=0; 1234 < i + j; ++i) /* { dg-error "invalid controlling predicate" } */ - a[i] = b[i]; - - // Likewise, this is ok. -#pragma simd - for (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 (i=0; (char)i < 1234; ++i) /* { dg-error "invalid controlling predicate" } */ - a[i] = b[i]; - -#pragma simd - for (i=255; i != something; --i) - a[i] = b[i]; - - // This condition gets folded into "i != 0" by - // c_parser_cilk_for_statement(). This is allowed as per the "!=" - // allowance above. -#pragma simd - for (i=100; i; --i) - a[i] = b[i]; - -#pragma simd - for (i=100; i != 5; i += something) - a[i] = b[i]; - - // Increment must be on the induction variable. -#pragma simd - for (i=0; i < 100; j++) /* { dg-error "invalid increment expression" } */ - a[i] = b[i]; - - // Likewise. -#pragma simd - for (i=0; i < 100; j = i + 1) /* { dg-error "invalid increment expression" } */ - a[i] = b[i]; - - // Likewise. -#pragma simd - for (i=0; i < 100; i = j + 1) /* { dg-error "invalid increment expression" } */ - a[i] = b[i]; - -#pragma simd - for (i=0; i < 100; i = i + 5) - a[i] = b[i]; - - // Only PLUS and MINUS increments are allowed. -#pragma simd - for (i=0; i < 100; i *= 5) /* { dg-error "invalid increment expression" } */ - a[i] = b[i]; - -#pragma simd - for (i=0; i < 100; i -= j) - a[i] = b[i]; - -#pragma simd - for (i=0; i < 100; i = i + j) - a[i] = b[i]; - -#pragma simd - for (i=0; i < 100; i = j + i) - a[i] = b[i]; - -#pragma simd - for (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; -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c deleted file mode 100644 index 2d09ae8..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c +++ /dev/null @@ -1,66 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -std=c99 -fcilkplus" } */ - -// Test storage classes in the initialization of a <#pragma simd> for -// loop. - -int *a, *b; - -void foo() -{ -#pragma simd - for (static int foo=5; foo < 10; ++foo) - a[foo] = b[foo]; - /* { dg-error "declaration of static variable" "storage class1" { target *-*-* } 12 } */ - /* { dg-error "induction variable cannot be static" "storage class2" { target *-*-* } 12 } */ - - static int bar; -#pragma simd - for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be static" } */ - a[bar] = bar; - -#pragma simd - for (extern int var=0; var < 1000; ++var) - a[var] = var; - /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* } 23 } */ - /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */ - /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 } */ - - extern int extvar; -#pragma simd - for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable cannot be extern" } */ - b[extvar] = a[extvar]; - - // This seems like it should be ok. - // Must check with standards people. -#pragma simd - for (auto int autoi = 0; autoi < 1000; ++autoi) - b[autoi] = a[autoi] * 2; - // Similarly here. - auto int autoj; -#pragma simd - for (auto int autoj = 0; autoj < 1000; ++autoj) - b[autoj] = a[autoj] * 2; - - register int regi; -#pragma simd - for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot be declared register" } */ - b[regi] = a[regi] * 2; - -#pragma simd - for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction variable cannot be declared register" } */ - b[regj] = a[regj] * 2; - - volatile int vi; -#pragma simd - for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be volatile" } */ - a[vi] = b[vi]; - -#pragma simd - for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable cannot be volatile" } */ - a[vj] = b[vj]; - -#pragma simd - for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var" } */ - a[ci] = b[ci]; -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c deleted file mode 100644 index 8660627..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c +++ /dev/null @@ -1,8 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -fcilkplus" } */ - -#pragma simd /* { dg-error "must be inside a function" } */ - -void foo() -{ -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c deleted file mode 100644 index 430aa41..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -fcilkplus -fdump-tree-gimple" } */ - -int *a, *b; - -void foo() -{ - int i; -#pragma simd vectorlength(8) - for (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" } } */ diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c deleted file mode 100644 index 4bff17d..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c +++ /dev/null @@ -1,22 +0,0 @@ -/* { 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() -{ - int i; -#pragma simd vectorlength(4) vectorlength(8) /* { dg-error "too many 'vectorlength' clauses" } */ - for (i=0; i < N; ++i) - a[i] = b[i]; - -#pragma simd vectorlength(3) /* { dg-error "must be a power of 2" } */ - for (i=0; i < N; ++i) - a[i] = b[i]; -} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for1.c b/gcc/testsuite/gcc.dg/cilk-plus/for1.c new file mode 100644 index 0000000..4fb5342 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/for1.c @@ -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]; +}