@@ -826,9 +826,9 @@ def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> {
826
826
let assemblyFormat = "$resval attr-dict `:` type($resval)";
827
827
}
828
828
829
- //===------------------------------------------------------------------------ ===//
829
+ //===----------------------------------------------------------------------===//
830
830
// Operations on !fir.box<T> type objects
831
- //===------------------------------------------------------------------------ ===//
831
+ //===----------------------------------------------------------------------===//
832
832
833
833
def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
834
834
let summary = "boxes a given reference and (optional) dimension information";
@@ -891,26 +891,27 @@ def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
891
891
}
892
892
893
893
def fir_ReboxOp : fir_Op<"rebox", [NoSideEffect, AttrSizedOperandSegments]> {
894
- let summary = "create a box given another box and (optional) dimension information";
894
+ let summary =
895
+ "create a box given another box and (optional) dimension information";
895
896
896
897
let description = [{
897
- Create a new boxed reference value from another box. This is meant to be used
898
- when the taking a reference to part of a boxed value, or to an entire boxed value with
899
- new shape or type information.
898
+ Create a new boxed reference value from another box. This is meant to be
899
+ used when the taking a reference to part of a boxed value, or to an entire
900
+ boxed value with new shape or type information.
900
901
901
902
The new extra information can be:
902
903
- new shape information (new lower bounds, new rank, or new extents.
903
904
New rank/extents can only be provided if the original fir.box is
904
- contiguous in all dimension but maybe the first one ). The shape
905
+ contiguous in all dimension but maybe the first row ). The shape
905
906
operand must be provided to set new shape information.
906
- - new type (only for derived types). It is possible to set the dynamic type
907
- of the new box to one of the parent types of the input box dynamic type.
908
- Type parameters cannot be changed. This change is reflected in the requested
909
- result type of the new box.
907
+ - new type (only for derived types). It is possible to set the dynamic
908
+ type of the new box to one of the parent types of the input box dynamic
909
+ type. Type parameters cannot be changed. This change is reflected in
910
+ the requested result type of the new box.
910
911
911
- A slice argument can be provided to build a reference to part of a boxed value.
912
- In this case, the shape operand must be absent or be a fir.shift that can be
913
- used to provide a non default origin for the slice.
912
+ A slice argument can be provided to build a reference to part of a boxed
913
+ value. In this case, the shape operand must be absent or be a fir.shift
914
+ that can be used to provide a non default origin for the slice.
914
915
915
916
The following example illustrates creating a fir.box for x(10:33:2)
916
917
where x is described by a fir.box and has non default lower bounds,
@@ -1342,6 +1343,16 @@ def fir_ArrayLoadOp : fir_Op<"array_load", [AttrSizedOperandSegments]> {
1342
1343
let summary = "Load an array as a value.";
1343
1344
1344
1345
let description = [{
1346
+ This operation taken with array_merge_store captures Fortran's
1347
+ copy-in/copy-out semantics. One way to think of this is that array_load
1348
+ creates a snapshot copy of the entire array. This copy can then be used
1349
+ as the "original value" of the array while the array's new value is
1350
+ computed. The array_merge_store operation is the copy-out semantics, which
1351
+ merge the updates with the original array value to produce the final array
1352
+ result. This abstracts the copy operations as opposed to always creating
1353
+ copies or requiring dependence analysis be performed on the syntax trees
1354
+ and before lowering to the IR.
1355
+
1345
1356
Load an entire array as a single SSA value.
1346
1357
1347
1358
```fortran
@@ -1540,6 +1551,81 @@ def fir_ArrayModifyOp : fir_Op<"array_modify", [AttrSizedOperandSegments,
1540
1551
let verifier = [{ return ::verify(*this); }];
1541
1552
}
1542
1553
1554
+ def fir_ArrayAccessOp : fir_Op<"array_access", [AttrSizedOperandSegments,
1555
+ NoSideEffect]> {
1556
+ let summary = "Fetch the reference of an element of an array value";
1557
+
1558
+ let description = [{
1559
+ Fetch the memory reference of an element in an array value.
1560
+
1561
+ ```fortran
1562
+ real :: a(n,m)
1563
+ ...
1564
+ ... a ...
1565
+ ... a(r,s+1) ...
1566
+ ```
1567
+
1568
+ One can use `fir.array_access` to recover the implied memory reference to
1569
+ the element `a(i,j)` in an array expression `a` as shown above. It can also
1570
+ be used to recover the reference element `a(r,s+1)` in the second
1571
+ expression.
1572
+
1573
+ ```mlir
1574
+ %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
1575
+ // load the entire array 'a'
1576
+ %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
1577
+ // fetch the value of one of the array value's elements
1578
+ %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
1579
+ ```
1580
+
1581
+ It is only possible to use `array_access` on an `array_load` result value.
1582
+ }];
1583
+
1584
+ let arguments = (ins
1585
+ fir_SequenceType:$sequence,
1586
+ Variadic<AnyCoordinateType>:$indices,
1587
+ Variadic<AnyIntegerType>:$typeparams
1588
+ );
1589
+
1590
+ let results = (outs fir_ReferenceType:$element);
1591
+
1592
+ let assemblyFormat = [{
1593
+ $sequence `,` $indices (`typeparams` $typeparams^)? attr-dict `:`
1594
+ functional-type(operands, results)
1595
+ }];
1596
+
1597
+ let verifier = "return ::verify(*this);";
1598
+ }
1599
+
1600
+ def fir_ArrayAmendOp : fir_Op<"array_amend", [NoSideEffect]> {
1601
+ let summary = "Mark an array value as having been changed by reference.";
1602
+
1603
+ let description = [{
1604
+ Marks an array value as having been changed via a reference. The reference
1605
+ into the array value is obtained via an fir.array_access op.
1606
+
1607
+ ```mlir
1608
+ // fetch the value of one of the array value's elements
1609
+ %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
1610
+ // modify the element by storing data using %1 as a reference
1611
+ %2 = ... %1 ...
1612
+ // mark the array value
1613
+ %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
1614
+ ```
1615
+ }];
1616
+
1617
+ let arguments = (ins
1618
+ fir_SequenceType:$sequence,
1619
+ fir_ReferenceType:$memref
1620
+ );
1621
+
1622
+ let results = (outs fir_SequenceType);
1623
+
1624
+ let assemblyFormat = [{
1625
+ $sequence `,` $memref attr-dict `:` functional-type(operands, results)
1626
+ }];
1627
+ }
1628
+
1543
1629
def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
1544
1630
[AttrSizedOperandSegments]> {
1545
1631
let summary = "Store merged array value to memory.";
@@ -1893,19 +1979,34 @@ def fir_SliceOp : fir_Op<"slice", [NoSideEffect, AttrSizedOperandSegments]> {
1893
1979
%fld = fir.field_index component, !fir.type<t{...component:ct...}>
1894
1980
%d = fir.slice %lo, %hi, %step path %fld : (index, index, index, !fir.field) -> !fir.slice<1>
1895
1981
```
1982
+
1983
+ Projections of `!fir.char` type can be further narrowed to invariant
1984
+ substrings.
1985
+
1986
+ ```mlir
1987
+ %d = fir.slice %lo, %hi, %step substr %offset, %width : (index, index, index, index, index) -> !fir.slice<1>
1988
+ ```
1896
1989
}];
1897
1990
1898
1991
let arguments = (ins
1899
- Variadic<AnyCoordinateType>:$triples,
1900
- Variadic<AnyComponentType>:$fields
1992
+ Variadic<AnyIntegerType>:$triples,
1993
+ Variadic<AnyComponentType>:$fields,
1994
+ Variadic<AnyIntegerType>:$substr
1901
1995
);
1902
1996
1903
1997
let results = (outs fir_SliceType);
1904
1998
1905
1999
let assemblyFormat = [{
1906
- $triples (`path` $fields^)? attr-dict `:` functional-type(operands, results)
2000
+ $triples (`path` $fields^)? (`substr` $substr^)? attr-dict `:`
2001
+ functional-type(operands, results)
1907
2002
}];
1908
2003
2004
+ let builders = [
2005
+ OpBuilder<(ins "mlir::ValueRange":$triples,
2006
+ CArg<"mlir::ValueRange", "llvm::None">:$fields,
2007
+ CArg<"mlir::ValueRange", "llvm::None">:$substr)>
2008
+ ];
2009
+
1909
2010
let verifier = "return ::verify(*this);";
1910
2011
1911
2012
let extraClassDeclaration = [{
0 commit comments