Skip to content

Commit 6657995

Browse files
committed
Fix some CHARACTER related bugs.
Adds lowering of substring operations in several new contexts that were TODO. Adds referential semantics operations to the array expression lowering framework. (The scope of this is greater than CHARACTER.) Fixes some threading of LEN values bugs. Begins the unification the default handling of assignment. Fixes bugs from multiple assignment patterns. Adds a temporary conflict analysis for array reference semantics. (This will be improved soon.) Ad hoc overloading of array_fetch, array_update to handle elemental objects is deprecated and will be removed. Corrects all failing tests with the new operations.
1 parent 53a9367 commit 6657995

25 files changed

+1940
-771
lines changed

flang/include/flang/Lower/EvExprDumper.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ LLVM_DUMP_METHOD void dumpEvExpr(
201201
const Fortran::evaluate::Expr<
202202
Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, 8>> &x);
203203
LLVM_DUMP_METHOD void dumpEvExpr(const Fortran::evaluate::ArrayRef &x);
204+
LLVM_DUMP_METHOD void dumpEvExpr(const Fortran::evaluate::DataRef &x);
205+
LLVM_DUMP_METHOD void dumpEvExpr(const Fortran::evaluate::Substring &x);
206+
LLVM_DUMP_METHOD void dumpEvExpr(
207+
const Fortran::evaluate::Designator<
208+
Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, 4>> &x);
204209

205210
} // namespace Fortran::lower
206211

flang/include/flang/Optimizer/Builder/Character.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ class CharacterExprHelper {
107107
/// Extract the kind of a character or array of character type.
108108
static fir::KindTy getCharacterOrSequenceKind(mlir::Type type);
109109

110-
/// Determine the base character type
110+
/// Determine the inner character type. Unwraps references, boxes, and
111+
/// sequences to find the !fir.char element type.
112+
static fir::CharacterType getCharType(mlir::Type type);
113+
114+
/// Get fir.char<kind> type with the same kind as inside str.
111115
static fir::CharacterType getCharacterType(mlir::Type type);
112116
static fir::CharacterType getCharacterType(const fir::CharBoxValue &box);
113117
static fir::CharacterType getCharacterType(mlir::Value str);

flang/include/flang/Optimizer/CodeGen/CGOps.td

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,15 @@ def fircg_XEmboxOp : fircg_Op<"ext_embox", [AttrSizedOperandSegments]> {
5454
Variadic<AnyIntegerType>:$shift,
5555
Variadic<AnyIntegerType>:$slice,
5656
Variadic<AnyCoordinateType>:$subcomponent,
57+
Variadic<AnyIntegerType>:$substr,
5758
Variadic<AnyIntegerType>:$lenParams
5859
);
5960
let results = (outs fir_BoxType);
6061

6162
let assemblyFormat = [{
6263
$memref (`(`$shape^`)`)? (`origin` $shift^)? (`[`$slice^`]`)?
63-
(`path` $subcomponent^)? (`typeparams` $lenParams^)? attr-dict
64-
`:` functional-type(operands, results)
64+
(`path` $subcomponent^)? (`substr` $substr^)? (`typeparams` $lenParams^)?
65+
attr-dict `:` functional-type(operands, results)
6566
}];
6667

6768
let extraClassDeclaration = [{
@@ -76,9 +77,10 @@ def fircg_XEmboxOp : fircg_Op<"ext_embox", [AttrSizedOperandSegments]> {
7677
unsigned shiftOffset() { return shapeOffset() + shape().size(); }
7778
unsigned sliceOffset() { return shiftOffset() + shift().size(); }
7879
unsigned subcomponentOffset() { return sliceOffset() + slice().size(); }
79-
unsigned lenParamOffset() {
80+
unsigned substrOffset() {
8081
return subcomponentOffset() + subcomponent().size();
8182
}
83+
unsigned lenParamOffset() { return substrOffset() + substr().size(); }
8284
}];
8385
}
8486

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 108 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -826,9 +826,9 @@ def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> {
826826
let assemblyFormat = "$resval attr-dict `:` type($resval)";
827827
}
828828

829-
//===------------------------------------------------------------------------===//
829+
//===----------------------------------------------------------------------===//
830830
// Operations on !fir.box<T> type objects
831-
//===------------------------------------------------------------------------===//
831+
//===----------------------------------------------------------------------===//
832832

833833
def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
834834
let summary = "boxes a given reference and (optional) dimension information";
@@ -891,26 +891,27 @@ def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
891891
}
892892

893893
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";
895896

896897
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.
900901

901902
The new extra information can be:
902903
- new shape information (new lower bounds, new rank, or new extents.
903904
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
905906
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.
910911

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.
914915

915916
The following example illustrates creating a fir.box for x(10:33:2)
916917
where x is described by a fir.box and has non default lower bounds,
@@ -1540,6 +1541,81 @@ def fir_ArrayModifyOp : fir_Op<"array_modify", [AttrSizedOperandSegments,
15401541
let verifier = [{ return ::verify(*this); }];
15411542
}
15421543

1544+
def fir_ArrayAccessOp : fir_Op<"array_access", [AttrSizedOperandSegments,
1545+
NoSideEffect]> {
1546+
let summary = "Fetch the reference of an element of an array value";
1547+
1548+
let description = [{
1549+
Fetch the memory reference of an element in an array value.
1550+
1551+
```fortran
1552+
real :: a(n,m)
1553+
...
1554+
... a ...
1555+
... a(r,s+1) ...
1556+
```
1557+
1558+
One can use `fir.array_access` to recover the implied memory reference to
1559+
the element `a(i,j)` in an array expression `a` as shown above. It can also
1560+
be used to recover the reference element `a(r,s+1)` in the second
1561+
expression.
1562+
1563+
```mlir
1564+
%s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
1565+
// load the entire array 'a'
1566+
%v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
1567+
// fetch the value of one of the array value's elements
1568+
%1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
1569+
```
1570+
1571+
It is only possible to use `array_access` on an `array_load` result value.
1572+
}];
1573+
1574+
let arguments = (ins
1575+
fir_SequenceType:$sequence,
1576+
Variadic<AnyCoordinateType>:$indices,
1577+
Variadic<AnyIntegerType>:$typeparams
1578+
);
1579+
1580+
let results = (outs fir_ReferenceType:$element);
1581+
1582+
let assemblyFormat = [{
1583+
$sequence `,` $indices (`typeparams` $typeparams^)? attr-dict `:`
1584+
functional-type(operands, results)
1585+
}];
1586+
1587+
let verifier = "return ::verify(*this);";
1588+
}
1589+
1590+
def fir_ArrayAmendOp : fir_Op<"array_amend", [NoSideEffect]> {
1591+
let summary = "Mark an array value as having been changed by reference.";
1592+
1593+
let description = [{
1594+
Marks an array value as having been changed via a reference. The reference
1595+
into the array value is obtained via an fir.array_access op.
1596+
1597+
```mlir
1598+
// fetch the value of one of the array value's elements
1599+
%1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
1600+
// modify the element by storing data using %1 as a reference
1601+
%2 = ... %1 ...
1602+
// mark the array value
1603+
%new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
1604+
```
1605+
}];
1606+
1607+
let arguments = (ins
1608+
fir_SequenceType:$sequence,
1609+
fir_ReferenceType:$memref
1610+
);
1611+
1612+
let results = (outs fir_SequenceType);
1613+
1614+
let assemblyFormat = [{
1615+
$sequence `,` $memref attr-dict `:` functional-type(operands, results)
1616+
}];
1617+
}
1618+
15431619
def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
15441620
[AttrSizedOperandSegments]> {
15451621
let summary = "Store merged array value to memory.";
@@ -1893,19 +1969,34 @@ def fir_SliceOp : fir_Op<"slice", [NoSideEffect, AttrSizedOperandSegments]> {
18931969
%fld = fir.field_index component, !fir.type<t{...component:ct...}>
18941970
%d = fir.slice %lo, %hi, %step path %fld : (index, index, index, !fir.field) -> !fir.slice<1>
18951971
```
1972+
1973+
Projections of `!fir.char` type can be further narrowed to invariant
1974+
substrings.
1975+
1976+
```mlir
1977+
%d = fir.slice %lo, %hi, %step substr %from, %to : (index, index, index, index, index) -> !fir.slice<1>
1978+
```
18961979
}];
18971980

18981981
let arguments = (ins
1899-
Variadic<AnyCoordinateType>:$triples,
1900-
Variadic<AnyComponentType>:$fields
1982+
Variadic<AnyIntegerType>:$triples,
1983+
Variadic<AnyComponentType>:$fields,
1984+
Variadic<AnyIntegerType>:$substr
19011985
);
19021986

19031987
let results = (outs fir_SliceType);
19041988

19051989
let assemblyFormat = [{
1906-
$triples (`path` $fields^)? attr-dict `:` functional-type(operands, results)
1990+
$triples (`path` $fields^)? (`substr` $substr^)? attr-dict `:`
1991+
functional-type(operands, results)
19071992
}];
19081993

1994+
let builders = [
1995+
OpBuilder<(ins "mlir::ValueRange":$triples,
1996+
CArg<"mlir::ValueRange", "llvm::None">:$fields,
1997+
CArg<"mlir::ValueRange", "llvm::None">:$substr)>
1998+
];
1999+
19092000
let verifier = "return ::verify(*this);";
19102001

19112002
let extraClassDeclaration = [{

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,22 @@ inline mlir::Type unwrapPassByRefType(mlir::Type t) {
193193
return t;
194194
}
195195

196+
/// Unwrap all pointer and box types and return the element type if it is a
197+
/// sequence type, otherwise return null.
198+
inline fir::SequenceType unwrapUntilSeqType(mlir::Type t) {
199+
while (true) {
200+
if (!t)
201+
return {};
202+
if (auto ty = dyn_cast_ptrOrBoxEleTy(t)) {
203+
t = ty;
204+
continue;
205+
}
206+
if (auto seqTy = t.dyn_cast<fir::SequenceType>())
207+
return seqTy;
208+
return {};
209+
}
210+
}
211+
196212
#ifndef NDEBUG
197213
// !fir.ptr<X> and !fir.heap<X> where X is !fir.ptr, !fir.heap, or !fir.ref
198214
// is undefined and disallowed.

0 commit comments

Comments
 (0)