Message ID | BF230D13CA30DD48930C31D4099330003A4B23A0@FMSMSX101.amr.corp.intel.com |
---|---|
State | New |
Headers | show |
On Mon, Dec 16, 2013 at 09:41:43PM +0000, Iyer, Balaji V wrote: > --- gcc/c/c-parser.c (revision 205759) > +++ gcc/c/c-parser.c (working copy) > @@ -208,6 +208,12 @@ > /* True if we are in a context where the Objective-C "Property attribute" > keywords are valid. */ > BOOL_BITFIELD objc_property_attr_context : 1; > + > + /* Cilk Plus specific parser/lexer information. */ > + > + /* Buffer to hold all the tokens from parsing the vector attribute for the > + SIMD-enabled functions (formerly known as elemental functions). */ > + vec <c_token, va_gc> *cilk_simd_fn_tokens; > } c_parser; Joseph, is this ok for you? > +/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector," > + "__vector" or "__vector__." */ > + > +static bool static inline bool > +is_cilkplus_vector_p (tree name) > +{ > + if (flag_enable_cilkplus > + && (simple_cst_equal (name, get_identifier ("vector")) == 1 > + || simple_cst_equal (name, get_identifier ("__vector")) == 1 > + || simple_cst_equal (name, get_identifier ("__vector__")) == 1)) > + return true; > + return false; > +} Why not just return flag_enable_cilkplus && is_attribute_p ("vector", name); ? > +#define CILK_SIMD_FN_CLAUSE_MASK \ > + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) I thought you'd instead add there PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK (or similar). > + if (token->type == CPP_NAME > + && TREE_CODE (token->value) == IDENTIFIER_NODE) > + if (simple_cst_equal (token->value, > + get_identifier ("vectorlength")) == 1) Why the simple_cst_equal + get_identifier? I mean, strcmp on IDENTIFIER_POINTER should be cheaper, and done elsewhere in c-parser.c. > + { > + if (!c_parser_cilk_clause_vectorlength (parser, NULL, true)) Why do you parse it here? Just parse it when parsing other clauses, and only during parsing of vectorlength clause create OMP_CLAUSE_SAFELEN out of it (after all the verifications). > + if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) > + { > + error_at (clause_loc, "using parameters for %<linear%> step is " > + "not supported in this release"); > + step = integer_one_node; That would be sorry, not error_at. > here = c_parser_peek_token (parser)->location; > - c_kind = c_parser_omp_clause_name (parser); > + > + if (mask == CILK_SIMD_FN_CLAUSE_MASK) Ugh, no. > + c_kind = c_parser_cilk_simd_fn_clause_name (parser); > + else > + c_kind = c_parser_omp_clause_name (parser); Always parse it the same, just use PRAGMA_CILK_CLAUSE_* for the Cilk+ specific clauses. > > switch (c_kind) > { > @@ -10933,7 +11092,8 @@ > c_name = "aligned"; > break; > case PRAGMA_OMP_CLAUSE_LINEAR: > - clauses = c_parser_omp_clause_linear (parser, clauses); > + clauses = c_parser_omp_clause_linear > + (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK); Again, this is too ugly. Perhaps check if (mask & PRAGMA_CILK_CLAUSE_VECTORLENGTH) != 0 or similar. Jakub
Hi Jakub, I will work on this, but I need a couple clarifications about some of your comments. Please see below: > > +#define CILK_SIMD_FN_CLAUSE_MASK \ > > + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) > \ > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) > \ > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) > \ > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) > \ > > + | (OMP_CLAUSE_MASK_1 << > PRAGMA_OMP_CLAUSE_NOTINBRANCH)) > > I thought you'd instead add there PRAGMA_CILK_CLAUSE_VECTORLENGTH, > PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK (or > similar). > I looked at OpenACC implementation and they seem to use the OMP_CLAUSE_* (line # 11174 in c-parser.c) Also, If I created CILK_CLAUSE_* variants, I have to re-create another function similar to c_parser_omp_all_clauses, whose workings will be identical to the c_parser_omp_all_clauses. Is that OK with you? More below..... > > + if (token->type == CPP_NAME > > + && TREE_CODE (token->value) == IDENTIFIER_NODE) > > + if (simple_cst_equal (token->value, > > + get_identifier ("vectorlength")) == 1) > > Why the simple_cst_equal + get_identifier? I mean, strcmp on > IDENTIFIER_POINTER should be cheaper, and done elsewhere in c-parser.c. > > > + { > > + if (!c_parser_cilk_clause_vectorlength (parser, NULL, true)) > > Why do you parse it here? Just parse it when parsing other clauses, and only > during parsing of vectorlength clause create OMP_CLAUSE_SAFELEN out of it > (after all the verifications). > > > here = c_parser_peek_token (parser)->location; > > - c_kind = c_parser_omp_clause_name (parser); > > + > > + if (mask == CILK_SIMD_FN_CLAUSE_MASK) > > Ugh, no. > > > + c_kind = c_parser_cilk_simd_fn_clause_name (parser); > > + else > > + c_kind = c_parser_omp_clause_name (parser); > ... Having a separate clause_name function seem to work and will do the mapping from Cilk Plus clause to OMP's right before calling the functions to handle it. > Always parse it the same, just use PRAGMA_CILK_CLAUSE_* for the Cilk+ > specific clauses. > > > > switch (c_kind) > > { > > @@ -10933,7 +11092,8 @@ > > c_name = "aligned"; > > break; > > case PRAGMA_OMP_CLAUSE_LINEAR: > > - clauses = c_parser_omp_clause_linear (parser, clauses); > > + clauses = c_parser_omp_clause_linear > > + (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK); > > Again, this is too ugly. Perhaps check if (mask & > PRAGMA_CILK_CLAUSE_VECTORLENGTH) != 0 or similar. > In this spot, I am looking for linear () clause, and I want do differentiate between OMP and CIlk Plus. The only way I know of to do it here is to check if the mask is a Cilk Plus one or OMP one (thus checking mask == CILK_SIMD_FN_CLAUSE_MASK). So how does anding mask with vectorlength do the trick? Thanks, Balaji V. Iyer. > Jakub
On Tue, Dec 17, 2013 at 03:51:14AM +0000, Iyer, Balaji V wrote: > Hi Jakub, > I will work on this, but I need a couple clarifications about some of your comments. Please see below: > > > > +#define CILK_SIMD_FN_CLAUSE_MASK \ > > > + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) > > \ > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) > > \ > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) > > \ > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) > > \ > > > + | (OMP_CLAUSE_MASK_1 << > > PRAGMA_OMP_CLAUSE_NOTINBRANCH)) > > > > I thought you'd instead add there PRAGMA_CILK_CLAUSE_VECTORLENGTH, > > PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK (or > > similar). > > > > I looked at OpenACC implementation and they seem to use the OMP_CLAUSE_* (line # 11174 in c-parser.c) It uses just PRAGMA_OMP_CLAUSE_NONE, which really means no clauses at all (I think it is for now). > Also, If I created CILK_CLAUSE_* variants, I have to re-create another function similar to c_parser_omp_all_clauses, whose workings will be identical to the c_parser_omp_all_clauses. Is that OK with you? No, I'd remove enum pragma_cilk_clause altogether and fold it into the end of pragma_omp_clause, as: PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_MASK, PRAGMA_CILK_CLAUSE_NOMASK, PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE, PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR, PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, PRAGMA_CILK_CLAUSE_LASTPRIVATE = PRAGMA_OMP_CLAUSE_LASTPRIVATE, PRAGMA_CILK_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION so that you can use it in the same bitmasks. That way, you don't have to change anything in c_parser_omp_all_clauses, just add handling of the 3 clauses that don't have OpenMP counterparts. Jakub
Hi! For reference, here's my rationale for OpenACC on this topic: On Tue, 17 Dec 2013 07:17:31 +0100, Jakub Jelinek <jakub@redhat.com> wrote: > On Tue, Dec 17, 2013 at 03:51:14AM +0000, Iyer, Balaji V wrote: > > Hi Jakub, > > I will work on this, but I need a couple clarifications about some of your comments. Please see below: > > > > > > +#define CILK_SIMD_FN_CLAUSE_MASK \ > > > > + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << > > > PRAGMA_OMP_CLAUSE_NOTINBRANCH)) > > > > > > I thought you'd instead add there PRAGMA_CILK_CLAUSE_VECTORLENGTH, > > > PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK (or > > > similar). > > > > > > > I looked at OpenACC implementation and they seem to use the OMP_CLAUSE_* (line # 11174 in c-parser.c) > > It uses just PRAGMA_OMP_CLAUSE_NONE, which really means no clauses at all (I > think it is for now). Right, that's only for now. > > Also, If I created CILK_CLAUSE_* variants, I have to re-create another function similar to c_parser_omp_all_clauses, whose workings will be identical to the c_parser_omp_all_clauses. Is that OK with you? > > No, I'd remove enum pragma_cilk_clause altogether and fold it into the end of > pragma_omp_clause, as: > PRAGMA_CILK_CLAUSE_VECTORLENGTH, > PRAGMA_CILK_CLAUSE_MASK, > PRAGMA_CILK_CLAUSE_NOMASK, > PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE, > PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR, > PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, > PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, > PRAGMA_CILK_CLAUSE_LASTPRIVATE = PRAGMA_OMP_CLAUSE_LASTPRIVATE, > PRAGMA_CILK_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION > so that you can use it in the same bitmasks. Hmm, indeed my inclination (and what I have implemented in my working trees) has been to literally re-use the existing PRAGMA_OMP_* ones for OpenACC, without adding new aliasesm, and extend/add new ones as required. My understanding/reasoning is that PRAGMA_OMP_* just literally represents a parser token of a pragma line (see the one-to-one translation in c-parser.c:c_parser_omp_clause_name, for example). This means that »#pragma omp parallel copyin ([...])« and »#pragma acc parallel copyin ([...])« can share the same PRAGMA_OMP_CLAUSE_COPYIN, even though it means something different to both of them; PRAGMA_OMP_CLAUSE_* alone doesn't convey any meaning (apart from the token/"string" used in the pragma line), and it gets its meaning only if interpreted as part of a Open* construct/directive. Just like many other tokens only get their semantic meaning when parsed inside a specific language construct. For OpenACC, the disambiguation, that is, translation from PRAGMA_OMP_CLAUSE_* to OMP_CLAUSE_*... > That way, you don't have to change anything in c_parser_omp_all_clauses, > just add handling of the 3 clauses that don't have OpenMP counterparts. ... then indeed happens in a new c_parser_oacc_all_clauses, which parses all the applicable PRAGMA_OMP_CLAUSE_* according to the OpenACC semantics. For example, said PRAGMA_OMP_CLAUSE_COPYIN is translated to OMP_CLAUSE_MAP with OMP_CLAUSE_MAP_TO, and the (new) PRAGMA_OMP_CLAUSE_PRESENT_OR_COPYOUT (which is only interpreted/valid inside OpenACC contexts) is translated to OMP_CLAUSE_MAP with (new) OMP_CLAUSE_MAP_PRESENT_OR_FROM (which is only interpreted/valid inside OpenACC contexts). Grüße, Thomas
On Tue, Dec 17, 2013 at 11:03:12AM +0100, Thomas Schwinge wrote: > > > Also, If I created CILK_CLAUSE_* variants, I have to re-create another function similar to c_parser_omp_all_clauses, whose workings will be identical to the c_parser_omp_all_clauses. Is that OK with you? > > > > No, I'd remove enum pragma_cilk_clause altogether and fold it into the end of > > pragma_omp_clause, as: > > PRAGMA_CILK_CLAUSE_VECTORLENGTH, > > PRAGMA_CILK_CLAUSE_MASK, > > PRAGMA_CILK_CLAUSE_NOMASK, > > PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE, > > PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR, > > PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, > > PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, > > PRAGMA_CILK_CLAUSE_LASTPRIVATE = PRAGMA_OMP_CLAUSE_LASTPRIVATE, > > PRAGMA_CILK_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION > > so that you can use it in the same bitmasks. > > Hmm, indeed my inclination (and what I have implemented in my working > trees) has been to literally re-use the existing PRAGMA_OMP_* ones for > OpenACC, without adding new aliasesm, and extend/add new ones as > required. The aliases would be only if they are needed, I understood that those are already used in #pragma simd parsing. Surely, if they are renamed to PRAGMA_OMP_* where they have counterparts, the aliases aren't needed. > My understanding/reasoning is that PRAGMA_OMP_* just literally represents > a parser token of a pragma line (see the one-to-one translation in > c-parser.c:c_parser_omp_clause_name, for example). This means that > »#pragma omp parallel copyin ([...])« and »#pragma acc parallel copyin > ([...])« can share the same PRAGMA_OMP_CLAUSE_COPYIN, even though it > means something different to both of them; PRAGMA_OMP_CLAUSE_* alone > doesn't convey any meaning (apart from the token/"string" used in the > pragma line), and it gets its meaning only if interpreted as part of a > Open* construct/directive. Just like many other tokens only get their > semantic meaning when parsed inside a specific language construct. For > OpenACC, the disambiguation, that is, translation from > PRAGMA_OMP_CLAUSE_* to OMP_CLAUSE_*... > > > That way, you don't have to change anything in c_parser_omp_all_clauses, > > just add handling of the 3 clauses that don't have OpenMP counterparts. > > ... then indeed happens in a new c_parser_oacc_all_clauses, which parses > all the applicable PRAGMA_OMP_CLAUSE_* according to the OpenACC > semantics. Unlike OpenACC, Cilk+ for the vector attribute has pretty much the OpenMP syntax, with just a few exceptions (in particular, 3 clauses have different names (and there are extra requirements for vectorlength?) and for linear there is an extension on the Cilk+ side. So, duplicating the c_parser_*all_clauses in that case is IMHO not needed, the mask specifies which clauses are allowed in the particular construct and the only case which needs disambiguation (linear clauses' step) can be disambiguated by checking if some Cilk+ specific clause is in the mask (already the clause splitting code uses such tests). If OpenACC clauses have different names from the OpenMP/Cilk+ ones, I don't see why you would need a new *_all_clauses function, just supply a different mask (unless we run out of the 64-bits in the bitmask, then we'd need extra steps, perhaps start using real bitmasks or something). > For example, said PRAGMA_OMP_CLAUSE_COPYIN is translated to > OMP_CLAUSE_MAP with OMP_CLAUSE_MAP_TO, and the (new) > PRAGMA_OMP_CLAUSE_PRESENT_OR_COPYOUT (which is only interpreted/valid > inside OpenACC contexts) is translated to OMP_CLAUSE_MAP with (new) > OMP_CLAUSE_MAP_PRESENT_OR_FROM (which is only interpreted/valid inside > OpenACC contexts). This is weird, because present or {alloc,from,to,fromto} is the OpenMP behavior, so I'd expect you would be adding a bit for the other, non-OpenMP compatible behavior instead. Jakub
Hi! On Tue, 17 Dec 2013 11:27:51 +0100, Jakub Jelinek <jakub@redhat.com> wrote: > On Tue, Dec 17, 2013 at 11:03:12AM +0100, Thomas Schwinge wrote: > > My understanding/reasoning is that PRAGMA_OMP_* just literally represents > > a parser token of a pragma line (see the one-to-one translation in > > c-parser.c:c_parser_omp_clause_name, for example). This means that > > »#pragma omp parallel copyin ([...])« and »#pragma acc parallel copyin > > ([...])« can share the same PRAGMA_OMP_CLAUSE_COPYIN, even though it > > means something different to both of them; PRAGMA_OMP_CLAUSE_* alone > > doesn't convey any meaning (apart from the token/"string" used in the > > pragma line), and it gets its meaning only if interpreted as part of a > > Open* construct/directive. Just like many other tokens only get their > > semantic meaning when parsed inside a specific language construct. For > > OpenACC, the disambiguation, that is, translation from > > PRAGMA_OMP_CLAUSE_* to OMP_CLAUSE_*... > > > > > That way, you don't have to change anything in c_parser_omp_all_clauses, > > > just add handling of the 3 clauses that don't have OpenMP counterparts. > > > > ... then indeed happens in a new c_parser_oacc_all_clauses, which parses > > all the applicable PRAGMA_OMP_CLAUSE_* according to the OpenACC > > semantics. > > Unlike OpenACC, Cilk+ for the vector attribute has pretty much the OpenMP > syntax, with just a few exceptions (in particular, 3 clauses have different > names (and there are extra requirements for vectorlength?) and for linear > there is an extension on the Cilk+ side. So, duplicating the > c_parser_*all_clauses in that case is IMHO not needed, the mask specifies > which clauses are allowed in the particular construct and the only case > which needs disambiguation (linear clauses' step) can be disambiguated > by checking if some Cilk+ specific clause is in the mask (already the > clause splitting code uses such tests). Right, if they're that similar, I agree that's the way to go. > If OpenACC clauses have different names from the OpenMP/Cilk+ ones, I don't > see why you would need a new *_all_clauses function, just supply a different > mask OpenACC clauses share some clause names and their semantics with OpenMP, and some new ones, but there are also several that have the same name (such as said copyin) but with a different meaning. For example for the copyin case, my understanding is that I can either re-use the existing PRAGMA_OMP_CLAUSE_COPYIN but then need to interpret it differently in an OpenACC context, and thus need a new c_parser_oacc_all_clauses (or add some ugly »if ([inside OpenACC directive]) { [...] } else { [existing OpenMP code]}«. Alternatively, I have to add a new PRAGMA_OMP_CLAUSE_OACC_COPYIN, and can then use the existing c_parser_omp_all_clauses. Due to the perceived one-to-one mapping between the existing PRAGMA_OMP_CLAUSE_* and the tokens (such as "copyin"), the former seemed more appropriate to me, as detailed above. > > For example, said PRAGMA_OMP_CLAUSE_COPYIN is translated to > > OMP_CLAUSE_MAP with OMP_CLAUSE_MAP_TO, and the (new) > > PRAGMA_OMP_CLAUSE_PRESENT_OR_COPYOUT (which is only interpreted/valid > > inside OpenACC contexts) is translated to OMP_CLAUSE_MAP with (new) > > OMP_CLAUSE_MAP_PRESENT_OR_FROM (which is only interpreted/valid inside > > OpenACC contexts). > > This is weird, because present or {alloc,from,to,fromto} is the OpenMP > behavior, so I'd expect you would be adding a bit for the other, non-OpenMP > compatible behavior instead. I'm currently working on this. Per my current understanding, in the front end and middle end (gimplify.c, omp-low.c), the handling of present_or_* vs. their "normal" variants is the same for OpenACC, and the difference is only apparent once they're interpreted in the runtime library, which is free to decide which way round to interpret the present_or bit. Anyway, you're absolutely right that I should preserve the same meaning of the map kinds, such as OMP_CLAUSE_MAP_FROM, for both the OpenACC (meaning present_or_copyout) and OpenMP (meaning map from) entry points, to avoid confusion at this level. Especially if their semantics are exactly the same (to be checked), and especially given we're trying to converge on the shared infrastructure, as I'm advocating it myself... I hope to post some code soon, which will hopefully help to display my ideas. Grüße, Thomas
> -----Original Message----- > From: Jakub Jelinek [mailto:jakub@redhat.com] > Sent: Tuesday, December 17, 2013 1:18 AM > To: Iyer, Balaji V > Cc: Joseph S. Myers; Aldy Hernandez; 'gcc-patches@gcc.gnu.org' > Subject: Re: [PING]: [GOMP4] [PATCH] SIMD-Enabled Functions (formerly > Elemental functions) for C > > On Tue, Dec 17, 2013 at 03:51:14AM +0000, Iyer, Balaji V wrote: > > Hi Jakub, > > I will work on this, but I need a couple clarifications about some of > your comments. Please see below: > > > > > > +#define CILK_SIMD_FN_CLAUSE_MASK \ > > > > + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) > > > \ > > > > + | (OMP_CLAUSE_MASK_1 << > > > PRAGMA_OMP_CLAUSE_NOTINBRANCH)) > > > > > > I thought you'd instead add there > PRAGMA_CILK_CLAUSE_VECTORLENGTH, > > > PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK > (or similar). > > > > > > > I looked at OpenACC implementation and they seem to use the > OMP_CLAUSE_* (line # 11174 in c-parser.c) > > It uses just PRAGMA_OMP_CLAUSE_NONE, which really means no clauses at > all (I > think it is for now). > > > Also, If I created CILK_CLAUSE_* variants, I have to re-create another > function similar to c_parser_omp_all_clauses, whose workings will be > identical to the c_parser_omp_all_clauses. Is that OK with you? > > No, I'd remove enum pragma_cilk_clause altogether and fold it into the end > of > pragma_omp_clause, as: > PRAGMA_CILK_CLAUSE_VECTORLENGTH, > PRAGMA_CILK_CLAUSE_MASK, > PRAGMA_CILK_CLAUSE_NOMASK, > PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE, > PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR, > PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, > PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = > PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, > PRAGMA_CILK_CLAUSE_LASTPRIVATE = > PRAGMA_OMP_CLAUSE_LASTPRIVATE, > PRAGMA_CILK_CLAUSE_REDUCTION = > PRAGMA_OMP_CLAUSE_REDUCTION > so that you can use it in the same bitmasks. > > That way, you don't have to change anything in c_parser_omp_all_clauses, > just add handling of the 3 clauses that don't have OpenMP counterparts. I think it sort of makes sense to me now. I will work on this. Oh, VECTORLENGTH in SIMD-enabled function is same as SIMDLEN in OMP4 And, MASK = INBRANCH NOMASK = NOTINBRANCH. Thanks, Balaji V. Iyer. > > Jakub
On Mon, 16 Dec 2013, Jakub Jelinek wrote: > On Mon, Dec 16, 2013 at 09:41:43PM +0000, Iyer, Balaji V wrote: > > --- gcc/c/c-parser.c (revision 205759) > > +++ gcc/c/c-parser.c (working copy) > > @@ -208,6 +208,12 @@ > > /* True if we are in a context where the Objective-C "Property attribute" > > keywords are valid. */ > > BOOL_BITFIELD objc_property_attr_context : 1; > > + > > + /* Cilk Plus specific parser/lexer information. */ > > + > > + /* Buffer to hold all the tokens from parsing the vector attribute for the > > + SIMD-enabled functions (formerly known as elemental functions). */ > > + vec <c_token, va_gc> *cilk_simd_fn_tokens; > > } c_parser; > > Joseph, is this ok for you? Fine with me.
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 205759) +++ gcc/c-family/c-common.c (working copy) @@ -771,6 +771,8 @@ handle_returns_nonnull_attribute, false }, { "omp declare simd", 0, -1, true, false, false, handle_omp_declare_simd_attribute, false }, + { "cilk simd function", 0, -1, true, false, false, + handle_omp_declare_simd_attribute, false }, { "omp declare target", 0, 0, true, false, false, handle_omp_declare_target_attribute, false }, { "bnd_variable_size", 0, 0, true, false, false, Index: gcc/c/c-parser.c =================================================================== --- gcc/c/c-parser.c (revision 205759) +++ gcc/c/c-parser.c (working copy) @@ -208,6 +208,12 @@ /* True if we are in a context where the Objective-C "Property attribute" keywords are valid. */ BOOL_BITFIELD objc_property_attr_context : 1; + + /* Cilk Plus specific parser/lexer information. */ + + /* Buffer to hold all the tokens from parsing the vector attribute for the + SIMD-enabled functions (formerly known as elemental functions). */ + vec <c_token, va_gc> *cilk_simd_fn_tokens; } c_parser; @@ -1246,6 +1252,7 @@ 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); +static bool c_parser_cilk_clause_vectorlength (c_parser *, tree *, bool); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -1647,7 +1654,8 @@ C_DTR_NORMAL, &dummy); if (declarator == NULL) { - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, omp_declare_simd_clauses); c_parser_skip_to_end_of_block_or_statement (parser); @@ -1734,7 +1742,8 @@ chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); } @@ -1746,7 +1755,8 @@ chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); start_init (d, asm_name, global_bindings_p ()); @@ -1774,7 +1784,8 @@ tree d = start_decl (declarator, specs, false, chainon (postfix_attrs, all_prefix_attrs)); - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) { tree parms = NULL_TREE; if (d && TREE_CODE (d) == FUNCTION_DECL) @@ -1902,7 +1913,8 @@ c_parser_declaration_or_fndef (parser, false, false, false, true, false, NULL, vNULL); store_parm_decls (); - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, omp_declare_simd_clauses); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus @@ -3765,6 +3777,134 @@ return attr_name; } +/* Returns name of the next clause in Cilk Plus SIMD-enabled function's + attribute. + If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and + the token is not consumed. Otherwise appropriate pragma_omp_clause is + returned and the token is consumed. */ + +static pragma_omp_clause +c_parser_cilk_simd_fn_clause_name (c_parser *parser) +{ + pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE; + + if (c_parser_next_token_is_not (parser, CPP_NAME)) + return result; + + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp (p, "vectorlength")) + result = PRAGMA_OMP_CLAUSE_SIMDLEN; + else if (!strcmp (p, "uniform")) + result = PRAGMA_OMP_CLAUSE_UNIFORM; + else if (!strcmp (p, "linear")) + result = PRAGMA_OMP_CLAUSE_LINEAR; + else if (!strcmp (p, "mask")) + result = PRAGMA_OMP_CLAUSE_INBRANCH; + else if (!strcmp (p, "nomask")) + result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; + + if (result != PRAGMA_OMP_CLAUSE_NONE) + c_parser_consume_token (parser); + return result; +} + +/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector," + "__vector" or "__vector__." */ + +static bool +is_cilkplus_vector_p (tree name) +{ + if (flag_enable_cilkplus + && (simple_cst_equal (name, get_identifier ("vector")) == 1 + || simple_cst_equal (name, get_identifier ("__vector")) == 1 + || simple_cst_equal (name, get_identifier ("__vector__")) == 1)) + return true; + return false; +} + +#define CILK_SIMD_FN_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) + +/* Parses the vector attribute of SIMD enabled functions in Cilk Plus. + VEC_TOKEN is the "vector" token that is replaced with "simd" and + pushed into the token list. + Syntax: + vector + vector (<vector attributes>). */ + +static void +c_parser_cilk_simd_fn_vector_attrs (c_parser *parser, c_token vec_token) +{ + gcc_assert (is_cilkplus_vector_p (vec_token.value)); + + int paren_scope = 0; + vec_safe_push (parser->cilk_simd_fn_tokens, vec_token); + /* Consume the "vector" token. */ + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + paren_scope++; + } + while (paren_scope > 0) + { + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_OPEN_PAREN) + paren_scope++; + else if (token->type == CPP_CLOSE_PAREN) + paren_scope--; + if (token->type == CPP_NAME + && TREE_CODE (token->value) == IDENTIFIER_NODE) + if (simple_cst_equal (token->value, + get_identifier ("vectorlength")) == 1) + { + if (!c_parser_cilk_clause_vectorlength (parser, NULL, true)) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return; + } + else + continue; + } + /* Do not push the last ')' since we are not pushing the '('. */ + if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0)) + vec_safe_push (parser->cilk_simd_fn_tokens, *token); + c_parser_consume_token (parser); + } + + /* Since we are converting an attribute to a pragma, we need to end the + attribute with PRAGMA_EOL. */ + c_token eol_token; + memset (&eol_token, 0, sizeof (eol_token)); + eol_token.type = CPP_PRAGMA_EOL; + vec_safe_push (parser->cilk_simd_fn_tokens, eol_token); +} + +/* Add 2 CPP_EOF at the end of PARSER->ELEM_FN_TOKENS vector. */ + +static void +c_finish_cilk_simd_fn_tokens (c_parser *parser) +{ + c_token last_token = parser->cilk_simd_fn_tokens->last (); + + /* c_parser_attributes is called in several places, so if these EOF + tokens are already inserted, then don't do them again. */ + if (last_token.type == CPP_EOF) + return; + + /* Two CPP_EOF token are added as a safety net since the normal C + front-end has two token look-ahead. */ + c_token eof_token; + eof_token.type = CPP_EOF; + vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); + vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); +} + /* Parse (possibly empty) attributes. This is a GNU extension. attributes: @@ -3829,6 +3969,12 @@ attr_name = c_parser_attribute_any_word (parser); if (attr_name == NULL) break; + if (is_cilkplus_vector_p (attr_name)) + { + c_token *v_token = c_parser_peek_token (parser); + c_parser_cilk_simd_fn_vector_attrs (parser, *v_token); + continue; + } c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) { @@ -3909,6 +4055,9 @@ } parser->lex_untranslated_string = false; } + + if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + c_finish_cilk_simd_fn_tokens (parser); return attrs; } @@ -10401,7 +10550,7 @@ linear ( variable-list : expression ) */ static tree -c_parser_omp_clause_linear (c_parser *parser, tree list) +c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; @@ -10418,10 +10567,16 @@ step = c_parser_expression (parser).value; mark_exp_read (step); step = c_fully_fold (step, false, NULL); + if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) + { + error_at (clause_loc, "using parameters for %<linear%> step is " + "not supported in this release"); + step = integer_one_node; + } if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) { error_at (clause_loc, "%<linear%> clause step expression must " - "be integral"); + "be integral"); step = integer_one_node; } @@ -10789,7 +10944,11 @@ c_parser_consume_token (parser); here = c_parser_peek_token (parser)->location; - c_kind = c_parser_omp_clause_name (parser); + + if (mask == CILK_SIMD_FN_CLAUSE_MASK) + c_kind = c_parser_cilk_simd_fn_clause_name (parser); + else + c_kind = c_parser_omp_clause_name (parser); switch (c_kind) { @@ -10933,7 +11092,8 @@ c_name = "aligned"; break; case PRAGMA_OMP_CLAUSE_LINEAR: - clauses = c_parser_omp_clause_linear (parser, clauses); + clauses = c_parser_omp_clause_linear + (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -12754,10 +12914,20 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, vec<c_token> clauses) { + + if (flag_enable_cilkplus + && clauses.exists () && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + { + error ("%<#pragma omp declare simd%> cannot be used in the same " + "function marked as a Cilk Plus SIMD-enabled function"); + vec_free (parser->cilk_simd_fn_tokens); + return; + } + /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd has already processed the tokens. */ - if (clauses[0].type == CPP_EOF) + if (clauses.exists () && clauses[0].type == CPP_EOF) return; if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) { @@ -12766,7 +12936,7 @@ clauses[0].type = CPP_EOF; return; } - if (clauses[0].type != CPP_NAME) + if (clauses.exists () && clauses[0].type != CPP_NAME) { error_at (DECL_SOURCE_LOCATION (fndecl), "%<#pragma omp declare simd%> not immediately followed by " @@ -12780,23 +12950,49 @@ unsigned int tokens_avail = parser->tokens_avail; gcc_assert (parser->tokens == &parser->tokens_buf[0]); - parser->tokens = clauses.address (); - parser->tokens_avail = clauses.length (); - + bool is_cilkplus_cilk_simd_fn = false; + + if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + { + parser->tokens = parser->cilk_simd_fn_tokens->address (); + parser->tokens_avail = vec_safe_length (parser->cilk_simd_fn_tokens); + is_cilkplus_cilk_simd_fn = true; + } + else + { + parser->tokens = clauses.address (); + parser->tokens_avail = clauses.length (); + } + /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */ while (parser->tokens_avail > 3) { c_token *token = c_parser_peek_token (parser); - gcc_assert (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); + if (!is_cilkplus_cilk_simd_fn) + gcc_assert (token->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); + else + gcc_assert (token->type == CPP_NAME + && is_cilkplus_vector_p (token->value)); c_parser_consume_token (parser); parser->in_pragma = true; - tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, - "#pragma omp declare simd"); + tree c = NULL_TREE; + if (is_cilkplus_cilk_simd_fn) + c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK, + "SIMD-enabled functions attribute"); + else + c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, + "#pragma omp declare simd"); c = c_omp_declare_simd_clauses_to_numbers (parms, c); if (c != NULL_TREE) c = tree_cons (NULL_TREE, c, NULL_TREE); + if (is_cilkplus_cilk_simd_fn) + { + tree k = build_tree_list (get_identifier ("cilk simd function"), c); + TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl); + DECL_ATTRIBUTES (fndecl) = k; + } c = build_tree_list (get_identifier ("omp declare simd"), c); TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); DECL_ATTRIBUTES (fndecl) = c; @@ -12804,7 +13000,11 @@ parser->tokens = &parser->tokens_buf[0]; parser->tokens_avail = tokens_avail; - clauses[0].type = CPP_PRAGMA; + if (clauses.exists ()) + clauses[0].type = CPP_PRAGMA; + + if (!vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + vec_free (parser->cilk_simd_fn_tokens); } @@ -13400,39 +13600,110 @@ } /* Cilk Plus: - vectorlength ( constant-expression ) */ + This function is shared by SIMD-enabled functions and #pragma simd. + If IS_SIMD_FN is true then it is parsing a SIMD-enabled function and + CLAUSES is unused. The main purpose of this function is to parse a + vectorlength attribute or clause and check for parse errors. + When IS_SIMD_FN is true then the function is merely caching the tokens + in PARSER->CILK_SIMD_FN_TOKENS. If errors are found then the token + cache is cleared since there is no reason to continue. + Syntax: + vectorlength ( constant-expression ) */ -static tree -c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses) +static bool +c_parser_cilk_clause_vectorlength (c_parser *parser, tree *clauses, + bool is_simd_fn) { - /* The vectorlength clause behaves exactly like OpenMP's safelen - clause. Represent it in OpenMP terms. */ - check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); + c_token *token = c_parser_peek_token (parser); + if (is_simd_fn) + { + gcc_assert (simple_cst_equal (token->value, + get_identifier ("vectorlength")) == 1); + // token->value = get_identifier ("simdlen"); + vec_safe_push (parser->cilk_simd_fn_tokens, *token); + c_parser_consume_token (parser); + } + else + /* The vectorlength clause behaves exactly like OpenMP's safelen + clause. Represent it in OpenMP terms. */ + check_no_duplicate_clause (*clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); + token = c_parser_peek_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return clauses; + { + /* No reason to keep any of these tokens if the + vectorlength is messed up. */ + vec_free (parser->cilk_simd_fn_tokens); + return false; + } + if (is_simd_fn) + vec_safe_push (parser->cilk_simd_fn_tokens, *token); + + *token = *c_parser_peek_token (parser); 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); + bool error_found = false; - if (!TREE_TYPE (expr) - || !TREE_CONSTANT (expr) - || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) - error_at (loc, "vectorlength must be an integer constant"); + /* If expr is error_mark_node, then the returning function would have + flagged the error. No need to flag it twice. */ + if (expr == error_mark_node) + error_found = true; + else if (!TREE_TYPE (expr) + || !TREE_CONSTANT (expr) + || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) + { + error_at (loc, "vectorlength must be an integer constant"); + error_found = true; + } else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1) - error_at (loc, "vectorlength must be a power of 2"); + { + error_at (loc, "vectorlength must be a power of 2"); + error_found = true; + } else { - tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); - OMP_CLAUSE_SAFELEN_EXPR (u) = expr; - OMP_CLAUSE_CHAIN (u) = clauses; - clauses = u; + if (is_simd_fn) + { + c_token new_token; + /* If we are here then it has be a number or an integral constant. + The function that checks this token only checks to see if it is + a keyword or name, so we set it to the most common case. */ + new_token.type = CPP_NUMBER; + new_token.keyword = RID_MAX; + new_token.value = expr; + vec_safe_push (parser->cilk_simd_fn_tokens, new_token); + } + else + { + tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (u) = expr; + OMP_CLAUSE_CHAIN (u) = *clauses; + *clauses = u; + } } + if (error_found && is_simd_fn) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + /* No reason to keep any of these tokens if the + vectorlength is messed up. */ + vec_free (parser->cilk_simd_fn_tokens); + return false; + } - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + token = c_parser_peek_token (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + { + /* No reason to keep any of these tokens if the + vectorlength is messed up. */ + vec_free (parser->cilk_simd_fn_tokens); + return false; + } - return clauses; + if (is_simd_fn) + vec_safe_push (parser->cilk_simd_fn_tokens, *token); + return true; } /* Cilk Plus: @@ -13571,7 +13842,7 @@ switch (c_kind) { case PRAGMA_CILK_CLAUSE_VECTORLENGTH: - clauses = c_parser_cilk_clause_vectorlength (parser, clauses); + c_parser_cilk_clause_vectorlength (parser, &clauses, false); break; case PRAGMA_CILK_CLAUSE_LINEAR: clauses = c_parser_cilk_clause_linear (parser, clauses); Index: gcc/omp-low.c =================================================================== --- gcc/omp-low.c (revision 205759) +++ gcc/omp-low.c (working copy) @@ -11300,7 +11300,7 @@ declare simd". */ bool cilk_clone = (flag_enable_cilkplus - && lookup_attribute ("cilk plus elemental", + && lookup_attribute ("cilk simd function", DECL_ATTRIBUTES (node->decl))); /* Allocate one more than needed just in case this is an in-branch Index: gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp =================================================================== --- gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp (revision 205759) +++ gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp (working copy) @@ -59,6 +59,10 @@ dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus" " " } +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -g" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -g" " " + dg-finish unset TEST_EXTRA_LIBS Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c (revision 0) @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -fopenmp" } */ + +#pragma omp declare simd linear(y:1) simdlen(4) +__attribute__((vector (linear (y:1), vectorlength(4)))) +int func (int x, int y) { /* { dg-error "cannot be used in the same function marked as a Cilk Plus SIMD-enabled" } */ + return (x+y); +} +__attribute__((vector (linear (y:1), private (x)))) /* { dg-error "expected clause" } */ +int func2 (int x, int y) { + return (x+y); +} + +__attribute__((vector (linear (y:1), simdlen (4)))) /* { dg-error "expected clause" } */ +int func2_1 (int x, int y) { + return (x+y); +} + +__attribute__((vector (linear (y:1), inbranch))) /* { dg-error "expected clause" } */ +int func2_3 (int x, int y) { + return (x+y); +} + +__attribute__((vector (notinbranch, vectorlength (4)))) /* { dg-error "expected clause" } */ +int func2_2 (int x, int y) { + return (x+y); +} + +int main (void) +{ + return (func (5,6)); +} Index: gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c (revision 0) @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -Wunknown-pragmas" } */ + +#define Q 4 + +int z = Q; + +__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" } */ +int func2 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4.5) ))) /* { dg-error "vectorlength must be an integer" } */ +int func3 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" } */ +int func4 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (Q) ))) /* This is OK! */ +int func5 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" } */ +int func6 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (sizeof (int)) ))) /* This is OK too! */ +int func7 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +int main (void) +{ + int ii = 0, q = 5; + for (ii = 0; ii < 10; ii++) + q += func2 (z, ii); + return q; +} Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c (revision 0) @@ -0,0 +1,14 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus -Wall" } */ + +__attribute__((vector (vectorlength(32)))) +//#pragma omp simd simdlen (32) +int func2 (int x, int y) /* { dg-warning "unsupported simdlen" } */ +{ + return (x+y); +} + +int main (void) +{ + return (func2 (5,6)); +} Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus -Wall" } */ + +__attribute__((vector (linear (x:y)))) /* { dg-error "is not supported in this release" } */ +int func2 (int x, int y) +{ + return (x+y); +} + +int main (void) +{ + return (func2 (5,6)); +} Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c (revision 0) @@ -0,0 +1,78 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -Wunknown-pragmas" } */ + +/* Tests the clauses in several combinations put in different locations. */ +/* This is mostly a parser test. */ +#define Q 4 + +int z = Q; + + __attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4) ))) +int func (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + __attribute__ ((__vector__ (uniform(x), vectorlength (2), linear (y:1) ))) +int func2 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(y), linear (x), vectorlength (4) ))) +int func3 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((__vector (uniform(x), linear (y:1), mask))) +int func4 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), nomask))) +int func5 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), mask, linear (y:1)))) +int func6 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector)) +int func7 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector (uniform (y), mask))) +int func8 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector, vector (uniform (y), mask))) +int func9 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +int main (int argc, char *argv[]) +{ + int ii = 0, q = 5; + for (ii = 0; ii < 10; ii++) + q += func (argc, ii); + return q; +} Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c =================================================================== --- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c (revision 0) +++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c (revision 0) @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ +void func (int x, int y) __attribute__((vector(linear(x:1), uniform (y)), + vector)); + +int q; +int main (void) +{ + int ii = 0; + q = 5; + for (ii = 0; ii < 100; ii++) + func (ii, q); + + return 0; +} +