diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -1595,6 +1595,40 @@ let verifier = "return ::verify(*this);"; } +def fir_ArrayAmendOp : fir_Op<"array_amend", [NoSideEffect]> { + 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. + + ```mlir + // fetch the value of one of the array value's elements + %1 = fir.array_access %v, %i, %j : (!fir.array, index, index) -> !fir.ref + // 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, !fir.ref) -> !fir.array + ``` + + 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]> { diff --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir --- a/flang/test/Fir/fir-ops.fir +++ b/flang/test/Fir/fir-ops.fir @@ -758,3 +758,15 @@ // CHECK: %{{.*}} = fir.array_access %{{.*}}, %{{.*}}, %{{.*}} : (!fir.array, index, index) -> !fir.ref return } + +func @array_amend_ops(%a : !fir.ref>) { + %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.shape<2>) -> !fir.array + %p = fir.array_access %v, %c1, %c1 : (!fir.array, index, index) -> !fir.ref + %res = fir.array_amend %v, %p : (!fir.array, !fir.ref) -> !fir.array + // CHECK: %{{.*}} = fir.array_amend %{{.*}}, %{{.*}} : (!fir.array, !fir.ref) -> !fir.array + return +}