https://gcc.gnu.org/g:907d363c5dfcf80a95bc0fa44b11268b95724a71

commit 907d363c5dfcf80a95bc0fa44b11268b95724a71
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Wed Apr 2 16:28:11 2025 +0200

    Sauvegarde modifs.

Diff:
---
 gcc/fortran/class.cc            | 244 +++-----------
 gcc/fortran/intrinsic.cc        |   8 -
 gcc/fortran/trans-array.cc      | 690 ++++++++++++++++++++++++----------------
 gcc/fortran/trans-array.h       |   3 +-
 gcc/fortran/trans-decl.cc       |   6 +-
 gcc/fortran/trans-descriptor.cc | 267 ++++++++--------
 gcc/fortran/trans-expr.cc       |   4 +-
 gcc/fortran/trans-intrinsic.cc  |  46 +--
 gcc/fortran/trans-io.cc         |  53 ++-
 gcc/fortran/trans-openmp.cc     |   2 +-
 gcc/fortran/trans-types.cc      |  61 ++--
 gcc/fortran/trans.h             |  34 +-
 libgfortran/io/transfer.c       |   4 +-
 13 files changed, 690 insertions(+), 732 deletions(-)

diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index 41be63bf768f..f7442f5c22ec 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1491,19 +1491,12 @@ finalization_get_offset (gfc_symbol *idx, gfc_symbol 
*idx2, gfc_symbol *offset,
 static void
 finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini,
                              gfc_symbol *array, gfc_symbol *byte_stride,
-                             gfc_symbol *idx, gfc_symbol *ptr,
-                             gfc_symbol *nelem,
-                             gfc_symbol *strides, gfc_symbol *sizes,
-                             gfc_symbol *idx2, gfc_symbol *offset,
-                             gfc_symbol *is_contiguous, gfc_expr *rank,
+                             gfc_symbol *nelem, gfc_symbol *is_contiguous,
                              gfc_namespace *sub_ns)
 {
-  gfc_symbol *tmp_array, *ptr2;
-  gfc_expr *size_expr, *offset2, *expr;
+  gfc_symbol *ptr2;
+  gfc_expr *size_expr, *expr;
   gfc_namespace *ns;
-  gfc_iterator *iter;
-  gfc_code *block2;
-  int i;
 
   block->next = gfc_get_code (EXEC_IF);
   block = block->next;
@@ -1611,81 +1604,26 @@ finalizer_insert_packed_call (gfc_code *block, 
gfc_finalizer *fini,
   ptr2->attr.flavor = FL_VARIABLE;
   ptr2->attr.pointer = 1;
   ptr2->attr.artificial = 1;
+  ptr2->attr.dimension = 1;
+  ptr2->as = gfc_get_array_spec ();
+  ptr2->as->type = AS_DEFERRED;
+  ptr2->as->rank = 1;
   gfc_set_sym_referenced (ptr2);
   gfc_commit_symbol (ptr2);
 
-  gfc_get_symbol ("tmp_array", ns, &tmp_array);
-  tmp_array->ts.type = BT_DERIVED;
-  tmp_array->ts.u.derived = array->ts.u.derived;
-  tmp_array->attr.flavor = FL_VARIABLE;
-  tmp_array->attr.dimension = 1;
-  tmp_array->attr.artificial = 1;
-  tmp_array->as = gfc_get_array_spec();
-  tmp_array->attr.intent = INTENT_INOUT;
-  tmp_array->as->type = AS_EXPLICIT;
-  tmp_array->as->rank = fini->proc_tree->n.sym->formal->sym->as->rank;
-
-  for (i = 0; i < tmp_array->as->rank; i++)
-    {
-      gfc_expr *shape_expr;
-      tmp_array->as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind,
-                                                 NULL, 1);
-      /* SIZE (array, dim=i+1, kind=gfc_index_integer_kind).  */
-      shape_expr
-       = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_SIZE, "size",
-                                   gfc_current_locus, 3,
-                                   gfc_lval_expr_from_sym (array),
-                                   gfc_get_int_expr (gfc_default_integer_kind,
-                                                     NULL, i+1),
-                                   gfc_get_int_expr (gfc_default_integer_kind,
-                                                     NULL,
-                                                     gfc_index_integer_kind));
-      shape_expr->ts.kind = gfc_index_integer_kind;
-      tmp_array->as->upper[i] = shape_expr;
-    }
-  gfc_set_sym_referenced (tmp_array);
-  gfc_commit_symbol (tmp_array);
-
-  /* Create loop.  */
-  iter = gfc_get_iterator ();
-  iter->var = gfc_lval_expr_from_sym (idx);
-  iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
-  iter->end = gfc_lval_expr_from_sym (nelem);
-  iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
-
-  block = gfc_get_code (EXEC_DO);
+  block = gfc_get_code (EXEC_POINTER_ASSIGN);
   ns->code = block;
-  block->ext.iterator = iter;
-  block->block = gfc_get_code (EXEC_DO);
-
-  /* Offset calculation for the new array: idx * size of type (in bytes).  */
-  offset2 = gfc_get_expr ();
-  offset2->expr_type = EXPR_OP;
-  offset2->where = gfc_current_locus;
-  offset2->value.op.op = INTRINSIC_TIMES;
-  offset2->value.op.op1 = gfc_lval_expr_from_sym (idx);
-  offset2->value.op.op2 = gfc_copy_expr (size_expr);
-  offset2->ts = byte_stride->ts;
-
-  /* Offset calculation of "array".  */
-  block2 = finalization_get_offset (idx, idx2, offset, strides, sizes,
-                                   byte_stride, rank, block->block, sub_ns);
-
-  /* Create code for
-     CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
-                      + idx * stride, c_ptr), ptr).  */
-  block2->next = finalization_scalarizer (array, ptr,
-                                         gfc_lval_expr_from_sym (offset),
-                                         sub_ns);
-  block2 = block2->next;
-  block2->next = finalization_scalarizer (tmp_array, ptr2, offset2, sub_ns);
-  block2 = block2->next;
-
-  /* ptr2 = ptr.  */
-  block2->next = gfc_get_code (EXEC_ASSIGN);
-  block2 = block2->next;
-  block2->expr1 = gfc_lval_expr_from_sym (ptr2);
-  block2->expr2 = gfc_lval_expr_from_sym (ptr);
+  block->expr1 = gfc_lval_expr_from_sym (ptr2);
+  gfc_free_ref_list (block->expr1->ref);
+  block->expr1->ref = gfc_get_ref ();
+  block->expr1->ref->type = REF_ARRAY;
+  block->expr1->ref->u.ar.type = AR_SECTION;
+  block->expr1->ref->u.ar.dimen = 1;
+  block->expr1->ref->u.ar.as = ptr2->as;
+  block->expr1->ref->u.ar.dimen_type[0] = DIMEN_RANGE;
+  block->expr1->ref->u.ar.start[0] = gfc_get_int_expr (gfc_index_integer_kind, 
nullptr, 1);
+  block->expr1->ref->u.ar.end[0] = gfc_lval_expr_from_sym (nelem);
+  block->expr2 = gfc_lval_expr_from_sym (array);
 
   /* Call now the user's final subroutine.  */
   block->next  = gfc_get_code (EXEC_CALL);
@@ -1693,44 +1631,7 @@ finalizer_insert_packed_call (gfc_code *block, 
gfc_finalizer *fini,
   block->symtree = fini->proc_tree;
   block->resolved_sym = fini->proc_tree->n.sym;
   block->ext.actual = gfc_get_actual_arglist ();
-  block->ext.actual->expr = gfc_lval_expr_from_sym (tmp_array);
-
-  if (fini->proc_tree->n.sym->formal->sym->attr.intent == INTENT_IN)
-    return;
-
-  /* Copy back.  */
-
-  /* Loop.  */
-  iter = gfc_get_iterator ();
-  iter->var = gfc_lval_expr_from_sym (idx);
-  iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
-  iter->end = gfc_lval_expr_from_sym (nelem);
-  iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
-
-  block->next = gfc_get_code (EXEC_DO);
-  block = block->next;
-  block->ext.iterator = iter;
-  block->block = gfc_get_code (EXEC_DO);
-
-  /* Offset calculation of "array".  */
-  block2 = finalization_get_offset (idx, idx2, offset, strides, sizes,
-                                   byte_stride, rank, block->block, sub_ns);
-
-  /* Create code for
-     CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
-                      + offset, c_ptr), ptr).  */
-  block2->next = finalization_scalarizer (array, ptr,
-                                         gfc_lval_expr_from_sym (offset),
-                                         sub_ns);
-  block2 = block2->next;
-  block2->next = finalization_scalarizer (tmp_array, ptr2,
-                                         gfc_copy_expr (offset2), sub_ns);
-  block2 = block2->next;
-
-  /* ptr = ptr2.  */
-  block2->next = gfc_get_code (EXEC_ASSIGN);
-  block2->next->expr1 = gfc_lval_expr_from_sym (ptr);
-  block2->next->expr2 = gfc_lval_expr_from_sym (ptr2);
+  block->ext.actual->expr = gfc_lval_expr_from_sym (ptr2);
 }
 
 
@@ -2025,29 +1926,10 @@ generate_finalization_wrapper (gfc_symbol *derived, 
gfc_namespace *ns,
   last_code->ext.iterator = iter;
   last_code->block = gfc_get_code (EXEC_DO);
 
-  /* strides(idx) = _F._stride(array,dim=idx).  */
+  /* sizes(idx) = ...  */
   last_code->block->next = gfc_get_code (EXEC_ASSIGN);
   block = last_code->block->next;
 
-  block->expr1 = gfc_lval_expr_from_sym (strides);
-  block->expr1->ref = gfc_get_ref ();
-  block->expr1->ref->type = REF_ARRAY;
-  block->expr1->ref->u.ar.type = AR_ELEMENT;
-  block->expr1->ref->u.ar.dimen = 1;
-  block->expr1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
-  block->expr1->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx);
-  block->expr1->ref->u.ar.as = strides->as;
-
-  block->expr2 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_STRIDE, "stride",
-                                          gfc_current_locus, 2,
-                                          gfc_lval_expr_from_sym (array),
-                                          gfc_lval_expr_from_sym (idx));
-
-  /* sizes(idx) = sizes(idx-1) * size(array,dim=idx, kind=index_kind).  */
-  block->next = gfc_get_code (EXEC_ASSIGN);
-  block = block->next;
-
-  /* sizes(idx) = ...  */
   block->expr1 = gfc_lval_expr_from_sym (sizes);
   block->expr1->ref = gfc_get_ref ();
   block->expr1->ref->type = REF_ARRAY;
@@ -2093,54 +1975,13 @@ generate_finalization_wrapper (gfc_symbol *derived, 
gfc_namespace *ns,
   block->expr2->value.op.op2->ts.kind = gfc_index_integer_kind;
   block->expr2->ts = idx->ts;
 
-  /* if (strides (idx) /= sizes(idx-1)) is_contiguous = .false.  */
-  block->next = gfc_get_code (EXEC_IF);
-  block = block->next;
-
-  block->block = gfc_get_code (EXEC_IF);
-  block = block->block;
-
-  /* if condition: strides(idx) /= sizes(idx-1).  */
-  block->expr1 = gfc_get_expr ();
-  block->expr1->ts.type = BT_LOGICAL;
-  block->expr1->ts.kind = gfc_default_logical_kind;
-  block->expr1->expr_type = EXPR_OP;
-  block->expr1->where = gfc_current_locus;
-  block->expr1->value.op.op = INTRINSIC_NE;
-
-  block->expr1->value.op.op1 = gfc_lval_expr_from_sym (strides);
-  block->expr1->value.op.op1->ref = gfc_get_ref ();
-  block->expr1->value.op.op1->ref->type = REF_ARRAY;
-  block->expr1->value.op.op1->ref->u.ar.type = AR_ELEMENT;
-  block->expr1->value.op.op1->ref->u.ar.dimen = 1;
-  block->expr1->value.op.op1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
-  block->expr1->value.op.op1->ref->u.ar.start[0] = gfc_lval_expr_from_sym 
(idx);
-  block->expr1->value.op.op1->ref->u.ar.as = strides->as;
-
-  block->expr1->value.op.op2 = gfc_lval_expr_from_sym (sizes);
-  block->expr1->value.op.op2->ref = gfc_get_ref ();
-  block->expr1->value.op.op2->ref->type = REF_ARRAY;
-  block->expr1->value.op.op2->ref->u.ar.as = sizes->as;
-  block->expr1->value.op.op2->ref->u.ar.type = AR_ELEMENT;
-  block->expr1->value.op.op2->ref->u.ar.dimen = 1;
-  block->expr1->value.op.op2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
-  block->expr1->value.op.op2->ref->u.ar.start[0] = gfc_get_expr ();
-  block->expr1->value.op.op2->ref->u.ar.start[0]->expr_type = EXPR_OP;
-  block->expr1->value.op.op2->ref->u.ar.start[0]->where = gfc_current_locus;
-  block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op = 
INTRINSIC_MINUS;
-  block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op1
-       = gfc_lval_expr_from_sym (idx);
-  block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op2
-       = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
-  block->expr1->value.op.op2->ref->u.ar.start[0]->ts
-       = block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op1->ts;
-
-  /* if body: is_contiguous = .false.  */
-  block->next = gfc_get_code (EXEC_ASSIGN);
-  block = block->next;
-  block->expr1 = gfc_lval_expr_from_sym (is_contiguous);
-  block->expr2 = gfc_get_logical_expr (gfc_default_logical_kind,
-                                      &gfc_current_locus, false);
+  /* is_contiguous = is_contiguous(array)  */
+  last_code->next = gfc_get_code (EXEC_ASSIGN);
+  last_code = last_code->next;
+  last_code->expr1 = gfc_lval_expr_from_sym (is_contiguous);
+  last_code->expr2 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_IS_CONTIGUOUS,
+                                          "is_contiguous", gfc_current_locus, 
1,
+                                          gfc_lval_expr_from_sym (array));
 
   /* Obtain the size (number of elements) of "array" MINUS ONE,
      which is used in the scalarization.  */
@@ -2152,28 +1993,21 @@ generate_finalization_wrapper (gfc_symbol *derived, 
gfc_namespace *ns,
   gfc_set_sym_referenced (nelem);
   gfc_commit_symbol (nelem);
 
-  /* nelem = sizes (rank) - 1.  */
+  /* nelem = sizes (rank)  */
   last_code->next = gfc_get_code (EXEC_ASSIGN);
   last_code = last_code->next;
 
   last_code->expr1 = gfc_lval_expr_from_sym (nelem);
 
   last_code->expr2 = gfc_get_expr ();
-  last_code->expr2->expr_type = EXPR_OP;
-  last_code->expr2->value.op.op = INTRINSIC_MINUS;
-  last_code->expr2->value.op.op2
-       = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
-  last_code->expr2->ts = last_code->expr2->value.op.op2->ts;
-  last_code->expr2->where = gfc_current_locus;
-
-  last_code->expr2->value.op.op1 = gfc_lval_expr_from_sym (sizes);
-  last_code->expr2->value.op.op1->ref = gfc_get_ref ();
-  last_code->expr2->value.op.op1->ref->type = REF_ARRAY;
-  last_code->expr2->value.op.op1->ref->u.ar.type = AR_ELEMENT;
-  last_code->expr2->value.op.op1->ref->u.ar.dimen = 1;
-  last_code->expr2->value.op.op1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
-  last_code->expr2->value.op.op1->ref->u.ar.start[0] = gfc_copy_expr (rank);
-  last_code->expr2->value.op.op1->ref->u.ar.as = sizes->as;
+  last_code->expr2 = gfc_lval_expr_from_sym (sizes);
+  last_code->expr2->ref = gfc_get_ref ();
+  last_code->expr2->ref->type = REF_ARRAY;
+  last_code->expr2->ref->u.ar.type = AR_ELEMENT;
+  last_code->expr2->ref->u.ar.dimen = 1;
+  last_code->expr2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
+  last_code->expr2->ref->u.ar.start[0] = gfc_copy_expr (rank);
+  last_code->expr2->ref->u.ar.as = sizes->as;
 
   /* Call final subroutines. We now generate code like:
      use iso_c_binding
@@ -2266,9 +2100,7 @@ generate_finalization_wrapper (gfc_symbol *derived, 
gfc_namespace *ns,
          /* CALL fini_rank (array) - possibly with packing.  */
           if (fini->proc_tree->n.sym->formal->sym->attr.dimension)
            finalizer_insert_packed_call (block, fini, array, byte_stride,
-                                         idx, ptr, nelem, strides,
-                                         sizes, idx2, offset, is_contiguous,
-                                         rank, sub_ns);
+                                         nelem, is_contiguous, sub_ns);
          else
            {
              block->next = gfc_get_code (EXEC_CALL);
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index 30f532b5766b..417d285ec308 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -3125,14 +3125,6 @@ add_functions (void)
 
   make_generic ("size", GFC_ISYM_SIZE, GFC_STD_F95);
 
-  /* Obtain the stride for a given dimensions; to be used only internally.
-     "make_from_module" makes it inaccessible for external users.  */
-  add_sym_2 (GFC_PREFIX ("stride"), GFC_ISYM_STRIDE, CLASS_INQUIRY, ACTUAL_NO,
-            BT_INTEGER, gfc_index_integer_kind, GFC_STD_GNU,
-            NULL, NULL, gfc_resolve_stride,
-            ar, BT_REAL, dr, REQUIRED, dm, BT_INTEGER, ii, OPTIONAL);
-  make_from_module();
-
   add_sym_1 ("sizeof", GFC_ISYM_SIZEOF, CLASS_INQUIRY, ACTUAL_NO,
             BT_INTEGER, ii, GFC_STD_GNU,
             gfc_check_sizeof, gfc_simplify_sizeof, NULL,
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 595ba97aa8ca..b33ba5730f24 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -932,7 +932,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t 
* post, gfc_ss * ss,
   gfc_loopinfo *loop;
   gfc_ss *s;
   gfc_array_info *info;
-  tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS], 
stride[GFC_MAX_DIMENSIONS];
+  tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS], 
sm[GFC_MAX_DIMENSIONS];
   tree type;
   tree desc;
   tree tmp;
@@ -964,6 +964,10 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
   if (class_expr == NULL_TREE && GFC_CLASS_TYPE_P (eltype))
     class_expr = get_class_info_from_ss (pre, ss, &eltype, &fcn_ss);
 
+  bool array_access = class_expr == NULL_TREE
+                     && eltype != NULL_TREE
+                     && !GFC_CLASS_TYPE_P (eltype);
+
   /* If the dynamic type is not available, use the declared type.  */
   if (eltype && GFC_CLASS_TYPE_P (eltype))
     eltype = gfc_get_element_type (TREE_TYPE (TYPE_FIELDS (eltype)));
@@ -1144,7 +1148,8 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
     }
 
   info->descriptor = desc;
-  size = gfc_index_one_node;
+  info->array_access = array_access;
+  size = elemsize;
 
   /*
      Fill in the bounds and stride.  This is a packed array, so:
@@ -1188,7 +1193,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
     {
       for (n = 0; n < total_dim; n++)
        {
-         stride[n] = size;
+         sm[n] = size;
 
          tree extent = to[n];
          if (!shift_bounds && !integer_zerop (from[n]))
@@ -1241,7 +1246,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
                                                    dealloc);
 
   gfc_set_temporary_descriptor (pre, desc, class_expr, elemsize, data_ptr,
-                               from, to, stride, total_dim, !bounds_known,
+                               from, to, sm, total_dim, !bounds_known,
                                rank_changer, shift_bounds);
 
   while (ss->parent)
@@ -2175,6 +2180,35 @@ gfc_build_constant_array_constructor (gfc_expr * expr, 
tree type)
 }
 
 
+static bool
+array_access_safe_p (gfc_expr *expr)
+{
+  if (expr->ts.type == BT_CLASS)
+    return false;
+
+  if (gfc_is_simply_contiguous (expr, false, true))
+    return true;
+
+  symbol_attribute attr = gfc_expr_attr (expr);
+  if (attr.pointer)
+    return false;
+
+  if (expr->expr_type == EXPR_VARIABLE
+      && attr.dummy)
+    {
+      gfc_symbol *sym = expr->symtree->n.sym;
+
+      gfc_array_spec *as = sym->as;
+      if (as
+         && !(as->type == AS_EXPLICIT
+              || as->type == AS_ASSUMED_SIZE))
+       return false;
+    }
+
+  return true;
+}
+
+
 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
    This mostly initializes the scalarizer state info structure with the
    appropriate values to directly use the array created by the function
@@ -2192,6 +2226,7 @@ trans_constant_array_constructor (gfc_ss * ss, tree type)
   info = &ss->info->data.array;
 
   info->descriptor = tmp;
+  info->array_access = array_access_safe_p (ss->info->expr);
   info->data = gfc_build_addr_expr (NULL_TREE, tmp);
   info->offset = gfc_index_zero_node;
 
@@ -2793,9 +2828,11 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, 
bool subscript,
                      end = gfc_evaluate_now (end, &outer_loop->pre);
                      info->end[dim] = end;
 
-                     tree stride = gfc_conv_descriptor_stride_get (tmp, 
tree_dim);
-                     stride = gfc_evaluate_now (stride, &outer_loop->pre);
-                     info->stride[dim] = stride;
+                     info->stride[dim] = gfc_index_one_node;
+
+                     tree spacing = gfc_conv_descriptor_sm_get (tmp, tree_dim);
+                     spacing = gfc_evaluate_now (spacing, &outer_loop->pre);
+                     info->spacing[dim] = spacing;
                    }
              }
            gfc_add_block_to_block (&outer_loop->post, &se.post);
@@ -2916,6 +2953,7 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, 
int base)
       else
        info->descriptor = gfc_evaluate_now (se.expr, block);
     }
+  info->array_access = array_access_safe_p (ss_info->expr);
   ss_info->string_length = se.string_length;
   ss_info->class_container = se.class_container;
 
@@ -2936,20 +2974,21 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * 
ss, int base)
                                                TYPE_NAME (arraytype)));
        }
       /* Also the data pointer.  */
-      tmp = gfc_conv_array_data (se.expr);
+      tree data = gfc_conv_array_data (se.expr);
       /* If this is a variable or address or a class array, use it directly.
          Otherwise we must evaluate it now to avoid breaking dependency
         analysis by pulling the expressions for elemental array indices
         inside the loop.  */
-      if (!(DECL_P (tmp)
-           || (TREE_CODE (tmp) == ADDR_EXPR
-               && DECL_P (TREE_OPERAND (tmp, 0)))
+      if (!(DECL_P (data)
+           || (TREE_CODE (data) == ADDR_EXPR
+               && DECL_P (TREE_OPERAND (data, 0)))
            || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
                && TREE_CODE (se.expr) == COMPONENT_REF
                && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (se.expr, 0)))))
          && !ss->is_alloc_lhs)
-       tmp = gfc_evaluate_now (tmp, block);
-      info->data = tmp;
+       data = gfc_evaluate_now (data, block);
+      info->data = data;
+      info->saved_data = data;
 
       tmp = gfc_conv_array_offset (se.expr);
       if (!ss->is_alloc_lhs)
@@ -3037,7 +3076,7 @@ gfc_conv_array_offset (tree descriptor)
 /* Get an expression for the array stride.  */
 
 tree
-gfc_conv_array_stride (tree descriptor, int dim)
+gfc_conv_array_sm (tree descriptor, int dim)
 {
   tree tmp;
   tree type;
@@ -3045,16 +3084,16 @@ gfc_conv_array_stride (tree descriptor, int dim)
   type = TREE_TYPE (descriptor);
 
   /* For descriptorless arrays use the array size.  */
-  tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
+  tmp = GFC_TYPE_ARRAY_SM (type, dim);
   if (tmp != NULL_TREE)
     return tmp;
 
-  tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
+  tmp = gfc_conv_descriptor_sm_get (descriptor, gfc_rank_cst[dim]);
   return tmp;
 }
 
 
-/* Like gfc_conv_array_stride, but for the lower bound.  */
+/* Like gfc_conv_array_sm, but for the lower bound.  */
 
 tree
 gfc_conv_array_lbound (tree descriptor, int dim)
@@ -3073,7 +3112,7 @@ gfc_conv_array_lbound (tree descriptor, int dim)
 }
 
 
-/* Like gfc_conv_array_stride, but for the upper bound.  */
+/* Like gfc_conv_array_sm, but for the upper bound.  */
 
 tree
 gfc_conv_array_ubound (tree descriptor, int dim)
@@ -3097,6 +3136,16 @@ gfc_conv_array_ubound (tree descriptor, int dim)
 }
 
 
+tree
+gfc_conv_array_extent (tree descriptor, int dim)
+{
+  tree lbound = gfc_conv_array_lbound (descriptor, dim);
+  tree ubound = gfc_conv_array_ubound (descriptor, dim);
+
+  return gfc_conv_array_extent_dim (lbound, ubound, nullptr);
+}
+
+
 /* Generate abridged name of a part-ref for use in bounds-check message.
    Cases:
    (1) for an ordinary array variable x return "x"
@@ -3299,122 +3348,6 @@ array_bound_check_elemental (gfc_se * se, gfc_ss * ss, 
gfc_expr * expr)
 }
 
 
-/* Return the offset for an index.  Performs bound checking for elemental
-   dimensions.  Single element references are processed separately.
-   DIM is the array dimension, I is the loop dimension.  */
-
-static tree
-conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
-                        gfc_array_ref * ar, tree stride)
-{
-  gfc_array_info *info;
-  tree index;
-  tree desc;
-  tree data;
-
-  info = &ss->info->data.array;
-
-  /* Get the index into the array for this dimension.  */
-  if (ar)
-    {
-      gcc_assert (ar->type != AR_ELEMENT);
-      switch (ar->dimen_type[dim])
-       {
-       case DIMEN_THIS_IMAGE:
-         gcc_unreachable ();
-         break;
-       case DIMEN_ELEMENT:
-         /* Elemental dimension.  */
-         gcc_assert (info->subscript[dim]
-                     && info->subscript[dim]->info->type == GFC_SS_SCALAR);
-         /* We've already translated this value outside the loop.  */
-         index = info->subscript[dim]->info->data.scalar.value;
-
-         index = trans_array_bound_check (se, ss, index, dim, &ar->where,
-                                          ar->as->type != AS_ASSUMED_SIZE
-                                          || dim < ar->dimen - 1);
-         break;
-
-       case DIMEN_VECTOR:
-         gcc_assert (info && se->loop);
-         gcc_assert (info->subscript[dim]
-                     && info->subscript[dim]->info->type == GFC_SS_VECTOR);
-         desc = info->subscript[dim]->info->data.array.descriptor;
-
-         /* Get a zero-based index into the vector.  */
-         index = fold_build2_loc (input_location, MINUS_EXPR,
-                                  gfc_array_index_type,
-                                  se->loop->loopvar[i], se->loop->from[i]);
-
-         /* Multiply the index by the stride.  */
-         index = fold_build2_loc (input_location, MULT_EXPR,
-                                  gfc_array_index_type,
-                                  index, gfc_conv_array_stride (desc, 0));
-
-         /* Read the vector to get an index into info->descriptor.  */
-         data = build_fold_indirect_ref_loc (input_location,
-                                         gfc_conv_array_data (desc));
-         index = gfc_build_array_ref (data, index, NULL);
-         index = gfc_evaluate_now (index, &se->pre);
-         index = fold_convert (gfc_array_index_type, index);
-
-         /* Do any bounds checking on the final info->descriptor index.  */
-         index = trans_array_bound_check (se, ss, index, dim, &ar->where,
-                                          ar->as->type != AS_ASSUMED_SIZE
-                                          || dim < ar->dimen - 1);
-         break;
-
-       case DIMEN_RANGE:
-         /* Scalarized dimension.  */
-         gcc_assert (info && se->loop);
-
-         /* Multiply the loop variable by the stride and delta.  */
-         index = se->loop->loopvar[i];
-         if (!integer_onep (info->stride[dim]))
-           index = fold_build2_loc (input_location, MULT_EXPR,
-                                    gfc_array_index_type, index,
-                                    info->stride[dim]);
-         if (!integer_zerop (info->delta[dim]))
-           index = fold_build2_loc (input_location, PLUS_EXPR,
-                                    gfc_array_index_type, index,
-                                    info->delta[dim]);
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-  else
-    {
-      /* Temporary array or derived type component.  */
-      gcc_assert (se->loop);
-      index = se->loop->loopvar[se->loop->order[i]];
-
-      /* Pointer functions can have stride[0] different from unity.
-        Use the stride returned by the function call and stored in
-        the descriptor for the temporary.  */
-      if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
-         && se->ss->info->expr
-         && se->ss->info->expr->symtree
-         && se->ss->info->expr->symtree->n.sym->result
-         && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
-       stride = gfc_conv_descriptor_stride_get (info->descriptor,
-                                                gfc_rank_cst[dim]);
-
-      if (info->delta[dim] && !integer_zerop (info->delta[dim]))
-       index = fold_build2_loc (input_location, PLUS_EXPR,
-                                gfc_array_index_type, index, info->delta[dim]);
-    }
-
-  /* Multiply by the stride.  */
-  if (stride != NULL && !integer_onep (stride))
-    index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                            index, stride);
-
-  return index;
-}
-
-
 /* Build a scalarized array reference using the vptr 'size'.  */
 
 static bool
@@ -3532,6 +3465,155 @@ non_negative_strides_array_p (tree expr)
 }
 
 
+static tree
+build_array_ref (tree desc, tree offset, tree decl, tree vptr)
+{
+  tree tmp;
+  tree type;
+  tree cdesc;
+
+  /* For class arrays the class declaration is stored in the saved
+     descriptor.  */
+  if (INDIRECT_REF_P (desc)
+      && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
+      && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
+    cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
+                                 TREE_OPERAND (desc, 0)));
+  else
+    cdesc = desc;
+
+  /* Class container types do not always have the GFC_CLASS_TYPE_P
+     but the canonical type does.  */
+  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
+      && TREE_CODE (cdesc) == COMPONENT_REF)
+    {
+      type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
+      if (TYPE_CANONICAL (type)
+         && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
+       vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
+    }
+
+  tmp = gfc_conv_array_data (desc);
+  tmp = build_fold_indirect_ref_loc (input_location, tmp);
+  tmp = gfc_build_array_ref (tmp, offset, decl,
+                            non_negative_strides_array_p (desc),
+                            vptr);
+  return tmp;
+}
+
+
+/* Return the offset for an index.  Performs bound checking for elemental
+   dimensions.  Single element references are processed separately.
+   DIM is the array dimension, I is the loop dimension.  */
+
+static tree
+conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
+                        gfc_array_ref * ar, tree spacing)
+{
+  gfc_array_info *info;
+  tree index;
+  tree data;
+  tree tmp;
+
+  info = &ss->info->data.array;
+
+  /* Get the index into the array for this dimension.  */
+  if (ar)
+    {
+      gcc_assert (ar->type != AR_ELEMENT);
+      switch (ar->dimen_type[dim])
+       {
+       case DIMEN_THIS_IMAGE:
+         gcc_unreachable ();
+         break;
+       case DIMEN_ELEMENT:
+         /* Elemental dimension.  */
+         gcc_assert (info->subscript[dim]
+                     && info->subscript[dim]->info->type == GFC_SS_SCALAR);
+         /* We've already translated this value outside the loop.  */
+         index = info->subscript[dim]->info->data.scalar.value;
+
+         index = trans_array_bound_check (se, ss, index, dim, &ar->where,
+                                          ar->as->type != AS_ASSUMED_SIZE
+                                          || dim < ar->dimen - 1);
+         break;
+
+       case DIMEN_VECTOR:
+         gcc_assert (info && se->loop);
+         gcc_assert (info->subscript[dim]
+                     && info->subscript[dim]->info->type == GFC_SS_VECTOR);
+
+         /* Get a zero-based index into the vector.  */
+         index = fold_build2_loc (input_location, MINUS_EXPR,
+                                  gfc_array_index_type,
+                                  se->loop->loopvar[i], se->loop->from[i]);
+
+         /* Multiply the index by the stride.  */
+         tmp = fold_build2_loc (input_location, MULT_EXPR,
+                                gfc_array_index_type, index,
+                                
info->subscript[dim]->info->data.array.spacing[0]);
+
+         data = info->subscript[dim]->info->data.array.data;
+         if (info->subscript[dim]->info->data.array.array_access)
+           index = fold_convert_loc (input_location, gfc_array_index_type, 
tmp);
+         else
+           {
+             data = fold_build2_loc (input_location, POINTER_PLUS_EXPR,
+                                     TREE_TYPE (data), data, tmp);
+             index = gfc_index_zero_node;
+           }
+         /* Read the vector to get an index into info->descriptor.  */
+         data = build_fold_indirect_ref_loc (input_location, data);
+         index = gfc_build_array_ref (data, index, NULL);
+         index = gfc_evaluate_now (index, &se->pre);
+         index = fold_convert (gfc_array_index_type, index);
+
+         /* Do any bounds checking on the final info->descriptor index.  */
+         index = trans_array_bound_check (se, ss, index, dim, &ar->where,
+                                          ar->as->type != AS_ASSUMED_SIZE
+                                          || dim < ar->dimen - 1);
+         break;
+
+       case DIMEN_RANGE:
+         /* Scalarized dimension.  */
+         gcc_assert (info && se->loop);
+
+         /* Multiply the loop variable by the stride and delta.  */
+         index = se->loop->loopvar[i];
+         if (!integer_onep (info->stride[dim]))
+           index = fold_build2_loc (input_location, MULT_EXPR,
+                                    gfc_array_index_type, index,
+                                    info->stride[dim]);
+         if (!integer_zerop (info->delta[dim]))
+           index = fold_build2_loc (input_location, PLUS_EXPR,
+                                    gfc_array_index_type, index,
+                                    info->delta[dim]);
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+  else
+    {
+      /* Temporary array or derived type component.  */
+      gcc_assert (se->loop);
+      index = se->loop->loopvar[se->loop->order[i]];
+
+      if (info->delta[dim] && !integer_zerop (info->delta[dim]))
+       index = fold_build2_loc (input_location, PLUS_EXPR,
+                                gfc_array_index_type, index, info->delta[dim]);
+    }
+
+  /* Multiply by the spacing.  */
+  if (spacing != NULL && !integer_onep (spacing))
+    return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                           index, spacing);
+  else
+    return index;
+}
+
+
 /* Build a scalarized reference to an array.  */
 
 static void
@@ -3540,7 +3622,6 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref 
* ar,
 {
   gfc_array_info *info;
   tree decl = NULL_TREE;
-  tree index;
   tree base;
   gfc_ss *ss;
   gfc_expr *expr;
@@ -3554,14 +3635,33 @@ gfc_conv_scalarized_array_ref (gfc_se * se, 
gfc_array_ref * ar,
   else
     n = 0;
 
-  index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
-  /* Add the offset for this dimension to the stored offset for all other
-     dimensions.  */
-  if (info->offset && !integer_zerop (info->offset))
-    index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
-                            index, info->offset);
+  tree tmp = conv_array_index_offset (se, ss, ss->dim[n], n, ar,
+                                     info->spacing[ss->dim[n]]);
+  tree index, data;
+  if (info->array_access)
+    {
+      index = tmp;
+
+      /* Add the offset for this dimension to the stored offset for all other
+        dimensions.  */
+      if (info->offset && !integer_zerop (info->offset))
+       index = fold_build2_loc (input_location, PLUS_EXPR, 
gfc_array_index_type,
+                                index, info->offset);
+
+      data = info->data;
+    }
+  else
+    {
+      tree offset = fold_convert (size_type_node, tmp);
+
+      data = info->data;
+      data = fold_build2_loc (input_location, POINTER_PLUS_EXPR, TREE_TYPE 
(data),
+                             data, offset);
+
+      index = gfc_index_zero_node;
+    }
 
-  base = build_fold_indirect_ref_loc (input_location, info->data);
+  base = build_fold_indirect_ref_loc (input_location, data);
 
   /* Use the vptr 'size' field to access the element of a class array.  */
   if (build_class_array_ref (se, base, index))
@@ -3621,43 +3721,6 @@ add_to_offset (tree *cst_offset, tree *offset, tree t)
 }
 
 
-static tree
-build_array_ref (tree desc, tree offset, tree decl, tree vptr)
-{
-  tree tmp;
-  tree type;
-  tree cdesc;
-
-  /* For class arrays the class declaration is stored in the saved
-     descriptor.  */
-  if (INDIRECT_REF_P (desc)
-      && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
-      && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
-    cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
-                                 TREE_OPERAND (desc, 0)));
-  else
-    cdesc = desc;
-
-  /* Class container types do not always have the GFC_CLASS_TYPE_P
-     but the canonical type does.  */
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
-      && TREE_CODE (cdesc) == COMPONENT_REF)
-    {
-      type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
-      if (TYPE_CANONICAL (type)
-         && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
-       vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
-    }
-
-  tmp = gfc_conv_array_data (desc);
-  tmp = build_fold_indirect_ref_loc (input_location, tmp);
-  tmp = gfc_build_array_ref (tmp, offset, decl,
-                            non_negative_strides_array_p (desc),
-                            vptr);
-  return tmp;
-}
-
-
 /* Build an array reference.  se->expr already holds the array descriptor.
    This should be either a variable, indirect variable reference or component
    reference.  For arrays which do not have a descriptor, se->expr will be
@@ -3671,7 +3734,6 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
   int n;
   tree offset, cst_offset;
   tree tmp;
-  tree stride;
   tree decl = NULL_TREE;
   gfc_se indexse;
   gfc_se tmpse;
@@ -3727,8 +3789,21 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
       && ar->as->type != AS_DEFERRED)
     decl = sym->backend_decl;
 
+  bool use_array_ref = array_access_safe_p (expr);
+  tree elem_len = NULL_TREE;
+  if (use_array_ref)
+    {
+      elem_len = gfc_get_array_span (decl, expr);
+      elem_len = fold_convert_loc (input_location, gfc_array_index_type,
+                                  elem_len);
+    }
+
   cst_offset = offset = gfc_index_zero_node;
-  add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (decl));
+  tmp = gfc_conv_array_offset (decl);
+  if (use_array_ref)
+    tmp = fold_build2_loc (input_location, EXACT_DIV_EXPR,
+                          gfc_array_index_type, tmp, elem_len);
+  add_to_offset (&cst_offset, &offset, tmp);
 
   /* Calculate the offsets from all the dimensions.  Make sure to associate
      the final offset so that we form a chain of loop invariant summands.  */
@@ -3795,10 +3870,14 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
            }
        }
 
-      /* Multiply the index by the stride.  */
-      stride = gfc_conv_array_stride (decl, n);
+      /* Multiply the index by the sm.  */
+      tree tmp = gfc_conv_array_sm (decl, n);
+      if (use_array_ref)
+       tmp = fold_build2_loc (input_location, EXACT_DIV_EXPR,
+                              gfc_array_index_type, tmp, elem_len);
+
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                            indexse.expr, stride);
+                            indexse.expr, tmp);
 
       /* And add it to the total.  */
       add_to_offset (&cst_offset, &offset, tmp);
@@ -3854,7 +3933,15 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
     }
 
   free (var_name);
-  se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
+  if (use_array_ref)
+    se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
+  else
+    {
+      offset = fold_convert_loc (input_location, size_type_node, offset);
+      tree ptr = fold_build2_loc (input_location, POINTER_PLUS_EXPR,
+                                 TREE_TYPE (se->expr), se->expr, offset);
+      se->expr = build_array_ref (ptr, gfc_array_index_type, decl, NULL_TREE);
+    }
 }
 
 
@@ -3867,21 +3954,34 @@ add_array_offset (stmtblock_t *pblock, gfc_loopinfo 
*loop, gfc_ss *ss,
 {
   gfc_se se;
   gfc_array_info *info;
-  tree stride, index;
 
   info = &ss->info->data.array;
 
   gfc_init_se (&se, NULL);
   se.loop = loop;
   se.expr = info->descriptor;
-  stride = gfc_conv_array_stride (info->descriptor, array_dim);
-  index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
+  tree tmp = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar,
+                                     info->spacing[array_dim]);
   gfc_add_block_to_block (pblock, &se.pre);
 
-  info->offset = fold_build2_loc (input_location, PLUS_EXPR,
-                                 gfc_array_index_type,
-                                 info->offset, index);
-  info->offset = gfc_evaluate_now (info->offset, pblock);
+  if (info->array_access)
+    {
+      tree index = fold_convert_loc (input_location, gfc_array_index_type, 
tmp);
+
+      info->offset = fold_build2_loc (input_location, PLUS_EXPR,
+                                     gfc_array_index_type,
+                                     info->offset, index);
+      info->offset = gfc_evaluate_now (info->offset, pblock);
+    }
+  else
+    {
+      tree offset = fold_convert_loc (input_location, size_type_node, tmp);
+
+      info->data = fold_build2_loc (input_location, POINTER_PLUS_EXPR,
+                                   TREE_TYPE (info->data),
+                                   info->data, offset);
+      info->data = gfc_evaluate_now (info->data, pblock);
+    }
 }
 
 
@@ -3892,7 +3992,6 @@ static void
 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
                         stmtblock_t * pblock)
 {
-  tree stride;
   gfc_ss_info *ss_info;
   gfc_array_info *info;
   gfc_ss_type ss_type;
@@ -3948,14 +4047,6 @@ gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, 
int flag,
        {
          gcc_assert (0 == ploop->order[0]);
 
-         stride = gfc_conv_array_stride (info->descriptor,
-                                         innermost_ss (ss)->dim[0]);
-
-         /* Calculate the stride of the innermost loop.  Hopefully this will
-            allow the backend optimizers to do their stuff more effectively.
-          */
-         info->stride0 = gfc_evaluate_now (stride, pblock);
-
          /* For the outermost loop calculate the offset due to any
             elemental dimensions.  It will have been initialized with the
             base offset of the array.  */
@@ -3989,7 +4080,10 @@ gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, 
int flag,
 
       /* Remember this offset for the second loop.  */
       if (dim == loop->temp_dim - 1 && loop->parent == NULL)
-        info->saved_offset = info->offset;
+       {
+         info->saved_offset = info->offset;
+         info->saved_data = info->data;
+       }
     }
 }
 
@@ -4219,6 +4313,7 @@ gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, 
stmtblock_t * body)
        continue;
 
       ss_info->data.array.offset = ss_info->data.array.saved_offset;
+      ss_info->data.array.data = ss_info->data.array.saved_data;
     }
 
   /* Restart all the inner loops we just finished.  */
@@ -4283,6 +4378,51 @@ evaluate_bound (stmtblock_t *block, tree *bounds, 
gfc_expr ** values,
 }
 
 
+static void
+conv_array_spacing (stmtblock_t * block, gfc_ss * ss, int dim)
+{
+  gfc_array_info *info;
+
+  gcc_assert (ss->info->type == GFC_SS_SECTION);
+
+  info = &ss->info->data.array;
+  tree desc = info->descriptor;
+
+  bool save_value = !ss->is_alloc_lhs;
+
+  tree value = NULL_TREE;
+
+  if (info->array_access)
+    {
+      tree type = TREE_TYPE (desc);
+      if (GFC_ARRAY_TYPE_P (type)
+         && GFC_TYPE_ARRAY_STRIDE (type, dim) != NULL_TREE)
+       value = GFC_TYPE_ARRAY_STRIDE (type, dim);
+      else if (dim == 0)
+       value = gfc_index_one_node;
+      else
+       {
+         if (info->spacing[dim - 1] == NULL_TREE)
+           conv_array_spacing (block, ss, dim - 1);
+
+         tree previous_spacing = info->spacing[dim - 1];
+         tree previous_extent = gfc_conv_array_extent (desc, dim - 1);
+         value = fold_build2_loc (input_location, MULT_EXPR,
+                                  gfc_array_index_type, previous_spacing,
+                                  previous_extent);
+       }
+    }
+  else
+    value = gfc_conv_descriptor_sm_get (info->descriptor,
+                                       gfc_rank_cst[dim]);
+
+  if (save_value)
+    info->spacing[dim] = gfc_evaluate_now (value, block);
+  else
+    info->spacing[dim] = value;
+}
+
+
 /* Calculate the lower bound of an array section.  */
 
 static void
@@ -4591,7 +4731,10 @@ done:
                                    !loop->array_parameter);
 
          for (n = 0; n < ss->dimen; n++)
-           gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
+           {
+             gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
+             conv_array_spacing (&outer_loop->pre, ss, ss->dim[n]);
+           }
          break;
 
        case GFC_SS_INTRINSIC:
@@ -4609,6 +4752,7 @@ done:
                gfc_add_block_to_block (&outer_loop->post, &se.post);
 
                info->descriptor = se.expr;
+               info->array_access = true;
 
                info->data = gfc_conv_array_data (info->descriptor);
                info->data = gfc_evaluate_now (info->data, &outer_loop->pre);
@@ -6187,7 +6331,7 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree 
* poffset,
 {
   gfc_array_spec *as;
   tree size;
-  tree stride;
+  tree sm;
   tree offset;
   tree ubound;
   tree lbound;
@@ -6200,9 +6344,12 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, 
tree * poffset,
 
   size = gfc_index_one_node;
   offset = gfc_index_zero_node;
-  stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
-  if (stride && VAR_P (stride))
-    gfc_add_modify (pblock, stride, gfc_index_one_node);
+  sm = GFC_TYPE_ARRAY_SM (type, 0);
+  if (sm && VAR_P (sm))
+    {
+      tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
+      gfc_add_modify (pblock, sm, tmp);
+    }
   for (dim = 0; dim < as->rank; dim++)
     {
       /* Evaluate non-constant array bound expressions.
@@ -6228,7 +6375,7 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree 
* poffset,
          gfc_add_block_to_block (pblock, &se.finalblock);
          gfc_add_modify (pblock, ubound, se.expr);
        }
-      /* The offset of this dimension.  offset = offset - lbound * stride.  */
+      /* The offset of this dimension.  offset = offset - lbound * sm.  */
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
                             lbound, size);
       offset = fold_build2_loc (input_location, MINUS_EXPR, 
gfc_array_index_type,
@@ -6236,13 +6383,13 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, 
tree * poffset,
 
       /* The size of this dimension, and the stride of the next.  */
       if (dim + 1 < as->rank)
-        stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
+        sm = GFC_TYPE_ARRAY_SM (type, dim + 1);
       else
-       stride = GFC_TYPE_ARRAY_SIZE (type);
+       sm = GFC_TYPE_ARRAY_SIZE (type);
 
-      if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
+      if (ubound != NULL_TREE && !(sm && INTEGER_CST_P (sm)))
        {
-         /* Calculate stride = size * (ubound + 1 - lbound).  */
+         /* Calculate sm = size * (ubound + 1 - lbound).  */
          tmp = fold_build2_loc (input_location, MINUS_EXPR,
                                 gfc_array_index_type,
                                 gfc_index_one_node, lbound);
@@ -6250,22 +6397,22 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, 
tree * poffset,
                                 gfc_array_index_type, ubound, tmp);
          tmp = fold_build2_loc (input_location, MULT_EXPR,
                                 gfc_array_index_type, size, tmp);
-         if (stride)
-           gfc_add_modify (pblock, stride, tmp);
+         if (sm)
+           gfc_add_modify (pblock, sm, tmp);
          else
-           stride = gfc_evaluate_now (tmp, pblock);
+           sm = gfc_evaluate_now (tmp, pblock);
 
          /* Make sure that negative size arrays are translated
             to being zero size.  */
          tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
-                                stride, gfc_index_zero_node);
+                                sm, gfc_index_zero_node);
          tmp = fold_build3_loc (input_location, COND_EXPR,
                                 gfc_array_index_type, tmp,
-                                stride, gfc_index_zero_node);
-         gfc_add_modify (pblock, stride, tmp);
+                                sm, gfc_index_zero_node);
+         gfc_add_modify (pblock, sm, tmp);
        }
 
-      size = stride;
+      size = sm;
     }
 
   gfc_trans_array_cobounds (type, pblock, sym);
@@ -6526,7 +6673,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
   tree dextent;
   tree dumdesc;
   tree tmp;
-  tree stride, stride2;
+  tree stride2, sm;
   tree stmt_packed;
   tree stmt_unpacked;
   tree partial;
@@ -6587,9 +6734,9 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
         anything as we still don't know the array stride.  */
       partial = gfc_create_var (logical_type_node, "partial");
       TREE_USED (partial) = 1;
-      tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
+      tmp = gfc_conv_descriptor_sm_get (dumdesc, gfc_rank_cst[0]);
       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
-                            gfc_index_one_node);
+                            gfc_conv_descriptor_span_get (dumdesc));
       gfc_add_modify (&init, partial, tmp);
     }
   else
@@ -6600,28 +6747,23 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
   if (no_repack)
     {
       /* Set the first stride.  */
-      stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
-      stride = gfc_evaluate_now (stride, &init);
-
-      tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
-                            stride, gfc_index_zero_node);
-      tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
-                            tmp, gfc_index_one_node, stride);
-      stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
-      gfc_add_modify (&init, stride, tmp);
+      sm = gfc_conv_descriptor_sm_get (dumdesc, gfc_rank_cst[0]);
+      tmp = gfc_evaluate_now (sm, &init);
+      sm = GFC_TYPE_ARRAY_SM (type, 0);
+      gfc_add_modify (&init, sm, tmp);
 
       /* Allow the user to disable array repacking.  */
       stmt_unpacked = NULL_TREE;
     }
   else
     {
-      gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
+      gcc_assert (GFC_TYPE_ARRAY_SM (type, 0) == GFC_TYPE_ARRAY_ELEM_LEN 
(type));
       /* A library call to repack the array if necessary.  */
       tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
       stmt_unpacked = build_call_expr_loc (input_location,
                                       gfor_fndecl_in_pack, 1, tmp);
 
-      stride = gfc_index_one_node;
+      sm = GFC_TYPE_ARRAY_ELEM_LEN (type);
 
       if (warn_array_temporaries)
        {
@@ -6672,6 +6814,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
          gfc_add_modify (&init, lbound, se.expr);
        }
 
+      tree extent = GFC_TYPE_ARRAY_EXTENT (type, n);
       ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
       /* Set the desired upper bound.  */
       if (as->upper[n])
@@ -6695,11 +6838,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
              locus where;
 
              gfc_locus_from_location (&where, loc);
-             temp = fold_build2_loc (input_location, MINUS_EXPR,
-                                     gfc_array_index_type, ubound, lbound);
-             temp = fold_build2_loc (input_location, PLUS_EXPR,
-                                     gfc_array_index_type,
-                                     gfc_index_one_node, temp);
+             temp = extent;
              stride2 = dextent;
              tmp = fold_build2_loc (input_location, NE_EXPR,
                                     gfc_array_index_type, temp, stride2);
@@ -6724,66 +6863,42 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree 
tmpdesc,
                                 gfc_array_index_type, tmp, lbound);
          gfc_add_modify (&init, ubound, tmp);
        }
-      /* The offset of this dimension.  offset = offset - lbound * stride.  */
+      /* The offset of this dimension.  offset = offset - lbound * sm.  */
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                            lbound, stride);
+                            lbound, sm);
       offset = fold_build2_loc (input_location, MINUS_EXPR,
                                gfc_array_index_type, offset, tmp);
 
-      /* The size of this dimension, and the stride of the next.  */
+      /* The size of this dimension, and the sm of the next.  */
       if (n + 1 < as->rank)
        {
-         stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
+         sm = GFC_TYPE_ARRAY_SM (type, n + 1);
 
          if (no_repack || partial != NULL_TREE)
            stmt_unpacked =
-             gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
+             gfc_conv_descriptor_sm_get (dumdesc, gfc_rank_cst[n+1]);
 
-         /* Figure out the stride if not a known constant.  */
-         if (!INTEGER_CST_P (stride))
+         /* Figure out the sm if not a known constant.  */
+         if (!INTEGER_CST_P (sm))
            {
              if (no_repack)
                stmt_packed = NULL_TREE;
              else
                {
-                 /* Calculate stride = size * (ubound + 1 - lbound).  */
-                 tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                                        gfc_array_index_type,
-                                        gfc_index_one_node, lbound);
-                 tmp = fold_build2_loc (input_location, PLUS_EXPR,
-                                        gfc_array_index_type, ubound, tmp);
+                 /* Calculate sm = size * (ubound + 1 - lbound).  */
                  size = fold_build2_loc (input_location, MULT_EXPR,
-                                         gfc_array_index_type, size, tmp);
+                                         gfc_array_index_type, size, extent);
                  stmt_packed = size;
                }
 
-             /* Assign the stride.  */
+             /* Assign the sm.  */
              if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
                tmp = fold_build3_loc (input_location, COND_EXPR,
                                       gfc_array_index_type, partial,
                                       stmt_unpacked, stmt_packed);
              else
                tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
-             gfc_add_modify (&init, stride, tmp);
-           }
-       }
-      else
-       {
-         stride = GFC_TYPE_ARRAY_SIZE (type);
-
-         if (stride && !INTEGER_CST_P (stride))
-           {
-             /* Calculate size = stride * (ubound + 1 - lbound).  */
-             tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                                    gfc_array_index_type,
-                                    gfc_index_one_node, lbound);
-             tmp = fold_build2_loc (input_location, PLUS_EXPR,
-                                    gfc_array_index_type,
-                                    ubound, tmp);
-             tmp = fold_build2_loc (input_location, MULT_EXPR,
-                                    gfc_array_index_type,
-                                    GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
-             gfc_add_modify (&init, stride, tmp);
+             gfc_add_modify (&init, sm, tmp);
            }
        }
     }
@@ -8443,15 +8558,26 @@ gfc_full_array_size (stmtblock_t *block, tree decl, int 
rank)
   tree nelems;
   tree tmp;
   if (rank < 0)
-    idx = gfc_conv_descriptor_rank_get (decl);
+    {
+      idx = gfc_conv_descriptor_rank_get (decl);
+      tmp = gfc_conv_descriptor_extent_get (decl, idx);
+      tmp = gfc_evaluate_now (tmp, block);
+
+      nelems = gfc_conv_descriptor_stride_get (decl, idx);
+      tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                            nelems, tmp);
+    }
   else
-    idx = gfc_rank_cst[rank - 1];
-  tmp = gfc_conv_descriptor_extent_get (decl, idx);
-  tmp = gfc_evaluate_now (tmp, block);
+    {
+      tmp = gfc_index_one_node;
+      for (int i = 0; i < rank; i++)
+       {
+         tree extent = gfc_conv_descriptor_extent_get (decl, gfc_rank_cst[i]);
+         tmp = fold_build2_loc (input_location, MULT_EXPR,
+                                gfc_array_index_type, tmp, extent);
 
-  nelems = gfc_conv_descriptor_stride_get (decl, idx);
-  tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                        nelems, tmp);
+       }
+    }
   return gfc_evaluate_now (tmp, block);
 }
 
@@ -10189,8 +10315,8 @@ update_reallocated_descriptor (stmtblock_t *block, 
gfc_loopinfo *loop)
                        gfc_conv_descriptor_lbound_get (desc, tree_dim));
          UPDATE_VALUE (info->end[dim],
                        gfc_conv_descriptor_ubound_get (desc, tree_dim));
-         UPDATE_VALUE (info->stride[dim],
-                       gfc_conv_descriptor_stride_get (desc, tree_dim));
+         UPDATE_VALUE (info->spacing[dim],
+                       gfc_conv_descriptor_sm_get (desc, tree_dim));
          info->delta[dim] = gfc_evaluate_now (info->delta[dim], block);
        }
 
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 3baf579300bb..709166f07551 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -161,9 +161,10 @@ void gfc_conv_array_parameter (gfc_se *, gfc_expr *, bool, 
const gfc_symbol *,
 tree gfc_conv_array_data (tree);
 tree gfc_conv_array_offset (tree);
 /* Return either an INT_CST or an expression for that part of the descriptor.  
*/
-tree gfc_conv_array_stride (tree, int);
+tree gfc_conv_array_sm (tree, int);
 tree gfc_conv_array_lbound (tree, int);
 tree gfc_conv_array_ubound (tree, int);
+tree gfc_conv_array_extent (tree, int);
 
 /* Set (co)bounds of an array.  */
 tree gfc_trans_array_bounds (tree, gfc_symbol *, tree *, stmtblock_t *);
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index d88ad3655c19..1e92b8c63925 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -1128,10 +1128,10 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
          suppress_warning (GFC_TYPE_ARRAY_UBOUND (type, dim));
        }
 
-      if (GFC_TYPE_ARRAY_STRIDE (type, dim) == NULL_TREE)
+      if (GFC_TYPE_ARRAY_SM (type, dim) == NULL_TREE)
        {
-         GFC_TYPE_ARRAY_STRIDE (type, dim) = create_index_var ("stride", nest);
-         suppress_warning (GFC_TYPE_ARRAY_STRIDE (type, dim));
+         GFC_TYPE_ARRAY_SM (type, dim) = create_index_var ("sm", nest);
+         suppress_warning (GFC_TYPE_ARRAY_SM (type, dim));
        }
     }
   for (dim = GFC_TYPE_ARRAY_RANK (type);
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index 7e709609435c..e5c1eb5b3835 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -168,7 +168,7 @@ gfc_get_cfi_dim_sm (tree desc, tree idx)
 #define DIMENSION_FIELD 4
 #define CAF_TOKEN_FIELD 5
 
-#define STRIDE_SUBFIELD 0
+#define SM_SUBFIELD 0
 #define LBOUND_SUBFIELD 1
 #define UBOUND_SUBFIELD 2
 
@@ -573,15 +573,15 @@ get_subfield (tree desc, tree dim, unsigned field_idx)
 }
 
 tree
-get_stride (tree desc, tree dim)
+get_sm (tree desc, tree dim)
 {
-  tree field = get_subfield (desc, dim, STRIDE_SUBFIELD);
+  tree field = get_subfield (desc, dim, SM_SUBFIELD);
   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
   return field;
 }
 
 tree
-conv_stride_get (tree desc, tree dim)
+conv_sm_get (tree desc, tree dim)
 {
   tree type = TREE_TYPE (desc);
   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
@@ -592,20 +592,40 @@ conv_stride_get (tree desc, tree dim)
          || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
          || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT
          || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
-    return gfc_index_one_node;
+    return conv_span_get (desc);
 
-  return non_lvalue_loc (input_location, get_stride (desc, dim));
+  return non_lvalue_loc (input_location, get_sm (desc, dim));
 }
 
 void
-conv_stride_set (stmtblock_t *block, tree desc, tree dim, tree value)
+conv_sm_set (stmtblock_t *block, tree desc, tree dim, tree value)
 {
   location_t loc = input_location;
-  tree t = get_stride (desc, dim);
+  tree t = get_sm (desc, dim);
   gfc_add_modify_loc (loc, block, t,
                      fold_convert_loc (loc, TREE_TYPE (t), value));
 }
 
+tree
+conv_stride_get (tree desc, tree dim)
+{
+  tree type = TREE_TYPE (desc);
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  if (integer_zerop (dim)
+      && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
+    return gfc_index_one_node;
+
+  tree sm = conv_sm_get (desc, dim);
+  tree span = conv_span_get (desc);
+  return fold_build2_loc (input_location, EXACT_DIV_EXPR, gfc_array_index_type,
+                         sm, span);
+}
+
 tree
 get_lbound (tree desc, tree dim)
 {
@@ -844,16 +864,16 @@ gfc_conv_descriptor_token_set (stmtblock_t *block, tree 
desc, tree value)
 }
 
 tree
-gfc_conv_descriptor_stride_get (tree desc, tree dim)
+gfc_conv_descriptor_sm_get (tree desc, tree dim)
 {
-  return gfc_descriptor::conv_stride_get (desc, dim);
+  return gfc_descriptor::conv_sm_get (desc, dim);
 }
 
 void
-gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
+gfc_conv_descriptor_sm_set (stmtblock_t *block, tree desc,
                                tree dim, tree value)
 {
-  gfc_descriptor::conv_stride_set (block, desc, dim, value);
+  gfc_descriptor::conv_sm_set (block, desc, dim, value);
 }
 
 tree
@@ -929,13 +949,9 @@ gfc_conv_descriptor_extent_get (tree desc, tree dim)
 
 
 tree
-gfc_conv_descriptor_sm_get (tree desc, tree dim)
+gfc_conv_descriptor_stride_get (tree desc, tree dim)
 {
-  tree stride = gfc_conv_descriptor_stride_get (desc, dim);
-  tree span = gfc_conv_descriptor_span_get (desc);
-
-  return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                         stride, span);
+  return gfc_descriptor::conv_stride_get (desc, dim);
 }
 
 
@@ -1942,8 +1958,8 @@ gfc_build_null_descriptor (tree type)
 
 static void
 set_bounds_update_offset (stmtblock_t *block, tree desc, int dim,
-                         tree lbound, tree ubound, tree stride, tree 
lbound_diff,
-                         tree *offset, tree *next_stride, bool 
stride_unchanged)
+                         tree lbound, tree ubound, tree sm, tree lbound_diff,
+                         tree *offset, tree *next_sm, bool sm_unchanged)
 {
   /* Stabilize values in case the expressions depend on the existing bounds.  
*/
   lbound = fold_convert (gfc_array_index_type, lbound);
@@ -1952,8 +1968,8 @@ set_bounds_update_offset (stmtblock_t *block, tree desc, 
int dim,
   ubound = fold_convert (gfc_array_index_type, ubound);
   ubound = gfc_evaluate_now (ubound, block);
 
-  stride = fold_convert (gfc_array_index_type, stride);
-  stride = gfc_evaluate_now (stride, block);
+  sm = fold_convert (gfc_array_index_type, sm);
+  sm = gfc_evaluate_now (sm, block);
 
   lbound_diff = fold_convert (gfc_array_index_type, lbound_diff);
   lbound_diff = gfc_evaluate_now (lbound_diff, block);
@@ -1962,40 +1978,40 @@ set_bounds_update_offset (stmtblock_t *block, tree 
desc, int dim,
                                  gfc_rank_cst[dim], lbound);
   gfc_conv_descriptor_ubound_set (block, desc,
                                  gfc_rank_cst[dim], ubound);
-  if (!stride_unchanged)
-    gfc_conv_descriptor_stride_set (block, desc,
-                                   gfc_rank_cst[dim], stride);
+  if (!sm_unchanged)
+    gfc_conv_descriptor_sm_set (block, desc,
+                                   gfc_rank_cst[dim], sm);
 
-  if (!offset && !next_stride)
+  if (!offset && !next_sm)
     return;
 
   /* Update offset.  */
   if (!integer_zerop (lbound_diff))
     {
       tree tmp = fold_build2_loc (input_location, MULT_EXPR,
-                                 gfc_array_index_type, lbound_diff, stride);
+                                 gfc_array_index_type, lbound_diff, sm);
       tmp = fold_build2_loc (input_location, MINUS_EXPR,
                             gfc_array_index_type, *offset, tmp);
       *offset = gfc_evaluate_now (tmp, block);
     }
 
-  if (!next_stride)
+  if (!next_sm)
     return;
 
-  /* Set stride for next dimension.  */
+  /* Set sm for next dimension.  */
   tree tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
-  *next_stride = fold_build2_loc (input_location, MULT_EXPR,
-                                 gfc_array_index_type, stride, tmp);
+  *next_sm = fold_build2_loc (input_location, MULT_EXPR,
+                             gfc_array_index_type, sm, tmp);
 }
 
 
 static void
 set_descriptor_dimension (stmtblock_t *block, tree desc, int dim,
-                         tree lbound, tree ubound, tree stride, tree *offset,
-                         tree *next_stride)
+                         tree lbound, tree ubound, tree sm, tree *offset,
+                         tree *next_sm)
 {
-  set_bounds_update_offset (block, desc, dim, lbound, ubound, stride, lbound,
-                           offset, next_stride, false);
+  set_bounds_update_offset (block, desc, dim, lbound, ubound, sm, lbound,
+                           offset, next_sm, false);
 }
 
 
@@ -2011,7 +2027,7 @@ conv_shift_descriptor_lbound (stmtblock_t* block, tree 
from_desc, tree to_desc,
 
   tree lbound = gfc_conv_descriptor_lbound_get (from_desc, gfc_rank_cst[dim]);
   tree ubound = gfc_conv_descriptor_ubound_get (from_desc, gfc_rank_cst[dim]);
-  tree stride = gfc_conv_descriptor_stride_get (from_desc, gfc_rank_cst[dim]);
+  tree sm = gfc_conv_descriptor_sm_get (from_desc, gfc_rank_cst[dim]);
 
   tree diff;
   if (zero_based)
@@ -2029,7 +2045,7 @@ conv_shift_descriptor_lbound (stmtblock_t* block, tree 
from_desc, tree to_desc,
   tree tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
                               ubound, diff);
 
-  set_bounds_update_offset (block, to_desc, dim, new_lbound, tmp1, stride, 
diff,
+  set_bounds_update_offset (block, to_desc, dim, new_lbound, tmp1, sm, diff,
                            offset, nullptr, from_desc == to_desc);
 }
 
@@ -2385,13 +2401,10 @@ gfc_conv_remap_descriptor (stmtblock_t *block, tree 
dest, tree src,
       tree offs = gfc_conv_descriptor_offset_get (src);
       for (int dim = 0; dim < src_rank; ++dim)
        {
-         tree stride = gfc_conv_descriptor_stride_get (src,
-                                           gfc_rank_cst[dim]);
-         tree lbound = gfc_conv_descriptor_lbound_get (src,
-                                           gfc_rank_cst[dim]);
+         tree sm = gfc_conv_descriptor_sm_get (src, gfc_rank_cst[dim]);
+         tree lbound = gfc_conv_descriptor_lbound_get (src, gfc_rank_cst[dim]);
          tmp = fold_build2_loc (input_location, MULT_EXPR,
-                                gfc_array_index_type, stride,
-                                lbound);
+                                gfc_array_index_type, sm, lbound);
          offs = fold_build2_loc (input_location, PLUS_EXPR,
                                  gfc_array_index_type, offs, tmp);
        }
@@ -2399,7 +2412,7 @@ gfc_conv_remap_descriptor (stmtblock_t *block, tree dest, 
tree src,
     }
   /* Set the bounds as declared for the LHS and calculate strides as
      well as another offset update accordingly.  */
-  tree stride = gfc_conv_descriptor_stride_get (src, gfc_rank_cst[0]);
+  tree sm = gfc_conv_descriptor_sm_get (src, gfc_rank_cst[0]);
   int last_dim = dest_rank - 1;
   for (int dim = 0; dim < dest_rank; ++dim)
     {
@@ -2418,8 +2431,8 @@ gfc_conv_remap_descriptor (stmtblock_t *block, tree dest, 
tree src,
       gfc_add_block_to_block (block, &upper_se.pre);
 
       set_descriptor_dimension (block, dest, dim, lower_se.expr, upper_se.expr,
-                               stride, &offset,
-                               dim < last_dim ? &stride : nullptr);
+                               sm, &offset,
+                               dim < last_dim ? &sm : nullptr);
     }
   gfc_conv_descriptor_offset_set (block, dest, offset);
 }
@@ -2485,12 +2498,12 @@ gfc_set_descriptor_with_shape (stmtblock_t *block, tree 
desc,
                               locus *where)
 {
   /* Set the span field.  */
-  tree tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
-  tmp = fold_convert (gfc_array_index_type, tmp);
-  gfc_conv_descriptor_span_set (block, desc, tmp);
+  tree elem_len = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
+  elem_len = fold_convert (gfc_array_index_type, elem_len);
+  gfc_conv_descriptor_span_set (block, desc, elem_len);
 
   /* Set data value, dtype, and offset.  */
-  tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
+  tree tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
   gfc_conv_descriptor_data_set (block, desc, fold_convert (tmp, ptr));
   gfc_conv_descriptor_dtype_set (block, desc, gfc_get_dtype (TREE_TYPE 
(desc)));
 
@@ -2511,9 +2524,9 @@ gfc_set_descriptor_with_shape (stmtblock_t *block, tree 
desc,
   gfc_copy_loopinfo_to_se (&shapese, &loop);
   shapese.ss = shape_ss;
 
-  tree stride = gfc_create_var (gfc_array_index_type, "stride");
+  tree sm = gfc_create_var (gfc_array_index_type, "sm");
   tree offset = gfc_create_var (gfc_array_index_type, "offset");
-  gfc_add_modify (block, stride, gfc_index_one_node);
+  gfc_add_modify (block, sm, elem_len);
   gfc_add_modify (block, offset, gfc_index_zero_node);
 
   /* Loop body.  */
@@ -2523,9 +2536,9 @@ gfc_set_descriptor_with_shape (stmtblock_t *block, tree 
desc,
   tree dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
                              loop.loopvar[0], loop.from[0]);
 
-  /* Set bounds and stride.  */
+  /* Set bounds and sm.  */
   gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
-  gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
+  gfc_conv_descriptor_sm_set (&body, desc, dim, sm);
 
   gfc_conv_expr (&shapese, shape);
   gfc_add_block_to_block (&body, &shapese.pre);
@@ -2535,11 +2548,11 @@ gfc_set_descriptor_with_shape (stmtblock_t *block, tree 
desc,
   /* Calculate offset.  */
   gfc_add_modify (&body, offset,
                  fold_build2_loc (input_location, PLUS_EXPR,
-                                  gfc_array_index_type, offset, stride));
-  /* Update stride.  */
-  gfc_add_modify (&body, stride,
+                                  gfc_array_index_type, offset, sm));
+  /* Update sm.  */
+  gfc_add_modify (&body, sm,
                  fold_build2_loc (input_location, MULT_EXPR,
-                                  gfc_array_index_type, stride,
+                                  gfc_array_index_type, sm,
                                   fold_convert (gfc_array_index_type,
                                                 shapese.expr)));
   /* Finish scalarization loop.  */
@@ -2594,17 +2607,20 @@ gfc_copy_sequence_descriptor (stmtblock_t &block, tree 
lhs_desc, tree rhs_desc,
       gfc_conv_descriptor_lbound_set (&block, arr, gfc_index_zero_node,
                                      gfc_index_zero_node);
       tree size = gfc_conv_descriptor_size (rhs_desc, rhs_rank);
+      tree span = gfc_conv_descriptor_span_get (rhs_desc);
+      size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                             size, span);
       gfc_conv_descriptor_ubound_set (&block, arr, gfc_index_zero_node, size);
-      gfc_conv_descriptor_stride_set (
+      gfc_conv_descriptor_sm_set (
        &block, arr, gfc_index_zero_node,
-       gfc_conv_descriptor_stride_get (rhs_desc, gfc_index_zero_node));
+       gfc_conv_descriptor_sm_get (rhs_desc, gfc_index_zero_node));
       for (int i = 1; i < lhs_rank; i++)
        {
          gfc_conv_descriptor_lbound_set (&block, arr, gfc_rank_cst[i],
                                          gfc_index_zero_node);
          gfc_conv_descriptor_ubound_set (&block, arr, gfc_rank_cst[i],
                                          gfc_index_zero_node);
-         gfc_conv_descriptor_stride_set (&block, arr, gfc_rank_cst[i], size);
+         gfc_conv_descriptor_sm_set (&block, arr, gfc_rank_cst[i], size);
        }
       gfc_conv_descriptor_dtype_set (&block, arr, 
                                     gfc_conv_descriptor_dtype_get (rhs_desc));
@@ -2814,33 +2830,29 @@ gfc_set_gfc_from_cfi (stmtblock_t *unconditional_block,
 
   if (contiguous_gfc)
     {
-      /* gfc->dim[i].stride
-          = idx == 0 ? 1 : gfc->dim[i-1].stride * cfi->dim[i-1].extent */
+      /* gfc->dim[i].sm
+          = idx == 0 ? cfi->elem_len : gfc->dim[i-1].stride * 
cfi->dim[i-1].extent */
       tree cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
                                   idx, build_zero_cst (TREE_TYPE (idx)));
       tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (idx),
                             idx, build_int_cst (TREE_TYPE (idx), 1));
       tree tmp2 = gfc_get_cfi_dim_extent (cfi, tmp);
-      tmp = gfc_conv_descriptor_stride_get (gfc, tmp);
+      tmp = gfc_conv_descriptor_sm_get (gfc, tmp);
       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp2),
                             tmp2, tmp);
       tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
-                       gfc_index_one_node, tmp);
+                       gfc_get_cfi_desc_elem_len (cfi), tmp);
     }
   else
     {
       /* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
       tmp = gfc_get_cfi_dim_sm (cfi, idx);
-      tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
-                            gfc_array_index_type, tmp,
-                            fold_convert (gfc_array_index_type,
-                                          gfc_get_cfi_desc_elem_len (cfi)));
     }
-  gfc_conv_descriptor_stride_set (&loop_body, gfc, idx, tmp);
+  gfc_conv_descriptor_sm_set (&loop_body, gfc, idx, tmp);
 
   /* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
   tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                        gfc_conv_descriptor_stride_get (gfc, idx),
+                        gfc_conv_descriptor_sm_get (gfc, idx),
                         gfc_conv_descriptor_lbound_get (gfc, idx));
   tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
                         gfc_conv_descriptor_offset_get (gfc), tmp);
@@ -2858,7 +2870,7 @@ void
 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
                                     tree *dtype_off, tree *span_off,
                                     tree *dim_off, tree *dim_size,
-                                    tree *stride_suboff, tree *lower_suboff,
+                                    tree *sm_suboff, tree *lower_suboff,
                                     tree *upper_suboff)
 {
   tree field;
@@ -2875,8 +2887,8 @@ gfc_get_descriptor_offsets_for_info (const_tree 
desc_type, tree *data_off,
   *dim_off = byte_position (field);
   type = TREE_TYPE (TREE_TYPE (field));
   *dim_size = TYPE_SIZE_UNIT (type);
-  field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
-  *stride_suboff = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), SM_SUBFIELD);
+  *sm_suboff = byte_position (field);
   field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
   *lower_suboff = byte_position (field);
   field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
@@ -2901,7 +2913,7 @@ gfc_set_temporary_descriptor (stmtblock_t *block, tree 
desc, tree class_src,
                              tree elemsize, tree data_ptr,
                              tree lbound[GFC_MAX_DIMENSIONS],
                              tree ubound[GFC_MAX_DIMENSIONS],
-                             tree stride[GFC_MAX_DIMENSIONS], int rank,
+                             tree sm[GFC_MAX_DIMENSIONS], int rank,
                              bool omit_bounds, bool rank_changer,
                              bool shift_bounds)
 {
@@ -2937,7 +2949,7 @@ gfc_set_temporary_descriptor (stmtblock_t *block, tree 
desc, tree class_src,
          /* Store the stride and bound components in the descriptor.  */
          tree this_lbound = shift_bounds ? gfc_index_zero_node : lbound[n];
          set_descriptor_dimension (block, desc, n, this_lbound, ubound[n],
-                                   stride[n], &offset, nullptr);
+                                   sm[n], &offset, nullptr);
        }
     }
 
@@ -3044,17 +3056,16 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
     dtype = gfc_get_dtype (TREE_TYPE (src), &rank);
   gfc_conv_descriptor_dtype_set (block, dest, dtype);
 
-  /* The 1st element in the section.  */
-  tree base = gfc_index_zero_node;
-  if (src_expr->ts.type == BT_CHARACTER && src_expr->rank == 0 && corank)
-    base = gfc_index_one_node;
-
   /* The offset from the 1st element in the section.  */
   tree offset = gfc_index_zero_node;
 
+  /* The 1st element in the section.  */
+  if (src_expr->ts.type == BT_CHARACTER && src_expr->rank == 0 && corank)
+    offset = gfc_conv_descriptor_elem_len_get (dest);
+
   for (int n = 0; n < ndim; n++)
     {
-      tree stride = gfc_conv_array_stride (src, n);
+      tree sm = gfc_conv_array_sm (src, n);
 
       /* Work out the 1st element in the section.  */
       tree start;
@@ -3069,16 +3080,16 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
        {
          /* Evaluate and remember the start of the section.  */
          start = info->start[n];
-         stride = gfc_evaluate_now (stride, block);
+         sm = gfc_evaluate_now (sm, block);
        }
 
       tmp = gfc_conv_array_lbound (src, n);
       tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
                             start, tmp);
       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
-                            tmp, stride);
-      base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
-                               base, tmp);
+                            tmp, sm);
+      offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
+                               offset, tmp);
 
       if (info->ref
          && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
@@ -3112,20 +3123,19 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
       gfc_conv_descriptor_ubound_set (block, dest,
                                      gfc_rank_cst[dim], to);
 
-      /* Multiply the stride by the section stride to get the
+      /* Multiply the sm by the section stride to get the
         total stride.  */
-      stride = fold_build2_loc (input_location, MULT_EXPR,
-                               gfc_array_index_type,
-                               stride, info->stride[n]);
+      sm = fold_build2_loc (input_location, MULT_EXPR,
+                           gfc_array_index_type,
+                           sm, info->stride[n]);
 
       tmp = fold_build2_loc (input_location, MULT_EXPR,
-                            TREE_TYPE (offset), stride, from);
+                            TREE_TYPE (offset), sm, from);
       offset = fold_build2_loc (input_location, MINUS_EXPR,
                               TREE_TYPE (offset), offset, tmp);
 
-      /* Store the new stride.  */
-      gfc_conv_descriptor_stride_set (block, dest,
-                                     gfc_rank_cst[dim], stride);
+      /* Store the new sm.  */
+      gfc_conv_descriptor_sm_set (block, dest, gfc_rank_cst[dim], sm);
     }
 
   for (int n = rank; n < rank + corank; n++)
@@ -3141,7 +3151,7 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
 
   if (data_needed)
     /* Point the data pointer at the 1st element in the section.  */
-    gfc_get_dataptr_offset (block, dest, src, base,
+    gfc_get_dataptr_offset (block, dest, src, gfc_index_zero_node,
                            subref, src_expr);
   else
     gfc_conv_descriptor_data_set (block, dest,
@@ -3210,6 +3220,7 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
   tree size;
   tree offset;
   tree stride;
+  tree sm;
   tree cond;
   gfc_expr *ubound;
   gfc_se se;
@@ -3265,6 +3276,8 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
     gfc_conv_descriptor_dtype_set (pblock, descriptor, gfc_get_dtype (type));
 
   tree empty_cond = logical_false_node;
+  sm = gfc_conv_descriptor_elem_len_get (descriptor);
+  sm = fold_convert_loc (input_location, gfc_array_index_type, sm);
 
   for (n = 0; n < rank; n++)
     {
@@ -3313,7 +3326,7 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
 
       /* Work out the offset for this component.  */
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                            se.expr, stride);
+                            se.expr, sm);
       offset = fold_build2_loc (input_location, MINUS_EXPR,
                                gfc_array_index_type, offset, tmp);
 
@@ -3352,9 +3365,9 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
                                      gfc_rank_cst[n], se.expr);
       conv_ubound = se.expr;
 
-      /* Store the stride.  */
-      gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
-                                     gfc_rank_cst[n], stride);
+      /* Store the sm.  */
+      gfc_conv_descriptor_sm_set (descriptor_block, descriptor,
+                                     gfc_rank_cst[n], sm);
 
       /* Calculate size and check whether extent is negative.  */
       size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound,
@@ -3372,7 +3385,7 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
                                           TYPE_MAX_VALUE 
(gfc_array_index_type)),
                                           size);
       cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
-                                           logical_type_node, tmp, stride),
+                                           logical_type_node, tmp, sm),
                           PRED_FORTRAN_OVERFLOW);
       tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, 
cond,
                             integer_one_node, integer_zero_node);
@@ -3390,6 +3403,10 @@ gfc_descr_init_count (tree descriptor, int rank, int 
corank, gfc_expr ** lower,
       stride = fold_build2_loc (input_location, MULT_EXPR,
                                gfc_array_index_type, stride, size);
       stride = gfc_evaluate_now (stride, pblock);
+
+      sm = fold_build2_loc (input_location, MULT_EXPR,
+                           gfc_array_index_type, sm, size);
+      sm = gfc_evaluate_now (sm, pblock);
     }
 
   for (n = rank; n < rank + corank; n++)
@@ -3483,9 +3500,9 @@ gfc_set_contiguous_array (stmtblock_t *block, tree desc, 
tree size,
   gfc_conv_descriptor_lbound_set (block, desc,
                                  gfc_index_zero_node,
                                  gfc_index_one_node);
-  gfc_conv_descriptor_stride_set (block, desc,
-                                 gfc_index_zero_node,
-                                 gfc_index_one_node);
+  gfc_conv_descriptor_sm_set (block, desc,
+                             gfc_index_zero_node,
+                             gfc_conv_descriptor_span_get (desc));
   gfc_conv_descriptor_ubound_set (block, desc,
                                  gfc_index_zero_node, size);
   gfc_conv_descriptor_data_set (block, desc, data_ptr);
@@ -3566,7 +3583,7 @@ gfc_copy_descriptor (stmtblock_t *block, tree dst, tree 
src, int rank)
     {
       dim = gfc_rank_cst[n];
       tmp = gfc_conv_descriptor_lbound_get (src, dim);
-      tmp2 = gfc_conv_descriptor_stride_get (src, dim);
+      tmp2 = gfc_conv_descriptor_sm_get (src, dim);
       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
                             tmp, tmp2);
       offset = fold_build2_loc (input_location, MINUS_EXPR,
@@ -3586,7 +3603,7 @@ get_std_lbound (gfc_expr *expr, tree desc, int dim, bool 
assumed_size)
 {
   tree lbound;
   tree ubound;
-  tree stride;
+  tree sm;
   tree cond, cond1, cond3, cond4;
   tree tmp;
   gfc_ref *ref;
@@ -3596,15 +3613,15 @@ get_std_lbound (gfc_expr *expr, tree desc, int dim, 
bool assumed_size)
       tmp = gfc_rank_cst[dim];
       lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
       ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
-      stride = gfc_conv_descriptor_stride_get (desc, tmp);
+      sm = gfc_conv_descriptor_sm_get (desc, tmp);
       cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
                               ubound, lbound);
       cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
-                              stride, gfc_index_zero_node);
+                              sm, gfc_index_zero_node);
       cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
                               logical_type_node, cond3, cond1);
       cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
-                              stride, gfc_index_zero_node);
+                              sm, gfc_index_zero_node);
       if (assumed_size)
        cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
                                tmp, build_int_cst (gfc_array_index_type,
@@ -3680,7 +3697,7 @@ gfc_set_descriptor_for_assign_realloc (stmtblock_t 
*block, gfc_loopinfo *loop,
      to the corresponding element of LBOUND(expr)."
      Reuse size1 to keep a dimension-by-dimension track of the
      stride of the new array.  */
-  tree size1 = gfc_index_one_node;
+  tree size1 = elemsize2;
   tree offset = gfc_index_zero_node;
 
   for (int n = 0; n < expr2->rank; n++)
@@ -3705,15 +3722,9 @@ gfc_set_descriptor_for_assign_realloc (stmtblock_t 
*block, gfc_loopinfo *loop,
          lbound = lbd;
        }
 
-      gfc_conv_descriptor_lbound_set (block, desc,
-                                     gfc_rank_cst[n],
-                                     lbound);
-      gfc_conv_descriptor_ubound_set (block, desc,
-                                     gfc_rank_cst[n],
-                                     ubound);
-      gfc_conv_descriptor_stride_set (block, desc,
-                                     gfc_rank_cst[n],
-                                     size1);
+      gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[n], lbound);
+      gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[n], ubound);
+      gfc_conv_descriptor_sm_set (block, desc, gfc_rank_cst[n], size1);
       lbound = gfc_conv_descriptor_lbound_get (desc,
                                               gfc_rank_cst[n]);
       tree tmp2 = fold_build2_loc (input_location, MULT_EXPR,
@@ -3811,7 +3822,9 @@ gfc_set_pdt_array_descriptor (stmtblock_t *block, tree 
desc,
      fields can then be filled from the values so obtained.  */
   gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
 
-  tree size = gfc_index_one_node;
+  gfc_conv_descriptor_dtype_set (block, desc,
+                                gfc_get_dtype (TREE_TYPE (desc)));
+  tree size = gfc_conv_descriptor_elem_len_get (desc);
   tree offset = gfc_index_zero_node;
   for (int i = 0; i < as->rank; i++)
     {
@@ -3830,17 +3843,11 @@ gfc_set_pdt_array_descriptor (stmtblock_t *block, tree 
desc,
       gfc_conv_expr_type (&tse, e, gfc_array_index_type);
       gfc_free_expr (e);
       tree upper = tse.expr;
-      gfc_conv_descriptor_ubound_set (block, desc,
-                                     gfc_rank_cst[i],
-                                     upper);
-      gfc_conv_descriptor_stride_set (block, desc,
-                                     gfc_rank_cst[i],
-                                     size);
+      gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[i], upper);
+      gfc_conv_descriptor_sm_set (block, desc, gfc_rank_cst[i], size);
       size = gfc_evaluate_now (size, block);
-      offset = fold_build2_loc (input_location,
-                               MINUS_EXPR,
-                               gfc_array_index_type,
-                               offset, size);
+      offset = fold_build2_loc (input_location, MINUS_EXPR,
+                               gfc_array_index_type, offset, size);
       offset = gfc_evaluate_now (offset, block);
       tree tmp = fold_build2_loc (input_location, MINUS_EXPR,
                                  gfc_array_index_type,
@@ -3852,8 +3859,6 @@ gfc_set_pdt_array_descriptor (stmtblock_t *block, tree 
desc,
                              gfc_array_index_type, size, tmp);
     }
   gfc_conv_descriptor_offset_set (block, desc, offset);
-  gfc_conv_descriptor_dtype_set (block, desc,
-                                gfc_get_dtype (TREE_TYPE (desc)));
   return size;
 }
 
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 78e5907fe44e..e49d447bb85e 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -4798,7 +4798,7 @@ gfc_set_interface_mapping_bounds (stmtblock_t * block, 
tree type, tree desc)
   for (n = 0; n < GFC_TYPE_ARRAY_RANK (type); n++)
     {
       dim = gfc_rank_cst[n];
-      GFC_TYPE_ARRAY_STRIDE (type, n) = gfc_conv_array_stride (desc, n);
+      GFC_TYPE_ARRAY_SM (type, n) = gfc_conv_array_sm (desc, n);
       if (GFC_TYPE_ARRAY_LBOUND (type, n) == NULL_TREE)
        {
          GFC_TYPE_ARRAY_LBOUND (type, n)
@@ -4820,7 +4820,7 @@ gfc_set_interface_mapping_bounds (stmtblock_t * block, 
tree type, tree desc)
        }
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
                             GFC_TYPE_ARRAY_LBOUND (type, n),
-                            GFC_TYPE_ARRAY_STRIDE (type, n));
+                            GFC_TYPE_ARRAY_SM (type, n));
       offset = fold_build2_loc (input_location, MINUS_EXPR,
                                gfc_array_index_type, offset, tmp);
     }
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index f226f1b5f038..7e0089161777 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -2309,7 +2309,7 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
 {
   gfc_ss *ss;
   gfc_se argse;
-  tree desc, tmp, stride, extent, cond;
+  tree desc, tmp, extent, cond;
   int i;
   tree fncall0;
   gfc_array_spec *as;
@@ -2347,19 +2347,19 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
       gfc_add_block_to_block (&se->post, &argse.post);
       desc = gfc_evaluate_now (argse.expr, &se->pre);
 
-      stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
+      tree sm = gfc_conv_descriptor_sm_get (desc, gfc_rank_cst[0]);
       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
-                             stride, build_int_cst (TREE_TYPE (stride), 1));
+                             sm, gfc_conv_descriptor_span_get (desc));
 
       for (i = 0; i < arg->rank - 1; i++)
        {
          extent = gfc_conv_descriptor_extent_get (desc, gfc_rank_cst[i]);
-         tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
+         tmp = gfc_conv_descriptor_sm_get (desc, gfc_rank_cst[i]);
          tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
                                 tmp, extent);
-         stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
+         sm = gfc_conv_descriptor_sm_get (desc, gfc_rank_cst[i+1]);
          tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
-                                stride, tmp);
+                                sm, tmp);
          cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
                                  boolean_type_node, cond, tmp);
        }
@@ -2738,34 +2738,6 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
 }
 
 
-static void
-conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
-{
-  gfc_actual_arglist *array_arg;
-  gfc_actual_arglist *dim_arg;
-  gfc_se argse;
-  tree desc, tmp;
-
-  array_arg = expr->value.function.actual;
-  dim_arg = array_arg->next;
-
-  gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
-
-  gfc_init_se (&argse, NULL);
-  gfc_conv_expr_descriptor (&argse, array_arg->expr);
-  gfc_add_block_to_block (&se->pre, &argse.pre);
-  gfc_add_block_to_block (&se->post, &argse.post);
-  desc = argse.expr;
-
-  gcc_assert (dim_arg->expr);
-  gfc_init_se (&argse, NULL);
-  gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
-  gfc_add_block_to_block (&se->pre, &argse.pre);
-  tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
-                        argse.expr, gfc_index_one_node);
-  se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
-}
-
 static void
 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
 {
@@ -9031,7 +9003,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
            }
          else
            tmp = gfc_rank_cst[arg1->expr->rank - 1];
-         tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
+         tmp = gfc_conv_descriptor_sm_get (arg1se.expr, tmp);
          if (arg2->expr->rank != 0)
            nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
                                                logical_type_node, tmp,
@@ -11294,10 +11266,6 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * 
expr)
       gfc_conv_intrinsic_spacing (se, expr);
       break;
 
-    case GFC_ISYM_STRIDE:
-      conv_intrinsic_stride (se, expr);
-      break;
-
     case GFC_ISYM_SUM:
       gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
       break;
diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc
index 4ca0ed7f91b9..99df15dcd86b 100644
--- a/gcc/fortran/trans-io.cc
+++ b/gcc/fortran/trans-io.cc
@@ -751,7 +751,7 @@ gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
 
   if (e->rank == 0)
     {
-      tree type, array, tmp;
+      tree type, array;
       gfc_symbol *sym;
       int rank;
 
@@ -765,40 +765,37 @@ gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
       array = sym->backend_decl;
       type = TREE_TYPE (array);
 
-      tree elts_count;
+      tree elts_count = NULL_TREE;
+      tree full_size = NULL_TREE;
       if (GFC_ARRAY_TYPE_P (type))
        elts_count = GFC_TYPE_ARRAY_SIZE (type);
       else
        {
          gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-         tree stride = gfc_conv_array_stride (array, rank);
-         tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                                gfc_array_index_type,
-                                gfc_conv_array_ubound (array, rank),
-                                gfc_conv_array_lbound (array, rank));
-         tmp = fold_build2_loc (input_location, PLUS_EXPR,
-                                gfc_array_index_type, tmp,
-                                gfc_index_one_node);
-         elts_count = fold_build2_loc (input_location, MULT_EXPR,
-                                       gfc_array_index_type, tmp, stride);
+         tree sm = gfc_conv_array_sm (array, rank);
+         tree tmp = gfc_conv_array_extent (array, rank);
+         full_size = fold_build2_loc (input_location, MULT_EXPR,
+                                      gfc_array_index_type, tmp, sm);
        }
-      gcc_assert (elts_count);
+      gcc_assert (elts_count || full_size);
 
       tree elt_size = TYPE_SIZE_UNIT (gfc_get_element_type (type));
       elt_size = fold_convert (gfc_array_index_type, elt_size);
 
-      tree size;
+      if (full_size == NULL_TREE)
+       full_size = fold_build2_loc (input_location, MULT_EXPR,
+                                    gfc_array_index_type, elts_count,
+                                    elt_size);
+
+      tree offset;
       if (TREE_CODE (se->expr) == ARRAY_REF)
        {
          tree index = TREE_OPERAND (se->expr, 1);
          index = fold_convert (gfc_array_index_type, index);
 
-         elts_count = fold_build2_loc (input_location, MINUS_EXPR,
-                                       gfc_array_index_type,
-                                       elts_count, index);
-
-         size = fold_build2_loc (input_location, MULT_EXPR,
-                                 gfc_array_index_type, elts_count, elt_size);
+         offset = fold_build2_loc (input_location, MULT_EXPR,
+                                   gfc_array_index_type, index,
+                                   elt_size);
        }
       else
        {
@@ -806,15 +803,13 @@ gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
          tree ptr = TREE_OPERAND (se->expr, 0);
 
          gcc_assert (TREE_CODE (ptr) == POINTER_PLUS_EXPR);
-         tree offset = fold_convert_loc (input_location, gfc_array_index_type,
-                                         TREE_OPERAND (ptr, 1));
-
-         size = fold_build2_loc (input_location, MULT_EXPR,
-                                 gfc_array_index_type, elts_count, elt_size);
-         size = fold_build2_loc (input_location, MINUS_EXPR,
-                                 gfc_array_index_type, size, offset);
+         offset = fold_convert_loc (input_location, gfc_array_index_type,
+                                    TREE_OPERAND (ptr, 1));
        }
-      gcc_assert (size);
+
+      gcc_assert (offset);
+      tree size = fold_build2_loc (input_location, MINUS_EXPR,
+                                  gfc_array_index_type, full_size, offset);
 
       se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
       se->string_length = fold_convert (gfc_charlen_type_node, size);
@@ -1823,7 +1818,7 @@ transfer_namelist_element (stmtblock_t * block, const 
char * var_name,
                             iocall[IOCALL_SET_NML_VAL_DIM], 5,
                             dt_parm_addr,
                             build_int_cst (gfc_int4_type_node, n_dim),
-                            gfc_conv_array_stride (decl, n_dim),
+                            gfc_conv_array_sm (decl, n_dim),
                             gfc_conv_array_lbound (decl, n_dim),
                             gfc_conv_array_ubound (decl, n_dim));
       gfc_add_expr_to_block (block, tmp);
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 4ac7ea0893c1..e6afb84c031d 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -1869,7 +1869,7 @@ gfc_omp_firstprivatize_type_sizes (struct 
gimplify_omp_ctx *ctx, tree type)
        {
          omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
          omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
-         omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
+         omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SM (type, r));
        }
       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index f3527694e800..72b7d715fe1b 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -1488,7 +1488,7 @@ gfc_get_element_type (tree type)
 
     struct descriptor_dimension
     {
-      index stride;
+      index sm;
       index lbound;
       index ubound;
     }
@@ -1661,9 +1661,9 @@ gfc_get_desc_dim_type (void)
   TYPE_NAME (type) = get_identifier ("descriptor_dimension");
   TYPE_PACKED (type) = 1;
 
-  /* Consists of the stride, lbound and ubound members.  */
+  /* Consists of the sm, lbound and ubound members.  */
   decl = gfc_add_field_to_struct_1 (type,
-                                   get_identifier ("stride"),
+                                   get_identifier ("sm"),
                                    gfc_array_index_type, &chain);
   suppress_warning (decl);
 
@@ -1855,11 +1855,15 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
   int known_offset;
   mpz_t offset;
   mpz_t stride;
+  mpz_t sm;
   mpz_t delta;
   gfc_expr *expr;
 
   mpz_init_set_ui (offset, 0);
   mpz_init_set_ui (stride, 1);
+  wide_int elem_len = wi::to_wide (TYPE_SIZE_UNIT (etype));
+  gcc_assert (wi::fits_shwi_p (elem_len));
+  mpz_init_set_ui (sm, elem_len.to_shwi ());
   mpz_init (delta);
 
   /* We don't use build_array_type because this does not include
@@ -1877,12 +1881,12 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
   known_offset = 1;
   for (n = 0; n < as->rank; n++)
     {
-      /* Fill in the stride and bound components of the type.  */
+      /* Fill in the sm and bound components of the type.  */
       if (known_stride)
-       tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
+       tmp = gfc_conv_mpz_to_tree (sm, gfc_index_integer_kind);
       else
         tmp = NULL_TREE;
-      GFC_TYPE_ARRAY_STRIDE (type, n) = tmp;
+      GFC_TYPE_ARRAY_SM (type, n) = tmp;
 
       expr = as->lower[n];
       if (expr && expr->expr_type == EXPR_CONSTANT)
@@ -1900,7 +1904,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
       if (known_stride)
        {
           /* Calculate the offset.  */
-          mpz_mul (delta, stride, as->lower[n]->value.integer);
+          mpz_mul (delta, sm, as->lower[n]->value.integer);
           mpz_sub (offset, offset, delta);
        }
       else
@@ -1926,6 +1930,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
                   as->lower[n]->value.integer);
           mpz_add_ui (delta, delta, 1);
           mpz_mul (stride, stride, delta);
+          mpz_mul (sm, sm, delta);
         }
 
       /* Only the first stride is known for partial packed arrays.  */
@@ -1968,6 +1973,9 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
   else
     GFC_TYPE_ARRAY_SIZE (type) = NULL_TREE;
 
+  if (packed != PACKED_NO)
+    GFC_TYPE_ARRAY_ELEM_LEN (type) = TYPE_SIZE_UNIT (etype);
+
   GFC_TYPE_ARRAY_RANK (type) = as->rank;
   GFC_TYPE_ARRAY_CORANK (type) = as->corank;
   GFC_TYPE_ARRAY_DTYPE (type) = NULL_TREE;
@@ -2047,6 +2055,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
 array_type_done:
   mpz_clear (offset);
   mpz_clear (stride);
+  mpz_clear (sm);
   mpz_clear (delta);
 
   return type;
@@ -2202,14 +2211,21 @@ gfc_get_array_type_bounds (tree etype, int dimen, int 
codimen, tree * lbound,
   GFC_TYPE_ARRAY_AKIND (fat_type) = akind;
 
   /* Build an array descriptor record type.  */
+  tree sm;
   if (packed != 0)
-    stride = gfc_index_one_node;
+    {
+      stride = gfc_index_one_node;
+      sm = TYPE_SIZE_UNIT (etype);
+    }
   else
-    stride = NULL_TREE;
+    {
+      stride = NULL_TREE;
+      sm = NULL_TREE;
+    }
   for (n = 0; n < dimen + codimen; n++)
     {
       if (n < dimen)
-       GFC_TYPE_ARRAY_STRIDE (fat_type, n) = stride;
+       GFC_TYPE_ARRAY_SM (fat_type, n) = sm;
 
       if (lbound)
        lower = lbound[n];
@@ -2241,18 +2257,19 @@ gfc_get_array_type_bounds (tree etype, int dimen, int 
codimen, tree * lbound,
 
       if (upper != NULL_TREE && lower != NULL_TREE && stride != NULL_TREE)
        {
-         tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                                gfc_array_index_type, upper, lower);
-         tmp = fold_build2_loc (input_location, PLUS_EXPR,
-                                gfc_array_index_type, tmp,
-                                gfc_index_one_node);
+         tmp = gfc_conv_array_extent_dim (lower, upper, nullptr);
          stride = fold_build2_loc (input_location, MULT_EXPR,
                                    gfc_array_index_type, tmp, stride);
+         sm = fold_build2_loc (input_location, MULT_EXPR,
+                               gfc_array_index_type, tmp, sm);
          /* Check the folding worked.  */
          gcc_assert (INTEGER_CST_P (stride));
        }
       else
-       stride = NULL_TREE;
+       {
+         stride = NULL_TREE;
+         sm = NULL_TREE;
+       }
     }
   GFC_TYPE_ARRAY_SIZE (fat_type) = stride;
 
@@ -3829,8 +3846,8 @@ gfc_get_array_descr_info (const_tree type, struct 
array_descr_info *info)
   int rank, dim;
   bool indirect = false;
   tree etype, ptype, t, base_decl;
-  tree data_off, span_off, dim_off, dtype_off, dim_size, elem_size;
-  tree lower_suboff, upper_suboff, stride_suboff;
+  tree data_off, span_off, dim_off, dtype_off, dim_size;
+  tree lower_suboff, upper_suboff, sm_suboff;
   tree dtype, field, rank_off;
 
   if (! GFC_DESCRIPTOR_TYPE_P (type))
@@ -3885,12 +3902,9 @@ gfc_get_array_descr_info (const_tree type, struct 
array_descr_info *info)
     base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
   gfc_get_descriptor_offsets_for_info (type, &data_off, &dtype_off, &span_off,
-                                      &dim_off, &dim_size, &stride_suboff,
+                                      &dim_off, &dim_size, &sm_suboff,
                                       &lower_suboff, &upper_suboff);
 
-  t = fold_build_pointer_plus (base_decl, span_off);
-  elem_size = build1 (INDIRECT_REF, gfc_array_index_type, t);
-
   t = base_decl;
   if (!integer_zerop (data_off))
     t = fold_build_pointer_plus (t, data_off);
@@ -3960,9 +3974,8 @@ gfc_get_array_descr_info (const_tree type, struct 
array_descr_info *info)
        }
       t = fold_build_pointer_plus (base_decl,
                                   size_binop (PLUS_EXPR,
-                                              dim_off, stride_suboff));
+                                              dim_off, sm_suboff));
       t = build1 (INDIRECT_REF, gfc_array_index_type, t);
-      t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size);
       info->dimen[dim].stride = t;
       if (dim + 1 < rank)
        dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 83b9b9b905fd..3e985bdb9127 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -196,20 +196,33 @@ typedef struct gfc_array_info
   tree descriptor;
   /* holds the pointer to the data array.  */
   tree data;
+  /* Original data pointer without additional offset.  */
+  tree saved_data;
   /* To move some of the array index calculation out of the innermost loop.  */
   tree offset;
+  /* Original offset.  */
   tree saved_offset;
-  tree stride0;
   /* Holds the SS for a subscript.  Indexed by actual dimension.  */
   struct gfc_ss *subscript[GFC_MAX_DIMENSIONS];
 
-  /* stride and delta are used to access this inside a scalarization loop.
+  /* stride, spacing and delta are used to access this inside a scalarization 
loop.
      start is used in the calculation of these.  Indexed by scalarizer
      dimension.  */
   tree start[GFC_MAX_DIMENSIONS];
   tree end[GFC_MAX_DIMENSIONS];
+  /* The spacing of indexes, that may be specified by the strides of array
+     references.  */
   tree stride[GFC_MAX_DIMENSIONS];
+  /* The spacing in memory of elements of consecutive indexes, for each
+     dimension. This is the intrinsic spacing of the array given by its stride
+     multiplier (sm).  In units whose size is given by the element type if
+     array_access is true, otherwise in bytes.  */
+  tree spacing[GFC_MAX_DIMENSIONS];
   tree delta[GFC_MAX_DIMENSIONS];
+
+  /* False: access with pointer arithmetics.
+     True: access with array reference.  */
+  bool array_access;
 }
 gfc_array_info;
 
@@ -1025,7 +1038,8 @@ struct GTY(())    lang_type        {
   enum gfc_array_kind akind;
   tree lbound[GFC_MAX_DIMENSIONS];
   tree ubound[GFC_MAX_DIMENSIONS];
-  tree stride[GFC_MAX_DIMENSIONS];
+  tree sm[GFC_MAX_DIMENSIONS];
+  tree elem_len;
   tree size;
   tree offset;
   tree dtype;
@@ -1097,8 +1111,20 @@ struct GTY(()) lang_decl {
   (TYPE_LANG_SPECIFIC(node)->lbound[dim])
 #define GFC_TYPE_ARRAY_UBOUND(node, dim) \
   (TYPE_LANG_SPECIFIC(node)->ubound[dim])
+#define GFC_TYPE_ARRAY_SM(node, dim) \
+  (TYPE_LANG_SPECIFIC(node)->sm[dim])
+#define GFC_TYPE_ARRAY_EXTENT(node, dim) \
+  (fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, \
+                   fold_build2_loc (input_location, MINUS_EXPR, \
+                                    gfc_array_index_type, \
+                                    GFC_TYPE_ARRAY_UBOUND((node), (dim)), \
+                                    GFC_TYPE_ARRAY_LBOUND((node), (dim))), \
+                   gfc_index_one_node))
 #define GFC_TYPE_ARRAY_STRIDE(node, dim) \
-  (TYPE_LANG_SPECIFIC(node)->stride[dim])
+  (fold_build2_loc (input_location, EXACT_DIV_EXPR, gfc_array_index_type, \
+                   GFC_TYPE_ARRAY_SM((node), (dim)), \
+                   GFC_TYPE_ARRAY_ELEM_LEN((node))))
+#define GFC_TYPE_ARRAY_ELEM_LEN(node) (TYPE_LANG_SPECIFIC(node)->elem_len)
 #define GFC_TYPE_ARRAY_RANK(node) (TYPE_LANG_SPECIFIC(node)->rank)
 #define GFC_TYPE_ARRAY_CORANK(node) (TYPE_LANG_SPECIFIC(node)->corank)
 #define GFC_TYPE_ARRAY_CAF_TOKEN(node) (TYPE_LANG_SPECIFIC(node)->caf_token)
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 3fc53938b4a2..4b9a3c820dcd 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -4929,7 +4929,7 @@ export_proto(st_set_nml_var_dim);
 
 void
 st_set_nml_var_dim (st_parameter_dt *dtp, GFC_INTEGER_4 n_dim,
-                   index_type stride, index_type lbound,
+                   index_type sm, index_type lbound,
                    index_type ubound)
 {
   namelist_info *nml;
@@ -4939,7 +4939,7 @@ st_set_nml_var_dim (st_parameter_dt *dtp, GFC_INTEGER_4 
n_dim,
 
   for (nml = dtp->u.p.ionml; nml->next; nml = nml->next);
 
-  GFC_DIMENSION_SET(nml->dim[n],lbound,ubound,stride);
+  GFC_DIMENSION_SET(nml->dim[n],lbound,ubound,sm);
 }

Reply via email to