[patch] cilkplus array notation for C (clean, independent patchset, take 1)

Aldy Hernandez aldyh@redhat.com
Wed Mar 20 15:32:00 GMT 2013


Hi Joseph.  Hi folks.

Attached is a patch implementing the array notation part of the cilkplus 
implementation.  This patch is against trunk, and is independent of 
anything else (cilkplus or otherwise).

This is the patch as it currently resides in the cilkplus-merge branch 
as discussed earlier on the gcc list (also, see 
http://gcc.gnu.org/wiki/cilkplus-merge), and is against trunk as of 
right before the outtage.

It is a followup to the patchset Joseph previously started reviewing, 
that according to Balaji, has all the requested requests applied.

I have found some little nits that I will point out in a reply to this 
message.

Joseph, folks, et al... How does this look?

Thanks.
-------------- next part --------------
gcc/
	* doc/passes.texi (Passes): Added documentation about changes done
	for Cilk Plus.
	* doc/invoke.texi (C Dialect Options): Added documentation about
	the -fcilkplus flag.
	* doc/generic.texi (Storage References): Added documentation for
	ARRAY_NOTATION_REF storage.
	* Makefile.in (C_COMMON_OBJS): Added
	c-family/array-notation-common.o.
gcc/c-family/
	* c-common.c (c_define_builtins): When cilkplus is enabled, the
	function array_notation_init_builtins() is called.
	(c_common_init_ts): Added ARRAY_NOTATION_REF as typed.
	* c-common.def (ARRAY_NOTATION_REF): New tree.
	* c-common.h (build_array_notation_expr): New function declaration.
	(build_array_notation_ref): Likewise.
	(extract_sec_implicit_index_arg): New extern declaration.
	(is_sec_implicit_index_fn): Likewise.
	(array_notation_init_builtins): Likewise.
	(ARRAY_NOTATION_CHECK): New define.
	(ARRAY_NOTATION_ARRAY): Likewise.
	(ARRAY_NOTATION_START): Likewise.
	(ARRAY_NOTATION_LENGTH): Likewise.
	(ARRAY_NOTATION_STRIDE): Likewise.
	(ARRAY_NOTATION_TYPE): Likewise.
	(array_notation_reduce_type): New enumerator.
	* c-pretty-print.c (pp_c_postifix_expression): Added a new case for
	ARRAY_NOTATION_REF.
	* c.opt (flag_enable_cilkplus): New flag.
	* array-notation-common.c: New file.
gcc/c/
	* c-typeck.c (build_array_ref): Added a check to see if array's
	index is greater than one.  If true, then emit an error.
	(build_function_call_vec): Exclude error reporting and checking
	for builtin array-notation functions.
	(convert_arguments): Likewise.
	(c_finish_return): Added a check for array notations as a return
	expression.  If true, then emit an error.
	(c_finish_loop): Added a check for array notations in a loop
	condition.  If true then emit an error.
	(lvalue_p): Added a ARRAY_NOTATION_REF case.
	(build_binary_op): Added a check for array notation expr inside
	op1 and op0.  If present, we call another function to find correct
	type.
	* Make-lang.in (C_AND_OBJC_OBJS): Added c-array-notation.o.
	* c-parser.c (c_parser_compound_statement): Check if array
	notation code is used in tree, if so, then transform them into
	appropriate C code.
	(c_parser_expr_no_commas): Check if array notation is used in LHS
	or RHS, if so, then build array notation expression instead of
	regular modify.
	(c_parser_postfix_expression_after_primary): Added a check for
	colon(s) after square braces, if so then handle it like an array
	notation.  Also, break up array notations in unary op if found.
	(c_parser_direct_declarator_inner): Added a check for array
	notation.
	(c_parser_compound_statement): Added a check for array notation in
	a stmt.  If one is present, then expand array notation expr.
	(c_parser_if_statement): Likewise.
	(c_parser_switch_statement): Added a check for array notations in
	a switch statement's condition.  If true, then output an error.
	(c_parser_while_statement): Similarly, but for a while.
	(c_parser_do_statement): Similarly, but for a do-while.
	(c_parser_for_statement): Similarly, but for a for-loop.
	(c_parser_unary_expression): Check if array notation is used in a
	pre-increment or pre-decrement expression.  If true, then expand
	them.
	(c_parser_array_notation): New function.
	* c-array-notation.c: New file.
gcc/testsuite/
	* gcc.dg/cilk-plus/array_notation: New directory and supporting
	infrastructure.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 54ea04f..11ef491 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1137,7 +1137,8 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
-  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o
+  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
+  c-family/array-notation-common.o
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -2001,6 +2002,9 @@ c-family/c-semantics.o : c-family/c-semantics.c $(CONFIG_H) $(SYSTEM_H) \
 c-family/c-ada-spec.o : c-family/c-ada-spec.c c-family/c-ada-spec.h \
 	$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPP_ID_DATA_H) $(TM_H) \
 	coretypes.h tree-iterator.h dumpfile.h
+  
+c-family/array-notation-common.o : c-family/array-notation-common.c $(TREE_H) \
+	$(SYSTEM_H) $(TREE_H) coretypes.h tree-iterator.h $(DIAGNOSTIC_CORE_H)
 
 c-family/stub-objc.o : c-family/stub-objc.c $(CONFIG_H) $(SYSTEM_H) \
 	coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-objc.h
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
new file mode 100644
index 0000000..7089c8e
--- /dev/null
+++ b/gcc/c-family/array-notation-common.c
@@ -0,0 +1,193 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains the builtin functions for Array
+   notations.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h" 
+#include "coretypes.h"
+#include "tree.h"
+#include "langhooks.h" 
+#include "tree-iterator.h"
+#include "diagnostic-core.h"
+
+int extract_sec_implicit_index_arg (location_t, tree);
+bool is_sec_implicit_index_fn (tree);
+void array_notation_init_builtins (void);
+
+/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is
+   not run as is.  */
+
+static void
+mark_cold (tree fndecl)
+{
+  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
+					DECL_ATTRIBUTES (fndecl));
+}
+
+/* This function inititializes array notation specific builtin information.  */
+
+
+void
+array_notation_init_builtins (void)
+{
+  tree func_type = NULL_TREE;
+  tree new_func = NULL_TREE;
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_add", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_mul", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_all_zero", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_any_zero", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_max", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+  
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_min", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_min_ind", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_max_ind", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+				       NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_any_nonzero", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_all_nonzero", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+  
+  func_type = build_function_type_list (integer_type_node, integer_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_implicit_index", func_type);
+  mark_cold (new_func);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (integer_type_node, ptr_type_node,
+					ptr_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce", func_type);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+
+  func_type = build_function_type_list (ptr_type_node, ptr_type_node,
+					ptr_type_node, ptr_type_node,
+					NULL_TREE);
+  new_func = build_fn_decl ("__sec_reduce_mutating", func_type);
+  new_func = lang_hooks.decls.pushdecl (new_func);
+  return;
+}
+
+/* Returns true if the function call specified in FUNC_NAME is
+   __sec_implicit_index.  */
+
+bool
+is_sec_implicit_index_fn (tree func_name)
+{
+  const char *function_name = NULL;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == FUNCTION_DECL)
+    func_name = DECL_NAME (func_name);
+  
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (func_name);
+  else if (TREE_CODE (func_name) == ADDR_EXPR)
+    {
+      func_name = TREE_OPERAND (func_name, 0);
+      if (TREE_CODE (func_name) == FUNCTION_DECL)
+	if (DECL_NAME (func_name))
+	  function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+    }
+
+  if (!function_name)
+    return false;
+  else if (!strcmp (function_name, "__sec_implicit_index"))
+    return true;
+  else
+    return false;
+}
+
+/* Returns the first and only argument for FN, which should be a
+   sec_implicit_index function.  FN's location in the source file is is 
+   indicated by LOCATION.  */
+
+int
+extract_sec_implicit_index_arg (location_t location, tree fn)
+{
+  tree fn_arg;
+  HOST_WIDE_INT return_int = 0;
+  if (!fn)
+    return -1;
+
+  if (TREE_CODE (fn) == CALL_EXPR)
+    {
+      fn_arg = CALL_EXPR_ARG (fn, 0);
+      if (really_constant_p (fn_arg))
+	return_int = (int) int_cst_value (fn_arg);
+      else
+	{
+	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
+	    location = EXPR_LOCATION (fn);
+	  error_at (location, "__sec_implicit_index parameter must be a " 
+		    "constant integer expression");
+	  return -1;
+	}
+    }
+  return return_int;
+}
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c7cdd0f..e818bf3 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5163,6 +5163,9 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
 #include "builtins.def"
 #undef DEF_BUILTIN
 
+  /* Initialize builtin functions for Cilk Plus.  */
+  if (flag_enable_cilkplus)
+    array_notation_init_builtins ();
   targetm.init_builtins ();
 
   build_common_builtin_nodes ();
@@ -11428,6 +11431,7 @@ c_common_init_ts (void)
 {
   MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
   MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
+  MARK_TS_TYPED (ARRAY_NOTATION_REF);
 }
 
 /* Build a user-defined numeric literal out of an integer constant type VALUE
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index 13113af..a5e3220 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -55,6 +55,14 @@ DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
    or for the purpose of -Wsizeof-pointer-memaccess warning.  */
 DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1)
 
+/* Array Notation expression.
+   Operand 0 is the array; operand 1 is the starting array index
+   Operand 2 contains the number of elements you need to access.
+   Operand 3 is the stride.
+   Operand 4 is the element size measured in units of alignments of
+   element type. */
+DEFTREECODE (ARRAY_NOTATION_REF, "array_notation_ref", tcc_reference, 5) 
+
 /*
 Local variables:
 mode:c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4014651..1726a4b 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -538,6 +538,10 @@ extern tree pushdecl_top_level (tree);
 extern tree pushdecl (tree);
 extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 			       location_t, tree, tree);
+extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
+				       location_t, tree, tree);
+extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree);
+extern void find_rank (tree, bool, size_t *);
 extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int field_decl_cmp (const void *, const void *);
@@ -1133,4 +1137,41 @@ enum stv_conv {
 extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
 				       tree op0, tree op1, bool);
 
+/* These #defines allow users to access different operands of the 
+      array notation tree.  */
+
+#define ARRAY_NOTATION_CHECK(NODE) TREE_CHECK (NODE, ARRAY_NOTATION_REF)
+#define ARRAY_NOTATION_ARRAY(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 0)
+#define ARRAY_NOTATION_START(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 1)
+#define ARRAY_NOTATION_LENGTH(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 2)
+#define ARRAY_NOTATION_STRIDE(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 3)
+#define ARRAY_NOTATION_TYPE(NODE) \
+  TREE_OPERAND (ARRAY_NOTATION_CHECK (NODE), 4)
+
+/* Holds to type of the reduction functions used in Array notations, that is
+   part of the Cilk Plus language extensions.  */
+typedef enum array_notation_reduce_type {
+  REDUCE_UNKNOWN = 0,
+  REDUCE_ADD,
+  REDUCE_MUL,
+  REDUCE_ALL_ZEROS,
+  REDUCE_ALL_NONZEROS,
+  REDUCE_ANY_ZEROS,
+  REDUCE_ANY_NONZEROS,
+  REDUCE_MAX,
+  REDUCE_MIN,
+  REDUCE_MAX_INDEX,
+  REDUCE_MIN_INDEX,
+  REDUCE_CUSTOM,
+  REDUCE_MUTATING
+} an_reduce_type;
+
+extern int extract_sec_implicit_index_arg (location_t, tree);
+extern bool is_sec_implicit_index_fn (tree);
+extern void array_notation_init_builtins (void);
+
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 13dd613..30c8e80 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1476,6 +1476,17 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
       pp_c_right_bracket (pp);
       break;
 
+    case ARRAY_NOTATION_REF:
+      pp_postfix_expression (pp, ARRAY_NOTATION_ARRAY (e));
+      pp_c_left_bracket (pp);
+      pp_postfix_expression (pp, ARRAY_NOTATION_START (e));
+      pp_colon (pp);
+      pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e));
+      pp_colon (pp);
+      pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e));
+      pp_c_right_bracket (pp);
+      break;
+      
     case CALL_EXPR:
       {
 	call_expr_arg_iterator iter;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 10ae84d..b0057a4 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -843,6 +843,10 @@ fcanonical-system-headers
 C ObjC C++ ObjC++
 Where shorter, use canonicalized paths to systems headers.
 
+fcilkplus
+C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilkplus) Init(0)
+Enable Cilk Plus
+
 fcheck-new
 C++ ObjC++ Var(flag_check_new)
 Check the return value of new
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 8310e0a..4cc5fe3 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -56,7 +56,7 @@ c/gccspec.o: c/gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
 # Language-specific object files for C and Objective C.
 C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
   c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
-  $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+  c/c-array-notation.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
 
 # Language-specific object files for C.
 C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
@@ -192,3 +192,8 @@ c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_
 	langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
 	c-family/c-objc.h c-family/c-common.h
 
+c/c-array-notation.o: c/c-array-notation.c c/c-lang.h $(CONFIG_H) \
+	$(SYSTEM_H) coretypes.h $(TREE_H) $(C_TREE_H) $(TARGET_H) \
+	intl.h output.h $(EXPR_H) langhooks.h tree-iterator.h $(BITMAP_H) \
+	$(GIMPLE_H) c-family/c-objc.h
+
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
new file mode 100644
index 0000000..a3e754a
--- /dev/null
+++ b/gcc/c/c-array-notation.c
@@ -0,0 +1,2750 @@
+/* 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) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "tree-iterator.h"
+#include "opts.h"
+#include "gcc.h"
+#include "c-family/c-common.h"
+
+void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
+			      vec<tree, va_gc> *);
+void find_rank (tree, bool, size_t *);
+void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
+tree fix_conditional_array_notations (tree);
+struct c_expr fix_array_notation_expr (location_t, enum tree_code,
+				       struct c_expr);
+bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
+static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var);
+bool contains_array_notation_expr (tree expr);
+tree expand_array_notation_exprs (tree t);
+
+
+struct inv_list
+{
+  vec<tree, va_gc> *list_values;
+  vec<tree, va_gc> *replacement;
+};
+
+
+/* Returns the rank of ARRAY through the *RANK.  The user can specify whether
+   (s)he wants to step into array_notation-specific builtin functions
+   (specified by the IGNORE_BUILTIN_FN).
+
+   For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0]
+   all have a rank of 2.  */
+
+void
+find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
+{
+  tree ii_tree;
+  size_t 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;
+    }
+  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 < (size_t) length; ii++)
+		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+	    }
+	  else
+	    gcc_unreachable ();
+	}
+      else 
+	for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) 
+	  find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+    }
+  return;
+}
+  
+
+/* Extracts all the array notations specified in NODE and stores them in a
+   dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE.  The
+   user can specify if (s)he wants to ignore the array notations inside the
+   array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
+   true).  */
+
+void
+extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
+			      vec<tree, va_gc> **array_list)
+{
+  size_t ii = 0;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
+  if (!node)
+    return;
+  else if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    {
+      vec_safe_push (*array_list, node);
+      return;
+    }
+  else if (TREE_CODE (node) == TREE_LIST)
+    {
+      extract_array_notation_exprs (TREE_PURPOSE (node), ignore_builtin_fn,
+				    array_list);
+      extract_array_notation_exprs (TREE_VALUE (node), ignore_builtin_fn,
+				    array_list);
+      extract_array_notation_exprs (TREE_CHAIN (node), ignore_builtin_fn,
+				    array_list);
+    }
+  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);
+    }
+  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
+	    {
+	      vec_safe_push (*array_list, node);
+	      return;
+	    }
+	}
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	{
+	  vec_safe_push (*array_list, node);
+	  return;
+	}
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+
+	  for (ii = 0; ii < (size_t) length; ii++)
+	    extract_array_notation_exprs
+	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
+	}
+      else
+	gcc_unreachable (); /* We should not get here.  */
+	  
+    } 
+  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);
+  return;
+}
+
+
+/* Replaces all occurances of array notations in tree ORIG that matches the
+   ones in LIST with the one in ARRAY_OPERAND.  The size of list and
+   ARRAY_OPERAND is ARRAY_SIZE.  For example, ARRAY_OPERAND[x] for some index
+   'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified
+   in LIST[x].   The  user can specify if (s)he wants to ignore the array
+   notations inside the array-notation specific builtin functions (using the
+   bool variable IGNORE_BUILTIN_FN).  */
+
+void
+replace_array_notations (tree *orig, bool ignore_builtin_fn,
+			 vec<tree, va_gc> *list,
+			 vec<tree, va_gc> *array_operand)
+{
+  size_t ii = 0;
+  tree node = NULL_TREE, node_replacement = NULL_TREE;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
+  if (vec_safe_length (list) == 0 || !*orig)
+    return;
+
+  if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
+    {
+      for (ii = 0; vec_safe_iterate (list, ii, &node); ii++) 
+	if (*orig == node)
+	  {
+	    node_replacement = (*array_operand)[ii];
+	    *orig = node_replacement;
+	  }
+    }
+  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);
+    }
+  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; vec_safe_iterate (list, ii, &node); ii++) 
+		if (*orig == node)
+		  {
+		    node_replacement = (*array_operand)[ii];
+		    *orig = node_replacement;
+		  }
+	    }
+	  return;
+	}
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
+	{
+	  for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
+	    if (*orig == node)
+	      {
+		node_replacement = (*array_operand)[ii];
+		*orig = node_replacement;
+	      }
+	  return;
+	}
+      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
+	  for (ii = 0; ii < (size_t) length; ii++)
+	    replace_array_notations
+	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+	       array_operand);
+	}
+      else
+	gcc_unreachable (); /* We should not get here!  */
+    }
+  else
+    {
+      for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++) 
+	replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, 
+				 list, array_operand);
+    }
+  return;
+}
+
+/* This function will find all the scalar expressions in *TP and push it in
+   DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 then
+   we have do not go into the *TP's subtrees.  */
+
+static tree
+find_inv_trees (tree *tp, int *walk_subtrees, void *data)
+{
+  struct inv_list *i_list = (struct inv_list *) data;
+
+  if (!tp || !*tp)
+    return NULL_TREE;
+  if (TREE_CONSTANT (*tp))
+    return NULL_TREE; /* No need to save constant to a variable.  */
+  if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
+    {
+      vec_safe_push (i_list->list_values, *tp);
+      *walk_subtrees = 0;
+    }
+  else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
+	   || TREE_CODE (*tp) == ARRAY_REF
+	   || TREE_CODE (*tp) == CALL_EXPR)
+    /* No need to step through the internals of array notation.  */
+    *walk_subtrees = 0;
+  else
+    *walk_subtrees = 1;
+  return NULL_TREE;
+}
+
+/* Replace all the scalar expressions in *TP with the appropriate replacement
+   stored in the struct *DATA (typecasted to void*).  The subtrees are not
+   touched if *WALK_SUBTREES is set to zero.  */
+
+static tree
+replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
+{
+  size_t ii = 0;
+  tree t, r;
+  struct inv_list *i_list = (struct inv_list *) data;
+
+  if (vec_safe_length (i_list->list_values))
+    {
+      for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
+	{
+	  if (simple_cst_equal (*tp, t) == 1)
+	    {
+	      vec_safe_iterate (i_list->replacement, ii, &r);
+	      gcc_assert (r != NULL_TREE);
+	      *tp = r;
+	      *walk_subtrees = 0;
+	    }
+	}
+    }
+  else
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
+/* Replaces all the scalar expressions in *NODE. */
+
+tree
+replace_invariant_exprs (tree *node)
+{
+  size_t ix = 0;
+  tree node_list = NULL_TREE;
+  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  struct inv_list data;
+  if (!node || !*node)
+    return NULL_TREE;
+
+  data.list_values = NULL;
+  data.replacement = NULL;
+  walk_tree (node, find_inv_trees, (void *)&data, NULL);
+
+  if (vec_safe_length (data.list_values))
+    {
+      node_list = push_stmt_list ();
+      for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
+	{
+	  new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
+				TREE_TYPE (t));
+	  gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
+	  new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
+	  add_stmt (new_node);
+	  vec_safe_push (data.replacement, new_var);
+	}
+      walk_tree (node, replace_inv_trees, (void *)&data, NULL);
+      node_list = pop_stmt_list (node_list);
+    }
+  return node_list;
+}
+  
+
+/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
+   The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
+   Their locations are specified by LHS_LOC, RHS_LOC.  The location of the
+   modify expression is location.  The original type of LHS and RHS are passed
+   in LHS_ORIGTYPE and RHS_ORIGTYPE.  */
+
+tree
+build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
+			   enum tree_code modifycode, location_t rhs_loc,
+			   tree rhs, tree rhs_origtype)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL, found_builtin_fn = false;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree loop = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree *body_label = NULL, *body_label_expr = NULL;
+  tree *exit_label = NULL, *exit_label_expr = NULL, *cond_expr = NULL;
+  tree *if_stmt_label = NULL;
+  tree scalar_mods = NULL_TREE;
+  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;
+  vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0;
+  size_t ii = 0, jj = 0;
+  int s_jj = 0;
+  tree ii_tree = NULL_TREE, new_modify_expr;
+  vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
+  tree new_var = NULL_TREE, builtin_loop = NULL_TREE;
+  size_t rhs_list_size = 0, lhs_list_size = 0;
+
+  /* If either of this is true, an error message must have been send out
+     already.  Not necessary to send out multiple error messages.  */
+  if (lhs == error_mark_node || rhs == error_mark_node)
+    return error_mark_node;
+  find_rank (rhs, false, &rhs_rank);
+  
+  extract_array_notation_exprs (rhs, false, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);
+  loop = push_stmt_list ();
+  if (rhs_rank)
+    {
+      scalar_mods = replace_invariant_exprs (&rhs);
+      if (scalar_mods)
+	add_stmt (scalar_mods);
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree rhs_node = (*rhs_list)[ii];
+      if (TREE_CODE (rhs_node) == CALL_EXPR)
+	{
+	  builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
+	  if (builtin_loop == error_mark_node)
+	    return error_mark_node;
+	  else if (builtin_loop)
+	    {
+	      add_stmt (builtin_loop);
+	      found_builtin_fn = true;
+	      if (new_var)
+		{
+		  vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
+		  vec_safe_push (rhs_sub_list, rhs_node);
+		  vec_safe_push (new_var_list, new_var);
+		  replace_array_notations (&rhs, false, rhs_sub_list,
+					   new_var_list);
+		}
+	    }
+	}
+    }
+
+  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);
+  extract_array_notation_exprs (lhs, true, &lhs_list);
+
+  rhs_list_size = vec_safe_length (rhs_list);
+  lhs_list_size = vec_safe_length (lhs_list);
+  
+  if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
+    {
+      tree rhs_base = rhs;
+      for (ii = 0; ii < (size_t) rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      
+      error_at (location, "%qD cannot be scalar when %qD is not", lhs,
+		rhs_base);
+      return error_mark_node;
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+      
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+      
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+  
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+  
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have the
+    following scenarios: 
+    1. LHS_RANK == RHS_RANK
+    2. LHS_RANK != RHS_RANK && RHS_RANK = 0 
+    
+    In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  body_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  body_label_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  exit_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  exit_label_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  if_stmt_label = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr =XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] =  XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down =  XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare =  XNEWVEC (tree, lhs_rank);
+  rhs_compare =  XNEWVEC (tree, rhs_rank);
+
+  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++)
+    {
+      tree lhs_node = (*lhs_list)[ii];
+      if (TREE_CODE (lhs_node) == 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
+		  lhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]));
+		  rhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]));
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then 
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0)))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  rhs_vector[ii][jj] = false;
+    }
+
+
+
+  for (ii = 0; ii < lhs_rank; ii++)
+    {
+      if (lhs_vector[0][ii])
+	{
+	  lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				    integer_type_node);
+	  lhs_ind_init[ii] = build_modify_expr
+	    (location, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
+	     NOP_EXPR,
+	     location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
+	     TREE_TYPE (lhs_var[ii]));
+	  
+	}
+    }
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type 
+	 integer.  */
+      rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+      rhs_ind_init[ii] = build_modify_expr
+	(location, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
+	 NOP_EXPR,
+	 location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0),
+	 TREE_TYPE (rhs_var[ii]));
+    }
+  
+
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statement will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    { 
+	      /* The last ARRAY_NOTATION element's ARRAY component should be 
+		 the array's base value.  */
+	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
+	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  if (lhs_count_down[ii][s_jj])
+	  	      /* Array[start_index + (induction_var * stride)].  */
+		      lhs_array_opr = build_array_ref
+			(location, lhs_array_opr,
+			 build2 (MINUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
+				 lhs_start[ii][s_jj],
+				 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
+					 lhs_var[s_jj],
+					 lhs_stride[ii][s_jj])));
+		  else
+		    lhs_array_opr = build_array_ref
+		      (location, lhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
+			       lhs_start[ii][s_jj],
+			       build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
+				       lhs_var[s_jj],
+				       lhs_stride[ii][s_jj])));
+		}
+	      vec_safe_push (lhs_array_operand, lhs_array_opr);
+	    }
+	  else
+	    vec_safe_push (lhs_array_operand, integer_one_node);
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
+	      for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  if (rhs_count_down[ii][s_jj])
+		    {
+		      /* Array[start_index - (induction_var * stride)] */
+		      rhs_array_opr = build_array_ref
+			(location, rhs_array_opr,
+			 build2 (MINUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
+				 rhs_start[ii][s_jj],
+				 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
+					 rhs_var[s_jj],
+					 rhs_stride[ii][s_jj])));
+		    }
+		  else
+		    {
+		      /* Array[start_index  + (induction_var * stride)] */
+		      rhs_array_opr = build_array_ref
+			(location, rhs_array_opr,
+			 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
+				 rhs_start[ii][s_jj],
+				 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
+					 rhs_var[s_jj],
+					 rhs_stride[ii][s_jj])));
+		    }
+		}
+	      vec_safe_push (rhs_array_operand, rhs_array_opr);
+	    }
+	  else
+	  /* This is just a dummy node to make sure the list sizes for both
+	     array list and array operand list are the same.  */
+	  vec_safe_push (rhs_array_operand, integer_one_node);
+	}
+
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value == -1) /* This means we have an error.  */
+		      return error_mark_node;
+		    else if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree lhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < lhs_rank; ee++)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  lhs_base);
+			return error_mark_node;
+		      }
+		  }  
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value == -1) /* This means we have an error.  */
+		      return error_mark_node;
+		    else if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree lhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < lhs_rank; ee++)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  lhs_base);
+			return error_mark_node;
+		      }
+		  }  
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      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])
+	{
+	  size_t iii = 0;
+	  if (lhs_rank == 0)
+	    lhs_compare[jj] = integer_one_node;
+	  else if (lhs_count_down[0][jj])
+	    lhs_compare[jj] = build2
+	      (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+	  else
+	    lhs_compare[jj] = build2
+	      (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
+
+
+	  /* The reason why we have this here is for the following case:
+	         Array[:][:] = function_call(something) + Array2[:][:];
+
+	     So, we will skip the first operand of RHS and then go to the
+	     2nd to find whether we should count up or down.  */
+	 
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	      
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    /* We use iii for rhs_length because that is the correct countdown
+	       we have to use.  */
+	      rhs_compare[jj] = build2
+		(LT_EXPR, boolean_type_node, rhs_var[jj],
+		 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
+			 rhs_length[iii][jj],
+			 build_int_cst (TREE_TYPE (rhs_var[jj]), -1)));
+	  else
+	    rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj],
+				      rhs_length[iii][jj]);
+	  if (lhs_compare[ii] != integer_one_node)
+	    cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
+				    lhs_compare[jj], rhs_compare[jj]);
+	  else
+	    cond_expr[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++)
+    {
+      if (lhs_rank)
+	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 (s_jj = ((int) MAX (lhs_rank, rhs_rank)) - 1; s_jj >= 0; s_jj--)
+    {
+      if (lhs_rank)
+	add_stmt (lhs_expr_incr[s_jj]);
+      if (rhs_rank && rhs_expr_incr[s_jj])
+	add_stmt (rhs_expr_incr[s_jj]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[s_jj]));
+      add_stmt (exit_label_expr[s_jj]);
+    }
+  pop_stmt_list (loop);
+  return loop;
+}
+
+
+/* Encloses the conditional statement passed in STMT with a loop around it
+   and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
+   The condition must have a ARRAY_NOTATION_REF tree.  */
+
+static tree
+fix_conditional_array_notations_1 (tree stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0;
+  tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
+  size_t rank = 0, ii = 0, jj = 0;
+  int s_jj = 0;
+  tree **array_ops, *array_var, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+  tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  location_t location = UNKNOWN_LOCATION;
+
+  if (TREE_CODE (stmt) == COND_EXPR)
+    cond = COND_EXPR_COND (stmt);
+  else if (TREE_CODE (stmt) == SWITCH_EXPR)
+    cond = SWITCH_COND (stmt);
+  else
+    /* Otherwise dont even touch the statement.  */
+    return stmt;
+
+  find_rank (cond, false, &rank);
+  extract_array_notation_exprs (cond, false, &array_list);
+  loop = push_stmt_list ();
+  for (ii = 0; ii < vec_safe_length (array_list); ii++)
+    { 
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == CALL_EXPR)
+	{
+	  builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
+	  if (builtin_loop == error_mark_node)
+	    {
+	      add_stmt (error_mark_node);
+	      pop_stmt_list (loop);
+	      return loop;
+	    }
+	  else if (builtin_loop)
+	    {
+	      vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
+	      vec_safe_push (sub_list, array_node);
+	      vec_safe_push (new_var_list, new_var);
+	      add_stmt (builtin_loop);
+	      replace_array_notations (&cond, false, sub_list, new_var_list); 
+	    }
+	}
+    }
+  find_rank (cond, true, &rank);
+  if (rank == 0)
+    {
+      add_stmt (stmt);
+      pop_stmt_list (loop); 
+      return loop;
+    }
+  
+  extract_array_notation_exprs (cond, true, &array_list);
+
+  if (vec_safe_length (array_list) == 0)
+    return stmt;
+
+  list_size = vec_safe_length (array_list);
+  location = EXPR_LOCATION (stmt);
+
+  array_ops =  XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] =  XNEWVEC (tree, rank);
+
+  array_vector =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] =  XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree,  rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree,  rank);
+
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      jj = 0;
+      for (jj_tree = array_node;
+	   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++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		  array_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 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;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of. */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      if (count_down[ii][s_jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_opr = build_array_ref
+		    (location, array_opr,
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_opr = build_array_ref
+		    (location, array_opr,
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+	/* This is just a dummy node to make sure the list sizes for both
+	   array list and array operand list are the same.  */
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  for (ii = 0; ii < rank; ii++) 
+    expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, array_var[ii], 
+			    build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), 
+				    array_var[ii], 
+				    build_int_cst (TREE_TYPE (array_var[ii]), 
+						   1)));
+  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 (s_jj = rank - 1; s_jj >= 0; s_jj--)
+    {
+      add_stmt (expr_incr[s_jj]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[s_jj]));
+      add_stmt (exit_label_expr[s_jj]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  // XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  return loop;
+}
+
+/* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
+   in STMT.  */
+
+tree
+fix_conditional_array_notations (tree stmt)
+{
+  if (TREE_CODE (stmt) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator tsi;
+      for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
+	{
+	  tree single_stmt = *tsi_stmt_ptr (tsi);
+	  *tsi_stmt_ptr (tsi) =
+	    fix_conditional_array_notations_1 (single_stmt);
+	}
+      return stmt;
+    }
+  else
+    return fix_conditional_array_notations_1 (stmt);
+}
+
+/* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
+   LOCATION with the tree_code CODE and the array notation expr is
+   passed in ARG.  Returns the fixed c_expr in ARG itself.  */
+
+struct c_expr 
+fix_array_notation_expr (location_t location, enum tree_code code,
+			 struct c_expr arg)
+{
+
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  int s_jj = 0;
+  tree **array_ops, *array_var, 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);
+
+  if (vec_safe_length (array_list) == 0)
+    return arg;
+
+  list_size = vec_safe_length (array_list);
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = (*array_list)[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		  array_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])) 
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label, i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      if (count_down[ii][s_jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_opr = build_array_ref
+		    (location, array_opr,
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_opr = build_array_ref
+		    (location, array_opr,
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+      	/* This is just a dummy node to make sure the list sizes for both
+	   array list and array operand list are the same.  */
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&arg.value, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      expr_incr[ii] =
+	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+    }
+  
+  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 (s_jj = rank - 1; s_jj >= 0; s_jj--)
+    {
+      add_stmt (expr_incr[s_jj]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[s_jj]));
+      add_stmt (exit_label_expr[s_jj]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  arg.value = loop;
+  return arg;
+}
+
+/* Replace array notation's built-in function passed in AN_BUILTIN_FN with
+   the appropriate loop and computation (all stored in variable LOOP of type
+   tree node).  The output of the function function is always a scalar and that
+   result is returned in *NEW_VAR.  *NEW_VAR is NULL_TREE if the function is
+   __sec_reduce_mutating.  */
+
+static tree
+fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
+{
+  tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
+  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
+  tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
+  tree new_exp_init = NULL_TREE;
+  an_reduce_type an_type = REDUCE_UNKNOWN;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  int s_jj = 0;
+  tree **array_ops, *array_var, jj_tree, loop, array_op0;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+  tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+  tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  location_t location = UNKNOWN_LOCATION;
+  
+  if (!is_builtin_array_notation_fn (CALL_EXPR_FN (an_builtin_fn), &an_type))
+    return NULL_TREE;
+
+  if (an_type != REDUCE_CUSTOM && an_type != REDUCE_MUTATING)
+    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  else
+    {
+      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+      call_fn = TREE_OPERAND (call_fn, 0);
+      
+      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
+    }
+  
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  find_rank (an_builtin_fn, true, &rank);
+
+  location = EXPR_LOCATION (an_builtin_fn);
+ 
+  if (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+	   && (an_type == REDUCE_MAX_INDEX  || an_type == REDUCE_MIN_INDEX))
+    {
+      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
+		" have arrays with dimension greater than 1.");
+      return error_mark_node;
+    }
+  
+  extract_array_notation_exprs (func_parm, true, &array_list);
+  list_size = vec_safe_length (array_list);
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+    case REDUCE_MUL:
+    case REDUCE_MAX:
+    case REDUCE_MIN:
+      new_var_type = ARRAY_NOTATION_TYPE ((*array_list)[0]);
+      break;
+    case REDUCE_ALL_ZEROS:
+    case REDUCE_ALL_NONZEROS:
+    case REDUCE_ANY_ZEROS:
+    case REDUCE_ANY_NONZEROS:
+      new_var_type = integer_type_node;
+      break;
+    case REDUCE_MAX_INDEX:
+    case REDUCE_MIN_INDEX:
+      new_var_type = integer_type_node;
+      break;
+    case REDUCE_CUSTOM:
+      if (call_fn && identity_value) 
+	new_var_type = ARRAY_NOTATION_TYPE ((*array_list)[0]);
+      break;
+    case REDUCE_MUTATING:
+      new_var_type = NULL_TREE;
+      break;
+    default:
+      gcc_unreachable ();  /* You should not reach here.  */
+    }
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree,  rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool,  rank);
+  
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = (*array_list)[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		  array_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = alloc_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr_node  = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      if (count_down[ii][s_jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_opr_node = build_array_ref
+		    (location, array_opr_node,
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_opr_node = build_array_ref
+		    (location, array_opr_node,
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	    }
+	  vec_safe_push (array_operand, array_opr_node);
+	}
+      else
+	/* This is just a dummy node to make sure the list sizes for both
+	   array list and array operand list are the same.  */
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  for (ii = 0; ii < rank; ii++)
+    {
+      expr_incr[ii] =
+	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+    }
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+
+  if (an_type != REDUCE_MUTATING)
+    {
+      *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
+      gcc_assert (*new_var && *new_var != error_mark_node);
+    }
+  else
+    *new_var = NULL_TREE;
+  
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    array_ind_value = build_decl (location, VAR_DECL, NULL_TREE, 
+				  TREE_TYPE (func_parm));
+  array_op0 = (*array_operand)[0];			      
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
+	 location, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_MUL:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
+	 location, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_ALL_ZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      /* Initially you assume everything is zero, now if we find a case where 
+	 it is NOT true, then we set the result to false. Otherwise 
+	 we just keep the previous value.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
+      break;
+    case REDUCE_ALL_NONZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false.  Otherwise
+	 we just keep the previous value.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
+      break;
+    case REDUCE_ANY_ZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      /* Initially we assume there are NO zeros in the list. When we find 
+	 a non-zero, we keep the previous value.  If we find a zero, we 
+	 set the value to true.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
+      break;
+    case REDUCE_ANY_NONZEROS:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      /* Initially we assume there are NO non-zeros in the list. When we find 
+	 a zero, we keep the previous value.  If we find a non-zero, we set 
+	 the value to true.  */
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_one_cst (new_var_type), new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(location, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
+      break;
+    case REDUCE_MAX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MAX_INDEX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 location, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_TYPE ((*array_operand)[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, TREE_OPERAND (array_op0, 1),
+	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_OPERAND (array_op0, 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (LT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN_INDEX:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, build_zero_cst (new_var_type), new_var_type);
+      new_exp_init = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
+      new_no_ind = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(location, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 location, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_TYPE (array_op0));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     location, TREE_OPERAND (array_op0, 1),
+	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
+	  new_yes_expr = build_modify_expr
+	    (location, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     location, func_parm, TREE_OPERAND (array_op0, 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(location,
+	 build2 (GT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_CUSTOM:
+      new_var_init = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, identity_value, new_var_type);
+      new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
+      new_expr = build_modify_expr
+	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 location, new_call_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MUTATING:
+      new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
+      break;
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    append_to_statement_list (ind_init [ii], &loop);
+
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    append_to_statement_list (new_exp_init, &loop);
+  if (an_type != REDUCE_MUTATING)
+    append_to_statement_list (new_var_init, &loop);
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      append_to_statement_list
+	(build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+      append_to_statement_list
+	(build3 (COND_EXPR, void_type_node, compare_expr[ii],
+		 build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+		 build1 (GOTO_EXPR, void_type_node, exit_label[ii])), &loop);
+      append_to_statement_list (body_label_expr[ii], &loop);
+    }
+					   
+  append_to_statement_list (new_expr, &loop);
+  
+  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+    {
+      append_to_statement_list (expr_incr[s_jj], &loop);
+      append_to_statement_list
+	(build1 (GOTO_EXPR, void_type_node, if_stmt_label[s_jj]), &loop);
+      append_to_statement_list (exit_label_expr[s_jj], &loop);
+    }
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  return loop;
+}
+
+/* Returns true of FUNC_NAME is a builtin array notation function.  The type of
+   function is returned in *TYPE.  */
+
+bool
+is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
+{
+  const char *function_name = NULL;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (func_name);
+  else if (TREE_CODE (func_name) == ADDR_EXPR)
+    {
+      func_name = TREE_OPERAND (func_name, 0);
+      if (TREE_CODE (func_name) == FUNCTION_DECL)
+	function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+    }
+  
+  if (!function_name)
+    return false;
+
+  if (!strcmp (function_name, "__sec_reduce_add"))
+    {
+      *type = REDUCE_ADD;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_mul"))
+    {
+      *type = REDUCE_MUL;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_all_zero"))
+    {
+      *type = REDUCE_ALL_ZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_all_nonzero"))
+    {
+      *type = REDUCE_ALL_NONZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_any_zero"))
+    {
+      *type = REDUCE_ANY_ZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_any_nonzero"))
+    {
+      *type = REDUCE_ANY_NONZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_max"))
+    {
+      *type = REDUCE_MAX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_min"))
+    {
+      *type = REDUCE_MIN;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_min_ind"))
+    {
+      *type = REDUCE_MIN_INDEX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_max_ind"))
+    {
+      *type = REDUCE_MAX_INDEX;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce"))
+    {
+      *type = REDUCE_CUSTOM;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_mutating"))
+    {
+      *type = REDUCE_MUTATING;
+      return true;
+    }
+  else
+    {
+      *type = REDUCE_UNKNOWN;
+      return false;
+    }
+  return false;
+}
+
+
+/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
+
+bool
+contains_array_notation_expr (tree expr)
+{
+  vec<tree, va_gc> *array_list = NULL;
+  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);
+  if (vec_safe_length (array_list) == 0)
+    return false;
+  else
+    return true;
+}
+
+/* Replaces array notations in void function call arguments in ARG with loop and
+   tree-node ARRAY_REF and returns that value in a tree node variable called
+   LOOP.  */
+
+static tree
+fix_array_notation_call_expr (tree arg)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  tree new_var = NULL_TREE;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  int s_jj = 0;
+  tree **array_ops, *array_var, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+  tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  an_reduce_type an_type = REDUCE_UNKNOWN;
+  location_t location = UNKNOWN_LOCATION;
+
+  if (TREE_CODE (arg) == CALL_EXPR
+      && is_builtin_array_notation_fn (CALL_EXPR_FN (arg), &an_type))
+    {
+      loop = fix_builtin_array_notation_fn (arg, &new_var);
+      /* We are ignoring the new var because either the user does not want to
+	 capture it OR he is using sec_reduce_mutating function.  */
+      return loop;
+    }
+  
+  find_rank (arg, false, &rank);
+  if (rank == 0)
+    return arg;
+  
+  extract_array_notation_exprs (arg, true, &array_list);
+
+  if (vec_safe_length (array_list) == 0)
+    return arg;
+  
+  list_size = vec_safe_length (array_list);
+  location = EXPR_LOCATION (arg);
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  body_label = XNEWVEC (tree, rank);
+  body_label_expr = XNEWVEC (tree, rank);
+  exit_label = XNEWVEC (tree, rank);
+  exit_label_expr = XNEWVEC (tree, rank);
+  compare_expr = XNEWVEC (tree, rank);
+  if_stmt_label = XNEWVEC (tree, rank);
+  
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down =  XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = (*array_list)[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == 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] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		  array_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])) 
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (location, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   location,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));
+	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* This will create the if statement label.  */
+      if_stmt_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* This label statment will point to the loop body.  */
+      body_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* This will create the exit label..i.e. where the while loop will branch
+	 out of.  */
+      exit_label[ii] = build_decl (location, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr_node = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      if (count_down[ii][s_jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_opr_node = build_array_ref
+		    (location, array_opr_node,
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_opr_node = build_array_ref
+		    (location, array_opr_node,
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
+			     array_start[ii][s_jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
+				     array_var[s_jj], array_stride[ii][s_jj])));
+		}
+	    }
+	  vec_safe_push (array_operand, array_opr_node);
+	}
+      else
+	/* This is just a dummy node to make sure the list sizes for both
+	   array list and array operand list are the same.  */
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&arg, true, array_list, array_operand);
+  for (ii = 0; ii < rank; ii++) 
+    expr_incr[ii] = 
+      build2 (MODIFY_EXPR, void_type_node, array_var[ii], 
+	      build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii], 
+		      build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+  
+  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 (s_jj = rank - 1; s_jj >= 0; s_jj--)
+    {
+      add_stmt (expr_incr[s_jj]);
+      add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[s_jj]));
+      add_stmt (exit_label_expr[s_jj]);
+    }
+
+  pop_stmt_list (loop);
+
+  XDELETEVEC (body_label);
+  XDELETEVEC (body_label_expr);
+  XDELETEVEC (exit_label);
+  XDELETEVEC (exit_label_expr);
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (if_stmt_label);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  arg = loop;
+  return arg;
+}
+
+
+/* Walks through tree node T and find all the call-statments that do not return
+   anything and fix up any array notations they may carry.  */
+
+tree
+expand_array_notation_exprs (tree t)
+{
+  if (!t || !contains_array_notation_expr (t))
+    return t;
+
+  switch (TREE_CODE (t))
+    {
+    case BIND_EXPR:
+      t = expand_array_notation_exprs (BIND_EXPR_BODY (t));
+      return t;
+    case COND_EXPR:
+      t = fix_conditional_array_notations (t);
+
+      /* After the expansion if it is still a COND_EXPR, we go into its
+	 subtrees.  */
+      if (TREE_CODE (t) == COND_EXPR)
+	{
+	  COND_EXPR_THEN (t) = expand_array_notation_exprs (COND_EXPR_THEN (t));
+	  COND_EXPR_ELSE (t) = expand_array_notation_exprs (COND_EXPR_ELSE (t));
+	}
+      else
+	t = expand_array_notation_exprs (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;
+}
+
+
+/* Returns array notation expression for the array base ARRAY of type TYPE,
+   with start index, length and stride given by START_INDEX, LENGTH and STRIDE,
+   respectively.  */
+
+tree
+build_array_notation_ref (location_t loc, tree array, tree start_index, 
+			  tree length, tree stride, tree type)
+{
+  tree array_ntn_tree = NULL_TREE;
+  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
+  
+  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+    {
+      error_at (loc,
+		"start-index of array notation triplet is not an integer.");
+      return error_mark_node;
+    }
+  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+    {
+      error_at (loc, "length of array notation triplet is not an integer.");
+      return error_mark_node;
+    }
+  if (stride && (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))))
+    {
+      error_at (loc, "stride of array notation triplet is not an integer.");
+      return error_mark_node;
+    }  
+  if (!stride)
+    {
+      if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length) 
+	  && tree_int_cst_lt (length, start_index))
+	stride = build_int_cst (TREE_TYPE (start_index), -1);
+      else
+	stride = build_int_cst (TREE_TYPE (start_index), 1);
+    }	      
+
+  find_rank (start_index, false, &start_rank);
+  find_rank (length, false, &length_rank);
+  find_rank (stride, false, &stride_rank);
+
+  if (start_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet's start-index is not "
+		"zero.");
+      return error_mark_node;
+    }
+  if (length_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet's length is not zero.");
+      return error_mark_node;
+    }
+  if (stride_rank != 0)
+    {
+      error_at (loc, "rank of array notation triplet's stride is not zero.");
+      return error_mark_node;
+    }
+  
+  
+  array_ntn_tree = build5 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
+			   NULL_TREE, NULL_TREE, NULL_TREE);
+  ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
+  ARRAY_NOTATION_START (array_ntn_tree) = start_index;
+  ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
+  ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
+  ARRAY_NOTATION_TYPE (array_ntn_tree) = type;
+  TREE_TYPE (array_ntn_tree) = type;
+  
+  return array_ntn_tree;
+}
+
+/* This function will check if OP is a CALL_EXPR that is a builtin array 
+   notation function.  If so, then we will return its type to be the type of
+   the array notation inside.  */
+
+tree
+find_correct_array_notation_type (tree op)
+{
+  tree fn_arg, return_type = NULL_TREE;
+  an_reduce_type dummy = REDUCE_UNKNOWN;
+
+  if (op)
+    {
+      return_type = TREE_TYPE (op); /* This is the default case.  */
+      if (TREE_CODE (op) == CALL_EXPR) 
+	if (is_builtin_array_notation_fn (CALL_EXPR_FN (op), &dummy)) 
+	  { 
+	    fn_arg = CALL_EXPR_ARG (op, 0); 
+	    if (fn_arg) 
+	      return_type = TREE_TYPE (fn_arg); 
+	  }
+    } 
+  return return_type;
+}
+
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 2ae4622..ba0a7f9 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -55,6 +55,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "plugin.h"
 
+
+extern bool contains_array_notation_expr (tree);
+extern struct c_expr fix_array_notation_expr (location_t, enum tree_code,
+					      struct c_expr);
+extern tree fix_conditional_array_notations (tree);
+extern tree expand_array_notation_exprs (tree);
+
 

 /* Initialization routine for this file.  */
 
@@ -1216,6 +1223,8 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -3067,6 +3076,15 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
 	      dimen = NULL_TREE;
 	      star_seen = false;
 	    }
+	  else if (flag_enable_cilkplus
+		   && c_parser_next_token_is (parser, CPP_COLON))
+	    {
+	      dimen = error_mark_node;
+	      star_seen = false;
+	      error_at (c_parser_peek_token (parser)->location,
+			"array notations cannot be used in declaration.");
+	      c_parser_consume_token (parser);
+	    }   
 	  else if (c_parser_next_token_is (parser, CPP_MULT))
 	    {
 	      if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
@@ -3089,6 +3107,14 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
 	}
       if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
 	c_parser_consume_token (parser);
+      else if (flag_enable_cilkplus
+	       && c_parser_next_token_is (parser, CPP_COLON))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "array notations cannot be used in declaration.");
+	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	  return NULL;
+	}
       else
 	{
 	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
@@ -4071,6 +4097,10 @@ c_parser_compound_statement (c_parser *parser)
     }
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
+
+  /* If the compound stmt contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (stmt))
+    stmt = expand_array_notation_exprs (stmt);
   return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
@@ -4714,6 +4744,7 @@ c_parser_if_statement (c_parser *parser)
   bool first_if = false;
   tree first_body, second_body;
   bool in_if_block;
+  tree if_stmt;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
   c_parser_consume_token (parser);
@@ -4732,7 +4763,12 @@ c_parser_if_statement (c_parser *parser)
   else
     second_body = NULL_TREE;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  if_stmt = c_end_compound_stmt (loc, block, flag_isoc99);
+
+  /* If the if statement contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (if_stmt))
+    if_stmt = fix_conditional_array_notations (if_stmt);
+  add_stmt (if_stmt);
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
@@ -4754,6 +4790,13 @@ c_parser_switch_statement (c_parser *parser)
     {
       switch_cond_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser).value;
+      if (flag_enable_cilkplus && contains_array_notation_expr (expr))
+	{
+	  error_at (switch_cond_loc,
+		    "array notations cannot be used as a condition for switch "
+		    "statement");
+	  expr = error_mark_node;
+	}
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -4793,6 +4836,12 @@ c_parser_while_statement (c_parser *parser)
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   cond = c_parser_paren_condition (parser);
+  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+    {
+      error_at (loc, "array notations cannot be used as a condition for while "
+		"statement");
+      cond = error_mark_node;
+    }
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   save_cont = c_cont_label;
@@ -4834,6 +4883,13 @@ c_parser_do_statement (c_parser *parser)
   new_cont = c_cont_label;
   c_cont_label = save_cont;
   cond = c_parser_paren_condition (parser);
+  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+    {
+      error_at (loc, "array notations cannot be used as a condition for a "
+		"do-while statement");
+      cond = error_mark_node;
+    }
+
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
@@ -5009,6 +5065,12 @@ c_parser_for_statement (c_parser *parser)
 	  else
 	    {
 	      cond = c_parser_condition (parser);
+	      if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+		{
+		  error_at (loc, "array notations cannot be used in a "
+			    "condition for a for-loop.");
+		  cond = error_mark_node;
+		}
 	      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 	    }
 	}
@@ -5035,6 +5097,7 @@ c_parser_for_statement (c_parser *parser)
 	}
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
+  
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   save_cont = c_cont_label;
@@ -5388,9 +5451,21 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
   rhs = default_function_array_read_conversion (exp_location, rhs);
-  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
-				 code, exp_location, rhs.value,
-				 rhs.original_type);
+  
+  /* The line below is where the statement has the form:
+     A = B, where A and B contain array notation exprs. So this is where
+     we handle those.  */
+  if (flag_enable_cilkplus
+      && (contains_array_notation_expr (lhs.value)
+	  || contains_array_notation_expr (rhs.value)))
+    ret.value = build_array_notation_expr (op_location, lhs.value,
+					   lhs.original_type, code,
+					   exp_location, rhs.value,
+					   rhs.original_type);
+  else
+    ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+				   code, exp_location, rhs.value,
+				   rhs.original_type);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -5870,14 +5945,28 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+
+      /* If there is array notations in op, 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 there is array notations in op, 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);
@@ -6873,10 +6962,36 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
 	case CPP_OPEN_SQUARE:
 	  /* Array reference.  */
 	  c_parser_consume_token (parser);
-	  idx = c_parser_expression (parser).value;
-	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-				     "expected %<]%>");
-	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  if (flag_enable_cilkplus
+	      && c_parser_peek_token (parser)->type == CPP_COLON)
+	    /* If we are here, then we have something like this:
+	       Array [ : ]
+	    */
+	    expr.value = c_parser_array_notation (expr_loc, 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 (expr_loc, 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;
@@ -6984,18 +7099,32 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
 	case CPP_PLUS_PLUS:
 	  /* Postincrement.  */
 	  c_parser_consume_token (parser);
-	  expr = default_function_array_read_conversion (expr_loc, expr);
-	  expr.value = build_unary_op (op_loc,
-				       POSTINCREMENT_EXPR, expr.value, 0);
+	  /* If the expressions have 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 expressions have 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;
@@ -10881,4 +11010,170 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
+/* This function parses Cilk Plus array notation.  The starting index is
+   passed in INITIAL_INDEX and the array name is passes in ARRAY_VALUE.  The
+   return value of this function is a tree_node called VALUE_TREE of type
+   ARRAY_NOTATION_REF.  */
+
+static tree 
+c_parser_array_notation (location_t loc, 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;
+
+  if (!array_value || array_value == error_mark_node)
+    {
+      /* No need to continue.  If either of these 2 were true, then an error
+	 must be emitted already.  Thus, no need to emit them twice.  */
+      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+      return error_mark_node;
+    }
+  
+  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);
+	  if (TREE_CODE (array_type) == POINTER_TYPE)
+	    {
+	      error_at (loc, "start-index and length fields necessary for "
+			"using array notations in pointers.");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	      return error_mark_node;
+	    }
+	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
+	    {
+	      error_at (loc, "array notations cannot be used with function "
+			"type.");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	      return error_mark_node;
+	    }
+	  if (TREE_CODE (array_type) == ARRAY_TYPE)
+	    {
+	      tree subtype = TREE_TYPE (array_type);
+	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
+		{
+		  /* Now this could be a function pointer.  Find them and
+		     give out an error.  */
+		  subtype = TREE_TYPE (subtype);
+		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
+		    {
+		      error_at (loc, "array notations cannot be used with "
+				"function pointer arrays.");
+		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+						 NULL);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	  array_type_domain = TYPE_DOMAIN (array_type);
+
+	  if (!array_type_domain)
+	    {
+	      error_at (loc, "start-index and length fields necessary for "
+			"using array notations in dimensionless arrays.");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	      return error_mark_node;
+	    }
+
+	  start_index = TYPE_MINVAL (array_type_domain);
+	  start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+				     start_index);
+	  if (!TYPE_MAXVAL (array_type_domain)
+	      || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
+	    {
+	      error_at (loc, "start-index and length fields necessary for "
+			"using array notations in variable-length arrays.");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	      return error_mark_node;
+	    }
+	  x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
+	  x.low++;
+	  end_index = double_int_to_tree (integer_type_node, x);
+	  end_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, end_index);
+	  stride = build_int_cst (integer_type_node, 1);
+	  stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
+	}
+      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;
+
+	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
+	    {
+	      error_at (loc, "array notations cannot be used with function "
+			"type.");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+	      return error_mark_node;
+	    }
+	  if (TREE_CODE (array_type) == ARRAY_TYPE
+	      || TREE_CODE (array_type) == POINTER_TYPE)
+	    {
+	      tree subtype = TREE_TYPE (array_type);
+	      while (subtype
+		     && (TREE_CODE (subtype) == POINTER_TYPE
+			 || TREE_CODE (subtype) == ARRAY_TYPE))
+		{
+		  /* Now this could be a function pointer.  Find them and
+		     give out an error.  */
+		  subtype = TREE_TYPE (subtype);
+		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
+		    {
+		      error_at (loc, "array notations cannot be used with "
+				"function pointer arrays.");
+		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+						 NULL);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	  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
+	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 = build_array_notation_ref (loc, array_value, start_index,
+					 end_index, stride, type);
+  return value_tree;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index ddb6d39..15dc83d 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -103,6 +103,8 @@ static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+extern bool contains_array_notation_expr (tree);
+extern tree find_correct_array_notation_type (tree);
 

 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -2303,7 +2305,17 @@ build_array_ref (location_t loc, tree array, tree index)
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
-
+  
+  if (flag_enable_cilkplus && contains_array_notation_expr (index))
+    {
+      size_t rank = 0;
+      find_rank (index, true, &rank);
+      if (rank > 1)
+	{
+	  error_at (loc, "rank of the array's index is greater than 1.");
+	  return error_mark_node;
+	}
+    }
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
       /* Allow vector[index] but not index[vector].  */
@@ -2722,6 +2734,9 @@ build_function_call_vec (location_t loc, tree function,
 	 often rewritten and don't match the original parameter list.  */
       if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
         origtypes = NULL;
+      if (flag_enable_cilkplus && name
+	  && !strncmp (IDENTIFIER_POINTER (name), "__sec_reduce", 12))
+	origtypes = NULL;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
     function = function_to_pointer_conversion (loc, function);
@@ -2944,6 +2959,14 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
       bool npc;
       tree parmval;
 
+      /* If the function call is a builtin function call, then we do not
+	 worry about it since we break them up into its equivalent later and
+	 we do the appropriate checks there.  */
+      if (flag_enable_cilkplus && fundecl && DECL_NAME (fundecl)
+	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fundecl)),
+		       "__sec_reduce", 12))
+	continue;
+      
       if (type == void_type_node)
 	{
 	  if (selector)
@@ -3181,10 +3204,19 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error_at (input_location,
-		"too few arguments to function %qE", function);
-      inform_declaration (fundecl);
-      return -1;
+      /* If array notation is used and Cilk Plus is enabled, then we do not
+	 worry about this error now.  We will handle them in a later place.  */
+      if (flag_enable_cilkplus && DECL_NAME (fundecl)
+	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fundecl)), "__sec_reduce",
+		       12))
+	;
+      else
+	{
+	  error_at (input_location,
+		    "too few arguments to function %qE", function);
+	  inform_declaration (fundecl);
+	  return -1;
+	}
     }
 
   return error_args ? -1 : (int) parmnum;
@@ -3875,6 +3907,7 @@ lvalue_p (const_tree ref)
 
     case INDIRECT_REF:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case VAR_DECL:
     case PARM_DECL:
     case RESULT_DECL:
@@ -5097,7 +5130,6 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   enum tree_code coder;
   tree rname = NULL_TREE;
   bool objc_ok = false;
-
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -8652,6 +8684,12 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     warning_at (loc, 0,
 		"function declared %<noreturn%> has a %<return%> statement");
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (retval))
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
   if (retval)
     {
       tree semantic_type = NULL_TREE;
@@ -8994,6 +9032,19 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
 {
   tree entry = NULL, exit = NULL, t;
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+    {
+      error_at (start_locus, "array notation expression cannot be used in a "
+		"loop's condition");
+      return;
+    }
+  if (flag_enable_cilkplus && contains_array_notation_expr (incr) && 0)
+    {
+      error_at (start_locus, "array notation expression cannot be used in a "
+		"loop's increment expression.");
+      return;
+    }
+  
   /* If the condition is zero don't generate a loop construct.  */
   if (cond && integer_zerop (cond))
     {
@@ -9500,8 +9551,18 @@ build_binary_op (location_t location, enum tree_code code,
       op1 = default_conversion (op1);
     }
 
-  orig_type0 = type0 = TREE_TYPE (op0);
-  orig_type1 = type1 = TREE_TYPE (op1);
+  /* When Cilk Plus is enabled and there is array notations inside op0, then
+     we check to see if there they are builtin array notation functions.  If
+     so, then we take on the type of the array notation inside it.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (op0)) 
+    orig_type0 = type0 = find_correct_array_notation_type (op0);
+  else
+    orig_type0 = type0 = TREE_TYPE (op0);
+
+  if (flag_enable_cilkplus && contains_array_notation_expr (op1))
+    orig_type1 = type1 = find_correct_array_notation_type (op1);
+  else 
+    orig_type1 = type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index cacab01..e4699ca 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -1123,6 +1123,7 @@ target system bytes are not the same width as host system bytes.
 @tindex INDIRECT_REF
 @tindex MEM_REF
 @tindex ARRAY_REF
+@tindex ARRAY_NOTATION_REF
 @tindex ARRAY_RANGE_REF
 @tindex TARGET_MEM_REF
 @tindex COMPONENT_REF
@@ -1138,6 +1139,15 @@ to represent the lower bound and component size but should not be used
 directly; call @code{array_ref_low_bound} and @code{array_ref_element_size}
 instead.
 
+@item ARRAY_NOTATION_REF
+These nodes represent array notation expressions that are part of the Cilk Plus
+language extensions (enabled by @option{-fcilkplus} flag).  The first operand 
+is the array.  Second, third and fourth operands are the start-index, number of
+elements accessed (also called length) and the stride, respectively.  The 
+fifth operand holds the array type.  Around the end of the parsing stage, 
+these array notations are broken up into array references (@code{ARRAY_REF})
+enclosed inside a loop iterating from 0 to the number of elements accessed.
+
 @item ARRAY_RANGE_REF
 These nodes represent access to a range (or ``slice'') of an array.  The
 operands are the same as that for @code{ARRAY_REF} and have the same
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9273d7d..41086d6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1792,6 +1792,17 @@ Program Interface v3.0 @w{@uref{http://www.openmp.org/}}.  This option
 implies @option{-pthread}, and thus is only supported on targets that
 have support for @option{-pthread}.
 
+@item -fcilkplus
+@opindex fcilkplus
+@cindex Enable Cilk Plus
+Enable the usage of Cilk Language extension features for C/C++.  When the flag
+@option{-fcilkplus} is specified, all the Cilk Plus components are converted 
+to the appropriate C/C++ code.  The present implementation follows ABI version 
+0.9.  There are four major parts to Cilk Plus language 
+extension: Array Notations, Cilk Keywords, SIMD annotations and elemental 
+functions.  Detailed information about Cilk Plus can be found at 
+@w{@uref{http://www.cilkplus.org}}. 
+
 @item -fgnu-tm
 @opindex fgnu-tm
 When the option @option{-fgnu-tm} is specified, the compiler
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 654f229..045f964 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -17,6 +17,7 @@ where near complete.
 
 @menu
 * Parsing pass::         The language front end turns text into bits.
+* Cilk Plus Transformation:: Transform Cilk Plus Code to equivalent C/C++.
 * Gimplification pass::  The bits are turned into something we can optimize.
 * Pass manager::         Sequencing the optimization passes.
 * Tree SSA passes::      Optimizations on a high-level representation.
@@ -101,6 +102,36 @@ that is more descriptive than "rest_of".
 The middle-end will, at its option, emit the function and data
 definitions immediately or queue them for later processing.
 
+@node Cilk Plus Transformation
+@section Cilk Plus Transformation
+@cindex CILK_PLUS
+
+If Cilk Plus generation (flag @option{-fcilkplus}) is enabled, all the Cilk 
+Plus code is transformed into equivalent C and C++ functions.  Majority of this 
+transformation occurs toward the end of the parsing and right before the 
+gimplification pass.  
+
+These are the major components to the Cilk Plus language extension:
+@itemize @bullet
+@item Array Notations:
+During parsing phase, all the array notation specific information is stored in 
+@code{ARRAY_NOTATION_REF} tree using the function 
+@code{c_parser_array_notation}.  During the end of parsing, we check the entire
+function to see if there are any array notation specific code (using the 
+function @code{contains_array_notation_expr}).  If this function returns 
+true, then we expand them using either @code{expand_array_notation_exprs} or
+@code{build_array_notation_expr}.  For the cases where array notations are 
+inside conditions, they are transformed using the function 
+@code{fix_conditional_array_notations}.  The C language-specific routines are 
+located in @file{c/c-array-notation.c} and the equivalent C++ routines are in 
+file @file{cp/cp-array-notation.c}.  Common routines such as functions to 
+initialize builtin functions are stored in @file{array-notation-common.c}.
+@end itemize
+
+Detailed information about Cilk Plus and language specification is provided in 
+@w{@uref{http://www.cilkplus.org/}}.  It is worth mentioning that the current 
+implementation follows ABI 0.9.
+
 @node Gimplification pass
 @section Gimplification pass
 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c
new file mode 100644
index 0000000..941a8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test1.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+  int array[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  if (argc < 2)
+    {
+      fprintf(stderr,"Usage:%s <NUMBER>\n", argv[0]);
+      return -1;
+    }
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = 15;
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[0:5:2] = 20;
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\tz = %2d\n", x, z);
+  array[x:5:z] = 50;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:z] = 505;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 25;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+					 1400;
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[atoi("5"):5:1] = 5555;
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 9999;
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\n", ii, array[ii]);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
new file mode 100644
index 0000000..5fb3680
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
@@ -0,0 +1,122 @@
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+  int array[10], array2[10], ii = 0, x = 2, z= 0 , y = 0 ;
+  if (argc < 2)
+    {
+      fprintf(stderr,"Usage:%s <NUMBER>\n", argv[0]);
+      return -1;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  array2[0:10:2] = array[0:10:2];
+
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\tz = %2d\n", x, z);
+  array2[x:5:z] = array[x:5:z];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array2[x:y:z] = array[x:y:z];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  printf("==============================================\n");
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+  array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %7d\tarray2[%2d] = %7d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\tarray2[%2d] = %2d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = 
+			     array2[atoi("5"):atoi("5"):atoi("1")];
+  printf("==============================================\n");
+  for (ii = 0; ii<10; ii++)
+    printf("array[%2d] = %2d\tarray2[%2d] = %2d\n", ii, array[ii], 
+	   ii, array2[ii]);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c
new file mode 100644
index 0000000..e8e3882
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test_ND.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  int array[10][15], ii = 0, jj = 0,x = 0, z= 1 , y = 10 ;
+  int array_2[10][15];
+ 
+  if (argc != 3)
+    {
+      fprintf(stderr, "Usage: %s 10 15\n", argv[0]);
+      return -1;
+    }
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%2d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+
+#if 1
+  printf("==============================================\n"); 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  printf("x = %2d\ty = %2d\tz = %2d\n", x, y, z);
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  printf("%4d ", array_2[ii][jj]);
+	}
+      printf("\n");
+    }
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c
new file mode 100644
index 0000000..cbcc682
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double.c
@@ -0,0 +1,73 @@
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c
new file mode 100644
index 0000000..8e65993
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/builtin_func_double2.c
@@ -0,0 +1,101 @@
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10], y_int2=0, y2=0;
+  double x, yy, array3[10], array4[10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 0;
+      array2[ii] = 5;
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_nonzero (array3[:] + array[4]); 
+  y_int2 = __sec_reduce_any_zero (array3[:] + array[4]); 
+  y = __sec_reduce_all_nonzero ((array3[:] + array4[:]) * (argc-1)); 
+  y2 = __sec_reduce_all_zero ((array3[:] + array4[:]) * (argc-1)); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", array3[ii] +array4[ii]);
+  }
+  printf("\n");
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", (array3[ii] + array4[ii]) * (argc-1));
+  }
+  printf("\n");
+  printf("Any Non-zeros (1st line) = %d\t All non-zeros (2nd line) = %d\n", 
+	 y_int, y);
+  printf("Any zeros (1st line) = %d\t All zeros (2nd line) = %d\n", y_int2, y2);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
new file mode 100644
index 0000000..6d7604b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
@@ -0,0 +1,65 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-finish
+
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c
new file mode 100644
index 0000000..0e7ac28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/gather_scatter.c
@@ -0,0 +1,47 @@
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <cstdlib> */
+
+int main(int argc, char **argv)
+{
+  int array[10][10], array2[10], array3[10], x = 0, y;
+  int x_correct, y_correct, ii, jj = 0;
+  float array4[10][10][10][10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 10; jj++)
+	{
+	  array[ii][jj] = 1+ii;
+	  array2[ii]= 2;
+	  array3[ii]= 3;
+	}
+    }
+  
+  array[array2[:]][array3[:]] = 1000;
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      printf("%4d\t", array[ii][jj]);
+    }
+    printf("\n");
+  }
+#endif
+
+  array4[array2[:]][array3[0:10:1]][array2[0:10:1]][array3[0:10:1]] =
+    (float)array[array2[:]][array3[:]]; 
+
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+      for (jj = 0; jj < 10; jj++) {
+	  for (kk = 0; kk < 10; kk++) {
+	      for (ll = 0; ll < 10; ll++) {
+		  printf("%4d\n", array4[ii][jj][kk][ll]);
+	      }
+	  }
+      }
+  }
+#endif  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c
new file mode 100644
index 0000000..833379b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/if_test.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+  int x = 3, y, z, array[10], array2[10], TwodArray[10][10], jj,kk,ll ;
+  int FourDArray[10][10][10][10];
+  int ii = 0; 
+
+  if (argc != 3)
+    {
+      fprintf(stderr, "Usage: %s 10 15\n", argv[0]);
+      return;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = argc%3;
+      array2[ii]= 10;
+    }
+  
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array[ii]);
+  printf("\n");
+
+  if (!array[:])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  if (!(array[0:10:1] + array[0:10:1]))
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  x = atoi (argv[1])-10;
+  y = atoi (argv[1])/2;
+  z = (atoi (argv[1]))/5;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii % 2)
+	array[ii] = 0;
+      else
+	array[ii] = 1;
+    }
+
+  /*printf("x = %2d y = %2d z = %2d\n", x, y, z); */
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[x:y:z] != 9)
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[atoi(argv[1])-10:atoi(argv[1]): atoi(argv[1])/5])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      TwodArray[ii][jj] = atoi(argv[1]);
+
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (TwodArray[:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[:][:][:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+    for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] +
+      FourDArray[0:10:1][0:5:2][9:-10:1][x:y:z]  != 20) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++)
+    printf("%4d ", array2[ii]);
+  printf("\n");
+
+  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c
new file mode 100644
index 0000000..0a4d806
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/sec_implicit_ex.c
@@ -0,0 +1,41 @@
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int jj, kk, array_3C[10][10][10];
+  int ii,array[10], y = 0, y_int = 0, array2[10], array_3[10][10][10];
+  double x, yy, array3[10], array4[10];
+
+  array[:] = __sec_implicit_index (0);
+  array_3[:][:][:] = __sec_implicit_index (1) + __sec_implicit_index(0) +
+    __sec_implicit_index (2);
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	{
+	  array_3C[ii][jj][kk] = ii+jj+kk;
+	}
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	{
+	  printf("Computed: %3d\t Correct: %3d\t", array_3[ii][jj][kk], 
+		 array_3C[ii][jj][kk]);
+	  if (array_3[ii][jj][kk] == array_3C[ii][jj][kk])
+	    printf("OK\n");
+	  else
+	    printf("ERROR\n");
+	}
+#endif
+
+  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
new file mode 100644
index 0000000..44e7361
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
@@ -0,0 +1,16 @@
+int main(void)
+{
+  extern int func(int);
+  int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration." } */
+  int  array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration." } */
+  extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration." } */
+  int *a, ***b;
+  extern char *c;
+  int array2[10];
+
+  a[:] = 5; /* { dg-error  "start-index and length fields necessary for using array notations in pointers." } */
+  c[1:2] =  3; /* This is OK.  */
+  (array2)[:] = 5; /* This is OK.  */
+  b[1:2][1:func(x)][:] = 3; /*  { dg-error  "start-index and length fields necessary for using array notations in pointers." }  */
+}
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/dimensionless-arrays.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/dimensionless-arrays.c
new file mode 100644
index 0000000..7a85f3c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/dimensionless-arrays.c
@@ -0,0 +1,8 @@
+extern int a[];
+extern int *b;
+
+void foo()
+{
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
new file mode 100644
index 0000000..6d7604b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
@@ -0,0 +1,65 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-finish
+
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
new file mode 100644
index 0000000..272ef41
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
@@ -0,0 +1,18 @@
+typedef int (*foo)(int);
+
+int main(int argc, char **argv)
+{
+  int array[10], array2[10][10];
+  // int array[10], array2[10], value, ii = 0;
+  foo func_array[10];
+  foo func_array2[10][10];
+  foo ***func_array_ptr;
+
+  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
new file mode 100644
index 0000000..ef39b2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
@@ -0,0 +1,42 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+float q;
+
+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;
+}
+
+void func (int *x)
+{
+  *x = 5;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10], array2[10];
+  array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer." } */
+  array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer." } */
+  array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer." } */
+  func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer." } */
+  array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer." } */
+  array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer." } */
+  array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer." } */
+  
+  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
+  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer." } */
+  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
+  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer." } */
+  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer." } */
+  return 0;
+} 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/gather-scatter.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/gather-scatter.c
new file mode 100644
index 0000000..7254acf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/gather-scatter.c
@@ -0,0 +1,17 @@
+int main (int argc, char **argv)
+{
+  extern int func (int);
+  int array[10][10], array2[10];
+
+  array2[array[:][:]] = 5; /* { dg-error "rank of the array's index is greater than 1" } */
+
+  array2[array[:][:]] = 5; /* { dg-error "rank of the array's index is greater than 1" } */
+  func (array2[array[:][:]]); /* { dg-error "rank of the array's index is greater than 1" } */
+  func (array2[array[argc:func(5)][0:10:2]]); /* { dg-error "rank of the array's index is greater than 1" } */
+  
+  array[array2[:]][array2[:]] = 5; /* This is OK.  */
+  array[array2[:]][array2[:]] = array2[array[:][:]]; /* { dg-error "rank of the array's index is greater than 1" }  */
+  array[array2[:]][array2[:]] = array2[array[0:10:1][:]]; /* { dg-error "rank of the array's index is greater than 1" }  */
+  array[array2[:]][array2[:]] = array2[array[:][argc:func (argc)]]; /* { dg-error "rank of the array's index is greater than 1" }  */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c
new file mode 100644
index 0000000..5a987d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c
@@ -0,0 +1,109 @@
+int main (int argc, char **argv)
+{
+  int array[10], array2[10][10];
+  int x, ii, jj ;
+
+  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  case 1:
+    x = 5;
+    break;
+  case 2:
+    x = 2;
+    break;
+  default:
+    x = 9;
+  }
+
+  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  case 1:
+    x = 5;
+    break;
+  case 2:
+    x = 2;
+    break;
+  default:
+    x = 9;
+  }
+
+  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  case 1:
+    x = 5;
+    break;
+  case 2:
+    x = 2;
+    break;
+  default:
+    x = 9;
+  }
+  
+  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  case 1:
+    x = 5;
+    break;
+  case 2:
+    x = 2;
+    break;
+  default:
+    x = 9;
+  }
+
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop." } */
+    {
+      x = 2;
+    }
+
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop." } */
+    {
+      x = 3;
+    }
+
+  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop." } */
+    x = 4;
+
+
+  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+    x = 3;
+
+  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+    x = 1;
+
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+    x = 2;
+
+  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+    x = 3;
+  } while (ii != array2[:][:]); 
+
+  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+    x = 2;
+  } while (ii != (x + array2[:][1:x:2]) + 2);
+  
+  do { 
+    x += 3;
+    if (x == 5)
+      return array2[:][:]; /* { dg-error "array notation expression cannot be used as a return value" } */
+  } while (ii != 0);
+
+  for (ii = 0;  ii < 10; ii++)
+    if (ii % 2)
+      return array[1:x:ii]; /* { dg-error "array notation expression cannot be used as a return value" } */
+
+  for (ii = 0; ii < x; ii++)
+    if (ii)
+      return array2[:][:]; /* { dg-error "array notation expression cannot be used as a return value" } */
+
+  for (array[:] = 0; ii < x; ii++) /* This should be OK.  */
+    x= 2;
+
+  for (ii = 0; ii < 10; array[:]++) /* This is OK.  */
+    x = 5;
+
+  for (jj = 0; jj < 10; array2[:][:]++) /* This is OK.  */
+    x = 3;
+
+  for (jj = 0; jj < 10; array2[:][1:x:4]++, jj++) /* This is OK.  */
+    x = 3;
+  
+  return x;
+}
+ 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors.c
new file mode 100644
index 0000000..58108d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors.c
@@ -0,0 +1,25 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
+
+  return 0;
+} /* { dg-error "expected ';' before" } */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c
new file mode 100644
index 0000000..173fd30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors2.c
@@ -0,0 +1,25 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" } */
+
+  return 0; /* { dg-error "expected ';' before" } */
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c
new file mode 100644
index 0000000..e5b10a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors3.c
@@ -0,0 +1,25 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[1::] ;  /* { dg-error "expected expression before" } */
+
+  return 0; /* { dg-error "expected ';' before" } */
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c
new file mode 100644
index 0000000..e1749d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/parser_errors4.c
@@ -0,0 +1,25 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  
+  array2[:] = array2[::] ;  /* { dg-error " expected ']' before ':' token" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c
new file mode 100644
index 0000000..173a605
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch.c
@@ -0,0 +1,28 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int x = 0;
+  int array[10][10], array2[10];
+
+  array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+
+  x = array2[:]; /* { dg-error "cannot be scalar when" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c
new file mode 100644
index 0000000..cf5293b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit.c
@@ -0,0 +1,25 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+
+  array[:][:] = __sec_implicit_index(5) + array[:][:]; /* { dg-error "__sec_implicit_index argument" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c
new file mode 100644
index 0000000..a62da97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_implicit2.c
@@ -0,0 +1,24 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+
+  array[:][:] = __sec_implicit_index(argc) + array[:][:]; /* { dg-error "__sec_implicit_index parameter" } */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c
new file mode 100644
index 0000000..2e74eda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/sec_reduce_max_min_ind.c
@@ -0,0 +1,31 @@
+/* {dg-do compile } */
+/* {dg-options } */
+
+int main (int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10][10], array2[10];
+  int x, y;
+  x = __sec_reduce_max_ind (array[:][:]); /* { dg-error "cannot have arrays with dimension greater than" } */
+
+  y = __sec_reduce_max_ind (array2[:]); /* this should be OK. */
+
+  x = __sec_reduce_min_ind (array[:][:]); /* { dg-error "cannot have arrays with dimension greater than" } */
+
+  y = __sec_reduce_min_ind (array2[:]); /* this should be OK. */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/vla.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/vla.c
new file mode 100644
index 0000000..f59baa2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/vla.c
@@ -0,0 +1,15 @@
+int func (int x)
+{
+  return x++;
+}
+int main(int argc, char **argv)
+{
+  int array[argc];
+
+  array[:] = 5; /* { dg-error "start-index and length fields necessary for using array notations in variable-length arrays." }  */
+  array[0:argc] = 5;               /* This is OK.  */
+  array[0:5:2] = 5;                /* This is OK.  */
+  array[0:argc:2] = 5;             /* This is OK.  */
+  array[0:argc:func (argc-2)] = 5; /* This is OK.  */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/an-if.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/an-if.c
new file mode 100644
index 0000000..d532ed0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/an-if.c
@@ -0,0 +1,36 @@
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <assert.h>
+
+const int n = 8;
+
+float x[8], y[8], z[8];
+
+int main() {
+    int i = 0;
+    for(i=1; i<=5; i+=4 ) {
+        x[0:n] = 3;
+        y[0:n] = i;
+        z[0:n] = 0;
+        assert( __sec_reduce_add(x[0:n])==3*n );
+        assert( __sec_reduce_add(y[0:n])==i*n );
+        assert( __sec_reduce_add(z[0:n])==0 );
+
+        if (x[0:n] >= y[0:n]) {  
+            z[0:n] = x[0:n] - y[0:n];
+        } else {   
+            z[0:n] = x[0:n] + y[0:n];
+        }
+#if HAVE_IO
+        printf("x\ty\tz\n");
+        for( size_t k=0; k<n; ++k ) {
+            printf("%g\t%g\t%g\n",x[k],y[k],z[k]);
+        }
+#endif
+        assert( __sec_reduce_add(x[0:n])==3*n );
+        assert( __sec_reduce_add(y[0:n])==i*n );
+        assert( __sec_reduce_add(z[0:n])==(3>=i?3-i:3+i)*n );
+    }
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c
new file mode 100644
index 0000000..3cf6de7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test1.c
@@ -0,0 +1,90 @@
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};	     
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+      
+  return x;
+}
+
+int main2 (int argc, char **argv)
+{
+  int array[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = 15;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != 15)
+      abort ();
+  array[0:5:2] = 20;
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != 20)
+      abort ();
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+
+  array[x:5:z] = 50;
+  
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 50)
+      abort ();
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:z] = 505;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 505)
+      abort ();
+    
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 25;
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 25)
+      abort ();
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+ 
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    1400;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != 1400)
+      abort ();
+  
+
+  array[atoi("5"):5:1] = 5555;
+  
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != 5555)
+      abort ();
+  
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 9999;
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    if (array[ii] != 9999)
+      abort ();
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c
new file mode 100644
index 0000000..089f0f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test2.c
@@ -0,0 +1,132 @@
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "5"};	     
+      x = main2 (2, array);
+    }
+  else
+    x = main2 (argc, argv);
+      
+  return x;
+}
+
+
+int main2(int argc, char **argv)
+{
+  int array[10], array2[10], ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  
+  array2[0:5:2] = array[0:5:2];
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+ 
+  array2[x:5:z] = array[x:5:z];
+
+  for (ii = x; ii < 5; ii += z)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array2[x:y:z] = array[x:y:z];
+  for (ii = x; ii < 10; ii = ii + z)
+    if (array2[ii] != array[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != array2[ii])
+      abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = array2[atoi("5"):atoi("5"):atoi("1")];
+
+  for (ii = 5; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      abort ();
+ 
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c
new file mode 100644
index 0000000..3f75f14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/array_test_ND.c
@@ -0,0 +1,108 @@
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "10", "15"};	     
+      x = main2 (3, array);
+    }
+  else if (argc == 3)
+    x = main2 (argc, argv);
+  else
+    abort ();
+      
+  return x;
+}
+
+int main2(int argc, char **argv)
+{  
+  int array[10][15], ii = 0, jj = 0,x = 0, z= 1 , y = 10 ;
+  int array_2[10][15];
+ 
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii += 2)
+    {
+      for (jj = 0; jj < 15; jj += 3)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + 1 + 5 + array[0][5] + x)
+	    abort ();
+	}
+    }
+
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < x; ii++)
+    {
+      for (jj = 0; jj < y; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + x + y + array[ii][jj])
+	    abort ();
+	}
+    }
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  
+  for (ii = 0; ii < x; ii += z)
+    {
+      for (jj = 0; jj < y; jj += z)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] + y + z)
+	    abort ();
+	}
+    }
+
+
+ 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] * array[ii][jj])
+	    abort ();
+	}
+    }
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c
new file mode 100644
index 0000000..d4e0924
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_custom.c
@@ -0,0 +1,70 @@
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+double my_func (double x, double y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce (0, array3[:] * array4[:], my_func); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c
new file mode 100644
index 0000000..4686d6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_fn_mutating.c
@@ -0,0 +1,70 @@
+#define HAVE_IO 1
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+void my_func (double *x, double y)
+{
+  if (*x < y)
+    *x = y;
+}
+
+
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x = 0.000, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+#if 1
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+#endif 
+  /* array[:] = 5; */
+  __sec_reduce_mutating (&x, array3[:] * array4[:], my_func); 
+#if  1
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+  printf("Max = %5.3f\t Max Index = %2d\n", max_value, max_index);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c
new file mode 100644
index 0000000..24203bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double.c
@@ -0,0 +1,129 @@
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+/* #include <stdlib.h> */
+
+void abort (void);
+void exit (int);
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10];
+  double x, yy, array3[10], array4[10];
+  double max_value = 0.000, min_value = 0.000, add_value, mul_value = 1.00;
+  int max_index = 0, min_index = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2; 
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.10;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+
+  /* array[:] = 5; */
+  x = __sec_reduce_max (array3[:] * array4[:]); 
+  y = __sec_reduce_max_ind ( array3[:] * array4[:]);
+
+  /* Initialize it to the first variable.  */
+  max_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] > max_value) {
+      max_value = array3[ii] * array4[ii];
+      max_index = ii;
+    }
+    
+  
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Max = %5.3f\t Max Index = %2d\n", x, y);
+#endif
+
+  if (x != max_value)
+    abort ();
+
+  if (y != max_index)
+    abort ();
+
+  x = __sec_reduce_min (array3[:] * array4[:]); 
+  y = __sec_reduce_min_ind ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Min = %5.3f\t Min Index = %2d\n", x, y);
+#endif
+
+  /* Initialize it to the first variable.  */
+  min_value = array3[0] * array4[0];
+  for (ii = 0; ii < 10; ii++)
+    if (array3[ii] * array4[ii] < min_value) {
+      min_value = array3[ii] * array4[ii];
+      min_index = ii;
+    }
+
+  if (x != min_value)
+    abort ();
+  if (y != min_index)
+    abort ();
+
+  x = __sec_reduce_add (array3[:] * array4[:]); 
+  yy = __sec_reduce_mul ( array3[:] * array4[:]); 
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Add = %5.3f\t Mul = %f\n", x, yy);
+#endif
+
+   /* Initialize it to the first variable.  */
+  add_value = 0.0000;
+  mul_value = 1.0000;
+  for (ii = 0; ii < 10; ii++)
+    {
+      add_value += (array3[ii] * array4[ii]);
+      mul_value *= (array3[ii] * array4[ii]);
+    }
+
+  if (x != add_value)
+    abort ();
+  if (yy != mul_value)
+    abort ();
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_zero (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zero ( array3[:] * array4[:]);
+
+  if (y_int != 1)
+    abort ();
+
+  if (y != 0)
+    abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) 
+    printf("%5.3f ", array3[ii] * array4[ii]);
+  printf("\n");
+  printf("Any Zeros = %d\t All Zeros = %d\n", y_int, y);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c
new file mode 100644
index 0000000..82ae638
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/builtin_func_double2.c
@@ -0,0 +1,77 @@
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+void exit (int);
+void abort (void);
+
+
+int main(int argc, char **argv)
+{
+  int ii,array[10], y = 0, y_int = 0, array2[10], y_int2=0, y2=0;
+  double x, yy, array3[10], array4[10];
+  int all_zero, all_nonzero, any_zero, any_nonzero;
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 0;
+      array2[ii] = 5;
+      if (ii%2 && ii)
+	array3[ii] = (double)(1.0000/(double)ii);
+      else
+	array3[ii] = (double) ii + 0.00;
+      array4[ii] = (double) (1.00000/ (double)(ii+1));
+    }
+  y_int = __sec_reduce_any_nonzero (array3[:] + array[4]); 
+  y_int2 = __sec_reduce_any_zero (array3[:] + array[4]); 
+  y = __sec_reduce_all_nonzero ((array3[:] + array4[:]) * (argc-1)); 
+  y2 = __sec_reduce_all_zero ((array3[:] + array4[:]) * (argc-1));
+
+  any_zero = 0;
+  any_nonzero = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      if ((array3[ii] + array[4]) == 0)
+	any_zero = 1;
+      else
+	any_nonzero = 1;
+    }
+
+  if (any_nonzero != y_int)
+    abort ();
+  if (any_zero != y_int2)
+    abort ();
+
+
+  all_zero = 0;
+  all_nonzero = 0;
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (((array3[ii] + array4[ii]) * (argc-1)) == 0)
+	all_zero = 1;
+      else
+	all_nonzero = 1;
+    }
+
+  if (y != all_nonzero)
+    abort ();
+  if (all_zero != y2)
+    abort ();
+ 
+
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", array3[ii] +array4[ii]);
+  }
+  printf("\n");
+  for (ii = 0; ii < 10; ii++) {
+    printf("%5.3f ", (array3[ii] + array4[ii]) * (argc-1));
+  }
+  printf("\n");
+  printf("Any Non-zeros (1st line) = %d\t All non-zeros (1st line) = %d\n", 
+	 y_int, y);
+  printf("Any zeros (2nd line) = %d\t All zeros (2nd line) = %d\n", y_int2, y2);
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/comma_exp.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/comma_exp.c
new file mode 100644
index 0000000..b326d3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/comma_exp.c
@@ -0,0 +1,57 @@
+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;
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 1;
+
+  array[0:10:1] = (array[:], 15);
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != 15)
+      abort ();
+  array[0:5:2] = (argc+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;
+
+  array[:]  = (atoi(argv[1]), (array2[0:10]+5));
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != 6)
+      abort ();
+
+  array[:] = (atoi(argv[1]), (array2[0:10]+array2[0:10]));
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != 2)
+      abort ();
+  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/conditional.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/conditional.c
new file mode 100644
index 0000000..ee0c488
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/conditional.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+int main(int argc, char **argv)
+{
+  short array[1000], array2[1000], *array3, cond[1000], ii = 0;
+
+  for (ii = 0; ii < 1000; ii++) {
+    cond[ii] = 1;
+    array[ii] = 1000;
+    array2[ii] = 2000;
+  }
+  array2[:] = cond[:] ?  array[:] : array2[:];
+ 
+  for (ii = 0; ii < 1000; ii++) {
+   if (array2[ii] != 1000)
+     return 1;
+  }
+
+  array2[0:500:2] = cond[0:500] ? array[0:500:1] : array2[0:500:2];
+
+  for (ii = 0; ii < 1000; ii++) {
+   if (array2[ii] != 1000)
+     return 1;
+  }
+  return 0;
+
+  for (ii = 0; ii < 1000; ii++) {
+    cond[ii] = ii % 2; /* This should give 0, 1, 0, 1, 0, 1, 0,... */
+    array2[ii] = 5;
+    array[ii] = 3; 
+  }
+  array3 = (short *) malloc (sizeof (short) * 1000);
+  array3[0:1000:argc] = cond[:] ? array[0:(argc * 1000)] : array2[argc-1:1000];
+  
+  for (ii = 0; ii < 1000; ii++) {
+    if ((cond[ii] == 0 && array3[ii] != 5) 
+        || (cond[ii] == 1 && array3[ii] != 3))
+     return 1;
+  }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once.c
new file mode 100644
index 0000000..0808fa6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once.c
@@ -0,0 +1,42 @@
+#define HAVE_IO 0
+#define NUMBER 1000
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+int func (int *x)
+{
+  int q = *x;
+   q++;
+   *x = q;
+#if HAVE_IO
+   printf("%d\n", (q));
+#endif
+   return *x;
+}
+int main (int argc, char **argv)
+{
+  char array[NUMBER], array2[NUMBER];
+  int ii, d = 2;
+#if 1
+  for (ii = 0; ii < NUMBER; ii++)  {
+   array[ii] = 5;
+   array2[ii]= 2;
+  }
+#endif
+  d = func (&d);    /* d = 1 */
+  array2[:] = d * array[:] + (char) func (&d); /* 3 * 5 + 4 */
+#if HAVE_IO
+  for (ii = 0; ii < NUMBER; ii++)
+    printf("array2[%d] = %d\n", ii, array2[ii]);
+#endif  
+  for (ii = 0; ii < NUMBER; ii++)
+    if (array2[ii] !=  (3 * 5 + 4))
+      return 1;
+  
+  return 0;
+}
+  
+
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
new file mode 100644
index 0000000..37d22c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
@@ -0,0 +1,60 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file was written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+# Many thanks to the GCC C-torture contributors.
+
+verbose "$tool $libdir" 1
+
+set library_var [get_multilibs]
+dg-init
+set CILK_TORTURE_OPTIONS [list \
+			   { -O0 -fcilkplus  -std=c99} \
+			   { -O1 -fcilkplus  -std=c99} \
+			   { -O2 -fcilkplus  -std=c99} \
+			   { -O3 -fcilkplus  -fomit-frame-pointer -funroll-loops -std=c99} \
+			   { -O3 -fcilkplus  -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \
+			   { -O3 -fcilkplus  -fomit-frame-pointer -funroll-all-loops -finline-functions -ftree-vectorize -std=c99 } \
+			   { -O3 -g -fcilkplus  -std=c99} \
+			   { -Os -fcilkplus  -std=c99} ]
+
+
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# load support procs
+load_lib torture-options.exp
+load_lib c-torture.exp
+
+torture-init
+set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS
+
+#
+# main test loop
+#
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]]  {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+	continue
+    }
+
+    c-torture-execute $src
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c
new file mode 100644
index 0000000..c217ca9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/gather_scatter.c
@@ -0,0 +1,60 @@
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+void exit (int);
+void abort(void);
+
+int main(int argc, char **argv)
+{
+  int array[10][10], array2[10], array3[10], x = 0, y;
+  int x_correct, y_correct, ii, jj = 0;
+  float array4[10][10][10][10];
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 10; jj++)
+	{
+	  array[ii][jj] = 1+ii;
+	  array2[ii]= 2;
+	  array3[ii]= 3;
+	}
+    }
+  
+  array[array2[:]][array3[:]] = 1000;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[array2[ii]][array3[ii]] != 1000)
+      abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      printf("%4d\t", array[ii][jj]);
+    }
+    printf("\n");
+  }
+#endif
+
+  array4[array2[:]][array3[0:10:1]][array2[0:10:1]][array3[0:10:1]] =
+    (float)array[array2[:]][array3[:]]; 
+
+  for (ii = 0; ii < 10; ii++)
+    if (array4[array2[ii]][array3[ii]][array2[ii]][array3[ii]] !=
+	(float)array[array2[ii]][array3[ii]])
+      abort ();
+  
+#if HAVE_IO
+  for (ii = 0; ii < 10; ii++) {
+      for (jj = 0; jj < 10; jj++) {
+	  for (kk = 0; kk < 10; kk++) {
+	      for (ll = 0; ll < 10; ll++) {
+		  printf("%4d\n", array4[ii][jj][kk][ll]);
+	      }
+	  }
+      }
+  }
+#endif
+
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c
new file mode 100644
index 0000000..ac48742
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/if_test.c
@@ -0,0 +1,250 @@
+
+void abort (void);
+void exit(int);
+
+int main(int argc, char **argv)
+{
+  int x = 0;
+  if (argc == 1)
+    {
+      const char *array[] = {"a.out", "10", "15"};	     
+      x = main2 (3, array);
+    }
+  else if (argc == 3)
+    x = main2 (argc, argv);
+  else
+    abort ();
+ 
+  return x;
+}
+
+
+int main2 (int argc, char **argv)
+{
+  int x = 3, y, z, array[10], array2[10], TwodArray[10][10], jj,kk,ll ;
+  int array2_check[10];
+  int FourDArray[10][10][10][10];
+  int ii = 0; 
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = argc%3;
+      array2[ii]= 10;
+      array2_check[ii] = 10;
+    }
+
+  if (!array[:])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (!array[ii])
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+  
+
+  
+  if (!(array[0:10:1] + array[0:10:1]))
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (!(array[ii]+ array[ii]))
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+  
+
+      
+       
+
+  x = atoi (argv[1])-10;
+  y = atoi (argv[1])/2;
+  z = (atoi (argv[1]))/5;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      if (ii % 2)
+	array[ii] = 0;
+      else
+	array[ii] = 1;
+    }
+
+  /*printf("x = %2d y = %2d z = %2d\n", x, y, z); */
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[x:y:z] != 9)
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = x; ii < (x+y); ii += z)
+    {
+      if (array[ii] != 9)
+	array2_check[ii] = 5;
+      else
+	array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+
+  for (ii = 0; ii < 10; ii++)
+    array2[ii] = 10;
+
+  /* This if loop will change all the 10's to 5's */
+  if (array[atoi(argv[1])-10:atoi(argv[1]): atoi(argv[1])/5])
+    array2[:] = 5;
+  else
+    array2[:] = 10;
+
+  for (ii = atoi(argv[1])-10; ii < atoi(argv[1]) + (atoi (argv[1])-10);
+       ii +=atoi(argv[1])/5)
+    if (array[ii])
+      array2_check[ii] = 5;
+    else
+      array2_check[ii] = 10;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2_check[ii] != array2[ii])
+      abort ();
+ 
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      TwodArray[ii][jj] = atoi(argv[1]);
+
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (TwodArray[:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      if (TwodArray[ii][jj] != 10)
+	array2_check[ii] = 10;
+    }
+  }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[:][:][:][:] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj++) {
+      for (kk = 0; kk < 10; kk++) {
+	for (ll = 0; ll < 10; ll++) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	}
+      }
+    }
+  }
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] != 10) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj += 2) {
+      for (kk = 9; kk >= 0; kk--) {
+	for (ll = x; ll < 10; ll = ll += z) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	  else
+	    array2_check[ii] = 5;
+	}
+      }
+    }
+  }
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array2[ii] = 10;
+      array2_check[ii] = 10;
+    }
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	for (ll = 0; ll < 10; ll++) 
+	  FourDArray[ii][jj][kk][ll] = atoi(argv[1]);
+  
+  /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
+  if (FourDArray[0:10:1][0:5:2][9:10:-1][x:y:z] +
+      FourDArray[0:10:1][0:5:2][9:-10:1][x:y:z]  != 20) 
+    array2[:] = 10; 
+  else
+    array2[:] = 5;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj < 10; jj += 2) {
+      for (kk = 9; kk >= 0; kk--) {
+	for (ll = x; ll < 10; ll = ll += z) {
+	  if (FourDArray[ii][jj][kk][ll] != 10)
+	    array2_check[ii] = 10;
+	  else
+	    array2_check[ii] = 5;
+	}
+      }
+    }
+  }
+  exit (0);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/n-ptr-test.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/n-ptr-test.c
new file mode 100644
index 0000000..faf1f52
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/n-ptr-test.c
@@ -0,0 +1,45 @@
+#define NUMBER 10
+#include <stdlib.h>
+
+int ***func2 (int ***a1, int ***a2, int size)
+{
+  a1[0:size:1][0:size:1][0:size] += (a2[0:size][0:size][0:size:1]  + size);
+  return a1;
+}
+
+int main (void)
+{
+  int ii, jj, kk;
+  int ***array3, ***array2 = NULL, ***array = NULL;
+
+  array = (int ***) malloc (sizeof (int **) * NUMBER);
+  array2 = (int ***) malloc (sizeof (int **) * NUMBER);
+  for (ii = 0; ii < NUMBER; ii++) {
+    array[ii] = (int **) malloc (sizeof (int *) * NUMBER);
+    array2[ii] = (int **) malloc (sizeof (int *) * NUMBER);
+    for (jj = 0; jj < NUMBER; jj++) { 
+      array[ii][jj] = (int *) malloc (sizeof (int) * NUMBER);
+      array2[ii][jj] = (int *) malloc (sizeof (int) * NUMBER);
+    } 
+  }
+
+  for (ii = 0; ii < NUMBER; ii++) {
+    for (jj = 0; jj < NUMBER; jj++) {
+      for (kk = 0; kk < NUMBER; kk++) {
+	array[ii][jj][kk] = 5;
+	array2[ii][jj][kk]= 2;
+      }
+    }
+  }
+  array3 = func2 ((int ***)array, (int ***)array2, NUMBER);
+  
+  for (ii = 0; ii < NUMBER; ii++) {
+    for (jj = 0; jj < NUMBER; jj++) {
+      for (kk = 0; kk < NUMBER; kk++) {
+	if (array3[ii][jj][kk] != (7 + NUMBER))
+          return 1;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c
new file mode 100644
index 0000000..ed7f557
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/sec_implicit_ex.c
@@ -0,0 +1,31 @@
+
+void abort (void);
+void exit  (int);
+
+
+int main(int argc, char **argv)
+{
+  int jj, kk, array_3C[10][10][10];
+  int ii,array[10], y = 0, y_int = 0, array2[10], array_3[10][10][10];
+  double x, yy, array3[10], array4[10];
+
+  array[:] = __sec_implicit_index (0);
+  array_3[:][:][:] = __sec_implicit_index (1) + __sec_implicit_index(0) +
+    __sec_implicit_index (2);
+
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	array_3C[ii][jj][kk] = ii+jj+kk;
+	
+  for (ii = 0; ii < 10; ii++)
+    for (jj = 0; jj < 10; jj++)
+      for (kk = 0; kk < 10; kk++)
+	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
+	  abort ();
+	
+
+  exit (0);
+  
+  return 0;
+}


More information about the Gcc-patches mailing list