diff mbox

Cilk Plus merging to trunk (2 of n)

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

Commit Message

Iyer, Balaji V Sept. 23, 2012, 12:01 a.m. UTC
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_language_specification.pdf).

Here are the ChangeLog entries for the changes I have made in this patch.

gcc/ChangeLog:
2012-09-22  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.
        * gimplify.c (gimplify_expr): Added a ARRAY_NOTATION_REF case.
        * 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         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.
        * array-notation-common.c: New file.

gcc/c/ChangeLog
2012-09-22  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/c-family/ChangeLog
2012-09-22  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/testsuite/ChangeLog
2012-09-21  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: New script.
        * 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/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.


I have tested this on x86 and x86_64 and passes all the applicable regression test. Is this OK for trunk?

Thanking You,

Yours Sincerely,

Balaji V. Iyer.

Comments

Joseph Myers Sept. 23, 2012, 8:45 p.m. UTC | #1
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_language_specification.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?

(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.

* Diagnostic function calls should have explicit locations passed.

* 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.

* 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.

* There should be nothing x86-specific about the testcases so they 
shouldn't need to be conditioned on x86 targets.

* 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.

* Instead of casting the result of xmalloc, use existing macros such as 
XNEWVEC.

* Use @option not @code for option named in the manual.

* 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.

There may also be other issues.)
Richard Biener Sept. 24, 2012, 9:52 a.m. UTC | #2
On Sun, Sep 23, 2012 at 2:01 AM, Iyer, Balaji V <balaji.v.iyer@intel.com> 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_language_specification.pdf).
>
> Here are the ChangeLog entries for the changes I have made in this patch.

Just a few comments on the middle-end side:

+/* 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)

I suppose that similar to ARRAY_RANGE_REF the type of the expression
specifies the size of the result which is an array itself?  ARRAY_NOTATION_REF
is then ARRAY_RANGE_REF with stride possibly != 1.  Thus please instead
change ARRAY_RANGE_REF to contain an explicit stride.

+	case ARRAY_NOTATION_REF:
+	  /* Nothing should happen here.  We just return ALL_DONE.  */
+	  ret = GS_ALL_DONE;
+	  break;
+

I don't believe that.  You should not restrict GENERIC to put gimplfied
operands into the operand slots.  See how ARRAY_RANGE_REF is handled.
The exception may be if ARRAY_NOTATION_REF never survives until
gimplfication (and thus is not part of GENERIC but a frontend specific tree).

Richard.

> gcc/ChangeLog:
> 2012-09-22  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.
>         * gimplify.c (gimplify_expr): Added a ARRAY_NOTATION_REF case.
>         * 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         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.
>         * array-notation-common.c: New file.
>
> gcc/c/ChangeLog
> 2012-09-22  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/c-family/ChangeLog
> 2012-09-22  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/testsuite/ChangeLog
> 2012-09-21  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: New script.
>         * 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/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.
>
>
> I have tested this on x86 and x86_64 and passes all the applicable regression test. Is this OK for trunk?
>
> Thanking You,
>
> Yours Sincerely,
>
> Balaji V. Iyer.
Iyer, Balaji V Sept. 24, 2012, 3:05 p.m. UTC | #3
Hi Richard,
	Please see my comments embedded below.

>-----Original Message-----
>From: Richard Guenther [mailto:richard.guenther@gmail.com]
>Sent: Monday, September 24, 2012 5:53 AM
>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, Sep 23, 2012 at 2:01 AM, Iyer, Balaji V <balaji.v.iyer@intel.com> 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_language_specif
>ication.pdf).
>>
>> Here are the ChangeLog entries for the changes I have made in this patch.
>
>Just a few comments on the middle-end side:
>
>+/* 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)
>
>I suppose that similar to ARRAY_RANGE_REF the type of the expression specifies
>the size of the result which is an array itself?  ARRAY_NOTATION_REF is then
>ARRAY_RANGE_REF with stride possibly != 1.  Thus please instead change
>ARRAY_RANGE_REF to contain an explicit stride.

IIRC ARRAY_RANGE_REF holds the start index and the end-index with no stride. Whereas ARRAY_NOTATION_REF holds start_index, the number of elements you need to access in the array and the stride. So, they both hold different information. Converting one to another can cause some implementation and performance complexities when we have assignments  that have different stride while accessing the same number of elements.  Also, I did not see much (if any) usage of Array_range_ref in C or C++. The only place that I saw were using it were in Fortran and Ada. Adding the extra field for one thing can require modifications those front-ends. This I felt was a bit unnecessary and excessive. I am replacing the ARRAY_NOTATION_REF tree with the appropriate array_ref and a loop. Thus, having a tree that holds array  notation information made things look straightforward.

>
>+	case ARRAY_NOTATION_REF:
>+	  /* Nothing should happen here.  We just return ALL_DONE.  */
>+	  ret = GS_ALL_DONE;
>+	  break;
>+
>
>I don't believe that.  You should not restrict GENERIC to put gimplfied operands
>into the operand slots.  See how ARRAY_RANGE_REF is handled.
>The exception may be if ARRAY_NOTATION_REF never survives until gimplfication
>(and thus is not part of GENERIC but a frontend specific tree).

ARRAY_NOTATION_REF does not survive gimplifcation. It gets broken up toward the end of parsing. In hindsight, I should have done something like this:

case ARRAY_NOTATION_REF:
   gcc_unreachable ();

Thanks,

Balaji V. Iyer.

>
>Richard.
>
>> gcc/ChangeLog:
>> 2012-09-22  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.
>>         * gimplify.c (gimplify_expr): Added a ARRAY_NOTATION_REF case.
>>         * 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
>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.
>>         * array-notation-common.c: New file.
>>
>> gcc/c/ChangeLog
>> 2012-09-22  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/c-family/ChangeLog
>> 2012-09-22  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/testsuite/ChangeLog
>> 2012-09-21  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: New script.
>>         * 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/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.
>>
>>
>> I have tested this on x86 and x86_64 and passes all the applicable regression
>test. Is this OK for trunk?
>>
>> Thanking You,
>>
>> Yours Sincerely,
>>
>> Balaji V. Iyer.
Richard Biener Sept. 26, 2012, 12:15 p.m. UTC | #4
On Mon, Sep 24, 2012 at 5:05 PM, Iyer, Balaji V <balaji.v.iyer@intel.com> wrote:
> Hi Richard,
>         Please see my comments embedded below.
>
>>-----Original Message-----
>>From: Richard Guenther [mailto:richard.guenther@gmail.com]
>>Sent: Monday, September 24, 2012 5:53 AM
>>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, Sep 23, 2012 at 2:01 AM, Iyer, Balaji V <balaji.v.iyer@intel.com> 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_language_specif
>>ication.pdf).
>>>
>>> Here are the ChangeLog entries for the changes I have made in this patch.
>>
>>Just a few comments on the middle-end side:
>>
>>+/* 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)
>>
>>I suppose that similar to ARRAY_RANGE_REF the type of the expression specifies
>>the size of the result which is an array itself?  ARRAY_NOTATION_REF is then
>>ARRAY_RANGE_REF with stride possibly != 1.  Thus please instead change
>>ARRAY_RANGE_REF to contain an explicit stride.
>
> IIRC ARRAY_RANGE_REF holds the start index and the end-index with no stride. Whereas ARRAY_NOTATION_REF holds start_index, the number of elements you need to access in the array and the stride. So, they both hold different information. Converting one to another can cause some implementation and performance complexities when we have assignments  that have different stride while accessing the same number of elements.  Also, I did not see much (if any) usage of Array_range_ref in C or C++. The only place that I saw were using it were in Fortran and Ada. Adding the extra field for one thing can require modifications those front-ends. This I felt was a bit unnecessary and excessive. I am replacing the ARRAY_NOTATION_REF tree with the appropriate array_ref and a loop. Thus, having a tree that holds array  notation information made things look straightforward.
>
>>
>>+      case ARRAY_NOTATION_REF:
>>+        /* Nothing should happen here.  We just return ALL_DONE.  */
>>+        ret = GS_ALL_DONE;
>>+        break;
>>+
>>
>>I don't believe that.  You should not restrict GENERIC to put gimplfied operands
>>into the operand slots.  See how ARRAY_RANGE_REF is handled.
>>The exception may be if ARRAY_NOTATION_REF never survives until gimplfication
>>(and thus is not part of GENERIC but a frontend specific tree).
>
> ARRAY_NOTATION_REF does not survive gimplifcation. It gets broken up toward the end of parsing. In hindsight, I should have done something like this:
>
> case ARRAY_NOTATION_REF:
>    gcc_unreachable ();

You should instead add ARRAY_NOTATION_REF to c-family/c-common.def
as C-family specific tree code then.

Richard.

> Thanks,
>
> Balaji V. Iyer.
>
>>
>>Richard.
>>
>>> gcc/ChangeLog:
>>> 2012-09-22  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.
>>>         * gimplify.c (gimplify_expr): Added a ARRAY_NOTATION_REF case.
>>>         * 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
>>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.
>>>         * array-notation-common.c: New file.
>>>
>>> gcc/c/ChangeLog
>>> 2012-09-22  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/c-family/ChangeLog
>>> 2012-09-22  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/testsuite/ChangeLog
>>> 2012-09-21  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: New script.
>>>         * 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/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.
>>>
>>>
>>> I have tested this on x86 and x86_64 and passes all the applicable regression
>>test. Is this OK for trunk?
>>>
>>> Thanking You,
>>>
>>> Yours Sincerely,
>>>
>>> Balaji V. Iyer.
Iyer, Balaji V Sept. 26, 2012, 1:48 p.m. UTC | #5
>-----Original Message-----
>From: Richard Guenther [mailto:richard.guenther@gmail.com]
>Sent: Wednesday, September 26, 2012 8:16 AM
>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 Mon, Sep 24, 2012 at 5:05 PM, Iyer, Balaji V <balaji.v.iyer@intel.com> wrote:
>> Hi Richard,
>>         Please see my comments embedded below.
>>
>>>-----Original Message-----
>>>From: Richard Guenther [mailto:richard.guenther@gmail.com]
>>>Sent: Monday, September 24, 2012 5:53 AM
>>>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, Sep 23, 2012 at 2:01 AM, Iyer, Balaji V <balaji.v.iyer@intel.com>
>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_langu
>>>age_specif
>>>ication.pdf).
>>>>
>>>> Here are the ChangeLog entries for the changes I have made in this patch.
>>>
>>>Just a few comments on the middle-end side:
>>>
>>>+/* 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)
>>>
>>>I suppose that similar to ARRAY_RANGE_REF the type of the expression
>>>specifies the size of the result which is an array itself?
>>>ARRAY_NOTATION_REF is then ARRAY_RANGE_REF with stride possibly != 1.
>>>Thus please instead change ARRAY_RANGE_REF to contain an explicit stride.
>>
>> IIRC ARRAY_RANGE_REF holds the start index and the end-index with no stride.
>Whereas ARRAY_NOTATION_REF holds start_index, the number of elements you
>need to access in the array and the stride. So, they both hold different
>information. Converting one to another can cause some implementation and
>performance complexities when we have assignments  that have different stride
>while accessing the same number of elements.  Also, I did not see much (if any)
>usage of Array_range_ref in C or C++. The only place that I saw were using it
>were in Fortran and Ada. Adding the extra field for one thing can require
>modifications those front-ends. This I felt was a bit unnecessary and excessive. I
>am replacing the ARRAY_NOTATION_REF tree with the appropriate array_ref and
>a loop. Thus, having a tree that holds array  notation information made things
>look straightforward.
>>
>>>
>>>+      case ARRAY_NOTATION_REF:
>>>+        /* Nothing should happen here.  We just return ALL_DONE.  */
>>>+        ret = GS_ALL_DONE;
>>>+        break;
>>>+
>>>
>>>I don't believe that.  You should not restrict GENERIC to put
>>>gimplfied operands into the operand slots.  See how ARRAY_RANGE_REF is
>handled.
>>>The exception may be if ARRAY_NOTATION_REF never survives until
>>>gimplfication (and thus is not part of GENERIC but a frontend specific tree).
>>
>> ARRAY_NOTATION_REF does not survive gimplifcation. It gets broken up
>toward the end of parsing. In hindsight, I should have done something like this:
>>
>> case ARRAY_NOTATION_REF:
>>    gcc_unreachable ();
>
>You should instead add ARRAY_NOTATION_REF to c-family/c-common.def as C-
>family specific tree code then.

I actually took out the ARRAY_NOTATION_REF case from gimplify_expr (will send out the fixed patch soon). And, I can do what you suggested. But the reason why I put it as a common tree is because if someone in future wants to implement array notations for other languages, they can do so without much difficulty.

If I did put the tree in c-common.def, where do I document the tree node (Or do I even need to document it)? I tried grepping the existing tree names (in c-common.def) in the doc directory and I don't see any hits.

Thanks,

Balaji V. Iyer.

>
>Richard.
>
>> Thanks,
>>
>> Balaji V. Iyer.
>>
>>>
>>>Richard.
>>>
>>>> gcc/ChangeLog:
>>>> 2012-09-22  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.
>>>>         * gimplify.c (gimplify_expr): Added a ARRAY_NOTATION_REF case.
>>>>         * 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
>>>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.
>>>>         * array-notation-common.c: New file.
>>>>
>>>> gcc/c/ChangeLog
>>>> 2012-09-22  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/c-family/ChangeLog
>>>> 2012-09-22  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/testsuite/ChangeLog
>>>> 2012-09-21  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: New script.
>>>>         * 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/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.
>>>>
>>>>
>>>> I have tested this on x86 and x86_64 and passes all the applicable
>>>> regression
>>>test. Is this OK for trunk?
>>>>
>>>> Thanking You,
>>>>
>>>> Yours Sincerely,
>>>>
>>>> Balaji V. Iyer.
diff mbox

Patch

Index: gcc/doc/generic.texi
===================================================================
--- gcc/doc/generic.texi	(revision 191645)
+++ gcc/doc/generic.texi	(working copy)
@@ -1124,6 +1124,7 @@ 
 @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 @@ 
 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 @code{-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
Index: gcc/doc/passes.texi
===================================================================
--- gcc/doc/passes.texi	(revision 191645)
+++ gcc/doc/passes.texi	(working copy)
@@ -19,6 +19,7 @@ 
 
 @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 @@ 
 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 is provided in 
+@w{@uref{http://www.cilk.com/}}.  It is worth mentioning that the current 
+implementation follows ABI and SPEC version 0.9.
+
 @node Gimplification pass
 @section Gimplification pass
 
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 191645)
+++ gcc/doc/invoke.texi	(working copy)
@@ -1773,6 +1773,17 @@ 
 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 and SPEC 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
Index: gcc/array-notation-common.c
===================================================================
--- gcc/array-notation-common.c	(revision 0)
+++ gcc/array-notation-common.c	(revision 0)
@@ -0,0 +1,183 @@ 
+/* 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 "expr.h"
+#include "recog.h"
+#include "tree-iterator.h"
+#include "diagnostic-core.h"
+
+int extract_sec_implicit_index_arg (tree);
+bool is_sec_implicit_index_fn (tree);
+void array_notation_init_builtins (void);
+
+/* This function indicates that certain functions are unlikely to 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);
+  return;
+}
+
+/* This function returns true if the function call 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;
+}
+
+/* This function will extract arguments for sec_implicit index function.  */
+
+int
+extract_sec_implicit_index_arg (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
+	{
+	  error ("__sec_implicit_index parameter must be constant integer "
+		 "expression");
+	  error ("Bailing out due to previous error");
+	  exit (ICE_EXIT_CODE);
+	}
+    }
+  return return_int;
+}
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 191645)
+++ gcc/c-family/c.opt	(working copy)
@@ -759,6 +759,10 @@ 
 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
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 191645)
+++ gcc/c-family/c-common.c	(working copy)
@@ -5014,6 +5014,9 @@ 
 #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 ();
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 191645)
+++ gcc/c-family/c-common.h	(working copy)
@@ -543,6 +543,9 @@ 
 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 void array_notation_init_builtins (void);
 extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int field_decl_cmp (const void *, const void *);
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 191645)
+++ gcc/c/c-parser.c	(working copy)
@@ -57,6 +57,13 @@ 
 #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 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 @@ 
     }
   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 @@ 
   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 @@ 
   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 @@ 
   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_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 @@ 
 	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 @@ 
 	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,99 @@ 
   the_parser = NULL;
 }
 
+/* This function parses Cilk Plus array notation.  */
+
+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"
Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c	(revision 191645)
+++ gcc/c/c-typeck.c	(working copy)
@@ -112,6 +112,8 @@ 
 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 @@ 
       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 @@ 
 
   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 @@ 
   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,6 +5675,10 @@ 
 	 or one that results from arithmetic, even including
 	 a cast to integer type.  */
       if (!null_pointer_constant)
+	{
+	  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"),
@@ -5663,7 +5688,7 @@ 
 				"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)
Index: gcc/c/Make-lang.in
===================================================================
--- gcc/c/Make-lang.in	(revision 191645)
+++ gcc/c/Make-lang.in	(working copy)
@@ -58,7 +58,7 @@ 
 # 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 @@ 
 	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
+
Index: gcc/c/c-array-notation.c
===================================================================
--- gcc/c/c-array-notation.c	(revision 0)
+++ gcc/c/c-array-notation.c	(revision 0)
@@ -0,0 +1,2367 @@ 
+/* 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"
+
+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);
+extern bool is_sec_implicit_index_fn (tree);
+extern int extract_sec_implicit_index_arg (tree fn);
+tree expand_array_notation_exprs (tree t);
+
+/* This function is to find the rank of an array notation expression.  
+   For example, an array notation of A[:][:] has 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;
+}
+
+/* This function will go through a tree and extract all the array notation 
+   expressions inside the subtrees.  */
+
+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 =
+	(tree *) xrealloc (*array_list, (ii + 1) * sizeof (tree));
+      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 = (tree *) xrealloc (*array_list, (ii + 1) *
+						  sizeof (tree));
+	      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 = (tree *) xrealloc (*array_list, (ii + 1) *
+					      sizeof (tree));
+	  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;
+}
+
+/* This function will replace a subtree that has array notation with the 
+   appropriate scalar equivalent.  */
+
+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;
+}
+
+/* This function will return an array notation expression.  */
+
+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)
+	    {
+	      add_stmt (builtin_loop);
+	      found_builtin_fn = true;
+	      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)
+    {
+      error_at (location, "Left Hand-side rank cannot be scalar when "
+		"right-hand side is not");
+      return error_mark_node;
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      error_at (location, "Rank-mismatch");
+      return error_mark_node;
+    }
+  
+  lhs_vector = (bool **) xmalloc (sizeof (bool *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = (bool *) xmalloc (sizeof (bool) * lhs_rank);
+  
+  rhs_vector = (bool **) xmalloc (sizeof (bool *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = (bool *) xmalloc (sizeof (bool) * rhs_rank);
+  
+  lhs_array = (tree **) xmalloc (sizeof (tree *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  
+  rhs_array = (tree **) xmalloc (sizeof (tree *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_value = (tree **) xmalloc (sizeof (tree *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  
+  rhs_value = (tree **) xmalloc (sizeof (tree *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_stride = (tree **) xmalloc (sizeof (tree *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = (tree *) xmalloc (sizeof (tree *) * lhs_rank);
+  
+  rhs_stride = (tree **) xmalloc (sizeof (tree *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_length = (tree **) xmalloc (sizeof (tree *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  
+  rhs_length = (tree **) xmalloc (sizeof (tree *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+  
+  lhs_start = (tree **) xmalloc (sizeof (tree *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  
+  rhs_start = (tree **) xmalloc (sizeof (tree *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_var = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  rhs_var = (tree *) xmalloc (sizeof (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 = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+  exit_label = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+  cond_expr = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * MAX (lhs_rank, rhs_rank));
+
+  lhs_expr_incr = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  rhs_expr_incr = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_ind_init = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  rhs_ind_init = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  lhs_count_down = (bool **) xmalloc (sizeof (bool *) * lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] = (bool *) xmalloc (sizeof (bool) * lhs_rank);
+  
+  rhs_count_down = (bool **) xmalloc (sizeof (bool *) * rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = (bool *) xmalloc (sizeof (bool) * rhs_rank);
+
+  lhs_compare = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  rhs_compare = (tree *) xmalloc (sizeof (tree) * rhs_rank);
+
+  rhs_array_operand = (tree *) xmalloc (sizeof (tree) * rhs_list_size);
+  lhs_array_operand = (tree *) xmalloc (sizeof (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;
+	    }
+	}
+    }
+
+
+
+  for (ii = 0; ii < lhs_rank; ii++)
+    {
+      if (lhs_vector[0][ii])
+	{
+	  lhs_var[ii] = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				    integer_type_node);
+	  lhs_ind_init[ii] = build_modify_expr
+	    (UNKNOWN_LOCATION, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
+	     NOP_EXPR,
+	     UNKNOWN_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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				integer_type_node);
+      rhs_ind_init[ii] = build_modify_expr
+	(UNKNOWN_LOCATION, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
+	 modifycode,
+	 UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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
+			(UNKNOWN_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
+		      (UNKNOWN_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 (rhs_list[ii]);
+		    if (idx_value < lhs_rank && idx_value >= 0)
+		      rhs_array_operand[ii] = lhs_var[idx_value];
+		    else
+		      {
+			error ("__sec_implicit_index parameter must be less "
+			       " than the rank of the Left Hand Side expr. ");
+			error ("Bailing out due to the previous error.");
+			exit (ICE_EXIT_CODE);
+		      }
+		  }  
+	    }
+	}
+      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 (rhs_list[ii]);
+		    if (idx_value < lhs_rank && idx_value >= 0)
+		      rhs_array_operand[ii] = lhs_var[idx_value];
+		    else
+		      {
+			error ("__sec_implicit_index parameter must be less "
+			       " than the rank of the Left Hand Side expr. ");
+			error ("Bailing out due to the previous error.");
+			exit (ICE_EXIT_CODE);
+		      }
+		  }  
+	    }
+	}
+      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])
+	{
+	  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]);
+
+
+	  /* 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[0][jj])
+	      rhs_compare[jj] = build2
+		(LT_EXPR, boolean_type_node, rhs_var[jj],
+		 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]), rhs_length[0][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[0][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;
+}
+
+/* This function will fix array notation exprs. in conditional statements.  */
+
+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;
+
+  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;
+
+  array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+      array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_start[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+    }
+
+  body_label = (tree *) xmalloc (sizeof (tree) * rank);
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+  ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+  
+  array_var = (tree *) xmalloc (sizeof (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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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
+		    (UNKNOWN_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
+		    (UNKNOWN_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);
+
+  free (body_label);
+  free (body_label_expr);
+  free (exit_label);
+  free (exit_label_expr);
+  free (compare_expr);
+  free (if_stmt_label);
+  free (expr_incr);
+  free (ind_init);
+  free (array_operand);
+  free (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      free (count_down[ii]);
+      free (array_value[ii]);
+      free (array_stride[ii]);
+      free (array_length[ii]);
+      free (array_start[ii]);
+      free (array_ops[ii]);
+      free (array_vector[ii]);
+    }
+
+  free (count_down);
+  free (array_value);
+  free (array_stride);
+  free (array_length);
+  free (array_start);
+  free (array_ops);
+  free (array_vector);
+
+  return loop;
+}
+
+/* This function is entry function to fix conditional array notation exprs.  */
+
+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);
+}
+
+/* This function will fix the array notation expression, mainly in unary
+   expression.  */
+
+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 = (tree **) xmalloc (sizeof (tree *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+      array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_start[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+    }
+
+  body_label = (tree *) xmalloc (sizeof (tree) * rank);
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+  ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+  array_var = (tree *) xmalloc (sizeof (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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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
+		    (UNKNOWN_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
+		    (UNKNOWN_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);
+
+  free (body_label);
+  free (body_label_expr);
+  free (exit_label);
+  free (exit_label_expr);
+  free (compare_expr);
+  free (if_stmt_label);
+  free (expr_incr);
+  free (ind_init);
+  free (array_operand);
+  free (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      free (count_down[ii]);
+      free (array_value[ii]);
+      free (array_stride[ii]);
+      free (array_length[ii]);
+      free (array_start[ii]);
+      free (array_ops[ii]);
+      free (array_vector[ii]);
+    }
+
+  free (count_down);
+  free (array_value);
+  free (array_stride);
+  free (array_length);
+  free (array_start);
+  free (array_ops);
+  free (array_vector);
+
+  arg.value = loop;
+  return arg;
+}
+
+/* This function will fix array notations inside function parameters.  */
+
+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, 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;
+  
+  if (!is_builtin_array_notation_fn (CALL_EXPR_FN (an_builtin_fn), &an_type))
+    return NULL_TREE;
+
+  if (an_type != REDUCE_CUSTOM)
+    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  else
+    {
+      call_fn = CALL_EXPR_ARG (an_builtin_fn, 0);
+      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, 1);
+      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, 2);
+    }
+  
+  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);
+  if (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+	   && (an_type == REDUCE_MAX_INDEX  || an_type == REDUCE_MIN_INDEX))
+    { 
+      error ("__sec_reduce_min_ind or __sec_reduce_max_ind cannot have arrays"
+	     " with dimension greater than 1.");
+      fnotice (stderr, "confused by earlier errors, bailing out\n"); 
+      exit (ICE_EXIT_CODE);
+    }
+  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;
+    default:
+      gcc_unreachable ();  /* You should not reach here.  */
+    }
+   
+  
+  array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+      array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_start[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+    }
+
+  body_label = (tree *) xmalloc (sizeof (tree) * rank);
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+  ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+  
+  array_var = (tree *) xmalloc (sizeof (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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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
+		    (UNKNOWN_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
+		    (UNKNOWN_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]);
+	}
+    }
+
+  *new_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, new_var_type);
+  gcc_assert (*new_var);
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    array_ind_value = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, 
+				  TREE_TYPE (func_parm));
+			      
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_MUL:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_ALL_ZEROS:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_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
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_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
+	(UNKNOWN_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
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_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
+	(UNKNOWN_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:
+      if (!call_fn)
+	{
+	  error ("Unknown/Invalid function!");
+	  exit (ICE_EXIT_CODE);
+	}
+      if (!identity_value)
+	{
+	  error ("Invalid Identity Value!");
+	  exit (ICE_EXIT_CODE);
+	}
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, identity_value, new_var_type);
+
+      new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
+      new_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, new_call_expr, TREE_TYPE (*new_var));
+      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);
+  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);
+    }
+
+  free (body_label);
+  free (body_label_expr);
+  free (exit_label);
+  free (exit_label_expr);
+  free (compare_expr);
+  free (if_stmt_label);
+  free (expr_incr);
+  free (ind_init);
+  free (array_operand);
+  free (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      free (count_down[ii]);
+      free (array_value[ii]);
+      free (array_stride[ii]);
+      free (array_length[ii]);
+      free (array_start[ii]);
+      free (array_ops[ii]);
+      free (array_vector[ii]);
+    }
+
+  free (count_down);
+  free (array_value);
+  free (array_stride);
+  free (array_length);
+  free (array_start);
+  free (array_ops);
+  free (array_vector);
+  
+  return loop;
+}
+
+/* This will check if function is a builtin array notation function.  */
+
+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
+    {
+      *type = REDUCE_UNKNOWN;
+      return false;
+    }
+  return false;
+}
+
+/* This function returns true if the tree/subtrees have array notations.  */
+
+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;
+}
+
+/* this function fixes up array notation exprs inside void function calls.  */
+
+static tree
+fix_array_notation_call_expr (tree 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, 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;
+
+  array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+      array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_start[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+    }
+
+  body_label = (tree *) xmalloc (sizeof (tree) * rank);
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+  ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+  
+  array_var = (tree *) xmalloc (sizeof (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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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 (UNKNOWN_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
+		    (UNKNOWN_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
+		    (UNKNOWN_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);
+
+  free (body_label);
+  free (body_label_expr);
+  free (exit_label);
+  free (exit_label_expr);
+  free (compare_expr);
+  free (if_stmt_label);
+  free (expr_incr);
+  free (ind_init);
+  free (array_operand);
+  free (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      free (count_down[ii]);
+      free (array_value[ii]);
+      free (array_stride[ii]);
+      free (array_length[ii]);
+      free (array_start[ii]);
+      free (array_ops[ii]);
+      free (array_vector[ii]);
+    }
+
+  free (count_down);
+  free (array_value);
+  free (array_stride);
+  free (array_length);
+  free (array_start);
+  free (array_ops);
+  free (array_vector);
+
+  arg = loop;
+  return arg;
+}
+
+/* This function will walk through a tree and find all call statements that 
+   do not return anything and fix up any array notations they might 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;
+}
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 191645)
+++ gcc/tree.h	(working copy)
@@ -44,6 +44,24 @@ 
 MAX_TREE_CODES
 };
 
+/* 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
+} an_reduce_type;
+
+
 #undef DEFTREECODE
 #undef END_OF_BASE_TREE_CODES
 
@@ -6504,4 +6522,18 @@ 
 	  && builtin_info.implicit_p[uns_fncode]);
 }
 
+/* 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)
+
 #endif  /* GCC_TREE_H  */
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp	(revision 0)
@@ -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/>.
+
+# This file was written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+# Many thanks to the GCC C-torture contributors.
+
+if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
+      return
+}
+
+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
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp	(revision 0)
@@ -0,0 +1,33 @@ 
+#   Copyright (C) 1997, 2000, 2007 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>
+
+if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
+      return
+}
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/compile/*.c]] " -O3 -ftree-vectorize -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/compile/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
+
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c	(revision 0)
@@ -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;
+}
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 191645)
+++ gcc/gimplify.c	(working copy)
@@ -7626,6 +7626,11 @@ 
 	  ret = gimplify_omp_atomic (expr_p, pre_p);
 	  break;
 
+	case ARRAY_NOTATION_REF:
+	  /* Nothing should happen here.  We just return ALL_DONE.  */
+	  ret = GS_ALL_DONE;
+	  break;
+
 	case TRANSACTION_EXPR:
 	  ret = gimplify_transaction (expr_p, pre_p);
 	  break;
Index: gcc/tree.def
===================================================================
--- gcc/tree.def	(revision 191645)
+++ gcc/tree.def	(working copy)
@@ -412,6 +412,14 @@ 
    of the range is taken from the type of the expression.  */
 DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", tcc_reference, 4)
 
+/* 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)
+
 /* Used only on an operand of complex type, these return
    a value of the corresponding component type.  */
 DEFTREECODE (REALPART_EXPR, "realpart_expr", tcc_reference, 1)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 191645)
+++ gcc/Makefile.in	(working copy)
@@ -1138,6 +1138,7 @@ 
 	$(GGC) \
 	alias.o \
 	alloc-pool.o \
+	array-notation-common.o \
 	auto-inc-dec.o \
 	bb-reorder.o \
 	bitmap.o \
@@ -3334,6 +3335,8 @@ 
    insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) $(OBSTACK_H) $(BITMAP_H) \
    $(EXPR_H) $(EXCEPT_H) $(REGS_H) $(TREE_PASS_H) $(DF_H) dce.h \
    lower-subreg.h
+array-notation-common.o: array-notation-common.c $(CONFIG_H) $(SYSTEM_H) \
+   $(TREE_H) $(RTL_H) $(OPTABS_H) $(GIMPLE_H) $(RECOG_H)
 target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) insn-config.h $(MACHMODE_H) $(GGC_H) toplev.h target-globals.h \
    $(FLAGS_H) $(REGS_H) $(RTL_H) reload.h expmed.h $(EXPR_H) $(OPTABS_H) \