[flang-commits] [flang] [flang] Delete the legacy array-value operations from FIR (PR #213159)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Thu Jul 30 20:26:30 PDT 2026
https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/213159
>From 4f2db932024306254a7c0b3cee36f8c57511f1c6 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 30 Jul 2026 15:49:56 -0400
Subject: [PATCH 1/2] [flang] Delete the legacy array-value operations from FIR
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.
---
flang/docs/FIRArrayOperations.md | 343 ---------------
flang/docs/HighLevelFIR.md | 19 +-
flang/docs/ReleaseNotes.md | 10 +
flang/docs/index.md | 1 -
.../flang/Optimizer/Builder/MutableBox.h | 3 +-
.../include/flang/Optimizer/Dialect/FIROps.td | 400 ------------------
flang/lib/Optimizer/Dialect/FIROps.cpp | 212 ----------
flang/test/Fir/fir-ops.fir | 44 +-
flang/test/Fir/invalid.fir | 209 ---------
flang/test/HLFIR/inline-elemental.fir | 16 +-
flang/test/Transforms/loop-versioning.fir | 15 -
flang/test/Transforms/simplifyintrinsics.fir | 103 -----
12 files changed, 28 insertions(+), 1347 deletions(-)
delete mode 100644 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 different 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..9fa47298ea18d 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1544,406 +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
-//===----------------------------------------------------------------------===//
-
def fir_ArrayCoorOp
: fir_Op<"array_coor", [NoMemoryEffect, AttrSizedOperandSegments,
fir_FortranObjectViewOpInterface]> {
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>
>From 38272c7f7757573b5a069f499828714e6d38e509 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 30 Jul 2026 19:14:36 -0400
Subject: [PATCH 2/2] [flang] Reinstate the "Record and array type operations"
banner
The deletion range for the array-value operations also swept the
section banner that groups fir.array_coor and the record/array
addressing operations that follow it, leaving them visually grouped
under the earlier box-operations banner. Comment-only change.
---
flang/include/flang/Optimizer/Dialect/FIROps.td | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 9fa47298ea18d..7635e3bf82035 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1544,6 +1544,10 @@ def fir_BoxTypeDescOp : fir_SimpleOneResultOp<"box_tdesc", [NoMemoryEffect]> {
let results = (outs fir_TypeDescType);
}
+//===----------------------------------------------------------------------===//
+// Record and array type operations
+//===----------------------------------------------------------------------===//
+
def fir_ArrayCoorOp
: fir_Op<"array_coor", [NoMemoryEffect, AttrSizedOperandSegments,
fir_FortranObjectViewOpInterface]> {
More information about the flang-commits
mailing list