diff mbox

[Cilkplus] Builtin Array Notation functions in C++ Compiler

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

Commit Message

Iyer, Balaji V Jan. 22, 2012, 2:03 a.m. UTC
Hello Everyone,
    This patch is for the Cilkplus branch in the C++ compiler. This patch will implement builtin functions for array notations.

Thanking You,

Yours Sincerely,

Balaji V. Iyer.
diff mbox

Patch

diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk
index 8d65ca2..11eca8e 100644
--- a/gcc/ChangeLog.cilk
+++ b/gcc/ChangeLog.cilk
@@ -1,4 +1,11 @@ 
-2011-01-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+2012-01-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* Makefile.in: Added array-notation-common.c file for compilation.
+	* array-notation-common.c (mark_cold): New function.
+	(array_notation_init_builtins): Likewise.
+	* tree.h: Added a new enum list called "array_notation_reduce_type."
+	
+2012-01-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* cilk.c (cilk_remove_annotated_functions): Added a int cast for
 	VEC_length in for-loop condition.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9732ffc..76d2bc0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1452,6 +1452,7 @@  OBJS = \
 	xcoffout.o \
         cilk.o \
         cilk-low.o \
+	array-notation-common.o \
 	$(out_object_file) \
 	$(EXTRA_OBJS) \
 	$(host_hook_obj)
@@ -3437,6 +3438,8 @@  lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 
 
+array-notation-common.o: array-notation-common.c $(CONFIG_H) $(SYSTEM_H) \
+    $(TREE_H) $(RTL_H) $(OPTABS_H) $(GIMPLE_H) $(RECOG_H) 
 
 cilk.o: cilk.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(OPTABS_H) \
    $(GIMPLE_H) $(RECOG_H) cilk.h
diff --git a/gcc/array-notation-common.c b/gcc/array-notation-common.c
new file mode 100644
index 0000000..059adc4
--- /dev/null
+++ b/gcc/array-notation-common.c
@@ -0,0 +1,101 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains the builtin functions for Array
+   notations.
+   Copyright (C) 2012  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "expr.h"
+#include "optabs.h" /* for sync_lock_release in detach */
+#include "recog.h"
+#include "cilk.h"
+#include "gimple.h"
+#include "tree-iterator.h"
+#include "c-family/c-common.h"
+#include "toplev.h" /* only correct declaration of warning() */
+#include "output.h"
+#include "dwarf2out.h"
+
+static void
+mark_cold (tree fndecl)
+{
+  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
+					DECL_ATTRIBUTES (fndecl));
+}
+
+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_zeros", 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_zeros", 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);
+  return;
+}
diff --git a/gcc/c-family/ChangeLog.cilk b/gcc/c-family/ChangeLog.cilk
index 5e57983..a4049d0 100644
--- a/gcc/c-family/ChangeLog.cilk
+++ b/gcc/c-family/ChangeLog.cilk
@@ -1,3 +1,8 @@ 
+2012-01-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-common.c (c_define_builtins): Added a call to
+	array_notation_init_builtins function.
+
 2011-12-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* c-common.h: Added build_array_notation_expr prototype.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 708b40c..15145a5 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -49,7 +49,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "libfuncs.h"
 #include "cilk.h"
 
-
+extern void array_notation_init_builtins (void);
 enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
                       EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
                       EXPAND_MEMORY};
@@ -4660,7 +4660,10 @@  c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
   /* this function will initialize all the builtin functions required by
    * the cilkplus port */
   if (flag_enable_cilk)
-    cilk_init_builtins();
+    {
+      cilk_init_builtins ();
+      array_notation_init_builtins ();
+    }
 
   targetm.init_builtins ();
 
diff --git a/gcc/cp/ChangeLog.cilk b/gcc/cp/ChangeLog.cilk
index 072a6de..ce50e89 100644
--- a/gcc/cp/ChangeLog.cilk
+++ b/gcc/cp/ChangeLog.cilk
@@ -1,3 +1,25 @@ 
+2012-01-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* call.c (convert_like_real): Type conversion is ignored if array
+	notation is present as a parameter.
+	* cp-array-notation.c (find_rank): Added a new parameter called
+	ignore_builtin_fn.  Also handled a case for STATEMENT_LIST.  Finally,
+	added a check to see if the builtin function should be ignored.
+	(extract_array_notation_exprs): Added a new parameter called
+	ignore_builtin_fn.  Also added a check to see for ignore_builtin_fn.
+	(replace_array_notations): Likewise.
+	(build_x_array_notation_expr): Modified find_rank call to add a bool.
+	Also added a check if the funtion is a builtin array notation function.
+	Added a bool parameter to extract_array_notation_exprs, find_rank and
+	replace_array_notations.
+	(fix_builtin_array_notation_fn): New function.
+	(is_builtin_array_notation_fn): Likewise.
+	(build_x_reduce_expr): Likewise.
+	(contains_array_notation_expr): Likewise.
+	(fix_unary_array_notation_exprs): Changed the name of the parameter.
+	Also handled a case check for CALL_EXPR and if so, called
+	fix_builtin_array_notation_fn.
+
 2012-01-17  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* cp-array-notation.c (max): New function.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5413eda..e222e04 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -43,6 +43,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "cilk.h"
 
+extern bool contains_array_notation_expr (tree);
 /* The various kinds of conversion.  */
 
 typedef enum conversion_kind {
@@ -5638,13 +5639,16 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      permerror (input_location, "invalid conversion from %qT to %qT",
-		 TREE_TYPE (expr), totype);
-      if (fn)
-	permerror (DECL_SOURCE_LOCATION (fn),
-		   "  initializing argument %P of %qD", argnum, fn);
-
+      if (flag_enable_cilk && contains_array_notation_expr (expr))
+	;
+      else
+	{
+	  permerror (input_location, "invalid conversion from %qT to %qT",
+		     TREE_TYPE (expr), totype);
+	  if (fn)
+	    permerror (DECL_SOURCE_LOCATION (fn),
+		       "  initializing argument %P of %qD", argnum, fn);
+	}
       return cp_convert (totype, expr);
     }
 
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index a8667dd..39845f6 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -45,20 +45,24 @@ 
 #include "bitmap.h"
 
 
-void replace_array_notations (tree *, tree *, tree *, int);
-void find_rank (tree array, int *rank);
+void replace_array_notations (tree *, bool, tree *, tree *, int);
+void find_rank (tree, bool, int *);
 static tree fix_conditional_array_notations_1 (tree stmt);
 tree fix_unary_array_notation_exprs (tree stmt);
+static bool is_builtin_array_notation_fn (tree, an_reduce_type *);
+static tree build_x_reduce_expr (tree, enum tree_code, tree, tsubst_flags_t,
+				 an_reduce_type);
+bool contains_array_notation_expr (tree);
 
 /* This function is to find the rank of an array notation expression.
  * For example, an array notation of A[:][:] has a rank of 2.
  */
 void
-find_rank (tree array, int *rank)
+find_rank (tree array, bool ignore_builtin_fn, int *rank)
 {
   tree ii_tree;
   int current_rank = 0, ii = 0;
-  
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
   if (!array)
     return;
   else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
@@ -73,16 +77,31 @@  find_rank (tree array, int *rank)
       else if (*rank == 0)
 	*rank = current_rank;
     }
+  else if (TREE_CODE (array) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi);
+	   tsi_next (&ii_tsi))
+	find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank);
+    }
   else
     {
       if (TREE_CODE (array) == CALL_EXPR
 	  || TREE_CODE (array) == AGGR_INIT_EXPR)
 	{
+	  tree func_name = CALL_EXPR_FN (array);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    if (ignore_builtin_fn)
+	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
+		/* If it is a builtin function, then we know it returns a
+		 * scalar
+		 */
+		return;
 	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
 	    {
 	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
 	      for (ii = 0; ii < length; ii++)
-		find_rank (TREE_OPERAND (array, ii), rank);
+		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
 	    }
 	  else
 	    gcc_unreachable ();
@@ -90,7 +109,7 @@  find_rank (tree array, int *rank)
       else
 	{
 	  for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++)
-	    find_rank (TREE_OPERAND (array, ii), rank);
+	    find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
 	}
     }
   return;
@@ -100,10 +119,13 @@  find_rank (tree array, int *rank)
  * expressions inside the subtrees
  */
 void
-extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
+extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
+			      tree **array_list, int *list_size)
 {
   int ii = 0;
   tree *new_array_list = NULL;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
+  
   if (!node)
     return;
   else if (TREE_CODE (node) == ARRAY_NOTATION_REF)
@@ -122,18 +144,36 @@  extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
     {
       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), array_list,
-				      list_size);
+	extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn,
+				      array_list, list_size);
     }
   else if (TREE_CODE (node) == CALL_EXPR || TREE_CODE (node) == AGGR_INIT_EXPR)
     {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
+	{
+	  if (ignore_builtin_fn)
+	    return;
+	  else
+	    {
+	      ii = *list_size;
+	      new_array_list = (tree *) xrealloc (*array_list, (ii + 1) *
+						  sizeof (tree));
+	      gcc_assert (new_array_list);
+	      new_array_list[ii] = node;
+	      ii++;
+	      *list_size = ii;
+	      *array_list = new_array_list;
+	      return;
+	    }
+	}
       if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
 	{
 	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
 
 	  for (ii = 0; ii < length; ii++)
-	    extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list,
-					  list_size);
+	    extract_array_notation_exprs
+	      (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list,
+	       list_size);
 	}
       else
 	gcc_unreachable  (); /* should not get here */
@@ -142,8 +182,8 @@  extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
   else
     {
       for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
-	extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list,
-				      list_size);
+	extract_array_notation_exprs (TREE_OPERAND (node, ii),
+				      ignore_builtin_fn, array_list, list_size);
     }
   return;
 }
@@ -152,10 +192,11 @@  extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
  * appropriate scalar equivalent
  */
 void
-replace_array_notations (tree *orig, tree *list, tree *array_operand,
-			 int array_size)
+replace_array_notations (tree *orig, bool ignore_builtin_fn, tree *list,
+			 tree *array_operand, int array_size)
 {
   int ii = 0;
+  an_reduce_type dummy_type = REDUCE_UNKNOWN;
   
   if (array_size == 0 || *list == NULL || !*orig)
     return;
@@ -172,18 +213,31 @@  replace_array_notations (tree *orig, tree *list, tree *array_operand,
     {
       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), list, array_operand,
-				 array_size);
+	replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn,
+				 list, array_operand, array_size);
     }
   else if (TREE_CODE (*orig) == CALL_EXPR
 	   || TREE_CODE (*orig) == AGGR_INIT_EXPR)
     {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
+	{
+	  if (!ignore_builtin_fn)
+	    {
+	      for (ii = 0; ii < array_size; ii++)
+		{
+		  if (*orig == list[ii])
+		    *orig = array_operand[ii];
+		}
+	    }
+	  return;
+	}
       if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
 	{
 	  int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
 	  for (ii = 0; ii < length; ii++)
-	    replace_array_notations (&TREE_OPERAND (*orig, ii), list,
-				     array_operand, array_size);
+	    replace_array_notations
+	      (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+	       array_operand, array_size);
 	}
       else
 	gcc_unreachable (); /* should not get here! */
@@ -192,8 +246,9 @@  replace_array_notations (tree *orig, tree *list, tree *array_operand,
     {
       for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
 	{
-	  replace_array_notations (&TREE_OPERAND (*orig, ii), list,
-				   array_operand, array_size);
+	  replace_array_notations
+	    (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+	     array_operand, array_size);
 	}
     }
   return;
@@ -235,17 +290,27 @@  build_x_array_notation_expr (tree lhs, enum tree_code modifycode, tree rhs,
   tree ii_tree = NULL_TREE;
   tree *rhs_list = NULL;
   int rhs_list_size = 0;
+  an_reduce_type type = REDUCE_UNKNOWN;
   
-  find_rank (lhs, &lhs_rank);
-  find_rank (rhs, &rhs_rank);
+  find_rank (lhs, true, &lhs_rank);
+  find_rank (rhs, true, &rhs_rank);
 
   /* If both are scalar, then no reason to do any of the components inside this
    * function... a simple build_x_modify_expr would do.
    */
   if (lhs_rank == 0 && rhs_rank == 0)
     return NULL_TREE;
+
+  if (TREE_CODE (rhs) == CALL_EXPR)
+    {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (rhs), &type))
+	{
+	  loop = build_x_reduce_expr (lhs, modifycode, rhs, complain, type);
+	  return loop;
+	}
+    }
   
-  extract_array_notation_exprs (rhs, &rhs_list, &rhs_list_size);
+  extract_array_notation_exprs (rhs, true, &rhs_list, &rhs_list_size);
 
   if (lhs_rank == 0 && rhs_rank != 0)
     {
@@ -540,7 +605,7 @@  build_x_array_notation_expr (tree lhs, enum tree_code modifycode, tree rhs,
 		}
 	    }
 	}
-      replace_array_notations (&rhs, rhs_list, rhs_array_operand,
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand,
 				 rhs_list_size);
 	array_expr_rhs = rhs;
     }
@@ -691,11 +756,11 @@  fix_conditional_array_notations_1 (tree stmt)
     /* otherwise don't even touch the statement */
     return stmt;
 
-  find_rank (cond, &rank);
+  find_rank (cond, true, &rank);
   if (rank == 0)
     return stmt;  
   
-  extract_array_notation_exprs (cond, &array_list, &list_size);
+  extract_array_notation_exprs (cond, true, &array_list, &list_size);
 
   if (*array_list == NULL_TREE || list_size == 0)
     return stmt;
@@ -862,7 +927,7 @@  fix_conditional_array_notations_1 (tree stmt)
 	    }
 	}
     }
-  replace_array_notations (&stmt, array_list, array_operand, list_size);
+  replace_array_notations (&stmt, true, array_list, array_operand, list_size);
 
   for (ii = 0; ii < rank; ii++)
     {
@@ -1154,8 +1219,422 @@  fix_array_notation_exprs (tree t)
   return t;
 }
 
+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 new_var_init;
+  an_reduce_type an_type = REDUCE_UNKNOWN;
+  tree *array_list = NULL;
+  int list_size = 0;
+  int rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+  tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  
+  if (!is_builtin_array_notation_fn (CALL_EXPR_FN (an_builtin_fn), &an_type))
+    return NULL_TREE;
+
+  func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  
+  find_rank (an_builtin_fn, false, &rank);
+  if (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+	   && (an_type == REDUCE_MAX_INDEX  || an_type == REDUCE_MIN_INDEX))
+    { 
+      error ("__sec_reduce_min_ind or __sec_reduce_max_ind cannot have arrays"
+	     " with dimension greater than 1.");
+      fnotice (stderr, "confused by earlier errors, bailing out\n"); 
+      exit (ICE_EXIT_CODE);
+    }
+  
+  extract_array_notation_exprs (func_parm, true, &array_list, &list_size);
+
+    switch (an_type)
+    {
+    case REDUCE_ADD:
+    case REDUCE_MUL:
+    case REDUCE_MAX:
+    case REDUCE_MIN:
+      new_var_type = ARRAY_NOTATION_TYPE (array_list[0]);
+      break;
+    case REDUCE_ALL_ZEROS:
+    case REDUCE_ANY_ZEROS:
+      new_var_type = integer_type_node;
+      break;
+    case REDUCE_MAX_INDEX:
+    case REDUCE_MIN_INDEX:
+      new_var_type = integer_type_node;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+   
+  
+  array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+  array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+      array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+      array_start[ii]  = (tree *) xmalloc (sizeof (tree) * rank);
+    }
+
+  body_label = (tree *) xmalloc(sizeof (tree) * rank);
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+  ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+  
+  count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+  array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+  
+  array_var = (tree *) xmalloc (sizeof (tree) * rank);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      for (jj_tree = array_list[ii];
+	   jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
+	   jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
+	{
+	  array_ops[ii][jj] = jj_tree;
+	  jj++;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_int_cst (TREE_TYPE (array_length[ii][jj]),
+					   0)))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  loop = alloc_stmt_list ();
+
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+				  integer_type_node);
+      ind_init[ii] =
+	build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+			   TREE_TYPE (array_var[ii]), NOP_EXPR,
+			   UNKNOWN_LOCATION,
+			   build_int_cst (TREE_TYPE (array_var[ii]), 0),
+			   TREE_TYPE (array_var[ii]));	
+    }
+
+  for (ii = 0; ii < rank ; ii++)
+    {
+      /* this will create the if statement label */
+      if_stmt_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+				      void_type_node);
+      DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+      DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+  
+      /* this label statment will point to the loop body */
+      body_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (body_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (body_label[ii]) = 0;
+      DECL_IGNORED_P (body_label[ii]) = 1;
+      body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+      /* this will create the exit label..i.e. where the while loop will branch
+	 out of
+      */
+      exit_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+				   void_type_node);
+      DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+      DECL_ARTIFICIAL (exit_label[ii]) = 0;
+      DECL_IGNORED_P (exit_label[ii]) = 1;
+      exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_operand[ii] = array_value[ii][rank - 1];
+	  gcc_assert (array_operand[ii]);
+
+	  for (jj = rank - 1; jj >= 0; jj--)
+	    {
+	      if (count_down[ii][jj])
+		{
+		  /* Array[start_index - (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (UNKNOWN_LOCATION, array_operand[ii],
+		     build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	      else
+		{
+		  /* Array[start_index + (induction_var * stride)] */
+		  array_operand[ii] = build_array_ref
+		    (UNKNOWN_LOCATION, array_operand[ii],
+		     build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+			     array_start[ii][jj],
+			     build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+				     array_var[jj], array_stride[ii][jj])));
+		}
+	    }
+	}
+    }
+  replace_array_notations (&func_parm, true, array_list, array_operand,
+			   list_size);
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      expr_incr[ii] =
+	build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+		build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+			build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+    }
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] =
+	      build2 (LT_EXPR, boolean_type_node, array_var[jj],
+		      build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+			      array_length[0][jj],
+			      build_int_cst (TREE_TYPE (array_var[jj]), -1)));
+	  else
+	    compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
+				       array_var[jj], array_length[0][jj]);
+	}
+    }
+
+  *new_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, new_var_type);
+  gcc_assert (*new_var);
+
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+      new_expr = build_x_modify_expr (*new_var, PLUS_EXPR, func_parm, 1);
+      break;
+    case REDUCE_MUL:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 1), 1);
+      new_expr = build_x_modify_expr (*new_var, MULT_EXPR, func_parm, 1);
+      break;
+    case REDUCE_ALL_ZEROS:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 1), 1);
+      /* 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_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (TREE_TYPE (*new_var), 0), 1);
+      new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      new_expr = build_x_conditional_expr (func_parm, new_yes_expr,
+					   new_no_expr, 1);
+      break;
+    case REDUCE_ANY_ZEROS:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+      /* 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_no_expr = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (TREE_TYPE (*new_var), 1), 1);
+      new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      new_expr = build_x_conditional_expr (func_parm, new_yes_expr,
+					   new_no_expr, 1);      
+      break;
+    case REDUCE_MAX:
+      if (INTEGRAL_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr
+	  (*new_var, NOP_EXPR, TYPE_MIN_VALUE (new_var_type), 1);
+      else /* Otherwise, we pick the first item in the array */
+	new_var_init = build_x_modify_expr
+	  (*new_var, NOP_EXPR,
+	   build_array_ref (UNKNOWN_LOCATION,
+			    TREE_OPERAND (array_operand[0], 0),
+			    build_int_cst (integer_type_node, 0)), 1);
+      new_no_expr  = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, func_parm, 1);
+      new_expr = build_x_conditional_expr
+	(build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+	 new_yes_expr, new_no_expr, 1);      
+      break;
+    case REDUCE_MIN:
+      if (INTEGRAL_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr
+	  (*new_var, NOP_EXPR, TYPE_MAX_VALUE (new_var_type), 1);
+      else /* Otherwise, we the first item in the array */
+	new_var_init = build_x_modify_expr
+	  (*new_var, NOP_EXPR,
+	   build_array_ref (UNKNOWN_LOCATION,
+			    TREE_OPERAND (array_operand[0], 0),
+			    build_int_cst (integer_type_node, 0)), 1);
+      new_no_expr  = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, func_parm, 1);
+      new_expr = build_x_conditional_expr
+	(build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+	 new_yes_expr, new_no_expr, 1);
+      break;
+    case REDUCE_MAX_INDEX:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+      new_no_expr  = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      if (list_size > 1) /* this means there is more than 1 */
+	new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, array_var[0],
+					    1);
+      else				    
+	new_yes_expr = build_x_modify_expr
+	  (*new_var, NOP_EXPR, TREE_OPERAND (array_operand[0], 1), 1);
+      
+      new_expr = build_x_conditional_expr
+	(build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+	 new_yes_expr, new_no_expr, 1);
+      break;
+    case REDUCE_MIN_INDEX:
+      new_var_init = build_x_modify_expr
+	(*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+      new_no_expr  = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+      if (list_size > 1)
+	new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, array_var[0],
+					    1);
+      else
+	new_yes_expr = build_x_modify_expr
+	  (*new_var, NOP_EXPR, TREE_OPERAND (array_operand[0], 1), 1);
+      
+      new_expr = build_x_conditional_expr
+	(build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+	 new_yes_expr, new_no_expr, 1);
+      break;
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  append_to_statement_list (new_var_init, &loop);
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      append_to_statement_list (ind_init [ii], &loop);
+
+      append_to_statement_list
+	(build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+      append_to_statement_list
+	(build3 (COND_EXPR, void_type_node, compare_expr[ii],
+		 build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+		 build1 (GOTO_EXPR, void_type_node, exit_label[ii])), &loop);
+      append_to_statement_list (body_label_expr[ii], &loop);
+    }
+					   
+  append_to_statement_list (new_expr, &loop);
+  
+  for (ii = rank - 1; ii >= 0; ii--)
+    {
+      append_to_statement_list (expr_incr[ii], &loop);
+      append_to_statement_list
+	(build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+      append_to_statement_list (exit_label_expr[ii], &loop);
+    }
+
+  free (body_label);
+  free (body_label_expr);
+  free (exit_label);
+  free (exit_label_expr);
+  free (compare_expr);
+  free (if_stmt_label);
+  free (expr_incr);
+  free (ind_init);
+  free (array_operand);
+  free (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      free (count_down[ii]);
+      free (array_value[ii]);
+      free (array_stride[ii]);
+      free (array_length[ii]);
+      free (array_start[ii]);
+      free (array_ops[ii]);
+      free (array_vector[ii]);
+    }
+
+  free (count_down);
+  free (array_value);
+  free (array_stride);
+  free (array_length);
+  free (array_start);
+  free (array_ops);
+  free (array_vector);
+
+  
+  return loop;
+}
+
+
 tree
-fix_unary_array_notation_exprs (tree stmt)
+fix_unary_array_notation_exprs (tree orig_stmt)
 {
 
   tree *array_list = NULL;
@@ -1166,11 +1645,35 @@  fix_unary_array_notation_exprs (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;
-  find_rank (stmt, &rank);
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  
+  find_rank (orig_stmt, false, &rank);
   if (rank == 0)
-    return stmt;  
+    return orig_stmt;  
   
-  extract_array_notation_exprs (stmt, &array_list, &list_size);
+  extract_array_notation_exprs (orig_stmt, false, &array_list, &list_size);
+
+  stmt = alloc_stmt_list ();
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE (array_list[ii]) == CALL_EXPR
+	  || TREE_CODE (array_list[ii]) == AGGR_INIT_EXPR)
+	{
+	  builtin_loop =
+	    fix_builtin_array_notation_fn (array_list[ii], &new_var);
+	  append_to_statement_list (builtin_loop, &stmt);
+	  replace_array_notations (&orig_stmt, false, &array_list[ii],
+				   &new_var, 1);
+	}
+    }
+  append_to_statement_list (orig_stmt, &stmt);
+  rank = 0;
+  list_size = 0;
+  array_list = NULL;
+  extract_array_notation_exprs (stmt, true, &array_list, &list_size);
+  find_rank (stmt, true, &rank);
+  if (rank == 0)
+    return stmt;
   
   if (*array_list == NULL_TREE || list_size == 0)
     return stmt;
@@ -1334,7 +1837,7 @@  fix_unary_array_notation_exprs (tree stmt)
 	    }
 	}
     }
-  replace_array_notations (&stmt, array_list, array_operand, list_size);
+  replace_array_notations (&stmt, true, array_list, array_operand, list_size);
 
   for (ii = 0; ii < rank; ii++)
     {
@@ -1416,3 +1919,97 @@  fix_unary_array_notation_exprs (tree stmt)
   stmt = loop;
   return stmt;
 }
+
+static bool
+is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
+{
+  const char *function_name;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (DECL_NAME (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_zeros"))
+    {
+      *type = REDUCE_ALL_ZEROS;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_any_zeros"))
+    {
+      *type = REDUCE_ANY_ZEROS;
+      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
+    {
+      *type = REDUCE_UNKNOWN;
+      return false;
+    }
+  return false;
+}
+    
+
+static tree
+build_x_reduce_expr (tree lhs, enum tree_code modifycode, tree rhs,
+		     tsubst_flags_t complain, an_reduce_type type)
+{
+  if (!type)
+    {
+      return build_x_modify_expr (lhs, modifycode, rhs, complain);
+    }
+  return NULL_TREE;
+}
+      
+bool
+contains_array_notation_expr (tree expr)
+{
+  tree *array_list = NULL;
+  int list_size = 0;
+  
+  extract_array_notation_exprs (expr, false, &array_list, &list_size);
+  if (*array_list == NULL || list_size == 0)
+    return false;
+  else
+    return true;
+}
+    
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fd35211..3979d78 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -41,7 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "parser.h"
 
-extern void extract_array_notation_exprs (tree, tree **, int *);
+extern void extract_array_notation_exprs (tree, bool, tree **, int *);
 extern tree fix_unary_array_notation_exprs (tree);
 struct pragma_simd_values local_simd_values;
 
diff --git a/gcc/testsuite/ChangeLog.cilk b/gcc/testsuite/ChangeLog.cilk
index 1071752..9fa7413 100644
--- a/gcc/testsuite/ChangeLog.cilk
+++ b/gcc/testsuite/ChangeLog.cilk
@@ -1,3 +1,7 @@ 
+2012-01-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	*  g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc: New.
+
 2012-01-17  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* g++.dg/cilk-plus/array_notation_tests/predecr_test.cc: New.
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc
new file mode 100644
index 0000000..f5b06da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc
@@ -0,0 +1,92 @@ 
+#if HAVE_IO
+#include <iostream> 
+#endif
+#include <cstdlib>
+
+extern int funct(int x);
+extern int funct2(int x, int y);
+extern void func_ptr (int *x);
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+  int array[10], array2[10], x = 0, y;
+  int x_correct, y_correct;
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 1+ii;
+      array2[ii]= 2;
+    }
+
+  x = __sec_reduce_max (array[:] + array2[:]);
+  y = __sec_reduce_max_ind (array[:] + array2[:]);
+#if HAVE_IO
+  std::cout <<  "Max = " << x << " Max Index = " << y << std::endl;
+#endif
+
+  x = __sec_reduce_max (array[0:5:1] + array2[5:5:1]);
+  y = __sec_reduce_max_ind (array[0:5] + array2[5:5:1]);
+#if HAVE_IO
+  std::cout <<  "Max = " << x << " Max Index = " << y << std::endl;
+#endif
+
+  x = __sec_reduce_min (array[:] + array2[:]);
+  y = __sec_reduce_min_ind (array[:] + array2[:]);
+#if HAVE_IO
+  std::cout <<  "Min = " << x << " Min Index = " << y << std::endl;
+#endif
+
+  x = __sec_reduce_min (array[0:5:1] + array2[5:5:1]);
+  y = __sec_reduce_min_ind (array[0:5] + array2[5:5:1]);
+#if HAVE_IO
+  std::cout <<  "Min = " << x << " Min Index = " << y << std::endl;
+#endif
+  
+  x = __sec_reduce_add (array[:] + array2[:]);
+  y = __sec_reduce_mul (array[:] + array2[:]);
+
+  x_correct = 0;
+  y_correct = 1;
+  for (int ii = 0; ii < 10; ii++)
+    {
+      x_correct += (array[ii] + array2[ii]);
+      y_correct *= (array[ii] + array2[ii]);
+    }
+#if HAVE_IO
+  std::cout <<  "Add          = " << x 
+    << " Multiply           = " << y << std::endl;
+  std::cout <<  "Add(Correct) = " << x_correct 
+    << " Multiply (Correct) = " << y_correct << std::endl;
+#endif
+
+  x = __sec_reduce_add (array[0:5:1] + array2[5:5:1]);
+  y = __sec_reduce_mul (array[0:5]   + array2[5:5:1]);
+  
+  x_correct = 0;
+  y_correct = 1;
+  for (int ii = 0; ii < 5; ii++)
+    {
+      x_correct += (array[ii] + array2[5+ii]);
+      y_correct *= (array[ii] + array2[5+ii]);
+    }
+#if HAVE_IO
+  std::cout <<  "Add          = " << x 
+    << " Multiply           = " << y << std::endl;
+  std::cout <<  "Add(Correct) = " << x_correct 
+    << " Multiply (Correct) = " << y_correct << std::endl;
+#endif
+
+    array[:] = argc - atoi ("1");
+
+    for (int ii = 0; ii < 10; ii++)
+      array2[ii] = argc - ii;
+
+  x = __sec_reduce_all_zeros (array[0:5:1]);
+  y = __sec_reduce_any_zeros (array2[:]);
+#if HAVE_IO
+  std::cout <<  "All Zeros = " << x << " Any Zeros = " << y << std::endl;
+#endif
+
+  return 0;
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 051187d..90f9653 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -73,8 +73,6 @@  struct reduction_values
   int not_reduced;
   struct reduction_values *ptr_next;
 };
-  
-
 
 /* bviyer: Since we can have multiple pragma simd, this will hold the values of
  * each of the pragma simd and then as soon as it finds a for loop
@@ -105,11 +103,19 @@  struct pragma_simd_values
   struct pragma_simd_values *ptr_next;
 };
 
-
-
-
 extern struct pragma_simd_values *psv_head;
 
+typedef enum array_notation_reduce_type {
+  REDUCE_UNKNOWN = 0,
+  REDUCE_ADD,
+  REDUCE_MUL,
+  REDUCE_ALL_ZEROS,
+  REDUCE_ANY_ZEROS,
+  REDUCE_MAX,
+  REDUCE_MIN,
+  REDUCE_MAX_INDEX,
+  REDUCE_MIN_INDEX
+} an_reduce_type;
 
 
 #undef DEFTREECODE