]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/c/c-array-notation.c
Replaced Dynamic arrays with vec trees in Array Notation for C.
[thirdparty/gcc.git] / gcc / c / c-array-notation.c
index 03b66b9cf794b9abe536d509036c5af804377013..7788f7bf145e25ed759c301ee9ba81e90367f92e 100644 (file)
 #include "opts.h"
 #include "c-family/c-common.h"
 
+/* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
+   to a variable and then set *VALUE to the new variable.  */
+
+static inline void
+make_triplet_val_inv (location_t loc, tree *value)
+{
+  tree var, new_exp;
+  if (TREE_CODE (*value) != INTEGER_CST
+      && TREE_CODE (*value) != PARM_DECL
+      && TREE_CODE (*value) != VAR_DECL)
+    {
+      var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
+      new_exp = build_modify_expr (loc, var, TREE_TYPE (var), NOP_EXPR, loc,
+                                  *value, TREE_TYPE (*value));
+      add_stmt (new_exp);
+      *value = var;
+    }
+}
+
+/* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT
+   or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
+   using data from LENGTH, COUNT_DOWN, and VAR.  INCR and CMP vectors are of
+   size RANK.  */
+
+static void
+create_cmp_incr (location_t loc, vec<an_loop_parts> *node, size_t rank,
+                vec<vec<an_parts> > an_info)
+{
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      tree var = (*node)[ii].var;
+      tree length = an_info[0][ii].length;
+      (*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, 0);
+      (*node)[ii].cmp = build2 (LT_EXPR, boolean_type_node, var, length);
+    }
+}
+
+/* Returns a vector of size RANK that contains an array ref that is derived from
+   array notation triplet parameters stored in VALUE, START, STRIDE.  IS_VECTOR
+   is used to check if the data stored at its corresponding location is an
+   array notation. VAR is the induction variable passed in by the caller.
+
+   For example: For an array notation A[5:10:2], the vector start  will be
+   of size 1 holding '5', stride of same size as start but holding the value of
+   as 2, is_vector as true and count_down as false. Let's assume VAR is 'x'
+   This function returns a vector of size 1 with the following data:
+   A[5 + (x * 2)] .
+*/
+
+static vec<tree, va_gc> *
+create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
+                  vec<an_loop_parts> an_loop_info, size_t size, size_t rank)
+{
+  tree ind_mult, ind_incr;
+  vec<tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < size; ii++)
+    if (an_info[ii][0].is_vector)
+      {
+       tree array_opr = an_info[ii][rank - 1].value;
+       for (int s_jj = rank - 1; s_jj >= 0; s_jj--)
+         {
+           tree var = an_loop_info[s_jj].var;
+           tree stride = an_info[ii][s_jj].stride;
+           tree start = an_info[ii][s_jj].start;
+           ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
+           ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
+           array_opr = build_array_ref (loc, array_opr, ind_incr);
+         }
+       vec_safe_push (array_operand, array_opr);
+      }
+    else
+      /* This is just a dummy node to make sure both the list sizes for both
+        array list and array operand list are the same.  */
+      vec_safe_push (array_operand, integer_one_node);
+  return array_operand;
+}                   
+  
 /* 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.  */
@@ -124,16 +201,13 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
   tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
   tree new_exp_init = NULL_TREE;
   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_init, array_op0;
-  tree **array_value, **array_stride, **array_length, **array_start;
-  tree *compare_expr, *expr_incr, *ind_init;
+  size_t list_size = 0, rank = 0, ii = 0;
+  tree loop_init, array_op0;
   tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
-  bool **count_down, **array_vector;
   location_t location = UNKNOWN_LOCATION;
   tree loop_with_init = alloc_stmt_list ();
-  
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
   enum built_in_function an_type =
     is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
   if (an_type == BUILT_IN_NONE)
@@ -201,157 +275,27 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
     default:
       gcc_unreachable (); 
     }
-  
-  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);
-    }
-
-  compare_expr = 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;
-           }
-       }
-    }
 
+  an_loop_info.safe_grow_cleared (rank);
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
   loop_init = alloc_stmt_list ();
 
   for (ii = 0; ii < rank; ii++)
     {
-      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+      an_loop_info[ii].var = 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,
+      an_loop_info[ii].ind_init =
+       build_modify_expr (location, an_loop_info[ii].var,
+                          TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
                           location,
-                          build_int_cst (TREE_TYPE (array_var[ii]), 0),
-                          TREE_TYPE (array_var[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);
+                          build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
+                          TREE_TYPE (an_loop_info[ii].var));   
     }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
   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]);
-       }
-    }
 
+  create_cmp_incr (location, &an_loop_info, rank, an_info);
   if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
     {
       *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
@@ -519,7 +463,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
        {
          new_yes_ind = build_modify_expr
            (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
-            location, array_var[0], TREE_TYPE (array_var[0]));
+            location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
          new_yes_expr = build_modify_expr
            (location, array_ind_value, TREE_TYPE (array_ind_value),
             NOP_EXPR,
@@ -569,7 +513,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
        {
          new_yes_ind = build_modify_expr
            (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
-            location, array_var[0], TREE_TYPE (array_var[0]));
+            location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
          new_yes_expr = build_modify_expr
            (location, array_ind_value, TREE_TYPE (array_ind_value),
             NOP_EXPR,
@@ -619,7 +563,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
     }
 
   for (ii = 0; ii < rank; ii++)
-    append_to_statement_list (ind_init [ii], &loop_init);
+    append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);
 
   if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
@@ -632,33 +576,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
   for (ii = 0; ii < rank; ii++)
     {
       tree new_loop = push_stmt_list ();
-      c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
-                    NULL_TREE, true);
+      c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+                    body, NULL_TREE, NULL_TREE, true);
       body = pop_stmt_list (new_loop);
     }
   append_to_statement_list_force (body, &loop_with_init);
-  
-  XDELETEVEC (compare_expr);
-  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);
+
+  an_info.release ();
+  an_loop_info.release ();
   
   return loop_with_init;
 }
@@ -674,31 +599,22 @@ 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;
+  bool found_builtin_fn = false;
   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 an_init = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
-  tree *cond_expr = NULL;
+  tree an_init = NULL_TREE;
+  vec<tree> cond_expr = vNULL;
   tree body, loop_with_init = alloc_stmt_list();
   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;
+  size_t ii = 0;
   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;
-
+  tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
+  size_t rhs_list_size = 0, lhs_list_size = 0; 
+  vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
+  vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
+  
   /* 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)
@@ -810,296 +726,49 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
   /* 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);
-
-      if (TREE_CODE (array_begin) != INTEGER_CST)
-       {
-         begin_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)));      
-         ARRAY_NOTATION_START (array_node) = begin_var;
-       }
-
-      if (TREE_CODE (array_lngth) != INTEGER_CST)
-       {
-         lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                 integer_type_node);
-         add_stmt (build_modify_expr (location, lngth_var,
-                                      TREE_TYPE (lngth_var),
-                                      NOP_EXPR, location, array_lngth,
-                                      TREE_TYPE (array_lngth)));
-         ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
-       }
-      if (TREE_CODE (array_strde) != INTEGER_CST)
-       {
-         strde_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                 integer_type_node);
-
-         add_stmt (build_modify_expr (location, strde_var,
-                                      TREE_TYPE (strde_var),
-                                      NOP_EXPR, location, array_strde,
-                                      TREE_TYPE (array_strde)));
-         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);
-
-         if (TREE_CODE (array_begin) != INTEGER_CST)
-           {
-             begin_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)));
-             ARRAY_NOTATION_START (array_node) = begin_var;
-           }
-         if (TREE_CODE (array_lngth) != INTEGER_CST)
-           {
-             lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-             add_stmt (build_modify_expr (location, lngth_var,
-                                          TREE_TYPE (lngth_var),
-                                          NOP_EXPR, location, array_lngth,
-                                          TREE_TYPE (array_lngth)));
-             ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
-           }
-         if (TREE_CODE (array_strde) != INTEGER_CST)
-           {
-             strde_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-
-             add_stmt (build_modify_expr (location, strde_var,
-                                          TREE_TYPE (strde_var),
-                                          NOP_EXPR, location, array_strde,
-                                          TREE_TYPE (array_strde)));
-             ARRAY_NOTATION_STRIDE (array_node) = strde_var;
-           }
-       }
+      make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_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);
-  cond_expr = 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);
+    if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+      {  
+       tree array_node = (*rhs_list)[ii];
+       make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
+       make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
+       make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
+      }
   
-  rhs_count_down =  XNEWVEC (bool *, rhs_list_size);
-  for (ii = 0; ii < rhs_list_size; ii++)
-    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+  cond_expr.safe_grow_cleared (MAX (lhs_rank, 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;
-         ii_tree = (*lhs_list)[ii];
-         while (ii_tree)
-           {
-             if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
-               {
-                 lhs_array[ii][jj] = ii_tree;
-                 jj++;
-                 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
-               }
-             else if (TREE_CODE (ii_tree) == ARRAY_REF)
-               ii_tree = TREE_OPERAND (ii_tree, 0);
-             else if (TREE_CODE (ii_tree) == VAR_DECL
-                      || TREE_CODE (ii_tree) == PARM_DECL)
-               break;
-           }
-       }
-    }
-  else
-    lhs_array[0][0] = NULL_TREE;
-  
+  lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   if (rhs_rank)
-    {
-      for (ii = 0; ii < rhs_list_size; ii++)
-       { 
-         jj = 0; 
-         ii_tree = (*rhs_list)[ii];
-         while (ii_tree)
-           {
-             if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
-               {
-                 rhs_array[ii][jj] = ii_tree;
-                 jj++;
-                 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
-               }
-             else if (TREE_CODE (ii_tree) == ARRAY_REF)
-               ii_tree = TREE_OPERAND (ii_tree, 0);
-             else if (TREE_CODE (ii_tree) == VAR_DECL
-                      || TREE_CODE (ii_tree) == PARM_DECL
-                      || TREE_CODE (ii_tree) == CALL_EXPR)
-               break;
-           }
-       }
-    }
+    rhs_an_loop_info.safe_grow_cleared (rhs_rank);
 
-  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++)
+  cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
+                               &lhs_an_info);
+  if (rhs_rank)
     {
-      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;
-           rhs_length[ii][jj] = NULL_TREE;
-         }
+      rhs_an_loop_info.safe_grow_cleared (rhs_rank);
+      cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
+                                   &rhs_an_info);
     }
-
-  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
-                                lhs_list_size, lhs_rank)
-      || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
-                                   rhs_list_size, rhs_rank))
+  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
+      || (rhs_rank
+         && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info)))
     {
       pop_stmt_list (an_init);
       return error_mark_node;
     }
-
   if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
-      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
-      && rhs_length[0][0]
-      && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+      && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST
+      && rhs_an_info[0][0].length
+      && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST)
     {
-      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
-      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length);
       /* Length can be negative or positive.  As long as the magnitude is OK,
         then the array notation is valid.  */
       if (absu_hwi (l_length) != absu_hwi (r_length))
@@ -1110,256 +779,77 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
        }
     }
   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]));
-       }
-    }
-
+    if (lhs_an_info[0][ii].is_vector)
+      {
+       lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                              integer_type_node);
+       lhs_an_loop_info[ii].ind_init = build_modify_expr
+         (location, lhs_an_loop_info[ii].var,
+          TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR,
+          location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)),
+          TREE_TYPE (lhs_an_loop_info[ii].var));
+      }
   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]));
+      rhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                            integer_type_node);
+      rhs_an_loop_info[ii].ind_init = build_modify_expr
+       (location, rhs_an_loop_info[ii].var,
+        TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR,
+        location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0),
+        TREE_TYPE (rhs_an_loop_info[ii].var));
     }
   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);
-       }
+      lhs_array_operand = create_array_refs
+       (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank);
       replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
       array_expr_lhs = lhs;
     }
-
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
   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;
-                     }
-                 }  
-           }
-       }
+      rhs_array_operand = create_array_refs
+       (location, rhs_an_info, rhs_an_loop_info, rhs_list_size, rhs_rank);
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      vec_safe_truncate (rhs_array_operand, 0);
+      rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
+                                                rhs_an_loop_info, rhs_rank,
+                                                rhs);
+      if (!rhs_array_operand)
+       return error_mark_node;
       replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
-      array_expr_rhs = rhs;
     }
-  else
+  else if (rhs_list_size > 0)
     {
-      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;
-                     }
-                 }  
-           }
-       }
+      rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
+                                                lhs_an_loop_info, lhs_rank,
+                                                lhs);
+      if (!rhs_array_operand)
+       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 is NULL, then we have function that returns void or
-     its return value is ignored.  */
-  if (!array_expr_lhs)
-    array_expr_lhs = lhs;
-
+  array_expr_lhs = lhs;
+  array_expr_rhs = rhs;
   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]);
-       }
-    }
+  create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info);
+  if (rhs_rank)
+    create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info);
+  
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    if (ii < lhs_rank && ii < rhs_rank)
+      cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
+                             lhs_an_loop_info[ii].cmp,
+                             rhs_an_loop_info[ii].cmp);
+    else if (ii < lhs_rank && ii >= rhs_rank)
+      cond_expr[ii] = lhs_an_loop_info[ii].cmp;
+    else
+      gcc_unreachable ();
 
   an_init = pop_stmt_list (an_init);
   append_to_statement_list_force (an_init, &loop_with_init);
@@ -1369,18 +859,27 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
       tree incr_list = alloc_stmt_list ();
       tree new_loop = push_stmt_list ();
       if (lhs_rank)
-       add_stmt (lhs_ind_init[ii]);
+       add_stmt (lhs_an_loop_info[ii].ind_init);
       if (rhs_rank)
-       add_stmt (rhs_ind_init[ii]);
+       add_stmt (rhs_an_loop_info[ii].ind_init);
       if (lhs_rank)
-       append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
-      if (rhs_rank && rhs_expr_incr[ii])
-       append_to_statement_list_force (rhs_expr_incr[ii], &incr_list);
+       append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
+      if (rhs_rank && rhs_an_loop_info[ii].incr)
+       append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
       c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
                     NULL_TREE, true);
       body = pop_stmt_list (new_loop);
     }
   append_to_statement_list_force (body, &loop_with_init);
+
+  lhs_an_info.release ();
+  lhs_an_loop_info.release ();
+  if (rhs_rank)
+    {
+      rhs_an_info.release ();
+      rhs_an_loop_info.release ();
+    }
+  cond_expr.release ();
   return loop_with_init;
 }
 
@@ -1396,15 +895,13 @@ 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_init;
-  tree **array_value, **array_stride, **array_length, **array_start;
-  tree *compare_expr, *expr_incr, *ind_init;
-  bool **count_down, **array_vector;
-  tree begin_var, lngth_var, strde_var;
+  size_t rank = 0, ii = 0;
+  tree loop_init;
   location_t location = EXPR_LOCATION (stmt);
   tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
   if (TREE_CODE (stmt) == COND_EXPR)
     cond = COND_EXPR_COND (stmt);
   else if (TREE_CODE (stmt) == SWITCH_EXPR)
@@ -1440,7 +937,6 @@ fix_conditional_array_notations_1 (tree stmt)
            }
        }
     }
-
   if (!find_rank (location, stmt, stmt, true, &rank))
     {
       pop_stmt_list (loop_init);
@@ -1458,194 +954,34 @@ fix_conditional_array_notations_1 (tree stmt)
     return stmt;
 
   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);
-    }
-
-  compare_expr = 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];
-      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);
-
-         if (TREE_CODE (array_begin) != INTEGER_CST)
-           {
-             begin_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)));
-             ARRAY_NOTATION_START (array_node) = begin_var;
-           }
-         if (TREE_CODE (array_lngth) != INTEGER_CST)
-           {
-             lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-             add_stmt (build_modify_expr (location, lngth_var,
-                                          TREE_TYPE (lngth_var),
-                                          NOP_EXPR, location, array_lngth,
-                                          TREE_TYPE (array_lngth)));
-             ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
-           }
-         if (TREE_CODE (array_strde) != INTEGER_CST)
-           {
-             strde_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-             add_stmt (build_modify_expr (location, strde_var,
-                                          TREE_TYPE (strde_var),
-                                          NOP_EXPR, location, array_strde,
-                                          TREE_TYPE (array_strde)));
-             ARRAY_NOTATION_STRIDE (array_node) = strde_var;
-           }
-       }
-    }  
-  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++;
-       }
-    }
+  an_loop_info.safe_grow_cleared (rank);
+  
   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;
-           }
-       }
-    }
-
+    if ((*array_list)[ii]
+       && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+      {
+       tree array_node = (*array_list)[ii];
+       make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
+       make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
+       make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
+      }
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
   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,
+      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                        integer_type_node);
+      an_loop_info[ii].ind_init =
+       build_modify_expr (location, an_loop_info[ii].var,
+                          TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
                           location,
-                          build_int_cst (TREE_TYPE (array_var[ii]), 0),
-                          TREE_TYPE (array_var[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);
+                          build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
+                          TREE_TYPE (an_loop_info[ii].var));
     }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
   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]);
-       }
-    }
-
+  create_cmp_incr (location, &an_loop_info, rank, an_info);
+  
   loop_init = pop_stmt_list (loop_init);
   body = stmt;
   append_to_statement_list_force (loop_init, &loop_with_init);
@@ -1653,33 +989,15 @@ fix_conditional_array_notations_1 (tree stmt)
   for (ii = 0; ii < rank; ii++)
     {
       tree new_loop = push_stmt_list ();
-      add_stmt (ind_init[ii]);
-      c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
-                    NULL_TREE, true);
+      add_stmt (an_loop_info[ii].ind_init);
+      c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+                    body, NULL_TREE, NULL_TREE, true);
       body = pop_stmt_list (new_loop);
     }
   append_to_statement_list_force (body, &loop_with_init);
-  XDELETEVEC (expr_incr);
-  XDELETEVEC (ind_init);
-  
-  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);
+  an_loop_info.release ();
+  an_info.release ();
 
   return loop_with_init;
 }
@@ -1716,13 +1034,11 @@ fix_array_notation_expr (location_t location, enum tree_code code,
 {
 
   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_init;
-  tree **array_value, **array_stride, **array_length, **array_start;
-  tree *compare_expr, *expr_incr, *ind_init;
+  size_t list_size = 0, rank = 0, ii = 0;
+  tree loop_init;
   tree body, loop_with_init = alloc_stmt_list ();
-  bool **count_down, **array_vector;
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
   
   if (!find_rank (location, arg.value, arg.value, false, &rank))
     {
@@ -1742,165 +1058,33 @@ fix_array_notation_expr (location_t location, enum tree_code code,
     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);
-    }
 
-  compare_expr = 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++;
-       }
-    }
+  an_loop_info.safe_grow_cleared (rank);
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
   
   loop_init = push_stmt_list ();
-
-  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,
+      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                        integer_type_node);
+      an_loop_info[ii].ind_init =
+       build_modify_expr (location, an_loop_info[ii].var,
+                          TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
                           location,
-                          build_int_cst (TREE_TYPE (array_var[ii]), 0),
-                          TREE_TYPE (array_var[ii]));
+                          build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
+                          TREE_TYPE (an_loop_info[ii].var));;
        
     }
-  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);
-    }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
   replace_array_notations (&arg.value, true, array_list, array_operand);
+  create_cmp_incr (location, &an_loop_info, rank, an_info);
 
-  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]);
-       }
-    }
-  
+  arg = default_function_array_read_conversion (location, arg);
   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);
-    }
+    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);
-    }
+    arg = parser_build_unary_op (location, code, arg);
 
   loop_init = pop_stmt_list (loop_init);
   append_to_statement_list_force (loop_init, &loop_with_init);
@@ -1909,36 +1093,16 @@ fix_array_notation_expr (location_t location, enum tree_code code,
   for (ii = 0; ii < rank; ii++)
     {
       tree new_loop = push_stmt_list ();
-      add_stmt (ind_init[ii]);
-      c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
+      add_stmt (an_loop_info[ii].ind_init);
+      c_finish_loop (location, an_loop_info[ii].cmp,
+                    an_loop_info[ii].incr, body, NULL_TREE,
                     NULL_TREE, true);
       body = pop_stmt_list (new_loop);
     }
   append_to_statement_list_force (body, &loop_with_init);
-   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_with_init;
+  an_info.release ();
+  an_loop_info.release ();
   return arg;
 }
 
@@ -1950,15 +1114,12 @@ 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_init;
-  tree **array_value, **array_stride, **array_length, **array_start;
+  size_t list_size = 0, rank = 0, ii = 0;
+  tree loop_init;
   tree body, loop_with_init = alloc_stmt_list ();
-  tree *compare_expr, *expr_incr, *ind_init;
-  bool **count_down, **array_vector;
-  tree begin_var, lngth_var, strde_var;
   location_t location = UNKNOWN_LOCATION;
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
 
   if (TREE_CODE (arg) == CALL_EXPR
       && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
@@ -1967,8 +1128,7 @@ fix_array_notation_call_expr (tree arg)
       /* 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_init;
-    }
-  
+    }  
   if (!find_rank (location, arg, arg, false, &rank))
     return error_mark_node;
   
@@ -1981,237 +1141,53 @@ fix_array_notation_call_expr (tree 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);
-    }
-
-  compare_expr = 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);
+  an_loop_info.safe_grow_cleared (rank);
   
   loop_init = 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);
-
-         if (TREE_CODE (array_begin) != INTEGER_CST)
-           {
-             begin_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)));
-             ARRAY_NOTATION_START (array_node) = begin_var;
-           }
-         if (TREE_CODE (array_lngth) != INTEGER_CST)
-           {
-             lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-             add_stmt (build_modify_expr (location, lngth_var,
-                                          TREE_TYPE (lngth_var),
-                                          NOP_EXPR, location, array_lngth,
-                                          TREE_TYPE (array_lngth)));
-             ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
-           }
-         if (TREE_CODE (array_strde) != INTEGER_CST)
-           {
-             strde_var = build_decl (location, VAR_DECL, NULL_TREE,
-                                     integer_type_node);
-             add_stmt (build_modify_expr (location, strde_var,
-                                          TREE_TYPE (strde_var),
-                                          NOP_EXPR, location, array_strde,
-                                          TREE_TYPE (array_strde)));
-             ARRAY_NOTATION_STRIDE (array_node) = strde_var;
-           }
-       }
-    }
-  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))
+    if ((*array_list)[ii]
+       && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
        {
-         array_ops[ii][jj] = jj_tree;
-         jj++;
+         tree array_node = (*array_list)[ii];
+         make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
+         make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
+         make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
        }
-    }
-
-  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;
-           }
-       }
-    }
-
-  if (length_mismatch_in_expr_p (location, array_length, list_size, rank))
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
+  if (length_mismatch_in_expr_p (location, an_info))
     {
       pop_stmt_list (loop_init);
       return error_mark_node;
     }
-  
   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]));
+      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                        integer_type_node);
+      an_loop_info[ii].ind_init =
+       build_modify_expr (location, an_loop_info[ii].var,
+                          TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location,
+                          build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
+                          TREE_TYPE (an_loop_info[ii].var));
        
     }
-  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);
-    }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
   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]);
-       }
-    }
-
+  create_cmp_incr (location, &an_loop_info, rank, an_info);
   loop_init = pop_stmt_list (loop_init);
   append_to_statement_list_force (loop_init, &loop_with_init);
   body = arg;
   for (ii = 0; ii < rank; ii++)
     {
       tree new_loop = push_stmt_list ();
-      add_stmt (ind_init[ii]);
-      c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
-                    NULL_TREE, true);
+      add_stmt (an_loop_info[ii].ind_init);
+      c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
+                    body, NULL_TREE, NULL_TREE, true);
       body = pop_stmt_list (new_loop);
     }
   append_to_statement_list_force (body, &loop_with_init);
-  XDELETEVEC (compare_expr);
-  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);
-  
+  an_loop_info.release ();
+  an_info.release ();
   return loop_with_init;
 }
 
@@ -2390,4 +1366,3 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
   
   return array_ntn_tree;
 }
-