[flang-commits] [flang] 95ee221 - [flang] Delete the legacy array-value operations from FIR (#213159)

via flang-commits flang-commits at lists.llvm.org
Fri Jul 31 05:47:18 PDT 2026


Author: Eugene Epshteyn
Date: 2026-07-31T08:47:13-04:00
New Revision: 95ee221ea8fade17576845f12df8c2cd26f85aa5

URL: https://github.com/llvm/llvm-project/commit/95ee221ea8fade17576845f12df8c2cd26f85aa5
DIFF: https://github.com/llvm/llvm-project/commit/95ee221ea8fade17576845f12df8c2cd26f85aa5.diff

LOG: [flang] Delete the legacy array-value operations from FIR (#213159)

Nothing in flang has produced fir.array_load, fir.array_fetch,
fir.array_update, fir.array_modify, fir.array_access, fir.array_amend,
or fir.array_merge_store since the legacy (non-HLFIR) expression
lowering was deleted (#210385, #210621, #210639, #210873), and the
array-value-copy pass that legalized them is gone (#211816, #212643).
Delete the operations and the surface that existed only for them:

- FIROps.td: the "Array value operations" section including the
copy-in/copy-out design comment; FIROps.cpp: the ops verifiers, effects
and getExtents. fir.array_coor is unrelated and stays, as does the
validTypeParams helper shared with fir.pack_array.
- Tests: the ops roundtrip/verifier blocks in fir-ops.fir and
invalid.fir; scaffolding rewrites in inline-elemental.fir (store via
hlfir.designate; hlfir.apply-in-do_loop coverage preserved),
loop-versioning.fir @test4 (the versioned loops are untouched), and
simplifyintrinsics.fir (inert copy-back loops dropped; no CHECK lines
affected).
- Docs: FIRArrayOperations.md (+ the index.md toctree line); past-tense
updates in HighLevelFIR.md; a stale comment in MutableBox.h; a
release-note entry recording the removal for downstream projects.
FIRLangRef is generated from FIROps.td and follows automatically.

Assisted-by: AI

Added: 
    

Modified: 
    flang/docs/HighLevelFIR.md
    flang/docs/ReleaseNotes.md
    flang/docs/index.md
    flang/include/flang/Optimizer/Builder/MutableBox.h
    flang/include/flang/Optimizer/Dialect/FIROps.td
    flang/lib/Optimizer/Dialect/FIROps.cpp
    flang/test/Fir/fir-ops.fir
    flang/test/Fir/invalid.fir
    flang/test/HLFIR/inline-elemental.fir
    flang/test/Transforms/loop-versioning.fir
    flang/test/Transforms/simplifyintrinsics.fir

Removed: 
    flang/docs/FIRArrayOperations.md


################################################################################
diff  --git a/flang/docs/FIRArrayOperations.md b/flang/docs/FIRArrayOperations.md
deleted file mode 100644
index 230409bd04a94..0000000000000
--- a/flang/docs/FIRArrayOperations.md
+++ /dev/null
@@ -1,343 +0,0 @@
-<!--===- docs/FIRArrayOperations.md
-
-   Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-   See https://llvm.org/LICENSE.txt for license information.
-   SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
--->
-
-# Design: FIR Array operations
-
-```{contents}
----
-local:
----
-```
-
-## General
-
-The array operations in FIR model the copy-in/copy-out semantics over Fortran
-statements.
-
-Fortran language semantics sometimes require the compiler to make a temporary
-copy of an array or array slice. Situations where this can occur include:
-
-* Passing a non-contiguous array to a procedure that does not declare it as
-  assumed-shape.
-* Array expressions, especially those involving `RESHAPE`, `PACK`, and `MERGE`.
-* Assignments of arrays where the array appears on both the left and right-hand
-  sides of the assignment.
-* Assignments of `POINTER` arrays.
-
-There are currently the following operations:
-- `fir.array_load`
-- `fir.array_merge_store`
-- `fir.array_fetch`
-- `fir.array_update`
-- `fir.array_access`
-- `fir.array_amend`
-
-`array_load`(s) and `array_merge_store` are a pairing that brackets the lifetime
-of the array copies.
-
-`array_fetch` and `array_update` are defined to work as getter/setter pairs on
-values of elements from loaded array copies. These have "GEP-like" syntax and
-semantics.
-
-Fortran arrays are implicitly memory bound as are some other Fortran type/kind
-entities. For entities that can be atomically promoted to the value domain,
-we use `array_fetch` and `array_update`.
-
-`array_access` and `array_amend` are defined to work as getter/setter pairs on
-references to elements in loaded array copies. `array_access` has "GEP-like"
-syntax. `array_amend` annotates which loaded array copy is being written to.
-It is invalid to update an array copy without `array_amend`; doing so will
-result in undefined behavior.
-For those type/kinds that cannot be promoted to values, we must leave them in a
-memory reference domain, and we use `array_access` and `array_amend`.
-
-## array_load
-
-This operation taken with `array_merge_store` captures Fortran's
-copy-in/copy-out semantics. One way to think of this is that array_load
-creates a snapshot copy of the entire array. This copy can then be used
-as the "original value" of the array while the array's new value is
-computed. The `array_merge_store` operation is the copy-out semantics, which
-merge the updates with the original array value to produce the final array
-result. This abstracts the copy operations as opposed to always creating
-copies or requiring dependence analysis be performed on the syntax trees
-and before lowering to the IR.
-
-Load an entire array as a single SSA value.
-
-```fortran
-  real :: a(o:n,p:m)
-  ...
-  ... = ... a ...
-```
-
-One can use `fir.array_load` to produce an ssa-value that captures an
-immutable value of the entire array `a`, as in the Fortran array expression
-shown above. Subsequent changes to the memory containing the array do not
-alter its composite value. This operation lets one load an array as a
-value while applying a runtime shape, shift, or slice to the memory
-reference, and its semantics guarantee immutability.
-
-```
-%s = fir.shape_shift %lb1, %ex1, %lb2, %ex2 : (index, index, index, index) -> !fir.shapeshift<2>
-// load the entire array 'a'
-%v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-// a fir.store here into array %a does not change %v
-```
-
-## array_merge_store
-
-The `array_merge_store` operation stores a merged array value to memory.
-
-
-```fortran
-  real :: a(n,m)
-  ...
-  a = ...
-```
-
-One can use `fir.array_merge_store` to merge/copy the value of `a` in an
-array expression as shown above.
-
-```
-  %v = fir.array_load %a(%shape) : ...
-  %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-  fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
-```
-
-This operation merges the original loaded array value, `%v`, with the
-chained updates, `%r`, and stores the result to the array at address, `%a`.
-
-This operation taken with `array_load`'s captures Fortran's
-copy-in/copy-out semantics. The first operands of `array_merge_store` is the
-result of the initial `array_load` operation. While this value could be
-retrieved by reference chasing through the 
diff erent array operations it is
-useful to have it on hand directly for analysis passes since this directly
-defines the "bounds" of the Fortran statement represented by these operations.
-The intention is to allow copy-in/copy-out regions to be easily delineated,
-analyzed, and optimized.
-
-## array_fetch
-
-The `array_fetch` operation fetches the value of an element in an array value.
-
-```fortran
-  real :: a(n,m)
-  ...
-  ... a ...
-  ... a(r,s+1) ...
-```
-
-One can use `fir.array_fetch` to fetch the (implied) value of `a(i,j)` in
-an array expression as shown above. It can also be used to extract the
-element `a(r,s+1)` in the second expression.
-
-```
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  // load the entire array 'a'
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  // fetch the value of one of the array value's elements
-  %1 = fir.array_fetch %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
-```
-
-It is only possible to use `array_fetch` on an `array_load` result value or a
-value that can be trace back transitively to an `array_load` as the dominating
-source. Other array operation such as `array_update` can be in between.
-
-## array_update
-
-The `array_update` operation is used to update the value of an element in an
-array value. A new array value is returned where all element values of the input
-array are identical except for the selected element which is the value passed in
-the update.
-
-```fortran
-  real :: a(n,m)
-  ...
-  a = ...
-```
-
-One can use `fir.array_update` to update the (implied) value of `a(i,j)`
-in an array expression as shown above.
-
-```
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  // load the entire array 'a'
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  // update the value of one of the array value's elements
-  // %r_{ij} = %f  if (i,j) = (%i,%j),   %v_{ij} otherwise
-  %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-  fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
-```
-
-An array value update behaves as if a mapping function from the indices
-to the new value has been added, replacing the previous mapping. These
-mappings can be added to the ssa-value, but will not be materialized in
-memory until the `fir.array_merge_store` is performed.
-`fir.array_update` can be seen as an array access with a notion that the array
-will be changed at the accessed position when `fir.array_merge_store` is
-performed.
-
-## array_access
-
-The `array_access` provides a reference to a single element from an array value.
-This is *not* a view in the immutable array, otherwise it couldn't be stored to.
-It can be see as a logical copy of the element and its position in the array.
-Tis reference can be written to and modified withoiut changing the original
-array.
-
-The `array_access` operation is used to fetch the memory reference of an element
-in an array value.
-
-```fortran
-  real :: a(n,m)
-  ...
-  ... a ...
-  ... a(r,s+1) ...
-```
-
-One can use `fir.array_access` to recover the implied memory reference to
-the element `a(i,j)` in an array expression `a` as shown above. It can also
-be used to recover the reference element `a(r,s+1)` in the second
-expression.
-
-```
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  // load the entire array 'a'
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  // fetch the value of one of the array value's elements
-  %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
-```
-
-It is only possible to use `array_access` on an `array_load` result value or a
-value that can be trace back transitively to an `array_load` as the dominating
-source. Other array operation such as `array_amend` can be in between.
-
-`array_access` if mainly used with `character`'s arrays and arrays of derived
-types where because they might have a non-compile time sizes that would be
-useless too load entirely or too big to load.
-
-Here is a simple example with a `character` array assignment.
-
-Fortran
-```
-subroutine foo(c1, c2, n)
-  integer(8) :: n
-  character(n) :: c1(:), c2(:)
-  c1 = c2
-end subroutine
-```
-
-It results in this cleaned-up FIR:
-```
-func @_QPfoo(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg1: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg2: !fir.ref<i64>) {
-    %0 = fir.load %arg2 : !fir.ref<i64>
-    %c0 = arith.constant 0 : index
-    %1:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index)
-    %2 = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
-    %3 = fir.array_load %arg1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
-    %c1 = arith.constant 1 : index
-    %4 = arith.subi %1#1, %c1 : index
-    %5 = fir.do_loop %arg3 = %c0 to %4 step %c1 unordered iter_args(%arg4 = %2) -> (!fir.array<?x!fir.char<1,?>>) {
-      %6 = fir.array_access %3, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
-      %7 = fir.array_access %arg4, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
-      %false = arith.constant false
-      %8 = fir.convert %7 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
-      %9 = fir.convert %6 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
-      fir.call @llvm.memmove.p0i8.p0i8.i64(%8, %9, %0, %false) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
-      %10 = fir.array_amend %arg4, %7 : (!fir.array<?x!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> !fir.array<?x!fir.char<1,?>>
-      fir.result %10 : !fir.array<?x!fir.char<1,?>>
-    }
-    fir.array_merge_store %2, %5 to %arg0 : !fir.array<?x!fir.char<1,?>>, !fir.array<?x!fir.char<1,?>>, !fir.box<!fir.array<?x!fir.char<1,?>>>
-    return
-  }
-  func private @llvm.memmove.p0i8.p0i8.i64(!fir.ref<i8>, !fir.ref<i8>, i64, i1)
-}
-```
-
-`fir.array_access` and `fir.array_amend` split the two purposes of
-`fir.array_update` into two distinct operations to work on type/kind that must
-reside in the memory reference domain. `fir.array_access` captures the array
-access semantics and `fir.array_amend` denotes which `fir.array_access` is the
-lhs.
-
-We do not want to start loading the entire `!fir.ref<!fir.char<1,?>>` here since
-it has dynamic length, and even if constant, could be too long to do so.
-
-## array_amend
-
-The `array_amend` operation marks an array value as having been changed via a
-reference obtain by an `array_access`. It acts as a logical transaction log
-that is used to merge the final result back with an `array_merge_store`
-operation.
-
-```
-  // fetch the value of one of the array value's elements
-  %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
-  // modify the element by storing data using %1 as a reference
-  %2 = ... %1 ...
-  // mark the array value
-  %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
-```
-
-## Example
-
-Here is an example of a FIR code using several array operations together. The
-example below is a simplified version of the FIR code comiing from the
-following Fortran code snippet.
-
-```fortran
-subroutine s(a,l,u)
-  type t
-    integer m
-  end type t
-  type(t) :: a(:)
-  integer :: l, u
-  forall (i=l:u)
-    a(i) = a(u-i+1)
-  end forall
-end
-```
-
-```
-func @_QPs(%arg0: !fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>, %arg1: !fir.ref<i32>, %arg2: !fir.ref<i32>) {
-  %l = fir.load %arg1 : !fir.ref<i32>
-  %l_index = fir.convert %l : (i32) -> index
-  %u = fir.load %arg2 : !fir.ref<i32>
-  %u_index = fir.convert %u : (i32) -> index
-  %c1 = arith.constant 1 : index
-  // This is the "copy-in" array used on the RHS of the expression. It will be indexed into and loaded at each iteration.
-  %array_a_src = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>>
-
-  // This is the "seed" for the "copy-out" array on the LHS. It'll flow from iteration to iteration and gets
-  // updated at each iteration.
-  %array_a_dest_init = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>>
-
-  %array_a_final = fir.do_loop %i = %l_index to %u_index step %c1 unordered iter_args(%array_a_dest = %array_a_dest_init) -> (!fir.array<?x!fir.type<_QFsTt{m:i32}>>) {
-    // Compute indexing for the RHS and array the element.
-    %u_minus_i = arith.subi %u_index, %i : index // u-i
-    %u_minus_i_plus_one = arith.addi %u_minus_i, %c1: index // u-i+1
-    %a_src_ref = fir.array_access %array_a_src, %u_minus_i_plus_one {Fortran.offsets} : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, index) -> !fir.ref<!fir.type<_QFsTt{m:i32}>>
-    %a_src_elt = fir.load %a_src_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>>
-
-    // Get the reference to the element in the array on the LHS
-    %a_dst_ref = fir.array_access %array_a_dest, %i {Fortran.offsets} : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, index) -> !fir.ref<!fir.type<_QFsTt{m:i32}>>
-
-    // Store the value, and update the array
-    fir.store %a_src_elt to %a_dst_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>>
-    %updated_array_a = fir.array_amend %array_a_dest, %a_dst_ref : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.ref<!fir.type<_QFsTt{m:i32}>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>>
-
-    // Forward the current updated array to the next iteration.
-    fir.result %updated_array_a : !fir.array<?x!fir.type<_QFsTt{m:i32}>>
-  }
-  // Store back the result by merging the initial value loaded before the loop
-  // with the final one produced by the loop.
-  fir.array_merge_store %array_a_dest_init, %array_a_final to %arg0 : !fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>
-  return
-}
-```

diff  --git a/flang/docs/HighLevelFIR.md b/flang/docs/HighLevelFIR.md
index 99a05c48b1e4e..ffc03be376836 100644
--- a/flang/docs/HighLevelFIR.md
+++ b/flang/docs/HighLevelFIR.md
@@ -19,9 +19,9 @@ and how bufferizations of character and array expressions should be done.
 This document proposes the addition of two concepts and a set of related
 operations in a new dialect HLFIR to allow a simpler lowering to a higher-level
 FIR representation that would later be lowered to the current FIR representation
-via MLIR translation passes.  As a result of these additions, it is likely that
-the fir.array_load/fir.array_merge_store and related array operations could be
-removed from FIR since array assignment analysis could directly happen on the
+via MLIR translation passes.  As a result of these additions, the
+fir.array_load/fir.array_merge_store and related array operations have been
+removed from FIR since array assignment analysis directly happens on the
 higher-level FIR representation.
 
 
@@ -110,8 +110,8 @@ The hlfir.declare operation and restrained memory types will allow:
   assignments or transformational intrinsics).
 - Generating debug information for the variables based on the hlfir.declare
   operation.
-- Generic Fortran aliasing analysis (currently implemented only around array
-  assignments with the fir.array_load concept).
+- Generic Fortran aliasing analysis (previously implemented only around array
+  assignments with the since-removed fir.array_load concept).
 
 The hlfir.declare will have a sibling fir.declare operation in FIR that will
 allow keeping variable information until debug info is generated. The main
@@ -501,7 +501,8 @@ The attributes can be:
 -   temporary_lhs: mark that the left hand side of the assignment is
     a compiler generated temporary.
 
-This will replace the current array_load/array_access/array_merge semantics.
+This replaced the legacy array_load/array_access/array_merge semantics, whose
+operations have since been removed from FIR.
 Instead, a more generic alias analysis will be performed on the LHS and RHS to
 detect aliasing, and a temporary inserted if needed. The alias analysis will
 look at all the memory references in the RHS operand tree and base overlap
@@ -1249,9 +1250,9 @@ func.func @_QPfoo(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: !fir.box<!fir.array
 
 Step 6: lower hlfir.designate/hlfir.assign in a translation pass:
 
-At this point, the representation is similar to the current representation after
-the array value copy pass, and the existing FIR flow is used (lowering
-fir.do_loop to cfg and doing codegen to LLVM).
+At this point, the representation is similar to what the legacy lowering
+produced after its array value copy pass (both since removed), and the existing
+FIR flow is used (lowering fir.do_loop to cfg and doing codegen to LLVM).
 
 ### Example 3: assignments with vector subscript
 

diff  --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 888da4d58b868..509456486e557 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -33,6 +33,16 @@ page](https://llvm.org/releases/).
 
 ## Non-comprehensive list of changes in this release
 
+- The legacy array-value operations (`fir.array_load`, `fir.array_fetch`,
+  `fir.array_update`, `fir.array_modify`, `fir.array_access`,
+  `fir.array_amend`, `fir.array_merge_store`) have been removed from FIR,
+  together with the `array-value-copy` pass that legalized them and its
+  `-mmlir -disable-avc` option. Nothing in flang has produced these
+  operations since the legacy (non-HLFIR) expression lowering was deleted.
+  Downstream projects that still construct them must migrate to HLFIR (or
+  their own legalization) before rebasing. `fir.array_coor` is unrelated
+  and remains supported.
+
 ## New Compiler Flags
 
 ## Windows Support

diff  --git a/flang/docs/index.md b/flang/docs/index.md
index 2e7150188c8d4..5ad7e4e23d410 100644
--- a/flang/docs/index.md
+++ b/flang/docs/index.md
@@ -69,7 +69,6 @@ on how to get in touch with us and to learn more about the current status.
    DoConcurrent
    DoConcurrentConversionToOpenMP
    F202X
-   FIRArrayOperations
    FIRLangRef
    FlangDriver
    FortranFeatureHistory

diff  --git a/flang/include/flang/Optimizer/Builder/MutableBox.h b/flang/include/flang/Optimizer/Builder/MutableBox.h
index e1cb0f9852ba7..9ba09495f328a 100644
--- a/flang/include/flang/Optimizer/Builder/MutableBox.h
+++ b/flang/include/flang/Optimizer/Builder/MutableBox.h
@@ -108,8 +108,7 @@ struct MutableBoxReallocation {
 /// is an ExtendedValue for the storage pointer.
 /// For example, when genReallocIfNeeded() is used for a LHS allocatable
 /// array in an assignment, the callback performs the actual assignment
-/// via the given storage pointer, so we end up generating array_updates and
-/// array_merge_stores in each branch.
+/// via the given storage pointer, in each branch.
 using ReallocStorageHandlerFunc = std::function<void(fir::ExtendedValue)>;
 
 MutableBoxReallocation

diff  --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index ae7b8796f8957..7635e3bf82035 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1544,402 +1544,6 @@ def fir_BoxTypeDescOp : fir_SimpleOneResultOp<"box_tdesc", [NoMemoryEffect]> {
   let results = (outs fir_TypeDescType);
 }
 
-//===----------------------------------------------------------------------===//
-// Array value operations
-//===----------------------------------------------------------------------===//
-
-// Array value operations are used to capture the semantics of
-// Fortran's array expressions in FIR. An abstract array expression is
-// evaluated in the following way.
-//
-//  1. Determination of the iteration space under which the assignment
-//     expression is to be evaluated. The iteration space may be implicit
-//     (from the shape of the result array) or explicit (defined by the user).
-//  2. If there are masking expressions, evaluate (and cache) the
-//     masking expression for the iteration space (from 1).
-//  3. The rhs of the assignment is evaluated for the iteration space. If
-//     masking expressions were present then the rhs is only evaluated where
-//     the mask was computed to be true. The entire rhs is completely evaluated
-//     before any results are stored to the lhs.
-//  4. Each of the result values computed in the previous step are merged back
-//     to the lhs array's storage.
-//
-// The model (in pseudo-code) is thus:
-//
-//   !- Load the arrays in the expression
-//   %10 = array_load A
-//   %11 = array_load B
-//   !- optional: compute mask values
-//   %masks = allocmem array<??xlogical>
-//   do_loop_nest %i = ... {
-//     %masks[i] = ...
-//   }
-//   !- Compute every element value "A = B ..."
-//   do_loop_nest %i = ... {
-//     if (%masks[i]) {
-//       array_fetch %11, ...       !- B(...)
-//       %20 = ...                  !- element-by-element computation
-//       array_update %10, %20, ... !- A(...) = ...
-//     }
-//   }
-//   !- Merge the new and old values into the memory for "A"
-//   array_merge_store <updated A> to <A's address>
-
-def fir_ArrayLoadOp : fir_Op<"array_load", [AttrSizedOperandSegments,
-                                            DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
-
-  let summary = "Load an array as a value.";
-
-  let description = [{
-    This operation taken with array_merge_store captures Fortran's
-    copy-in/copy-out semantics. One way to think of this is that array_load
-    creates a snapshot copy of the entire array. This copy can then be used
-    as the "original value" of the array while the array's new value is
-    computed. The array_merge_store operation is the copy-out semantics, which
-    merge the updates with the original array value to produce the final array
-    result. This abstracts the copy operations as opposed to always creating
-    copies or requiring dependence analysis be performed on the syntax trees
-    and before lowering to the IR.
-
-    Load an entire array as a single SSA value.
-
-    ```fortran
-      real :: a(o:n,p:m)
-      ...
-      ... = ... a ...
-    ```
-
-    One can use `fir.array_load` to produce an ssa-value that captures an
-    immutable value of the entire array `a`, as in the Fortran array expression
-    shown above. Subsequent changes to the memory containing the array do not
-    alter its composite value. This operation lets one load an array as a
-    value while applying a runtime shape, shift, or slice to the memory
-    reference, and its semantics guarantee immutability.
-
-    ```
-      %s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shapeshift<2>
-      // load the entire array 'a'
-      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-      // a fir.store here into array %a does not change %v
-    ```
-  }];
-
-  let arguments = (ins
-    AnyRefOrBox:$memref,
-    Optional<AnyShapeOrShiftType>:$shape,
-    Optional<fir_SliceType>:$slice,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let results = (outs fir_SequenceType);
-
-  let assemblyFormat = [{
-    $memref (`(`$shape^`)`)? (`[`$slice^`]`)? (`typeparams` $typeparams^)?
-        attr-dict `:` functional-type(operands, results)
-  }];
-
-  let hasVerifier = 1;
-
-  let extraClassDeclaration = [{
-    std::vector<mlir::Value> getExtents();
-  }];
-}
-
-def fir_ArrayFetchOp : fir_Op<"array_fetch", [AttrSizedOperandSegments,
-    NoMemoryEffect]> {
-
-  let summary = "Fetch the value of an element of an array value";
-
-  let description = [{
-    Fetch the value of an element in an array value.
-
-    ```fortran
-      real :: a(n,m)
-      ...
-      ... a ...
-      ... a(r,s+1) ...
-    ```
-
-    One can use `fir.array_fetch` to fetch the (implied) value of `a(i,j)` in
-    an array expression as shown above. It can also be used to extract the
-    element `a(r,s+1)` in the second expression.
-
-    ```
-      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-      // load the entire array 'a'
-      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-      // fetch the value of one of the array value's elements
-      %1 = fir.array_fetch %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
-    ```
-
-    It is only possible to use `array_fetch` on an `array_load` result value.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$sequence,
-    Variadic<AnyCoordinateType>:$indices,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let results = (outs AnyType:$element);
-
-  let assemblyFormat = [{
-    $sequence `,` $indices (`typeparams` $typeparams^)? attr-dict `:`
-      functional-type(operands, results)
-  }];
-
-  let hasVerifier = 1;
-}
-
-def fir_ArrayUpdateOp : fir_Op<"array_update", [AttrSizedOperandSegments,
-    NoMemoryEffect]> {
-
-  let summary = "Update the value of an element of an array value";
-
-  let description = [{
-    Updates the value of an element in an array value. A new array value is
-    returned where all element values of the input array are identical except
-    for the selected element which is the value passed in the update.
-
-    ```fortran
-      real :: a(n,m)
-      ...
-      a = ...
-    ```
-
-    One can use `fir.array_update` to update the (implied) value of `a(i,j)`
-    in an array expression as shown above.
-
-    ```
-      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-      // load the entire array 'a'
-      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-      // update the value of one of the array value's elements
-      // %r_{ij} = %f  if (i,j) = (%i,%j),   %v_{ij} otherwise
-      %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-      fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
-    ```
-
-    An array value update behaves as if a mapping function from the indices
-    to the new value has been added, replacing the previous mapping. These
-    mappings can be added to the ssa-value, but will not be materialized in
-    memory until the `fir.array_merge_store` is performed.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$sequence,
-    AnyType:$merge,
-    Variadic<AnyCoordinateType>:$indices,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let results = (outs fir_SequenceType);
-
-  let assemblyFormat = [{
-    $sequence `,` $merge `,` $indices (`typeparams` $typeparams^)? attr-dict
-      `:` functional-type(operands, results)
-  }];
-
-  let hasVerifier = 1;
-}
-
-def fir_ArrayModifyOp : fir_Op<"array_modify", [AttrSizedOperandSegments,
-    NoMemoryEffect]> {
-  let summary = "Get an address for an array value to modify it.";
-
-  let description = [{
-    Modify the value of an element in an array value through actions done
-    on the returned address. A new array value is also
-    returned where all element values of the input array are identical except
-    for the selected element which is the value after the modification done
-    on the element address.
-
-    ```fortran
-      real :: a(n)
-      ...
-      ! Elemental user defined assignment from type(SomeType) to real.
-      a = value_of_some_type
-    ```
-
-    One can use `fir.array_modify` to update the (implied) value of `a(i)`
-    in an array expression as shown above.
-
-    ```
-      %s = fir.shape %n : (index) -> !fir.shape<1>
-      // Load the entire array 'a'.
-      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.array<?xf32>
-      // Update the value of one of the array value's elements with a user
-      // defined assignment from %rhs.
-      %new = fir.do_loop %i = ... (%inner = %v) {
-        %rhs = ...
-        %addr, %r = fir.array_modify %inner, %i : (!fir.array<?xf32>, index) -> (fir.ref<f32>, !fir.array<?xf32>)
-        fir.call @user_def_assign(%addr, %rhs) (fir.ref<f32>, fir.ref<!fir.type<SomeType>>) -> ()
-        fir.result %r : !fir.ref<!fir.array<?xf32>>
-      }
-      fir.array_merge_store %v, %new to %a : !fir.ref<!fir.array<?xf32>>
-    ```
-
-    An array value modification behaves as if a mapping function from the indices
-    to the new value has been added, replacing the previous mapping. These
-    mappings can be added to the ssa-value, but will not be materialized in
-    memory until the `fir.array_merge_store` is performed.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$sequence,
-    Variadic<AnyCoordinateType>:$indices,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let results = (outs fir_ReferenceType, fir_SequenceType);
-
-  let assemblyFormat = [{
-    $sequence `,` $indices (`typeparams` $typeparams^)? attr-dict
-      `:` functional-type(operands, results)
-  }];
-
-  let hasVerifier = 1;
-}
-
-def fir_ArrayAccessOp : fir_Op<"array_access", [AttrSizedOperandSegments,
-    NoMemoryEffect]> {
-  let summary = "Fetch the reference of an element of an array value";
-
-  let description = [{
-    The `array_access` provides a reference to a single element from an array
-    value. This is *not* a view in the immutable array, otherwise it couldn't
-    be stored to. It can be see as a logical copy of the element and its
-    position in the array. This reference can be written to and modified without
-    changing the original array.
-
-    The `array_access` operation is used to fetch the memory reference of an
-    element in an array value.
-
-    ```fortran
-      real :: a(n,m)
-      ...
-      ... a ...
-      ... a(r,s+1) ...
-    ```
-
-    One can use `fir.array_access` to recover the implied memory reference to
-    the element `a(i,j)` in an array expression `a` as shown above. It can also
-    be used to recover the reference element `a(r,s+1)` in the second
-    expression.
-
-    ```
-      %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-      // load the entire array 'a'
-      %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-      // fetch the value of one of the array value's elements
-      %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
-    ```
-
-    It is only possible to use `array_access` on an `array_load` result value or
-    a value that can be trace back transitively to an `array_load` as the
-    dominating source. Other array operations such as `array_amend` can be in
-    between.
-
-    TODO: The above restriction is not enforced. The design of the operation
-    might need to be revisited to avoid such restrictions.
-
-    More information about `array_access` and other array operations can be
-    found in flang/docs/FIRArrayOperations.md.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$sequence,
-    Variadic<AnyCoordinateType>:$indices,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let results = (outs fir_ReferenceType:$element);
-
-  let assemblyFormat = [{
-    $sequence `,` $indices (`typeparams` $typeparams^)? attr-dict `:`
-      functional-type(operands, results)
-  }];
-
-  let hasVerifier = 1;
-}
-
-def fir_ArrayAmendOp : fir_Op<"array_amend", [NoMemoryEffect]> {
-  let summary = "Mark an array value as having been changed by reference.";
-
-  let description = [{
-    The `array_amend` operation marks an array value as having been changed via
-    a reference obtained by an `array_access`. It acts as a logical transaction
-    log that is used to merge the final result back with an `array_merge_store`
-    operation.
-
-    ```
-      // fetch the value of one of the array value's elements
-      %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
-      // modify the element by storing data using %1 as a reference
-      %2 = ... %1 ...
-      // mark the array value
-      %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
-    ```
-
-    More information about `array_amend` and other array operations can be
-    found in flang/docs/FIRArrayOperations.md.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$sequence,
-    fir_ReferenceType:$memref
-  );
-
-  let results = (outs fir_SequenceType);
-
-  let assemblyFormat = [{
-    $sequence `,` $memref attr-dict `:` functional-type(operands, results)
-  }];
-}
-
-def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
-    [AttrSizedOperandSegments, DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
-
-  let summary = "Store merged array value to memory.";
-
-  let description = [{
-    Store a merged array value to memory.
-
-    ```fortran
-      real :: a(n,m)
-      ...
-      a = ...
-    ```
-
-    One can use `fir.array_merge_store` to merge/copy the value of `a` in an
-    array expression as shown above.
-
-    ```
-      %v = fir.array_load %a(%shape) : ...
-      %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-      fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
-    ```
-
-    This operation merges the original loaded array value, `%v`, with the
-    chained updates, `%r`, and stores the result to the array at address, `%a`.
-  }];
-
-  let arguments = (ins
-    fir_SequenceType:$original,
-    fir_SequenceType:$sequence,
-    AnyRefOrBox:$memref,
-    Optional<fir_SliceType>:$slice,
-    Variadic<AnyIntegerType>:$typeparams
-  );
-
-  let assemblyFormat = [{
-    $original `,` $sequence `to` $memref (`[` $slice^ `]`)? (`typeparams`
-      $typeparams^)? attr-dict `:` type(operands)
-  }];
-
-  let hasVerifier = 1;
-}
-
 //===----------------------------------------------------------------------===//
 // Record and array type operations
 //===----------------------------------------------------------------------===//

diff  --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 798ab130c1d30..970efae5488a2 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1261,218 +1261,6 @@ std::optional<std::int64_t> fir::ArrayCoorOp::getViewOffset(mlir::OpResult) {
   return std::nullopt;
 }
 
-//===----------------------------------------------------------------------===//
-// ArrayLoadOp
-//===----------------------------------------------------------------------===//
-
-static mlir::Type adjustedElementType(mlir::Type t) {
-  if (auto ty = mlir::dyn_cast<fir::ReferenceType>(t)) {
-    auto eleTy = ty.getEleTy();
-    if (fir::isa_char(eleTy))
-      return eleTy;
-    if (fir::isa_derived(eleTy))
-      return eleTy;
-    if (mlir::isa<fir::SequenceType>(eleTy))
-      return eleTy;
-  }
-  return t;
-}
-
-std::vector<mlir::Value> fir::ArrayLoadOp::getExtents() {
-  if (auto sh = getShape())
-    if (auto *op = sh.getDefiningOp()) {
-      if (auto shOp = mlir::dyn_cast<fir::ShapeOp>(op)) {
-        auto extents = shOp.getExtents();
-        return {extents.begin(), extents.end()};
-      }
-      return mlir::cast<fir::ShapeShiftOp>(op).getExtents();
-    }
-  return {};
-}
-
-void fir::ArrayLoadOp::getEffects(
-    llvm::SmallVectorImpl<
-        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
-        &effects) {
-  effects.emplace_back(mlir::MemoryEffects::Read::get(), &getMemrefMutable(),
-                       mlir::SideEffects::DefaultResource::get());
-  addVolatileMemoryEffects({getMemref().getType()}, effects);
-}
-
-llvm::LogicalResult fir::ArrayLoadOp::verify() {
-  auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
-  auto arrTy = mlir::dyn_cast<fir::SequenceType>(eleTy);
-  if (!arrTy)
-    return emitOpError("must be a reference to an array");
-  auto arrDim = arrTy.getDimension();
-
-  if (auto shapeOp = getShape()) {
-    auto shapeTy = shapeOp.getType();
-    unsigned shapeTyRank = 0u;
-    if (auto s = mlir::dyn_cast<fir::ShapeType>(shapeTy)) {
-      shapeTyRank = s.getRank();
-    } else if (auto ss = mlir::dyn_cast<fir::ShapeShiftType>(shapeTy)) {
-      shapeTyRank = ss.getRank();
-    } else {
-      auto s = mlir::cast<fir::ShiftType>(shapeTy);
-      shapeTyRank = s.getRank();
-      if (!mlir::isa<fir::BaseBoxType>(getMemref().getType()))
-        return emitOpError("shift can only be provided with fir.box memref");
-    }
-    if (arrDim && arrDim != shapeTyRank)
-      return emitOpError("rank of dimension mismatched");
-  }
-
-  if (auto sliceOp = getSlice()) {
-    if (auto sl = mlir::dyn_cast_or_null<fir::SliceOp>(sliceOp.getDefiningOp()))
-      if (!sl.getSubstr().empty())
-        return emitOpError("array_load cannot take a slice with substring");
-    if (auto sliceTy = mlir::dyn_cast<fir::SliceType>(sliceOp.getType()))
-      if (sliceTy.getRank() != arrDim)
-        return emitOpError("rank of dimension in slice mismatched");
-  }
-
-  if (!validTypeParams(getMemref().getType(), getTypeparams()))
-    return emitOpError("invalid type parameters");
-
-  return mlir::success();
-}
-
-//===----------------------------------------------------------------------===//
-// ArrayMergeStoreOp
-//===----------------------------------------------------------------------===//
-
-llvm::LogicalResult fir::ArrayMergeStoreOp::verify() {
-  if (!mlir::isa<fir::ArrayLoadOp>(getOriginal().getDefiningOp()))
-    return emitOpError("operand #0 must be result of a fir.array_load op");
-  if (auto sl = getSlice()) {
-    if (auto sliceOp =
-            mlir::dyn_cast_or_null<fir::SliceOp>(sl.getDefiningOp())) {
-      if (!sliceOp.getSubstr().empty())
-        return emitOpError(
-            "array_merge_store cannot take a slice with substring");
-      if (!sliceOp.getFields().empty()) {
-        // This is an intra-object merge, where the slice is projecting the
-        // subfields that are to be overwritten by the merge operation.
-        auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
-        if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy)) {
-          auto projTy =
-              fir::applyPathToType(seqTy.getEleTy(), sliceOp.getFields());
-          if (fir::unwrapSequenceType(getOriginal().getType()) != projTy)
-            return emitOpError(
-                "type of origin does not match sliced memref type");
-          if (fir::unwrapSequenceType(getSequence().getType()) != projTy)
-            return emitOpError(
-                "type of sequence does not match sliced memref type");
-          return mlir::success();
-        }
-        return emitOpError("referenced type is not an array");
-      }
-    }
-    return mlir::success();
-  }
-  auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
-  if (getOriginal().getType() != eleTy)
-    return emitOpError("type of origin does not match memref element type");
-  if (getSequence().getType() != eleTy)
-    return emitOpError("type of sequence does not match memref element type");
-  if (!validTypeParams(getMemref().getType(), getTypeparams()))
-    return emitOpError("invalid type parameters");
-  return mlir::success();
-}
-
-void fir::ArrayMergeStoreOp::getEffects(
-    llvm::SmallVectorImpl<
-        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
-        &effects) {
-  effects.emplace_back(mlir::MemoryEffects::Write::get(), &getMemrefMutable(),
-                       mlir::SideEffects::DefaultResource::get());
-  addVolatileMemoryEffects({getMemref().getType()}, effects);
-}
-
-//===----------------------------------------------------------------------===//
-// ArrayFetchOp
-//===----------------------------------------------------------------------===//
-
-// Template function used for both array_fetch and array_update verification.
-template <typename A>
-mlir::Type validArraySubobject(A op) {
-  auto ty = op.getSequence().getType();
-  return fir::applyPathToType(ty, op.getIndices());
-}
-
-llvm::LogicalResult fir::ArrayFetchOp::verify() {
-  auto arrTy = mlir::cast<fir::SequenceType>(getSequence().getType());
-  auto indSize = getIndices().size();
-  if (indSize < arrTy.getDimension())
-    return emitOpError("number of indices != dimension of array");
-  if (indSize == arrTy.getDimension() &&
-      ::adjustedElementType(getElement().getType()) != arrTy.getEleTy())
-    return emitOpError("return type does not match array");
-  auto ty = validArraySubobject(*this);
-  if (!ty || ty != ::adjustedElementType(getType()))
-    return emitOpError("return type and/or indices do not type check");
-  if (!mlir::isa<fir::ArrayLoadOp>(getSequence().getDefiningOp()))
-    return emitOpError("argument #0 must be result of fir.array_load");
-  if (!validTypeParams(arrTy, getTypeparams()))
-    return emitOpError("invalid type parameters");
-  return mlir::success();
-}
-
-//===----------------------------------------------------------------------===//
-// ArrayAccessOp
-//===----------------------------------------------------------------------===//
-
-llvm::LogicalResult fir::ArrayAccessOp::verify() {
-  auto arrTy = mlir::cast<fir::SequenceType>(getSequence().getType());
-  std::size_t indSize = getIndices().size();
-  if (indSize < arrTy.getDimension())
-    return emitOpError("number of indices != dimension of array");
-  if (indSize == arrTy.getDimension() &&
-      getElement().getType() != fir::ReferenceType::get(arrTy.getEleTy()))
-    return emitOpError("return type does not match array");
-  mlir::Type ty = validArraySubobject(*this);
-  if (!ty || fir::ReferenceType::get(ty) != getType())
-    return emitOpError("return type and/or indices do not type check");
-  if (!validTypeParams(arrTy, getTypeparams()))
-    return emitOpError("invalid type parameters");
-  return mlir::success();
-}
-
-//===----------------------------------------------------------------------===//
-// ArrayUpdateOp
-//===----------------------------------------------------------------------===//
-
-llvm::LogicalResult fir::ArrayUpdateOp::verify() {
-  if (fir::isa_ref_type(getMerge().getType()))
-    return emitOpError("does not support reference type for merge");
-  auto arrTy = mlir::cast<fir::SequenceType>(getSequence().getType());
-  auto indSize = getIndices().size();
-  if (indSize < arrTy.getDimension())
-    return emitOpError("number of indices != dimension of array");
-  if (indSize == arrTy.getDimension() &&
-      ::adjustedElementType(getMerge().getType()) != arrTy.getEleTy())
-    return emitOpError("merged value does not have element type");
-  auto ty = validArraySubobject(*this);
-  if (!ty || ty != ::adjustedElementType(getMerge().getType()))
-    return emitOpError("merged value and/or indices do not type check");
-  if (!validTypeParams(arrTy, getTypeparams()))
-    return emitOpError("invalid type parameters");
-  return mlir::success();
-}
-
-//===----------------------------------------------------------------------===//
-// ArrayModifyOp
-//===----------------------------------------------------------------------===//
-
-llvm::LogicalResult fir::ArrayModifyOp::verify() {
-  auto arrTy = mlir::cast<fir::SequenceType>(getSequence().getType());
-  auto indSize = getIndices().size();
-  if (indSize < arrTy.getDimension())
-    return emitOpError("number of indices must match array dimension");
-  return mlir::success();
-}
-
 //===----------------------------------------------------------------------===//
 // BoxAddrOp
 //===----------------------------------------------------------------------===//

diff  --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir
index 9aebabff59e53..06d4d2206b74f 100644
--- a/flang/test/Fir/fir-ops.fir
+++ b/flang/test/Fir/fir-ops.fir
@@ -658,27 +658,8 @@ func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n :
   %arr3 = fir.insert_on_range %arr2, %c1_i32 from (2) to (9) : (!fir.array<10xi32>, i32) -> !fir.array<10xi32>
   fir.call @noret1(%arr3) : (!fir.array<10xi32>) -> ()
 
-  // CHECK: [[SHAPE:%.*]] = fir.shape_shift [[INDXM:%.*]], [[INDXN:%.*]], [[INDXO:%.*]], [[INDXP:%.*]] : (index, index, index, index) -> !fir.shapeshift<2>
-  // CHECK: [[AV1:%.*]] = fir.array_load [[ARR1]]([[SHAPE]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // CHECK: [[FVAL:%.*]] = fir.array_fetch [[AV1]], [[I10]], [[J20]] : (!fir.array<?x?xf32>, index, index) -> f32
-  // CHECK: [[AV2:%.*]] = fir.array_update [[AV1]], [[FVAL]], [[I10]], [[J20]] : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-  // CHECK: fir.array_merge_store [[AV1]], [[AV2]] to [[ARR1]] : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
+  // CHECK: fir.shape_shift [[INDXM]], [[INDXN]], [[INDXO]], [[INDXP]] : (index, index, index, index) -> !fir.shapeshift<2>
   %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %f = fir.array_fetch %av1, %i10, %j20 : (!fir.array<?x?xf32>, index, index) -> f32
-  %av2 = fir.array_update %av1, %f, %i10, %j20 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-  fir.array_merge_store %av1, %av2 to %arr1 : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
-
-  // CHECK: [[AV3:%.*]] = fir.array_load [[ARR1]]([[SHAPE]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // CHECK: [[FVAL2:%.*]] = fir.array_fetch [[AV3]], [[I10]], [[J20]] : (!fir.array<?x?xf32>, index, index) -> f32
-  // CHECK: [[AV4:%.*]]:2 = fir.array_modify [[AV3]], [[I10]], [[J20]] : (!fir.array<?x?xf32>, index, index) -> (!fir.ref<f32>, !fir.array<?x?xf32>)
-  // CHECK: fir.store [[FVAL2]] to [[AV4]]#0 : !fir.ref<f32>
-  // CHECK: fir.array_merge_store [[AV3]], [[AV4]]#1 to [[ARR1]] : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
-  %av3 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %f2 = fir.array_fetch %av3, %i10, %j20 : (!fir.array<?x?xf32>, index, index) -> f32
-  %addr, %av4 = fir.array_modify %av3, %i10, %j20 : (!fir.array<?x?xf32>, index, index) -> (!fir.ref<f32>, !fir.array<?x?xf32>)
-  fir.store %f2 to %addr : !fir.ref<f32>
-  fir.array_merge_store %av3, %av4 to %arr1 : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
   return
 }
 
@@ -813,29 +794,6 @@ func.func @load_invariant(%arg0: !fir.ref<i32>) -> i32 {
   return %0 : i32
 }
 
-func.func @array_access_ops(%a : !fir.ref<!fir.array<?x?xf32>>) {
-  %c1 = arith.constant 1 : index
-  %n = arith.constant 0 : index
-  %m = arith.constant 50 : index
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  %p = fir.array_access %v, %c1, %c1 : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
-  // CHECK: %{{.*}} = fir.array_access %{{.*}}, %{{.*}}, %{{.*}} : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
-  return
-}
-
-func.func @array_amend_ops(%a : !fir.ref<!fir.array<?x?xf32>>) {
-  %c1 = arith.constant 1 : index
-  %n = arith.constant 0 : index
-  %m = arith.constant 50 : index
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  %p = fir.array_access %v, %c1, %c1 : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
-  %res = fir.array_amend %v, %p : (!fir.array<?x?xf32>, !fir.ref<f32>) -> !fir.array<?x?xf32>
-  // CHECK: %{{.*}} = fir.array_amend %{{.*}}, %{{.*}} : (!fir.array<?x?xf32>, !fir.ref<f32>) -> !fir.array<?x?xf32>
-  return
-}
-
 func.func private @dispatch(%arg0: !fir.class<!fir.type<dispatch_derived1{a:i32,b:i32}>>, %arg1: i32) -> () {
   // CHECK-LABEL: func.func private @dispatch(
   // CHECK-SAME: %[[CLASS:.*]]: !fir.class<!fir.type<dispatch_derived1{a:i32,b:i32}>>, %[[INTARG:.*]]: i32)

diff  --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir
index 92280768e7154..ce31ceb3f069c 100644
--- a/flang/test/Fir/invalid.fir
+++ b/flang/test/Fir/invalid.fir
@@ -214,57 +214,6 @@ func.func @array_access(%arr : !fir.ref<!fir.array<?x?xf32>>) {
 
 // -----
 
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %c2 = arith.constant 2 : index
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  // expected-error at +1 {{'fir.array_load' op operand #0 must be any reference or box, but got 'index'}}
-  %av1 = fir.array_load %c2(%s) : (index, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<f32>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  // expected-error at +1 {{'fir.array_load' op must be a reference to an array}}
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<f32>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n: (index, index) -> !fir.shapeshift<1>
-  // expected-error at +1 {{'fir.array_load' op rank of dimension mismatched}}
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<1>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %c2 = arith.constant 2 : index
-  %shift = fir.shift %c2 : (index) -> !fir.shift<1>
-  // expected-error at +1 {{'fir.array_load' op shift can only be provided with fir.box memref}}
-  %av1 = fir.array_load %arr1(%shift) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shift<1>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %c47 = arith.constant 47 : index
-  %c78 = arith.constant 78 : index
-  %c3 = arith.constant 3 : index
-  %slice = fir.slice %c47, %c78, %c3 : (index,index,index) -> !fir.slice<1>
-  %s = fir.shape_shift %m, %n, %o, %p: (index, index, index, index) -> !fir.shapeshift<2>
-  // expected-error at +1 {{'fir.array_load' op rank of dimension in slice mismatched}}
-  %av1 = fir.array_load %arr1(%s)[%slice] : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, !fir.slice<1>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
 func.func @test_coordinate_of(%arr : !fir.ref<!fir.array<?x?xf32>>) {
   %1 = arith.constant 10 : i32
   // expected-error at +1 {{'fir.coordinate_of' op cannot find coordinate with unknown extents}}
@@ -647,84 +596,6 @@ func.func @bad_save_result(%buffer : !fir.ref<!fir.array<?xf32>>, %n :index) {
 
 // -----
 
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_fetch' op number of indices != dimension of array}}
-  %f = fir.array_fetch %av1, %m : (!fir.array<?x?xf32>, index) -> f32
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_fetch' op return type does not match array}}
-  %f = fir.array_fetch %av1, %m, %n : (!fir.array<?x?xf32>, index, index) -> i32
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %f = fir.array_fetch %av1, %m, %n : (!fir.array<?x?xf32>, index, index) -> f32
-  // expected-error at +1 {{'fir.array_update' op number of indices != dimension of array}}
-  %av2 = fir.array_update %av1, %f, %m : (!fir.array<?x?xf32>, f32, index) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %c0 = arith.constant 0 : i32
-  // expected-error at +1 {{'fir.array_update' op merged value does not have element type}}
-  %av2 = fir.array_update %av1, %c0, %m, %n : (!fir.array<?x?xf32>, i32, index, index) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index, %f: !fir.ref<i32>) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_update' op does not support reference type for merge}}
-  %av2 = fir.array_update %av1, %f, %m, %n : (!fir.array<?x?xf32>, !fir.ref<i32>, index, index) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @test_misc_ops(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index) {
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %f = fir.array_fetch %av1, %m, %n : (!fir.array<?x?xf32>, index, index) -> f32
-  %av2 = fir.array_update %av1, %f, %m, %n : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_merge_store' op operand #0 must be result of a fir.array_load op}}
-  fir.array_merge_store %av2, %av2 to %arr1 : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
-  return
-}
-
-// -----
-
-func.func @bad_array_modify(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index, %f : f32) {
-  %i10 = arith.constant 10 : index
-  %j20 = arith.constant 20 : index
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_modify' op number of indices must match array dimension}}
-  %addr, %av2 = fir.array_modify %av1, %i10 : (!fir.array<?x?xf32>, index) -> (!fir.ref<f32>, !fir.array<?x?xf32>)
-  fir.store %f to %addr : !fir.ref<f32>
-  fir.array_merge_store %av1, %av2 to %arr1 : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>
-  return
-}
-
-// -----
-
 func.func @slice_must_be_integral() {
   %0 = arith.constant 42 : i32
   %1 = fir.field_index field, !fir.type<t(param:i32){field:i32}> (%0 : i32)
@@ -746,86 +617,6 @@ func.func @array_coor_no_slice_substr(%a : !fir.ref<!fir.array<?x?xf32>>) {
 
 // -----
 
-func.func @array_coor_no_slice_substr(%a : !fir.ref<!fir.array<?x?xf32>>) {
-  %c1 = arith.constant 1 : index
-  %c10 = arith.constant 10 : index
-  %slice = fir.slice %c1, %c10, %c1 substr %c1, %c10 : (index, index, index, index, index) -> !fir.slice<1>
-  // expected-error at +1 {{'fir.array_load' op array_load cannot take a slice with substring}}
-  %v = fir.array_load %a[%slice] : (!fir.ref<!fir.array<?x?xf32>>, !fir.slice<1>) -> !fir.array<?x?xf32>
-  return
-}
-
-// -----
-
-func.func @array_merge_store_no_slice_substr(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m : index, %n : index, %o : index, %p : index, %f : f32) {
-  %i10 = arith.constant 10 : index
-  %j20 = arith.constant 20 : index
-  %c1 = arith.constant 1 : index
-  %c10 = arith.constant 10 : index
-  %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2>
-  %slice = fir.slice %c1, %c10, %c1 substr %c1, %c10 : (index, index, index, index, index) -> !fir.slice<1>
-  %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
-  %addr, %av2 = fir.array_modify %av1, %i10, %i10 : (!fir.array<?x?xf32>, index, index) -> (!fir.ref<f32>, !fir.array<?x?xf32>)
-  fir.store %f to %addr : !fir.ref<f32>
-  // expected-error at +1 {{'fir.array_merge_store' op array_merge_store cannot take a slice with substring}}
-  fir.array_merge_store %av1, %av2 to %arr1[%slice] : !fir.array<?x?xf32>, !fir.array<?x?xf32>, !fir.ref<!fir.array<?x?xf32>>, !fir.slice<1>
-  return
-}
-
-// -----
-
-func.func @array_access(%a : !fir.ref<!fir.array<?x?xf32>>) {
-  %c1 = arith.constant 1 : index
-  %n = arith.constant 0 : index
-  %m = arith.constant 50 : index
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_access' op number of indices != dimension of array}}
-  %p = fir.array_access %v, %c1 : (!fir.array<?x?xf32>, index) -> !fir.ref<f32>
-  return
-}
-
-// -----
-
-func.func @array_access(%a : !fir.ref<!fir.array<?x?xf32>>) {
-  %c1 = arith.constant 1 : index
-  %n = arith.constant 0 : index
-  %m = arith.constant 50 : index
-  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
-  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
-  // expected-error at +1 {{'fir.array_access' op return type does not match array}}
-  %p = fir.array_access %v, %c1, %c1 : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f64>
-  return
-}
-
-// -----
-
-func.func @foo(%arg0: !fir.ref<!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>>) {
-  %c1 = arith.constant 1 : index
-  %c0 = arith.constant 0 : index
-  %c9 = arith.constant 9 : index
-  %c19 = arith.constant 19 : index
-  %c30 = arith.constant 30 : index
-  %0 = fir.shape %c30 : (index) -> !fir.shape<1>
-  %1 = fir.array_load %arg0(%0) : (!fir.ref<!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>>, !fir.shape<1>) -> !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>
-  %2 = fir.do_loop %arg1 = %c1 to %c9 step %c1 unordered iter_args(%arg2 = %1) -> (!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>) {
-    %3 = fir.field_index c, !fir.type<t{c:!fir.array<20xi32>}>
-    %4 = fir.do_loop %arg3 = %c0 to %c19 step %c1 unordered iter_args(%arg4 = %arg2) -> (!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>) {
-      // expected-error at +1 {{'fir.array_access' op return type and/or indices do not type check}}
-      %5 = fir.array_access %1, %arg1, %3, %arg3 : (!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>, index, !fir.field, index) -> !fir.ref<f32>
-      %6 = fir.call @ifoo(%5) : (!fir.ref<f32>) -> i32
-      %7 = fir.array_update %arg4, %6, %arg1, %3, %arg3 : (!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>, i32, index, !fir.field, index) -> !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>
-      fir.result %7 : !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>
-    }
-    fir.result %4 : !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>
-  }
-  fir.array_merge_store %1, %2 to %arg0 : !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>, !fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>, !fir.ref<!fir.array<30x!fir.type<t{c:!fir.array<20xi32>}>>>
-  return
-}
-func.func private @ifoo(!fir.ref<f32>) -> i32
-
-// -----
-
 func.func private @dispatch(%arg0: !fir.class<!fir.type<derived{a:i32,b:i32}>>) -> () {
   // expected-error at +1 {{'fir.dispatch' op pass_arg_pos must be smaller than the number of operands}}
   fir.dispatch "proc1"(%arg0 : !fir.class<!fir.type<derived{a:i32,b:i32}>>) (%arg0 : !fir.class<!fir.type<derived{a:i32,b:i32}>>) {pass_arg_pos = 1 : i32}

diff  --git a/flang/test/HLFIR/inline-elemental.fir b/flang/test/HLFIR/inline-elemental.fir
index 2d3beace4c759..0c8c4cce3bef3 100644
--- a/flang/test/HLFIR/inline-elemental.fir
+++ b/flang/test/HLFIR/inline-elemental.fir
@@ -81,18 +81,16 @@ func.func @inline_to_loop(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "
     %12 = arith.muli %10, %11 : i32
     hlfir.yield_element %12 : i32
   }
-  %array = fir.array_load %0#0 : (!fir.box<!fir.array<?xi32>>) -> !fir.array<?xi32>
   %c1 = arith.constant 1 : index
   %max = arith.subi %4#1, %c1 : index
-  %7 = fir.do_loop %arg4 = %c0 to %max step %c1 unordered iter_args(%arg5 = %array) -> (!fir.array<?xi32>) {
+  fir.do_loop %arg4 = %c0 to %max step %c1 unordered {
     %8 = hlfir.apply %6, %arg4 : (!hlfir.expr<?xi32>, index) -> i32
     %9 = hlfir.designate %3#0 (%arg4)  : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
     %10 = fir.load %9 : !fir.ref<i32>
     %11 = arith.addi %8, %10 : i32
-    %12 = fir.array_update %arg5, %11, %arg4 : (!fir.array<?xi32>, i32, index) -> !fir.array<?xi32>
-    fir.result %12 : !fir.array<?xi32>
+    %12 = hlfir.designate %0#0 (%arg4)  : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
+    fir.store %11 to %12 : !fir.ref<i32>
   }
-  fir.array_merge_store %array, %7 to %arg0 : !fir.array<?xi32>, !fir.array<?xi32>, !fir.box<!fir.array<?xi32>>
   hlfir.destroy %6 : !hlfir.expr<?xi32>
   return
 }
@@ -108,9 +106,8 @@ func.func @inline_to_loop(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "
 // CHECK-DAG:     %[[C:.*]]:2 = hlfir.declare %[[C_ARG]]
 // CHECK-DAG:     %[[D:.*]]:2 = hlfir.declare %[[D_ARG]]
 // CHECK-NEXT:    %[[B_DIM0:.*]]:3 = fir.box_dims %[[B]]#0, %[[C0]]
-// CHECK-NEXT:    %[[ARRAY:.*]] = fir.array_load %[[A]]#0
 // CHECK-NEXT:    %[[MAX:.*]] = arith.subi %[[B_DIM0]]#1, %[[C1]]
-// CHECK-NEXT:    %[[LOOP:.*]] = fir.do_loop %[[I:.*]] = %[[C0]] to %[[MAX]] step %[[C1]] unordered iter_args(%[[LOOP_ARRAY:.*]] = %[[ARRAY]])
+// CHECK-NEXT:    fir.do_loop %[[I:.*]] = %[[C0]] to %[[MAX]] step %[[C1]] unordered {
 // inline the elemental:
 // CHECK-NEXT:      %[[B_I_REF:.*]] = hlfir.designate %[[B]]#0 (%[[I]])
 // CHECK-NEXT:      %[[C_I_REF:.*]] = hlfir.designate %[[C]]#0 (%[[I]])
@@ -121,10 +118,9 @@ func.func @inline_to_loop(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "
 // CHECK-NEXT:      %[[D_I_REF:.*]] = hlfir.designate %[[D]]#0 (%[[I]])
 // CHECK-NEXT:      %[[D_I:.*]] = fir.load %[[D_I_REF]]
 // CHECK-NEXT:      %[[ADD:.*]] = arith.addi %[[MUL]], %[[D_I]]
-// CHECK-NEXT:      %[[ARRAY_UPD:.*]] = fir.array_update %[[LOOP_ARRAY]], %[[ADD]], %[[I]]
-// CHECK-NEXT:      fir.result %[[ARRAY_UPD]]
+// CHECK-NEXT:      %[[A_I_REF:.*]] = hlfir.designate %[[A]]#0 (%[[I]])
+// CHECK-NEXT:      fir.store %[[ADD]] to %[[A_I_REF]]
 // CHECK-NEXT:    }
-// CHECK-NEXT:    fir.array_merge_store %[[ARRAY]], %[[LOOP]] to %[[A_ARG]]
 // CHECK-NEXT:    return
 // CHECK-NEXT:  }
 

diff  --git a/flang/test/Transforms/loop-versioning.fir b/flang/test/Transforms/loop-versioning.fir
index cf601fc49b998..fc67f2e087b25 100644
--- a/flang/test/Transforms/loop-versioning.fir
+++ b/flang/test/Transforms/loop-versioning.fir
@@ -192,9 +192,6 @@ func.func @sum1dfixed(%arg0: !fir.ref<!fir.array<?xf64>> {fir.bindc_name = "a"},
   func.func @test4(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a"}, %arg1: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "b"}, %arg2: !fir.ref<i32> {fir.bindc_name = "n1"}, %arg3: !fir.ref<i32> {fir.bindc_name = "m1"}) {
     %0 = fir.alloca index {bindc_name = ".buff.pos"}
     %1 = fir.alloca index {bindc_name = ".buff.size"}
-    %c0 = arith.constant 0 : index
-    %2:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-    %3 = fir.array_load %arg0 : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32>
     %c0_0 = arith.constant 0 : index
     fir.store %c0_0 to %0 : !fir.ref<index>
     %c32 = arith.constant 32 : index
@@ -243,18 +240,6 @@ func.func @sum1dfixed(%arg0: !fir.ref<!fir.array<?xf64>> {fir.bindc_name = "a"},
       fir.result %26 : !fir.heap<f32>
     }
     %13 = fir.convert %12 : (!fir.heap<f32>) -> !fir.heap<!fir.array<?xf32>>
-    %14 = fir.load %0 : !fir.ref<index>
-    %15 = fir.shape %14 : (index) -> !fir.shape<1>
-    %16 = fir.array_load %13(%15) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.array<?xf32>
-    %c1 = arith.constant 1 : index
-    %c0_1 = arith.constant 0 : index
-    %17 = arith.subi %2#1, %c1 : index
-    %18 = fir.do_loop %arg4 = %c0_1 to %17 step %c1 unordered iter_args(%arg5 = %3) -> (!fir.array<?xf32>) {
-      %19 = fir.array_fetch %16, %arg4 : (!fir.array<?xf32>, index) -> f32
-      %20 = fir.array_update %arg5, %19, %arg4 : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
-      fir.result %20 : !fir.array<?xf32>
-    }
-    fir.array_merge_store %3, %18 to %arg0 : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.array<?xf32>>
     fir.freemem %13 : !fir.heap<!fir.array<?xf32>>
     return
   }

diff  --git a/flang/test/Transforms/simplifyintrinsics.fir b/flang/test/Transforms/simplifyintrinsics.fir
index 1cfda08e39694..2ef470f7f2ebd 100644
--- a/flang/test/Transforms/simplifyintrinsics.fir
+++ b/flang/test/Transforms/simplifyintrinsics.fir
@@ -1220,7 +1220,6 @@ func.func @_QMtestPcount_generate_mask(%arg0: !fir.ref<!fir.array<10x10x!fir.log
   %c10_1 = arith.constant 10 : index
   %1 = fir.alloca !fir.array<10xi32> {bindc_name = "res", uniq_name = "_QMtestFcount_generate_maskEres"}
   %2 = fir.shape %c10_1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.array<10xi32>
   %c2_i32 = arith.constant 2 : i32
   %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10x!fir.logical<4>>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10x!fir.logical<4>>>
@@ -1242,16 +1241,9 @@ func.func @_QMtestPcount_generate_mask(%arg0: !fir.ref<!fir.array<10x10x!fir.log
   %16:3 = fir.box_dims %15, %c0_2 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %17 = fir.box_addr %15 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %18 = fir.shape_shift %16#0, %16#1 : (index, index) -> !fir.shapeshift<1>
-  %19 = fir.array_load %17(%18) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1 = arith.constant 1 : index
   %c0_3 = arith.constant 0 : index
   %20 = arith.subi %c10_1, %c1 : index
-  %21 = fir.do_loop %arg1 = %c0_3 to %20 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<10xi32>) {
-    %23 = fir.array_fetch %19, %arg1 : (!fir.array<?xi32>, index) -> i32
-    %24 = fir.array_update %arg2, %23, %arg1 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>
-    fir.result %24 : !fir.array<10xi32>
-  }
-  fir.array_merge_store %3, %21 to %1 : !fir.array<10xi32>, !fir.array<10xi32>, !fir.ref<!fir.array<10xi32>>
   fir.freemem %17 : !fir.heap<!fir.array<?xi32>>
   %22 = fir.load %1 : !fir.ref<!fir.array<10xi32>>
   return %22 : !fir.array<10xi32>
@@ -1405,7 +1397,6 @@ func.func @_QPtestAny_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>>
   %c10_1 = arith.constant 10 : index
   %1 = fir.alloca !fir.array<10x!fir.logical<4>> {bindc_name = "testAny_DimArg", uniq_name = "_QFtestAny_DimArgEtestAny_DimArg"}
   %2 = fir.shape %c10_1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.array<10x!fir.logical<4>>
   %c2_i32 = arith.constant 2 : i32
   %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10x!fir.logical<4>>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10x!fir.logical<4>>>
@@ -1425,16 +1416,9 @@ func.func @_QPtestAny_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>>
   %15:3 = fir.box_dims %14, %c0_2 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, index) -> (index, index, index)
   %16 = fir.box_addr %14 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>) -> !fir.heap<!fir.array<?x!fir.logical<4>>>
   %17 = fir.shape_shift %15#0, %15#1 : (index, index) -> !fir.shapeshift<1>
-  %18 = fir.array_load %16(%17) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.array<?x!fir.logical<4>>
   %c1 = arith.constant 1 : index
   %c0_3 = arith.constant 0 : index
   %19 = arith.subi %c10_1, %c1 : index
-  %20 = fir.do_loop %arg1 = %c0_3 to %19 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<10x!fir.logical<4>>) {
-    %22 = fir.array_fetch %18, %arg1 : (!fir.array<?x!fir.logical<4>>, index) -> !fir.logical<4>
-    %23 = fir.array_update %arg2, %22, %arg1 : (!fir.array<10x!fir.logical<4>>, !fir.logical<4>, index) -> !fir.array<10x!fir.logical<4>>
-    fir.result %23 : !fir.array<10x!fir.logical<4>>
-  }
-  fir.array_merge_store %3, %20 to %1 : !fir.array<10x!fir.logical<4>>, !fir.array<10x!fir.logical<4>>, !fir.ref<!fir.array<10x!fir.logical<4>>>
   fir.freemem %16 : !fir.heap<!fir.array<?x!fir.logical<4>>>
   %21 = fir.load %1 : !fir.ref<!fir.array<10x!fir.logical<4>>>
   return %21 : !fir.array<10x!fir.logical<4>>
@@ -1644,7 +1628,6 @@ func.func @_QPtestAll_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>>
   %c10_1 = arith.constant 10 : index
   %1 = fir.alloca !fir.array<10x!fir.logical<4>> {bindc_name = "testAll_DimArg", uniq_name = "_QFtestAll_DimArgEtestAll_DimArg"}
   %2 = fir.shape %c10_1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.array<10x!fir.logical<4>>
   %c1_i32 = arith.constant 1 : i32
   %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10x!fir.logical<4>>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10x!fir.logical<4>>>
@@ -1664,16 +1647,9 @@ func.func @_QPtestAll_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>>
   %15:3 = fir.box_dims %14, %c0_2 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, index) -> (index, index, index)
   %16 = fir.box_addr %14 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>) -> !fir.heap<!fir.array<?x!fir.logical<4>>>
   %17 = fir.shape_shift %15#0, %15#1 : (index, index) -> !fir.shapeshift<1>
-  %18 = fir.array_load %16(%17) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.array<?x!fir.logical<4>>
   %c1 = arith.constant 1 : index
   %c0_3 = arith.constant 0 : index
   %19 = arith.subi %c10_1, %c1 : index
-  %20 = fir.do_loop %arg1 = %c0_3 to %19 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<10x!fir.logical<4>>) {
-    %22 = fir.array_fetch %18, %arg1 : (!fir.array<?x!fir.logical<4>>, index) -> !fir.logical<4>
-    %23 = fir.array_update %arg2, %22, %arg1 : (!fir.array<10x!fir.logical<4>>, !fir.logical<4>, index) -> !fir.array<10x!fir.logical<4>>
-    fir.result %23 : !fir.array<10x!fir.logical<4>>
-  }
-  fir.array_merge_store %3, %20 to %1 : !fir.array<10x!fir.logical<4>>, !fir.array<10x!fir.logical<4>>, !fir.ref<!fir.array<10x!fir.logical<4>>>
   fir.freemem %16 : !fir.heap<!fir.array<?x!fir.logical<4>>>
   %21 = fir.load %1 : !fir.ref<!fir.array<10x!fir.logical<4>>>
   return %21 : !fir.array<10x!fir.logical<4>>
@@ -1695,7 +1671,6 @@ func.func @_QPtestminloc_works1d(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_works1d", uniq_name = "_QFtestminloc_works1dEtestminloc_works1d"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
   %6 = fir.shape %c10_0 : (index) -> !fir.shape<1>
@@ -1720,16 +1695,9 @@ func.func @_QPtestminloc_works1d(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_
   %19:3 = fir.box_dims %18, %c0_1 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %20 = fir.box_addr %18 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %21 = fir.shape_shift %19#0, %19#1 : (index, index) -> !fir.shapeshift<1>
-  %22 = fir.array_load %20(%21) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_2 = arith.constant 1 : index
   %c0_3 = arith.constant 0 : index
   %23 = arith.subi %c1, %c1_2 : index
-  %24 = fir.do_loop %arg2 = %c0_3 to %23 step %c1_2 unordered iter_args(%arg3 = %3) -> (!fir.array<1xi32>) {
-    %26 = fir.array_fetch %22, %arg2 : (!fir.array<?xi32>, index) -> i32
-    %27 = fir.array_update %arg3, %26, %arg2 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %27 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %24 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %20 : !fir.heap<!fir.array<?xi32>>
   %25 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %25 : !fir.array<1xi32>
@@ -1820,7 +1788,6 @@ func.func @_QPtestminloc_works2d_nomask(%arg0: !fir.ref<!fir.array<10x10xi32>> {
   %c2 = arith.constant 2 : index
   %1 = fir.alloca !fir.array<2xi32> {bindc_name = "testminloc_works2d_nomask", uniq_name = "_QFtestminloc_works2d_nomaskEtestminloc_works2d_nomask"}
   %2 = fir.shape %c2 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.array<2xi32>
   %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10xi32>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>>
   %c8_i32 = arith.constant 8 : i32
@@ -1843,17 +1810,9 @@ func.func @_QPtestminloc_works2d_nomask(%arg0: !fir.ref<!fir.array<10x10xi32>> {
   %17:3 = fir.box_dims %16, %c0_1 : (!fir.box<!fir.heap<!fir.array<?xi64>>>, index) -> (index, index, index)
   %18 = fir.box_addr %16 : (!fir.box<!fir.heap<!fir.array<?xi64>>>) -> !fir.heap<!fir.array<?xi64>>
   %19 = fir.shape_shift %17#0, %17#1 : (index, index) -> !fir.shapeshift<1>
-  %20 = fir.array_load %18(%19) : (!fir.heap<!fir.array<?xi64>>, !fir.shapeshift<1>) -> !fir.array<?xi64>
   %c1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %21 = arith.subi %c2, %c1 : index
-  %22 = fir.do_loop %arg1 = %c0_2 to %21 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<2xi32>) {
-    %24 = fir.array_fetch %20, %arg1 : (!fir.array<?xi64>, index) -> i64
-    %25 = fir.convert %24 : (i64) -> i32
-    %26 = fir.array_update %arg2, %25, %arg1 : (!fir.array<2xi32>, i32, index) -> !fir.array<2xi32>
-    fir.result %26 : !fir.array<2xi32>
-  }
-  fir.array_merge_store %3, %22 to %1 : !fir.array<2xi32>, !fir.array<2xi32>, !fir.ref<!fir.array<2xi32>>
   fir.freemem %18 : !fir.heap<!fir.array<?xi64>>
   %23 = fir.load %1 : !fir.ref<!fir.array<2xi32>>
   return %23 : !fir.array<2xi32>
@@ -1939,7 +1898,6 @@ func.func @_QPtestminloc_works1d_scalarmask_f64(%arg0: !fir.ref<!fir.array<10xf6
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_works1d_scalarmask_f64", uniq_name = "_QFtestminloc_works1d_scalarmask_f64Etestminloc_works1d_scalarmask_f64"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>>
   %6 = fir.embox %arg1 : (!fir.ref<!fir.logical<4>>) -> !fir.box<!fir.logical<4>>
@@ -1963,16 +1921,9 @@ func.func @_QPtestminloc_works1d_scalarmask_f64(%arg0: !fir.ref<!fir.array<10xf6
   %18:3 = fir.box_dims %17, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %19 = fir.box_addr %17 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %20 = fir.shape_shift %18#0, %18#1 : (index, index) -> !fir.shapeshift<1>
-  %21 = fir.array_load %19(%20) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %22 = arith.subi %c1, %c1_1 : index
-  %23 = fir.do_loop %arg2 = %c0_2 to %22 step %c1_1 unordered iter_args(%arg3 = %3) -> (!fir.array<1xi32>) {
-    %25 = fir.array_fetch %21, %arg2 : (!fir.array<?xi32>, index) -> i32
-    %26 = fir.array_update %arg3, %25, %arg2 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %26 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %23 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %19 : !fir.heap<!fir.array<?xi32>>
   %24 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %24 : !fir.array<1xi32>
@@ -2051,7 +2002,6 @@ func.func @_QPtestminloc_doesntwork1d_back(%arg0: !fir.ref<!fir.array<10xi32>> {
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_doesntwork1d_back", uniq_name = "_QFtestminloc_doesntwork1d_backEtestminloc_doesntwork1d_back"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
   %true = arith.constant true
@@ -2075,16 +2025,9 @@ func.func @_QPtestminloc_doesntwork1d_back(%arg0: !fir.ref<!fir.array<10xi32>> {
   %18:3 = fir.box_dims %17, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %19 = fir.box_addr %17 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %20 = fir.shape_shift %18#0, %18#1 : (index, index) -> !fir.shapeshift<1>
-  %21 = fir.array_load %19(%20) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %22 = arith.subi %c1, %c1_1 : index
-  %23 = fir.do_loop %arg1 = %c0_2 to %22 step %c1_1 unordered iter_args(%arg2 = %3) -> (!fir.array<1xi32>) {
-    %25 = fir.array_fetch %21, %arg1 : (!fir.array<?xi32>, index) -> i32
-    %26 = fir.array_update %arg2, %25, %arg1 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %26 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %23 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %19 : !fir.heap<!fir.array<?xi32>>
   %24 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %24 : !fir.array<1xi32>
@@ -2105,7 +2048,6 @@ func.func @_QPtestminloc_1d_dim(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_n
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_1d_dim", uniq_name = "_QFtestminloc_1d_dimEtestminloc_1d_dim"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
   %c1_i32 = arith.constant 1 : i32
@@ -2130,11 +2072,6 @@ func.func @_QPtestminloc_1d_dim(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_n
   %c1_0 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %19 = arith.subi %c1, %c1_0 : index
-  %20 = fir.do_loop %arg1 = %c0 to %19 step %c1_0 unordered iter_args(%arg2 = %3) -> (!fir.array<1xi32>) {
-    %22 = fir.array_update %arg2, %18, %arg1 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %22 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %20 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   %21 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %21 : !fir.array<1xi32>
 }
@@ -2203,7 +2140,6 @@ func.func @_QPtestminloc_doesntwork1d_unknownsize(%arg0: !fir.box<!fir.array<?xi
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_doesntwork1d_unknownsize", uniq_name = "_QFtestminloc_doesntwork1d_unknownsizeEtestminloc_doesntwork1d_unknownsize"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.absent !fir.box<i1>
   %c4 = arith.constant 4 : index
   %false = arith.constant false
@@ -2225,16 +2161,9 @@ func.func @_QPtestminloc_doesntwork1d_unknownsize(%arg0: !fir.box<!fir.array<?xi
   %16:3 = fir.box_dims %15, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %17 = fir.box_addr %15 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %18 = fir.shape_shift %16#0, %16#1 : (index, index) -> !fir.shapeshift<1>
-  %19 = fir.array_load %17(%18) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %20 = arith.subi %c1, %c1_1 : index
-  %21 = fir.do_loop %arg1 = %c0_2 to %20 step %c1_1 unordered iter_args(%arg2 = %3) -> (!fir.array<1xi32>) {
-    %23 = fir.array_fetch %19, %arg1 : (!fir.array<?xi32>, index) -> i32
-    %24 = fir.array_update %arg2, %23, %arg1 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %24 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %21 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %17 : !fir.heap<!fir.array<?xi32>>
   %22 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %22 : !fir.array<1xi32>
@@ -2256,7 +2185,6 @@ func.func @_QPtestminloc_doesntwork1d_chars(%arg0: !fir.boxchar<1> {fir.bindc_na
   %c1 = arith.constant 1 : index
   %3 = fir.alloca !fir.array<1xi32> {bindc_name = "testminloc_doesntwork1d_chars", uniq_name = "_QFtestminloc_doesntwork1d_charsEtestminloc_doesntwork1d_chars"}
   %4 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %5 = fir.array_load %3(%4) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %6 = fir.shape %c10 : (index) -> !fir.shape<1>
   %7 = fir.embox %2(%6) : (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.char<1>>>
   %8 = fir.absent !fir.box<i1>
@@ -2280,16 +2208,9 @@ func.func @_QPtestminloc_doesntwork1d_chars(%arg0: !fir.boxchar<1> {fir.bindc_na
   %20:3 = fir.box_dims %19, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %21 = fir.box_addr %19 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %22 = fir.shape_shift %20#0, %20#1 : (index, index) -> !fir.shapeshift<1>
-  %23 = fir.array_load %21(%22) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %24 = arith.subi %c1, %c1_1 : index
-  %25 = fir.do_loop %arg1 = %c0_2 to %24 step %c1_1 unordered iter_args(%arg2 = %5) -> (!fir.array<1xi32>) {
-    %27 = fir.array_fetch %23, %arg1 : (!fir.array<?xi32>, index) -> i32
-    %28 = fir.array_update %arg2, %27, %arg1 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %28 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %5, %25 to %3 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %21 : !fir.heap<!fir.array<?xi32>>
   %26 = fir.load %3 : !fir.ref<!fir.array<1xi32>>
   return %26 : !fir.array<1xi32>
@@ -2327,7 +2248,6 @@ func.func @_QPtestminloc_doesntwork1d_unknownmask(%arg0: !fir.ref<!fir.array<10x
   %c1_0 = arith.constant 1 : index
   fir.store %c1_0 to %4 : !fir.ref<index>
   %13 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %14 = fir.array_load %7(%13) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %15 = fir.shape %c10 : (index) -> !fir.shape<1>
   %16 = fir.embox %arg0(%15) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
   %17 = fir.load %3 : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
@@ -2361,16 +2281,9 @@ func.func @_QPtestminloc_doesntwork1d_unknownmask(%arg0: !fir.ref<!fir.array<10x
   %38:3 = fir.box_dims %37, %c0_2 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %39 = fir.box_addr %37 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %40 = fir.shape_shift %38#0, %38#1 : (index, index) -> !fir.shapeshift<1>
-  %41 = fir.array_load %39(%40) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_3 = arith.constant 1 : index
   %c0_4 = arith.constant 0 : index
   %42 = arith.subi %c1, %c1_3 : index
-  %43 = fir.do_loop %arg1 = %c0_4 to %42 step %c1_3 unordered iter_args(%arg2 = %14) -> (!fir.array<1xi32>) {
-    %45 = fir.array_fetch %41, %arg1 : (!fir.array<?xi32>, index) -> i32
-    %46 = fir.array_update %arg2, %45, %arg1 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %46 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %14, %43 to %7 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %39 : !fir.heap<!fir.array<?xi32>>
   %44 = fir.load %7 : !fir.ref<!fir.array<1xi32>>
   return %44 : !fir.array<1xi32>
@@ -2391,7 +2304,6 @@ func.func @_QPtestmaxloc_works1d(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testmaxloc_works1d", uniq_name = "_QFtestmaxloc_works1dEtestmaxloc_works1d"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
   %6 = fir.shape %c10_0 : (index) -> !fir.shape<1>
@@ -2416,16 +2328,9 @@ func.func @_QPtestmaxloc_works1d(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_
   %19:3 = fir.box_dims %18, %c0_1 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %20 = fir.box_addr %18 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %21 = fir.shape_shift %19#0, %19#1 : (index, index) -> !fir.shapeshift<1>
-  %22 = fir.array_load %20(%21) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_2 = arith.constant 1 : index
   %c0_3 = arith.constant 0 : index
   %23 = arith.subi %c1, %c1_2 : index
-  %24 = fir.do_loop %arg2 = %c0_3 to %23 step %c1_2 unordered iter_args(%arg3 = %3) -> (!fir.array<1xi32>) {
-    %26 = fir.array_fetch %22, %arg2 : (!fir.array<?xi32>, index) -> i32
-    %27 = fir.array_update %arg3, %26, %arg2 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %27 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %24 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %20 : !fir.heap<!fir.array<?xi32>>
   %25 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %25 : !fir.array<1xi32>
@@ -2515,7 +2420,6 @@ func.func @_QPtestmaxloc_works1d_scalarmask_f64(%arg0: !fir.ref<!fir.array<10xf6
   %c1 = arith.constant 1 : index
   %1 = fir.alloca !fir.array<1xi32> {bindc_name = "testmaxloc_works1d_scalarmask_f64", uniq_name = "_QFtestmaxloc_works1d_scalarmask_f64Etestminloc_works1d_scalarmask_f64"}
   %2 = fir.shape %c1 : (index) -> !fir.shape<1>
-  %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.array<1xi32>
   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
   %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>>
   %6 = fir.embox %arg1 : (!fir.ref<!fir.logical<4>>) -> !fir.box<!fir.logical<4>>
@@ -2539,16 +2443,9 @@ func.func @_QPtestmaxloc_works1d_scalarmask_f64(%arg0: !fir.ref<!fir.array<10xf6
   %18:3 = fir.box_dims %17, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
   %19 = fir.box_addr %17 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   %20 = fir.shape_shift %18#0, %18#1 : (index, index) -> !fir.shapeshift<1>
-  %21 = fir.array_load %19(%20) : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> !fir.array<?xi32>
   %c1_1 = arith.constant 1 : index
   %c0_2 = arith.constant 0 : index
   %22 = arith.subi %c1, %c1_1 : index
-  %23 = fir.do_loop %arg2 = %c0_2 to %22 step %c1_1 unordered iter_args(%arg3 = %3) -> (!fir.array<1xi32>) {
-    %25 = fir.array_fetch %21, %arg2 : (!fir.array<?xi32>, index) -> i32
-    %26 = fir.array_update %arg3, %25, %arg2 : (!fir.array<1xi32>, i32, index) -> !fir.array<1xi32>
-    fir.result %26 : !fir.array<1xi32>
-  }
-  fir.array_merge_store %3, %23 to %1 : !fir.array<1xi32>, !fir.array<1xi32>, !fir.ref<!fir.array<1xi32>>
   fir.freemem %19 : !fir.heap<!fir.array<?xi32>>
   %24 = fir.load %1 : !fir.ref<!fir.array<1xi32>>
   return %24 : !fir.array<1xi32>


        


More information about the flang-commits mailing list