public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] cilkplus array notation for C (clean, independent patchset, take 1)
@ 2013-03-20 15:32 Aldy Hernandez
  2013-03-20 16:33 ` Aldy Hernandez
                   ` (4 more replies)
  0 siblings, 5 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-20 15:32 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Iyer, Balaji V, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

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.

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 211163 bytes --]

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);
+
 \f
 /* 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);
 \f
 /* 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;
+}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
@ 2013-03-20 16:33 ` Aldy Hernandez
  2013-03-20 22:28   ` Iyer, Balaji V
  2013-03-21  5:31   ` Jeff Law
  2013-03-20 22:00 ` [cilkplus-merge] test for side effects Aldy Hernandez
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-20 16:33 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Iyer, Balaji V, gcc-patches

On 03/20/13 10:30, Aldy Hernandez wrote:
>
> 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.

Balaji:

> +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);
etc
etc

All these builtins need to be documented in doc/.

> +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
etc
etc

Can't you do all these dg-runtest's within one pair of 
dg-init/dg-finish?  Similarly for the other .exp files.

As I'd mentioned, you have .exp files named compile.exp and execute.exp 
which seem to be causing ambiguity problems in parallel checks (make 
check -jN).  For some reason, with this patch, the rest of dg.exp fails 
to run after Cilkplus' compile/execute.exp runs.  Renaming these to 
something less generic does the trick.  Do you mind prefixing all the 
.exp's with "cilkplus_" or something similar?

[Perhaps someone can pontificate as to what the actual problem is here 
and describe it.  Dejagnu is a mystery to me.]

> 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

If these are mere syntax error tests, I suggest you get rid of all the 
optimization variants.  Surely there is no need to test the error at -O, 
then at -O2, etc.  -O0 should suffice.  For that matter, you shouldn't 
pass any optimization flag and let the test itself set the flags with 
"// dg-options" or whatever in the test itself (if for some reason you 
have a test that has one particular error only reportable at some 
optimization level).

And please make sure there are no regressions on the branch when 
checking with "make check -k -jN" (N > 1) and for a plain serial check-- 
at least while we iron out this dejagnu setup.

Thanks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [cilkplus-merge] test for side effects
  2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
  2013-03-20 16:33 ` Aldy Hernandez
@ 2013-03-20 22:00 ` Aldy Hernandez
  2013-03-21 14:25 ` [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-20 22:00 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Iyer, Balaji V, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1589 bytes --]


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

Balaji:

In Joseph's review on October 19, 2012 
(http://gcc.gnu.org/ml/gcc-patches/2012-10/msg01838.html) he mentioned:

> Say expr1 through expr9 are expressions with side effects, and you have:
>
> expr1[expr2:expr3:expr4] = expr5[expr6:expr7:expr8] + expr9;
>
> The spec says "However, in such a statement, a sub-expression with rank
> zero is evaluated only once." - that is, each of the nine expressions is
> evaluated once.  I don't see any calls to save_expr to ensure these
> semantics, or any testcases that verify that they are adhered to.

If I understand Joseph's comment, this is still broken on the branch. 
For example, in the example below:

   array[func1() + 11 : func2() + 22 : func3() + 33] = 666;

...the function calls should only be called once, yet currently we generate:

   D.1739 = 0;
   <D.1740>:
   D.1769 = func2 ();
   D.1770 = D.1769 + 22;
   if (D.1739 < D.1770) goto <D.1741>; else goto <D.1742>;
   <D.1741>:
   D.1771 = func1 ();		<-- BOO HISS
   D.1772 = D.1771 + 11;
   D.1773 = func3 ();		<-- BOO HISS
   D.1774 = D.1773 + 33;
   D.1775 = D.1739 * D.1774;
   D.1776 = D.1772 + D.1775;
   array[D.1776] = 666;
   D.1739 = D.1739 + 1;
   goto <D.1740>;
   <D.1742>:

As you can see, func1() and func3() are being called repeatedly within 
the loop.

I am adding the attached execute test to the harness.  If my 
understanding is correct, this test should pass.

Joseph, please let me know if I misunderstood things in some way.

Committed to cilkplus-merge branch.

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 1022 bytes --]

commit 4447dcf380a08f74bf5b91fd84d7013cbbb34ee8
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Wed Mar 20 16:47:02 2013 -0500

    Add new test to verify that the array index, limit, and stride are
    only evaluated once.

diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/side-effects-1.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/side-effects-1.c
new file mode 100644
index 0000000..1845862
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/side-effects-1.c
@@ -0,0 +1,23 @@
+/* Test that the array index, limit, and stride are evaluated only
+   once.  */
+
+int array[1000];
+
+int func1_times = 0;
+int func2_times = 0;
+int func3_times = 0;
+int func1() { func1_times++; return 0; }
+int func2() { func2_times++; return 0; }
+int func3() { func3_times++; return 0; }
+
+int main()
+{
+  array[func1() + 11 : func2() + 22 : func3() + 33] = 666;
+
+  if (func1_times != 1
+      || func2_times != 1
+      || func3_times != 1)
+    abort();
+
+  return 0;
+}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 16:33 ` Aldy Hernandez
@ 2013-03-20 22:28   ` Iyer, Balaji V
  2013-03-21 12:55     ` Aldy Hernandez
  2013-03-21  5:31   ` Jeff Law
  1 sibling, 1 reply; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-20 22:28 UTC (permalink / raw)
  To: Aldy Hernandez, Joseph S. Myers; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4978 bytes --]

HI Aldy, Joseph et al.,
	Attached, please find a fixed patch. Please see my responses to Aldy's questions below:

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Wednesday, March 20, 2013 12:33 PM
> To: Joseph S. Myers
> Cc: Iyer, Balaji V; gcc-patches
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
> 
> On 03/20/13 10:30, Aldy Hernandez wrote:
> >
> > 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.
> 
> Balaji:
> 
> > +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);
> etc
> etc
> 
> All these builtins need to be documented in doc/.

DONE!


> 
> > +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
> etc
> etc
> 
> Can't you do all these dg-runtest's within one pair of dg-init/dg-finish?  Similarly
> for the other .exp files.

The reason why I did these is so that we can easily isolate the errors to one run if necessary. I fixed them as you requested.

> 
> As I'd mentioned, you have .exp files named compile.exp and execute.exp which
> seem to be causing ambiguity problems in parallel checks (make check -jN).  For
> some reason, with this patch, the rest of dg.exp fails to run after Cilkplus'
> compile/execute.exp runs.  Renaming these to something less generic does the
> trick.  Do you mind prefixing all the .exp's with "cilkplus_" or something similar?

FIXED! I added the "cilkplus_AN_c_" prefix to everything, where "an" stands for Array Notation . This way it won't interfere with the future Cilk Plus patches' test case.

> 
> [Perhaps someone can pontificate as to what the actual problem is here and
> describe it.  Dejagnu is a mystery to me.]
> 
> > 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
> 
> If these are mere syntax error tests, I suggest you get rid of all the optimization
> variants.  Surely there is no need to test the error at -O, then at -O2, etc.  -O0
> should suffice.  For that matter, you shouldn't pass any optimization flag and let
> the test itself set the flags with "// dg-options" or whatever in the test itself (if
> for some reason you have a test that has one particular error only reportable at
> some optimization level).

I did this purely as a safety measure for the commonly used flags that I know of. If it won't cause too much of a problem I would like to keep it.

> 
> And please make sure there are no regressions on the branch when checking
> with "make check -k -jN" (N > 1) and for a plain serial check-- at least while we
> iron out this dejagnu setup.

It works for make -j8 check on my 8 core machine.

Thanks,

Balaji V. Iyer.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 15301 bytes --]

diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 045f964..81b6502 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -125,7 +125,25 @@ 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}.
+initialize builtin functions are stored in @file{array-notation-common.c}.  In
+the current array notation implementation there are 12 builtin reduction
+operations.  Details about these functions and their usage are available in
+the Cilk Plus language specification at @w{@uref{http://www.cilkplus.org}}.
+
+@itemize @bullet
+@item __sec_reduce_add
+@item __sec_reduce_mul
+@item __sec_reduce_max
+@item __sec_reduce_min
+@item __sec_reduce_max_ind
+@item __sec_reduce_min_ind
+@item __sec_reduce_all_zero
+@item __sec_reduce_all_nonzero
+@item __sec_reduce_any_zero
+@item __sec_reduce_any_nonzero
+@item __sec_reduce
+@item __sec_reduce_mutating
+@end itemize
 @end itemize
 
 Detailed information about Cilk Plus and language specification is provided in 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
index 5fb3680..fd128b1 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
@@ -26,7 +26,7 @@ int main(int argc, char **argv)
       array[ii] = 10;
       array2[ii] = 5000000;
     }
-  array2[0:10:2] = array[0:10:2];
+  array2[0:5:2] = array[0:5:2];
 
   printf("==============================================\n");
   for (ii = 0; ii<10; ii++)
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
@@ -0,0 +1,34 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-#   Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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/cilkplus_AN_c_errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
@@ -0,0 +1,34 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-#   Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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/execute/cilkplus_AN_c_execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
new file mode 100644
index 0000000..37d22c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
@@ -0,0 +1,60 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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/execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
deleted file mode 100644
index 37d22c5..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 16:33 ` Aldy Hernandez
  2013-03-20 22:28   ` Iyer, Balaji V
@ 2013-03-21  5:31   ` Jeff Law
  2013-03-21  6:09     ` Jakub Jelinek
  1 sibling, 1 reply; 28+ messages in thread
From: Jeff Law @ 2013-03-21  5:31 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Joseph S. Myers, Iyer, Balaji V, gcc-patches

On 03/20/2013 10:33 AM, Aldy Hernandez wrote:

>
> As I'd mentioned, you have .exp files named compile.exp and execute.exp
> which seem to be causing ambiguity problems in parallel checks (make
> check -jN).  For some reason, with this patch, the rest of dg.exp fails
> to run after Cilkplus' compile/execute.exp runs.  Renaming these to
> something less generic does the trick.  Do you mind prefixing all the
> .exp's with "cilkplus_" or something similar?
>
> [Perhaps someone can pontificate as to what the actual problem is here
> and describe it.  Dejagnu is a mystery to me.]
I doubt it's anything really related to dejagnu and is more related to 
how the "make check" target is constructed in gcc/Makefile.in.  It's 
brutally ugly.

I recently had to swap in some dejagnu/tcl basics; and I did everything 
possible to forget it as soon as possible.  I'd really forgotten how 
much I hated writing tcl code.

Jeff

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21  5:31   ` Jeff Law
@ 2013-03-21  6:09     ` Jakub Jelinek
  2013-03-21 13:01       ` Aldy Hernandez
  2013-03-21 16:54       ` Mike Stump
  0 siblings, 2 replies; 28+ messages in thread
From: Jakub Jelinek @ 2013-03-21  6:09 UTC (permalink / raw)
  To: Jeff Law; +Cc: Aldy Hernandez, Joseph S. Myers, Iyer, Balaji V, gcc-patches

On Wed, Mar 20, 2013 at 11:30:58PM -0600, Jeff Law wrote:
> On 03/20/2013 10:33 AM, Aldy Hernandez wrote:
> >As I'd mentioned, you have .exp files named compile.exp and execute.exp
> >which seem to be causing ambiguity problems in parallel checks (make
> >check -jN).  For some reason, with this patch, the rest of dg.exp fails
> >to run after Cilkplus' compile/execute.exp runs.  Renaming these to
> >something less generic does the trick.  Do you mind prefixing all the
> >.exp's with "cilkplus_" or something similar?

Renaming is desirable anyway, people who run make check-gcc
execute.exp=something don't expect to run also some subset of cilk+ tests.
The Makefile runs some execute.exp=2* and similar when parallelized, see
check_gcc_parallelize in gcc/Makefile.in.
Anyway, have you tested that without parallelization make check doesn't skip
some tests?  Often when a new *.exp file say sets some globals and never
resets them, this could affect following *.exp files.

	Jakub

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 22:28   ` Iyer, Balaji V
@ 2013-03-21 12:55     ` Aldy Hernandez
  0 siblings, 0 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 12:55 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: Joseph S. Myers, gcc-patches


>> All these builtins need to be documented in doc/.
>
> DONE!

> +initialize builtin functions are stored in @file{array-notation-common.c}.  In
> +the current array notation implementation there are 12 builtin reduction
> +operations.  Details about these functions and their usage are available in
> +the Cilk Plus language specification at @w{@uref{http://www.cilkplus.org}}.
> +
> +@itemize @bullet
> +@item __sec_reduce_add
> +@item __sec_reduce_mul
> +@item __sec_reduce_max
> +@item __sec_reduce_min
> +@item __sec_reduce_max_ind

First, the common documentation idiom is "built-in" not builtin. 
Second, these should be documented in extend.texi along with the rest of 
the builtins listed there.

>> As I'd mentioned, you have .exp files named compile.exp and execute.exp which
>> seem to be causing ambiguity problems in parallel checks (make check -jN).  For
>> some reason, with this patch, the rest of dg.exp fails to run after Cilkplus'
>> compile/execute.exp runs.  Renaming these to something less generic does the
>> trick.  Do you mind prefixing all the .exp's with "cilkplus_" or something similar?
>
> FIXED! I added the "cilkplus_AN_c_" prefix to everything, where "an" stands for Array Notation . This way it won't interfere with the future Cilk Plus patches' test case.

I think eventually all the compile tests for all of cilkplus should go 
in one directory and one for the execute tests.  There is no need for a 
separate directory for the array notation, etc, etc.  For that matter, 
we should probably munge everything into one dg style directory.  But 
this is ok for now.

> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> @@ -26,7 +26,7 @@ int main(int argc, char **argv)
>        array[ii] = 10;
>        array2[ii] = 5000000;
>      }
> -  array2[0:10:2] = array[0:10:2];
> +  array2[0:5:2] = array[0:5:2];

What is this non-related change?

>> If these are mere syntax error tests, I suggest you get rid of all the optimization
>> variants.  Surely there is no need to test the error at -O, then at -O2, etc.  -O0
>> should suffice.  For that matter, you shouldn't pass any optimization flag and let
>> the test itself set the flags with "// dg-options" or whatever in the test itself (if
>> for some reason you have a test that has one particular error only reportable at
>> some optimization level).
>
> I did this purely as a safety measure for the commonly used flags that I know of. If it won't cause too much of a problem I would like to keep it.

All these errors are in the front-end, so optimization shouldn't matter. 
  It just seems like over kill to run 750 tests for just 15 individual 
.c files.  We can leave this for now.

>
>>
>> And please make sure there are no regressions on the branch when checking
>> with "make check -k -jN" (N > 1) and for a plain serial check-- at least while we
>> iron out this dejagnu setup.
>
> It works for make -j8 check on my 8 core machine.

I assume "make -j1" still works and has no regressions?

Can you repost an updated (and tested) patch?

Thanks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21  6:09     ` Jakub Jelinek
@ 2013-03-21 13:01       ` Aldy Hernandez
  2013-03-21 13:06         ` Iyer, Balaji V
  2013-03-21 16:54       ` Mike Stump
  1 sibling, 1 reply; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 13:01 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jeff Law, Joseph S. Myers, Iyer, Balaji V, gcc-patches

On 03/21/13 01:09, Jakub Jelinek wrote:
> On Wed, Mar 20, 2013 at 11:30:58PM -0600, Jeff Law wrote:
>> On 03/20/2013 10:33 AM, Aldy Hernandez wrote:
>>> As I'd mentioned, you have .exp files named compile.exp and execute.exp
>>> which seem to be causing ambiguity problems in parallel checks (make
>>> check -jN).  For some reason, with this patch, the rest of dg.exp fails
>>> to run after Cilkplus' compile/execute.exp runs.  Renaming these to
>>> something less generic does the trick.  Do you mind prefixing all the
>>> .exp's with "cilkplus_" or something similar?
>
> Renaming is desirable anyway, people who run make check-gcc
> execute.exp=something don't expect to run also some subset of cilk+ tests.
> The Makefile runs some execute.exp=2* and similar when parallelized, see
> check_gcc_parallelize in gcc/Makefile.in.

Right, that's exactly how I found the problem :).

> Anyway, have you tested that without parallelization make check doesn't skip
> some tests?  Often when a new *.exp file say sets some globals and never
> resets them, this could affect following *.exp files.

Balaji, please check the corresponding .sum files before and after your 
patch to make sure that the same number of tests are being tested.  We 
have a nifty script in contrib/compare_tests for this task.

And as Jakub has said, check (with and) without parallelization.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 13:01       ` Aldy Hernandez
@ 2013-03-21 13:06         ` Iyer, Balaji V
  2013-03-21 13:09           ` Aldy Hernandez
  0 siblings, 1 reply; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-21 13:06 UTC (permalink / raw)
  To: Aldy Hernandez, Jakub Jelinek; +Cc: Jeff Law, Joseph S. Myers, gcc-patches

> 
> Balaji, please check the corresponding .sum files before and after your patch to
> make sure that the same number of tests are being tested.  We have a nifty
> script in contrib/compare_tests for this task.

That's how I verify it. (I grep for the ^FAIL in trunk and the applied branch and make sure the output files are the same by going through it). Did I miss anything?

> 
> And as Jakub has said, check (with and) without parallelization.
> 

Yes, I am doing that also for the patch I am submitting.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 13:06         ` Iyer, Balaji V
@ 2013-03-21 13:09           ` Aldy Hernandez
  2013-03-21 13:15             ` Iyer, Balaji V
  0 siblings, 1 reply; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 13:09 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: Jakub Jelinek, Jeff Law, Joseph S. Myers, gcc-patches

On 03/21/13 08:06, Iyer, Balaji V wrote:
>>
>> Balaji, please check the corresponding .sum files before and after your patch to
>> make sure that the same number of tests are being tested.  We have a nifty
>> script in contrib/compare_tests for this task.
>
> That's how I verify it. (I grep for the ^FAIL in trunk and the applied branch and make sure the output files are the same by going through it). Did I miss anything?

If you're using compare_tests, you should be fine.  But just grepping 
for FAIL won't do because there are tests that could have passed before, 
but are no longer being tested, so they don't show up as a fail.  I 
believe compare_tests complains with "tests that used to pass but have 
disappeared" (or something similar).

>
>>
>> And as Jakub has said, check (with and) without parallelization.
>>
>
> Yes, I am doing that also for the patch I am submitting.

Thank you.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 13:09           ` Aldy Hernandez
@ 2013-03-21 13:15             ` Iyer, Balaji V
  0 siblings, 0 replies; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-21 13:15 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jakub Jelinek, Jeff Law, Joseph S. Myers, gcc-patches



> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Thursday, March 21, 2013 9:09 AM
> To: Iyer, Balaji V
> Cc: Jakub Jelinek; Jeff Law; Joseph S. Myers; gcc-patches
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
> 
> On 03/21/13 08:06, Iyer, Balaji V wrote:
> >>
> >> Balaji, please check the corresponding .sum files before and after
> >> your patch to make sure that the same number of tests are being
> >> tested.  We have a nifty script in contrib/compare_tests for this task.
> >
> > That's how I verify it. (I grep for the ^FAIL in trunk and the applied branch and
> make sure the output files are the same by going through it). Did I miss
> anything?
> 
> If you're using compare_tests, you should be fine.  But just grepping for FAIL
> won't do because there are tests that could have passed before, but are no
> longer being tested, so they don't show up as a fail.  I believe compare_tests
> complains with "tests that used to pass but have disappeared" (or something
> similar).

I first look at the expected passes, expected fails, etc. If those numbers match up, then I do what I said above . Otherwise I look at things that have failed that shouldn't and/or passed that shouldn't have (this, should almost never happen because all the Cilk plus related code are all enclosed between inside an if (flag_enable_cilkplus) statement).


> 
> >
> >>
> >> And as Jakub has said, check (with and) without parallelization.
> >>
> >
> > Yes, I am doing that also for the patch I am submitting.
> 
> Thank you.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
  2013-03-20 16:33 ` Aldy Hernandez
  2013-03-20 22:00 ` [cilkplus-merge] test for side effects Aldy Hernandez
@ 2013-03-21 14:25 ` Aldy Hernandez
  2013-03-21 19:08   ` Iyer, Balaji V
  2013-03-21 15:56 ` Joseph S. Myers
  2013-03-21 16:48 ` Joseph S. Myers
  4 siblings, 1 reply; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 14:25 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Iyer, Balaji V, gcc-patches


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

Balaji, in Joseph's last review he mentioned:

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

I see you have dispensed with the rank mismatch error altogether.  Was 
this on purpose?  For example, you now have:

>       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;

Which is basically failing to set *rank when it's already set (with no 
error).  Is this on purpose?  If so, can you explain?

If it's on purpose, document it in the comment at the top of the 
function.  And then, why don't you exit the function immediately upon 
entry if *rank is non-zero?  It's a waste of time to do the rest of the 
analysis if you're just going to throw it away.

Furthermore, Joseph suggested you store the location of the initial rank 
so you can give a meaningful error message later and tell the user where 
the mismatch is occurring and where the original rank occurred.

Aldy

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
                   ` (2 preceding siblings ...)
  2013-03-21 14:25 ` [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
@ 2013-03-21 15:56 ` Joseph S. Myers
  2013-03-22 22:04   ` Iyer, Balaji V
  2013-03-21 16:48 ` Joseph S. Myers
  4 siblings, 1 reply; 28+ messages in thread
From: Joseph S. Myers @ 2013-03-21 15:56 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Iyer, Balaji V, gcc-patches

On Wed, 20 Mar 2013, Aldy Hernandez wrote:

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

This review largely deals with coding style (interpreted broadly).  I'll 
review more of the substance separately later; reposting with fixes for 
all the accumulated issues is probably a good idea anyway, to avoid the 
same issues coming up repeatedly.

> 	* c-common.c (c_define_builtins): When cilkplus is enabled, the
> 	function array_notation_init_builtins() is called.

Don't use () after a function name when referring to the function.

> diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c

> +int extract_sec_implicit_index_arg (location_t, tree);
> +bool is_sec_implicit_index_fn (tree);
> +void array_notation_init_builtins (void);

Non-static function declarations like this should not be inside a .c file.  
If these functions are used outside this file, there should be an 
associated header that declares them; include it in the .c file.  If only 
used inside the .c file that defines them, make them static (and 
topologically sort static functions inside a source file so that forward 
static declarations are only needed for cases of recursion).

> +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is
> +   not run as is.  */

The cold attribute means unlikely to be executed rather than "not run as 
is".  Maybe "not run as is" is what's relevant here, but I'm not clear 
why this attribute would be useful for built-in functions at all - the 
documentation suggests it's only relevant when a user defines a function 
themselves, and affects the code generated for that function, so wouldn't 
be relevant at all for built-in functions.

> +void
> +array_notation_init_builtins (void)

Other built-in functions use various .def files (builtins.def and the 
files it includes) to avoid lots of repetitive code like this - can you 
integrate this with that mechanism?  If you do so, then you should be able 
to avoid (or massively simplify) functions like:

> +/* Returns true if the function call specified in FUNC_NAME is
> +   __sec_implicit_index.  */
> +
> +bool
> +is_sec_implicit_index_fn (tree func_name)

because code can use the BUILT_IN_* enum values to test whether a 
particular function is in use - which is certainly cleaner than using 
strcmp against the function name.

> +/* Returns the first and only argument for FN, which should be a
> +   sec_implicit_index function.  FN's location in the source file is is 
> +   indicated by LOCATION.  */
> +
> +int
> +extract_sec_implicit_index_arg (location_t location, tree fn)
> +{
> +  tree fn_arg;
> +  HOST_WIDE_INT return_int = 0;
> +  if (!fn)
> +    return -1;

Why the random check for a NULL argument?  If a NULL argument is valid 
(meaning that it makes the code cleaner to allow such arguments rather 
than making sure the function isn't called with them), this should be 
documented in the comment above the function; otherwise, if such an 
argument isn't valid, there is no need to check for it.

You declare return_int as HOST_WIDE_INT, but it only receives a value cast 
to int, and is used only to store a value returned as int.  Either use int 
consistently, or HOST_WIDE_INT consistently, but I don't see a reason to 
use both.

> +  if (TREE_CODE (fn) == CALL_EXPR)
> +    {
> +      fn_arg = CALL_EXPR_ARG (fn, 0);
> +      if (really_constant_p (fn_arg))

I don't think really_constant_p is what's wanted; 
<http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-Intel_Cilk_plus_lang_spec_2.htm> 
says "The argument shall be an integer constant expression.", and such 
expressions always appear in the C front end as INTEGER_CST.  So you can 
just check for INTEGER_CST.

Now a subtlety here is that the function argument will have been folded by 
this point, meaning that cases that aren't integer constant expressions in 
C standard terms will be wrongly allowed (both by the original code and by 
a version checking against INTEGER_CST).  In such cases, the way to get 
things checked correctly is to use a keyword rather than a built-in 
function - as with __builtin_choose_expr or __builtin_shuffle, for 
example.  Since this operation seems special in ways that built-in 
functions generally aren't, that seems reasonable anyway.  So the code 
parsing this keyword would check that the argument is an INTEGER_CST, of 
integer type (since INTEGER_CSTs can have pointer type in GCC), like that 
for __builtin_choose_expr does.  It would then quite likely create its own 
tree code for the operation, rather than using a CALL_EXPR at all.  (It 
would need to manage converting to int, given how the specification 
defines things in terms of a prototype for type int - so e.g. a constant 
1ULL << 32 would act like 0 if int is 32 bits, under the present 
specification.)

The specification doesn't seem very clear on to what extent the __sec_* 
operations must act like functions (what happens if someone puts 
parentheses around the __sec_* name, for example - that wouldn't work with 
the keyword approach).  So the specification should be clarified there, 
but I think saying the __sec_* operations are syntactically special, like 
keywords, is more appropriate than requiring other uses to work.

> +	return_int = (int) int_cst_value (fn_arg);
> +      else
> +	{
> +	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
> +	    location = EXPR_LOCATION (fn);
> +	  error_at (location, "__sec_implicit_index parameter must be a " 
> +		    "constant integer expression");

The term is "integer constant expression" not "constant integer 
expression".

> diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c

> +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);

As before, forward declarations inside .c files should only be for static 
functions with recursive calls to themselves, not for non-static 
functions or static functions not involved in recursion.

> +struct inv_list
> +{
> +  vec<tree, va_gc> *list_values;
> +  vec<tree, va_gc> *replacement;
> +};

Comment on this type explaining what it's for.

> +/* Returns the rank of ARRAY through the *RANK.  The user can specify whether
> +   (s)he wants to step into array_notation-specific builtin functions
> +   (specified by the IGNORE_BUILTIN_FN).

The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring 
array-notation-specific built-in functions if IGNORE_BUILTIN_FN." would be 
better.

> +void
> +find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
> +{
> +  tree ii_tree;
> +  size_t current_rank = 0, ii = 0;
> +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
> +  if (!array)
> +    return;

As before, avoid random checks for NULL parameters unless there is an 
actual reason to allow them and the comments document that they are 
allowed and what the semantics are in that case.  In general, explain what 
ARRAY is - an expression?

Is *RANK always set by this function?  Make clear in the comment above the 
function whether it is, and whether the initial value of *RANK before the 
function is called is of any significance.  I note that

> +  else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
> +    {
> +      for (ii_tree = array;
> +	   ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
> +	   ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
> +	current_rank++;
> +      if (*rank == 0)
> +	*rank = current_rank;

does appear to look at the value before the function has set it, implying 
that the original value of *RANK *does* mean something.

> +      if (TREE_CODE (array) == CALL_EXPR)
> +	{
> +	  tree func_name = CALL_EXPR_FN (array);
> +	  if (TREE_CODE (func_name) == ADDR_EXPR)
> +	    if (!ignore_builtin_fn)
> +	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
> +		/* If it is a builtin function, then we know it returns a 
> +		   scalar.  */
> +		return;
> +	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
> +	    {
> +	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
> +	      for (ii = 0; ii < (size_t) length; ii++)

TREE_INT_CST_LOW returns unsigned HOST_WIDE_INT.  There should be no need 
for converting twice, first to int and then to size_t.  And rather than 
depending on implementation default of CALL_EXPR, call_expr_nargs would be 
a better way to calculate the length.

> +		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);

But actually, you're dealing with a CALL_EXPR here.  So you should be able 
to use existing iterators over CALL_EXPR arguments (e.g. 
FOR_EACH_CALL_EXPR_ARG) rather than explicitly using the number of 
arguments at all.  Doing so, and separately checking CALL_EXPR_FN, and 
CALL_EXPR_STATIC_CHAIN if applicable, seems cleaner than depending on 
low-level details of the sequence of operands to a CALL_EXPR.

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

There's no argument LIST_SIZE, so the comment needs updating.  Again, the 
wording about "The user" is awkward; the comment should directly define 
the semantics of the function in terms of its argument, without reference 
to "The user".

> +{
> +  size_t ii = 0;
> +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
> +  
> +  if (!node)
> +    return;

Again, check for NULL argument without any mention in the comment that 
such arguments are valid; remove unless there is a reason to make them 
valid.

> +  else if (TREE_CODE (node) == TREE_LIST)

What's NODE?  My first guess would have been an expression, but if a 
TREE_LIST is possible that's clearly not the answer, so explain in the 
comment above the function what NODE is.  (If a TREE_LIST is being used 
within expressions to store something specific to array notation, don't do 
so - TREE_LIST is deprecated, existing uses should be phased out in favour 
of more specific and less memory-hungry datastructures and new uses should 
not be added.)

> +      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
> +	{
> +	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
> +
> +	  for (ii = 0; ii < (size_t) length; ii++)
> +	    extract_array_notation_exprs
> +	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);

Same problems as before with an iterator over CALL_EXPR that should avoid 
depending on low-level details of how CALL_EXPR is implemented, and excess 
integer type conversions.

> +/* Replaces all occurances of array notations in tree ORIG that matches the
> +   ones in LIST with the one in ARRAY_OPERAND.  The size of list and
> +   ARRAY_OPERAND is ARRAY_SIZE.  For example, ARRAY_OPERAND[x] for some index
> +   'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified
> +   in LIST[x].   The  user can specify if (s)he wants to ignore the array
> +   notations inside the array-notation specific builtin functions (using the
> +   bool variable IGNORE_BUILTIN_FN).  */

Again, avoid "The user".

> +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;

Again, avoid checks for NULL or document that NULL arguments are valid if 
there's a good reason.  Generally, document what sort of thing ORIG is.

> +      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
> +	{
> +	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
> +	  for (ii = 0; ii < (size_t) length; ii++)
> +	    replace_array_notations
> +	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
> +	       array_operand);

Again, better CALL_EXPR iterators.

> +/* This function will find all the scalar expressions in *TP and push it in
> +   DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 then
> +   we have do not go into the *TP's subtrees.  */

Rather than "This function will", just "Find ..." (and say "Returns 
NULL_TREE." or something like that - presumably the return type is so it 
can be passed to walk_tree).

> +/* Replaces all the scalar expressions in *NODE. */
> +
> +tree
> +replace_invariant_exprs (tree *node)

Comment needs to explain the semantics of the return value.

> +tree
> +build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
> +			   enum tree_code modifycode, location_t rhs_loc,
> +			   tree rhs, tree rhs_origtype)

> +    }
> +
> +
> +
> +  for (ii = 0; ii < lhs_rank; ii++)

Excess blank lines in middle of function.  Generally there shouldn't be 
two or more consecutive blank lines inside a function (if you want to have 
different sizes of blanks to split up levels of structure in the function, 
that suggests the function is too big and should be split up into separate 
functions).

> +	     TREE_TYPE (lhs_var[ii]));
> +	  
> +	}

This location for a blank line doesn't make sense.

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

Comments should not have an initial "*" on each line.

> +/* Encloses the conditional statement passed in STMT with a loop around it
> +   and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
> +   The condition must have a ARRAY_NOTATION_REF tree.  */
> +
> +static tree
> +fix_conditional_array_notations_1 (tree stmt)

Comment should explain return value semantics.

> +			   TREE_TYPE (array_var[ii]));
> +	
> +    }

Another stray blank line.  Check the patch generally for stray blank lines 
immediately before a '}', I don't think they ever make sense, but I may 
have missed some.

> +  // XDELETEVEC (array_var);

I don't think this sort of commented-out code should be added.  If you're 
deliberately not doing something that a reader might expect to be done, 
have a comment explaining *why* you're not doing it, not just 
commented-out code to do it.

> +      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
> +		" have arrays with dimension greater than 1.");

Diagnostics don't end with ".".

> +    default:
> +      gcc_unreachable ();  /* You should not reach here.  */

No need for comments like this that just repeat the plain semantics of the 
C code.  There's nothing else a call to gcc_unreachable could possibly 
mean; such a comment is of no more use than "i++; /* Add 1 to i.  */".

> +/* Returns true of FUNC_NAME is a builtin array notation function.  The type of
> +   function is returned in *TYPE.  */

"true if", not "true of".

> +bool
> +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
> +{
> +  const char *function_name = NULL;
> +
> +  if (!func_name)
> +    return false;

Another unexplained test for a NULL argument.  Again, explain what sort of 
things FUNC_NAME may be.  (This is another function that should be using 
BUILT_IN_* enum values rather than strcmp, if you rework how the built-in 
functions are implemented.)

> +/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */

"true if", again.

> +/* Replaces array notations in void function call arguments in ARG with loop and
> +   tree-node ARRAY_REF and returns that value in a tree node variable called
> +   LOOP.  */

LOOP is not an argument to this function, so it doesn't make sense to 
refer to it in the comment.  I suspect " in a tree node variable called 
LOOP" should simply be removed.

> +  if (TREE_CODE (arg) == CALL_EXPR
> +      && is_builtin_array_notation_fn (CALL_EXPR_FN (arg), &an_type))
> +    {
> +      loop = fix_builtin_array_notation_fn (arg, &new_var);
> +      /* We are ignoring the new var because either the user does not want to
> +	 capture it OR he is using sec_reduce_mutating function.  */

In general I think "the user" comments should be avoided though this one 
is a bit less awkward than those defining function semantics by reference 
to "the user".

> +/* Walks through tree node T and find all the call-statments that do not return
> +   anything and fix up any array notations they may carry.  */
> +
> +tree
> +expand_array_notation_exprs (tree t)

Comment should document return value.

> +{
> +  if (!t || !contains_array_notation_expr (t))
> +    return t;

Another check for NULL without a comment saying NULL is a valid argument.

> +/* Returns array notation expression for the array base ARRAY of type TYPE,
> +   with start index, length and stride given by START_INDEX, LENGTH and STRIDE,
> +   respectively.  */
> +
> +tree
> +build_array_notation_ref (location_t loc, tree array, tree start_index, 
> +			  tree length, tree stride, tree type)
> +{
> +  tree array_ntn_tree = NULL_TREE;
> +  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
> +  
> +  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))

I'd expect the argument would have to be an expression, so would always 
have a TYPE and the !TREE_TYPE (start_index) check should be unnecessary.  
If it is needed, explain further in the comment at the start of the 
function.  Likewise for other checks for NULL types in this function.

> +    {
> +      error_at (loc,
> +		"start-index of array notation triplet is not an integer.");

Diagnostic should not end with ".".

> +      error_at (loc, "length of array notation triplet is not an integer.");

Likewise.

> +      error_at (loc, "stride of array notation triplet is not an integer.");

Likewise.

> +      error_at (loc, "rank of an array notation triplet's start-index is not "
> +		"zero.");

Likewise.

> +      error_at (loc, "rank of an array notation triplet's length is not zero.");

Likewise.

> +      error_at (loc, "rank of array notation triplet's stride is not zero.");

Likewise.

That's a coding style review of the first half or so of the patch, more 
later....

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
                   ` (3 preceding siblings ...)
  2013-03-21 15:56 ` Joseph S. Myers
@ 2013-03-21 16:48 ` Joseph S. Myers
  4 siblings, 0 replies; 28+ messages in thread
From: Joseph S. Myers @ 2013-03-21 16:48 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Iyer, Balaji V, gcc-patches

Continuing the review for coding style...

> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c

> +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);

Again, include appropriate headers; no extern function declarations like 
this in .c files.

> +	      error_at (c_parser_peek_token (parser)->location,
> +			"array notations cannot be used in declaration.");

No "." at end of diagnostic.

> +	  error_at (c_parser_peek_token (parser)->location,
> +		    "array notations cannot be used in declaration.");

Likewise.

> +		  error_at (loc, "array notations cannot be used in a "
> +			    "condition for a for-loop.");

Likewise.

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

Can NULL actually occur here?

> +  token = c_parser_peek_token (parser);
> +   
> +  if (token == NULL)

c_parser_peek_token can never return NULL (EOF is a CPP_EOF token).

> +	      error_at (loc, "start-index and length fields necessary for "
> +			"using array notations in pointers.");

No "." at end of diagnostic.

> +	      error_at (loc, "array notations cannot be used with function "
> +			"type.");

Likewise.

> +		      error_at (loc, "array notations cannot be used with "
> +				"function pointer arrays.");

Likewise.

> +	      error_at (loc, "start-index and length fields necessary for "
> +			"using array notations in dimensionless arrays.");

Likewise.

> +	      error_at (loc, "start-index and length fields necessary for "
> +			"using array notations in variable-length arrays.");

Likewise.

> +	      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++;

If you want to increment a double_int value, use operator ++ on the 
double_int itself; don't just change the low part and ignore possible 
overflow.

> +	      error_at (loc, "array notations cannot be used with function "
> +			"type.");

No "." at end of diagnostic.

> +		      error_at (loc, "array notations cannot be used with "
> +				"function pointer arrays.");

Likewise.

> 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);

Include headers, don't add extern function declarations in .c files.

> @@ -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;
> -
> +  

Don't change a blank line by adding trailing whitespace to it.

> +	  error_at (loc, "rank of the array's index is greater than 1.");

No "." at end of diagnostic.

> +      if (flag_enable_cilkplus && name
> +	  && !strncmp (IDENTIFIER_POINTER (name), "__sec_reduce", 12))

Should replace by something cleaner than examining the name, once the way 
these built-ins are implemented has been changed to have enum values.

> +      if (flag_enable_cilkplus && fundecl && DECL_NAME (fundecl)
> +	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fundecl)),
> +		       "__sec_reduce", 12))

Likewise.

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

Likewise.

> @@ -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;

Avoid spurious changes like this not related to the substance of the 
patch.

> +  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;

Use %' for English apostrophes in diagnostics, so that a proper apostrophe 
rather than neutral vertical ' can be used in appropriate locales.

> +      error_at (start_locus, "array notation expression cannot be used in a "
> +		"loop's increment expression.");

Likewise, and remove the trailing ".".

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21  6:09     ` Jakub Jelinek
  2013-03-21 13:01       ` Aldy Hernandez
@ 2013-03-21 16:54       ` Mike Stump
  2013-03-21 23:34         ` Aldy Hernandez
  1 sibling, 1 reply; 28+ messages in thread
From: Mike Stump @ 2013-03-21 16:54 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jeff Law, Aldy Hernandez, Joseph S. Myers, Iyer, Balaji V, gcc-patches

On Mar 20, 2013, at 11:09 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Mar 20, 2013 at 11:30:58PM -0600, Jeff Law wrote:
>> On 03/20/2013 10:33 AM, Aldy Hernandez wrote:
>>> As I'd mentioned, you have .exp files named compile.exp and execute.exp
>>> which seem to be causing ambiguity problems in parallel checks (make
>>> check -jN).  For some reason, with this patch, the rest of dg.exp fails
>>> to run after Cilkplus' compile/execute.exp runs.  Renaming these to
>>> something less generic does the trick.  Do you mind prefixing all the
>>> .exp's with "cilkplus_" or something similar?
> 
> Renaming is desirable anyway,

So, the problem that causes it to not work needs to be fixed, before the patches go in.  Renaming is a form of bug pushing and that can't be used to fix the problem.  When the underlying problem is fixed, then rename, not before.  The problem is that the entire sanity of the test suite depends critically on resetting the environment to be back the way it was upon the finishing of any particular .exp.  You can run with -v -v -v -v and see check differences in the output, it might let you narrow down the issue.  You can run env (or parry env) before and after, and quickly see if it is due to an environment variable.  In theory, you can have tcl dump all the variables from the symbol tables, (info locals and info globals being the starting point)… but you'd need to differentiate between the variables that must be the same, and the variables that can be different.  One might be able to turn on tracing to find it, though, that can make your eyes bleed.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 14:25 ` [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
@ 2013-03-21 19:08   ` Iyer, Balaji V
  2013-03-21 23:30     ` Aldy Hernandez
  0 siblings, 1 reply; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-21 19:08 UTC (permalink / raw)
  To: Aldy Hernandez, Joseph S. Myers; +Cc: gcc-patches

Please see my response below:

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Thursday, March 21, 2013 10:25 AM
> To: Joseph S. Myers
> Cc: Iyer, Balaji V; gcc-patches
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
> 
> 
> > I have found some little nits that I will point out in a reply to this
> > message.
> 
> Balaji, in Joseph's last review he mentioned:
> 
> > In find_rank you have error ("Rank Mismatch!"); - this is not a
> > properly formatted error message according to the GNU Coding standards
> > (which typically would not have any uppercase).  I'd also suggest that
> > when you find a rank, you store (through a location_t * pointer) the
> > location of the first expression found with that rank, so if you then
> > find a mismatching rank you can use error_at to point to that rank and
> > then inform to point to the previous rank it didn't match.
> 
> I see you have dispensed with the rank mismatch error altogether.  Was this on
> purpose?  For example, you now have:
> 
> >       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;
> 
> Which is basically failing to set *rank when it's already set (with no error).  Is this
> on purpose?  If so, can you explain?
> 
> If it's on purpose, document it in the comment at the top of the function.  And
> then, why don't you exit the function immediately upon entry if *rank is non-
> zero?  It's a waste of time to do the rest of the analysis if you're just going to
> throw it away.
> 
> Furthermore, Joseph suggested you store the location of the initial rank so you
> can give a meaningful error message later and tell the user where the mismatch
> is occurring and where the original rank occurred.

I believe I have done what Joseph mentioned. If you would look at line 473 c-array-notation.c it mentions when LHS is scalar while RHS is not (which is unacceptable). Also, if they both have array notations and there is a rank mismatch, then it is pointed out in line 490 of c-array-notation.c. 

> 
> Aldy

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 19:08   ` Iyer, Balaji V
@ 2013-03-21 23:30     ` Aldy Hernandez
  0 siblings, 0 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 23:30 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: Joseph S. Myers, gcc-patches

On 03/21/13 14:07, Iyer, Balaji V wrote:
> Please see my response below:
>
>> -----Original Message-----
>> From: Aldy Hernandez [mailto:aldyh@redhat.com]
>> Sent: Thursday, March 21, 2013 10:25 AM
>> To: Joseph S. Myers
>> Cc: Iyer, Balaji V; gcc-patches
>> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
>> take 1)
>>
>>
>>> I have found some little nits that I will point out in a reply to this
>>> message.
>>
>> Balaji, in Joseph's last review he mentioned:
>>
>>> In find_rank you have error ("Rank Mismatch!"); - this is not a
>>> properly formatted error message according to the GNU Coding standards
>>> (which typically would not have any uppercase).  I'd also suggest that
>>> when you find a rank, you store (through a location_t * pointer) the
>>> location of the first expression found with that rank, so if you then
>>> find a mismatching rank you can use error_at to point to that rank and
>>> then inform to point to the previous rank it didn't match.
>>
>> I see you have dispensed with the rank mismatch error altogether.  Was this on
>> purpose?  For example, you now have:
>>
>>>        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;
>>
>> Which is basically failing to set *rank when it's already set (with no error).  Is this
>> on purpose?  If so, can you explain?
>>
>> If it's on purpose, document it in the comment at the top of the function.  And
>> then, why don't you exit the function immediately upon entry if *rank is non-
>> zero?  It's a waste of time to do the rest of the analysis if you're just going to
>> throw it away.
>>
>> Furthermore, Joseph suggested you store the location of the initial rank so you
>> can give a meaningful error message later and tell the user where the mismatch
>> is occurring and where the original rank occurred.
>
> I believe I have done what Joseph mentioned. If you would look at line 473 c-array-notation.c it mentions when LHS is scalar while RHS is not (which is unacceptable). Also, if they both have array notations and there is a rank mismatch, then it is pointed out in line 490 of c-array-notation.c.

I see.  You have moved the diagnostic to the caller.

However, you still have not saved the location_t for giving a better 
diagnostic.  Don't worry.  I'll put this in a laundry list I'm going to 
keep in the wiki so we don't loose track of things.  I'll take this one.

Also, if you're only setting *rank if it's previously 0, why not exit if 
*rank==0 upon entry?

Aldy

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 16:54       ` Mike Stump
@ 2013-03-21 23:34         ` Aldy Hernandez
  2013-03-22 22:36           ` Mike Stump
  0 siblings, 1 reply; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-21 23:34 UTC (permalink / raw)
  To: Mike Stump
  Cc: Jakub Jelinek, Jeff Law, Joseph S. Myers, Iyer, Balaji V, gcc-patches

On 03/21/13 11:54, Mike Stump wrote:
> On Mar 20, 2013, at 11:09 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Wed, Mar 20, 2013 at 11:30:58PM -0600, Jeff Law wrote:
>>> On 03/20/2013 10:33 AM, Aldy Hernandez wrote:
>>>> As I'd mentioned, you have .exp files named compile.exp and execute.exp
>>>> which seem to be causing ambiguity problems in parallel checks (make
>>>> check -jN).  For some reason, with this patch, the rest of dg.exp fails
>>>> to run after Cilkplus' compile/execute.exp runs.  Renaming these to
>>>> something less generic does the trick.  Do you mind prefixing all the
>>>> .exp's with "cilkplus_" or something similar?
>>
>> Renaming is desirable anyway,
>
> So, the problem that causes it to not work needs to be fixed, before the patches go in.  Renaming is a form of bug pushing and that can't be used to fix the problem.  When the underlying problem is fixed, then rename, not before.  The problem is that the entire sanity of the test suite depends critically on resetting the environment to be back the way it was upon the finishing of any particular .exp.  You can run with -v -v -v -v and see check differences in the output, it might let you narrow down the issue.  You can run env (or parry env) before and after, and quickly see if it is due to an environment variable.  In theory, you can have tcl dump all the variables from the symbol tables, (info locals and info globals being the starting point)Â… but you'd need to differentiate between the variables that must be the same, and the variables that can be different.  One might be able to turn on tracing to find it, though, that can make your eyes bleed.

I can look into this later on, but this problem happened even when I 
replaced cilkplus' compile.exp, errors.exp, and execute.exp into just an 
"exit".  So it seems unrelated to the cilk patchset.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 15:56 ` Joseph S. Myers
@ 2013-03-22 22:04   ` Iyer, Balaji V
  2013-03-25 16:45     ` Aldy Hernandez
  2013-03-26 16:27     ` Joseph S. Myers
  0 siblings, 2 replies; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-22 22:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: aldyh, Joseph Myers [joseph@codesourcery.com]

[-- Attachment #1: Type: text/plain, Size: 23279 bytes --]

Attached, please find a patch that should be applied to the head of cilkplus-merge. 
This patch is generated by diffing with the following hash: 4f4932be8230284919d197cccb4b10201f82a0b3

This patch also adds documentation about the built-in reduction funtions of array notations that Aldy pointed out in a previous email.

I have not fixed all the issues below (the big one that is left is the bultin function representation that Joseph Pointed out). I have fixed most of the other issues. All the things I have fixed are marked by "FIXED!"

Is this Ok to commit into cilkplus-merge?

Thanks,

Balaji V. Iyer.


> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Joseph S. Myers
> Sent: Thursday, March 21, 2013 11:56 AM
> To: Aldy Hernandez
> Cc: Iyer, Balaji V; gcc-patches
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
> 
> On Wed, 20 Mar 2013, Aldy Hernandez wrote:
> 
> > Joseph, folks, et al... How does this look?
> 
> This review largely deals with coding style (interpreted broadly).  I'll review more
> of the substance separately later; reposting with fixes for all the accumulated
> issues is probably a good idea anyway, to avoid the same issues coming up
> repeatedly.
> 
> > 	* c-common.c (c_define_builtins): When cilkplus is enabled, the
> > 	function array_notation_init_builtins() is called.
> 
> Don't use () after a function name when referring to the function.

FIXED!

> 
> > diff --git a/gcc/c-family/array-notation-common.c
> > b/gcc/c-family/array-notation-common.c
> 
> > +int extract_sec_implicit_index_arg (location_t, tree); bool
> > +is_sec_implicit_index_fn (tree); void array_notation_init_builtins
> > +(void);

FIXED!

> 
> Non-static function declarations like this should not be inside a .c file.
> If these functions are used outside this file, there should be an associated
> header that declares them; include it in the .c file.  If only used inside the .c file
> that defines them, make them static (and topologically sort static functions
> inside a source file so that forward static declarations are only needed for cases
> of recursion).
> 
> > +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL
> is
> > +   not run as is.  */
> 
> The cold attribute means unlikely to be executed rather than "not run as is".
> Maybe "not run as is" is what's relevant here, but I'm not clear why this attribute
> would be useful for built-in functions at all - the documentation suggests it's
> only relevant when a user defines a function themselves, and affects the code
> generated for that function, so wouldn't be relevant at all for built-in functions.
> 
> > +void
> > +array_notation_init_builtins (void)
> 
> Other built-in functions use various .def files (builtins.def and the files it includes)
> to avoid lots of repetitive code like this - can you integrate this with that
> mechanism?  If you do so, then you should be able to avoid (or massively
> simplify) functions like:
> 
> > +/* Returns true if the function call specified in FUNC_NAME is
> > +   __sec_implicit_index.  */
> > +
> > +bool
> > +is_sec_implicit_index_fn (tree func_name)
> 
> because code can use the BUILT_IN_* enum values to test whether a particular
> function is in use - which is certainly cleaner than using strcmp against the
> function name.
> 
> > +/* Returns the first and only argument for FN, which should be a
> > +   sec_implicit_index function.  FN's location in the source file is is
> > +   indicated by LOCATION.  */
> > +
> > +int
> > +extract_sec_implicit_index_arg (location_t location, tree fn) {
> > +  tree fn_arg;
> > +  HOST_WIDE_INT return_int = 0;
> > +  if (!fn)
> > +    return -1;
> 
> Why the random check for a NULL argument?  If a NULL argument is valid
> (meaning that it makes the code cleaner to allow such arguments rather than
> making sure the function isn't called with them), this should be documented in
> the comment above the function; otherwise, if such an argument isn't valid,
> there is no need to check for it.

I always tend to check for a null pointer before I access the fields in the structure. In this case it is unnecessary. In some cases (e.g. find_rank) there is a good chance a null pointer will be passed into the function and we need to check that and reject those.

> 
> You declare return_int as HOST_WIDE_INT, but it only receives a value cast to
> int, and is used only to store a value returned as int.  Either use int consistently,
> or HOST_WIDE_INT consistently, but I don't see a reason to use both.

FIXED!

> 
> > +  if (TREE_CODE (fn) == CALL_EXPR)
> > +    {
> > +      fn_arg = CALL_EXPR_ARG (fn, 0);
> > +      if (really_constant_p (fn_arg))
> 
> I don't think really_constant_p is what's wanted;
> <http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
> Intel_Cilk_plus_lang_spec_2.htm>
> says "The argument shall be an integer constant expression.", and such
> expressions always appear in the C front end as INTEGER_CST.  So you can just
> check for INTEGER_CST.

What about C++? This function is shared by both C and C++.

> 
> Now a subtlety here is that the function argument will have been folded by this
> point, meaning that cases that aren't integer constant expressions in C standard
> terms will be wrongly allowed (both by the original code and by a version
> checking against INTEGER_CST).  In such cases, the way to get things checked
> correctly is to use a keyword rather than a built-in function - as with
> __builtin_choose_expr or __builtin_shuffle, for example.  Since this operation
> seems special in ways that built-in functions generally aren't, that seems
> reasonable anyway.  So the code parsing this keyword would check that the
> argument is an INTEGER_CST, of integer type (since INTEGER_CSTs can have
> pointer type in GCC), like that for __builtin_choose_expr does.  It would then
> quite likely create its own tree code for the operation, rather than using a
> CALL_EXPR at all.  (It would need to manage converting to int, given how the
> specification defines things in terms of a prototype for type int - so e.g. a
> constant 1ULL << 32 would act like 0 if int is 32 bits, under the present
> specification.)
> 
> The specification doesn't seem very clear on to what extent the __sec_*
> operations must act like functions (what happens if someone puts parentheses
> around the __sec_* name, for example - that wouldn't work with the keyword
> approach).  So the specification should be clarified there, but I think saying the
> __sec_* operations are syntactically special, like keywords, is more appropriate
> than requiring other uses to work.
> 
> > +	return_int = (int) int_cst_value (fn_arg);
> > +      else
> > +	{
> > +	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
> > +	    location = EXPR_LOCATION (fn);
> > +	  error_at (location, "__sec_implicit_index parameter must be a "
> > +		    "constant integer expression");
> 
> The term is "integer constant expression" not "constant integer expression".

FIXED!

> 
> > diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
> 
> > +void replace_array_notations (tree *, bool, vec<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);
> 
> As before, forward declarations inside .c files should only be for static functions
> with recursive calls to themselves, not for non-static functions or static
> functions not involved in recursion.

FIXED!

> 
> > +struct inv_list
> > +{
> > +  vec<tree, va_gc> *list_values;
> > +  vec<tree, va_gc> *replacement;
> > +};
> 
> Comment on this type explaining what it's for.

FIXED!

> 
> > +/* Returns the rank of ARRAY through the *RANK.  The user can specify
> whether
> > +   (s)he wants to step into array_notation-specific builtin functions
> > +   (specified by the IGNORE_BUILTIN_FN).
> 
> The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring array-
> notation-specific built-in functions if IGNORE_BUILTIN_FN." would be better.

Yes, I agree with your wording. Thanks! and FIXED!

> 
> > +void
> > +find_rank (tree array, bool ignore_builtin_fn, size_t *rank) {
> > +  tree ii_tree;
> > +  size_t current_rank = 0, ii = 0;
> > +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > +  if (!array)
> > +    return;
> 
> As before, avoid random checks for NULL parameters unless there is an actual
> reason to allow them and the comments document that they are allowed and
> what the semantics are in that case.  In general, explain what ARRAY is - an
> expression?

This check is necessary. Find rank can get a NULL pointer and that must be caught and rejected.

> 
> Is *RANK always set by this function?  Make clear in the comment above the
> function whether it is, and whether the initial value of *RANK before the
> function is called is of any significance.  I note that
> 
> > +  else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
> > +    {
> > +      for (ii_tree = array;
> > +	   ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
> > +	   ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
> > +	current_rank++;
> > +      if (*rank == 0)
> > +	*rank = current_rank;
> 
> does appear to look at the value before the function has set it, implying that the
> original value of *RANK *does* mean something.

FIXED! I looked this way due to an artifact of a previous implementation. It looks a little bit more cleaner now.

> 
> > +      if (TREE_CODE (array) == CALL_EXPR)
> > +	{
> > +	  tree func_name = CALL_EXPR_FN (array);
> > +	  if (TREE_CODE (func_name) == ADDR_EXPR)
> > +	    if (!ignore_builtin_fn)
> > +	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
> > +		/* If it is a builtin function, then we know it returns a
> > +		   scalar.  */
> > +		return;
> > +	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
> > +	    {
> > +	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
> > +	      for (ii = 0; ii < (size_t) length; ii++)
> 
> TREE_INT_CST_LOW returns unsigned HOST_WIDE_INT.  There should be no
> need for converting twice, first to int and then to size_t.  And rather than
> depending on implementation default of CALL_EXPR, call_expr_nargs would be
> a better way to calculate the length.
> 
> > +		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
> 
> But actually, you're dealing with a CALL_EXPR here.  So you should be able to
> use existing iterators over CALL_EXPR arguments (e.g.
> FOR_EACH_CALL_EXPR_ARG) rather than explicitly using the number of
> arguments at all.  Doing so, and separately checking CALL_EXPR_FN, and
> CALL_EXPR_STATIC_CHAIN if applicable, seems cleaner than depending on low-
> level details of the sequence of operands to a CALL_EXPR.

FIXED! (I used your suggestion and used FOR_EACH_CALL_EXPR_ARG)


> 
> > +/* Extracts all the array notations specified in NODE and stores them in a
> > +   dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE.  The
> > +   user can specify if (s)he wants to ignore the array notations inside the
> > +   array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
> > +   true).  */
> > +
> > +void
> > +extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
> > +			      vec<tree, va_gc> **array_list)
> 
> There's no argument LIST_SIZE, so the comment needs updating.  Again, the
> wording about "The user" is awkward; the comment should directly define the
> semantics of the function in terms of its argument, without reference to "The
> user".

FIXED! Reworded the comment.

> 
> > +{
> > +  size_t ii = 0;
> > +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > +
> > +  if (!node)
> > +    return;
> 
> Again, check for NULL argument without any mention in the comment that such
> arguments are valid; remove unless there is a reason to make them valid.
> 
> > +  else if (TREE_CODE (node) == TREE_LIST)
> 
> What's NODE?  My first guess would have been an expression, but if a TREE_LIST
> is possible that's clearly not the answer, so explain in the comment above the
> function what NODE is.  (If a TREE_LIST is being used within expressions to store
> something specific to array notation, don't do so - TREE_LIST is deprecated,
> existing uses should be phased out in favour of more specific and less memory-
> hungry datastructures and new uses should not be added.)

FIXED! What is replacing tree-list? I have used tree-list in my later patches and in my Cilk Plus branch.

> 
> > +      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
> > +	{
> > +	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
> > +
> > +	  for (ii = 0; ii < (size_t) length; ii++)
> > +	    extract_array_notation_exprs
> > +	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
> 
> Same problems as before with an iterator over CALL_EXPR that should avoid
> depending on low-level details of how CALL_EXPR is implemented, and excess
> integer type conversions.

FIXED!

> 
> > +/* Replaces all occurances of array notations in tree ORIG that matches the
> > +   ones in LIST with the one in ARRAY_OPERAND.  The size of list and
> > +   ARRAY_OPERAND is ARRAY_SIZE.  For example, ARRAY_OPERAND[x] for
> some index
> > +   'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF
> specified
> > +   in LIST[x].   The  user can specify if (s)he wants to ignore the array
> > +   notations inside the array-notation specific builtin functions (using the
> > +   bool variable IGNORE_BUILTIN_FN).  */
> 
> Again, avoid "The user".

FIXED!

> 
> > +void
> > +replace_array_notations (tree *orig, bool ignore_builtin_fn,
> > +			 vec<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;

This ORIG must be checked for NULL because you will step this function even if the node is NULL. This is the spot to check that.

> 
> Again, avoid checks for NULL or document that NULL arguments are valid if
> there's a good reason.  Generally, document what sort of thing ORIG is.
> 
> > +      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
> > +	{
> > +	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
> > +	  for (ii = 0; ii < (size_t) length; ii++)
> > +	    replace_array_notations
> > +	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
> > +	       array_operand);
> 
> Again, better CALL_EXPR iterators.

FIXED!

> 
> > +/* This function will find all the scalar expressions in *TP and push it in
> > +   DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 then
> > +   we have do not go into the *TP's subtrees.  */
> 
> Rather than "This function will", just "Find ..." (and say "Returns NULL_TREE." or
> something like that - presumably the return type is so it can be passed to
> walk_tree).
> 
> > +/* Replaces all the scalar expressions in *NODE. */
> > +
> > +tree
> > +replace_invariant_exprs (tree *node)
> 
> Comment needs to explain the semantics of the return value.

FIXED! 

> 
> > +tree
> > +build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
> > +			   enum tree_code modifycode, location_t rhs_loc,
> > +			   tree rhs, tree rhs_origtype)
> 
> > +    }
> > +
> > +
> > +
> > +  for (ii = 0; ii < lhs_rank; ii++)
> 
> Excess blank lines in middle of function.  Generally there shouldn't be two or
> more consecutive blank lines inside a function (if you want to have different
> sizes of blanks to split up levels of structure in the function, that suggests the
> function is too big and should be split up into separate functions).

FIXED!

> 
> > +	     TREE_TYPE (lhs_var[ii]));
> > +
> > +	}
> 
> This location for a blank line doesn't make sense.

FIXED!

> 
> > +  /* The following statements will do the following:
> > +   * <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>
> > +   */
> 
> Comments should not have an initial "*" on each line.

FIXED!

> 
> > +/* Encloses the conditional statement passed in STMT with a loop around it
> > +   and replaces the condition in STMT with a ARRAY_REF tree-node to the
> array.
> > +   The condition must have a ARRAY_NOTATION_REF tree.  */
> > +
> > +static tree
> > +fix_conditional_array_notations_1 (tree stmt)
> 
> Comment should explain return value semantics.

FIXED!

> 
> > +			   TREE_TYPE (array_var[ii]));
> > +
> > +    }
> 
> Another stray blank line.  Check the patch generally for stray blank lines
> immediately before a '}', I don't think they ever make sense, but I may have
> missed some.

I think I have caught all of it. I apologize if I missed any.

> 
> > +  // XDELETEVEC (array_var);
> 
> I don't think this sort of commented-out code should be added.  If you're
> deliberately not doing something that a reader might expect to be done, have a
> comment explaining *why* you're not doing it, not just commented-out code to
> do it.

FIXED!

> 
> > +      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind
> cannot"
> > +		" have arrays with dimension greater than 1.");
> 
> Diagnostics don't end with ".".
> 
> > +    default:
> > +      gcc_unreachable ();  /* You should not reach here.  */
> 
> No need for comments like this that just repeat the plain semantics of the C
> code.  There's nothing else a call to gcc_unreachable could possibly mean; such
> a comment is of no more use than "i++; /* Add 1 to i.  */".

FIXED!

> 
> > +/* Returns true of FUNC_NAME is a builtin array notation function.  The type
> of
> > +   function is returned in *TYPE.  */
> 
> "true if", not "true of".
> 

FIXED! Sorry for this stupid mistake.

> > +bool
> > +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) {
> > +  const char *function_name = NULL;
> > +
> > +  if (!func_name)
> > +    return false;
> 
> Another unexplained test for a NULL argument.  Again, explain what sort of
> things FUNC_NAME may be.  (This is another function that should be using
> BUILT_IN_* enum values rather than strcmp, if you rework how the built-in
> functions are implemented.)
> 
> > +/* Returns true of EXPR (and its subtrees) contain
> > +ARRAY_NOTATION_EXPR node.  */
> 
> "true if", again.

FIXED!


> 
> > +/* Replaces array notations in void function call arguments in ARG with loop
> and
> > +   tree-node ARRAY_REF and returns that value in a tree node variable called
> > +   LOOP.  */
> 
> LOOP is not an argument to this function, so it doesn't make sense to refer to it
> in the comment.  I suspect " in a tree node variable called LOOP" should simply
> be removed.

FIXED!

> 
> > +  if (TREE_CODE (arg) == CALL_EXPR
> > +      && is_builtin_array_notation_fn (CALL_EXPR_FN (arg), &an_type))
> > +    {
> > +      loop = fix_builtin_array_notation_fn (arg, &new_var);
> > +      /* We are ignoring the new var because either the user does not want to
> > +	 capture it OR he is using sec_reduce_mutating function.  */
> 
> In general I think "the user" comments should be avoided though this one is a bit
> less awkward than those defining function semantics by reference to "the user".
> 
> > +/* Walks through tree node T and find all the call-statments that do not
> return
> > +   anything and fix up any array notations they may carry.  */
> > +
> > +tree
> > +expand_array_notation_exprs (tree t)
> 
> Comment should document return value.

FIXED!

> 
> > +{
> > +  if (!t || !contains_array_notation_expr (t))
> > +    return t;
> 
> Another check for NULL without a comment saying NULL is a valid argument.

This function also can receive a null pointer.

> 
> > +/* Returns array notation expression for the array base ARRAY of type TYPE,
> > +   with start index, length and stride given by START_INDEX, LENGTH and
> STRIDE,
> > +   respectively.  */
> > +
> > +tree
> > +build_array_notation_ref (location_t loc, tree array, tree start_index,
> > +			  tree length, tree stride, tree type) {
> > +  tree array_ntn_tree = NULL_TREE;
> > +  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
> > +
> > +  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE
> > + (start_index)))
> 
> I'd expect the argument would have to be an expression, so would always have
> a TYPE and the !TREE_TYPE (start_index) check should be unnecessary.
> If it is needed, explain further in the comment at the start of the function.
> Likewise for other checks for NULL types in this function.

FIXED! But Stride could easily be NULL, (e.g. array[0:10]) and in this case we have put one in. So, I have left that check in.
> 
> > +    {
> > +      error_at (loc,
> > +		"start-index of array notation triplet is not an integer.");
> 
> Diagnostic should not end with ".".

FIXED!

> 
> > +      error_at (loc, "length of array notation triplet is not an
> > + integer.");
> 
> Likewise.

FIXED!

> 
> > +      error_at (loc, "stride of array notation triplet is not an
> > + integer.");
> 
> Likewise.

FIXED!

> 
> > +      error_at (loc, "rank of an array notation triplet's start-index is not "
> > +		"zero.");
> 
> Likewise.

FIXED!

> 
> > +      error_at (loc, "rank of an array notation triplet's length is
> > + not zero.");
> 
> Likewise.

FIXED!

> 
> > +      error_at (loc, "rank of array notation triplet's stride is not
> > + zero.");
> 
> Likewise.

FIXED!

> 
> That's a coding style review of the first half or so of the patch, more later....

Thanks for reviewing my code!

-Balaji V. Iyer.

> 
> --
> Joseph S. Myers
> joseph@codesourcery.com

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 66497 bytes --]

diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
index 6591fd1..10db29b 100644
--- a/gcc/c-family/ChangeLog.cilkplus
+++ b/gcc/c-family/ChangeLog.cilkplus
@@ -1,7 +1,11 @@
+2013-03-22  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-pretty-print.c (pp_c_expression): Added ARRAY_NOTATION_REF case.
+
 2013-03-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* c-common.c (c_define_builtins): When cilkplus is enabled, the
-	function array_notation_init_builtins() is called.
+	function array_notation_init_builtins is called.
 	(c_common_init_ts): Added ARRAY_NOTATION_REF as typed.
 	* c-common.def (ARRAY_NOTATION_REF): New tree.
 	* c-common.h (build_array_notation_expr): New function declaration.
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 7089c8e..b775225 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -29,19 +29,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-iterator.h"
 #include "diagnostic-core.h"
 
-int extract_sec_implicit_index_arg (location_t, tree);
-bool is_sec_implicit_index_fn (tree);
-void array_notation_init_builtins (void);
-
-/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is
-   not run as is.  */
-
-static void
-mark_cold (tree fndecl)
-{
-  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
-					DECL_ATTRIBUTES (fndecl));
-}
 
 /* This function inititializes array notation specific builtin information.  */
 
@@ -54,67 +41,56 @@ array_notation_init_builtins (void)
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_add", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_mul", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_all_zero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_any_zero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_max", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
   
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_min", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_min_ind", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_max_ind", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 				       NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_any_nonzero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_all_nonzero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
   
   func_type = build_function_type_list (integer_type_node, integer_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_implicit_index", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
@@ -167,25 +143,23 @@ is_sec_implicit_index_fn (tree func_name)
    sec_implicit_index function.  FN's location in the source file is is 
    indicated by LOCATION.  */
 
-int
+HOST_WIDE_INT
 extract_sec_implicit_index_arg (location_t location, tree fn)
 {
   tree fn_arg;
   HOST_WIDE_INT return_int = 0;
-  if (!fn)
-    return -1;
 
   if (TREE_CODE (fn) == CALL_EXPR)
     {
       fn_arg = CALL_EXPR_ARG (fn, 0);
       if (really_constant_p (fn_arg))
-	return_int = (int) int_cst_value (fn_arg);
+	return_int = int_cst_value (fn_arg);
       else
 	{
 	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
 	    location = EXPR_LOCATION (fn);
 	  error_at (location, "__sec_implicit_index parameter must be a " 
-		    "constant integer expression");
+		    "integer constant expression");
 	  return -1;
 	}
     }
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index edcff2e..e07085d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -541,7 +541,7 @@ extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
 				       location_t, tree, tree);
 extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree);
-extern void find_rank (tree, bool, size_t *);
+extern bool find_rank (location_t, tree, tree, bool, size_t *);
 extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int field_decl_cmp (const void *, const void *);
@@ -1173,5 +1173,10 @@ typedef enum array_notation_reduce_type {
 extern int extract_sec_implicit_index_arg (location_t, tree);
 extern bool is_sec_implicit_index_fn (tree);
 extern void array_notation_init_builtins (void);
+extern struct c_expr fix_array_notation_expr (location_t, enum tree_code, 
+					      struct c_expr);
+extern bool contains_array_notation_expr (tree);
+extern tree expand_array_notation_exprs (tree);
+extern tree fix_conditional_array_notations (tree);
 
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 30c8e80..b8af90c 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1479,11 +1479,11 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
     case ARRAY_NOTATION_REF:
       pp_postfix_expression (pp, ARRAY_NOTATION_ARRAY (e));
       pp_c_left_bracket (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_START (e));
+      pp_expression (pp, ARRAY_NOTATION_START (e));
       pp_colon (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e));
+      pp_expression (pp, ARRAY_NOTATION_LENGTH (e));
       pp_colon (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e));
+      pp_expression (pp, ARRAY_NOTATION_STRIDE (e));
       pp_c_right_bracket (pp);
       break;
       
@@ -2161,6 +2161,7 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case CALL_EXPR:
     case COMPONENT_REF:
     case BIT_FIELD_REF:
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
old mode 100644
new mode 100755
index a3e754a..3d36382
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -31,19 +31,17 @@
 #include "gcc.h"
 #include "c-family/c-common.h"
 
-void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
+static 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 void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
+static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
 static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var);
-bool contains_array_notation_expr (tree expr);
-tree expand_array_notation_exprs (tree t);
 
 
+/* This structure holds all the scalar values and its appropriate variable 
+   replacment.  It is mainly used by the function that pulls all the invariant
+   parts that should be executed only once that comes with array notation 
+   expressions.  */
 struct inv_list
 {
   vec<tree, va_gc> *list_values;
@@ -51,72 +49,80 @@ struct inv_list
 };
 
 
-/* Returns the rank of ARRAY through the *RANK.  The user can specify whether
-   (s)he wants to step into array_notation-specific builtin functions
-   (specified by the IGNORE_BUILTIN_FN).
+/* Sets *RANK of expression ARRAY, ignoring array notation specific built-in 
+   functions if IGNORE_BUILTIN_FN is true.  The ORIG_EXPR is printed out if an
+   error occured in the rank calculation.  The functions returns false if it
+   encounters an error in rank calculation.  
 
    For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0]
    all have a rank of 2.  */
 
-void
-find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
+bool
+find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn,
+	   size_t *rank)
 {
   tree ii_tree;
-  size_t current_rank = 0, ii = 0;
+  size_t ii = 0, current_rank = 0;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
   if (!array)
-    return;
+    return true;
   else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
     {
       for (ii_tree = array;
 	   ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
 	   ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
 	current_rank++;
-      if (*rank == 0)
-	*rank = current_rank;
+	if (*rank == 0)
+	  *rank = current_rank;
+	else if (*rank != current_rank)
+	  {
+	    error_at (loc, "rank mismatch in expression %qE", orig_expr);
+	    return false;
+	  }
     }
   else if (TREE_CODE (array) == STATEMENT_LIST)
     {
       tree_stmt_iterator ii_tsi;
       for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi);
 	   tsi_next (&ii_tsi))
-	find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank);
+	if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
+			ignore_builtin_fn, rank))
+	  return false;
     }
   else
     {
       if (TREE_CODE (array) == CALL_EXPR)
 	{
 	  tree func_name = CALL_EXPR_FN (array);
+	  tree arg;
+	  call_expr_arg_iterator iter;
 	  if (TREE_CODE (func_name) == ADDR_EXPR)
 	    if (!ignore_builtin_fn)
 	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
-		/* If it is a builtin function, then we know it returns a 
-		   scalar.  */
-		return;
-	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
-	    {
-	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
-	      for (ii = 0; ii < (size_t) length; ii++)
-		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
-	    }
-	  else
-	    gcc_unreachable ();
+		/* If it is a builtin function, then it returns a scalar.  */
+		return true;
+
+	  FOR_EACH_CALL_EXPR_ARG (arg, iter, array)
+	    if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
+	      return false;
 	}
       else 
 	for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) 
-	  find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+	  if (!find_rank (loc, orig_expr, TREE_OPERAND (array, ii),
+			  ignore_builtin_fn, rank))
+	    return false;
     }
-  return;
+  return true;
 }
   
 
-/* Extracts all the array notations specified in NODE and stores them in a
-   dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE.  The
-   user can specify if (s)he wants to ignore the array notations inside the
-   array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
-   true).  */
+/* Extracts all array notations in NODE ans stores in ARRAY_LIST.  If 
+   IGNORE_BUILTIN_FN is set, then array notations inside array notation
+   specific builtin functions are ignored.  The NODE can be anything from a
+   full function to a single variable.  */
 
-void
+static void
 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 			      vec<tree, va_gc> **array_list)
 {
@@ -148,6 +154,8 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
     }
   else if (TREE_CODE (node) == CALL_EXPR)
     {
+      tree arg;
+      call_expr_arg_iterator iter;
       if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
 	{
 	  if (ignore_builtin_fn)
@@ -163,17 +171,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
-      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
-	{
-	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
 
-	  for (ii = 0; ii < (size_t) length; ii++)
-	    extract_array_notation_exprs
-	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
-	}
-      else
-	gcc_unreachable (); /* We should not get here.  */
-	  
+      FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
+	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
   else 
     for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
@@ -183,15 +183,12 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 }
 
 
-/* Replaces all occurances of array notations in tree ORIG that matches the
-   ones in LIST with the one in ARRAY_OPERAND.  The size of list and
-   ARRAY_OPERAND is ARRAY_SIZE.  For example, ARRAY_OPERAND[x] for some index
-   'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified
-   in LIST[x].   The  user can specify if (s)he wants to ignore the array
-   notations inside the array-notation specific builtin functions (using the
-   bool variable IGNORE_BUILTIN_FN).  */
+/* Replaces all the occurances of array notations in *LIST with the appropriate
+   one in ARRAY_OPERAND.  If IGNORE_BUILTIN_FN is set, then array notations
+   inside array-notation specific builtin functions are ignored.  ORIG can be
+   anything from a collection of statement lists to a single variable.  */
 
-void
+static void
 replace_array_notations (tree *orig, bool ignore_builtin_fn,
 			 vec<tree, va_gc> *list,
 			 vec<tree, va_gc> *array_operand)
@@ -200,7 +197,7 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
   tree node = NULL_TREE, node_replacement = NULL_TREE;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
   
-  if (vec_safe_length (list) == 0 || !*orig)
+  if (!*orig || vec_safe_length (list) == 0)
     return;
 
   if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
@@ -221,6 +218,8 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
     }
   else if (TREE_CODE (*orig) == CALL_EXPR)
     {
+      tree arg;
+      call_expr_arg_iterator iter;
       if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
 	{
 	  if (!ignore_builtin_fn)
@@ -244,16 +243,14 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
-      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
+      ii = 0;
+      FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
-	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
-	  for (ii = 0; ii < (size_t) length; ii++)
-	    replace_array_notations
-	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
-	       array_operand);
-	}
-      else
-	gcc_unreachable (); /* We should not get here!  */
+	  replace_array_notations (&arg, ignore_builtin_fn, list,
+				   array_operand);
+	  CALL_EXPR_ARG (*orig, ii) = arg;
+	  ii++;
+	}     
     }
   else
     {
@@ -264,9 +261,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
   return;
 }
 
-/* This function will find all the scalar expressions in *TP and push it in
-   DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 then
-   we have do not go into the *TP's subtrees.  */
+/* Find all the scalar expressions in *TP and push it in DATA struct, 
+   typecasted to (void *).  If *WALK_SUBTREES is set to 0 then do not go into 
+   the *TP's subtrees.  */
 
 static tree
 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
@@ -322,7 +319,9 @@ replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-/* Replaces all the scalar expressions in *NODE. */
+/* Replaces all the scalar expressions in *NODE.  Returns a STATEMENT_LIST that
+   holds the NODE along with variables that holds the results of the invariant
+   expressions.  */
 
 tree
 replace_invariant_exprs (tree *node)
@@ -391,13 +390,16 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
   tree ii_tree = NULL_TREE, new_modify_expr;
   vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
   tree new_var = NULL_TREE, builtin_loop = NULL_TREE;
+  tree begin_var, lngth_var, strde_var;
   size_t rhs_list_size = 0, lhs_list_size = 0;
 
   /* If either of this is true, an error message must have been send out
      already.  Not necessary to send out multiple error messages.  */
   if (lhs == error_mark_node || rhs == error_mark_node)
     return error_mark_node;
-  find_rank (rhs, false, &rhs_rank);
+  
+  if (!find_rank (location, rhs, rhs, false, &rhs_rank))
+    return error_mark_node;
   
   extract_array_notation_exprs (rhs, false, &rhs_list);
   rhs_list_size = vec_safe_length (rhs_list);
@@ -434,8 +436,11 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 
   lhs_rank = 0;
   rhs_rank = 0;
-  find_rank (lhs, true, &lhs_rank);
-  find_rank (rhs, true, &rhs_rank);
+  if (!find_rank (location, lhs, lhs, true, &lhs_rank))
+    return error_mark_node;
+  
+  if (!find_rank (location, rhs, rhs, true, &rhs_rank))
+    return error_mark_node;
 
   if (lhs_rank == 0 && rhs_rank == 0)
     {
@@ -466,12 +471,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
   if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
     {
       tree rhs_base = rhs;
-      for (ii = 0; ii < (size_t) rhs_rank; ii++)
-	rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+	{
+	  for (ii = 0; ii < (size_t) rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
       
-      error_at (location, "%qD cannot be scalar when %qD is not", lhs,
-		rhs_base);
-      return error_mark_node;
+	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+		    rhs_base);
+	  return error_mark_node;
+	}
+      else
+	{
+	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+		    rhs_base);
+	  return error_mark_node;
+	}
+
     }
   if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
     {
@@ -491,6 +506,72 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
       return error_mark_node;
     }
   
+  /* Here we assign the array notation components to variable so that we can
+     satisfy the exec once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree array_node = (*lhs_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      
+      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+			      integer_type_node);
+      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+			      integer_type_node);
+      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+			      integer_type_node);
+
+      add_stmt (build_modify_expr (location, begin_var, TREE_TYPE (begin_var),
+				   NOP_EXPR, location, array_begin,
+				   TREE_TYPE (array_begin)));
+      add_stmt (build_modify_expr (location, lngth_var, TREE_TYPE (lngth_var),
+				   NOP_EXPR, location, array_lngth,
+				   TREE_TYPE (array_lngth)));
+      add_stmt (build_modify_expr (location, strde_var, TREE_TYPE (strde_var),
+				   NOP_EXPR, location, array_strde,
+				   TREE_TYPE (array_strde)));
+      
+      ARRAY_NOTATION_START (array_node) = begin_var;
+      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+    }
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree array_node = (*rhs_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+
+	  add_stmt (build_modify_expr (location, begin_var,
+				       TREE_TYPE (begin_var),
+				       NOP_EXPR, location, array_begin,
+				       TREE_TYPE (array_begin)));
+	  add_stmt (build_modify_expr (location, lngth_var,
+				       TREE_TYPE (lngth_var),
+				       NOP_EXPR, location, array_lngth,
+				       TREE_TYPE (array_lngth)));
+	  add_stmt (build_modify_expr (location, strde_var,
+				       TREE_TYPE (strde_var),
+				       NOP_EXPR, location, array_strde,
+				       TREE_TYPE (array_strde)));
+      
+	  ARRAY_NOTATION_START (array_node) = begin_var;
+	  ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	  ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	}
+    }
+  
   lhs_vector = XNEWVEC (bool *, lhs_list_size);
   for (ii = 0; ii < lhs_list_size; ii++)
     lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
@@ -678,8 +759,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	  rhs_vector[ii][jj] = false;
     }
 
-
-
   for (ii = 0; ii < lhs_rank; ii++)
     {
       if (lhs_vector[0][ii])
@@ -691,7 +770,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	     NOP_EXPR,
 	     location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
 	     TREE_TYPE (lhs_var[ii]));
-	  
 	}
     }
 
@@ -965,19 +1043,19 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
     }
   
   /* The following statements will do the following:
-   * <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>
-   */
+     <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++)
@@ -1012,7 +1090,9 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 
 /* Encloses the conditional statement passed in STMT with a loop around it
    and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
-   The condition must have a ARRAY_NOTATION_REF tree.  */
+   The condition must have a ARRAY_NOTATION_REF tree.  An expansion of array
+   notation in STMT is returned in a STATEMENT_LIST.  */
+   
 
 static tree
 fix_conditional_array_notations_1 (tree stmt)
@@ -1027,8 +1107,9 @@ fix_conditional_array_notations_1 (tree stmt)
   tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
   tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
   bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
   location_t location = UNKNOWN_LOCATION;
-
+  
   if (TREE_CODE (stmt) == COND_EXPR)
     cond = COND_EXPR_COND (stmt);
   else if (TREE_CODE (stmt) == SWITCH_EXPR)
@@ -1037,7 +1118,11 @@ fix_conditional_array_notations_1 (tree stmt)
     /* Otherwise dont even touch the statement.  */
     return stmt;
 
-  find_rank (cond, false, &rank);
+  location = EXPR_LOCATION (stmt);
+  
+  if (!find_rank (location, cond, cond, false, &rank))
+    return error_mark_node;
+  
   extract_array_notation_exprs (cond, false, &array_list);
   loop = push_stmt_list ();
   for (ii = 0; ii < vec_safe_length (array_list); ii++)
@@ -1062,7 +1147,9 @@ fix_conditional_array_notations_1 (tree stmt)
 	    }
 	}
     }
-  find_rank (cond, true, &rank);
+
+  if (!find_rank (location, cond, cond, true, &rank))
+    return error_mark_node;
   if (rank == 0)
     {
       add_stmt (stmt);
@@ -1076,7 +1163,6 @@ fix_conditional_array_notations_1 (tree stmt)
     return stmt;
 
   list_size = vec_safe_length (array_list);
-  location = EXPR_LOCATION (stmt);
 
   array_ops =  XNEWVEC (tree *, list_size);
   for (ii = 0; ii < list_size; ii++)
@@ -1115,6 +1201,42 @@ fix_conditional_array_notations_1 (tree stmt)
 
   array_var = XNEWVEC (tree, rank);
 
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+
+	  add_stmt (build_modify_expr (location, begin_var,
+				       TREE_TYPE (begin_var),
+				       NOP_EXPR, location, array_begin,
+				       TREE_TYPE (array_begin)));
+	  add_stmt (build_modify_expr (location, lngth_var,
+				       TREE_TYPE (lngth_var),
+				       NOP_EXPR, location, array_lngth,
+				       TREE_TYPE (array_lngth)));
+	  add_stmt (build_modify_expr (location, strde_var,
+				       TREE_TYPE (strde_var),
+				       NOP_EXPR, location, array_strde,
+				       TREE_TYPE (array_strde)));
+      
+	  ARRAY_NOTATION_START (array_node) = begin_var;
+	  ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	  ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	}
+    }
+  
   for (ii = 0; ii < list_size; ii++)
     {
       tree array_node = (*array_list)[ii];
@@ -1174,7 +1296,6 @@ fix_conditional_array_notations_1 (tree stmt)
 			   location,
 			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
 			   TREE_TYPE (array_var[ii]));
-	
     }
 
   for (ii = 0; ii < rank ; ii++)
@@ -1291,7 +1412,6 @@ fix_conditional_array_notations_1 (tree stmt)
   XDELETEVEC (if_stmt_label);
   XDELETEVEC (expr_incr);
   XDELETEVEC (ind_init);
-  // XDELETEVEC (array_var);
   
   for (ii = 0; ii < list_size; ii++)
     {
@@ -1354,7 +1474,15 @@ fix_array_notation_expr (location_t location, enum tree_code code,
   tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
   bool **count_down, **array_vector;
   
-  find_rank (arg.value, false, &rank);
+  if (!find_rank (location, arg.value, arg.value, false, &rank))
+    {
+      /* If this function returns a NULL, we convert the tree value in the
+	 structure to error_mark_node and the parser should take care of the
+	 rest.  */
+      arg.value = error_mark_node;
+      return arg;
+    }
+  
   if (rank == 0)
     return arg;
   
@@ -1413,6 +1541,8 @@ fix_array_notation_expr (location_t location, enum tree_code code,
 	  jj++;
 	}
     }
+  
+  loop = push_stmt_list ();
 
   for (ii = 0; ii < list_size; ii++)
     {
@@ -1451,8 +1581,6 @@ fix_array_notation_expr (location_t location, enum tree_code code,
 	}
     }
 
-  loop = push_stmt_list ();
-
   for (ii = 0; ii < rank; ii++)
     {
       array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
@@ -1531,12 +1659,10 @@ fix_array_notation_expr (location_t location, enum tree_code code,
   replace_array_notations (&arg.value, true, array_list, array_operand);
 
   for (ii = 0; ii < rank; ii++)
-    {
-      expr_incr[ii] =
-	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
-		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
-			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
-    }
+    expr_incr[ii] =
+      build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+	      build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+		      build_int_cst (TREE_TYPE (array_var[ii]), 1)));
   
   for (jj = 0; jj < rank; jj++)
     {
@@ -1553,7 +1679,6 @@ fix_array_notation_expr (location_t location, enum tree_code code,
 				       array_var[jj], array_length[0][jj]);
 	}
     }
-
   
   for (ii = 0; ii < rank; ii++)
     {
@@ -1669,10 +1794,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
 	 || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
 	 || TREE_CODE (func_parm) == NOP_EXPR)
     func_parm = TREE_OPERAND (func_parm, 0);
-  
-  find_rank (an_builtin_fn, true, &rank);
 
   location = EXPR_LOCATION (an_builtin_fn);
+  
+  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
+    return error_mark_node;
  
   if (rank == 0)
     return an_builtin_fn;
@@ -1680,7 +1806,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
 	   && (an_type == REDUCE_MAX_INDEX  || an_type == REDUCE_MIN_INDEX))
     {
       error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
-		" have arrays with dimension greater than 1.");
+		" have arrays with dimension greater than 1");
       return error_mark_node;
     }
   
@@ -1712,7 +1838,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
       new_var_type = NULL_TREE;
       break;
     default:
-      gcc_unreachable ();  /* You should not reach here.  */
+      gcc_unreachable (); 
     }
   
   array_ops = XNEWVEC (tree *, list_size);
@@ -1879,12 +2005,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
     }
   replace_array_notations (&func_parm, true, array_list, array_operand);
   for (ii = 0; ii < rank; ii++)
-    {
-      expr_incr[ii] =
-	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
-		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
-			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
-    }
+    expr_incr[ii] =
+      build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+	      build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+		      build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+    
   
   for (jj = 0; jj < rank; jj++)
     {
@@ -2218,10 +2343,10 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
   return loop;
 }
 
-/* Returns true of FUNC_NAME is a builtin array notation function.  The type of
+/* Returns true if FUNC_NAME is a builtin array notation function.  The type of
    function is returned in *TYPE.  */
 
-bool
+static bool
 is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 {
   const char *function_name = NULL;
@@ -2310,7 +2435,7 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 }
 
 
-/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
+/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
 
 bool
 contains_array_notation_expr (tree expr)
@@ -2331,9 +2456,8 @@ contains_array_notation_expr (tree expr)
     return true;
 }
 
-/* Replaces array notations in void function call arguments in ARG with loop and
-   tree-node ARRAY_REF and returns that value in a tree node variable called
-   LOOP.  */
+/* Replaces array notations in void function call arguments in ARG and returns
+   a STATEMENT_LIST.  */
 
 static tree
 fix_array_notation_call_expr (tree arg)
@@ -2347,6 +2471,7 @@ fix_array_notation_call_expr (tree arg)
   tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
   tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
   bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
   an_reduce_type an_type = REDUCE_UNKNOWN;
   location_t location = UNKNOWN_LOCATION;
 
@@ -2359,12 +2484,13 @@ fix_array_notation_call_expr (tree arg)
       return loop;
     }
   
-  find_rank (arg, false, &rank);
+  if (!find_rank (location, arg, arg, false, &rank))
+    return error_mark_node;
+  
   if (rank == 0)
     return arg;
   
   extract_array_notation_exprs (arg, true, &array_list);
-
   if (vec_safe_length (array_list) == 0)
     return arg;
   
@@ -2407,7 +2533,42 @@ fix_array_notation_call_expr (tree arg)
     count_down[ii] = XNEWVEC (bool, rank);
   
   array_var = XNEWVEC (tree, rank);
+  
+  loop = push_stmt_list ();
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
 
+	  begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+	  strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+
+	  add_stmt (build_modify_expr (location, begin_var,
+				       TREE_TYPE (begin_var),
+				       NOP_EXPR, location, array_begin,
+				       TREE_TYPE (array_begin)));
+	  add_stmt (build_modify_expr (location, lngth_var,
+				       TREE_TYPE (lngth_var),
+				       NOP_EXPR, location, array_lngth,
+				       TREE_TYPE (array_lngth)));
+	  add_stmt (build_modify_expr (location, strde_var,
+				       TREE_TYPE (strde_var),
+				       NOP_EXPR, location, array_strde,
+				       TREE_TYPE (array_strde)));
+      
+	  ARRAY_NOTATION_START (array_node) = begin_var;
+	  ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	  ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	}
+    }
   for (ii = 0; ii < list_size; ii++)
     {
       jj = 0;
@@ -2457,8 +2618,6 @@ fix_array_notation_call_expr (tree arg)
 	}
     }
 
-  loop = push_stmt_list ();
-
   for (ii = 0; ii < rank; ii++)
     {
       array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
@@ -2610,7 +2769,9 @@ fix_array_notation_call_expr (tree arg)
 
 
 /* Walks through tree node T and find all the call-statments that do not return
-   anything and fix up any array notations they may carry.  */
+   anything and fix up any array notations they may carry.  The return value
+   is the same type as T but with all array notations replaced with appropriate
+   STATEMENT_LISTS.  */
 
 tree
 expand_array_notation_exprs (tree t)
@@ -2665,20 +2826,20 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
   tree array_ntn_tree = NULL_TREE;
   size_t stride_rank = 0, length_rank = 0, start_rank = 0;
   
-  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
     {
       error_at (loc,
-		"start-index of array notation triplet is not an integer.");
+		"start-index of array notation triplet is not an integer");
       return error_mark_node;
     }
-  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
     {
-      error_at (loc, "length of array notation triplet is not an integer.");
+      error_at (loc, "length of array notation triplet is not an integer");
       return error_mark_node;
     }
-  if (stride && (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))))
+  if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
     {
-      error_at (loc, "stride of array notation triplet is not an integer.");
+      error_at (loc, "stride of array notation triplet is not an integer");
       return error_mark_node;
     }  
   if (!stride)
@@ -2690,24 +2851,27 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
 	stride = build_int_cst (TREE_TYPE (start_index), 1);
     }	      
 
-  find_rank (start_index, false, &start_rank);
-  find_rank (length, false, &length_rank);
-  find_rank (stride, false, &stride_rank);
+  if (!find_rank (loc, start_index, start_index, false, &start_rank))
+    return error_mark_node;
+  if (!find_rank (loc, length, length, false, &length_rank))
+    return error_mark_node;
+  if (!find_rank (loc, stride, stride, false, &stride_rank))
+    return error_mark_node;
 
   if (start_rank != 0)
     {
       error_at (loc, "rank of an array notation triplet's start-index is not "
-		"zero.");
+		"zero");
       return error_mark_node;
     }
   if (length_rank != 0)
     {
-      error_at (loc, "rank of an array notation triplet's length is not zero.");
+      error_at (loc, "rank of an array notation triplet's length is not zero");
       return error_mark_node;
     }
   if (stride_rank != 0)
     {
-      error_at (loc, "rank of array notation triplet's stride is not zero.");
+      error_at (loc, "rank of array notation triplet's stride is not zero");
       return error_mark_node;
     }
   
@@ -2747,4 +2911,3 @@ find_correct_array_notation_type (tree op)
     } 
   return return_type;
 }
-
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index ba0a7f9..2ca5a3a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11052,14 +11052,14 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (TREE_CODE (array_type) == POINTER_TYPE)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in pointers.");
+			"using array notations in pointers");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
 	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
 	    {
 	      error_at (loc, "array notations cannot be used with function "
-			"type.");
+			"type");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11074,7 +11074,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
 		    {
 		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays.");
+				"function pointer arrays");
 		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
 						 NULL);
 		      return error_mark_node;
@@ -11086,7 +11086,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (!array_type_domain)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in dimensionless arrays.");
+			"using array notations in dimensionless arrays");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11098,7 +11098,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in variable-length arrays.");
+			"using array notations in variable-length arrays");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11120,7 +11120,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
 	    {
 	      error_at (loc, "array notations cannot be used with function "
-			"type.");
+			"type");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11138,7 +11138,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
 		    {
 		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays.");
+				"function pointer arrays");
 		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
 						 NULL);
 		      return error_mark_node;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 15dc83d..cb2fe4a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2309,7 +2309,8 @@ build_array_ref (location_t loc, tree array, tree index)
   if (flag_enable_cilkplus && contains_array_notation_expr (index))
     {
       size_t rank = 0;
-      find_rank (index, true, &rank);
+      if (!find_rank (loc, index, index, true, &rank))
+	return error_mark_node;
       if (rank > 1)
 	{
 	  error_at (loc, "rank of the array's index is greater than 1.");
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 627bf69..3ce9969 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -82,6 +82,8 @@ extensions, accepted by GCC in C90 mode and in C++.
 * x86 specific memory model extensions for transactional memory:: x86 memory models.
 * Object Size Checking:: Built-in functions for limited buffer overflow
                         checking.
+* Cilk Plus Builtins::  Built-in functions that are part of Cilk Plus language
+                        extension.
 * Other Builtins::      Other built-in functions.
 * Target Builtins::     Built-in functions specific to particular targets.
 * Target Format Checks:: Format checks specific to particular targets.
@@ -8762,6 +8764,31 @@ Similar to @code{__builtin_bswap32}, except the argument and return types
 are 64 bit.
 @end deftypefn
 
+@node Cilk Plus Builtins
+@section Cilk Plus C/C++ language extension Built-in Functions.
+
+GCC provides support for the following built-in reduction funtions if Cilk Plus
+is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
+
+@itemize @bullet
+@item __sec_reduce
+@item __sec_reduce_add
+@item __sec_reduce_all_nonzero
+@item __sec_reduce_all_zero
+@item __sec_reduce_any_nonzero
+@item __sec_reduce_any_zero
+@item __sec_reduce_max
+@item __sec_reduce_min
+@item __sec_reduce_max_ind
+@item __sec_reduce_min_ind
+@item __sec_reduce_mul
+@item __sec_reduce_mutating
+@end itemize
+
+Further details and examples about these built-in functions are described 
+in the Cilk Plus language manual which can be found at 
+@uref{http://www.cilkplus.org}.
+
 @node Target Builtins
 @section Built-in Functions Specific to Particular Target Machines
 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
index 5fb3680..fd128b1 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
@@ -26,7 +26,7 @@ int main(int argc, char **argv)
       array[ii] = 10;
       array2[ii] = 5000000;
     }
-  array2[0:10:2] = array[0:10:2];
+  array2[0:5:2] = array[0:5:2];
 
   printf("==============================================\n");
   for (ii = 0; ii<10; ii++)
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
@@ -0,0 +1,34 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-#   Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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/cilkplus_AN_c_errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
@@ -0,0 +1,34 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
index 44e7361..4035ed5 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
@@ -1,16 +1,16 @@
 int main(void)
 {
   extern int func(int);
-  int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration." } */
-  int  array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration." } */
-  extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration." } */
+  int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration" } */
+  int  array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration" } */
+  extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration" } */
   int *a, ***b;
   extern char *c;
   int array2[10];
 
-  a[:] = 5; /* { dg-error  "start-index and length fields necessary for using array notations in pointers." } */
+  a[:] = 5; /* { dg-error  "start-index and length fields necessary for using array notations in pointers" } */
   c[1:2] =  3; /* This is OK.  */
   (array2)[:] = 5; /* This is OK.  */
-  b[1:2][1:func(x)][:] = 3; /*  { dg-error  "start-index and length fields necessary for using array notations in pointers." }  */
+  b[1:2][1:func(x)][:] = 3; /*  { dg-error  "start-index and length fields necessary for using array notations in pointers" }  */
 }
 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-#   Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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
index 272ef41..82008c0 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
@@ -3,16 +3,15 @@ typedef int (*foo)(int);
 int main(int argc, char **argv)
 {
   int array[10], array2[10][10];
-  // int array[10], array2[10], value, ii = 0;
   foo func_array[10];
   foo func_array2[10][10];
   foo ***func_array_ptr;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
 
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
index ef39b2b..59c2d1e 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
@@ -25,18 +25,18 @@ void func (int *x)
 int main2 (int argc, char **argv)
 {
   int array[10], array2[10];
-  array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer." } */
-  func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer." } */
+  array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer" } */
   
-  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer." } */
-  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer." } */
+  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */
   return 0;
 } 
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
new file mode 100644
index 0000000..77955a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
@@ -0,0 +1,23 @@
+int function_call (int x)
+{
+  return x;
+}
+
+int main(int argc, char **argv)
+{
+  int array[100], array2[100][100];
+
+  array[:] = array[:] + array2[:][:]; /* { dg-error "rank mismatch in expression" } */
+
+  if (array[:] + array2[:][:]) /* { dg-error "rank mismatch in expression" } */
+    return argc == 5;
+
+  argc += function_call (array[:] + array2[5:10:2][:]); /* { dg-error "rank mismatch in expression" } */
+
+  argc += function_call (function_call (array[:] + array2[5:10:2][:])); /* { dg-error "rank mismatch in expression" } */
+
+   argc += __sec_reduce_add (array[:], array2[:][:]); /* { dg-error "rank mismatch in expression" } */
+
+   argc += __sec_reduce_add (array2[:][:]) + argc; /* This is OK.  */
+  return argc;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
new file mode 100644
index 0000000..37d22c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
@@ -0,0 +1,60 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <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/exec-once2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c
new file mode 100644
index 0000000..ba70ab8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c
@@ -0,0 +1,82 @@
+#ifdef HAVE_IO
+#include <stdio.h>
+#endif
+
+
+int func1(int x)
+{
+  /* If x == 2 then it should return 0.  */
+  return (x - 2);
+}
+
+int func2(int x)
+{
+  /* If x == 2 then it should return 1000.  */
+  return (x * 500);
+}
+
+int func3 (int x)
+{
+  /* If x == 2 then it should return 1.  */
+  /* If x == 1 then it should return 0.  */
+  return (x-1);
+}
+
+int func4(int x)
+{
+  if (x > 0) 
+    return x;
+  else 
+    return x--;
+}
+
+
+/* This program makes an assumption that argc == 1.  */
+int main (int argc, char **argv)
+{
+
+  int array[2500];
+
+  /* This should set array[0->999] to 5.  */
+  array[argc-1:func2(++argc):1] = 5;
+  array[1000:500:1] = 10; /* set all variables in array[1000-->1499] to 10.  */
+  array[1500:500:1] = 15; /* set all variables in array[1500-->1999] to 15.  */
+  array[2000:500:1] = 20; /* set all variables in array[2000-->2499] to 20.  */
+  array[2000:500:1] = 25; /* set all variables in array[2500-->2999] to 25.  */
+  array[2000:500:1] = 30; /* set all variables in array[3000-->3499] to 30.  */
+  
+  argc = func3 (argc); /* This will set argc back to 1.  */
+#if HAVE_IO
+  printf("argc = %d\n", argc);
+#endif
+  /* If the parameters inside the function get evaluated only once, then this
+     if statement must work fine, i.e. the triplet values will be 0, 1000, 1.
+
+     Otherwise, the program should crash or give some uneasy value.  */
+
+  /* If done correctly, it should boil down to: array[0:1000:1].  */
+  if (array[func3(argc):func2(++argc)] != 5) {
+#ifdef HAVE_IO
+    printf ("Should not be there(1).\n");
+#endif
+    return 1;
+  }
+  
+  /* If done correctly, it should boil down to: array[999:500:-1].  */
+  if (func4(array[func2(argc)-1:func2(argc--):func1(argc)]) != 5) {
+#ifdef HAVE_IO
+    printf ("Should not be there(2).\n");
+#endif
+    return 1;
+  }
+
+  /* If done correctly, it should boil down to: array[1000:500:1].  */
+  if (func4 (func4(array[func2(argc++):500: func1(argc--)])) != 5) {
+#ifdef HAVE_IO
+    printf ("Should not be there(3).\n");
+#endif
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
deleted file mode 100644
index 37d22c5..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-21 23:34         ` Aldy Hernandez
@ 2013-03-22 22:36           ` Mike Stump
  2013-03-23  1:36             ` Iyer, Balaji V
  0 siblings, 1 reply; 28+ messages in thread
From: Mike Stump @ 2013-03-22 22:36 UTC (permalink / raw)
  To: Aldy Hernandez
  Cc: Jakub Jelinek, Jeff Law, Joseph S. Myers, Iyer, Balaji V, gcc-patches

On Mar 21, 2013, at 4:33 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> I can look into this later on, but this problem happened even when I replaced cilkplus' compile.exp, errors.exp, and execute.exp into just an "exit".  So it seems unrelated to the cilk patch set.

Ah, I withdraw my objection.  The bug can't be in those file, if those files say exit and the problem persists.  Then, we're into conflation of filenames if I had to guess, which I hate doing, but, if it proves accurate, then changing the spelling is exactly the right fix, or, at least, it isn't unreasonable.  Thanks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-22 22:36           ` Mike Stump
@ 2013-03-23  1:36             ` Iyer, Balaji V
  2013-03-23  5:00               ` Mike Stump
  0 siblings, 1 reply; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-23  1:36 UTC (permalink / raw)
  To: Mike Stump, Aldy Hernandez
  Cc: Jakub Jelinek, Jeff Law, Joseph S. Myers, gcc-patches


________________________________________
From: gcc-patches-owner@gcc.gnu.org [gcc-patches-owner@gcc.gnu.org] on behalf of Mike Stump [mrs@mrs.kithrup.com]
Sent: Friday, March 22, 2013 6:36 PM
To: Aldy Hernandez
Cc: Jakub Jelinek; Jeff Law; Joseph S. Myers; Iyer, Balaji V; gcc-patches
Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)

On Mar 21, 2013, at 4:33 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> I can look into this later on, but this problem happened even when I replaced cilkplus' compile.exp, errors.exp, and execute.exp into just an "exit".  So it seems unrelated to the cilk patch set.

Ah, I withdraw my objection.  The bug can't be in those file, if those files say exit and the problem persists.  Then, we're into conflation of filenames if I had to guess, which I hate doing, but, if it proves accurate, then changing the spelling is exactly the right fix, or, at least, it isn't unreasonable.  Thanks.

Hi Mike,
      I can confirm that renaming scripts to something unique fixed the issue.

Thanks,

Balaji V. Iyer.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-23  1:36             ` Iyer, Balaji V
@ 2013-03-23  5:00               ` Mike Stump
  0 siblings, 0 replies; 28+ messages in thread
From: Mike Stump @ 2013-03-23  5:00 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Aldy Hernandez, Jakub Jelinek, Jeff Law, Joseph S. Myers, gcc-patches

On Mar 22, 2013, at 6:36 PM, "Iyer, Balaji V" <balaji.v.iyer@intel.com> wrote:
> I can confirm that renaming scripts to something unique fixed the issue.

That's what others have said, I've not see it first hand.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-22 22:04   ` Iyer, Balaji V
@ 2013-03-25 16:45     ` Aldy Hernandez
  2013-03-25 21:39       ` Iyer, Balaji V
  2013-03-26 17:05       ` Joseph S. Myers
  2013-03-26 16:27     ` Joseph S. Myers
  1 sibling, 2 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-25 16:45 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, Joseph Myers [joseph@codesourcery.com]

On 03/22/13 17:03, Iyer, Balaji V wrote:

> I have not fixed all the issues below (the big one that is left is the bultin function representation that Joseph Pointed out). I have fixed most of the other issues. All the things I have fixed are marked by "FIXED!"

Don't worry, I can work on the builtin function representation.

I am keeping a list of pending issues on the wiki 
(http://gcc.gnu.org/wiki/cilkplus-merge) with my name in parenthesis for 
items I am working on.  Particularly, I have added a sub-section for 
array notation items that have been pointed out in reviews but have not 
been completed.  I suggest you keep this list up to date as well, so we 
don't loose track of what has been pointed out.

> diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
> index 6591fd1..10db29b 100644
> --- a/gcc/c-family/ChangeLog.cilkplus
> +++ b/gcc/c-family/ChangeLog.cilkplus
> @@ -1,7 +1,11 @@
> +2013-03-22  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> +
> +	* c-pretty-print.c (pp_c_expression): Added ARRAY_NOTATION_REF case.
> +
>  2013-03-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>
>  	* c-common.c (c_define_builtins): When cilkplus is enabled, the

You can combine changelog entries into one entry.  This will make it 
easier when we merge into mainline.  So basically, add the 
c-pretty-print.c entry to the entry below it.

>> Non-static function declarations like this should not be inside a .c file.
>> If these functions are used outside this file, there should be an associated
>> header that declares them; include it in the .c file.  If only used inside the .c file
>> that defines them, make them static (and topologically sort static functions
>> inside a source file so that forward static declarations are only needed for cases
>> of recursion).
>>
>>> +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL
>> is
>>> +   not run as is.  */
>>
>> The cold attribute means unlikely to be executed rather than "not run as is".
>> Maybe "not run as is" is what's relevant here, but I'm not clear why this attribute
>> would be useful for built-in functions at all - the documentation suggests it's
>> only relevant when a user defines a function themselves, and affects the code
>> generated for that function, so wouldn't be relevant at all for built-in functions.

I see you fixed this.  Since you are only fixing some of the items 
Joseph pointed out in this patch, please put "FIXED" below each item you 
did to aid in reviewing.

>>
>>> +void
>>> +array_notation_init_builtins (void)
>>
>> Other built-in functions use various .def files (builtins.def and the files it includes)
>> to avoid lots of repetitive code like this - can you integrate this with that
>> mechanism?  If you do so, then you should be able to avoid (or massively
>> simplify) functions like:
>>
>>> +/* Returns true if the function call specified in FUNC_NAME is
>>> +   __sec_implicit_index.  */
>>> +
>>> +bool
>>> +is_sec_implicit_index_fn (tree func_name)
>>
>> because code can use the BUILT_IN_* enum values to test whether a particular
>> function is in use - which is certainly cleaner than using strcmp against the
>> function name.

And here put "FIXED" if fixed, or "Aldy is going to work on this" or 
remove it altogether so it's not assumed that it was fixed by this patch 
since you're quoting it.

>>
>>> +/* Returns the first and only argument for FN, which should be a
>>> +   sec_implicit_index function.  FN's location in the source file is is
>>> +   indicated by LOCATION.  */
>>> +
>>> +int
>>> +extract_sec_implicit_index_arg (location_t location, tree fn) {
>>> +  tree fn_arg;
>>> +  HOST_WIDE_INT return_int = 0;
>>> +  if (!fn)
>>> +    return -1;
>>
>> Why the random check for a NULL argument?  If a NULL argument is valid
>> (meaning that it makes the code cleaner to allow such arguments rather than
>> making sure the function isn't called with them), this should be documented in
>> the comment above the function; otherwise, if such an argument isn't valid,
>> there is no need to check for it.
>
> I always tend to check for a null pointer before I access the fields in the structure. In this case it is unnecessary. In some cases (e.g. find_rank) there is a good chance a null pointer will be passed into the function and we need to check that and reject those.

I think what Joseph is suggesting is that if NULL is not valid, then the 
caller should check this.  But if NULL is valid, then it should be 
documented in the function comment at the top.

>>> +  if (TREE_CODE (fn) == CALL_EXPR)
>>> +    {
>>> +      fn_arg = CALL_EXPR_ARG (fn, 0);
>>> +      if (really_constant_p (fn_arg))
>>
>> I don't think really_constant_p is what's wanted;
>> <http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
>> Intel_Cilk_plus_lang_spec_2.htm>
>> says "The argument shall be an integer constant expression.", and such
>> expressions always appear in the C front end as INTEGER_CST.  So you can just
>> check for INTEGER_CST.
>
> What about C++? This function is shared by both C and C++.

Same thing for C++, but...

>
>>
>> Now a subtlety here is that the function argument will have been folded by this
>> point, meaning that cases that aren't integer constant expressions in C standard
>> terms will be wrongly allowed (both by the original code and by a version
>> checking against INTEGER_CST).  In such cases, the way to get things checked
>> correctly is to use a keyword rather than a built-in function - as with
>> __builtin_choose_expr or __builtin_shuffle, for example.  Since this operation
>> seems special in ways that built-in functions generally aren't, that seems
>> reasonable anyway.  So the code parsing this keyword would check that the
>> argument is an INTEGER_CST, of integer type (since INTEGER_CSTs can have
>> pointer type in GCC), like that for __builtin_choose_expr does.  It would then
>> quite likely create its own tree code for the operation, rather than using a
>> CALL_EXPR at all.  (It would need to manage converting to int, given how the
>> specification defines things in terms of a prototype for type int - so e.g. a
>> constant 1ULL << 32 would act like 0 if int is 32 bits, under the present
>> specification.)
>>
>> The specification doesn't seem very clear on to what extent the __sec_*
>> operations must act like functions (what happens if someone puts parentheses
>> around the __sec_* name, for example - that wouldn't work with the keyword
>> approach).  So the specification should be clarified there, but I think saying the
>> __sec_* operations are syntactically special, like keywords, is more appropriate
>> than requiring other uses to work.
>>
>>> +	return_int = (int) int_cst_value (fn_arg);
>>> +      else
>>> +	{
>>> +	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
>>> +	    location = EXPR_LOCATION (fn);
>>> +	  error_at (location, "__sec_implicit_index parameter must be a "
>>> +		    "constant integer expression");
>>
>> The term is "integer constant expression" not "constant integer expression".
>
> FIXED!

...it looks like you're going to have to rework all this as a keyword.

For now, I suggest you check for INTEGER_CST as suggested, put a FIXME 
comment explaining that we need to rework this as a keyword, and add an 
entry to the wiki as a TODO item.  This way you can attack the rest of 
the easier/cosmetic changes Joseph is suggesting without getting bogged 
down by the keyword.

Also, can you follow up with the specification changes suggested?

> +   parts that should be executed only once that comes with array notation
> +   expressions.  */

You probably want a comma in there somewhere, or split this sentence 
somehow.

>
>>
>>> +/* Returns the rank of ARRAY through the *RANK.  The user can specify
>> whether
>>> +   (s)he wants to step into array_notation-specific builtin functions
>>> +   (specified by the IGNORE_BUILTIN_FN).
>>
>> The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring array-
>> notation-specific built-in functions if IGNORE_BUILTIN_FN." would be better.
>
> Yes, I agree with your wording. Thanks! and FIXED!

> +/* Sets *RANK of expression ARRAY, ignoring array notation specific built-in

^^^^^^^^^^^
Almost, "Set *RANK to the rank of ARRAY, ignoring...".

> +/* Extracts all array notations in NODE ans stores in ARRAY_LIST.  If
> +   IGNORE_BUILTIN_FN is set, then array notations inside array notation
> +   specific builtin functions are ignored.  The NODE can be anything from a
> +   full function to a single variable.  */

s/ans/and

s/stores in/stores them in/

>
>>
>>> +{
>>> +  size_t ii = 0;
>>> +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
>>> +
>>> +  if (!node)
>>> +    return;
>>
>> Again, check for NULL argument without any mention in the comment that such
>> arguments are valid; remove unless there is a reason to make them valid.
>>
>>> +  else if (TREE_CODE (node) == TREE_LIST)
>>
>> What's NODE?  My first guess would have been an expression, but if a TREE_LIST
>> is possible that's clearly not the answer, so explain in the comment above the
>> function what NODE is.  (If a TREE_LIST is being used within expressions to store
>> something specific to array notation, don't do so - TREE_LIST is deprecated,
>> existing uses should be phased out in favour of more specific and less memory-
>> hungry datastructures and new uses should not be added.)
>
> FIXED! What is replacing tree-list? I have used tree-list in my later patches and in my Cilk Plus branch.

For list of things, probably vectors, etc.

> +/* Find all the scalar expressions in *TP and push it in DATA struct,

s/it/them

>>> +bool
>>> +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) {
>>> +  const char *function_name = NULL;
>>> +
>>> +  if (!func_name)
>>> +    return false;
>>
>> Another unexplained test for a NULL argument.  Again, explain what sort of
>> things FUNC_NAME may be.  (This is another function that should be using
>> BUILT_IN_* enum values rather than strcmp, if you rework how the built-in
>> functions are implemented.)

Still present in the current patch ??

>
>>
>>> +{
>>> +  if (!t || !contains_array_notation_expr (t))
>>> +    return t;
>>
>> Another check for NULL without a comment saying NULL is a valid argument.
>
> This function also can receive a null pointer.

Then, document that NULL is a valid argument please.

> +  /* Here we assign the array notation components to variable so that we can
> +     satisfy the exec once rule.  */
> +  for (ii = 0; ii < lhs_list_size; ii++)
> +    {
> +      tree array_node = (*lhs_list)[ii];
> +      tree array_begin = ARRAY_NOTATION_START (array_node);
> +      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
> +      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
> +
> +      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
> +			      integer_type_node);
> +      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
...
...

There's a big chunk of code here that AFAICT is not part of the review. 
  Did I miss something, or did this creep in somehow?

> +
> +  loop = push_stmt_list ();

Similarly here.  What's this bit part of?

> @@ -2407,7 +2533,42 @@ fix_array_notation_call_expr (tree arg)
>      count_down[ii] = XNEWVEC (bool, rank);
>
>    array_var = XNEWVEC (tree, rank);
> +
> +  loop = push_stmt_list ();
> +  for (ii = 0; ii < list_size; ii++)
> +    {
> +      tree array_node = (*array_list)[ii];
> +      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
> +	{
> +	  tree array_begin = ARRAY_NOTATION_START (array_node);
> +	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);

Also here.  Did I miss something?

> +* Cilk Plus Builtins::  Built-in functions that are part of Cilk Plus language
> +                        extension.

Should be "Built-in functions for the Cilk Plus language extension."

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> index 272ef41..82008c0 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> @@ -3,16 +3,15 @@ typedef int (*foo)(int);
>  int main(int argc, char **argv)
>  {
>    int array[10], array2[10][10];
> -  // int array[10], array2[10], value, ii = 0;

Do not add commented out code.

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> index 5fb3680..fd128b1 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> @@ -26,7 +26,7 @@ int main(int argc, char **argv)
>        array[ii] = 10;
>        array2[ii] = 5000000;
>      }
> -  array2[0:10:2] = array[0:10:2];
> +  array2[0:5:2] = array[0:5:2];

Is this change part of this review cycle, or is this something else?  If 
the latter, then submit it as a separate patch.

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> index 272ef41..82008c0 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> @@ -3,16 +3,15 @@ typedef int (*foo)(int);
>  int main(int argc, char **argv)
>  {
>    int array[10], array2[10][10];
> -  // int array[10], array2[10], value, ii = 0;

Do not add commented out code.

Thanks for following up on this.

Could you tackle the changes I have suggested and repost the patch?

Thanks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-25 16:45     ` Aldy Hernandez
@ 2013-03-25 21:39       ` Iyer, Balaji V
  2013-03-25 21:49         ` Aldy Hernandez
  2013-03-26 17:05       ` Joseph S. Myers
  1 sibling, 1 reply; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-25 21:39 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Joseph Myers [joseph@codesourcery.com]

[-- Attachment #1: Type: text/plain, Size: 15700 bytes --]

Hello Joseph, Aldy et al.,
   Attached, please find a fixed patch. This patch should fix all the issues that Joseph mentioned in both the emails with the exception of the built-in __sec_reduce functions. Aldy is currently looking into those. The changes that Aldy mentioned below have also been fixed with the appropriate comments below:

My current email client is not putting the '>' correctly, so all my comments are in CAPS below. I am currently looking into fixing that. Till then, I am sorry for the inconvenience.

Thanks,

Balaji V. Iyer.


________________________________________
From: Aldy Hernandez [aldyh@redhat.com]
Sent: Monday, March 25, 2013 12:45 PM
To: Iyer, Balaji V
Cc: gcc-patches@gcc.gnu.org; Joseph Myers [joseph@codesourcery.com]
Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)

On 03/22/13 17:03, Iyer, Balaji V wrote:

> I have not fixed all the issues below (the big one that is left is the bultin function representation that Joseph Pointed out). I have fixed most of the other issues. All the things I have fixed are marked by "FIXED!"

Don't worry, I can work on the builtin function representation.

I am keeping a list of pending issues on the wiki
(http://gcc.gnu.org/wiki/cilkplus-merge) with my name in parenthesis for
items I am working on.  Particularly, I have added a sub-section for
array notation items that have been pointed out in reviews but have not
been completed.  I suggest you keep this list up to date as well, so we
don't loose track of what has been pointed out.

> diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
> index 6591fd1..10db29b 100644
> --- a/gcc/c-family/ChangeLog.cilkplus
> +++ b/gcc/c-family/ChangeLog.cilkplus
> @@ -1,7 +1,11 @@
> +2013-03-22  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> +
> +     * c-pretty-print.c (pp_c_expression): Added ARRAY_NOTATION_REF case.
> +
>  2013-03-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>
>       * c-common.c (c_define_builtins): When cilkplus is enabled, the

You can combine changelog entries into one entry.  This will make it
easier when we merge into mainline.  So basically, add the
c-pretty-print.c entry to the entry below it.

FIXED!!

>> Non-static function declarations like this should not be inside a .c file.
>> If these functions are used outside this file, there should be an associated
>> header that declares them; include it in the .c file.  If only used inside the .c file
>> that defines them, make them static (and topologically sort static functions
>> inside a source file so that forward static declarations are only needed for cases
>> of recursion).
>>
>>> +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL
>> is
>>> +   not run as is.  */
>>
>> The cold attribute means unlikely to be executed rather than "not run as is".
>> Maybe "not run as is" is what's relevant here, but I'm not clear why this attribute
>> would be useful for built-in functions at all - the documentation suggests it's
>> only relevant when a user defines a function themselves, and affects the code
>> generated for that function, so wouldn't be relevant at all for built-in functions.

I see you fixed this.  Since you are only fixing some of the items
Joseph pointed out in this patch, please put "FIXED" below each item you
did to aid in reviewing.

YES. THIS IS FIXED ALSO!

>>
>>> +void
>>> +array_notation_init_builtins (void)
>>
>> Other built-in functions use various .def files (builtins.def and the files it includes)
>> to avoid lots of repetitive code like this - can you integrate this with that
>> mechanism?  If you do so, then you should be able to avoid (or massively
>> simplify) functions like:
>>
>>> +/* Returns true if the function call specified in FUNC_NAME is
>>> +   __sec_implicit_index.  */
>>> +
>>> +bool
>>> +is_sec_implicit_index_fn (tree func_name)
>>
>> because code can use the BUILT_IN_* enum values to test whether a particular
>> function is in use - which is certainly cleaner than using strcmp against the
>> function name.

And here put "FIXED" if fixed, or "Aldy is going to work on this" or
remove it altogether so it's not assumed that it was fixed by this patch
since you're quoting it.

OK.

>>
>>> +/* Returns the first and only argument for FN, which should be a
>>> +   sec_implicit_index function.  FN's location in the source file is is
>>> +   indicated by LOCATION.  */
>>> +
>>> +int
>>> +extract_sec_implicit_index_arg (location_t location, tree fn) {
>>> +  tree fn_arg;
>>> +  HOST_WIDE_INT return_int = 0;
>>> +  if (!fn)
>>> +    return -1;
>>
>> Why the random check for a NULL argument?  If a NULL argument is valid
>> (meaning that it makes the code cleaner to allow such arguments rather than
>> making sure the function isn't called with them), this should be documented in
>> the comment above the function; otherwise, if such an argument isn't valid,
>> there is no need to check for it.
>
> I always tend to check for a null pointer before I access the fields in the structure. In this case it is unnecessary. In some cases (e.g. find_rank) there is a good chance a null pointer will be passed into the function and we need to check that and reject those.

I think what Joseph is suggesting is that if NULL is not valid, then the
caller should check this.  But if NULL is valid, then it should be
documented in the function comment at the top.

FIXED!

>>> +  if (TREE_CODE (fn) == CALL_EXPR)
>>> +    {
>>> +      fn_arg = CALL_EXPR_ARG (fn, 0);
>>> +      if (really_constant_p (fn_arg))
>>
>> I don't think really_constant_p is what's wanted;
>> <http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
>> Intel_Cilk_plus_lang_spec_2.htm>
>> says "The argument shall be an integer constant expression.", and such
>> expressions always appear in the C front end as INTEGER_CST.  So you can just
>> check for INTEGER_CST.
>
> What about C++? This function is shared by both C and C++.

Same thing for C++, but...

>
>>
>> Now a subtlety here is that the function argument will have been folded by this
>> point, meaning that cases that aren't integer constant expressions in C standard
>> terms will be wrongly allowed (both by the original code and by a version
>> checking against INTEGER_CST).  In such cases, the way to get things checked
>> correctly is to use a keyword rather than a built-in function - as with
>> __builtin_choose_expr or __builtin_shuffle, for example.  Since this operation
>> seems special in ways that built-in functions generally aren't, that seems
>> reasonable anyway.  So the code parsing this keyword would check that the
>> argument is an INTEGER_CST, of integer type (since INTEGER_CSTs can have
>> pointer type in GCC), like that for __builtin_choose_expr does.  It would then
>> quite likely create its own tree code for the operation, rather than using a
>> CALL_EXPR at all.  (It would need to manage converting to int, given how the
>> specification defines things in terms of a prototype for type int - so e.g. a
>> constant 1ULL << 32 would act like 0 if int is 32 bits, under the present
>> specification.)
>>
>> The specification doesn't seem very clear on to what extent the __sec_*
>> operations must act like functions (what happens if someone puts parentheses
>> around the __sec_* name, for example - that wouldn't work with the keyword
>> approach).  So the specification should be clarified there, but I think saying the
>> __sec_* operations are syntactically special, like keywords, is more appropriate
>> than requiring other uses to work.
>>
>>> +   return_int = (int) int_cst_value (fn_arg);
>>> +      else
>>> +   {
>>> +     if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
>>> +       location = EXPR_LOCATION (fn);
>>> +     error_at (location, "__sec_implicit_index parameter must be a "
>>> +               "constant integer expression");
>>
>> The term is "integer constant expression" not "constant integer expression".
>
> FIXED!

...it looks like you're going to have to rework all this as a keyword.

OK, CAN I LOOK AT THIS AFTER WE FINISH THE BUILTIN FUNCTION IMPLEMENTATION FIX?

For now, I suggest you check for INTEGER_CST as suggested, put a FIXME
comment explaining that we need to rework this as a keyword, and add an
entry to the wiki as a TODO item.  This way you can attack the rest of
the easier/cosmetic changes Joseph is suggesting without getting bogged
down by the keyword.

Also, can you follow up with the specification changes suggested?

YES, I HAVE CONTACTED THE APPRIOPRIATE PEOPLE. I WILL TRY TO GET ANSWERS TO IT AS SOON AS I GET IT.

> +   parts that should be executed only once that comes with array notation
> +   expressions.  */

You probably want a comma in there somewhere, or split this sentence
somehow.

FIXED!

>
>>
>>> +/* Returns the rank of ARRAY through the *RANK.  The user can specify
>> whether
>>> +   (s)he wants to step into array_notation-specific builtin functions
>>> +   (specified by the IGNORE_BUILTIN_FN).
>>
>> The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring array-
>> notation-specific built-in functions if IGNORE_BUILTIN_FN." would be better.
>
> Yes, I agree with your wording. Thanks! and FIXED!

> +/* Sets *RANK of expression ARRAY, ignoring array notation specific built-in

^^^^^^^^^^^
Almost, "Set *RANK to the rank of ARRAY, ignoring...".

FIXED!

> +/* Extracts all array notations in NODE ans stores in ARRAY_LIST.  If
> +   IGNORE_BUILTIN_FN is set, then array notations inside array notation
> +   specific builtin functions are ignored.  The NODE can be anything from a
> +   full function to a single variable.  */

s/ans/and

s/stores in/stores them in/

FIXED!

>
>>
>>> +{
>>> +  size_t ii = 0;
>>> +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
>>> +
>>> +  if (!node)
>>> +    return;
>>
>> Again, check for NULL argument without any mention in the comment that such
>> arguments are valid; remove unless there is a reason to make them valid.
>>
>>> +  else if (TREE_CODE (node) == TREE_LIST)
>>
>> What's NODE?  My first guess would have been an expression, but if a TREE_LIST
>> is possible that's clearly not the answer, so explain in the comment above the
>> function what NODE is.  (If a TREE_LIST is being used within expressions to store
>> something specific to array notation, don't do so - TREE_LIST is deprecated,
>> existing uses should be phased out in favour of more specific and less memory-
>> hungry datastructures and new uses should not be added.)
>
> FIXED! What is replacing tree-list? I have used tree-list in my later patches and in my Cilk Plus branch.

For list of things, probably vectors, etc.

> +/* Find all the scalar expressions in *TP and push it in DATA struct,

s/it/them

FIXED!

>>> +bool
>>> +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) {
>>> +  const char *function_name = NULL;
>>> +
>>> +  if (!func_name)
>>> +    return false;
>>
>> Another unexplained test for a NULL argument.  Again, explain what sort of
>> things FUNC_NAME may be.  (This is another function that should be using
>> BUILT_IN_* enum values rather than strcmp, if you rework how the built-in
>> functions are implemented.)

Still present in the current patch ??

FIXED! I removed the check for !func_name

>
>>
>>> +{
>>> +  if (!t || !contains_array_notation_expr (t))
>>> +    return t;
>>
>> Another check for NULL without a comment saying NULL is a valid argument.
>
> This function also can receive a null pointer.

Then, document that NULL is a valid argument please.

FIXED!

> +  /* Here we assign the array notation components to variable so that we can
> +     satisfy the exec once rule.  */
> +  for (ii = 0; ii < lhs_list_size; ii++)
> +    {
> +      tree array_node = (*lhs_list)[ii];
> +      tree array_begin = ARRAY_NOTATION_START (array_node);
> +      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
> +      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
> +
> +      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
> +                           integer_type_node);
> +      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
...
...

There's a big chunk of code here that AFAICT is not part of the review.
  Did I miss something, or did this creep in somehow?

THIS CHANGE IS BASED ON A PREVIOUS EMAIL FROM YOU (ALDY) ABOUT CHECKING FOR EXECUTE-ONCE RULE (I.E. ARAY NOTATION TRIPLET VARIABLES ARE ONLY EXECUTED ONCE)

> +
> +  loop = push_stmt_list ();

Similarly here.  What's this bit part of?

THIS CHANGE IS TO ACCOMODATE THE CHANGE ABOVE.

> @@ -2407,7 +2533,42 @@ fix_array_notation_call_expr (tree arg)
>      count_down[ii] = XNEWVEC (bool, rank);
>
>    array_var = XNEWVEC (tree, rank);
> +
> +  loop = push_stmt_list ();
> +  for (ii = 0; ii < list_size; ii++)
> +    {
> +      tree array_node = (*array_list)[ii];
> +      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
> +     {
> +       tree array_begin = ARRAY_NOTATION_START (array_node);
> +       tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);

Also here.  Did I miss something?

PLEASE SEE MY COMMENTS ABOVE:

> +* Cilk Plus Builtins::  Built-in functions that are part of Cilk Plus language
> +                        extension.

Should be "Built-in functions for the Cilk Plus language extension."

FIXED!

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> index 272ef41..82008c0 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> @@ -3,16 +3,15 @@ typedef int (*foo)(int);
>  int main(int argc, char **argv)
>  {
>    int array[10], array2[10][10];
> -  // int array[10], array2[10], value, ii = 0;

Do not add commented out code.

OK. I BELIEVE THE PATCH IS SUPPOSED TO REMOVE THE COMMENT OUT. PLEASE LET ME KNOW IF I HAVE MISTAKEN SOMETHING.

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> index 5fb3680..fd128b1 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
> @@ -26,7 +26,7 @@ int main(int argc, char **argv)
>        array[ii] = 10;
>        array2[ii] = 5000000;
>      }
> -  array2[0:10:2] = array[0:10:2];
> +  array2[0:5:2] = array[0:5:2];

Is this change part of this review cycle, or is this something else?  If
the latter, then submit it as a separate patch.

THIS WAS A SMALL BUG FIX IN THE TEST CODE.

> diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> index 272ef41..82008c0 100644
> --- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> +++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
> @@ -3,16 +3,15 @@ typedef int (*foo)(int);
>  int main(int argc, char **argv)
>  {
>    int array[10], array2[10][10];
> -  // int array[10], array2[10], value, ii = 0;

Do not add commented out code.

FIXED!

Thanks for following up on this.

Could you tackle the changes I have suggested and repost the patch?

Thanks.

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 50276 bytes --]

diff --git gcc/c-family/ChangeLog.cilkplus gcc/c-family/ChangeLog.cilkplus
index 6591fd1..eb7ff47 100644
--- gcc/c-family/ChangeLog.cilkplus
+++ gcc/c-family/ChangeLog.cilkplus
@@ -1,7 +1,7 @@
 2013-03-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* c-common.c (c_define_builtins): When cilkplus is enabled, the
-	function array_notation_init_builtins() is called.
+	function array_notation_init_builtins is called.
 	(c_common_init_ts): Added ARRAY_NOTATION_REF as typed.
 	* c-common.def (ARRAY_NOTATION_REF): New tree.
 	* c-common.h (build_array_notation_expr): New function declaration.
@@ -18,5 +18,6 @@
 	(array_notation_reduce_type): New enumerator.
 	* c-pretty-print.c (pp_c_postifix_expression): Added a new case for
 	ARRAY_NOTATION_REF.
+	(pp_c_expression): Likewise.
 	* c.opt (flag_enable_cilkplus): New flag.
 	* array-notation-common.c: New file.
diff --git gcc/c-family/array-notation-common.c gcc/c-family/array-notation-common.c
index 7089c8e..b775225 100644
--- gcc/c-family/array-notation-common.c
+++ gcc/c-family/array-notation-common.c
@@ -29,19 +29,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-iterator.h"
 #include "diagnostic-core.h"
 
-int extract_sec_implicit_index_arg (location_t, tree);
-bool is_sec_implicit_index_fn (tree);
-void array_notation_init_builtins (void);
-
-/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is
-   not run as is.  */
-
-static void
-mark_cold (tree fndecl)
-{
-  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
-					DECL_ATTRIBUTES (fndecl));
-}
 
 /* This function inititializes array notation specific builtin information.  */
 
@@ -54,67 +41,56 @@ array_notation_init_builtins (void)
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_add", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_mul", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_all_zero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_any_zero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_max", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
   
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_min", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_min_ind", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_max_ind", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 				       NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_any_nonzero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_reduce_all_nonzero", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
   
   func_type = build_function_type_list (integer_type_node, integer_type_node,
 					NULL_TREE);
   new_func = build_fn_decl ("__sec_implicit_index", func_type);
-  mark_cold (new_func);
   new_func = lang_hooks.decls.pushdecl (new_func);
 
   func_type = build_function_type_list (integer_type_node, ptr_type_node,
@@ -167,25 +143,23 @@ is_sec_implicit_index_fn (tree func_name)
    sec_implicit_index function.  FN's location in the source file is is 
    indicated by LOCATION.  */
 
-int
+HOST_WIDE_INT
 extract_sec_implicit_index_arg (location_t location, tree fn)
 {
   tree fn_arg;
   HOST_WIDE_INT return_int = 0;
-  if (!fn)
-    return -1;
 
   if (TREE_CODE (fn) == CALL_EXPR)
     {
       fn_arg = CALL_EXPR_ARG (fn, 0);
       if (really_constant_p (fn_arg))
-	return_int = (int) int_cst_value (fn_arg);
+	return_int = int_cst_value (fn_arg);
       else
 	{
 	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
 	    location = EXPR_LOCATION (fn);
 	  error_at (location, "__sec_implicit_index parameter must be a " 
-		    "constant integer expression");
+		    "integer constant expression");
 	  return -1;
 	}
     }
diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h
index edcff2e..001e0c4 100644
--- gcc/c-family/c-common.h
+++ gcc/c-family/c-common.h
@@ -541,7 +541,7 @@ extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
 				       location_t, tree, tree);
 extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree);
-extern void find_rank (tree, bool, size_t *);
+extern bool find_rank (location_t, tree, tree, bool, size_t *);
 extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int field_decl_cmp (const void *, const void *);
@@ -1173,5 +1173,10 @@ typedef enum array_notation_reduce_type {
 extern int extract_sec_implicit_index_arg (location_t, tree);
 extern bool is_sec_implicit_index_fn (tree);
 extern void array_notation_init_builtins (void);
-
+extern struct c_expr fix_array_notation_expr (location_t, enum tree_code, 
+					      struct c_expr);
+extern bool contains_array_notation_expr (tree);
+extern tree expand_array_notation_exprs (tree);
+extern tree fix_conditional_array_notations (tree);
+extern tree find_correct_array_notation_type (tree);
 #endif /* ! GCC_C_COMMON_H */
diff --git gcc/c-family/c-pretty-print.c gcc/c-family/c-pretty-print.c
index 30c8e80..b8af90c 100644
--- gcc/c-family/c-pretty-print.c
+++ gcc/c-family/c-pretty-print.c
@@ -1479,11 +1479,11 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
     case ARRAY_NOTATION_REF:
       pp_postfix_expression (pp, ARRAY_NOTATION_ARRAY (e));
       pp_c_left_bracket (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_START (e));
+      pp_expression (pp, ARRAY_NOTATION_START (e));
       pp_colon (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e));
+      pp_expression (pp, ARRAY_NOTATION_LENGTH (e));
       pp_colon (pp);
-      pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e));
+      pp_expression (pp, ARRAY_NOTATION_STRIDE (e));
       pp_c_right_bracket (pp);
       break;
       
@@ -2161,6 +2161,7 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case CALL_EXPR:
     case COMPONENT_REF:
     case BIT_FIELD_REF:
diff --git gcc/c/c-array-notation.c gcc/c/c-array-notation.c
index 38ed7ea..9ee281e 100755
--- gcc/c/c-array-notation.c
+++ gcc/c/c-array-notation.c
@@ -31,19 +31,17 @@
 #include "gcc.h"
 #include "c-family/c-common.h"
 
-void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
+static 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 void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
+static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
 static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var);
-bool contains_array_notation_expr (tree expr);
-tree expand_array_notation_exprs (tree t);
 
 
+/* This structure holds all the scalar values and its appropriate variable 
+   replacment.  It is mainly used by the function that pulls all the invariant
+   parts that should be executed only once, which comes with array notation 
+   expressions.  */
 struct inv_list
 {
   vec<tree, va_gc> *list_values;
@@ -51,72 +49,84 @@ struct inv_list
 };
 
 
-/* Returns the rank of ARRAY through the *RANK.  The user can specify whether
-   (s)he wants to step into array_notation-specific builtin functions
-   (specified by the IGNORE_BUILTIN_FN).
+/* Set *RANK of expression ARRAY, ignoring array notation specific built-in 
+   functions if IGNORE_BUILTIN_FN is true.  The ORIG_EXPR is printed out if an
+   error occured in the rank calculation.  The functions returns false if it
+   encounters an error in rank calculation.  If ARRAY can be NULL, since it is
+   recursively accessing all the fields in a subtree.  If so, then just return
+   true.
 
    For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0]
    all have a rank of 2.  */
 
-void
-find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
+bool
+find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn,
+	   size_t *rank)
 {
   tree ii_tree;
-  size_t current_rank = 0, ii = 0;
+  size_t ii = 0, current_rank = 0;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
   if (!array)
-    return;
+    return true;
   else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
     {
       for (ii_tree = array;
 	   ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
 	   ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
 	current_rank++;
-      if (*rank == 0)
-	*rank = current_rank;
+	if (*rank == 0)
+	  *rank = current_rank;
+	else if (*rank != current_rank)
+	  {
+	    error_at (loc, "rank mismatch in expression %qE", orig_expr);
+	    return false;
+	  }
     }
   else if (TREE_CODE (array) == STATEMENT_LIST)
     {
       tree_stmt_iterator ii_tsi;
       for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi);
 	   tsi_next (&ii_tsi))
-	find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank);
+	if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
+			ignore_builtin_fn, rank))
+	  return false;
     }
   else
     {
       if (TREE_CODE (array) == CALL_EXPR)
 	{
 	  tree func_name = CALL_EXPR_FN (array);
+	  tree arg;
+	  call_expr_arg_iterator iter;
 	  if (TREE_CODE (func_name) == ADDR_EXPR)
 	    if (!ignore_builtin_fn)
 	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
-		/* If it is a builtin function, then we know it returns a 
-		   scalar.  */
-		return;
-	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
-	    {
-	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
-	      for (ii = 0; ii < (size_t) length; ii++)
-		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
-	    }
-	  else
-	    gcc_unreachable ();
+		/* If it is a builtin function, then it returns a scalar.  */
+		return true;
+
+	  FOR_EACH_CALL_EXPR_ARG (arg, iter, array)
+	    if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
+	      return false;
 	}
       else 
 	for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) 
-	  find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+	  if (!find_rank (loc, orig_expr, TREE_OPERAND (array, ii),
+			  ignore_builtin_fn, rank))
+	    return false;
     }
-  return;
+  return true;
 }
   
 
-/* Extracts all the array notations specified in NODE and stores them in a
-   dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE.  The
-   user can specify if (s)he wants to ignore the array notations inside the
-   array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
-   true).  */
+/* Extracts all array notations in NODE and stores them in ARRAY_LIST.  If 
+   IGNORE_BUILTIN_FN is set, then array notations inside array notation
+   specific builtin functions are ignored.  The NODE can be anything from a
+   full function to a single variable.  Since function is stepping through all
+   the subtrees, there is a good chance that node can be a NULL_TREE.  If so,
+   then the function just returns.  */
 
-void
+static void
 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 			      vec<tree, va_gc> **array_list)
 {
@@ -148,6 +158,8 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
     }
   else if (TREE_CODE (node) == CALL_EXPR)
     {
+      tree arg;
+      call_expr_arg_iterator iter;
       if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
 	{
 	  if (ignore_builtin_fn)
@@ -163,17 +175,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
-      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
-	{
-	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
 
-	  for (ii = 0; ii < (size_t) length; ii++)
-	    extract_array_notation_exprs
-	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
-	}
-      else
-	gcc_unreachable (); /* We should not get here.  */
-	  
+      FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
+	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
   else 
     for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
@@ -183,15 +187,15 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 }
 
 
-/* Replaces all occurances of array notations in tree ORIG that matches the
-   ones in LIST with the one in ARRAY_OPERAND.  The size of list and
-   ARRAY_OPERAND is ARRAY_SIZE.  For example, ARRAY_OPERAND[x] for some index
-   'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified
-   in LIST[x].   The  user can specify if (s)he wants to ignore the array
-   notations inside the array-notation specific builtin functions (using the
-   bool variable IGNORE_BUILTIN_FN).  */
+/* Replaces all the occurances of array notations in *LIST with the appropriate
+   one in ARRAY_OPERAND.  If IGNORE_BUILTIN_FN is set, then array notations
+   inside array-notation specific builtin functions are ignored.  ORIG can be
+   anything from a collection of statement lists to a single variable.  Since
+   this function steps through all the subtrees, it is probable that *ORIG can
+   be a NULL_TREE.  If so, then the function just returns.
+*/
 
-void
+static void
 replace_array_notations (tree *orig, bool ignore_builtin_fn,
 			 vec<tree, va_gc> *list,
 			 vec<tree, va_gc> *array_operand)
@@ -221,6 +225,8 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
     }
   else if (TREE_CODE (*orig) == CALL_EXPR)
     {
+      tree arg;
+      call_expr_arg_iterator iter;
       if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
 	{
 	  if (!ignore_builtin_fn)
@@ -244,16 +250,14 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
-      if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
+      ii = 0;
+      FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
-	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
-	  for (ii = 0; ii < (size_t) length; ii++)
-	    replace_array_notations
-	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
-	       array_operand);
-	}
-      else
-	gcc_unreachable (); /* We should not get here!  */
+	  replace_array_notations (&arg, ignore_builtin_fn, list,
+				   array_operand);
+	  CALL_EXPR_ARG (*orig, ii) = arg;
+	  ii++;
+	}     
     }
   else
     {
@@ -264,9 +268,11 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
   return;
 }
 
-/* This function will find all the scalar expressions in *TP and push it in
-   DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 then
-   we have do not go into the *TP's subtrees.  */
+/* Find all the scalar expressions in *TP and push them in DATA struct, 
+   typecasted to (void *).  If *WALK_SUBTREES is set to 0 then do not go into 
+   the *TP's subtrees.  Since this function steps through all the subtrees, *TP
+   and TP can be both NULL_TREE and NULL respectively.  If so, then the function
+   just returns NULL_TREE.  */
 
 static tree
 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
@@ -322,7 +328,11 @@ replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-/* Replaces all the scalar expressions in *NODE. */
+/* Replaces all the scalar expressions in *NODE.  Returns a STATEMENT_LIST that
+   holds the NODE along with variables that holds the results of the invariant
+   expressions.  Since this function steps through all the subtrees, it is
+   probable than *NODE or NODE can be NULL_TREE and NULL respectively.  If so,
+   then the function just returns NULL_TREE.  */
 
 tree
 replace_invariant_exprs (tree *node)
@@ -331,6 +341,7 @@ replace_invariant_exprs (tree *node)
   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;
 
@@ -398,7 +409,9 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
      already.  Not necessary to send out multiple error messages.  */
   if (lhs == error_mark_node || rhs == error_mark_node)
     return error_mark_node;
-  find_rank (rhs, false, &rhs_rank);
+  
+  if (!find_rank (location, rhs, rhs, false, &rhs_rank))
+    return error_mark_node;
   
   extract_array_notation_exprs (rhs, false, &rhs_list);
   rhs_list_size = vec_safe_length (rhs_list);
@@ -435,8 +448,11 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 
   lhs_rank = 0;
   rhs_rank = 0;
-  find_rank (lhs, true, &lhs_rank);
-  find_rank (rhs, true, &rhs_rank);
+  if (!find_rank (location, lhs, lhs, true, &lhs_rank))
+    return error_mark_node;
+  
+  if (!find_rank (location, rhs, rhs, true, &rhs_rank))
+    return error_mark_node;
 
   if (lhs_rank == 0 && rhs_rank == 0)
     {
@@ -467,12 +483,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
   if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
     {
       tree rhs_base = rhs;
-      for (ii = 0; ii < (size_t) rhs_rank; ii++)
-	rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+	{
+	  for (ii = 0; ii < (size_t) rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
       
-      error_at (location, "%qD cannot be scalar when %qD is not", lhs,
-		rhs_base);
-      return error_mark_node;
+	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+		    rhs_base);
+	  return error_mark_node;
+	}
+      else
+	{
+	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+		    rhs_base);
+	  return error_mark_node;
+	}
+
     }
   if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
     {
@@ -745,8 +771,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	  rhs_vector[ii][jj] = false;
     }
 
-
-
   for (ii = 0; ii < lhs_rank; ii++)
     {
       if (lhs_vector[0][ii])
@@ -758,7 +782,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	     NOP_EXPR,
 	     location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
 	     TREE_TYPE (lhs_var[ii]));
-	  
 	}
     }
 
@@ -1032,19 +1055,19 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
     }
   
   /* 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>
-   */
+     <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++)
@@ -1079,7 +1102,9 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 
 /* Encloses the conditional statement passed in STMT with a loop around it
    and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
-   The condition must have a ARRAY_NOTATION_REF tree.  */
+   The condition must have a ARRAY_NOTATION_REF tree.  An expansion of array
+   notation in STMT is returned in a STATEMENT_LIST.  */
+   
 
 static tree
 fix_conditional_array_notations_1 (tree stmt)
@@ -1105,7 +1130,11 @@ fix_conditional_array_notations_1 (tree stmt)
     /* Otherwise dont even touch the statement.  */
     return stmt;
 
-  find_rank (cond, false, &rank);
+  location = EXPR_LOCATION (stmt);
+  
+  if (!find_rank (location, cond, cond, false, &rank))
+    return error_mark_node;
+  
   extract_array_notation_exprs (cond, false, &array_list);
   loop = push_stmt_list ();
   for (ii = 0; ii < vec_safe_length (array_list); ii++)
@@ -1130,7 +1159,9 @@ fix_conditional_array_notations_1 (tree stmt)
 	    }
 	}
     }
-  find_rank (cond, true, &rank);
+
+  if (!find_rank (location, cond, cond, true, &rank))
+    return error_mark_node;
   if (rank == 0)
     {
       add_stmt (stmt);
@@ -1144,7 +1175,6 @@ fix_conditional_array_notations_1 (tree stmt)
     return stmt;
 
   list_size = vec_safe_length (array_list);
-  location = EXPR_LOCATION (stmt);
 
   array_ops =  XNEWVEC (tree *, list_size);
   for (ii = 0; ii < list_size; ii++)
@@ -1278,7 +1308,6 @@ fix_conditional_array_notations_1 (tree stmt)
 			   location,
 			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
 			   TREE_TYPE (array_var[ii]));
-	
     }
 
   for (ii = 0; ii < rank ; ii++)
@@ -1457,7 +1486,15 @@ fix_array_notation_expr (location_t location, enum tree_code code,
   tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
   bool **count_down, **array_vector;
   
-  find_rank (arg.value, false, &rank);
+  if (!find_rank (location, arg.value, arg.value, false, &rank))
+    {
+      /* If this function returns a NULL, we convert the tree value in the
+	 structure to error_mark_node and the parser should take care of the
+	 rest.  */
+      arg.value = error_mark_node;
+      return arg;
+    }
+  
   if (rank == 0)
     return arg;
   
@@ -1634,12 +1671,10 @@ fix_array_notation_expr (location_t location, enum tree_code code,
   replace_array_notations (&arg.value, true, array_list, array_operand);
 
   for (ii = 0; ii < rank; ii++)
-    {
-      expr_incr[ii] =
-	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
-		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
-			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
-    }
+    expr_incr[ii] =
+      build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+	      build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+		      build_int_cst (TREE_TYPE (array_var[ii]), 1)));
   
   for (jj = 0; jj < rank; jj++)
     {
@@ -1656,7 +1691,6 @@ fix_array_notation_expr (location_t location, enum tree_code code,
 				       array_var[jj], array_length[0][jj]);
 	}
     }
-
   
   for (ii = 0; ii < rank; ii++)
     {
@@ -1772,10 +1806,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
 	 || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
 	 || TREE_CODE (func_parm) == NOP_EXPR)
     func_parm = TREE_OPERAND (func_parm, 0);
-  
-  find_rank (an_builtin_fn, true, &rank);
 
   location = EXPR_LOCATION (an_builtin_fn);
+  
+  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
+    return error_mark_node;
  
   if (rank == 0)
     return an_builtin_fn;
@@ -1783,7 +1818,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
 	   && (an_type == REDUCE_MAX_INDEX  || an_type == REDUCE_MIN_INDEX))
     {
       error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
-		" have arrays with dimension greater than 1.");
+		" have arrays with dimension greater than 1");
       return error_mark_node;
     }
   
@@ -1815,7 +1850,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
       new_var_type = NULL_TREE;
       break;
     default:
-      gcc_unreachable ();  /* You should not reach here.  */
+      gcc_unreachable (); 
     }
   
   array_ops = XNEWVEC (tree *, list_size);
@@ -1982,12 +2017,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
     }
   replace_array_notations (&func_parm, true, array_list, array_operand);
   for (ii = 0; ii < rank; ii++)
-    {
-      expr_incr[ii] =
-	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
-		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
-			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
-    }
+    expr_incr[ii] =
+      build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+	      build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+		      build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+    
   
   for (jj = 0; jj < rank; jj++)
     {
@@ -2321,17 +2355,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
   return loop;
 }
 
-/* Returns true of FUNC_NAME is a builtin array notation function.  The type of
+/* Returns true if FUNC_NAME is a builtin array notation function.  The type of
    function is returned in *TYPE.  */
 
-bool
+static bool
 is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 {
   const char *function_name = NULL;
 
-  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)
@@ -2413,7 +2444,7 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 }
 
 
-/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
+/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
 
 bool
 contains_array_notation_expr (tree expr)
@@ -2434,9 +2465,8 @@ contains_array_notation_expr (tree expr)
     return true;
 }
 
-/* Replaces array notations in void function call arguments in ARG with loop and
-   tree-node ARRAY_REF and returns that value in a tree node variable called
-   LOOP.  */
+/* Replaces array notations in void function call arguments in ARG and returns
+   a STATEMENT_LIST.  */
 
 static tree
 fix_array_notation_call_expr (tree arg)
@@ -2463,12 +2493,13 @@ fix_array_notation_call_expr (tree arg)
       return loop;
     }
   
-  find_rank (arg, false, &rank);
+  if (!find_rank (location, arg, arg, false, &rank))
+    return error_mark_node;
+  
   if (rank == 0)
     return arg;
   
   extract_array_notation_exprs (arg, true, &array_list);
-
   if (vec_safe_length (array_list) == 0)
     return arg;
   
@@ -2747,7 +2778,10 @@ fix_array_notation_call_expr (tree arg)
 
 
 /* Walks through tree node T and find all the call-statments that do not return
-   anything and fix up any array notations they may carry.  */
+   anything and fix up any array notations they may carry.  The return value
+   is the same type as T but with all array notations replaced with appropriate
+   STATEMENT_LISTS.  Since this function recursively steps through all the
+   subtrees, t can be a NULL_TREE.  If so, then the function just returns.  */
 
 tree
 expand_array_notation_exprs (tree t)
@@ -2802,20 +2836,22 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
   tree array_ntn_tree = NULL_TREE;
   size_t stride_rank = 0, length_rank = 0, start_rank = 0;
   
-  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
     {
       error_at (loc,
-		"start-index of array notation triplet is not an integer.");
+		"start-index of array notation triplet is not an integer");
       return error_mark_node;
     }
-  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
     {
-      error_at (loc, "length of array notation triplet is not an integer.");
+      error_at (loc, "length of array notation triplet is not an integer");
       return error_mark_node;
     }
-  if (stride && (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))))
+
+  /* The stride is an optional field.  */
+  if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
     {
-      error_at (loc, "stride of array notation triplet is not an integer.");
+      error_at (loc, "stride of array notation triplet is not an integer");
       return error_mark_node;
     }  
   if (!stride)
@@ -2827,24 +2863,27 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
 	stride = build_int_cst (TREE_TYPE (start_index), 1);
     }	      
 
-  find_rank (start_index, false, &start_rank);
-  find_rank (length, false, &length_rank);
-  find_rank (stride, false, &stride_rank);
+  if (!find_rank (loc, start_index, start_index, false, &start_rank))
+    return error_mark_node;
+  if (!find_rank (loc, length, length, false, &length_rank))
+    return error_mark_node;
+  if (!find_rank (loc, stride, stride, false, &stride_rank))
+    return error_mark_node;
 
   if (start_rank != 0)
     {
       error_at (loc, "rank of an array notation triplet's start-index is not "
-		"zero.");
+		"zero");
       return error_mark_node;
     }
   if (length_rank != 0)
     {
-      error_at (loc, "rank of an array notation triplet's length is not zero.");
+      error_at (loc, "rank of an array notation triplet's length is not zero");
       return error_mark_node;
     }
   if (stride_rank != 0)
     {
-      error_at (loc, "rank of array notation triplet's stride is not zero.");
+      error_at (loc, "rank of array notation triplet's stride is not zero");
       return error_mark_node;
     }
   
@@ -2884,4 +2923,3 @@ find_correct_array_notation_type (tree op)
     } 
   return return_type;
 }
-
diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index ba0a7f9..f051ab5 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -56,12 +56,6 @@ along with GCC; see the file COPYING3.  If not see
 #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);
-
 \f
 /* Initialization routine for this file.  */
 
@@ -3082,7 +3076,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
 	      dimen = error_mark_node;
 	      star_seen = false;
 	      error_at (c_parser_peek_token (parser)->location,
-			"array notations cannot be used in declaration.");
+			"array notations cannot be used in declaration");
 	      c_parser_consume_token (parser);
 	    }   
 	  else if (c_parser_next_token_is (parser, CPP_MULT))
@@ -3111,7 +3105,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
 	       && c_parser_next_token_is (parser, CPP_COLON))
 	{
 	  error_at (c_parser_peek_token (parser)->location,
-		    "array notations cannot be used in declaration.");
+		    "array notations cannot be used in declaration");
 	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	  return NULL;
 	}
@@ -5068,10 +5062,11 @@ c_parser_for_statement (c_parser *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.");
+			    "condition for a for-loop");
 		  cond = error_mark_node;
 		}
-	      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+	      c_parser_skip_until_found (parser, CPP_SEMICOLON,
+					 "expected %<;%>");
 	    }
 	}
       /* Parse the increment expression (the third expression in a
@@ -11023,9 +11018,8 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   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)
+  if (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.  */
@@ -11038,7 +11032,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   type = TREE_TYPE (array_type);
   token = c_parser_peek_token (parser);
    
-  if (token == NULL)
+  if (token->type == CPP_EOF)
     {
       c_parser_error (parser, "expected %<:%> or numeral");
       return value_tree;
@@ -11052,14 +11046,14 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (TREE_CODE (array_type) == POINTER_TYPE)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in pointers.");
+			"using array notations in pointers");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
 	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
 	    {
 	      error_at (loc, "array notations cannot be used with function "
-			"type.");
+			"type");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11074,7 +11068,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
 		    {
 		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays.");
+				"function pointer arrays");
 		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
 						 NULL);
 		      return error_mark_node;
@@ -11086,7 +11080,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (!array_type_domain)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in dimensionless arrays.");
+			"using array notations in dimensionless arrays");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11098,13 +11092,13 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in variable-length arrays.");
+			"using array notations in variable-length arrays");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
-	  x.low++;
-	  end_index = double_int_to_tree (integer_type_node, x);
+	  end_index = TYPE_MAXVAL (array_type_domain);
+	  end_index = fold_build2 (PLUS_EXPR, TREE_TYPE (end_index),
+				   end_index, integer_one_node);
 	  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);
@@ -11120,7 +11114,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	  if (TREE_CODE (array_type) == FUNCTION_TYPE)
 	    {
 	      error_at (loc, "array notations cannot be used with function "
-			"type.");
+			"type");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
@@ -11138,7 +11132,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
 		    {
 		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays.");
+				"function pointer arrays");
 		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
 						 NULL);
 		      return error_mark_node;
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 15dc83d..59658b7 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -103,8 +103,6 @@ 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);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -2305,14 +2303,15 @@ 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 (!find_rank (loc, index, index, true, &rank))
+	return error_mark_node;
       if (rank > 1)
 	{
-	  error_at (loc, "rank of the array's index is greater than 1.");
+	  error_at (loc, "rank of the array's index is greater than 1");
 	  return error_mark_node;
 	}
     }
@@ -5130,6 +5129,7 @@ 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;
@@ -9035,13 +9035,13 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
   if (flag_enable_cilkplus && contains_array_notation_expr (cond))
     {
       error_at (start_locus, "array notation expression cannot be used in a "
-		"loop's condition");
+		"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.");
+		"loop's increment expression");
       return;
     }
   
diff --git gcc/doc/extend.texi gcc/doc/extend.texi
index 627bf69..b22eb79 100644
--- gcc/doc/extend.texi
+++ gcc/doc/extend.texi
@@ -82,6 +82,7 @@ extensions, accepted by GCC in C90 mode and in C++.
 * x86 specific memory model extensions for transactional memory:: x86 memory models.
 * Object Size Checking:: Built-in functions for limited buffer overflow
                         checking.
+* Cilk Plus Builtins::  Built-in functions for the Cilk Plus language extension.
 * Other Builtins::      Other built-in functions.
 * Target Builtins::     Built-in functions specific to particular targets.
 * Target Format Checks:: Format checks specific to particular targets.
@@ -8762,6 +8763,31 @@ Similar to @code{__builtin_bswap32}, except the argument and return types
 are 64 bit.
 @end deftypefn
 
+@node Cilk Plus Builtins
+@section Cilk Plus C/C++ language extension Built-in Functions.
+
+GCC provides support for the following built-in reduction funtions if Cilk Plus
+is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
+
+@itemize @bullet
+@item __sec_reduce
+@item __sec_reduce_add
+@item __sec_reduce_all_nonzero
+@item __sec_reduce_all_zero
+@item __sec_reduce_any_nonzero
+@item __sec_reduce_any_zero
+@item __sec_reduce_max
+@item __sec_reduce_min
+@item __sec_reduce_max_ind
+@item __sec_reduce_min_ind
+@item __sec_reduce_mul
+@item __sec_reduce_mutating
+@end itemize
+
+Further details and examples about these built-in functions are described 
+in the Cilk Plus language manual which can be found at 
+@uref{http://www.cilkplus.org}.
+
 @node Target Builtins
 @section Built-in Functions Specific to Particular Target Machines
 
diff --git gcc/doc/passes.texi gcc/doc/passes.texi
index 81b6502..045f964 100644
--- gcc/doc/passes.texi
+++ gcc/doc/passes.texi
@@ -125,25 +125,7 @@ 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}.  In
-the current array notation implementation there are 12 builtin reduction
-operations.  Details about these functions and their usage are available in
-the Cilk Plus language specification at @w{@uref{http://www.cilkplus.org}}.
-
-@itemize @bullet
-@item __sec_reduce_add
-@item __sec_reduce_mul
-@item __sec_reduce_max
-@item __sec_reduce_min
-@item __sec_reduce_max_ind
-@item __sec_reduce_min_ind
-@item __sec_reduce_all_zero
-@item __sec_reduce_all_nonzero
-@item __sec_reduce_any_zero
-@item __sec_reduce_any_nonzero
-@item __sec_reduce
-@item __sec_reduce_mutating
-@end itemize
+initialize builtin functions are stored in @file{array-notation-common.c}.
 @end itemize
 
 Detailed information about Cilk Plus and language specification is provided in 
diff --git gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
index 44e7361..4035ed5 100644
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
@@ -1,16 +1,16 @@
 int main(void)
 {
   extern int func(int);
-  int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration." } */
-  int  array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration." } */
-  extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration." } */
+  int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration" } */
+  int  array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration" } */
+  extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration" } */
   int *a, ***b;
   extern char *c;
   int array2[10];
 
-  a[:] = 5; /* { dg-error  "start-index and length fields necessary for using array notations in pointers." } */
+  a[:] = 5; /* { dg-error  "start-index and length fields necessary for using array notations in pointers" } */
   c[1:2] =  3; /* This is OK.  */
   (array2)[:] = 5; /* This is OK.  */
-  b[1:2][1:func(x)][:] = 3; /*  { dg-error  "start-index and length fields necessary for using array notations in pointers." }  */
+  b[1:2][1:func(x)][:] = 3; /*  { dg-error  "start-index and length fields necessary for using array notations in pointers" }  */
 }
 
diff --git gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
index 272ef41..82008c0 100644
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
@@ -3,16 +3,15 @@ typedef int (*foo)(int);
 int main(int argc, char **argv)
 {
   int array[10], array2[10][10];
-  // int array[10], array2[10], value, ii = 0;
   foo func_array[10];
   foo func_array2[10][10];
   foo ***func_array_ptr;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
 
   return 0;
 }
diff --git gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
index ef39b2b..59c2d1e 100644
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
@@ -25,18 +25,18 @@ void func (int *x)
 int main2 (int argc, char **argv)
 {
   int array[10], array2[10];
-  array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer." } */
-  func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer." } */
+  array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer" } */
   
-  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer." } */
-  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
-  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer." } */
-  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer." } */
+  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */
   return 0;
 } 
diff --git gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c
index 5a987d7..90a22eb 100644
--- gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/misc.c
@@ -47,17 +47,17 @@ int main (int argc, char **argv)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop." } */
+  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." } */
+  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." } */
+  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
diff --git gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
new file mode 100644
index 0000000..77955a3
--- /dev/null
+++ gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
@@ -0,0 +1,23 @@
+int function_call (int x)
+{
+  return x;
+}
+
+int main(int argc, char **argv)
+{
+  int array[100], array2[100][100];
+
+  array[:] = array[:] + array2[:][:]; /* { dg-error "rank mismatch in expression" } */
+
+  if (array[:] + array2[:][:]) /* { dg-error "rank mismatch in expression" } */
+    return argc == 5;
+
+  argc += function_call (array[:] + array2[5:10:2][:]); /* { dg-error "rank mismatch in expression" } */
+
+  argc += function_call (function_call (array[:] + array2[5:10:2][:])); /* { dg-error "rank mismatch in expression" } */
+
+   argc += __sec_reduce_add (array[:], array2[:][:]); /* { dg-error "rank mismatch in expression" } */
+
+   argc += __sec_reduce_add (array2[:][:]) + argc; /* This is OK.  */
+  return argc;
+}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-25 21:39       ` Iyer, Balaji V
@ 2013-03-25 21:49         ` Aldy Hernandez
  0 siblings, 0 replies; 28+ messages in thread
From: Aldy Hernandez @ 2013-03-25 21:49 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, Joseph Myers [joseph@codesourcery.com]

>>> The specification doesn't seem very clear on to what extent the __sec_*
>>> operations must act like functions (what happens if someone puts parentheses
>>> around the __sec_* name, for example - that wouldn't work with the keyword
>>> approach).  So the specification should be clarified there, but I think saying the
>>> __sec_* operations are syntactically special, like keywords, is more appropriate
>>> than requiring other uses to work.
>>>
>>>> +   return_int = (int) int_cst_value (fn_arg);
>>>> +      else
>>>> +   {
>>>> +     if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
>>>> +       location = EXPR_LOCATION (fn);
>>>> +     error_at (location, "__sec_implicit_index parameter must be a "
>>>> +               "constant integer expression");
>>>
>>> The term is "integer constant expression" not "constant integer expression".
>>
>> FIXED!
>
> ...it looks like you're going to have to rework all this as a keyword.
>
> OK, CAN I LOOK AT THIS AFTER WE FINISH THE BUILTIN FUNCTION IMPLEMENTATION FIX?

Yes.

Thank you for fixing everything I pointed out.  Let's now wait for 
Joseph to give the final ok.  There are some things he suggested, that I 
didn't look at at all, so I am deferring to him.

Thanks again.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-22 22:04   ` Iyer, Balaji V
  2013-03-25 16:45     ` Aldy Hernandez
@ 2013-03-26 16:27     ` Joseph S. Myers
  1 sibling, 0 replies; 28+ messages in thread
From: Joseph S. Myers @ 2013-03-26 16:27 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, aldyh

On Fri, 22 Mar 2013, Iyer, Balaji V wrote:

> > Why the random check for a NULL argument?  If a NULL argument is valid
> > (meaning that it makes the code cleaner to allow such arguments rather than
> > making sure the function isn't called with them), this should be documented in
> > the comment above the function; otherwise, if such an argument isn't valid,
> > there is no need to check for it.
> 
> I always tend to check for a null pointer before I access the fields in 
> the structure. In this case it is unnecessary. In some cases (e.g. 
> find_rank) there is a good chance a null pointer will be passed into the 
> function and we need to check that and reject those.

"always tend to check for a null pointer" is not good practice.  
Sometimes such checks are good, and sometimes they are bad.

Each function should have a defined interface that makes clear the 
semantics and valid values of its operands - including whether NULL is 
valid, and, if so, what the semantics of a NULL argument are.  These 
semantics should be clear from the comment above the function.

What the semantics should be in each case depends on a global view of the 
relevant code.  Based on such a global view you need to determine the 
interfaces resulting in the cleanest code - in some cases there may be a 
special case, the absence of a datastructure as opposed to its presence, 
that is naturally represented by a NULL argument, but in that case it's a 
judgement to be made for the code as a whole whether this case should be 
checked for in the caller or the callee (or maybe further up or down the 
call stack in some cases).  Where erroneous input to the compiler is the 
cause of NULL arguments, passing error_mark_node may be better in some 
cases if it means fewer special-case checks.

If in a particular case it shouldn't be possible for a NULL pointer to be 
present in a particular place (function argument, variable, etc.), for any 
input to the compiler, it is always wrong to have a check for a NULL 
pointer that silently continues compilation.  Instead, in such cases where 
NULL is invalid you have two options:

* No check, if NULL is present and dereferenced the compiler will crash.

* A check inside a gcc_assert, to verify this precondition of the function 
and give a slightly friendlier internal compiler error than a segfault.  
(Or any other similar option resulting in an abort with an ICE.)

You need to judge in each case which of the two is appropriate, just as 
with any other case where there is some precondition for a function that 
you might or might not decide to verify with an assertion, depending on 
factors such as:

* how complicated such a check is to write;

* how expensive the check is when the compiler runs;

* how likely the check is to find bugs in the compiler;

* how helpful the check's presence is to people reading the source code 
and trying to understand what the data may look like at a particular 
point.

Note also that the fact that you observe a NULL pointer being passed to a 
function and causing a crash there does not of itself mean that adding a 
check for NULL is a valid fix.  It's only a valid fix if analysis of the 
issue shows that it was indeed correct for NULL to be passed to that 
function for the given input to the compiler.  Sometimes it may turn out 
that NULL shouldn't have been passed to that function at all for that 
input and that the proper fix is elsewhere in the compiler.

> > > +  if (TREE_CODE (fn) == CALL_EXPR)
> > > +    {
> > > +      fn_arg = CALL_EXPR_ARG (fn, 0);
> > > +      if (really_constant_p (fn_arg))
> > 
> > I don't think really_constant_p is what's wanted;
> > <http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
> > Intel_Cilk_plus_lang_spec_2.htm>
> > says "The argument shall be an integer constant expression.", and such
> > expressions always appear in the C front end as INTEGER_CST.  So you can just
> > check for INTEGER_CST.
> 
> What about C++? This function is shared by both C and C++.

This patch seems just to be for C.  really_constant_p is wrong for C, 
since INTEGER_CSTs wrapped with conversions can be used to represent 
values folded to constants that aren't integer constant expressions.  
Maybe you need a conditional on the language, but I don't know what the 
right check for C++ might be in that case.

> > > +void
> > > +find_rank (tree array, bool ignore_builtin_fn, size_t *rank) {
> > > +  tree ii_tree;
> > > +  size_t current_rank = 0, ii = 0;
> > > +  an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > > +  if (!array)
> > > +    return;
> > 
> > As before, avoid random checks for NULL parameters unless there is an actual
> > reason to allow them and the comments document that they are allowed and
> > what the semantics are in that case.  In general, explain what ARRAY is - an
> > expression?
> 
> This check is necessary. Find rank can get a NULL pointer and that must 
> be caught and rejected.

Then make sure the comment explaining the semantics of ARRAY includes the 
case of a NULL pointer, explaining what the semantics of such a pointer 
are and what the semantics of the function are in that case.

> > What's NODE?  My first guess would have been an expression, but if a TREE_LIST
> > is possible that's clearly not the answer, so explain in the comment above the
> > function what NODE is.  (If a TREE_LIST is being used within expressions to store
> > something specific to array notation, don't do so - TREE_LIST is deprecated,
> > existing uses should be phased out in favour of more specific and less memory-
> > hungry datastructures and new uses should not be added.)
> 
> FIXED! What is replacing tree-list? I have used tree-list in my later 
> patches and in my Cilk Plus branch.

TREE_LIST is replaced by whatever datastructure is appropriate in each 
case.  When possible, that structure has a static type other than "tree", 
specific to the particular case in question; it may be an ad hoc type in 
GCC, or use GCC-specific infrastructure such as vec.h, or standard C++ 
library features where there aren't problems with interaction with garbage 
collection.  If in doubt about how to represent something without using 
TREE_LIST, post details of the particular datastructure and how it is used 
to the gcc@ list.

TREE_LISTs have TYPE, CHAIN, VALUE and PURPOSE pointers as well as a 
TREE_CODE.  It's rare for all of these to be used, so they are generally 
particularly memory-inefficient.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-25 16:45     ` Aldy Hernandez
  2013-03-25 21:39       ` Iyer, Balaji V
@ 2013-03-26 17:05       ` Joseph S. Myers
  2013-03-26 21:11         ` Iyer, Balaji V
  1 sibling, 1 reply; 28+ messages in thread
From: Joseph S. Myers @ 2013-03-26 17:05 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Iyer, Balaji V, gcc-patches

On Mon, 25 Mar 2013, Aldy Hernandez wrote:

> > I always tend to check for a null pointer before I access the fields in the
> > structure. In this case it is unnecessary. In some cases (e.g. find_rank)
> > there is a good chance a null pointer will be passed into the function and
> > we need to check that and reject those.
> 
> I think what Joseph is suggesting is that if NULL is not valid, then the
> caller should check this.  But if NULL is valid, then it should be documented
> in the function comment at the top.

The caller should only check it if it's valid in the caller but not the 
callee.  If it's invalid in the caller as well, neither should check 
(except maybe in an assertion if felt appropriate in a particular case).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
  2013-03-26 17:05       ` Joseph S. Myers
@ 2013-03-26 21:11         ` Iyer, Balaji V
  0 siblings, 0 replies; 28+ messages in thread
From: Iyer, Balaji V @ 2013-03-26 21:11 UTC (permalink / raw)
  To: Joseph Myers, Aldy Hernandez; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1488 bytes --]

Hello Joseph, Aldy et al.,
	Attached please find a patch that will fixed the problem below and another problem you mentioned in a previous email (I had used really_constant_p(..) and you mentioned that in C we need to check for INTEGER_CST).

Please let me know if I have missed anything else that you mentioned.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Joseph Myers [mailto:joseph@codesourcery.com]
> Sent: Tuesday, March 26, 2013 1:05 PM
> To: Aldy Hernandez
> Cc: Iyer, Balaji V; gcc-patches@gcc.gnu.org
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
> 
> On Mon, 25 Mar 2013, Aldy Hernandez wrote:
> 
> > > I always tend to check for a null pointer before I access the fields
> > > in the structure. In this case it is unnecessary. In some cases
> > > (e.g. find_rank) there is a good chance a null pointer will be
> > > passed into the function and we need to check that and reject those.
> >
> > I think what Joseph is suggesting is that if NULL is not valid, then
> > the caller should check this.  But if NULL is valid, then it should be
> > documented in the function comment at the top.
> 
> The caller should only check it if it's valid in the caller but not the callee.  If it's
> invalid in the caller as well, neither should check (except maybe in an assertion if
> felt appropriate in a particular case).

FIXED!

> 
> --
> Joseph S. Myers
> joseph@codesourcery.com

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 8255 bytes --]

diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index b775225..894c02a 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -152,7 +152,7 @@ extract_sec_implicit_index_arg (location_t location, tree fn)
   if (TREE_CODE (fn) == CALL_EXPR)
     {
       fn_arg = CALL_EXPR_ARG (fn, 0);
-      if (really_constant_p (fn_arg))
+      if (TREE_CODE (fn_arg) == INTEGER_CST)
 	return_int = int_cst_value (fn_arg);
       else
 	{
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index 9ee281e..dd0a1b0 100755
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -52,9 +52,7 @@ struct inv_list
 /* Set *RANK of expression ARRAY, ignoring array notation specific built-in 
    functions if IGNORE_BUILTIN_FN is true.  The ORIG_EXPR is printed out if an
    error occured in the rank calculation.  The functions returns false if it
-   encounters an error in rank calculation.  If ARRAY can be NULL, since it is
-   recursively accessing all the fields in a subtree.  If so, then just return
-   true.
+   encounters an error in rank calculation.
 
    For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0]
    all have a rank of 2.  */
@@ -66,10 +64,8 @@ find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn,
   tree ii_tree;
   size_t ii = 0, current_rank = 0;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
-  
-  if (!array)
-    return true;
-  else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
+ 
+  if (TREE_CODE (array) == ARRAY_NOTATION_REF)
     {
       for (ii_tree = array;
 	   ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
@@ -111,7 +107,8 @@ find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn,
 	}
       else 
 	for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) 
-	  if (!find_rank (loc, orig_expr, TREE_OPERAND (array, ii),
+	  if (TREE_OPERAND (array, ii)
+	      && !find_rank (loc, orig_expr, TREE_OPERAND (array, ii),
 			  ignore_builtin_fn, rank))
 	    return false;
     }
@@ -133,21 +130,22 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
   size_t ii = 0;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
   
-  if (!node)
-    return;
-  else if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+  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);
+      if (TREE_PURPOSE (node))
+	extract_array_notation_exprs (TREE_PURPOSE (node), ignore_builtin_fn,
+				      array_list);
+      if (TREE_VALUE (node))
+	extract_array_notation_exprs (TREE_VALUE (node), ignore_builtin_fn,
+				      array_list);
+      if (TREE_CHAIN (node))
+	extract_array_notation_exprs (TREE_CHAIN (node), ignore_builtin_fn,
+				      array_list);
     }
   else if (TREE_CODE (node) == STATEMENT_LIST)
     {
@@ -181,8 +179,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
     } 
   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);
+      if (TREE_OPERAND (node, ii))
+	extract_array_notation_exprs (TREE_OPERAND (node, ii),
+				      ignore_builtin_fn, array_list);
   return;
 }
 
@@ -190,10 +189,7 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 /* Replaces all the occurances of array notations in *LIST with the appropriate
    one in ARRAY_OPERAND.  If IGNORE_BUILTIN_FN is set, then array notations
    inside array-notation specific builtin functions are ignored.  ORIG can be
-   anything from a collection of statement lists to a single variable.  Since
-   this function steps through all the subtrees, it is probable that *ORIG can
-   be a NULL_TREE.  If so, then the function just returns.
-*/
+   anything from a collection of statement lists to a single variable.  */
 
 static void
 replace_array_notations (tree *orig, bool ignore_builtin_fn,
@@ -204,7 +200,7 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
   tree node = NULL_TREE, node_replacement = NULL_TREE;
   an_reduce_type dummy_type = REDUCE_UNKNOWN;
   
-  if (vec_safe_length (list) == 0 || !*orig)
+  if (vec_safe_length (list) == 0)
     return;
 
   if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
@@ -262,8 +258,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
   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);
+	if (TREE_OPERAND (*orig, ii))
+	  replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
+				   list, array_operand);
     }
   return;
 }
@@ -330,9 +327,7 @@ replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
 
 /* Replaces all the scalar expressions in *NODE.  Returns a STATEMENT_LIST that
    holds the NODE along with variables that holds the results of the invariant
-   expressions.  Since this function steps through all the subtrees, it is
-   probable than *NODE or NODE can be NULL_TREE and NULL respectively.  If so,
-   then the function just returns NULL_TREE.  */
+   expressions.  */
 
 tree
 replace_invariant_exprs (tree *node)
@@ -342,9 +337,6 @@ replace_invariant_exprs (tree *node)
   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);
@@ -987,6 +979,8 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
        build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii], 
 	       build_one_cst (TREE_TYPE (lhs_var[ii]))));
   
+  /* If array_expr_lhs is NULL, then we have function that returns void or
+     its return value is ignored.  */
   if (!array_expr_lhs)
     array_expr_lhs = lhs;
 
@@ -2372,9 +2366,6 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 	function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
     }
   
-  if (!function_name)
-    return false;
-
   if (!strcmp (function_name, "__sec_reduce_add"))
     {
       *type = REDUCE_ADD;
@@ -2444,7 +2435,9 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
 }
 
 
-/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.  */
+/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node.
+   If EXPR is NULL_TREE or does not contain any array notations, then the
+   function returns false.   */
 
 bool
 contains_array_notation_expr (tree expr)
@@ -2780,13 +2773,12 @@ fix_array_notation_call_expr (tree arg)
 /* Walks through tree node T and find all the call-statments that do not return
    anything and fix up any array notations they may carry.  The return value
    is the same type as T but with all array notations replaced with appropriate
-   STATEMENT_LISTS.  Since this function recursively steps through all the
-   subtrees, t can be a NULL_TREE.  If so, then the function just returns.  */
+   STATEMENT_LISTS.  */
 
 tree
 expand_array_notation_exprs (tree t)
 {
-  if (!t || !contains_array_notation_expr (t))
+  if (!contains_array_notation_expr (t))
     return t;
 
   switch (TREE_CODE (t))
@@ -2801,8 +2793,12 @@ expand_array_notation_exprs (tree t)
 	 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));
+	  if (COND_EXPR_THEN (t))
+	    COND_EXPR_THEN (t) =
+	      expand_array_notation_exprs (COND_EXPR_THEN (t));
+	  if (COND_EXPR_ELSE (t))
+	    COND_EXPR_ELSE (t) =
+	      expand_array_notation_exprs (COND_EXPR_ELSE (t));
 	}
       else
 	t = expand_array_notation_exprs (t);

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2013-03-26 21:11 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-20 15:32 [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
2013-03-20 16:33 ` Aldy Hernandez
2013-03-20 22:28   ` Iyer, Balaji V
2013-03-21 12:55     ` Aldy Hernandez
2013-03-21  5:31   ` Jeff Law
2013-03-21  6:09     ` Jakub Jelinek
2013-03-21 13:01       ` Aldy Hernandez
2013-03-21 13:06         ` Iyer, Balaji V
2013-03-21 13:09           ` Aldy Hernandez
2013-03-21 13:15             ` Iyer, Balaji V
2013-03-21 16:54       ` Mike Stump
2013-03-21 23:34         ` Aldy Hernandez
2013-03-22 22:36           ` Mike Stump
2013-03-23  1:36             ` Iyer, Balaji V
2013-03-23  5:00               ` Mike Stump
2013-03-20 22:00 ` [cilkplus-merge] test for side effects Aldy Hernandez
2013-03-21 14:25 ` [patch] cilkplus array notation for C (clean, independent patchset, take 1) Aldy Hernandez
2013-03-21 19:08   ` Iyer, Balaji V
2013-03-21 23:30     ` Aldy Hernandez
2013-03-21 15:56 ` Joseph S. Myers
2013-03-22 22:04   ` Iyer, Balaji V
2013-03-25 16:45     ` Aldy Hernandez
2013-03-25 21:39       ` Iyer, Balaji V
2013-03-25 21:49         ` Aldy Hernandez
2013-03-26 17:05       ` Joseph S. Myers
2013-03-26 21:11         ` Iyer, Balaji V
2013-03-26 16:27     ` Joseph S. Myers
2013-03-21 16:48 ` Joseph S. Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).