From patchwork Fri Mar 22 22:03:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Iyer, Balaji V" X-Patchwork-Id: 230279 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 889BF2C0040 for ; Sat, 23 Mar 2013 09:04:23 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; q=dns; s=default; b=qJWSUMRgNzLisecT jkmhyIX3JpObX/3pN13V2XY6QPbj0KlV5x02jUwSCvSrXX5ZkYxBZVBQ/lUA1TF3 pQOPqHLDs1n3o/S0EChKrzL9aAk6TlLnhboqT2QiG8jBFG/lTSnva6BNAEzPrJZV t+DLte4cYToW1cNg1IwtZtdGUpo= 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:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; s=default; bh=eyzlAQMc7I8nlM0lAFrb9s p3pKQ=; b=Dm55o+MNlI79L1F7TJ7XSeEBwS0w5ZU9y4V1rOLGqmgFi9vk/7FZUF 4qHVsNhDZP1W/V2URDpipqOHV9q0N2Dl4rWejcGJmUpkT1qtQTTPybfWXBraCf9p /kRf9UFbCC4k5rdvEgiCjVkoptsUfVRGoaLM1Z+sno+k57oE+Em9c= Received: (qmail 4727 invoked by alias); 22 Mar 2013 22:04:09 -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 4699 invoked by uid 89); 22 Mar 2013 22:03:51 -0000 X-Spam-SWARE-Status: No, score=-8.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, TW_TM, T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.1 Received: from mga11.intel.com (HELO mga11.intel.com) (192.55.52.93) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 22 Mar 2013 22:03:38 +0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 22 Mar 2013 15:03:30 -0700 X-ExtLoop1: 1 Received: from fmsmsx107.amr.corp.intel.com ([10.19.9.54]) by fmsmga002.fm.intel.com with ESMTP; 22 Mar 2013 15:03:29 -0700 Received: from FMSMSX110.amr.corp.intel.com (10.19.9.29) by FMSMSX107.amr.corp.intel.com (10.19.9.54) with Microsoft SMTP Server (TLS) id 14.1.355.2; Fri, 22 Mar 2013 15:03:29 -0700 Received: from fmsmsx102.amr.corp.intel.com ([169.254.2.241]) by fmsmsx110.amr.corp.intel.com ([169.254.12.62]) with mapi id 14.01.0355.002; Fri, 22 Mar 2013 15:03:28 -0700 From: "Iyer, Balaji V" To: "gcc-patches@gcc.gnu.org" CC: "aldyh@redhat.com" , "Joseph Myers [joseph@codesourcery.com]" Subject: RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1) Date: Fri, 22 Mar 2013 22:03:28 +0000 Message-ID: References: <5149D62F.9070503@redhat.com> In-Reply-To: MIME-Version: 1.0 X-Virus-Found: No Attached, please find a patch that should be applied to the head of cilkplus-merge. This patch is generated by diffing with the following hash: 4f4932be8230284919d197cccb4b10201f82a0b3 This patch also adds documentation about the built-in reduction funtions of array notations that Aldy pointed out in a previous email. I have not fixed all the issues below (the big one that is left is the bultin function representation that Joseph Pointed out). I have fixed most of the other issues. All the things I have fixed are marked by "FIXED!" Is this Ok to commit into cilkplus-merge? Thanks, Balaji V. Iyer. > -----Original Message----- > From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches- > owner@gcc.gnu.org] On Behalf Of Joseph S. Myers > Sent: Thursday, March 21, 2013 11:56 AM > To: Aldy Hernandez > Cc: Iyer, Balaji V; gcc-patches > Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset, > take 1) > > On Wed, 20 Mar 2013, Aldy Hernandez wrote: > > > Joseph, folks, et al... How does this look? > > This review largely deals with coding style (interpreted broadly). I'll review more > of the substance separately later; reposting with fixes for all the accumulated > issues is probably a good idea anyway, to avoid the same issues coming up > repeatedly. > > > * c-common.c (c_define_builtins): When cilkplus is enabled, the > > function array_notation_init_builtins() is called. > > Don't use () after a function name when referring to the function. FIXED! > > > diff --git a/gcc/c-family/array-notation-common.c > > b/gcc/c-family/array-notation-common.c > > > +int extract_sec_implicit_index_arg (location_t, tree); bool > > +is_sec_implicit_index_fn (tree); void array_notation_init_builtins > > +(void); FIXED! > > Non-static function declarations like this should not be inside a .c file. > If these functions are used outside this file, there should be an associated > header that declares them; include it in the .c file. If only used inside the .c file > that defines them, make them static (and topologically sort static functions > inside a source file so that forward static declarations are only needed for cases > of recursion). > > > +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL > is > > + not run as is. */ > > The cold attribute means unlikely to be executed rather than "not run as is". > Maybe "not run as is" is what's relevant here, but I'm not clear why this attribute > would be useful for built-in functions at all - the documentation suggests it's > only relevant when a user defines a function themselves, and affects the code > generated for that function, so wouldn't be relevant at all for built-in functions. > > > +void > > +array_notation_init_builtins (void) > > Other built-in functions use various .def files (builtins.def and the files it includes) > to avoid lots of repetitive code like this - can you integrate this with that > mechanism? If you do so, then you should be able to avoid (or massively > simplify) functions like: > > > +/* Returns true if the function call specified in FUNC_NAME is > > + __sec_implicit_index. */ > > + > > +bool > > +is_sec_implicit_index_fn (tree func_name) > > because code can use the BUILT_IN_* enum values to test whether a particular > function is in use - which is certainly cleaner than using strcmp against the > function name. > > > +/* Returns the first and only argument for FN, which should be a > > + sec_implicit_index function. FN's location in the source file is is > > + indicated by LOCATION. */ > > + > > +int > > +extract_sec_implicit_index_arg (location_t location, tree fn) { > > + tree fn_arg; > > + HOST_WIDE_INT return_int = 0; > > + if (!fn) > > + return -1; > > Why the random check for a NULL argument? If a NULL argument is valid > (meaning that it makes the code cleaner to allow such arguments rather than > making sure the function isn't called with them), this should be documented in > the comment above the function; otherwise, if such an argument isn't valid, > there is no need to check for it. I always tend to check for a null pointer before I access the fields in the structure. In this case it is unnecessary. In some cases (e.g. find_rank) there is a good chance a null pointer will be passed into the function and we need to check that and reject those. > > You declare return_int as HOST_WIDE_INT, but it only receives a value cast to > int, and is used only to store a value returned as int. Either use int consistently, > or HOST_WIDE_INT consistently, but I don't see a reason to use both. FIXED! > > > + if (TREE_CODE (fn) == CALL_EXPR) > > + { > > + fn_arg = CALL_EXPR_ARG (fn, 0); > > + if (really_constant_p (fn_arg)) > > I don't think really_constant_p is what's wanted; > Intel_Cilk_plus_lang_spec_2.htm> > says "The argument shall be an integer constant expression.", and such > expressions always appear in the C front end as INTEGER_CST. So you can just > check for INTEGER_CST. What about C++? This function is shared by both C and C++. > > Now a subtlety here is that the function argument will have been folded by this > point, meaning that cases that aren't integer constant expressions in C standard > terms will be wrongly allowed (both by the original code and by a version > checking against INTEGER_CST). In such cases, the way to get things checked > correctly is to use a keyword rather than a built-in function - as with > __builtin_choose_expr or __builtin_shuffle, for example. Since this operation > seems special in ways that built-in functions generally aren't, that seems > reasonable anyway. So the code parsing this keyword would check that the > argument is an INTEGER_CST, of integer type (since INTEGER_CSTs can have > pointer type in GCC), like that for __builtin_choose_expr does. It would then > quite likely create its own tree code for the operation, rather than using a > CALL_EXPR at all. (It would need to manage converting to int, given how the > specification defines things in terms of a prototype for type int - so e.g. a > constant 1ULL << 32 would act like 0 if int is 32 bits, under the present > specification.) > > The specification doesn't seem very clear on to what extent the __sec_* > operations must act like functions (what happens if someone puts parentheses > around the __sec_* name, for example - that wouldn't work with the keyword > approach). So the specification should be clarified there, but I think saying the > __sec_* operations are syntactically special, like keywords, is more appropriate > than requiring other uses to work. > > > + return_int = (int) int_cst_value (fn_arg); > > + else > > + { > > + if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn)) > > + location = EXPR_LOCATION (fn); > > + error_at (location, "__sec_implicit_index parameter must be a " > > + "constant integer expression"); > > The term is "integer constant expression" not "constant integer expression". FIXED! > > > diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c > > > +void replace_array_notations (tree *, bool, vec *, > > + vec *); > > +void find_rank (tree, bool, size_t *); void > > +extract_array_notation_exprs (tree, bool, vec **); tree > > +fix_conditional_array_notations (tree); struct c_expr > > +fix_array_notation_expr (location_t, enum tree_code, > > + struct c_expr); > > +bool is_builtin_array_notation_fn (tree func_name, an_reduce_type > > +*type); static tree fix_builtin_array_notation_fn (tree > > +an_builtin_fn, tree *new_var); bool contains_array_notation_expr > > +(tree expr); tree expand_array_notation_exprs (tree t); > > As before, forward declarations inside .c files should only be for static functions > with recursive calls to themselves, not for non-static functions or static > functions not involved in recursion. FIXED! > > > +struct inv_list > > +{ > > + vec *list_values; > > + vec *replacement; > > +}; > > Comment on this type explaining what it's for. FIXED! > > > +/* Returns the rank of ARRAY through the *RANK. The user can specify > whether > > + (s)he wants to step into array_notation-specific builtin functions > > + (specified by the IGNORE_BUILTIN_FN). > > The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring array- > notation-specific built-in functions if IGNORE_BUILTIN_FN." would be better. Yes, I agree with your wording. Thanks! and FIXED! > > > +void > > +find_rank (tree array, bool ignore_builtin_fn, size_t *rank) { > > + tree ii_tree; > > + size_t current_rank = 0, ii = 0; > > + an_reduce_type dummy_type = REDUCE_UNKNOWN; > > + if (!array) > > + return; > > As before, avoid random checks for NULL parameters unless there is an actual > reason to allow them and the comments document that they are allowed and > what the semantics are in that case. In general, explain what ARRAY is - an > expression? This check is necessary. Find rank can get a NULL pointer and that must be caught and rejected. > > Is *RANK always set by this function? Make clear in the comment above the > function whether it is, and whether the initial value of *RANK before the > function is called is of any significance. I note that > > > + else if (TREE_CODE (array) == ARRAY_NOTATION_REF) > > + { > > + for (ii_tree = array; > > + ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; > > + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) > > + current_rank++; > > + if (*rank == 0) > > + *rank = current_rank; > > does appear to look at the value before the function has set it, implying that the > original value of *RANK *does* mean something. FIXED! I looked this way due to an artifact of a previous implementation. It looks a little bit more cleaner now. > > > + if (TREE_CODE (array) == CALL_EXPR) > > + { > > + tree func_name = CALL_EXPR_FN (array); > > + if (TREE_CODE (func_name) == ADDR_EXPR) > > + if (!ignore_builtin_fn) > > + if (is_builtin_array_notation_fn (func_name, &dummy_type)) > > + /* If it is a builtin function, then we know it returns a > > + scalar. */ > > + return; > > + if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST) > > + { > > + int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0)); > > + for (ii = 0; ii < (size_t) length; ii++) > > TREE_INT_CST_LOW returns unsigned HOST_WIDE_INT. There should be no > need for converting twice, first to int and then to size_t. And rather than > depending on implementation default of CALL_EXPR, call_expr_nargs would be > a better way to calculate the length. > > > + find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank); > > But actually, you're dealing with a CALL_EXPR here. So you should be able to > use existing iterators over CALL_EXPR arguments (e.g. > FOR_EACH_CALL_EXPR_ARG) rather than explicitly using the number of > arguments at all. Doing so, and separately checking CALL_EXPR_FN, and > CALL_EXPR_STATIC_CHAIN if applicable, seems cleaner than depending on low- > level details of the sequence of operands to a CALL_EXPR. FIXED! (I used your suggestion and used FOR_EACH_CALL_EXPR_ARG) > > > +/* Extracts all the array notations specified in NODE and stores them in a > > + dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE. The > > + user can specify if (s)he wants to ignore the array notations inside the > > + array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to > > + true). */ > > + > > +void > > +extract_array_notation_exprs (tree node, bool ignore_builtin_fn, > > + vec **array_list) > > There's no argument LIST_SIZE, so the comment needs updating. Again, the > wording about "The user" is awkward; the comment should directly define the > semantics of the function in terms of its argument, without reference to "The > user". FIXED! Reworded the comment. > > > +{ > > + size_t ii = 0; > > + an_reduce_type dummy_type = REDUCE_UNKNOWN; > > + > > + if (!node) > > + return; > > Again, check for NULL argument without any mention in the comment that such > arguments are valid; remove unless there is a reason to make them valid. > > > + else if (TREE_CODE (node) == TREE_LIST) > > What's NODE? My first guess would have been an expression, but if a TREE_LIST > is possible that's clearly not the answer, so explain in the comment above the > function what NODE is. (If a TREE_LIST is being used within expressions to store > something specific to array notation, don't do so - TREE_LIST is deprecated, > existing uses should be phased out in favour of more specific and less memory- > hungry datastructures and new uses should not be added.) FIXED! What is replacing tree-list? I have used tree-list in my later patches and in my Cilk Plus branch. > > > + if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST) > > + { > > + int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0)); > > + > > + for (ii = 0; ii < (size_t) length; ii++) > > + extract_array_notation_exprs > > + (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list); > > Same problems as before with an iterator over CALL_EXPR that should avoid > depending on low-level details of how CALL_EXPR is implemented, and excess > integer type conversions. FIXED! > > > +/* Replaces all occurances of array notations in tree ORIG that matches the > > + ones in LIST with the one in ARRAY_OPERAND. The size of list and > > + ARRAY_OPERAND is ARRAY_SIZE. For example, ARRAY_OPERAND[x] for > some index > > + 'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF > specified > > + in LIST[x]. The user can specify if (s)he wants to ignore the array > > + notations inside the array-notation specific builtin functions (using the > > + bool variable IGNORE_BUILTIN_FN). */ > > Again, avoid "The user". FIXED! > > > +void > > +replace_array_notations (tree *orig, bool ignore_builtin_fn, > > + vec *list, > > + vec *array_operand) > > +{ > > + size_t ii = 0; > > + tree node = NULL_TREE, node_replacement = NULL_TREE; > > + an_reduce_type dummy_type = REDUCE_UNKNOWN; > > + > > + if (vec_safe_length (list) == 0 || !*orig) > > + return; This ORIG must be checked for NULL because you will step this function even if the node is NULL. This is the spot to check that. > > Again, avoid checks for NULL or document that NULL arguments are valid if > there's a good reason. Generally, document what sort of thing ORIG is. > > > + if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST) > > + { > > + int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0)); > > + for (ii = 0; ii < (size_t) length; ii++) > > + replace_array_notations > > + (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list, > > + array_operand); > > Again, better CALL_EXPR iterators. FIXED! > > > +/* This function will find all the scalar expressions in *TP and push it in > > + DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0 then > > + we have do not go into the *TP's subtrees. */ > > Rather than "This function will", just "Find ..." (and say "Returns NULL_TREE." or > something like that - presumably the return type is so it can be passed to > walk_tree). > > > +/* Replaces all the scalar expressions in *NODE. */ > > + > > +tree > > +replace_invariant_exprs (tree *node) > > Comment needs to explain the semantics of the return value. FIXED! > > > +tree > > +build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, > > + enum tree_code modifycode, location_t rhs_loc, > > + tree rhs, tree rhs_origtype) > > > + } > > + > > + > > + > > + for (ii = 0; ii < lhs_rank; ii++) > > Excess blank lines in middle of function. Generally there shouldn't be two or > more consecutive blank lines inside a function (if you want to have different > sizes of blanks to split up levels of structure in the function, that suggests the > function is too big and should be split up into separate functions). FIXED! > > > + TREE_TYPE (lhs_var[ii])); > > + > > + } > > This location for a blank line doesn't make sense. FIXED! > > > + /* The following statements will do the following: > > + * : (in order from outermost to innermost) > > + * if (cond_expr) then go to body_label > > + * else go to exit_label > > + * : > > + * array expression > > + * > > + * (the increment, goto and exit_label goes from innermost to > > + * outermost). > > + * ii++ and jj++ > > + * go to if_stmt_label > > + * : > > + * > > + */ > > Comments should not have an initial "*" on each line. FIXED! > > > +/* Encloses the conditional statement passed in STMT with a loop around it > > + and replaces the condition in STMT with a ARRAY_REF tree-node to the > array. > > + The condition must have a ARRAY_NOTATION_REF tree. */ > > + > > +static tree > > +fix_conditional_array_notations_1 (tree stmt) > > Comment should explain return value semantics. FIXED! > > > + TREE_TYPE (array_var[ii])); > > + > > + } > > Another stray blank line. Check the patch generally for stray blank lines > immediately before a '}', I don't think they ever make sense, but I may have > missed some. I think I have caught all of it. I apologize if I missed any. > > > + // XDELETEVEC (array_var); > > I don't think this sort of commented-out code should be added. If you're > deliberately not doing something that a reader might expect to be done, have a > comment explaining *why* you're not doing it, not just commented-out code to > do it. FIXED! > > > + error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind > cannot" > > + " have arrays with dimension greater than 1."); > > Diagnostics don't end with ".". > > > + default: > > + gcc_unreachable (); /* You should not reach here. */ > > No need for comments like this that just repeat the plain semantics of the C > code. There's nothing else a call to gcc_unreachable could possibly mean; such > a comment is of no more use than "i++; /* Add 1 to i. */". FIXED! > > > +/* Returns true of FUNC_NAME is a builtin array notation function. The type > of > > + function is returned in *TYPE. */ > > "true if", not "true of". > FIXED! Sorry for this stupid mistake. > > +bool > > +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) { > > + const char *function_name = NULL; > > + > > + if (!func_name) > > + return false; > > Another unexplained test for a NULL argument. Again, explain what sort of > things FUNC_NAME may be. (This is another function that should be using > BUILT_IN_* enum values rather than strcmp, if you rework how the built-in > functions are implemented.) > > > +/* Returns true of EXPR (and its subtrees) contain > > +ARRAY_NOTATION_EXPR node. */ > > "true if", again. FIXED! > > > +/* Replaces array notations in void function call arguments in ARG with loop > and > > + tree-node ARRAY_REF and returns that value in a tree node variable called > > + LOOP. */ > > LOOP is not an argument to this function, so it doesn't make sense to refer to it > in the comment. I suspect " in a tree node variable called LOOP" should simply > be removed. FIXED! > > > + if (TREE_CODE (arg) == CALL_EXPR > > + && is_builtin_array_notation_fn (CALL_EXPR_FN (arg), &an_type)) > > + { > > + loop = fix_builtin_array_notation_fn (arg, &new_var); > > + /* We are ignoring the new var because either the user does not want to > > + capture it OR he is using sec_reduce_mutating function. */ > > In general I think "the user" comments should be avoided though this one is a bit > less awkward than those defining function semantics by reference to "the user". > > > +/* Walks through tree node T and find all the call-statments that do not > return > > + anything and fix up any array notations they may carry. */ > > + > > +tree > > +expand_array_notation_exprs (tree t) > > Comment should document return value. FIXED! > > > +{ > > + if (!t || !contains_array_notation_expr (t)) > > + return t; > > Another check for NULL without a comment saying NULL is a valid argument. This function also can receive a null pointer. > > > +/* Returns array notation expression for the array base ARRAY of type TYPE, > > + with start index, length and stride given by START_INDEX, LENGTH and > STRIDE, > > + respectively. */ > > + > > +tree > > +build_array_notation_ref (location_t loc, tree array, tree start_index, > > + tree length, tree stride, tree type) { > > + tree array_ntn_tree = NULL_TREE; > > + size_t stride_rank = 0, length_rank = 0, start_rank = 0; > > + > > + if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE > > + (start_index))) > > I'd expect the argument would have to be an expression, so would always have > a TYPE and the !TREE_TYPE (start_index) check should be unnecessary. > If it is needed, explain further in the comment at the start of the function. > Likewise for other checks for NULL types in this function. FIXED! But Stride could easily be NULL, (e.g. array[0:10]) and in this case we have put one in. So, I have left that check in. > > > + { > > + error_at (loc, > > + "start-index of array notation triplet is not an integer."); > > Diagnostic should not end with ".". FIXED! > > > + error_at (loc, "length of array notation triplet is not an > > + integer."); > > Likewise. FIXED! > > > + error_at (loc, "stride of array notation triplet is not an > > + integer."); > > Likewise. FIXED! > > > + error_at (loc, "rank of an array notation triplet's start-index is not " > > + "zero."); > > Likewise. FIXED! > > > + error_at (loc, "rank of an array notation triplet's length is > > + not zero."); > > Likewise. FIXED! > > > + error_at (loc, "rank of array notation triplet's stride is not > > + zero."); > > Likewise. FIXED! > > That's a coding style review of the first half or so of the patch, more later.... Thanks for reviewing my code! -Balaji V. Iyer. > > -- > Joseph S. Myers > joseph@codesourcery.com diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus index 6591fd1..10db29b 100644 --- a/gcc/c-family/ChangeLog.cilkplus +++ b/gcc/c-family/ChangeLog.cilkplus @@ -1,7 +1,11 @@ +2013-03-22 Balaji V. Iyer + + * c-pretty-print.c (pp_c_expression): Added ARRAY_NOTATION_REF case. + 2013-03-20 Balaji V. Iyer * c-common.c (c_define_builtins): When cilkplus is enabled, the - function array_notation_init_builtins() is called. + function array_notation_init_builtins is called. (c_common_init_ts): Added ARRAY_NOTATION_REF as typed. * c-common.def (ARRAY_NOTATION_REF): New tree. * c-common.h (build_array_notation_expr): New function declaration. diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c index 7089c8e..b775225 100644 --- a/gcc/c-family/array-notation-common.c +++ b/gcc/c-family/array-notation-common.c @@ -29,19 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "diagnostic-core.h" -int extract_sec_implicit_index_arg (location_t, tree); -bool is_sec_implicit_index_fn (tree); -void array_notation_init_builtins (void); - -/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is - not run as is. */ - -static void -mark_cold (tree fndecl) -{ - DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE, - DECL_ATTRIBUTES (fndecl)); -} /* This function inititializes array notation specific builtin information. */ @@ -54,67 +41,56 @@ array_notation_init_builtins (void) func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_add", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_mul", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_all_zero", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_any_zero", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_max", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_min", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_min_ind", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_max_ind", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_any_nonzero", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_reduce_all_nonzero", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, integer_type_node, NULL_TREE); new_func = build_fn_decl ("__sec_implicit_index", func_type); - mark_cold (new_func); new_func = lang_hooks.decls.pushdecl (new_func); func_type = build_function_type_list (integer_type_node, ptr_type_node, @@ -167,25 +143,23 @@ is_sec_implicit_index_fn (tree func_name) sec_implicit_index function. FN's location in the source file is is indicated by LOCATION. */ -int +HOST_WIDE_INT extract_sec_implicit_index_arg (location_t location, tree fn) { tree fn_arg; HOST_WIDE_INT return_int = 0; - if (!fn) - return -1; if (TREE_CODE (fn) == CALL_EXPR) { fn_arg = CALL_EXPR_ARG (fn, 0); if (really_constant_p (fn_arg)) - return_int = (int) int_cst_value (fn_arg); + return_int = int_cst_value (fn_arg); else { if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn)) location = EXPR_LOCATION (fn); error_at (location, "__sec_implicit_index parameter must be a " - "constant integer expression"); + "integer constant expression"); return -1; } } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index edcff2e..e07085d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -541,7 +541,7 @@ extern tree build_modify_expr (location_t, tree, tree, enum tree_code, extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code, location_t, tree, tree); extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree); -extern void find_rank (tree, bool, size_t *); +extern bool find_rank (location_t, tree, tree, bool, size_t *); extern tree build_indirect_ref (location_t, tree, ref_operator); extern int field_decl_cmp (const void *, const void *); @@ -1173,5 +1173,10 @@ typedef enum array_notation_reduce_type { extern int extract_sec_implicit_index_arg (location_t, tree); extern bool is_sec_implicit_index_fn (tree); extern void array_notation_init_builtins (void); +extern struct c_expr fix_array_notation_expr (location_t, enum tree_code, + struct c_expr); +extern bool contains_array_notation_expr (tree); +extern tree expand_array_notation_exprs (tree); +extern tree fix_conditional_array_notations (tree); #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index 30c8e80..b8af90c 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -1479,11 +1479,11 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e) case ARRAY_NOTATION_REF: pp_postfix_expression (pp, ARRAY_NOTATION_ARRAY (e)); pp_c_left_bracket (pp); - pp_postfix_expression (pp, ARRAY_NOTATION_START (e)); + pp_expression (pp, ARRAY_NOTATION_START (e)); pp_colon (pp); - pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e)); + pp_expression (pp, ARRAY_NOTATION_LENGTH (e)); pp_colon (pp); - pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e)); + pp_expression (pp, ARRAY_NOTATION_STRIDE (e)); pp_c_right_bracket (pp); break; @@ -2161,6 +2161,7 @@ pp_c_expression (c_pretty_printer *pp, tree e) case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: case ARRAY_REF: + case ARRAY_NOTATION_REF: case CALL_EXPR: case COMPONENT_REF: case BIT_FIELD_REF: diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c old mode 100644 new mode 100755 index a3e754a..3d36382 --- a/gcc/c/c-array-notation.c +++ b/gcc/c/c-array-notation.c @@ -31,19 +31,17 @@ #include "gcc.h" #include "c-family/c-common.h" -void replace_array_notations (tree *, bool, vec *, +static void replace_array_notations (tree *, bool, vec *, vec *); -void find_rank (tree, bool, size_t *); -void extract_array_notation_exprs (tree, bool, vec **); -tree fix_conditional_array_notations (tree); -struct c_expr fix_array_notation_expr (location_t, enum tree_code, - struct c_expr); -bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type); +static void extract_array_notation_exprs (tree, bool, vec **); +static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type); static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var); -bool contains_array_notation_expr (tree expr); -tree expand_array_notation_exprs (tree t); +/* This structure holds all the scalar values and its appropriate variable + replacment. It is mainly used by the function that pulls all the invariant + parts that should be executed only once that comes with array notation + expressions. */ struct inv_list { vec *list_values; @@ -51,72 +49,80 @@ struct inv_list }; -/* Returns the rank of ARRAY through the *RANK. The user can specify whether - (s)he wants to step into array_notation-specific builtin functions - (specified by the IGNORE_BUILTIN_FN). +/* Sets *RANK of expression ARRAY, ignoring array notation specific built-in + functions if IGNORE_BUILTIN_FN is true. The ORIG_EXPR is printed out if an + error occured in the rank calculation. The functions returns false if it + encounters an error in rank calculation. For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0] all have a rank of 2. */ -void -find_rank (tree array, bool ignore_builtin_fn, size_t *rank) +bool +find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn, + size_t *rank) { tree ii_tree; - size_t current_rank = 0, ii = 0; + size_t ii = 0, current_rank = 0; an_reduce_type dummy_type = REDUCE_UNKNOWN; + if (!array) - return; + return true; else if (TREE_CODE (array) == ARRAY_NOTATION_REF) { for (ii_tree = array; ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) current_rank++; - if (*rank == 0) - *rank = current_rank; + if (*rank == 0) + *rank = current_rank; + else if (*rank != current_rank) + { + error_at (loc, "rank mismatch in expression %qE", orig_expr); + return false; + } } else if (TREE_CODE (array) == STATEMENT_LIST) { tree_stmt_iterator ii_tsi; for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi)) - find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank); + if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi), + ignore_builtin_fn, rank)) + return false; } else { if (TREE_CODE (array) == CALL_EXPR) { tree func_name = CALL_EXPR_FN (array); + tree arg; + call_expr_arg_iterator iter; if (TREE_CODE (func_name) == ADDR_EXPR) if (!ignore_builtin_fn) if (is_builtin_array_notation_fn (func_name, &dummy_type)) - /* If it is a builtin function, then we know it returns a - scalar. */ - return; - if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST) - { - int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0)); - for (ii = 0; ii < (size_t) length; ii++) - find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank); - } - else - gcc_unreachable (); + /* If it is a builtin function, then it returns a scalar. */ + return true; + + FOR_EACH_CALL_EXPR_ARG (arg, iter, array) + if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank)) + return false; } else for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) - find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank); + if (!find_rank (loc, orig_expr, TREE_OPERAND (array, ii), + ignore_builtin_fn, rank)) + return false; } - return; + return true; } -/* Extracts all the array notations specified in NODE and stores them in a - dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE. The - user can specify if (s)he wants to ignore the array notations inside the - array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to - true). */ +/* Extracts all array notations in NODE ans stores in ARRAY_LIST. If + IGNORE_BUILTIN_FN is set, then array notations inside array notation + specific builtin functions are ignored. The NODE can be anything from a + full function to a single variable. */ -void +static void extract_array_notation_exprs (tree node, bool ignore_builtin_fn, vec **array_list) { @@ -148,6 +154,8 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn, } else if (TREE_CODE (node) == CALL_EXPR) { + tree arg; + call_expr_arg_iterator iter; if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type)) { if (ignore_builtin_fn) @@ -163,17 +171,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn, vec_safe_push (*array_list, node); return; } - if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST) - { - int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0)); - for (ii = 0; ii < (size_t) length; ii++) - extract_array_notation_exprs - (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list); - } - else - gcc_unreachable (); /* We should not get here. */ - + FOR_EACH_CALL_EXPR_ARG (arg, iter, node) + extract_array_notation_exprs (arg, ignore_builtin_fn, array_list); } else for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) @@ -183,15 +183,12 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn, } -/* Replaces all occurances of array notations in tree ORIG that matches the - ones in LIST with the one in ARRAY_OPERAND. The size of list and - ARRAY_OPERAND is ARRAY_SIZE. For example, ARRAY_OPERAND[x] for some index - 'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified - in LIST[x]. The user can specify if (s)he wants to ignore the array - notations inside the array-notation specific builtin functions (using the - bool variable IGNORE_BUILTIN_FN). */ +/* Replaces all the occurances of array notations in *LIST with the appropriate + one in ARRAY_OPERAND. If IGNORE_BUILTIN_FN is set, then array notations + inside array-notation specific builtin functions are ignored. ORIG can be + anything from a collection of statement lists to a single variable. */ -void +static void replace_array_notations (tree *orig, bool ignore_builtin_fn, vec *list, vec *array_operand) @@ -200,7 +197,7 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn, tree node = NULL_TREE, node_replacement = NULL_TREE; an_reduce_type dummy_type = REDUCE_UNKNOWN; - if (vec_safe_length (list) == 0 || !*orig) + if (!*orig || vec_safe_length (list) == 0) return; if (TREE_CODE (*orig) == ARRAY_NOTATION_REF) @@ -221,6 +218,8 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn, } else if (TREE_CODE (*orig) == CALL_EXPR) { + tree arg; + call_expr_arg_iterator iter; if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type)) { if (!ignore_builtin_fn) @@ -244,16 +243,14 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn, } return; } - if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST) + ii = 0; + FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig) { - int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0)); - for (ii = 0; ii < (size_t) length; ii++) - replace_array_notations - (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list, - array_operand); - } - else - gcc_unreachable (); /* We should not get here! */ + replace_array_notations (&arg, ignore_builtin_fn, list, + array_operand); + CALL_EXPR_ARG (*orig, ii) = arg; + ii++; + } } else { @@ -264,9 +261,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn, return; } -/* This function will find all the scalar expressions in *TP and push it in - DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0 then - we have do not go into the *TP's subtrees. */ +/* Find all the scalar expressions in *TP and push it in DATA struct, + typecasted to (void *). If *WALK_SUBTREES is set to 0 then do not go into + the *TP's subtrees. */ static tree find_inv_trees (tree *tp, int *walk_subtrees, void *data) @@ -322,7 +319,9 @@ replace_inv_trees (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } -/* Replaces all the scalar expressions in *NODE. */ +/* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that + holds the NODE along with variables that holds the results of the invariant + expressions. */ tree replace_invariant_exprs (tree *node) @@ -391,13 +390,16 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, tree ii_tree = NULL_TREE, new_modify_expr; vec *lhs_list = NULL, *rhs_list = NULL; tree new_var = NULL_TREE, builtin_loop = NULL_TREE; + tree begin_var, lngth_var, strde_var; size_t rhs_list_size = 0, lhs_list_size = 0; /* If either of this is true, an error message must have been send out already. Not necessary to send out multiple error messages. */ if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; - find_rank (rhs, false, &rhs_rank); + + if (!find_rank (location, rhs, rhs, false, &rhs_rank)) + return error_mark_node; extract_array_notation_exprs (rhs, false, &rhs_list); rhs_list_size = vec_safe_length (rhs_list); @@ -434,8 +436,11 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, lhs_rank = 0; rhs_rank = 0; - find_rank (lhs, true, &lhs_rank); - find_rank (rhs, true, &rhs_rank); + if (!find_rank (location, lhs, lhs, true, &lhs_rank)) + return error_mark_node; + + if (!find_rank (location, rhs, rhs, true, &rhs_rank)) + return error_mark_node; if (lhs_rank == 0 && rhs_rank == 0) { @@ -466,12 +471,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR) { tree rhs_base = rhs; - for (ii = 0; ii < (size_t) rhs_rank; ii++) - rhs_base = ARRAY_NOTATION_ARRAY (rhs); + if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF) + { + for (ii = 0; ii < (size_t) rhs_rank; ii++) + rhs_base = ARRAY_NOTATION_ARRAY (rhs); - error_at (location, "%qD cannot be scalar when %qD is not", lhs, - rhs_base); - return error_mark_node; + error_at (location, "%qE cannot be scalar when %qE is not", lhs, + rhs_base); + return error_mark_node; + } + else + { + error_at (location, "%qE cannot be scalar when %qE is not", lhs, + rhs_base); + return error_mark_node; + } + } if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) { @@ -491,6 +506,72 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, return error_mark_node; } + /* Here we assign the array notation components to variable so that we can + satisfy the exec once rule. */ + for (ii = 0; ii < lhs_list_size; ii++) + { + tree array_node = (*lhs_list)[ii]; + tree array_begin = ARRAY_NOTATION_START (array_node); + tree array_lngth = ARRAY_NOTATION_LENGTH (array_node); + tree array_strde = ARRAY_NOTATION_STRIDE (array_node); + + begin_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + lngth_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + strde_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + + add_stmt (build_modify_expr (location, begin_var, TREE_TYPE (begin_var), + NOP_EXPR, location, array_begin, + TREE_TYPE (array_begin))); + add_stmt (build_modify_expr (location, lngth_var, TREE_TYPE (lngth_var), + NOP_EXPR, location, array_lngth, + TREE_TYPE (array_lngth))); + add_stmt (build_modify_expr (location, strde_var, TREE_TYPE (strde_var), + NOP_EXPR, location, array_strde, + TREE_TYPE (array_strde))); + + ARRAY_NOTATION_START (array_node) = begin_var; + ARRAY_NOTATION_LENGTH (array_node) = lngth_var; + ARRAY_NOTATION_STRIDE (array_node) = strde_var; + } + + for (ii = 0; ii < rhs_list_size; ii++) + { + tree array_node = (*rhs_list)[ii]; + if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF) + { + tree array_begin = ARRAY_NOTATION_START (array_node); + tree array_lngth = ARRAY_NOTATION_LENGTH (array_node); + tree array_strde = ARRAY_NOTATION_STRIDE (array_node); + + begin_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + lngth_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + strde_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + + add_stmt (build_modify_expr (location, begin_var, + TREE_TYPE (begin_var), + NOP_EXPR, location, array_begin, + TREE_TYPE (array_begin))); + add_stmt (build_modify_expr (location, lngth_var, + TREE_TYPE (lngth_var), + NOP_EXPR, location, array_lngth, + TREE_TYPE (array_lngth))); + add_stmt (build_modify_expr (location, strde_var, + TREE_TYPE (strde_var), + NOP_EXPR, location, array_strde, + TREE_TYPE (array_strde))); + + ARRAY_NOTATION_START (array_node) = begin_var; + ARRAY_NOTATION_LENGTH (array_node) = lngth_var; + ARRAY_NOTATION_STRIDE (array_node) = strde_var; + } + } + lhs_vector = XNEWVEC (bool *, lhs_list_size); for (ii = 0; ii < lhs_list_size; ii++) lhs_vector[ii] = XNEWVEC (bool, lhs_rank); @@ -678,8 +759,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, rhs_vector[ii][jj] = false; } - - for (ii = 0; ii < lhs_rank; ii++) { if (lhs_vector[0][ii]) @@ -691,7 +770,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, NOP_EXPR, location, build_zero_cst (TREE_TYPE (lhs_var[ii])), TREE_TYPE (lhs_var[ii])); - } } @@ -965,19 +1043,19 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, } /* The following statements will do the following: - * : (in order from outermost to innermost) - * if (cond_expr) then go to body_label - * else go to exit_label - * : - * array expression - * - * (the increment, goto and exit_label goes from innermost to - * outermost). - * ii++ and jj++ - * go to if_stmt_label - * : - * - */ + : (in order from outermost to innermost) + if (cond_expr) then go to body_label + else go to exit_label + : + array expression + + (the increment, goto and exit_label goes from innermost to + outermost). + ii++ and jj++ + go to if_stmt_label + : + + */ for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++) @@ -1012,7 +1090,9 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, /* Encloses the conditional statement passed in STMT with a loop around it and replaces the condition in STMT with a ARRAY_REF tree-node to the array. - The condition must have a ARRAY_NOTATION_REF tree. */ + The condition must have a ARRAY_NOTATION_REF tree. An expansion of array + notation in STMT is returned in a STATEMENT_LIST. */ + static tree fix_conditional_array_notations_1 (tree stmt) @@ -1027,8 +1107,9 @@ fix_conditional_array_notations_1 (tree stmt) tree *body_label, *body_label_expr, *exit_label, *exit_label_expr; tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init; bool **count_down, **array_vector; + tree begin_var, lngth_var, strde_var; location_t location = UNKNOWN_LOCATION; - + if (TREE_CODE (stmt) == COND_EXPR) cond = COND_EXPR_COND (stmt); else if (TREE_CODE (stmt) == SWITCH_EXPR) @@ -1037,7 +1118,11 @@ fix_conditional_array_notations_1 (tree stmt) /* Otherwise dont even touch the statement. */ return stmt; - find_rank (cond, false, &rank); + location = EXPR_LOCATION (stmt); + + if (!find_rank (location, cond, cond, false, &rank)) + return error_mark_node; + extract_array_notation_exprs (cond, false, &array_list); loop = push_stmt_list (); for (ii = 0; ii < vec_safe_length (array_list); ii++) @@ -1062,7 +1147,9 @@ fix_conditional_array_notations_1 (tree stmt) } } } - find_rank (cond, true, &rank); + + if (!find_rank (location, cond, cond, true, &rank)) + return error_mark_node; if (rank == 0) { add_stmt (stmt); @@ -1076,7 +1163,6 @@ fix_conditional_array_notations_1 (tree stmt) return stmt; list_size = vec_safe_length (array_list); - location = EXPR_LOCATION (stmt); array_ops = XNEWVEC (tree *, list_size); for (ii = 0; ii < list_size; ii++) @@ -1115,6 +1201,42 @@ fix_conditional_array_notations_1 (tree stmt) array_var = XNEWVEC (tree, rank); + + for (ii = 0; ii < list_size; ii++) + { + tree array_node = (*array_list)[ii]; + if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF) + { + tree array_begin = ARRAY_NOTATION_START (array_node); + tree array_lngth = ARRAY_NOTATION_LENGTH (array_node); + tree array_strde = ARRAY_NOTATION_STRIDE (array_node); + + begin_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + lngth_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + strde_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + + add_stmt (build_modify_expr (location, begin_var, + TREE_TYPE (begin_var), + NOP_EXPR, location, array_begin, + TREE_TYPE (array_begin))); + add_stmt (build_modify_expr (location, lngth_var, + TREE_TYPE (lngth_var), + NOP_EXPR, location, array_lngth, + TREE_TYPE (array_lngth))); + add_stmt (build_modify_expr (location, strde_var, + TREE_TYPE (strde_var), + NOP_EXPR, location, array_strde, + TREE_TYPE (array_strde))); + + ARRAY_NOTATION_START (array_node) = begin_var; + ARRAY_NOTATION_LENGTH (array_node) = lngth_var; + ARRAY_NOTATION_STRIDE (array_node) = strde_var; + } + } + for (ii = 0; ii < list_size; ii++) { tree array_node = (*array_list)[ii]; @@ -1174,7 +1296,6 @@ fix_conditional_array_notations_1 (tree stmt) location, build_int_cst (TREE_TYPE (array_var[ii]), 0), TREE_TYPE (array_var[ii])); - } for (ii = 0; ii < rank ; ii++) @@ -1291,7 +1412,6 @@ fix_conditional_array_notations_1 (tree stmt) XDELETEVEC (if_stmt_label); XDELETEVEC (expr_incr); XDELETEVEC (ind_init); - // XDELETEVEC (array_var); for (ii = 0; ii < list_size; ii++) { @@ -1354,7 +1474,15 @@ fix_array_notation_expr (location_t location, enum tree_code code, tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init; bool **count_down, **array_vector; - find_rank (arg.value, false, &rank); + if (!find_rank (location, arg.value, arg.value, false, &rank)) + { + /* If this function returns a NULL, we convert the tree value in the + structure to error_mark_node and the parser should take care of the + rest. */ + arg.value = error_mark_node; + return arg; + } + if (rank == 0) return arg; @@ -1413,6 +1541,8 @@ fix_array_notation_expr (location_t location, enum tree_code code, jj++; } } + + loop = push_stmt_list (); for (ii = 0; ii < list_size; ii++) { @@ -1451,8 +1581,6 @@ fix_array_notation_expr (location_t location, enum tree_code code, } } - loop = push_stmt_list (); - for (ii = 0; ii < rank; ii++) { array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, @@ -1531,12 +1659,10 @@ fix_array_notation_expr (location_t location, enum tree_code code, replace_array_notations (&arg.value, true, array_list, array_operand); for (ii = 0; ii < rank; ii++) - { - expr_incr[ii] = - build2 (MODIFY_EXPR, void_type_node, array_var[ii], - build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii], - build_int_cst (TREE_TYPE (array_var[ii]), 1))); - } + expr_incr[ii] = + build2 (MODIFY_EXPR, void_type_node, array_var[ii], + build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii], + build_int_cst (TREE_TYPE (array_var[ii]), 1))); for (jj = 0; jj < rank; jj++) { @@ -1553,7 +1679,6 @@ fix_array_notation_expr (location_t location, enum tree_code code, array_var[jj], array_length[0][jj]); } } - for (ii = 0; ii < rank; ii++) { @@ -1669,10 +1794,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR || TREE_CODE (func_parm) == NOP_EXPR) func_parm = TREE_OPERAND (func_parm, 0); - - find_rank (an_builtin_fn, true, &rank); location = EXPR_LOCATION (an_builtin_fn); + + if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank)) + return error_mark_node; if (rank == 0) return an_builtin_fn; @@ -1680,7 +1806,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) && (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)) { error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot" - " have arrays with dimension greater than 1."); + " have arrays with dimension greater than 1"); return error_mark_node; } @@ -1712,7 +1838,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_var_type = NULL_TREE; break; default: - gcc_unreachable (); /* You should not reach here. */ + gcc_unreachable (); } array_ops = XNEWVEC (tree *, list_size); @@ -1879,12 +2005,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) } replace_array_notations (&func_parm, true, array_list, array_operand); for (ii = 0; ii < rank; ii++) - { - expr_incr[ii] = - build2 (MODIFY_EXPR, void_type_node, array_var[ii], - build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii], - build_int_cst (TREE_TYPE (array_var[ii]), 1))); - } + expr_incr[ii] = + build2 (MODIFY_EXPR, void_type_node, array_var[ii], + build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii], + build_int_cst (TREE_TYPE (array_var[ii]), 1))); + for (jj = 0; jj < rank; jj++) { @@ -2218,10 +2343,10 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) return loop; } -/* Returns true of FUNC_NAME is a builtin array notation function. The type of +/* Returns true if FUNC_NAME is a builtin array notation function. The type of function is returned in *TYPE. */ -bool +static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) { const char *function_name = NULL; @@ -2310,7 +2435,7 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) } -/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node. */ +/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node. */ bool contains_array_notation_expr (tree expr) @@ -2331,9 +2456,8 @@ contains_array_notation_expr (tree expr) return true; } -/* Replaces array notations in void function call arguments in ARG with loop and - tree-node ARRAY_REF and returns that value in a tree node variable called - LOOP. */ +/* Replaces array notations in void function call arguments in ARG and returns + a STATEMENT_LIST. */ static tree fix_array_notation_call_expr (tree arg) @@ -2347,6 +2471,7 @@ fix_array_notation_call_expr (tree arg) tree *body_label, *body_label_expr, *exit_label, *exit_label_expr; tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init; bool **count_down, **array_vector; + tree begin_var, lngth_var, strde_var; an_reduce_type an_type = REDUCE_UNKNOWN; location_t location = UNKNOWN_LOCATION; @@ -2359,12 +2484,13 @@ fix_array_notation_call_expr (tree arg) return loop; } - find_rank (arg, false, &rank); + if (!find_rank (location, arg, arg, false, &rank)) + return error_mark_node; + if (rank == 0) return arg; extract_array_notation_exprs (arg, true, &array_list); - if (vec_safe_length (array_list) == 0) return arg; @@ -2407,7 +2533,42 @@ fix_array_notation_call_expr (tree arg) count_down[ii] = XNEWVEC (bool, rank); array_var = XNEWVEC (tree, rank); + + loop = push_stmt_list (); + for (ii = 0; ii < list_size; ii++) + { + tree array_node = (*array_list)[ii]; + if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF) + { + tree array_begin = ARRAY_NOTATION_START (array_node); + tree array_lngth = ARRAY_NOTATION_LENGTH (array_node); + tree array_strde = ARRAY_NOTATION_STRIDE (array_node); + begin_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + lngth_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + strde_var = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + + add_stmt (build_modify_expr (location, begin_var, + TREE_TYPE (begin_var), + NOP_EXPR, location, array_begin, + TREE_TYPE (array_begin))); + add_stmt (build_modify_expr (location, lngth_var, + TREE_TYPE (lngth_var), + NOP_EXPR, location, array_lngth, + TREE_TYPE (array_lngth))); + add_stmt (build_modify_expr (location, strde_var, + TREE_TYPE (strde_var), + NOP_EXPR, location, array_strde, + TREE_TYPE (array_strde))); + + ARRAY_NOTATION_START (array_node) = begin_var; + ARRAY_NOTATION_LENGTH (array_node) = lngth_var; + ARRAY_NOTATION_STRIDE (array_node) = strde_var; + } + } for (ii = 0; ii < list_size; ii++) { jj = 0; @@ -2457,8 +2618,6 @@ fix_array_notation_call_expr (tree arg) } } - loop = push_stmt_list (); - for (ii = 0; ii < rank; ii++) { array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, @@ -2610,7 +2769,9 @@ fix_array_notation_call_expr (tree arg) /* Walks through tree node T and find all the call-statments that do not return - anything and fix up any array notations they may carry. */ + anything and fix up any array notations they may carry. The return value + is the same type as T but with all array notations replaced with appropriate + STATEMENT_LISTS. */ tree expand_array_notation_exprs (tree t) @@ -2665,20 +2826,20 @@ build_array_notation_ref (location_t loc, tree array, tree start_index, tree array_ntn_tree = NULL_TREE; size_t stride_rank = 0, length_rank = 0, start_rank = 0; - if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index))) + if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index))) { error_at (loc, - "start-index of array notation triplet is not an integer."); + "start-index of array notation triplet is not an integer"); return error_mark_node; } - if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length))) + if (!INTEGRAL_TYPE_P (TREE_TYPE (length))) { - error_at (loc, "length of array notation triplet is not an integer."); + error_at (loc, "length of array notation triplet is not an integer"); return error_mark_node; } - if (stride && (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))) + if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride))) { - error_at (loc, "stride of array notation triplet is not an integer."); + error_at (loc, "stride of array notation triplet is not an integer"); return error_mark_node; } if (!stride) @@ -2690,24 +2851,27 @@ build_array_notation_ref (location_t loc, tree array, tree start_index, stride = build_int_cst (TREE_TYPE (start_index), 1); } - find_rank (start_index, false, &start_rank); - find_rank (length, false, &length_rank); - find_rank (stride, false, &stride_rank); + if (!find_rank (loc, start_index, start_index, false, &start_rank)) + return error_mark_node; + if (!find_rank (loc, length, length, false, &length_rank)) + return error_mark_node; + if (!find_rank (loc, stride, stride, false, &stride_rank)) + return error_mark_node; if (start_rank != 0) { error_at (loc, "rank of an array notation triplet's start-index is not " - "zero."); + "zero"); return error_mark_node; } if (length_rank != 0) { - error_at (loc, "rank of an array notation triplet's length is not zero."); + error_at (loc, "rank of an array notation triplet's length is not zero"); return error_mark_node; } if (stride_rank != 0) { - error_at (loc, "rank of array notation triplet's stride is not zero."); + error_at (loc, "rank of array notation triplet's stride is not zero"); return error_mark_node; } @@ -2747,4 +2911,3 @@ find_correct_array_notation_type (tree op) } return return_type; } - diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index ba0a7f9..2ca5a3a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -11052,14 +11052,14 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (TREE_CODE (array_type) == POINTER_TYPE) { error_at (loc, "start-index and length fields necessary for " - "using array notations in pointers."); + "using array notations in pointers"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; } if (TREE_CODE (array_type) == FUNCTION_TYPE) { error_at (loc, "array notations cannot be used with function " - "type."); + "type"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; } @@ -11074,7 +11074,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE) { error_at (loc, "array notations cannot be used with " - "function pointer arrays."); + "function pointer arrays"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; @@ -11086,7 +11086,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (!array_type_domain) { error_at (loc, "start-index and length fields necessary for " - "using array notations in dimensionless arrays."); + "using array notations in dimensionless arrays"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; } @@ -11098,7 +11098,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain))) { error_at (loc, "start-index and length fields necessary for " - "using array notations in variable-length arrays."); + "using array notations in variable-length arrays"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; } @@ -11120,7 +11120,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (TREE_CODE (array_type) == FUNCTION_TYPE) { error_at (loc, "array notations cannot be used with function " - "type."); + "type"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; } @@ -11138,7 +11138,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE) { error_at (loc, "array notations cannot be used with " - "function pointer arrays."); + "function pointer arrays"); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); return error_mark_node; diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 15dc83d..cb2fe4a 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2309,7 +2309,8 @@ build_array_ref (location_t loc, tree array, tree index) if (flag_enable_cilkplus && contains_array_notation_expr (index)) { size_t rank = 0; - find_rank (index, true, &rank); + if (!find_rank (loc, index, index, true, &rank)) + return error_mark_node; if (rank > 1) { error_at (loc, "rank of the array's index is greater than 1."); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 627bf69..3ce9969 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -82,6 +82,8 @@ extensions, accepted by GCC in C90 mode and in C++. * x86 specific memory model extensions for transactional memory:: x86 memory models. * Object Size Checking:: Built-in functions for limited buffer overflow checking. +* Cilk Plus Builtins:: Built-in functions that are part of Cilk Plus language + extension. * Other Builtins:: Other built-in functions. * Target Builtins:: Built-in functions specific to particular targets. * Target Format Checks:: Format checks specific to particular targets. @@ -8762,6 +8764,31 @@ Similar to @code{__builtin_bswap32}, except the argument and return types are 64 bit. @end deftypefn +@node Cilk Plus Builtins +@section Cilk Plus C/C++ language extension Built-in Functions. + +GCC provides support for the following built-in reduction funtions if Cilk Plus +is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag. + +@itemize @bullet +@item __sec_reduce +@item __sec_reduce_add +@item __sec_reduce_all_nonzero +@item __sec_reduce_all_zero +@item __sec_reduce_any_nonzero +@item __sec_reduce_any_zero +@item __sec_reduce_max +@item __sec_reduce_min +@item __sec_reduce_max_ind +@item __sec_reduce_min_ind +@item __sec_reduce_mul +@item __sec_reduce_mutating +@end itemize + +Further details and examples about these built-in functions are described +in the Cilk Plus language manual which can be found at +@uref{http://www.cilkplus.org}. + @node Target Builtins @section Built-in Functions Specific to Particular Target Machines diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c index 5fb3680..fd128b1 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c @@ -26,7 +26,7 @@ int main(int argc, char **argv) array[ii] = 10; array2[ii] = 5000000; } - array2[0:10:2] = array[0:10:2]; + array2[0:5:2] = array[0:5:2]; printf("==============================================\n"); for (ii = 0; ii<10; ii++) diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp new file mode 100644 index 0000000..a965997 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp @@ -0,0 +1,34 @@ +# 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 +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " +dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp deleted file mode 100644 index 6d7604b..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp +++ /dev/null @@ -1,65 +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 -# . - -# Written by Balaji V. Iyer - - -load_lib gcc-dg.exp - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " " -dg-finish - - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " -dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp new file mode 100644 index 0000000..a965997 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp @@ -0,0 +1,34 @@ +# 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 +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " +dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c index 44e7361..4035ed5 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c @@ -1,16 +1,16 @@ int main(void) { extern int func(int); - int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration." } */ - int array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration." } */ - extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration." } */ + int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration" } */ + int array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration" } */ + extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration" } */ int *a, ***b; extern char *c; int array2[10]; - a[:] = 5; /* { dg-error "start-index and length fields necessary for using array notations in pointers." } */ + a[:] = 5; /* { dg-error "start-index and length fields necessary for using array notations in pointers" } */ c[1:2] = 3; /* This is OK. */ (array2)[:] = 5; /* This is OK. */ - b[1:2][1:func(x)][:] = 3; /* { dg-error "start-index and length fields necessary for using array notations in pointers." } */ + b[1:2][1:func(x)][:] = 3; /* { dg-error "start-index and length fields necessary for using array notations in pointers" } */ } diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp deleted file mode 100644 index 6d7604b..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp +++ /dev/null @@ -1,65 +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 -# . - -# Written by Balaji V. Iyer - - -load_lib gcc-dg.exp - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " " -dg-finish - - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " " -dg-finish - -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " -dg-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c index 272ef41..82008c0 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c @@ -3,16 +3,15 @@ typedef int (*foo)(int); int main(int argc, char **argv) { int array[10], array2[10][10]; - // int array[10], array2[10], value, ii = 0; foo func_array[10]; foo func_array2[10][10]; foo ***func_array_ptr; - array[:] = func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */ - func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */ - func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */ - array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */ - func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays." } */ + array[:] = func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */ + func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */ + func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */ + array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */ + func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */ return 0; } diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c index ef39b2b..59c2d1e 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c @@ -25,18 +25,18 @@ void func (int *x) int main2 (int argc, char **argv) { int array[10], array2[10]; - array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer." } */ - array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer." } */ - array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer." } */ - func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer." } */ - array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer." } */ - array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer." } */ - array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer." } */ + array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */ + func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer" } */ + array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer" } */ - ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */ - array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer." } */ - array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */ - array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer." } */ - func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer." } */ + ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */ + func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */ return 0; } diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c new file mode 100644 index 0000000..77955a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c @@ -0,0 +1,23 @@ +int function_call (int x) +{ + return x; +} + +int main(int argc, char **argv) +{ + int array[100], array2[100][100]; + + array[:] = array[:] + array2[:][:]; /* { dg-error "rank mismatch in expression" } */ + + if (array[:] + array2[:][:]) /* { dg-error "rank mismatch in expression" } */ + return argc == 5; + + argc += function_call (array[:] + array2[5:10:2][:]); /* { dg-error "rank mismatch in expression" } */ + + argc += function_call (function_call (array[:] + array2[5:10:2][:])); /* { dg-error "rank mismatch in expression" } */ + + argc += __sec_reduce_add (array[:], array2[:][:]); /* { dg-error "rank mismatch in expression" } */ + + argc += __sec_reduce_add (array2[:][:]) + argc; /* This is OK. */ + return argc; +} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp new file mode 100644 index 0000000..37d22c5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp @@ -0,0 +1,60 @@ +# 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 +# . + +# This file was written by Balaji V. Iyer +# Many thanks to the GCC C-torture contributors. + +verbose "$tool $libdir" 1 + +set library_var [get_multilibs] +dg-init +set CILK_TORTURE_OPTIONS [list \ + { -O0 -fcilkplus -std=c99} \ + { -O1 -fcilkplus -std=c99} \ + { -O2 -fcilkplus -std=c99} \ + { -O3 -fcilkplus -fomit-frame-pointer -funroll-loops -std=c99} \ + { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \ + { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -ftree-vectorize -std=c99 } \ + { -O3 -g -fcilkplus -std=c99} \ + { -Os -fcilkplus -std=c99} ] + + + +if $tracelevel then { + strace $tracelevel +} + +# load support procs +load_lib torture-options.exp +load_lib c-torture.exp + +torture-init +set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS + +# +# main test loop +# + +foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] { + # If we're only testing specific files and this isn't one of them, skip it. + if ![runtest_file_p $runtests $src] then { + continue + } + + c-torture-execute $src +} + +torture-finish diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c new file mode 100644 index 0000000..ba70ab8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c @@ -0,0 +1,82 @@ +#ifdef HAVE_IO +#include +#endif + + +int func1(int x) +{ + /* If x == 2 then it should return 0. */ + return (x - 2); +} + +int func2(int x) +{ + /* If x == 2 then it should return 1000. */ + return (x * 500); +} + +int func3 (int x) +{ + /* If x == 2 then it should return 1. */ + /* If x == 1 then it should return 0. */ + return (x-1); +} + +int func4(int x) +{ + if (x > 0) + return x; + else + return x--; +} + + +/* This program makes an assumption that argc == 1. */ +int main (int argc, char **argv) +{ + + int array[2500]; + + /* This should set array[0->999] to 5. */ + array[argc-1:func2(++argc):1] = 5; + array[1000:500:1] = 10; /* set all variables in array[1000-->1499] to 10. */ + array[1500:500:1] = 15; /* set all variables in array[1500-->1999] to 15. */ + array[2000:500:1] = 20; /* set all variables in array[2000-->2499] to 20. */ + array[2000:500:1] = 25; /* set all variables in array[2500-->2999] to 25. */ + array[2000:500:1] = 30; /* set all variables in array[3000-->3499] to 30. */ + + argc = func3 (argc); /* This will set argc back to 1. */ +#if HAVE_IO + printf("argc = %d\n", argc); +#endif + /* If the parameters inside the function get evaluated only once, then this + if statement must work fine, i.e. the triplet values will be 0, 1000, 1. + + Otherwise, the program should crash or give some uneasy value. */ + + /* If done correctly, it should boil down to: array[0:1000:1]. */ + if (array[func3(argc):func2(++argc)] != 5) { +#ifdef HAVE_IO + printf ("Should not be there(1).\n"); +#endif + return 1; + } + + /* If done correctly, it should boil down to: array[999:500:-1]. */ + if (func4(array[func2(argc)-1:func2(argc--):func1(argc)]) != 5) { +#ifdef HAVE_IO + printf ("Should not be there(2).\n"); +#endif + return 1; + } + + /* If done correctly, it should boil down to: array[1000:500:1]. */ + if (func4 (func4(array[func2(argc++):500: func1(argc--)])) != 5) { +#ifdef HAVE_IO + printf ("Should not be there(3).\n"); +#endif + return 1; + } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp deleted file mode 100644 index 37d22c5..0000000 --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp +++ /dev/null @@ -1,60 +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 -# . - -# This file was written by Balaji V. Iyer -# Many thanks to the GCC C-torture contributors. - -verbose "$tool $libdir" 1 - -set library_var [get_multilibs] -dg-init -set CILK_TORTURE_OPTIONS [list \ - { -O0 -fcilkplus -std=c99} \ - { -O1 -fcilkplus -std=c99} \ - { -O2 -fcilkplus -std=c99} \ - { -O3 -fcilkplus -fomit-frame-pointer -funroll-loops -std=c99} \ - { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \ - { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -ftree-vectorize -std=c99 } \ - { -O3 -g -fcilkplus -std=c99} \ - { -Os -fcilkplus -std=c99} ] - - - -if $tracelevel then { - strace $tracelevel -} - -# load support procs -load_lib torture-options.exp -load_lib c-torture.exp - -torture-init -set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS - -# -# main test loop -# - -foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] { - # If we're only testing specific files and this isn't one of them, skip it. - if ![runtest_file_p $runtests $src] then { - continue - } - - c-torture-execute $src -} - -torture-finish