diff mbox

[Ping] FW: [PATCH] Cilk Plus merging to trunk (2 of n)

Message ID BF230D13CA30DD48930C31D40993300016C842FB@FMSMSX102.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Oct. 4, 2012, 6:09 p.m. UTC
Hello Richard,
	Please see my responses below. Also attached, please find a fixed patch. Is this OK for trunk?

Here are the ChangeLog entries:
========================================================================================
gcc/ChangeLog
2012-10-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* Makefile.in (C_COMMON_OBJS): Added c-family/array-notation-common.o.
	* doc/passes.texi (Cilk Plus Transformation): Documented array 
	notation and overall transformations for Cilk Plus.
	* doc/invoke.texi (C Dialect Options): Documented -fcilkplus flag.
	* doc/generic.texi (Storage References): Documented ARRAY_NOTATION_REF
	tree addition.

gcc/c-family/ChangeLog
2012-10-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-common.h (build_array_notation_expr): New function declaration.
	(ARRAY_NOTATION_ARRAY): Added new #define.
	(ARRAY_NOTATION_CHECK): Likewise.
	(ARRAY_NOTATION_START): Likewise.
	(ARRAY_NOTATION_LENGTH): Likewise.
	(ARRAY_NOTATION_STRIDE): Likewise.
	(ARRAY_NOTATION_TYPE): Likewise.
	(enum array_notation_reduce_type): Added new enumerator.
	* c-common.def: Added new tree ARRAY_NOTATION_REF.
	* c-common.c (c_define_builtins): Added a call to initialize array
	notation builtin functions.
	(c_common_init_ts): Set ARRAY_NOTATION_REF as typed.
	* c-pretty-print.c (pp_c_postfix_expression): Added ARRAY_NOTATION_REF
	case.
	* c.opt (-fcilkplus): Define new command line switch. 
	* array-notation-common.c: New file.

gcc/c/ChangeLog
2012-10-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-typeck.c (convert_arguments): Added a check if tree contains
	array notation expressions before throwing errors or doing anything.
	(convert_for_assignments): Likewise.
	* Make-lang.in (C_AND_OBJC_OBJS): Added c-array-notation.o.
	* c-parser.c (c_parser_compound_statement): Check if array notation code
	is used in tree, if so, then transform them into appropriate C code.
	(c_parser_expr_no_commas): Check if array notation is used in LHS or
	RHS, if so, then build array notation expression instead of regular
	modify.
	(c_parser_postfix_expression_after_primary): Added a check for colon(s)
	after square braces, if so then handle it like an array notation.  Also,
	break up array notations in unary op if found.
	(c_parser_array_notation): New function.
	* c-array-notation.c: New file.

gcc/testsuite/ChangeLog
2012-10-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* gcc.dg/cilk-plus/array_notation/execute/execute.exp: New script.
	* gcc.dg/cilk-plus/array_notation/compile/compile.exp: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/errors.exp: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c: New test.
	* gcc.dg/cilk-plus/array_notation/execute/if_test.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c: 
	Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c:
	Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c: 
	Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/array_test2.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/execute/array_test1.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c:
	Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/if_test.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c:
	Likewise.
	* gcc.dg/cilk-plus/array_notation/compile/array_test1.c: Likewise
	* gcc.dg/cilk-plus/array_notation/compile/array_test2.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/parse_error.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/parse_error2.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/parse_error3.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/parse_error4.c: Likewise.
	* gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c: 
	Likewise.
============================================================================================

>-----Original Message-----
>From: Richard Guenther [mailto:richard.guenther@gmail.com]
>Sent: Thursday, October 04, 2012 4:29 AM
>To: Iyer, Balaji V
>Cc: Joseph S. Myers; gcc-patches@gcc.gnu.org
>Subject: Re: [Ping]FW: [PATCH] Cilk Plus merging to trunk (2 of n)
>
>On Thu, Oct 4, 2012 at 2:22 AM, Iyer, Balaji V <balaji.v.iyer@intel.com> wrote:
>> Hi Joseph,
>>         Did you get a chance to look at this submission? I think I have fixed all the
>changes you have mentioned. Is it OK for trunk?
>>
>> Thanks,
>>
>> Balaji V. Iyer.
>>
>>>-----Original Message-----
>>>From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
>>>owner@gcc.gnu.org] On Behalf Of Iyer, Balaji V
>>>Sent: Wednesday, September 26, 2012 7:16 PM
>>>To: Joseph Myers
>>>Cc: gcc-patches@gcc.gnu.org; aldyh@redhat.com; rth@redhat.com;
>>>law@redhat.com
>>>Subject: RE: [PATCH] Cilk Plus merging to trunk (2 of n)
>>>
>>>Hello Joseph,
>>>       In my last patch, I forgot to add the change Richard Guenther
>>>wanted me to make. He wanted me to move the ARRAY_NOTATION_REF node
>>>from tree.def to c-family/c-common.def.  Here is a new one that has
>>>this change. I am sorry for this.
>>>
>>>Here are ChangeLog entries:
>>>
>>>gcc/ChangeLog
>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>
>>>        * tree.h (array_notation_reduce_type): Added new enumerator.
>
>This should be moved to c-tree.h then, and ...

I hope it is OK that I moved this to c-common.h. This way I can use it for C++ also when that patch comes out.

>
>>>        * Makefile.in (OBJS): Added array-notation-common.o.
>>>        * doc/passes.texi (Cilk Plus Transformation): Documented array
>>>        notation and overall transformations for Cilk Plus.
>>>        * doc/invoke.texi (C Dialect Options): Documented -fcilkplus flag.
>>>        * doc/generic.texi (Storage References): Documented
>>>ARRAY_NOTATION_REF
>>>        tree addition.
>>>        * tree-pretty-pretty.c (dump_generic_node): Added
>ARRAY_NOTATION_REF
>>>        case.
>
>... this to c-pretty-print.c and

DONE!

>
>>>        * array-notation-common.c: New file.
>
>... this to the c-common/ directory.

DONE! (I hope you meant c-family directory).

>
>Basically this should be a completely frontend-only patch.
>
>Richard.

Thanks,

Balaji V. Iyer.

>
>>>gcc/c-family/ChangeLog
>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>
>>>        * c-common.h (build_array_notation_expr): New function declaration.
>>>        (ARRAY_NOTATION_ARRAY): Added new #define.
>>>        (ARRAY_NOTATION_CHECK): Likewise.
>>>        (ARRAY_NOTATION_START): Likewise.
>>>        (ARRAY_NOTATION_LENGTH): Likewise.
>>>        (ARRAY_NOTATION_STRIDE): Likewise.
>>>        (ARRAY_NOTATION_TYPE): Likewise.
>>>        * c-common.def: Added new tree ARRAY_NOTATION_REF.
>>>        * c-common.c (c_define_builtins): Added a call to initialize array
>>>        notation builtin functions.
>>>        (c_common_init_ts): Set ARRAY_NOTATION_REF as typed.
>>>        * c.opt (-fcilkplus): Define new command line switch.
>>>
>>>gcc/c/ChangeLog
>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>
>>>        * c-typeck.c (convert_arguments): Added a check if tree contains
>>>        array notation expressions before throwing errors or doing anything.
>>>        * Make-lang.in (C_AND_OBJC_OBJS): Added c-array-notation.o.
>>>        * c-parser.c (c_parser_compound_statement): Check if array notation
>code
>>>        is used in tree, if so, then transform them into appropriate C code.
>>>        (c_parser_expr_no_commas): Check if array notation is used in LHS or
>>>        RHS, if so, then build array notation expression instead of regular
>>>        modify.
>>>        (c_parser_postfix_expression_after_primary): Added a check for colon(s)
>>>        after square braces, if so then handle it like an array notation.  Also,
>>>        break up array notations in unary op if found.
>>>        (c_parser_array_notation): New function.
>>>        * c-array-notation.c: New file.
>>>
>>>gcc/testsuite/ChangeLog
>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>
>>>        * gcc.dg/cilk-plus/array_notation/execute/execute.exp: New script.
>>>        * gcc.dg/cilk-plus/array_notation/compile/compile.exp: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/errors.exp: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c: New test.
>>>        * gcc.dg/cilk-plus/array_notation/execute/if_test.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c:
>>>        Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c:
>>>        Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c:
>>>        Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test2.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test1.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c:
>>>        Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/if_test.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c:
>>>        Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test1.c: Likewise
>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test2.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error2.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error3.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error4.c: Likewise.
>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c:
>>>        Likewise.
>>>
>>>Thanks,
>>>
>>>Balaji V. Iyer.
>>>
>>>>-----Original Message-----
>>>>From: Iyer, Balaji V
>>>>Sent: Wednesday, September 26, 2012 5:54 PM
>>>>To: 'Joseph Myers'
>>>>Cc: gcc-patches@gcc.gnu.org; aldyh@redhat.com; rth@redhat.com;
>>>>law@redhat.com
>>>>Subject: RE: [PATCH] Cilk Plus merging to trunk (2 of n)
>>>>
>>>>Hello Joseph,
>>>>      Please see my responses below and I have attached a fixed patch:
>>>>
>>>>>-----Original Message-----
>>>>>From: Joseph Myers [mailto:joseph@codesourcery.com]
>>>>>Sent: Sunday, September 23, 2012 4:45 PM
>>>>>To: Iyer, Balaji V
>>>>>Cc: gcc-patches@gcc.gnu.org; aldyh@redhat.com; rth@redhat.com;
>>>>>law@redhat.com
>>>>>Subject: Re: [PATCH] Cilk Plus merging to trunk (2 of n)
>>>>>
>>>>>On Sun, 23 Sep 2012, Iyer, Balaji V wrote:
>>>>>
>>>>>> Hello Everyone,
>>>>>>     Attached, please find a patch that will implement Cilk Plus
>>>>>> Array Notations for the C compiler. Array notations are indented
>>>>>> to allow programmers to directly express parallelism in their programs.
>>>>>> Array notations can be used to possibly see a more predictable
>>>>>> performance improvement, hardware resource-utilization and
>>>>>> vectorization. To enable the compiler recognize array notation
>>>>>> syntax, we have added a flag "-fcilkplus." If this flag is not
>>>>>> used, none of these changes are visible to the compiler user. For
>>>>>> more information and examples about array notations please see
>>>>>> Chapter 4 in the Cilk Plus Specification
>>>>>>
>>>>>(http://software.intel.com/sites/default/files/m/6/3/1/cilk_plus_lan
>>>>>gu
>>>>>a
>>>>>ge_specif
>>>>>ication.pdf).
>>>>>
>>>>>There seem to be a lot of deficiencies in this specification.  I
>>>>>list some here - I don't want answers in email explaining what is
>>>>>intended (unless it's already explained in the specification and I
>>>>>missed it), I want the specification revised to describe things in
>>>>>closer relation to C standard terms, and then you can answer in
>>>>>email pointing to the relevant wording in the improved specification
>>>>>- and to the testcases in your patch verifying that the semantics
>>>>>are properly implemented, but without needing to elaborate beyond
>>>>>pointing to specification text and
>>>>testcases for each question.
>>>>>
>>>>>What syntax productions, in C11 terms, are <array base>, <lower
>>>>>bound>, <length> and <stride> in the syntax given for section
>>>>>operators?  Are there constraints that <lower bound>, <length> and
>>>>><stride> must be of integer
>>>>type?
>>>>>Are there other constraints on their types and values?
>>>>>(For example, must anything be constant?  If there isn't such a
>>>>>requirement, what exactly is the requirement that "The right-hand
>>>>>side expression must have the same rank and size as the array
>>>>>context." - if a constraint, in what cases is it a constraint?
>>>>>Maybe a constraint that values must match if integer constant
>>>>>expressions, with non-matching runtime values, at least one not an
>>>>>integer constant expression, being undefined behavior at runtime,
>>>>>for example?  What anyway is "size" in that quoted sentence?  Unlike
>>>>>"rank" and "shape", it doesn't seem to be a defined term.)
>>>>>
>>>>>What do you mean, in standard terms, by "must have a declared size"?
>>>>>How is this defined in relation to standard C array-to-pointer decay?
>>>>>What about adjustment of function parameter types?  What about array
>>>>>sizes
>>>>declared as [*]?
>>>>>What if the <array base> is in parentheses?
>>>>>
>>>>>Should I take it, from the absence of any restrictions mentioned on
>>>>>this subject, that the array that is sectioned may have elements of
>>>>>arbitrary type - so it's valid to operate this way on arrays of
>>>>>pointers, complex numbers or structures, for example?  But that the
>>>>>usual constraints on assignment apply, so that if you try A[:] =
>>>>>B[:] where A and B are two-dimensional arrays, this is a constraint
>>>>>violation, because the elements that would be assigned elementwise
>>>>>are
>>>>themselves still arrays and C doesn't allow array assignment?
>>>>>
>>>>>Is it valid or invalid to have an expression of the form
>>>>>(A[1:2])[1:2] with parentheses around a partial array section
>>>>>expression, of which a further section is taken?  It's not in the
>>>>>syntax given, but that syntax doesn't actually show the precise syntax
>productions added to C11.
>>>>>
>>>>>What is the type of an array section expression?  What is the result
>>>>>of applying sizeof to such an expression?  What about GNU C typeof?
>>>>>Use in
>>>>>C11 _Generic?
>>>>>
>>>>>Can such expressions be used in conditional expressions, scalar ?
>>>>>section
>>>>>: other-section?  If you'd defined types, at least this could be
>>>>>deduced from the existing C rules on conditional expressions that
>>>>>say what the
>>>>permitted types are.
>>>>>Can you use them with comma operators, A[:] = (B, C[:])?  It's far
>>>>>from clear from the document as-is to what extent such expressions
>>>>>have an existence with types and values like normal expressions, in
>>>>>which case this would of course be permitted, as opposed to being
>>>>>special-case things for
>>>>the RHS of assignments.
>>>>>
>>>>>You say (4.3.2.2) that certain operators are applied with the same
>>>>>precedence and rules on permitted operands as for scalars.  What
>>>>>promotions apply?  If operations are carried out on two signed char
>>>>>arrays, for example, are the elements considered to be promoted to
>>>>>int, resulting in an expression whose type is thought of as a
>>>>>section of an array of int, which may then be converted back to
>>>>>signed char if stored in a signed char array?  (Thus, internal
>>>>>operations take place in int and what would have been overflow in
>>>>>signed char would not cause undefined
>>>>>behavior.)
>>>>>
>>>>>In general, do such conversions apply between different operands,
>>>>>and on assignment?
>>>>>
>>>>>I note you do not mention shift operators in the list in 4.3.2.2 of
>>>>>those permitted - obviously that requires testcases that they are duly
>rejected.
>>>>>
>>>>>Are functions such as __sec_reduce_add defined to apply the relevant
>>>>>operation to an accumulated value and each element of the section in
>>>>>turn, in some unspecified order?  Or may it evaluate, for example, a
>>>>>sum of four elements as (a
>>>>>+ b) + (c + d)?  What about if a user function is provided?
>>>>>
>>>>>I take it each function has constraints corresponding to those on
>>>>>the relevant arithmetic operation?  (For example, __sec_reduce_add
>>>>>couldn't be called for
>>>>>pointers.)  Can the *zero functions be called for pointers (testing
>>>>>whether they are NULL)?  What about the *max* and *min* functions?
>>>>>What about those functions for floating-point - do they follow the
>>>>>semantics of fmax / fmin regarding NaNs?  Are the results
>>>>>unspecified if the answer is a floating-point zero and both +0.0 and -0.0 are
>present?
>>>>
>>>>Here is a link to the latest spec. This should clear several of the
>>>>questions you are seeking.
>>>>(http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
>>>>Intel_Cilk_plus_lang_spec_2.htm#array)
>>>>
>>>>>
>>>>>(Regarding the patch itself, see my previous comments on previous
>>>>>patches in this series.  For example:
>>>>>
>>>>>* All functions should have comments explaining the semantics of
>>>>>their arguments and return values.
>>>>
>>>>Fixed. Please see attached patch.
>>>>
>>>>>
>>>>>* Diagnostic function calls should have explicit locations passed.
>>>>
>>>>Fixed.
>>>>
>>>>>
>>>>>* Every diagnostic (that's not an ICE) should have a corresponding
>>>>>testcase in the testsuite for the associated cases of invalid code -
>>>>>I see no tests using dg-error at all in this patch.  Every case
>>>>>where the specification says something is not permitted should have
>>>>>an associated check in the compiler, diagnostic and testcase.
>>>>
>>>>Added. Please see testsuite/gcc.dg/cilk-plus/errors directory in the patch.
>>>>
>>>>>
>>>>>* Diagnostic formatting also needs fixing to follow the GNU Coding
>Standards.
>>>>>
>>>>>* The usage
>>>>>
>>>>>+      error ("__sec_implicit_index parameter must be constant integer "
>>>>>+             "expression");
>>>>>+      error ("Bailing out due to previous error");
>>>>>+      exit (ICE_EXIT_CODE);
>>>>>
>>>>>should be avoided.  Front-end code should never need to call exit
>>>>>directly.  If you have an internal error - something that should not
>>>>>be possible for any user code, valid or invalid - use internal_error.
>>>>>If an error can occur for invalid user code, just call error_at and
>>>>>allow the compiler to continue execution to find further problems in
>>>>>the user's code,
>>>>without bailing out.
>>>>
>>>>Fixed.
>>>>
>>>>>
>>>>>* There should be nothing x86-specific about the testcases so they
>>>>>shouldn't need to be conditioned on x86 targets.
>>>>
>>>>OK, removed from the scripts.
>>>>
>>>>>
>>>>>* Avoid using "int" as a type in the compiler to count the number of
>>>>>some entity on the host, use size_t instead, there's no need to add
>>>>>new cases that will cause trouble when someone wants to build a
>>>>>program with 2^31 of something, although there are plenty of such
>>>>>cases
>>>already.
>>>>
>>>>OK.
>>>>
>>>>>
>>>>>* Instead of casting the result of xmalloc, use existing macros such
>>>>>as
>>>>XNEWVEC.
>>>>
>>>>Fixed.
>>>>
>>>>>
>>>>>* Use @option not @code for option named in the manual.
>>>>
>>>>Fixed.
>>>>
>>>>>
>>>>>* Instead of declaring non-static functions
>>>>>
>>>>>+int extract_sec_implicit_index_arg (tree); bool
>>>>>+is_sec_implicit_index_fn (tree); void array_notation_init_builtins
>>>>>+(void);
>>>>>
>>>>>in a source file (array-notation-common.c), either make them static
>>>>>or declare them in an appropriate header included everywhere needing
>>>>>those
>>>>declarations.
>>>>
>>>>Fixed.
>>>>
>>>>>
>>>>
>>>>Attached, please find a fixed patch for array notation for C. OK for trunk?
>>>>
>>>>Here is the ChangeLog for the Changes:
>>>>
>>>>gcc/ChangeLog
>>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>>
>>>>        * tree.h (array_notation_reduce_type): Added new enumerator.
>>>>        (ARRAY_NOTATION_ARRAY): Added new #define.
>>>>        (ARRAY_NOTATION_CHECK): Likewise.
>>>>        (ARRAY_NOTATION_START): Likewise.
>>>>        (ARRAY_NOTATION_LENGTH): Likewise.
>>>>        (ARRAY_NOTATION_STRIDE): Likewise.
>>>>        (ARRAY_NOTATION_TYPE): Likewise.
>>>>        * tree.def: Added new tree ARRAY_NOTATION_REF.
>>>>        * Makefile.in (OBJS): Added array-notation-common.o.
>>>>        * doc/passes.texi (Cilk Plus Transformation): Documented array
>>>>        notation and overall transformations for Cilk Plus.
>>>>        * doc/invoke.texi (C Dialect Options): Documented -fcilkplus flag.
>>>>        * doc/generic.texi (Storage References): Documented
>>>>ARRAY_NOTATION_REF
>>>>        tree addition.
>>>>        * tree-pretty-pretty.c (dump_generic_node): Added
>ARRAY_NOTATION_REF
>>>>        case.
>>>>        * array-notation-common.c: New file.
>>>>
>>>>gcc/c-family/ChangeLog
>>>>
>>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>>
>>>>        * c-common.h (build_array_notation_expr): New function declaration.
>>>>        * c-common.c (c_define_builtins): Added a call to initialize array
>>>>        notation builtin functions.
>>>>        * c.opt (-fcilkplus): Define new command line switch.
>>>>
>>>>gcc/c/ChangeLog
>>>>
>>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>>
>>>>        * c-typeck.c (convert_arguments): Added a check if tree contains
>>>>        array notation expressions before throwing errors or doing anything.
>>>>        * Make-lang.in (C_AND_OBJC_OBJS): Added c-array-notation.o.
>>>>        * c-parser.c (c_parser_compound_statement): Check if array notation
>code
>>>>        is used in tree, if so, then transform them into appropriate C code.
>>>>        (c_parser_expr_no_commas): Check if array notation is used in LHS or
>>>>        RHS, if so, then build array notation expression instead of regular
>>>>        modify.
>>>>        (c_parser_postfix_expression_after_primary): Added a check for colon(s)
>>>>        after square braces, if so then handle it like an array notation.  Also,
>>>>        break up array notations in unary op if found.
>>>>        (c_parser_array_notation): New function.
>>>>        * c-array-notation.c: New file.
>>>>
>>>>
>>>>gcc/testsuite/ChangeLog
>>>>2012-09-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>>>>
>>>>        * gcc.dg/cilk-plus/array_notation/execute/execute.exp: New script.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/compile.exp: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/errors.exp: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c: New test.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/if_test.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c:
>>>>        Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c:
>>>>        Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c:
>>>>        Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test2.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/execute/array_test1.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c:
>>>>        Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/if_test.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c:
>>>>        Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test1.c: Likewise
>>>>        * gcc.dg/cilk-plus/array_notation/compile/array_test2.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error2.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error3.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/parse_error4.c: Likewise.
>>>>        * gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c:
>>>>        Likewise.
>>>>
>>>>Thanks,
>>>>
>>>>Balaji V. Iyer.
>>>>
>>>>>There may also be other issues.)
>>>>>
>>>>>--
>>>>>Joseph S. Myers
>>>>>joseph@codesourcery.com

Comments

Joseph Myers Oct. 19, 2012, 9:37 p.m. UTC | #1
On Thu, 4 Oct 2012, Iyer, Balaji V wrote:

> >>>>Here is a link to the latest spec. This should clear several of the
> >>>>questions you are seeking.
> >>>>(http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
> >>>>Intel_Cilk_plus_lang_spec_2.htm#array)

This specification is much improved, especially as regards specifying the 
types of section expressions.  I'm not convinced that "the type of the 
array being subscripted shall have a declared size" is properly defined in 
standard terms, but I can guess reasonable semantics - that if the 
array-to-pointer decay were considered not to occur in such a context, 
then the expressions for the array being subscripted shall have array 
type, not pointer type, and the array type shall not be one with 
unspecified size (array[]), although it may be a VLA.  For example, given 
"int a[10];", it would be valid to say a[:] or (a)[:] but not (+a)[:].  I 
don't, however, see any testcases at all in this patch for that particular 
requirements - not even for the completely clear-cut cases, such as giving 
an error for "extern int a[]; a[:];" or "int *a; a[:];".

Say expr1 through expr9 are expressions with side effects, and you have:

expr1[expr2:expr3:expr4] = expr5[expr6:expr7:expr8] + expr9;

The spec says "However, in such a statement, a sub-expression with rank 
zero is evaluated only once." - that is, each of the nine expressions is 
evaluated once.  I don't see any calls to save_expr to ensure these 
semantics, or any testcases that verify that they are adhered to.

(Are multidimensional section expressions valid when what you have is 
pointers to pointers, e.g. "int ***p; p[0:10][0:10][0:10];"?  I don't see 
anything to rule them out, so I assume they are valid, but don't see 
testcases for them either.)

Looking at the patch itself:

In find_rank you have error ("Rank Mismatch!"); - this is not a properly 
formatted error message according to the GNU Coding standards (which 
typically would not have any uppercase).  I'd also suggest that when you 
find a rank, you store (through a location_t * pointer) the location of 
the first expression found with that rank, so if you then find a 
mismatching rank you can use error_at to point to that rank and then 
inform to point to the previous rank it didn't match.

I'm not convinced that your logic, falling back to examining each operand 
for a generic expression, is correct to find the ranks of all kinds of 
expressions.  For example, there are rules:

* "The rank of a simple subscript expression (postfix-expression [ 
expression ]) is the sum of the ranks of its operand expressions. The rank 
of the subscript operand shall not be greater than one." - how do you 
ensure this rule?  Where do you test for errors if the subscript has too 
high a rank (both in the front-end code, and in the testsuite), and test 
(in the testsuite) for cases where the subscript has rank 1?

* "The rank of a comma expression is the rank of its second operand." - I 
don't see anything special to handle that.  Are there testcases for rank 
of comma expressions?  Apart from testing rank, you may need to test how 
they are evaluated (that each part, with independent rank, gets fully 
evaluted in turn) - I don't see anything obvious in the code to handle 
them appropriately.

In general, I'd say you should have tests in the testsuite for each 
syntactic type of expression supported by GCC, both standard and GNU 
extensions, testing how it interacts with section expressions - both valid 
cases, and cases that are invalid because of rank mismatches.  As another 
example, you don't have tests of conditional expressions.

Where do you test (both in code, and testcases to verify errors) that "The 
rank of each expression in a section triplet shall be zero."?  What about 
"The rank of the postfix expression identifying the function to call shall 
be zero."?  "A full expression shall have rank zero, unless it appears in 
an expression statement or as the controlling expression of an if 
statement."?  (This means, I suppose, that uses such as initializers or 
sizes in array declarators must be rejected.)  I'd advise going through 
each sentence in the relevant part of the spec that says something is 
invalid and making sure you diagnose it and have a test of this.

Where in the patch you use int for the size of something (e.g. a list) on 
the host, please use size_t.

In extract_array_notation_exprs you appear to be reallocating every time 
something is added to a list (with XRESIZEVEC).  It would probably be more 
efficient to use the vec.h infrastructure for an automatically resizing 
vector on which you push things.

In c_parser_array_notation you appear to be converting indices to 
integer_type_node in some cases, not converting at all in other cases.  
But the spec says "The expressions in a triplet are converted to 
ptrdiff_t.", so you need to convert to target ptrdiff_t, not target int.  
And there's a requirement that "Each of the expressions in a section 
triplet shall have integer type.".  So you need to check that, and give an 
error if it doesn't have integer type, before converting - and of course 
add testcases for each of the possible positions for an expression having 
one that doesn't have integer type.

In c-typeck.c you disable some errors and warnings for expressions 
containing array notations.  I don't know where the later point is at 
which you check for such errors - but in any case, you need testcases for 
these diagnostics on those cases to show that they aren't being lost.

In invoke.texi you have:

+@opindex flag_enable_cilkplus

But @opindex is for the user-visible options, not for internal variables.  
That is,

@opindex fcilkplus

would be appropriate.

In passes.texi you refer to "the Cilk runtime library (located in 
libcilkrts directory)".  But no such directory is added by this patch.  
Only add references to it in documentation with the patch that adds the 
directory.
Iyer, Balaji V Oct. 19, 2012, 9:54 p.m. UTC | #2
Hi Joseph,
	Thank you very much for your response. I will look into this and get back to you soon!

-Balaji V. Iyer.

>-----Original Message-----
>From: Joseph Myers [mailto:joseph@codesourcery.com]
>Sent: Friday, October 19, 2012 5:38 PM
>To: Iyer, Balaji V
>Cc: Richard Guenther; gcc-patches@gcc.gnu.org
>Subject: RE: [Ping]FW: [PATCH] Cilk Plus merging to trunk (2 of n)
>
>On Thu, 4 Oct 2012, Iyer, Balaji V wrote:
>
>> >>>>Here is a link to the latest spec. This should clear several of
>> >>>>the questions you are seeking.
>> >>>>(http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
>> >>>>Intel_Cilk_plus_lang_spec_2.htm#array)
>
>This specification is much improved, especially as regards specifying the types of
>section expressions.  I'm not convinced that "the type of the array being
>subscripted shall have a declared size" is properly defined in standard terms, but I
>can guess reasonable semantics - that if the array-to-pointer decay were
>considered not to occur in such a context, then the expressions for the array
>being subscripted shall have array type, not pointer type, and the array type shall
>not be one with unspecified size (array[]), although it may be a VLA.  For example,
>given "int a[10];", it would be valid to say a[:] or (a)[:] but not (+a)[:].  I don't,
>however, see any testcases at all in this patch for that particular requirements -
>not even for the completely clear-cut cases, such as giving an error for "extern int
>a[]; a[:];" or "int *a; a[:];".
>
>Say expr1 through expr9 are expressions with side effects, and you have:
>
>expr1[expr2:expr3:expr4] = expr5[expr6:expr7:expr8] + expr9;
>
>The spec says "However, in such a statement, a sub-expression with rank zero is
>evaluated only once." - that is, each of the nine expressions is evaluated once.  I
>don't see any calls to save_expr to ensure these semantics, or any testcases that
>verify that they are adhered to.
>
>(Are multidimensional section expressions valid when what you have is pointers
>to pointers, e.g. "int ***p; p[0:10][0:10][0:10];"?  I don't see anything to rule
>them out, so I assume they are valid, but don't see testcases for them either.)
>
>Looking at the patch itself:
>
>In find_rank you have error ("Rank Mismatch!"); - this is not a properly formatted
>error message according to the GNU Coding standards (which typically would not
>have any uppercase).  I'd also suggest that when you find a rank, you store
>(through a location_t * pointer) the location of the first expression found with
>that rank, so if you then find a mismatching rank you can use error_at to point to
>that rank and then inform to point to the previous rank it didn't match.
>
>I'm not convinced that your logic, falling back to examining each operand for a
>generic expression, is correct to find the ranks of all kinds of expressions.  For
>example, there are rules:
>
>* "The rank of a simple subscript expression (postfix-expression [ expression ]) is
>the sum of the ranks of its operand expressions. The rank of the subscript
>operand shall not be greater than one." - how do you ensure this rule?  Where do
>you test for errors if the subscript has too high a rank (both in the front-end code,
>and in the testsuite), and test (in the testsuite) for cases where the subscript has
>rank 1?
>
>* "The rank of a comma expression is the rank of its second operand." - I don't
>see anything special to handle that.  Are there testcases for rank of comma
>expressions?  Apart from testing rank, you may need to test how they are
>evaluated (that each part, with independent rank, gets fully evaluted in turn) - I
>don't see anything obvious in the code to handle them appropriately.
>
>In general, I'd say you should have tests in the testsuite for each syntactic type of
>expression supported by GCC, both standard and GNU extensions, testing how it
>interacts with section expressions - both valid cases, and cases that are invalid
>because of rank mismatches.  As another example, you don't have tests of
>conditional expressions.
>
>Where do you test (both in code, and testcases to verify errors) that "The rank of
>each expression in a section triplet shall be zero."?  What about "The rank of the
>postfix expression identifying the function to call shall be zero."?  "A full
>expression shall have rank zero, unless it appears in an expression statement or as
>the controlling expression of an if statement."?  (This means, I suppose, that uses
>such as initializers or sizes in array declarators must be rejected.)  I'd advise going
>through each sentence in the relevant part of the spec that says something is
>invalid and making sure you diagnose it and have a test of this.
>
>Where in the patch you use int for the size of something (e.g. a list) on the host,
>please use size_t.
>
>In extract_array_notation_exprs you appear to be reallocating every time
>something is added to a list (with XRESIZEVEC).  It would probably be more
>efficient to use the vec.h infrastructure for an automatically resizing vector on
>which you push things.
>
>In c_parser_array_notation you appear to be converting indices to
>integer_type_node in some cases, not converting at all in other cases.
>But the spec says "The expressions in a triplet are converted to ptrdiff_t.", so you
>need to convert to target ptrdiff_t, not target int.
>And there's a requirement that "Each of the expressions in a section triplet shall
>have integer type.".  So you need to check that, and give an error if it doesn't
>have integer type, before converting - and of course add testcases for each of
>the possible positions for an expression having one that doesn't have integer
>type.
>
>In c-typeck.c you disable some errors and warnings for expressions containing
>array notations.  I don't know where the later point is at which you check for such
>errors - but in any case, you need testcases for these diagnostics on those cases
>to show that they aren't being lost.
>
>In invoke.texi you have:
>
>+@opindex flag_enable_cilkplus
>
>But @opindex is for the user-visible options, not for internal variables.
>That is,
>
>@opindex fcilkplus
>
>would be appropriate.
>
>In passes.texi you refer to "the Cilk runtime library (located in libcilkrts
>directory)".  But no such directory is added by this patch.
>Only add references to it in documentation with the patch that adds the
>directory.
>
>--
>Joseph S. Myers
>joseph@codesourcery.com
Joseph Myers Oct. 24, 2012, 10:46 p.m. UTC | #3
On Wed, 24 Oct 2012, Iyer, Balaji V wrote:

> > Where in the patch you use int for the size of something (e.g. a list) on the host,
> > please use size_t.
> 
> Can you please give me an example where I am violating this rule? Here 
> is a link to the last submitted patch in case you need it 
> (http://gcc.gnu.org/ml/gcc-patches/2012-10/msg00431.html).

For example, see build_array_notation_expr.  The variables ii, jj, 
rhs_list_size, lhs_list_size should be size_t.  I see no reason in 
principle those lists should not have 2^31 or more elements, on a 64-bit 
host.  Unless there is some reason why, whatever the host and target, the 
values of some variable in the compiler could never need to exceed 2^31, 
int is probably not the right type for that variable.

> Also you mention "host" and "target." What do you exactly mean by that? 
> I generally use those terms in like a cross-compiler setting (i.e. host 
> = the machine on which you are compiling and target means the target 
> architecture you are compiling for).

That's what I mean.  You're measuring the size of an array on the host, so 
use size_t not int to measure that size.  If you were measuring something 
on the target, you might need HOST_WIDE_INT (for example, a compiler on a 
32-bit host can reasonably build objects for a 64-bit target that declare 
arrays with more than 2^31 elements, so size_t is not the right type to 
use in the compiler for the size of a target array).
Iyer, Balaji V Nov. 5, 2012, 9:42 p.m. UTC | #4
Hello Joseph,
	Here is the fixed patch with all your changes and the ChangeLog entries below.

gcc/ChangeLog
2012-11-05  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * Makefile.in (C_COMMON_OBJS): Added c-family/array-notation-common.o.
        * doc/passes.texi (Cilk Plus Transformation): Documented array
        notation and overall transformations for Cilk Plus.
        * doc/invoke.texi (C Dialect Options): Documented -fcilkplus flag.
        * doc/generic.texi (Storage References): Documented ARRAY_NOTATION_REF
        tree addition.

gcc/c-family/ChangeLog
2012-11-05  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-common.h (build_array_notation_expr): New function declaration.
        (ARRAY_NOTATION_ARRAY): Added new #define.
        (ARRAY_NOTATION_CHECK): Likewise.
        (ARRAY_NOTATION_START): Likewise.
        (ARRAY_NOTATION_LENGTH): Likewise.
        (ARRAY_NOTATION_STRIDE): Likewise.
        (ARRAY_NOTATION_TYPE): Likewise.
        (enum array_notation_reduce_type): Added new enumerator.
        * c-common.def: Added new tree ARRAY_NOTATION_REF.
        * c-common.c (c_define_builtins): Added a call to initialize array
        notation builtin functions.
        (c_common_init_ts): Set ARRAY_NOTATION_REF as typed.
        * c-pretty-print.c (pp_c_postfix_expression): Added ARRAY_NOTATION_REF
        case.
        * c.opt (-fcilkplus): Define new command line switch.
        * array-notation-common.c: New file.

gcc/c/ChangeLog
2012-11-05  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-typeck.c (build_array_ref): Added a check to see if array's index
        is greater than one.  If true, then emit an error.
        (build_function_call_vec): Exclude error reporting & checking for
        builtin array-notation functions.
        (convert_arguments): Likewise.
        (c_finish_return): Added a check for array notations as a return
        expression.  If true, then emit an error.
        (c_finish_loop): Added a check for array notations in a loop condition.
        If true then emit an error.
        (lvalue_p): Added a ARRAY_NOTATION_REF case.
        * Make-lang.in (C_AND_OBJC_OBJS): Added c-array-notation.o.
        * c-parser.c (c_parser_compound_statement): Check if array notation code
        is used in tree, if so, then transform them into appropriate C code.
        (c_parser_expr_no_commas): Check if array notation is used in LHS or
        RHS, if so, then build array notation expression instead of regular
        modify.
        (c_parser_postfix_expression_after_primary): Added a check for colon(s)
        after square braces, if so then handle it like an array notation.  Also,
        break up array notations in unary op if found.
        (c_parser_direct_declarator_inner): Added a check for array notation.
        (c_parser_compound_statement): Added a check for array notation in a
        stmt.  If one is present, then expand array notation expr.
        (c_parser_if_statement): Likewise.
        (c_parser_switch_statement): Added a check for array notations in a
        switch statement's condition.  If true, then output an error.
        (c_parser_while_statement): Same as switch statement, but for a while.
        (c_parser_do_statement): Same as switch statement, but for a do-while.
        (c_parser_for_statement): Same as switch statement, but for a for-loop.
        (c_parser_unary_expression): Check if array notation is used in a
        pre-increment or pre-decrement expression.  If true, then expand them.
        (c_parser_array_notation): New function.
        * c-array-notation.c: New file.

gcc/testsuite/ChangeLog
2012-11-05  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * gcc.dg/cilk-plus/array_notation/execute/execute.exp: New script.
        * gcc.dg/cilk-plus/array_notation/compile/compile.exp: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/errors.exp: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c: New test.
        * gcc.dg/cilk-plus/array_notation/execute/comma_exp.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/conditional.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/exec-once.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/if_test.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/n-ptr_test.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/array_test2.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/execute/array_test1.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/if_test.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/compile/array_test1.c: Likewise
        * gcc.dg/cilk-plus/array_notation/compile/array_test2.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/parse_error.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/parse_error2.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/parse_error3.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/parse_error4.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c:
        Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/fn_triplet_values.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/gather-scatter.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/misc.c: Likewise.
        * gcc.dg/cilk-plus/array_notation/errors/vla.c: Likewise.

Thanks,

Balaji V. Iyer.


> -----Original Message-----
> From: Joseph Myers [mailto:joseph@codesourcery.com]
> Sent: Friday, October 19, 2012 5:38 PM
> To: Iyer, Balaji V
> Cc: Richard Guenther; gcc-patches@gcc.gnu.org
> Subject: RE: [Ping]FW: [PATCH] Cilk Plus merging to trunk (2 of n)
> 
> On Thu, 4 Oct 2012, Iyer, Balaji V wrote:
> 
> > >>>>Here is a link to the latest spec. This should clear several of
> > >>>>the questions you are seeking.
> > >>>>(http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
> > >>>>Intel_Cilk_plus_lang_spec_2.htm#array)
> 
> This specification is much improved, especially as regards specifying the types of
> section expressions.  I'm not convinced that "the type of the array being
> subscripted shall have a declared size" is properly defined in standard terms, but
> I can guess reasonable semantics - that if the array-to-pointer decay were
> considered not to occur in such a context, then the expressions for the array
> being subscripted shall have array type, not pointer type, and the array type shall
> not be one with unspecified size (array[]), although it may be a VLA.  For
> example, given "int a[10];", it would be valid to say a[:] or (a)[:] but not (+a)[:].  I
> don't, however, see any testcases at all in this patch for that particular
> requirements - not even for the completely clear-cut cases, such as giving an
> error for "extern int a[]; a[:];" or "int *a; a[:];".
> 
> Say expr1 through expr9 are expressions with side effects, and you have:
> 
> expr1[expr2:expr3:expr4] = expr5[expr6:expr7:expr8] + expr9;
> 
> The spec says "However, in such a statement, a sub-expression with rank zero is
> evaluated only once." - that is, each of the nine expressions is evaluated once.  I
> don't see any calls to save_expr to ensure these semantics, or any testcases that
> verify that they are adhered to.
> 
> (Are multidimensional section expressions valid when what you have is pointers
> to pointers, e.g. "int ***p; p[0:10][0:10][0:10];"?  I don't see anything to rule
> them out, so I assume they are valid, but don't see testcases for them either.)
> 
> Looking at the patch itself:
> 
> In find_rank you have error ("Rank Mismatch!"); - this is not a properly
> formatted error message according to the GNU Coding standards (which
> typically would not have any uppercase).  I'd also suggest that when you find a
> rank, you store (through a location_t * pointer) the location of the first
> expression found with that rank, so if you then find a mismatching rank you can
> use error_at to point to that rank and then inform to point to the previous rank
> it didn't match.
> 
> I'm not convinced that your logic, falling back to examining each operand for a
> generic expression, is correct to find the ranks of all kinds of expressions.  For
> example, there are rules:
> 
> * "The rank of a simple subscript expression (postfix-expression [ expression ]) is
> the sum of the ranks of its operand expressions. The rank of the subscript
> operand shall not be greater than one." - how do you ensure this rule?  Where
> do you test for errors if the subscript has too high a rank (both in the front-end
> code, and in the testsuite), and test (in the testsuite) for cases where the
> subscript has rank 1?
> 
> * "The rank of a comma expression is the rank of its second operand." - I don't
> see anything special to handle that.  Are there testcases for rank of comma
> expressions?  Apart from testing rank, you may need to test how they are
> evaluated (that each part, with independent rank, gets fully evaluted in turn) - I
> don't see anything obvious in the code to handle them appropriately.
> 
> In general, I'd say you should have tests in the testsuite for each syntactic type
> of expression supported by GCC, both standard and GNU extensions, testing
> how it interacts with section expressions - both valid cases, and cases that are
> invalid because of rank mismatches.  As another example, you don't have tests
> of conditional expressions.
> 
> Where do you test (both in code, and testcases to verify errors) that "The rank
> of each expression in a section triplet shall be zero."?  What about "The rank of
> the postfix expression identifying the function to call shall be zero."?  "A full
> expression shall have rank zero, unless it appears in an expression statement or
> as the controlling expression of an if statement."?  (This means, I suppose, that
> uses such as initializers or sizes in array declarators must be rejected.)  I'd advise
> going through each sentence in the relevant part of the spec that says
> something is invalid and making sure you diagnose it and have a test of this.
> 
> Where in the patch you use int for the size of something (e.g. a list) on the host,
> please use size_t.
> 
> In extract_array_notation_exprs you appear to be reallocating every time
> something is added to a list (with XRESIZEVEC).  It would probably be more
> efficient to use the vec.h infrastructure for an automatically resizing vector on
> which you push things.
> 
> In c_parser_array_notation you appear to be converting indices to
> integer_type_node in some cases, not converting at all in other cases.
> But the spec says "The expressions in a triplet are converted to ptrdiff_t.", so
> you need to convert to target ptrdiff_t, not target int.
> And there's a requirement that "Each of the expressions in a section triplet shall
> have integer type.".  So you need to check that, and give an error if it doesn't
> have integer type, before converting - and of course add testcases for each of
> the possible positions for an expression having one that doesn't have integer
> type.
> 
> In c-typeck.c you disable some errors and warnings for expressions containing
> array notations.  I don't know where the later point is at which you check for
> such errors - but in any case, you need testcases for these diagnostics on those
> cases to show that they aren't being lost.
> 
> In invoke.texi you have:
> 
> +@opindex flag_enable_cilkplus
> 
> But @opindex is for the user-visible options, not for internal variables.
> That is,
> 
> @opindex fcilkplus
> 
> would be appropriate.
> 
> In passes.texi you refer to "the Cilk runtime library (located in libcilkrts
> directory)".  But no such directory is added by this patch.
> Only add references to it in documentation with the patch that adds the
> directory.
> 
> --
> Joseph S. Myers
> joseph@codesourcery.com
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 77ba4df..6339570 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1122,7 +1122,8 @@  C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
-  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o
+  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
+  c-family/array-notation-common.o
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -1971,6 +1972,9 @@  c-family/c-semantics.o : c-family/c-semantics.c $(CONFIG_H) $(SYSTEM_H) \
 c-family/c-ada-spec.o : c-family/c-ada-spec.c c-family/c-ada-spec.h \
 	$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPP_ID_DATA_H) $(TM_H) \
 	coretypes.h tree-iterator.h dumpfile.h
+  
+c-family/array-notation-common.o : c-family/array-notation-common.c $(TREE_H) \
+	$(SYSTEM_H) $(TREE_H) coretypes.h tree-iterator.h $(DIAGNOSTIC_CORE_H)
 
 c-family/stub-objc.o : c-family/stub-objc.c $(CONFIG_H) $(SYSTEM_H) \
 	coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-objc.h
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
new file mode 100644
index 0000000..aefd80b
--- /dev/null
+++ b/gcc/c-family/array-notation-common.c
@@ -0,0 +1,193 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains the builtin functions for Array
+   notations.
+   Copyright (C) 2012  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h" 
+#include "coretypes.h"
+#include "tree.h"
+#include "langhooks.h" 
+#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.  */
+
+
+void
+array_notation_init_builtins (void)
+{
+  tree func_type = NULL_TREE;
+  tree new_func = NULL_TREE;
+  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,
+					ptr_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce", func_type);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (ptr_type_node, ptr_type_node,
+					ptr_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_mutating", func_type);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+  return;
+}
+
+/* Returns true if the function call specified in FUNC_NAME is
+   __sec_implicit_index.  */
+
+bool
+is_sec_implicit_index_fn (tree func_name)
+{
+  const char *function_name = NULL;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == FUNCTION_DECL)
+    func_name = DECL_NAME (func_name);
+  
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (func_name);
+  else if (TREE_CODE (func_name) == ADDR_EXPR)
+    {
+      func_name = TREE_OPERAND (func_name, 0);
+      if (TREE_CODE (func_name) == FUNCTION_DECL)
+	if (DECL_NAME (func_name))
+	  function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+    }
+
+  if (!function_name)
+    return false;
+  else if (!strcmp (function_name, "__sec_implicit_index"))
+    return true;
+  else
+    return false;
+}
+
+/* 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;
+
+  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);
+      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");
+	  return -1;
+	}
+    }
+  return return_int;
+}
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6de2f1c..7c425a3 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5014,6 +5014,9 @@  c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
 #include "builtins.def"
 #undef DEF_BUILTIN
 
+  /* Initialize builtin functions for Cilk Plus.  */
+  if (flag_enable_cilkplus)
+    array_notation_init_builtins ();
   targetm.init_builtins ();
 
   build_common_builtin_nodes ();
@@ -11113,6 +11116,7 @@  c_common_init_ts (void)
 {
   MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
   MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
+  MARK_TS_TYPED (ARRAY_NOTATION_REF);
 }
 
 /* Build a user-defined numeric literal out of an integer constant type VALUE
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index b6df9a3..24e6ff9 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -57,6 +57,14 @@  DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
    or for the purpose of -Wsizeof-pointer-memaccess warning.  */
 DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1)
 
+/* Array Notation expression.
+   Operand 0 is the array; operand 1 is the starting array index
+   Operand 2 contains the number of elements you need to access.
+   Operand 3 is the stride.
+   Operand 4 is the element size measured in units of alignments of
+   element type. */
+DEFTREECODE (ARRAY_NOTATION_REF, "array_notation_ref", tcc_reference, 5) 
+
 /*
 Local variables:
 mode:c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index cefe92d..6c5568c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -542,6 +542,8 @@  extern tree pushdecl_top_level (tree);
 extern tree pushdecl (tree);
 extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 			       location_t, tree, tree);
+extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
+				       location_t, tree, tree);
 extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int field_decl_cmp (const void *, const void *);
@@ -1122,4 +1124,41 @@  extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
 
 extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
 
+/* These #defines allow users to access different operands of the 
+      array notation tree.  */
+
+#define ARRAY_NOTATION_CHECK(NODE) TREE_CHECK (NODE, ARRAY_NOTATION_REF)
+#define ARRAY_NOTATION_ARRAY(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 0)
+#define ARRAY_NOTATION_START(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 1)
+#define ARRAY_NOTATION_LENGTH(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 2)
+#define ARRAY_NOTATION_STRIDE(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 3)
+#define ARRAY_NOTATION_TYPE(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 4)
+
+/* Holds to type of the reduction functions used in Array notations, that is
+   part of the Cilk Plus language extensions.  */
+typedef enum array_notation_reduce_type {
+  REDUCE_UNKNOWN = 0,
+  REDUCE_ADD,
+  REDUCE_MUL,
+  REDUCE_ALL_ZEROS,
+  REDUCE_ALL_NONZEROS,
+  REDUCE_ANY_ZEROS,
+  REDUCE_ANY_NONZEROS,
+  REDUCE_MAX,
+  REDUCE_MIN,
+  REDUCE_MAX_INDEX,
+  REDUCE_MIN_INDEX,
+  REDUCE_CUSTOM,
+  REDUCE_MUTATING
+} an_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);
+
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index edeccce..a2b7eb4 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1477,6 +1477,17 @@  pp_c_postfix_expression (c_pretty_printer *pp, tree e)
       pp_c_right_bracket (pp);
       break;
 
+    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_colon (pp);
+      pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e));
+      pp_colon (pp);
+      pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e));
+      pp_c_right_bracket (pp);
+      break;
+      
     case CALL_EXPR:
       {
 	call_expr_arg_iterator iter;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index b02c515..4bb19b9 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -759,6 +759,10 @@  Recognize built-in functions
 fbuiltin-
 C ObjC C++ ObjC++ Joined
 
+fcilkplus
+C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilkplus) Init(0)
+Enable Cilk Plus
+
 fcheck-new
 C++ ObjC++ Var(flag_check_new)
 Check the return value of new
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index a39c91c..582aaf6 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -58,7 +58,7 @@  c/gccspec.o: c/gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
 # Language-specific object files for C and Objective C.
 C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
   c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
-  $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+  c/c-array-notation.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
 
 # Language-specific object files for C.
 C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
@@ -194,3 +194,8 @@  c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_
 	langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
 	c-family/c-objc.h
 
+c/c-array-notation.o: c/c-array-notation.c c/c-lang.h $(CONFIG_H) \
+	$(SYSTEM_H) coretypes.h $(TREE_H) $(C_TREE_H) $(TARGET_H) \
+	intl.h output.h $(EXPR_H) langhooks.h tree-iterator.h $(BITMAP_H) \
+	$(GIMPLE_H) c-family/c-objc.h
+
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
new file mode 100644
index 0000000..97f3d4a
--- /dev/null
+++ b/gcc/c/c-array-notation.c
@@ -0,0 +1,2472 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains routines to handle Array Notation expression
+   handling routines in the C Compiler.
+   Copyright (C) 2011, 2012  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "tree-iterator.h"
+#include "opts.h"
+#include "gcc.h"
+#include "c-family/c-common.h"
+
+void replace_array_notations (tree *, bool, tree *, tree *, int);
+void find_rank (tree, bool, int *);
+void extract_array_notation_exprs (tree, bool, tree **, int *);
+tree fix_conditional_array_notations (tree);
+struct c_expr fix_array_notation_expr (location_t, enum tree_code,
+				       struct c_expr);
+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);
+
+
+/* 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).
+
+   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, int *rank)
+{
+  tree ii_tree;
+  int current_rank = 0, ii = 0;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  if (!array)
+    return;
+  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)
+	error ("Rank Mismatch!");
+      else if (*rank == 0)
+	*rank = current_rank;
+    }
+  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);
+    }
+  else
+    {
+      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 < length; ii++)
+		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+	    }
+	  else
+	    gcc_unreachable ();
+	}
+      else 
+	for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) 
+	  find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+    }
+  return;
+}
+
+
+/* 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,
+			      tree **array_list, int *list_size)
+{
+  int ii = 0;
+  tree *new_array_list = NULL;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
+  if (!node)
+    return;
+  else if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    {
+      ii = *list_size;
+      new_array_list = XRESIZEVEC (tree, *array_list, ii + 1);
+      gcc_assert (new_array_list);
+      new_array_list[ii] = node;
+      ii++;
+      *list_size = ii;
+      *array_list = new_array_list;
+      return;
+    }
+  else if (TREE_CODE (node) == TREE_LIST)
+    {
+      extract_array_notation_exprs (TREE_PURPOSE (node), ignore_builtin_fn,
+				    array_list, list_size);
+      extract_array_notation_exprs (TREE_VALUE (node), ignore_builtin_fn,
+				    array_list, list_size);
+      extract_array_notation_exprs (TREE_CHAIN (node), ignore_builtin_fn,
+				    array_list, list_size);
+    }
+  else if (TREE_CODE (node) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
+				      ignore_builtin_fn, array_list,
+				      list_size);
+    }
+  else if (TREE_CODE (node) == CALL_EXPR)
+    {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
+	{
+	  if (ignore_builtin_fn)
+	    return;
+	  else
+	    {
+	      ii = *list_size;
+	      new_array_list = XRESIZEVEC (tree, *array_list, ii + 1);
+	      gcc_assert (new_array_list);
+	      new_array_list[ii] = node;
+	      ii++;
+	      *list_size = ii;
+	      *array_list = new_array_list;
+	      return;
+	    }
+	}
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	{
+	  ii = *list_size;
+	  new_array_list = XRESIZEVEC (tree, *array_list, ii + 1);
+	  gcc_assert (new_array_list); 
+	  new_array_list[ii] = node;
+	  ii++;
+	  *list_size = ii;
+	  *array_list = new_array_list;
+	  return;
+	}
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+
+	  for (ii = 0; ii < length; ii++)
+	    extract_array_notation_exprs
+	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list,
+	       list_size);
+	}
+      else
+	gcc_unreachable (); /* We should not get here.  */
+	  
+    } 
+  else 
+    for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
+      extract_array_notation_exprs (TREE_OPERAND (node, ii), 
+				    ignore_builtin_fn, array_list, list_size);
+  return;
+}
+
+
+/* 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).  */
+
+void
+replace_array_notations (tree *orig, bool ignore_builtin_fn, tree *list,
+			 tree *array_operand, int array_size)
+{
+  int ii = 0;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
+  if (array_size == 0 || *list == NULL || !*orig)
+    return;
+
+  if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
+    {
+      for (ii = 0; ii < array_size; ii++)
+	{
+	  if (*orig == list[ii])
+	    *orig = array_operand[ii];
+	}
+    }
+  else if (TREE_CODE (*orig) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn,
+				 list, array_operand, array_size);
+    }
+  else if (TREE_CODE (*orig) == CALL_EXPR)
+    {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
+	{
+	  if (!ignore_builtin_fn)
+	    {
+	      for (ii = 0; ii < array_size; ii++)
+		{
+		  if (*orig == list[ii])
+		    *orig = array_operand[ii];
+		}
+	    }
+	  return;
+	}
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
+	{
+	  for (ii = 0; ii < array_size; ii++)
+	    {
+	      if (*orig == list[ii])
+		*orig = array_operand[ii];
+	    }
+	  return;
+	}
+      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
+	  for (ii = 0; ii < length; ii++)
+	    replace_array_notations
+	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+	       array_operand, array_size);
+	}
+      else
+	gcc_unreachable (); /* We should not get here!  */
+    }
+  else
+    {
+      for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++) 
+	replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, 
+				 list, array_operand, array_size);
+    }
+  return;
+}
+
+/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
+   The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
+   Their locations are specified by LHS_LOC, RHS_LOC.  The location of the
+   modify expression is location.  The original type of LHS and RHS are passed
+   in LHS_ORIGTYPE and RHS_ORIGTYPE.  */
+
+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)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL, found_builtin_fn = false;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree loop = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree *body_label = NULL, *body_label_expr = NULL;
+  tree *exit_label = NULL, *exit_label_expr = NULL, *cond_expr = NULL;
+  tree *if_stmt_label = NULL;
+  tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
+  tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
+  bool **lhs_count_down = NULL, **rhs_count_down = NULL;
+  tree *lhs_compare = NULL, *rhs_compare = NULL, *rhs_array_operand = NULL;
+  tree *lhs_array_operand = NULL;
+  int lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
+  tree ii_tree = NULL_TREE, new_modify_expr, *lhs_list = NULL;
+  tree *rhs_list = NULL, new_var = NULL_TREE, builtin_loop = NULL_TREE;
+  int rhs_list_size = 0, lhs_list_size = 0;
+
+  find_rank (rhs, false, &rhs_rank);
+  extract_array_notation_exprs (rhs, false, &rhs_list, &rhs_list_size);
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE (rhs_list[ii]) == CALL_EXPR)
+	{
+	  builtin_loop = fix_builtin_array_notation_fn (rhs_list[ii],
+							&new_var);
+	  if (builtin_loop == error_mark_node)
+	    return error_mark_node;
+	  else if (builtin_loop)
+	    {
+	      add_stmt (builtin_loop);
+	      found_builtin_fn = true;
+	      if (new_var)
+		replace_array_notations (&rhs, false, &rhs_list[ii],
+					 &new_var, 1);
+	    }
+	}
+    }
+
+  lhs_rank = 0;
+  rhs_rank = 0;
+  find_rank (lhs, true, &lhs_rank);
+  find_rank (rhs, true, &rhs_rank);
+
+  if (lhs_rank == 0 && rhs_rank == 0)
+    {
+      if (found_builtin_fn)
+	{
+	  new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
+					       modifycode, rhs_loc, rhs,
+					       rhs_origtype);
+	  add_stmt (new_modify_expr);
+	  pop_stmt_list (loop);
+	  
+	  return loop;
+	}
+      else
+	{
+	  pop_stmt_list (loop);
+	  return NULL_TREE;
+	}
+    }
+  rhs_list_size = 0;
+  rhs_list = NULL;
+  extract_array_notation_exprs (rhs, true, &rhs_list, &rhs_list_size);
+  extract_array_notation_exprs (lhs, true, &lhs_list, &lhs_list_size);
+  
+  if (lhs_rank == 0 && rhs_rank != 0)
+    {
+      tree rhs_base = rhs;
+      for (ii = 0; ii < 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;
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+  
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+      
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+  
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+  
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have the
+    following scenarios: 
+    1. LHS_RANK == RHS_RANK
+    2. LHS_RANK != RHS_RANK && RHS_RANK = 0 
+    
+    In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  body_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  body_label_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  exit_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  exit_label_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  if_stmt_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr =XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] =  XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down =  XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare =  XNEWVEC (tree, lhs_rank);
+  rhs_compare =  XNEWVEC (tree, rhs_rank);
+
+  rhs_array_operand =  XNEWVEC (tree, rhs_list_size);
+  lhs_array_operand =  XNEWVEC (tree, lhs_list_size);
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  jj = 0;
+	  for (ii_tree = lhs_list[ii];
+	       ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
+	       ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
+	    {
+	      lhs_array[ii][jj] = ii_tree;
+	      jj++;
+	    }
+	}
+    }
+  else
+    lhs_array[0][0] = NULL_TREE;
+  
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{ 
+	  jj = 0; 
+	  for (ii_tree = rhs_list[ii];
+	       ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
+	       ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
+	    {
+	      rhs_array[ii][jj] = ii_tree;
+	      jj++;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      if (TREE_CODE (lhs_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < lhs_rank; jj++)
+	    {
+	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
+		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
+		  lhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]);
+		  lhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]);
+		  lhs_vector[ii][jj] = true;
+		  /* IF the stride value is variable (i.e. not constant) then 
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
+		    lhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (lhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
+		    lhs_count_down[ii][jj] = true;
+		  else
+		    lhs_count_down[ii][jj] = false;
+		}
+	      else
+		lhs_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE (rhs_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rhs_rank; jj++)
+	    {
+	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
+		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then 
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0)))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  rhs_vector[ii][jj] = false;
+    }
+
+
+
+  for (ii = 0; ii < lhs_rank; ii++)
+    {
+      if (lhs_vector[0][ii])
+	{
+	  lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				    integer_type_node);
+	  lhs_ind_init[ii] = build_modify_expr
+	    (location, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
+	     NOP_EXPR,
+	     location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
+	     TREE_TYPE (lhs_var[ii]));
+	  
+	}
+    }
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type 
+	 integer.  */
+      rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+      rhs_ind_init[ii] = build_modify_expr
+	(location, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
+	 modifycode,
+	 location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0),
+	 TREE_TYPE (rhs_var[ii]));
+    }
+  
+
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statement will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    { 
+	      /* The last ARRAY_NOTATION element's ARRAY component should be 
+		 the array's base value.  */
+	      lhs_array_operand[ii] = lhs_value[ii][lhs_rank - 1];
+	      gcc_assert (lhs_array_operand[ii]);
+	      for (jj = lhs_rank - 1; jj >= 0; jj--)
+		{
+		  if (lhs_count_down[ii][jj])
+		      /* Array[start_index + (induction_var * stride)].  */
+		      lhs_array_operand[ii] = build_array_ref
+			(location, lhs_array_operand[ii],
+			 build2 (MINUS_EXPR, TREE_TYPE (lhs_var[jj]),
+				 lhs_start[ii][jj],
+				 build2 (MULT_EXPR, TREE_TYPE (lhs_var[jj]),
+					 lhs_var[jj],
+					 lhs_stride[ii][jj])));
+		  else
+		    lhs_array_operand[ii] = build_array_ref
+		      (location, lhs_array_operand[ii],
+		       build2 (PLUS_EXPR, TREE_TYPE (lhs_var[jj]),
+			       lhs_start[ii][jj],
+			       build2 (MULT_EXPR, TREE_TYPE (lhs_var[jj]),
+				       lhs_var[jj],
+				       lhs_stride[ii][jj])));
+		}
+	    }
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand,
+			       lhs_list_size);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      rhs_array_operand[ii] = rhs_value[ii][rhs_rank - 1];
+	      gcc_assert (rhs_array_operand[ii]);
+	      for (jj = rhs_rank - 1; jj >= 0; jj--)
+		{
+		  if (rhs_count_down[ii][jj])
+		    {
+		      /* Array[start_index - (induction_var * stride)] */
+		      rhs_array_operand[ii] = build_array_ref
+			(location, rhs_array_operand[ii],
+			 build2 (MINUS_EXPR, TREE_TYPE (rhs_var[jj]),
+				 rhs_start[ii][jj],
+				 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
+					 rhs_var[jj],
+					 rhs_stride[ii][jj])));
+		    }
+		  else
+		    {
+		      /* Array[start_index  + (induction_var * stride)] */
+		      rhs_array_operand[ii] = build_array_ref
+			(location, rhs_array_operand[ii],
+			 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[jj]),
+				 rhs_start[ii][jj],
+				 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
+					 rhs_var[jj],
+					 rhs_stride[ii][jj])));
+		    }
+		}
+	    }
+	}
+
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (TREE_CODE (rhs_list[ii]) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_list[ii]);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_list[ii]);
+		    if (idx_value == -1) /* This means we have an error.  */
+		      return error_mark_node;
+		    else if (idx_value < lhs_rank && idx_value >= 0)
+		      rhs_array_operand[ii] = lhs_var[idx_value];
+		    else
+		      {
+			int ee = 0;
+			tree lhs_base = lhs_list[ii];
+			for (ee = 0; ee < lhs_rank; ee++)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  lhs_base);
+			return error_mark_node;
+		      }
+		  }  
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand,
+			       rhs_list_size);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (TREE_CODE (rhs_list[ii]) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_list[ii]);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_list[ii]);
+		    if (idx_value == -1) /* This means we have an error.  */
+		      return error_mark_node;
+		    else if (idx_value < lhs_rank && idx_value >= 0)
+		      rhs_array_operand[ii] = lhs_var[idx_value];
+		    else
+		      {
+			int ee = 0;
+			tree lhs_base = lhs_list[ii];
+			for (ee = 0; ee < lhs_rank; ee++)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  lhs_base);
+			return error_mark_node;
+		      }
+		  }  
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand,
+			       rhs_list_size);
+      array_expr_rhs = rhs;
+      rhs_expr_incr[0] = NULL_TREE;
+    }
+
+  for (ii = 0; ii < rhs_rank; ii++) 
+    rhs_expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, rhs_var[ii], 
+				build2 
+				(PLUS_EXPR, TREE_TYPE (rhs_var[ii]), 
+				 rhs_var[ii], 
+				 build_one_cst (TREE_TYPE (rhs_var[ii]))));
+
+  for (ii = 0; ii < lhs_rank; ii++) 
+    lhs_expr_incr[ii] = build2 
+      (MODIFY_EXPR, void_type_node, lhs_var[ii], 
+       build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii], 
+	       build_one_cst (TREE_TYPE (lhs_var[ii]))));
+  
+  if (!array_expr_lhs)
+    array_expr_lhs = lhs;
+
+  array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype, 
+				  modifycode, rhs_loc, array_expr_rhs, 
+				  rhs_origtype);
+
+  for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
+    {
+      if (rhs_rank && rhs_expr_incr[jj])
+	{
+	  int iii = 0;
+	  if (lhs_count_down[0][jj])
+	    lhs_compare[jj] = build2
+	      (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+	  else
+	    lhs_compare[jj] = build2
+	      (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+
+
+	  /* The reason why we have this here is for the following case:
+	         Array[:][:] = function_call(something) + Array2[:][:];
+
+	     So, we will skip the first operand of RHS and then go to the
+	     2nd to find whether we should count up or down.  */
+	 
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	      
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    /* We use iii for rhs_length because that is the correct countdown
+	       we have to use.  */
+	      rhs_compare[jj] = build2
+		(LT_EXPR, boolean_type_node, rhs_var[jj],
+		 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
+			 rhs_length[iii][jj],
+			 build_int_cst (TREE_TYPE (rhs_var[jj]), -1)));
+	  else
+	    rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj],
+				      rhs_length[iii][jj]);
+	  cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
+				  lhs_compare[jj], rhs_compare[jj]);
+	}
+      else
+	{
+	  if (lhs_count_down[0][jj])
+	    cond_expr[jj] = build2
+	      (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+	  else
+	    cond_expr[jj] = build2
+	      (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+	}
+    }
+  
+  /* The following statements will do the following:
+   * <if_stmt_label>: (in order from outermost to innermost)
+   *                  if (cond_expr) then go to body_label
+   *                  else                go to exit_label
+   * <body_label>:
+   *                  array expression
+   *
+   *                  (the increment, goto and exit_label goes from innermost to
+   *                   outermost).
+   *                  ii++ and jj++
+   *                  go to if_stmt_label
+   * <exit_label>:
+   *                  <REST OF CODE>
+   */
+
+  
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    {
+      add_stmt (lhs_ind_init [ii]);
+      if (rhs_rank)
+	add_stmt (rhs_ind_init[ii]);
+      add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (build3 (COND_EXPR, void_type_node, cond_expr[ii],
+			build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+			build1 (GOTO_EXPR, void_type_node, exit_label[ii])));
+      add_stmt (body_label_expr[ii]);
+    }
+
+  if (MAX (lhs_rank, rhs_rank))
+    add_stmt (array_expr);
+
+  for (ii = MAX (lhs_rank, rhs_rank) - 1; ii >= 0; ii--)
+    {
+      add_stmt (lhs_expr_incr[ii]);
+      if (rhs_rank && rhs_expr_incr[ii])
+	add_stmt (rhs_expr_incr[ii]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (exit_label_expr[ii]);
+    }
+  pop_stmt_list (loop);
+  return loop;
+}
+
+/* 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)
+{
+  tree *array_list = NULL;
+  int list_size = 0;
+  tree cond = NULL;
+  int rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  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;
+  location_t location = UNKNOWN_LOCATION;
+
+  if (TREE_CODE (stmt) == COND_EXPR)
+    cond = COND_EXPR_COND (stmt);
+  else if (TREE_CODE (stmt) == SWITCH_EXPR)
+    cond = SWITCH_COND (stmt);
+  /* FIXME: Handle the case for CILK_FOR_STMT also here when Cilk For is 
+     implemented.  */
+  else
+    /* Otherwise dont even touch the statement.  */
+    return stmt;
+
+  find_rank (cond, true, &rank);
+  if (rank == 0)
+    return stmt;  
+  
+  extract_array_notation_exprs (cond, true, &array_list, &list_size);
+
+  if (*array_list == NULL_TREE || list_size == 0)
+    return stmt;
+
+  location = EXPR_LOCATION (stmt);
+  
+  array_ops =  XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] =  XNEWVEC (tree, rank);
+  
+  array_vector =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] =  XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree,  rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree,  rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+
+  array_operand =  XNEWVEC (tree, list_size);
+  
+  array_var = XNEWVEC (tree, rank);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = array_list[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = push_stmt_list();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of. */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_operand[ii] = array_value[ii][rank - 1];
+	  gcc_assert (array_operand[ii]);
+	  for (jj = rank - 1; jj >= 0; jj--)
+	    {
+	      if (count_down[ii][jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	    }
+	}
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand, list_size);
+
+  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)));
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      add_stmt (ind_init [ii]);
+      add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (build3 (COND_EXPR, void_type_node, compare_expr[ii],
+			build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+			build1 (GOTO_EXPR, void_type_node, exit_label[ii])));
+      add_stmt (body_label_expr[ii]);
+    }
+
+  add_stmt (stmt);
+
+  for (ii = rank - 1; ii >= 0; ii--)
+    {
+      add_stmt (expr_incr[ii]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (exit_label_expr[ii]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_operand);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  return loop;
+}
+
+/* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
+   in STMT.  */
+
+tree
+fix_conditional_array_notations (tree stmt)
+{
+  if (TREE_CODE (stmt) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator tsi;
+      for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
+	{
+	  tree single_stmt = *tsi_stmt_ptr (tsi);
+	  *tsi_stmt_ptr (tsi) =
+	    fix_conditional_array_notations_1 (single_stmt);
+	}
+      return stmt;
+    }
+  else
+    return fix_conditional_array_notations_1 (stmt);
+}
+
+/* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
+   LOCATION with the tree_code CODE and the array notation expr is
+   passed in ARG.  Returns the fixed c_expr in ARG itself.  */
+
+struct c_expr 
+fix_array_notation_expr (location_t location, enum tree_code code,
+			 struct c_expr arg)
+{
+
+  tree *array_list = NULL;
+  int list_size = 0;
+  int rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  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;
+  
+  find_rank (arg.value, false, &rank);
+  if (rank == 0)
+    return arg;
+
+  extract_array_notation_exprs (arg.value, true, &array_list, &list_size);
+
+  if (list_size == 0 || *array_list == NULL_TREE)
+    return arg;
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+
+  array_operand = XNEWVEC (tree, list_size);
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = array_list[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])) 
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label, i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_operand[ii] = array_value[ii][rank - 1];
+	  gcc_assert (array_operand[ii]);
+	  for (jj = rank - 1; jj >= 0; jj--)
+	    {
+	      if (count_down[ii][jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	    }
+	}
+    }
+  replace_array_notations (&arg.value, true, array_list, array_operand,
+			   list_size);
+
+  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)));
+    }
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      add_stmt (ind_init [ii]);
+      add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (build3 (COND_EXPR, void_type_node, compare_expr[ii],
+			build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+			build1 (GOTO_EXPR, void_type_node, exit_label[ii])));
+      add_stmt (body_label_expr[ii]);
+    }
+
+  if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+    {
+      arg = default_function_array_read_conversion (location, arg);
+      arg.value = build_unary_op (location, code, arg.value, 0);
+    }
+  else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+    {
+      arg = default_function_array_read_conversion (location, arg);
+      arg = parser_build_unary_op (location, code, arg);
+    }
+
+  add_stmt (arg.value);
+  
+  for (ii = rank - 1; ii >= 0; ii--)
+    {
+      add_stmt (expr_incr[ii]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (exit_label_expr[ii]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_operand);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  arg.value = loop;
+  return arg;
+}
+
+/* Replace array notation's built-in function passed in AN_BUILTIN_FN with
+   the appropriate loop and computation (all stored in variable LOOP of type
+   tree node).  The output of the function function is always a scalar and that
+   result is returned in *NEW_VAR.  *NEW_VAR is NULL_TREE if the function is
+   __sec_reduce_mutating.  */
+
+static tree
+fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
+{
+  tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
+  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
+  tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
+  tree new_exp_init = NULL_TREE;
+  an_reduce_type an_type = REDUCE_UNKNOWN;
+  tree *array_list = NULL;
+  int list_size = 0;
+  int rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+  tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+  tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  location_t location = UNKNOWN_LOCATION;
+  
+  if (!is_builtin_array_notation_fn (CALL_EXPR_FN (an_builtin_fn), &an_type))
+    return NULL_TREE;
+
+  if (an_type != REDUCE_CUSTOM && an_type != REDUCE_MUTATING)
+    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  else
+    {
+      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+      call_fn = TREE_OPERAND (call_fn, 0);
+      
+      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
+    }
+  
+  while (TREE_CODE (func_parm) == CONVERT_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 (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+	   && (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.");
+      return error_mark_node;
+    }
+  extract_array_notation_exprs (func_parm, true, &array_list, &list_size);
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+    case REDUCE_MUL:
+    case REDUCE_MAX:
+    case REDUCE_MIN:
+      new_var_type = ARRAY_NOTATION_TYPE (array_list[0]);
+      break;
+    case REDUCE_ALL_ZEROS:
+    case REDUCE_ALL_NONZEROS:
+    case REDUCE_ANY_ZEROS:
+    case REDUCE_ANY_NONZEROS:
+      new_var_type = integer_type_node;
+      break;
+    case REDUCE_MAX_INDEX:
+    case REDUCE_MIN_INDEX:
+      new_var_type = integer_type_node;
+      break;
+    case REDUCE_CUSTOM:
+      if (call_fn && identity_value) 
+	new_var_type = ARRAY_NOTATION_TYPE (array_list[0]);
+      break;
+    case REDUCE_MUTATING:
+      new_var_type = NULL_TREE;
+      break;
+    default:
+      gcc_unreachable ();  /* You should not reach here.  */
+    }
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree,  rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool,  rank);
+
+  array_operand = XNEWVEC (tree, list_size);
+  
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = array_list[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = alloc_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_operand[ii] = array_value[ii][rank - 1];
+	  gcc_assert (array_operand[ii]);
+	  for (jj = rank - 1; jj >= 0; jj--)
+	    {
+	      if (count_down[ii][jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	    }
+	}
+    }
+  replace_array_notations (&func_parm, true, array_list, array_operand,
+			   list_size);
+  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)));
+    }
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+
+  if (an_type != REDUCE_MUTATING)
+    {
+      *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
+      gcc_assert (*new_var && *new_var != error_mark_node);
+    }
+  else
+    *new_var = NULL_TREE;
+  
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    array_ind_value = build_decl (location, VAR_DECL, NULL_TREE, 
+				  TREE_TYPE (func_parm));
+			      
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
+	 location, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_MUL:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
+	 location, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_ALL_ZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      /* Initially you assume everything is zero, now if we find a case where 
+	 it is NOT true, then we set the result to false. Otherwise 
+	 we just keep the previous value.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
+      break;
+    case REDUCE_ALL_NONZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false.  Otherwise
+	 we just keep the previous value.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
+      break;
+    case REDUCE_ANY_ZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      /* Initially we assume there are NO zeros in the list. When we find 
+	 a non-zero, we keep the previous value.  If we find a zero, we 
+	 set the value to true.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
+      break;
+    case REDUCE_ANY_NONZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      /* Initially we assume there are NO non-zeros in the list. When we find 
+	 a zero, we keep the previous value.  If we find a non-zero, we set 
+	 the value to true.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
+      break;
+    case REDUCE_MAX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MAX_INDEX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 location, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_OPERAND (array_operand[0], 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (LT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN_INDEX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 location, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_OPERAND (array_operand[0], 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (GT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_CUSTOM:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, identity_value, new_var_type);
+      new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, new_call_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MUTATING:
+      new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
+      break;
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    append_to_statement_list (ind_init [ii], &loop);
+
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    append_to_statement_list (new_exp_init, &loop);
+  if (an_type != REDUCE_MUTATING)
+    append_to_statement_list (new_var_init, &loop);
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      append_to_statement_list
+	(build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+      append_to_statement_list
+	(build3 (COND_EXPR, void_type_node, compare_expr[ii],
+		 build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+		 build1 (GOTO_EXPR, void_type_node, exit_label[ii])), &loop);
+      append_to_statement_list (body_label_expr[ii], &loop);
+    }
+					   
+  append_to_statement_list (new_expr, &loop);
+  
+  for (ii = rank - 1; ii >= 0; ii--)
+    {
+      append_to_statement_list (expr_incr[ii], &loop);
+      append_to_statement_list
+	(build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+      append_to_statement_list (exit_label_expr[ii], &loop);
+    }
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_operand);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  return loop;
+}
+
+/* Returns true of FUNC_NAME is a builtin array notation function.  The type of
+   function is returned in *TYPE.  */
+
+static bool
+is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
+{
+  const char *function_name = NULL;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (func_name);
+  else if (TREE_CODE (func_name) == ADDR_EXPR)
+    {
+      func_name = TREE_OPERAND (func_name, 0);
+      if (TREE_CODE (func_name) == FUNCTION_DECL)
+	function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+    }
+  
+  if (!function_name)
+    return false;
+
+  if (!strcmp (function_name, "__sec_reduce_add"))
+    {
+      *type = REDUCE_ADD;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_mul"))
+    {
+      *type = REDUCE_MUL;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_all_zero"))
+    {
+      *type = REDUCE_ALL_ZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_all_nonzero"))
+    {
+      *type = REDUCE_ALL_NONZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_any_zero"))
+    {
+      *type = REDUCE_ANY_ZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_any_nonzero"))
+    {
+      *type = REDUCE_ANY_NONZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_max"))
+    {
+      *type = REDUCE_MAX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_min"))
+    {
+      *type = REDUCE_MIN;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_min_ind"))
+    {
+      *type = REDUCE_MIN_INDEX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_max_ind"))
+    {
+      *type = REDUCE_MAX_INDEX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce"))
+    {
+      *type = REDUCE_CUSTOM;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_mutating"))
+    {
+      *type = REDUCE_MUTATING;
+      return true;
+    }
+  else
+    {
+      *type = REDUCE_UNKNOWN;
+      return false;
+    }
+  return false;
+}
+
+
+/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
+
+bool
+contains_array_notation_expr (tree expr)
+{
+  tree *array_list = NULL;
+  int list_size = 0;
+  an_reduce_type type = REDUCE_UNKNOWN;
+
+  if (!expr)
+    return false;
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    if (is_builtin_array_notation_fn (DECL_NAME (expr), &type))
+      return true;
+  
+  extract_array_notation_exprs (expr, false, &array_list, &list_size);
+  if (array_list == NULL || list_size == 0)
+    return false;
+  else
+    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.  */
+
+static tree
+fix_array_notation_call_expr (tree arg)
+{
+  tree *array_list = NULL, new_var = NULL_TREE;
+  int list_size = 0;
+  int rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  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;
+  an_reduce_type an_type = REDUCE_UNKNOWN;
+  location_t location = UNKNOWN_LOCATION;
+
+  if (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.  */
+      return loop;
+    }
+  
+  find_rank (arg, false, &rank);
+  if (rank == 0)
+    return arg;
+  
+  extract_array_notation_exprs (arg, true, &array_list, &list_size);
+
+  if (list_size == 0 || *array_list == NULL_TREE)
+    return arg;
+
+  location = EXPR_LOCATION (arg);
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+
+  array_operand = XNEWVEC (tree, list_size);
+  
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = array_list[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])) 
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_operand[ii] = array_value[ii][rank - 1];
+	  gcc_assert (array_operand[ii]);
+
+	  for (jj = rank - 1; jj >= 0; jj--)
+	    {
+	      if (count_down[ii][jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (location, array_operand[ii],
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	    }
+	}
+    }
+  replace_array_notations (&arg, true, array_list, array_operand,
+			   list_size);
+  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)));
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+  for (ii = 0; ii < rank; ii++)
+    {
+      add_stmt (ind_init [ii]);
+      add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (build3 (COND_EXPR, void_type_node, compare_expr[ii],
+			build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+			build1 (GOTO_EXPR, void_type_node, exit_label[ii])));
+      add_stmt (body_label_expr[ii]);
+    }
+  add_stmt (arg);
+  for (ii = rank - 1; ii >= 0; ii--)
+    {
+      add_stmt (expr_incr[ii]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]));
+      add_stmt (exit_label_expr[ii]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_operand);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  arg = loop;
+  return 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.  */
+
+tree
+expand_array_notation_exprs (tree t)
+{
+  if (!t || !contains_array_notation_expr (t))
+    return t;
+
+  switch (TREE_CODE (t))
+    {
+    case BIND_EXPR:
+      t = expand_array_notation_exprs (BIND_EXPR_BODY (t));
+      return t;
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator ii_tsi;
+	for (ii_tsi = tsi_start (t); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	  *tsi_stmt_ptr (ii_tsi) = 
+	    expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi));
+      }
+      return t;
+    case CALL_EXPR:
+      t = fix_array_notation_call_expr (t);
+      return t;
+    default:
+      return t;
+    }
+  return t;
+}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index bea9791..7e04439 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -57,6 +57,13 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "plugin.h"
 
+
+extern bool contains_array_notation_expr (tree);
+extern struct c_expr fix_array_notation_expr (location_t, enum tree_code,
+					      struct c_expr);
+extern tree fix_conditional_array_notations (tree);
+extern tree expand_array_notation_exprs (tree);
+
 
 /* Initialization routine for this file.  */
 
@@ -1224,6 +1231,8 @@  static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+static tree c_parser_array_notation (c_parser *, tree, tree);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -4079,6 +4088,10 @@  c_parser_compound_statement (c_parser *parser)
     }
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
+
+  /* If the compound stmt contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (stmt))
+    stmt = expand_array_notation_exprs (stmt);
   return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
@@ -4722,6 +4735,7 @@  c_parser_if_statement (c_parser *parser)
   bool first_if = false;
   tree first_body, second_body;
   bool in_if_block;
+  tree if_stmt;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
   c_parser_consume_token (parser);
@@ -4740,7 +4754,12 @@  c_parser_if_statement (c_parser *parser)
   else
     second_body = NULL_TREE;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  if_stmt = c_end_compound_stmt (loc, block, flag_isoc99);
+
+  /* If the if statement contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (if_stmt))
+    if_stmt = fix_conditional_array_notations (if_stmt);
+  add_stmt (if_stmt);
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
@@ -5403,9 +5422,21 @@  c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
   rhs = default_function_array_read_conversion (exp_location, rhs);
-  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
-				 code, exp_location, rhs.value,
-				 rhs.original_type);
+  
+  /* The line below is where the statement has the form:
+     A = B, where A and B contain array notation exprs. So this is where
+     we handle those.  */
+  if (flag_enable_cilkplus
+      && (contains_array_notation_expr (lhs.value)
+	  || contains_array_notation_expr (rhs.value)))
+    ret.value = build_array_notation_expr (op_location, lhs.value,
+					   lhs.original_type, code,
+					   exp_location, rhs.value,
+					   rhs.original_type);
+  else
+    ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+				   code, exp_location, rhs.value,
+				   rhs.original_type);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -5885,14 +5916,26 @@  c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+      /* If the unary expression has array notations, then we expand them.  */
+      if (flag_enable_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF)
+	return fix_array_notation_expr (exp_loc, PREINCREMENT_EXPR, op);
+      else
+	{
+	  op = default_function_array_read_conversion (exp_loc, op);
+	  return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+	}
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+      /* If the unary expression has array notations, then we expand them.  */
+      if (flag_enable_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF)
+	return fix_array_notation_expr (exp_loc, PREDECREMENT_EXPR, op);
+      else
+	{
+	  op = default_function_array_read_conversion (exp_loc, op);
+	  return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+	}
     case CPP_AND:
       c_parser_consume_token (parser);
       op = c_parser_cast_expression (parser, NULL);
@@ -6886,10 +6929,35 @@  c_parser_postfix_expression_after_primary (c_parser *parser,
 	case CPP_OPEN_SQUARE:
 	  /* Array reference.  */
 	  c_parser_consume_token (parser);
-	  idx = c_parser_expression (parser).value;
-	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-				     "expected %<]%>");
-	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  if (flag_enable_cilkplus
+	      && c_parser_peek_token (parser)->type == CPP_COLON)
+	    /* If we are here, thenwe have something like this:
+	       Array [ : ]
+	    */
+	    expr.value = c_parser_array_notation (parser, NULL_TREE,
+						  expr.value);
+	  else
+	    {	      
+	      idx = c_parser_expression (parser).value;
+	      /* Here we have 3 options:
+		 1. Array [EXPR] -- Normal Array call.
+		 2. Array [EXPR : EXPR] -- Array notation without stride.
+		 3. Array [EXPR : EXPR : EXPR] -- Array notation with stride.
+
+		 For 1, we just handle it just like a normal array expression.
+		 For 2 and 3 we handle it like we handle array notations.  The
+		 idx value we have above becomes the initial/start index.
+	      */
+	      if (flag_enable_cilkplus
+		  && c_parser_peek_token (parser)->type == CPP_COLON)
+		expr.value = c_parser_array_notation (parser, idx, expr.value);
+	      else
+		{
+		  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+					     "expected %<]%>");
+		  expr.value = build_array_ref (op_loc, expr.value, idx);
+		}
+	    }
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
@@ -6994,18 +7062,32 @@  c_parser_postfix_expression_after_primary (c_parser *parser,
 	case CPP_PLUS_PLUS:
 	  /* Postincrement.  */
 	  c_parser_consume_token (parser);
-	  expr = default_function_array_read_conversion (expr_loc, expr);
-	  expr.value = build_unary_op (op_loc,
-				       POSTINCREMENT_EXPR, expr.value, 0);
+	  /* If the expression has array notations, we expand them.  */
+	  if (flag_enable_cilkplus
+	      && TREE_CODE (expr.value) == ARRAY_NOTATION_REF)
+	    expr = fix_array_notation_expr (expr_loc, POSTINCREMENT_EXPR, expr);
+	  else
+	    {
+	      expr = default_function_array_read_conversion (expr_loc, expr);
+	      expr.value = build_unary_op (op_loc,
+					   POSTINCREMENT_EXPR, expr.value, 0);
+	    }
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
 	case CPP_MINUS_MINUS:
 	  /* Postdecrement.  */
 	  c_parser_consume_token (parser);
-	  expr = default_function_array_read_conversion (expr_loc, expr);
-	  expr.value = build_unary_op (op_loc,
-				       POSTDECREMENT_EXPR, expr.value, 0);
+	  /* If the expression has array notations, we expand them.  */
+	  if (flag_enable_cilkplus
+	      && TREE_CODE (expr.value) == ARRAY_NOTATION_REF)
+	    expr = fix_array_notation_expr (expr_loc, POSTDECREMENT_EXPR, expr);
+	  else
+	    {
+	      expr = default_function_array_read_conversion (expr_loc, expr);
+	      expr.value = build_unary_op (op_loc,
+					   POSTDECREMENT_EXPR, expr.value, 0);
+	    }
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
@@ -10889,4 +10971,102 @@  c_parse_file (void)
   the_parser = NULL;
 }
 
+/* This function parses Cilk Plus array notation.  The starting index is
+   passed in INITIAL_INDEX and the array name is passes in ARRAY_VALUE.  The
+   return value of this function is a tree_node called VALUE_TREE of type
+   ARRAY_NOTATION_REF.  */
+
+static tree 
+c_parser_array_notation (c_parser *parser, tree initial_index, tree array_value)
+{
+  c_token *token = NULL;
+  tree start_index = NULL_TREE, end_index = NULL_TREE, stride = NULL_TREE;
+  tree value_tree = NULL_TREE, type = NULL_TREE, array_type = NULL_TREE;
+  tree array_type_domain = NULL_TREE; 
+  double_int x;
+
+  array_type = TREE_TYPE (array_value);
+  gcc_assert (array_type);
+  type = TREE_TYPE (array_type);
+  token = c_parser_peek_token (parser);
+  
+  if (token == NULL)
+    {
+      c_parser_error (parser, "expected %<:%> or numeral");
+      return value_tree;
+    }
+  else if (token->type == CPP_COLON)
+    {
+      if (!initial_index)
+	{
+	  /* If we are here, then we have a case like this A[:].  */
+	  c_parser_consume_token (parser);
+	  array_type_domain = TYPE_DOMAIN (array_type);
+	  gcc_assert (array_type_domain);
+	  start_index = TYPE_MINVAL (array_type_domain);
+	  start_index = fold_build1 (CONVERT_EXPR, integer_type_node,
+				     start_index);
+	  x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
+	  x.low++;
+	  end_index = double_int_to_tree (integer_type_node, x);
+	  
+	  if (tree_int_cst_lt (build_int_cst (TREE_TYPE (end_index), 0),
+			       end_index))
+	    stride = build_int_cst (TREE_TYPE (start_index), 1);
+	  else
+	    stride = build_int_cst (TREE_TYPE (start_index), -1);
+	}
+      else if (initial_index != error_mark_node)
+	{
+	  /* If we are here, then there should be 2 possibilities:
+	     1. Array [EXPR : EXPR]
+	     2. Array [EXPR : EXPR : EXPR]
+	  */
+	  start_index = initial_index;
+
+	  c_parser_consume_token (parser); /* consume the ':' */
+	  end_index = c_parser_expression (parser).value;
+	  if (!end_index || end_index == error_mark_node)
+	    {
+	      c_parser_skip_to_end_of_block_or_statement (parser);
+	      return error_mark_node;
+	    }
+	  if (c_parser_peek_token (parser)->type == CPP_COLON)
+	    {
+	      c_parser_consume_token (parser);
+	      stride = c_parser_expression (parser).value;
+	      if (!stride || stride == error_mark_node)
+		{
+		  c_parser_skip_to_end_of_block_or_statement (parser);
+		  return error_mark_node;
+		}
+	    }
+	  else
+	    if (TREE_CONSTANT (start_index) && TREE_CONSTANT (end_index)
+		&& tree_int_cst_lt (end_index, start_index))
+	      stride = build_int_cst (TREE_TYPE (start_index), -1);
+	    else
+	      stride = build_int_cst (TREE_TYPE (start_index), 1);
+	}
+      else
+	c_parser_error (parser, "expected array notation expression");
+    }
+  else
+    c_parser_error (parser, "expected array notation expression");
+  
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+    
+
+  value_tree = build5 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
+		       NULL_TREE, NULL_TREE, NULL_TREE);
+  ARRAY_NOTATION_ARRAY (value_tree) = array_value;
+  ARRAY_NOTATION_START (value_tree) = start_index;
+  ARRAY_NOTATION_LENGTH (value_tree) = end_index;
+  ARRAY_NOTATION_STRIDE (value_tree) = stride;
+  ARRAY_NOTATION_TYPE (value_tree) = type;
+
+  TREE_TYPE (value_tree) = type;
+  return value_tree;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 5b4ad28..5074398 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -112,6 +112,8 @@  static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+extern bool contains_array_notation_expr (tree);
+
 
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -2953,6 +2955,13 @@  convert_arguments (tree typelist, VEC(tree,gc) *values,
       bool npc;
       tree parmval;
 
+      /* If array notations are used, then we do not worry about this now.  We
+	 will take care of them later.  */
+      if (flag_enable_cilkplus
+	  && (contains_array_notation_expr (val)
+	      || contains_array_notation_expr (fundecl)))
+	continue;
+      
       if (type == void_type_node)
 	{
 	  if (selector)
@@ -3192,10 +3201,19 @@  convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error_at (input_location,
-		"too few arguments to function %qE", function);
-      inform_declaration (fundecl);
-      return -1;
+      /* If array notation is used and Cilk Plus is enabled, then we do not
+	 worry about this error now.  We will handle them in a later place.  */
+      if (flag_enable_cilkplus
+	  && (contains_array_notation_expr (function)
+	      || contains_array_notation_expr (build_tree_list_vec (values))))
+	;
+      else
+	{
+	  error_at (input_location,
+		    "too few arguments to function %qE", function);
+	  inform_declaration (fundecl);
+	  return -1;
+	}
     }
 
   return error_args ? -1 : (int) parmnum;
@@ -5108,6 +5126,9 @@  convert_for_assignment (location_t location, tree type, tree rhs,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
+  /* We will break up array notations in a later place.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (rhs))
+    return rhs;
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -5654,16 +5675,20 @@  convert_for_assignment (location_t location, tree type, tree rhs,
 	 or one that results from arithmetic, even including
 	 a cast to integer type.  */
       if (!null_pointer_constant)
-	WARN_FOR_ASSIGNMENT (location, 0,
-			     G_("passing argument %d of %qE makes "
-				"pointer from integer without a cast"),
-			     G_("assignment makes pointer from integer "
-				"without a cast"),
-			     G_("initialization makes pointer from "
-				"integer without a cast"),
-			     G_("return makes pointer from integer "
-				"without a cast"));
-
+	{
+	  if (flag_enable_cilkplus && contains_array_notation_expr (rhs))
+	    ;
+	  else
+	    WARN_FOR_ASSIGNMENT (location, 0,
+				 G_("passing argument %d of %qE makes "
+				    "pointer from integer without a cast"),
+				 G_("assignment makes pointer from integer "
+				    "without a cast"),
+				 G_("initialization makes pointer from "
+				    "integer without a cast"),
+				 G_("return makes pointer from integer "
+				    "without a cast"));
+	}
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index c48b663..8963147 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -1124,6 +1124,7 @@  target system bytes are not the same width as host system bytes.
 @tindex INDIRECT_REF
 @tindex MEM_REF
 @tindex ARRAY_REF
+@tindex ARRAY_NOTATION_REF
 @tindex ARRAY_RANGE_REF
 @tindex TARGET_MEM_REF
 @tindex COMPONENT_REF
@@ -1139,6 +1140,15 @@  to represent the lower bound and component size but should not be used
 directly; call @code{array_ref_low_bound} and @code{array_ref_element_size}
 instead.
 
+@item ARRAY_NOTATION_REF
+These nodes represent array notation expressions that are part of the Cilk Plus
+language extensions (enabled by @option{-fcilkplus} flag).  The first operand 
+is the array.  Second, third and fourth operands are the start-index, number of
+elements accessed (also called length) and the stride, respectively.  The 
+fifth operand holds the array type.  Around the end of the parsing stage, 
+these array notations are broken up into array references (@code{ARRAY_REF})
+enclosed inside a loop iterating from 0 to the number of elements accessed.
+
 @item ARRAY_RANGE_REF
 These nodes represent access to a range (or ``slice'') of an array.  The
 operands are the same as that for @code{ARRAY_REF} and have the same
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 297b651..821c983 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1777,6 +1777,17 @@  Program Interface v3.0 @w{@uref{http://www.openmp.org/}}.  This option
 implies @option{-pthread}, and thus is only supported on targets that
 have support for @option{-pthread}.
 
+@item -fcilkplus
+@opindex flag_enable_cilkplus
+@cindex Enable Cilk Plus
+Enable the usage of Cilk Language extension features for C/C++.  When the flag
+@option{-fcilkplus} is specified, all the Cilk Plus components are converted 
+to the appropriate C/C++ code.  The present implementation follows ABI version 
+0.9.  There are four major parts to Cilk Plus language 
+extension: Array Notations, Cilk Keywords, SIMD annotations and elemental 
+functions.  Detailed information about Cilk Plus can be found at 
+@w{@uref{http://www.cilk.com}}. 
+
 @item -fgnu-tm
 @opindex fgnu-tm
 When the option @option{-fgnu-tm} is specified, the compiler
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 8329ddd..ccd73ac 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -19,6 +19,7 @@  where near complete.
 
 @menu
 * Parsing pass::         The language front end turns text into bits.
+* Cilk Plus Transformation:: Transform Cilk Plus Code to equivalent C/C++.
 * Gimplification pass::  The bits are turned into something we can optimize.
 * Pass manager::         Sequencing the optimization passes.
 * Tree SSA passes::      Optimizations on a high-level representation.
@@ -103,6 +104,38 @@  that is more descriptive than "rest_of".
 The middle-end will, at its option, emit the function and data
 definitions immediately or queue them for later processing.
 
+@node Cilk Plus Transformation
+@section Cilk Plus Transformation
+@cindex CILK_PLUS
+
+If Cilk Plus generation (flag @option{-fcilkplus}) is enabled, all the Cilk 
+Plus code is transformed into equivalent C and C++ functions.  In addition, all
+the necessary function calls to the Cilk runtime library
+(located in libcilkrts directory) are inserted (only used by Cilk keywords).  
+Majority of this transformation occurs toward the end of the parsing and 
+right before the gimplification pass.  
+
+These are the major components to the Cilk Plus language extension:
+@itemize @bullet
+@item Array Notations:
+During parsing phase, all the array notation specific information is stored in 
+@code{ARRAY_NOTATION_REF} tree using the function 
+@code{c_parser_array_notation}.  During the end of parsing, we check the entire
+function to see if there are any array notation specific code (using the 
+function @code{contains_array_notation_expr}).  If this function returns 
+true, then we expand them using either @code{expand_array_notation_exprs} or
+@code{build_array_notation_expr}.  For the cases where array notations are 
+inside conditions, they are transformed using the function 
+@code{fix_conditional_array_notations}.  The C language-specific routines are 
+located in @file{c/c-array-notation.c} and the equivalent C++ routines are in 
+file @file{cp/cp-array-notation.c}.  Common routines such as functions to 
+initialize builtin functions are stored in @file{array-notation-common.c}.
+@end itemize
+
+Detailed information about Cilk Plus and language specification is provided in 
+@w{@uref{http://www.cilk.com/}}.  It is worth mentioning that the current 
+implementation follows ABI 0.9.
+
 @node Gimplification pass
 @section Gimplification pass
 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c
new file mode 100644
index 0000000..0c5d742
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c
@@ -0,0 +1,74 @@ 
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+  int array[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  if (argc < 2)
+    {
+      fprintf(stderr,"Usage:%s <NUMBER>\n", argv[0]);
+      return -1;
+    }
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = 15;
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[0:10:2] = 20;
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\tz = %2d\n", x, z);
+  array[x:5:z] = 50;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:z] = 505;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 25;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+					 1400;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[atoi("5"):5:1] = 5555;
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 9999;
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  return 0;
+}
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
new file mode 100644
index 0000000..5fb3680
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
@@ -0,0 +1,122 @@ 
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+  int array[10], array2[10], ii = 0, x = 2, z= 0 , y = 0 ;
+  if (argc < 2)
+    {
+      fprintf(stderr,"Usage:%s <NUMBER>\n", argv[0]);
+      return -1;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  array2[0:10:2] = array[0:10:2];
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\tz = %2d\n", x, z);
+  array2[x:5:z] = array[x:5:z];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array2[x:y:z] = array[x:y:z];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+  array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\tarray2[%2d] = %2d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = 
+			     array2[atoi("5"):atoi("5"):atoi("1")];
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\tarray2[%2d] = %2d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c
new file mode 100644
index 0000000..e8e3882
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c
@@ -0,0 +1,98 @@ 
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  int array[10][15], ii = 0, jj = 0,x = 0, z= 1 , y = 10 ;
+  int array_2[10][15];
+ 
+  if (argc != 3)
+    {
+      fprintf(stderr, "Usage: %s 10 15\n", argv[0]);
+      return -1;
+    }
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+#if 1
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%4d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c
new file mode 100644
index 0000000..cbcc682
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c
@@ -0,0 +1,73 @@ 
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c
new file mode 100644
index 0000000..8e65993
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c
@@ -0,0 +1,101 @@ 
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10], y_int2=0, y2=0;
+  double x, yy, array3[10], array4[10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 0;
+      array2[ii] = 5;
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_nonzero (array3[:] + array[4]); 
+  y_int2 = __sec_reduce_any_zero (array3[:] + array[4]); 
+  y = __sec_reduce_all_nonzero ((array3[:] + array4[:]) * (argc-1)); 
+  y2 = __sec_reduce_all_zero ((array3[:] + array4[:]) * (argc-1)); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", array3[ii] +array4[ii]);
+  }
+  printf("\n");
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", (array3[ii] + array4[ii]) * (argc-1));
+  }
+  printf("\n");
+  printf("Any Non-zeros (1st line) = %d\t All non-zeros (2nd line) = %d\n", 
+	 y_int, y);
+  printf("Any zeros (1st line) = %d\t All zeros (2nd line) = %d\n", y_int2, y2);
+#endif
+  return 0;
+}
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
new file mode 100644
index 0000000..0f93a82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
@@ -0,0 +1,65 @@ 
+#   Copyright (C) 2012 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
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+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/compile/gather_scatter.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c
new file mode 100644
index 0000000..0e7ac28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c
@@ -0,0 +1,47 @@ 
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <cstdlib> */
+
+int main(int argc, char **argv)
+{
+  int array[10][10], array2[10], array3[10], x = 0, y;
+  int x_correct, y_correct, ii, jj = 0;
+  float array4[10][10][10][10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 10; jj++)
+	{
+	  array[ii][jj] = 1+ii;
+	  array2[ii]= 2;
+	  array3[ii]= 3;
+	}
+    }
+  
+  array[array2[:]][array3[:]] = 1000;
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      printf("%4d\t", array[ii][jj]);
+    }
+    printf("\n");
+  }
+#endif
+
+  array4[array2[:]][array3[0:10:1]][array2[0:10:1]][array3[0:10:1]] =
+    (float)array[array2[:]][array3[:]]; 
+
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+      for (jj = 0; jj < 10; jj++) {
+	  for (kk = 0; kk < 10; kk++) {
+	      for (ll = 0; ll < 10; ll++) {
+		  printf("%4d\n", array4[ii][jj][kk][ll]);
+	      }
+	  }
+      }
+  }
+#endif  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c
new file mode 100644
index 0000000..833379b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c
@@ -0,0 +1,162 @@ 
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+  int x = 3, y, z, array[10], array2[10], TwodArray[10][10], jj,kk,ll ;
+  int FourDArray[10][10][10][10];
+  int ii = 0; 
+
+  if (argc != 3)
+    {
+      fprintf(stderr, "Usage: %s 10 15\n", argv[0]);
+      return;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = argc%3;
+      array2[ii]= 10;
+    }
+  
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array[ii]);
+  printf("\n");
+
+  if (!array[:])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  if (!(array[0:10:1] + array[0:10:1]))
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  x = atoi (argv[1])-10;
+  y = atoi (argv[1])/2;
+  z = (atoi (argv[1]))/5;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii % 2)
+	array[ii] = 0;
+      else
+	array[ii] = 1;
+    }
+
+  /*printf("x = %2d y = %2d z = %2d\n", x, y, z); */
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[x:y:z] != 9)
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[atoi(argv[1])-10:atoi(argv[1]): atoi(argv[1])/5])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      TwodArray[ii][jj] = atoi(argv[1]);
+
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (TwodArray[:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[:][:][:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+    for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] +
+      FourDArray[0:10:1][0:5:2][9:-10:1][x:y:z]  != 20) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c
new file mode 100644
index 0000000..0a4d806
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c
@@ -0,0 +1,41 @@ 
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int jj, kk, array_3C[10][10][10];
+  int ii,array[10], y = 0, y_int = 0, array2[10], array_3[10][10][10];
+  double x, yy, array3[10], array4[10];
+
+  array[:] = __sec_implicit_index (0);
+  array_3[:][:][:] = __sec_implicit_index (1) + __sec_implicit_index(0) +
+    __sec_implicit_index (2);
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	{
+	  array_3C[ii][jj][kk] = ii+jj+kk;
+	}
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	{
+	  printf("Computed: %3d\t Correct: %3d\t", array_3[ii][jj][kk], 
+		 array_3C[ii][jj][kk]);
+	  if (array_3[ii][jj][kk] == array_3C[ii][jj][kk])
+	    printf("OK\n");
+	  else
+	    printf("ERROR\n");
+	}
+#endif
+
+  
+  return 0;
+}
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
new file mode 100644
index 0000000..0f93a82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
@@ -0,0 +1,65 @@ 
+#   Copyright (C) 2012 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
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+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/parser_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors.c
new file mode 100644
index 0000000..58108d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors.c
@@ -0,0 +1,25 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
+
+  return 0;
+} /* { dg-error "expected ';' before" } */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c
new file mode 100644
index 0000000..173fd30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c
@@ -0,0 +1,25 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" } */
+
+  return 0; /* { dg-error "expected ';' before" } */
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c
new file mode 100644
index 0000000..e5b10a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c
@@ -0,0 +1,25 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[1::] ;  /* { dg-error "expected expression before" } */
+
+  return 0; /* { dg-error "expected ';' before" } */
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c
new file mode 100644
index 0000000..e1749d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c
@@ -0,0 +1,25 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[::] ;  /* { dg-error " expected ']' before ':' token" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c
new file mode 100644
index 0000000..173a605
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c
@@ -0,0 +1,28 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int x = 0;
+  int array[10][10], array2[10];
+
+  array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+
+  x = array2[:]; /* { dg-error "cannot be scalar when" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c
new file mode 100644
index 0000000..cf5293b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c
@@ -0,0 +1,25 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+
+  array[:][:] = __sec_implicit_index(5) + array[:][:]; /* { dg-error "__sec_implicit_index argument" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c
new file mode 100644
index 0000000..a62da97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c
@@ -0,0 +1,24 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+
+  array[:][:] = __sec_implicit_index(argc) + array[:][:]; /* { dg-error "__sec_implicit_index parameter" } */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c
new file mode 100644
index 0000000..2e74eda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c
@@ -0,0 +1,31 @@ 
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  int x, y;
+  x = __sec_reduce_max_ind (array[:][:]); /* { dg-error "cannot have arrays with dimension greater than" } */
+
+  y = __sec_reduce_max_ind (array2[:]); /* this should be OK. */
+
+  x = __sec_reduce_min_ind (array[:][:]); /* { dg-error "cannot have arrays with dimension greater than" } */
+
+  y = __sec_reduce_min_ind (array2[:]); /* this should be OK. */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c
new file mode 100644
index 0000000..74502a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c
@@ -0,0 +1,92 @@ 
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};	     
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+      
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = 15;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != 15)
+      abort ();
+  
+
+  array[0:5:2] = 20;
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != 20)
+      abort ();
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+
+  array[x:5:z] = 50;
+  
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 50)
+      abort ();
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:z] = 505;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 505)
+      abort ();
+    
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 25;
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 25)
+      abort ();
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+ 
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    1400;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 1400)
+      abort ();
+  
+
+  array[atoi("5"):5:1] = 5555;
+  
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != 5555)
+      abort ();
+  
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 9999;
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    if (array[ii] != 9999)
+      abort ();
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c
new file mode 100644
index 0000000..089f0f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c
@@ -0,0 +1,132 @@ 
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};	     
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+      
+  return x;
+}
+
+
+int main2(int argc, char **argv)
+{
+  int array[10], array2[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  
+  array2[0:5:2] = array[0:5:2];
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+ 
+  array2[x:5:z] = array[x:5:z];
+
+  for (ii = x; ii < 5; ii += z)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array2[x:y:z] = array[x:y:z];
+  for (ii = x; ii < 10; ii = ii + z)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = array2[atoi("5"):atoi("5"):atoi("1")];
+
+  for (ii = 5; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      abort ();
+ 
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c
new file mode 100644
index 0000000..3f75f14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c
@@ -0,0 +1,108 @@ 
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "10", "15"};	     
+      x = main2 (3, array);
+    }
+  else if (argc == 3)
+    x = main2 (argc, argv);
+  else
+    abort ();
+      
+  return x;
+}
+
+int main2(int argc, char **argv)
+{  
+  int array[10][15], ii = 0, jj = 0,x = 0, z= 1 , y = 10 ;
+  int array_2[10][15];
+ 
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii += 2)
+    {
+      for (jj = 0; jj < 15; jj += 3)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + 1 + 5 + array[0][5] + x)
+	    abort ();
+	}
+    }
+
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < x; ii++)
+    {
+      for (jj = 0; jj < y; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + x + y + array[ii][jj])
+	    abort ();
+	}
+    }
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  
+  for (ii = 0; ii < x; ii += z)
+    {
+      for (jj = 0; jj < y; jj += z)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] + y + z)
+	    abort ();
+	}
+    }
+
+
+ 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] * array[ii][jj])
+	    abort ();
+	}
+    }
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c
new file mode 100644
index 0000000..d4e0924
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c
@@ -0,0 +1,70 @@ 
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+double my_func (double x, double y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce (0, array3[:] * array4[:], my_func); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c
new file mode 100644
index 0000000..ca04a4f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c
@@ -0,0 +1,70 @@ 
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+void my_func (double *x, double y)
+{
+  if (*x < y)
+    *x = y;
+}
+
+
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+#if 1 
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+#endif 
+  /* array[:] = 5; */
+  __sec_reduce_mutating (&x, array3[:] * array4[:], my_func); 
+#if 1
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+  printf("Max = %5.3f\t Max Index = %2d\n", max_value, max_index);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c
new file mode 100644
index 0000000..24203bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c
@@ -0,0 +1,129 @@ 
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  /* Initialize it to the first variable.  */
+  min_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] < min_value) {
+      min_value = array3[ii] * array4[ii];
+      min_index = ii;
+    }
+
+  if (x != min_value)
+    abort ();
+  if (y != min_index)
+    abort ();
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+   /* Initialize it to the first variable.  */
+  add_value = 0.0000;
+  mul_value = 1.0000;
+  for (ii = 0; ii < 10; ii++)
+    {
+      add_value += (array3[ii] * array4[ii]);
+      mul_value *= (array3[ii] * array4[ii]);
+    }
+
+  if (x != add_value)
+    abort ();
+  if (yy != mul_value)
+    abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]);
+
+  if (y_int != 1)
+    abort ();
+
+  if (y != 0)
+    abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c
new file mode 100644
index 0000000..82ae638
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c
@@ -0,0 +1,77 @@ 
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+void exit (int);
+void abort (void);
+
+
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10], y_int2=0, y2=0;
+  double x, yy, array3[10], array4[10];
+  int all_zero, all_nonzero, any_zero, any_nonzero;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 0;
+      array2[ii] = 5;
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_nonzero (array3[:] + array[4]); 
+  y_int2 = __sec_reduce_any_zero (array3[:] + array[4]); 
+  y = __sec_reduce_all_nonzero ((array3[:] + array4[:]) * (argc-1)); 
+  y2 = __sec_reduce_all_zero ((array3[:] + array4[:]) * (argc-1));
+
+  any_zero = 0;
+  any_nonzero = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      if ((array3[ii] + array[4]) == 0)
+	any_zero = 1;
+      else
+	any_nonzero = 1;
+    }
+
+  if (any_nonzero != y_int)
+    abort ();
+  if (any_zero != y_int2)
+    abort ();
+
+
+  all_zero = 0;
+  all_nonzero = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (((array3[ii] + array4[ii]) * (argc-1)) == 0)
+	all_zero = 1;
+      else
+	all_nonzero = 1;
+    }
+
+  if (y != all_nonzero)
+    abort ();
+  if (all_zero != y2)
+    abort ();
+ 
+
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", array3[ii] +array4[ii]);
+  }
+  printf("\n");
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", (array3[ii] + array4[ii]) * (argc-1));
+  }
+  printf("\n");
+  printf("Any Non-zeros (1st line) = %d\t All non-zeros (1st line) = %d\n", 
+	 y_int, y);
+  printf("Any zeros (2nd line) = %d\t All zeros (2nd line) = %d\n", y_int2, y2);
+#endif
+  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
new file mode 100644
index 0000000..4fd3dbd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
@@ -0,0 +1,60 @@ 
+# Copyright (C) 2012 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
+# <http://www.gnu.org/licenses/>.
+
+# This file was written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+# 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/gather_scatter.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c
new file mode 100644
index 0000000..c217ca9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c
@@ -0,0 +1,60 @@ 
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+void exit (int);
+void abort(void);
+
+int main(int argc, char **argv)
+{
+  int array[10][10], array2[10], array3[10], x = 0, y;
+  int x_correct, y_correct, ii, jj = 0;
+  float array4[10][10][10][10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 10; jj++)
+	{
+	  array[ii][jj] = 1+ii;
+	  array2[ii]= 2;
+	  array3[ii]= 3;
+	}
+    }
+  
+  array[array2[:]][array3[:]] = 1000;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[array2[ii]][array3[ii]] != 1000)
+      abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      printf("%4d\t", array[ii][jj]);
+    }
+    printf("\n");
+  }
+#endif
+
+  array4[array2[:]][array3[0:10:1]][array2[0:10:1]][array3[0:10:1]] =
+    (float)array[array2[:]][array3[:]]; 
+
+  for (ii = 0; ii < 10; ii++)
+    if (array4[array2[ii]][array3[ii]][array2[ii]][array3[ii]] !=
+	(float)array[array2[ii]][array3[ii]])
+      abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+      for (jj = 0; jj < 10; jj++) {
+	  for (kk = 0; kk < 10; kk++) {
+	      for (ll = 0; ll < 10; ll++) {
+		  printf("%4d\n", array4[ii][jj][kk][ll]);
+	      }
+	  }
+      }
+  }
+#endif
+
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c
new file mode 100644
index 0000000..ac48742
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c
@@ -0,0 +1,250 @@ 
+
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "10", "15"};	     
+      x = main2 (3, array);
+    }
+  else if (argc == 3)
+    x = main2 (argc, argv);
+  else
+    abort ();
+ 
+  return x;
+}
+
+
+int main2 (int argc, char **argv)
+{
+  int x = 3, y, z, array[10], array2[10], TwodArray[10][10], jj,kk,ll ;
+  int array2_check[10];
+  int FourDArray[10][10][10][10];
+  int ii = 0; 
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = argc%3;
+      array2[ii]= 10;
+      array2_check[ii] = 10;
+    }
+
+  if (!array[:])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (!array[ii])
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+  
+
+  
+  if (!(array[0:10:1] + array[0:10:1]))
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (!(array[ii]+ array[ii]))
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+  
+
+      
+       
+
+  x = atoi (argv[1])-10;
+  y = atoi (argv[1])/2;
+  z = (atoi (argv[1]))/5;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii % 2)
+	array[ii] = 0;
+      else
+	array[ii] = 1;
+    }
+
+  /*printf("x = %2d y = %2d z = %2d\n", x, y, z); */
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[x:y:z] != 9)
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = x; ii < (x+y); ii += z)
+    {
+      if (array[ii] != 9)
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[atoi(argv[1])-10:atoi(argv[1]): atoi(argv[1])/5])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = atoi(argv[1])-10; ii < atoi(argv[1]) + (atoi (argv[1])-10);
+       ii +=atoi(argv[1])/5)
+    if (array[ii])
+      array2_check[ii] = 5;
+    else
+      array2_check[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+ 
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      TwodArray[ii][jj] = atoi(argv[1]);
+
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (TwodArray[:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      if (TwodArray[ii][jj] != 10)
+	array2_check[ii] = 10;
+    }
+  }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[:][:][:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      for (kk = 0; kk < 10; kk++) {
+	for (ll = 0; ll < 10; ll++) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	}
+      }
+    }
+  }
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj += 2) {
+      for (kk = 9; kk >= 0; kk--) {
+	for (ll = x; ll < 10; ll = ll += z) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	  else
+	    array2_check[ii] = 5;
+	}
+      }
+    }
+  }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] +
+      FourDArray[0:10:1][0:5:2][9:-10:1][x:y:z]  != 20) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj += 2) {
+      for (kk = 9; kk >= 0; kk--) {
+	for (ll = x; ll < 10; ll = ll += z) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	  else
+	    array2_check[ii] = 5;
+	}
+      }
+    }
+  }
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c
new file mode 100644
index 0000000..ed7f557
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c
@@ -0,0 +1,31 @@ 
+
+void abort (void);
+void exit  (int);
+
+
+int main(int argc, char **argv)
+{
+  int jj, kk, array_3C[10][10][10];
+  int ii,array[10], y = 0, y_int = 0, array2[10], array_3[10][10][10];
+  double x, yy, array3[10], array4[10];
+
+  array[:] = __sec_implicit_index (0);
+  array_3[:][:][:] = __sec_implicit_index (1) + __sec_implicit_index(0) +
+    __sec_implicit_index (2);
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	array_3C[ii][jj][kk] = ii+jj+kk;
+	
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
+	  abort ();
+	
+
+  exit (0);
+  
+  return 0;
+}