diff mbox

[Cilkplus] Builtin ArrayNotation functions Support (for C Compiler)

Message ID BF230D13CA30DD48930C31D40993300002121D@FMSMSX101.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Jan. 25, 2012, 8:04 p.m. UTC
Hello Everyone,
    This patch is for the C compiler in Cilkplus branch. This patch will implement builtin array notation function calls in the C Compiler.

Thanking You,

Yours Sincerely,

Balaji V. Iyer.
diff mbox

Patch

diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk
index 11eca8e..8e4fab9 100644
--- a/gcc/ChangeLog.cilk
+++ b/gcc/ChangeLog.cilk
@@ -1,3 +1,25 @@ 
+2012-01-25  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-array-notation.c (replace_array_notations): Added a new bool as
+	parameter and added support for it.
+	(find_rank): Likewise.
+	(extract_array_notation_exprs): Likewise.
+	(replace_array_notations): Likewise.
+	(max): New function.
+	(fix_builtin_array_notation_fn): Likewise.
+	(is_builtin_array_notation_fn): Likewise.
+	(contains_array_notation_expr): Likewise.
+	(build_array_notation_expr): Added support for builtin function.
+	Changed all for-loops that have comparison with lhs_rank, with
+	max (lhs_rank and rhs_rank).  Also added a check if array_expr_lhs is
+	NULL, then we set that equal to lhs.
+	* c-parser.c (c_parser_expr_no_commas): Added support for array
+	notations inside function calls (i.e. function that takes array notation
+	as input and returns a scalar value).
+	* c-typeck.c (convert_arguments): If array notation is present inside
+	a function call, then we skip it for now since we will fix it up in a
+	later step.
+
 2012-01-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* Makefile.in: Added array-notation-common.c file for compilation.
diff --git a/gcc/c-array-notation.c b/gcc/c-array-notation.c
index ac791eb..1dac533 100644
--- a/gcc/c-array-notation.c
+++ b/gcc/c-array-notation.c
@@ -38,18 +38,25 @@ 
 #include "gimple.h"
 #include "c-family/c-objc.h"
 
-void replace_array_notations (tree *, tree *, tree *, int);
-void find_rank (tree, int *);
-void extract_array_notation_exprs (tree, tree **, int *);
+void replace_array_notations (tree *, bool, tree *, tree *, int);
+void find_rank (tree, bool, int *);
+void extract_array_notation_exprs (tree, bool, tree **, int *);
 tree fix_conditional_array_notations (tree);
 struct c_expr fix_array_notation_expr (location_t, enum tree_code,
 				       struct c_expr);
+static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
+static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var);
+bool contains_array_notation_expr (tree expr);
+
+/* 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)
@@ -64,16 +71,30 @@  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)
+      if (TREE_CODE (array) == CALL_EXPR)
 	{
+	  tree func_name = CALL_EXPR_FN (array);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    if (ignore_builtin_fn)
+	      if (is_builtin_array_notation_fn (func_name, &dummy_type))
+		/* If it is a builtin function, then we know it returns a
+		 * scalar
+		 */
+		return;
 	  if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
 	    {
 	      int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
 	      for (ii = 0; ii < length; ii++)
-		find_rank (TREE_OPERAND (array, ii), rank);
+		find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
 	    }
 	  else
 	    gcc_unreachable ();
@@ -81,17 +102,23 @@  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;
 }
 
+/* this function will go through a tree and extract all the array notation
+ * 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)
@@ -110,18 +137,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)
+  else if (TREE_CODE (node) == CALL_EXPR)
     {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
+	{
+	  if (ignore_builtin_fn)
+	    return;
+	  else
+	    {
+	      ii = *list_size;
+	      new_array_list = (tree *) xrealloc (*array_list, (ii + 1) *
+						  sizeof (tree));
+	      gcc_assert (new_array_list);
+	      new_array_list[ii] = node;
+	      ii++;
+	      *list_size = ii;
+	      *array_list = new_array_list;
+	      return;
+	    }
+	}
       if (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 */
@@ -130,17 +175,21 @@  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;
 }
 
+/* this function will replace a subtree that has array notation with the
+ * 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;
@@ -157,18 +206,30 @@  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)
+  else if (TREE_CODE (*orig) == CALL_EXPR)
     {
+      if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
+	{
+	  if (!ignore_builtin_fn)
+	    {
+	      for (ii = 0; ii < array_size; ii++)
+		{
+		  if (*orig == list[ii])
+		    *orig = array_operand[ii];
+		}
+	    }
+	  return;
+	}
       if (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! */
@@ -177,19 +238,30 @@  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;
 }
 
+/* this is a small function that will give the max of 2 integers */
+static int
+max (int x, int y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
 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;
+  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;
@@ -205,14 +277,67 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
   bool *lhs_count_down = NULL, **rhs_count_down = NULL;
   tree *lhs_compare = NULL, *rhs_compare = NULL, *rhs_array_operand = NULL;
   int lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
-  tree ii_tree = NULL_TREE;
-  tree *rhs_list = NULL;
+  tree ii_tree = NULL_TREE, new_modify_expr;
+  tree *rhs_list = NULL, new_var = NULL_TREE, builtin_loop = NULL_TREE;
   int rhs_list_size = 0;
+
+  find_rank (rhs, false, &rhs_rank);
+
+  extract_array_notation_exprs (rhs, false, &rhs_list, &rhs_list_size);
+
+  loop = push_stmt_list ();
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE (rhs_list[ii]) == CALL_EXPR)
+	{
+	  builtin_loop = fix_builtin_array_notation_fn (rhs_list[ii], &new_var);
+	  if (builtin_loop)
+	    {
+	      add_stmt (builtin_loop);
+	      found_builtin_fn = true;
+	      replace_array_notations (&rhs, false, &rhs_list[ii], &new_var, 1);
+	    }
+	}
+    }
+
+  lhs_rank = 0;
+  rhs_rank = 0;
+  find_rank (lhs, true, &lhs_rank);
+  find_rank (rhs, true, &rhs_rank);
+
+  if (lhs_rank == 0 && rhs_rank == 0)
+    {
+      if (found_builtin_fn)
+	{
+	  new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
+					       modifycode, rhs_loc, rhs,
+					       rhs_origtype);
+	  add_stmt (new_modify_expr);
+	  pop_stmt_list (loop);
+	  
+	  return loop;
+	}
+      else
+	{
+	  pop_stmt_list (loop);
+	  return NULL_TREE;
+	}
+    }
+
   
-  find_rank (lhs, &lhs_rank);
-  find_rank (rhs, &rhs_rank);
 
-  extract_array_notation_exprs (rhs, &rhs_list, &rhs_list_size);
+  /* if (TREE_CODE (rhs) == CALL_EXPR) */
+  /*   { */
+  /*     if (is_builtin_array_notation_fn (CALL_EXPR_FN (rhs), &type)) */
+  /* 	{ */
+  /* 	  loop = build_reduce_expr (location, lhs, lhs_origtype, modifycode, */
+  /* 				    rhs_loc, rhs, rhs_origtype); */
+  /* 	  return loop; */
+  /* 	} */
+  /*   } */
+  
+  extract_array_notation_exprs (rhs, true, &rhs_list, &rhs_list_size);
   
   if (lhs_rank == 0 && rhs_rank != 0)
     {
@@ -270,12 +395,12 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
    *
    * In both the scenarios, just checking the LHS_RANK is OK
    */
-  body_label = (tree *) xmalloc (sizeof (tree) * lhs_rank);
-  body_label_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank);
-  exit_label = (tree *) xmalloc (sizeof (tree) * lhs_rank);
-  exit_label_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank);
-  cond_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank);
-  if_stmt_label = (tree *) xmalloc (sizeof (tree) * lhs_rank);
+  body_label = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
+  body_label_expr = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
+  exit_label = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
+  exit_label_expr = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
+  cond_expr = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
+  if_stmt_label = (tree *) xmalloc (sizeof (tree) * max (lhs_rank, rhs_rank));
 
   lhs_expr_incr = (tree *) xmalloc (sizeof (tree) * lhs_rank);
   rhs_expr_incr = (tree *) xmalloc (sizeof (tree) * rhs_rank);
@@ -354,8 +479,10 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 		{
 		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
 		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
-		  rhs_length[ii][jj] = ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
-		  rhs_stride[ii][jj] = ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
 		  rhs_vector[ii][jj] = true;
 		  /* If the stride value is variable (i.e. not constant) then
 		   * assume that the length is positive
@@ -375,7 +502,7 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	}
     }
 
-  loop = push_stmt_list();
+
 
   for (ii = 0; ii < lhs_rank; ii++)
     {
@@ -385,7 +512,7 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 				    TREE_TYPE (lhs_start[ii]));
 	  lhs_ind_init[ii] = build_modify_expr
 	    (UNKNOWN_LOCATION, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
-	     modifycode,
+	     NOP_EXPR,
 	     UNKNOWN_LOCATION, build_int_cst (TREE_TYPE (lhs_start[ii]), 0),
 	     TREE_TYPE (lhs_start[ii]));
 	  
@@ -407,7 +534,7 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
     }
   
 
-  for (ii = 0; ii < lhs_rank ; ii++)
+  for (ii = 0; ii < max (lhs_rank, rhs_rank); ii++)
     {
       /* this will create the if statement label */
       if_stmt_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
@@ -497,9 +624,9 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 		}
 	    }
 	}
-      replace_array_notations (&rhs, rhs_list, rhs_array_operand,
-				 rhs_list_size);
-	array_expr_rhs = rhs;
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand,
+			       rhs_list_size);
+      array_expr_rhs = rhs;
     }
   else
     {
@@ -513,14 +640,16 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 	(MODIFY_EXPR, void_type_node, rhs_var[ii],
 	 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]), rhs_var[ii],
 		 build_int_cst (TREE_TYPE (rhs_var[ii]), 1)));
-    }
-      
+    } 
+
+  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 < lhs_rank; jj++)
+  for (jj = 0; jj < max (lhs_rank, rhs_rank); jj++)
     {
       if (rhs_rank && rhs_expr_incr[jj])
 	{
@@ -579,7 +708,7 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
    */
 
   
-  for (ii = 0; ii < lhs_rank; ii++)
+  for (ii = 0; ii < max (lhs_rank, rhs_rank); ii++)
     {
       add_stmt (lhs_ind_init [ii]);
       if (rhs_rank)
@@ -591,10 +720,11 @@  build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
 
       add_stmt (body_label_expr[ii]);
     }
-  
-  add_stmt (array_expr);
 
-  for (ii = lhs_rank - 1; ii >= 0; ii--)
+  if (max (lhs_rank, rhs_rank))
+    add_stmt (array_expr);
+
+  for (ii = max (lhs_rank, rhs_rank) - 1; ii >= 0; ii--)
     {
       add_stmt (lhs_expr_incr[ii]);
       if (rhs_rank && rhs_expr_incr[ii])
@@ -629,13 +759,14 @@  fix_conditional_array_notations_1 (tree stmt)
   else if (TREE_CODE (stmt) == FOR_STMT || TREE_CODE (stmt) == CILK_FOR_STMT)
     cond = FOR_COND (stmt);
   else
+    /* otherwise dont 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;
@@ -802,7 +933,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++)
     {
@@ -915,13 +1046,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, &rank);
+  find_rank (arg.value, false, &rank);
   if (rank == 0)
-    return arg;  
-  
-  extract_array_notation_exprs (arg.value, &array_list, &list_size);
+    return arg;
 
-  if (*array_list == NULL_TREE || list_size == 0)
+ 
+
+  extract_array_notation_exprs (arg.value, true, &array_list, &list_size);
+
+  if (list_size == 0 || *array_list == NULL_TREE)
     return arg;
 
   array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
@@ -1010,7 +1143,7 @@  fix_array_notation_expr (location_t location, enum tree_code code,
 	}
     }
 
-  loop = push_stmt_list();
+  loop = push_stmt_list ();
 
   for (ii = 0; ii < rank; ii++)
     {
@@ -1086,7 +1219,8 @@  fix_array_notation_expr (location_t location, enum tree_code code,
 	    }
 	}
     }
-  replace_array_notations (&arg.value, array_list, array_operand, list_size);
+  replace_array_notations (&arg.value, true, array_list, array_operand,
+			   list_size);
 
   for (ii = 0; ii < rank; ii++)
     {
@@ -1111,6 +1245,7 @@  fix_array_notation_expr (location_t location, enum tree_code code,
 				       array_var[jj], array_length[0][jj]);
 	}
     }
+
   
   for (ii = 0; ii < rank; ii++)
     {
@@ -1178,4 +1313,593 @@  fix_array_notation_expr (location_t location, enum tree_code code,
   arg.value = loop;
   return arg;
 }
+
+
+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;
+  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);
+  if (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX)
+    array_ind_value = build_decl
+      (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, TREE_TYPE (func_parm));
+			      
+  switch (an_type)
+    {
+    case REDUCE_ADD:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_MUL:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      new_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (func_parm));
+      break;
+    case REDUCE_ALL_ZEROS:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      /* Initially you assume everything is zero, now if we find a case where
+       * it is NOT true, then we set the result to false. Otherwise
+       * we just keep the previous value
+       */
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (TREE_TYPE (*new_var)),
+	 TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
+      break;
+    case REDUCE_ANY_ZEROS:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      /* Initially we assume there are NO zeros in the list. When we find
+       * a non-zero, we keep the previous value. If we find a zero, we
+       * set the value to true
+       */
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_one_cst (new_var_type), new_var_type);
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
+			      build_zero_cst (TREE_TYPE (func_parm)));
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION, new_cond_expr, false, new_yes_expr,
+	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
+      break;
+    case REDUCE_MAX:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION,
+	 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, new_var_type);
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_yes_expr = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, func_parm, TREE_TYPE (*new_var));
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION,
+	 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
+	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MAX_INDEX:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_no_ind = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_OPERAND (array_operand[0], 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION,
+	 build2 (LT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    case REDUCE_MIN_INDEX:
+      new_var_init = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, build_zero_cst (new_var_type), new_var_type);
+      new_no_ind = build_modify_expr
+	(UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	 UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var));
+      new_no_expr = build_modify_expr
+	(UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	 NOP_EXPR,
+	 UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value));
+      if (list_size > 1)
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, array_var[0], TREE_TYPE (array_var[0]));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_TYPE (array_operand[0]));
+	}
+      else
+	{
+	  new_yes_ind = build_modify_expr
+	    (UNKNOWN_LOCATION, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+	     UNKNOWN_LOCATION, TREE_OPERAND (array_operand[0], 1),
+	     TREE_TYPE (TREE_OPERAND (array_operand[0], 1)));
+	  new_yes_expr = build_modify_expr
+	    (UNKNOWN_LOCATION, array_ind_value, TREE_TYPE (array_ind_value),
+	     NOP_EXPR,
+	     UNKNOWN_LOCATION, func_parm, TREE_OPERAND (array_operand[0], 1));
+	}
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+ 
+      new_expr = build_conditional_expr
+	(UNKNOWN_LOCATION,
+	 build2 (GT_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
+		 func_parm),
+	 false,
+	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
+      break;
+    default:
+      gcc_unreachable ();
+      break;
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    append_to_statement_list (ind_init [ii], &loop);
+
+  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;
+}
+
+static bool
+is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
+{
+  const char *function_name = NULL;
+
+  if (!func_name)
+    return false;
+
+  if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+    function_name = IDENTIFIER_POINTER (func_name);
+  else if (TREE_CODE (func_name) == ADDR_EXPR)
+    {
+      func_name = TREE_OPERAND (func_name, 0);
+      if (TREE_CODE (func_name) == FUNCTION_DECL)
+	function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+    }
   
+  if (!function_name)
+    return false;
+
+  if (!strcmp (function_name, "__sec_reduce_add"))
+    {
+      *type = REDUCE_ADD;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_mul"))
+    {
+      *type = REDUCE_MUL;
+      return true;
+    }
+  else if (!strcmp (function_name, "__sec_reduce_all_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;
+}
+
+bool
+contains_array_notation_expr (tree expr)
+{
+  tree *array_list = NULL;
+  int list_size = 0;
+  an_reduce_type type = REDUCE_UNKNOWN;
+  
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    if (is_builtin_array_notation_fn (DECL_NAME (expr), &type))
+      return true;
+  
+  
+  extract_array_notation_exprs (expr, false, &array_list, &list_size);
+  if (array_list == NULL || list_size == 0)
+    return false;
+  else
+    return true;
+}
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 1078ef4..c67ea97 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -62,6 +62,7 @@  extern tree c_build_sync (tree *);
 extern tree fix_conditional_array_notations (tree);
 extern struct c_expr  fix_array_notation_expr (location_t, enum tree_code,
 					      struct c_expr);
+extern bool contains_array_notation_expr (tree);
 struct pragma_simd_values local_simd_values;
 
 
@@ -5474,11 +5475,11 @@  c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   rhs = default_function_array_read_conversion (exp_location, rhs);
 
   /* bviyer: The line below is where the parser has the form:
-   * A = B
+   * A = B, where A&B could contain array notation expressions 
    * So this is where we must modify the Array Notation arrays */
 
-  if (TREE_CODE (lhs.value) == ARRAY_NOTATION_REF
-      || TREE_CODE (rhs.value) == ARRAY_NOTATION_REF)
+  if (flag_enable_cilk && (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,
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 57dc486..7aa6996 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -110,6 +110,8 @@  static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+
+extern bool contains_array_notation_expr (tree);
 
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -3027,6 +3029,8 @@  convert_arguments (tree typelist, VEC(tree,gc) *values,
       bool npc;
       tree parmval;
 
+      if (flag_enable_cilk && contains_array_notation_expr (val))
+	continue;
       if (type == void_type_node)
 	{
 	  if (selector)
@@ -3268,11 +3272,16 @@  convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error_at (input_location,
-		"too few arguments to function %qE", function);
-      if (fundecl && !DECL_BUILT_IN (fundecl))
-	inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
-      return -1;
+      if (flag_enable_cilk && contains_array_notation_expr (function))
+	;
+      else
+	{
+	  error_at (input_location,
+		    "too few arguments to function %qE", function);
+	  if (fundecl && !DECL_BUILT_IN (fundecl))
+	    inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
+	  return -1;
+	}
     }
 
   return error_args ? -1 : (int) parmnum;
@@ -5173,6 +5182,9 @@  convert_for_assignment (location_t location, tree type, tree rhs,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
+  if (flag_enable_cilk && contains_array_notation_expr (rhs))
+    return rhs;
+  
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -5719,16 +5731,20 @@  convert_for_assignment (location_t location, tree type, tree rhs,
 	 or one that results from arithmetic, even including
 	 a cast to integer type.  */
       if (!null_pointer_constant)
-	WARN_FOR_ASSIGNMENT (location, 0,
-			     G_("passing argument %d of %qE makes "
-				"pointer from integer without a cast"),
-			     G_("assignment makes pointer from integer "
-				"without a cast"),
-			     G_("initialization makes pointer from "
-				"integer without a cast"),
-			     G_("return makes pointer from integer "
-				"without a cast"));
-
+	{
+	  if (flag_enable_cilk && contains_array_notation_expr (rhs))
+	    ;
+	  else
+	    WARN_FOR_ASSIGNMENT (location, 0,
+				 G_("passing argument %d of %qE makes "
+				    "pointer from integer without a cast"),
+				 G_("assignment makes pointer from integer "
+				    "without a cast"),
+				 G_("initialization makes pointer from "
+				    "integer without a cast"),
+				 G_("return makes pointer from integer "
+				    "without a cast"));
+	}
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
diff --git a/gcc/testsuite/ChangeLog.cilk b/gcc/testsuite/ChangeLog.cilk
index 9fa7413..c032e14 100644
--- a/gcc/testsuite/ChangeLog.cilk
+++ b/gcc/testsuite/ChangeLog.cilk
@@ -1,3 +1,7 @@ 
+2012-01-25  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* gcc.dg/cilk-plus/array_notation_tests/builtin_func_double.c: New.
+
 2012-01-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	*  g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc: New.
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/builtin_func_double.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/builtin_func_double.c
new file mode 100644
index 0000000..e52bbcc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/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, y);
+#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_zeros (array3[:] * array4[:]); 
+  y = __sec_reduce_all_zeros ( 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;
+}