Skip to content

Commit a8db1fb

Browse files
authored
[flang] update fir.coordinate_of to carry the fields (#127231)
This patch updates fir.coordinate_op to carry the field index as attributes instead of relying on getting it from the fir.field_index operations defining its operands. The rational is that FIR currently has a few operations that require DAGs to be preserved in order to be able to do code generation. This is the case of fir.coordinate_op, which requires its fir.field operand producer to be visible. This makes IR transformation harder/brittle, so I want to update FIR to get rid if this. Codegen/printer/parser of fir.coordinate_of and many tests need to be updated after this change.
1 parent 2871f69 commit a8db1fb

File tree

68 files changed

+835
-1027
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+835
-1027
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,95 @@ struct DebuggingResource
5050
mlir::StringRef getName() final { return "DebuggingResource"; }
5151
};
5252

53+
class CoordinateIndicesAdaptor;
54+
using IntOrValue = llvm::PointerUnion<mlir::IntegerAttr, mlir::Value>;
55+
5356
} // namespace fir
5457

5558
#define GET_OP_CLASSES
5659
#include "flang/Optimizer/Dialect/FIROps.h.inc"
5760

61+
namespace fir {
62+
class CoordinateIndicesAdaptor {
63+
public:
64+
using value_type = IntOrValue;
65+
66+
CoordinateIndicesAdaptor(mlir::DenseI32ArrayAttr fieldIndices,
67+
mlir::ValueRange values)
68+
: fieldIndices(fieldIndices), values(values) {}
69+
70+
value_type operator[](size_t index) const {
71+
assert(index < size() && "index out of bounds");
72+
return *std::next(begin(), index);
73+
}
74+
75+
size_t size() const {
76+
return fieldIndices ? fieldIndices.size() : values.size();
77+
}
78+
79+
bool empty() const {
80+
return values.empty() && (!fieldIndices || fieldIndices.empty());
81+
}
82+
83+
class iterator
84+
: public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
85+
value_type, std::ptrdiff_t,
86+
value_type *, value_type> {
87+
public:
88+
iterator(const CoordinateIndicesAdaptor *base,
89+
std::optional<llvm::ArrayRef<int32_t>::iterator> fieldIter,
90+
llvm::detail::IterOfRange<const mlir::ValueRange> valuesIter)
91+
: base(base), fieldIter(fieldIter), valuesIter(valuesIter) {}
92+
93+
value_type operator*() const {
94+
if (fieldIter && **fieldIter != fir::CoordinateOp::kDynamicIndex) {
95+
return mlir::IntegerAttr::get(base->fieldIndices.getElementType(),
96+
**fieldIter);
97+
}
98+
return *valuesIter;
99+
}
100+
101+
iterator &operator++() {
102+
if (fieldIter) {
103+
if (**fieldIter == fir::CoordinateOp::kDynamicIndex)
104+
valuesIter++;
105+
(*fieldIter)++;
106+
} else {
107+
valuesIter++;
108+
}
109+
return *this;
110+
}
111+
112+
bool operator==(const iterator &rhs) const {
113+
return base == rhs.base && fieldIter == rhs.fieldIter &&
114+
valuesIter == rhs.valuesIter;
115+
}
116+
117+
private:
118+
const CoordinateIndicesAdaptor *base;
119+
std::optional<llvm::ArrayRef<int32_t>::const_iterator> fieldIter;
120+
llvm::detail::IterOfRange<const mlir::ValueRange> valuesIter;
121+
};
122+
123+
iterator begin() const {
124+
std::optional<llvm::ArrayRef<int32_t>::const_iterator> fieldIter;
125+
if (fieldIndices)
126+
fieldIter = fieldIndices.asArrayRef().begin();
127+
return iterator(this, fieldIter, values.begin());
128+
}
129+
130+
iterator end() const {
131+
std::optional<llvm::ArrayRef<int32_t>::const_iterator> fieldIter;
132+
if (fieldIndices)
133+
fieldIter = fieldIndices.asArrayRef().end();
134+
return iterator(this, fieldIter, values.end());
135+
}
136+
137+
private:
138+
mlir::DenseI32ArrayAttr fieldIndices;
139+
mlir::ValueRange values;
140+
};
141+
142+
} // namespace fir
143+
58144
#endif // FORTRAN_OPTIMIZER_DIALECT_FIROPS_H

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,10 +1748,16 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
17481748
Unlike LLVM's GEP instruction, one cannot stride over the outermost
17491749
reference; therefore, the leading 0 index must be omitted.
17501750

1751+
This operation can be used to index derived type fields, in which case
1752+
the operand is the name of the index field.
1753+
17511754
```
17521755
%i = ... : index
17531756
%h = ... : !fir.heap<!fir.array<100 x f32>>
17541757
%p = fir.coordinate_of %h, %i : (!fir.heap<!fir.array<100 x f32>>, index) -> !fir.ref<f32>
1758+
1759+
%d = ... : !fir.ref<!fir.type<t{field1:i32, field2:f32}>>
1760+
%f = fir.coordinate_of %d, field2 : (!fir.ref<!fir.type<t{field1:i32, field2:f32}>>) -> !fir.ref<f32>
17551761
```
17561762

17571763
In the example, `%p` will be a pointer to the `%i`-th f32 value in the
@@ -1761,7 +1767,8 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
17611767
let arguments = (ins
17621768
AnyRefOrBox:$ref,
17631769
Variadic<AnyCoordinateType>:$coor,
1764-
TypeAttr:$baseType
1770+
TypeAttr:$baseType,
1771+
OptionalAttr<DenseI32ArrayAttr>:$field_indices
17651772
);
17661773

17671774
let results = (outs RefOrLLVMPtr);
@@ -1771,10 +1778,14 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
17711778

17721779
let builders = [
17731780
OpBuilder<(ins "mlir::Type":$resultType,
1774-
"mlir::Value":$ref, "mlir::ValueRange":$coor),
1775-
[{ return build($_builder, $_state, resultType, ref, coor,
1776-
mlir::TypeAttr::get(ref.getType())); }]>,
1781+
"mlir::Value":$ref, "mlir::ValueRange":$coor)>,
1782+
OpBuilder<(ins "mlir::Type":$resultType,
1783+
"mlir::Value":$ref, "llvm::ArrayRef<fir::IntOrValue>":$coor)>
17771784
];
1785+
let extraClassDeclaration = [{
1786+
constexpr static int32_t kDynamicIndex = std::numeric_limits<int32_t>::min();
1787+
CoordinateIndicesAdaptor getIndices();
1788+
}];
17781789
}
17791790

17801791
def fir_ExtractValueOp : fir_OneResultOp<"extract_value", [NoMemoryEffect]> {

flang/lib/Lower/OpenMP/Utils.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -354,14 +354,12 @@ mlir::Value createParentSymAndGenIntermediateMaps(
354354
// type.
355355
if (fir::RecordType recordType = mlir::dyn_cast<fir::RecordType>(
356356
fir::unwrapPassByRefType(curValue.getType()))) {
357-
mlir::Value idxConst = firOpBuilder.createIntegerConstant(
358-
clauseLocation, firOpBuilder.getIndexType(),
359-
indices[currentIndicesIdx]);
360-
mlir::Type memberTy =
361-
recordType.getTypeList().at(indices[currentIndicesIdx]).second;
357+
fir::IntOrValue idxConst = mlir::IntegerAttr::get(
358+
firOpBuilder.getI32Type(), indices[currentIndicesIdx]);
359+
mlir::Type memberTy = recordType.getType(indices[currentIndicesIdx]);
362360
curValue = firOpBuilder.create<fir::CoordinateOp>(
363361
clauseLocation, firOpBuilder.getRefType(memberTy), curValue,
364-
idxConst);
362+
llvm::SmallVector<fir::IntOrValue, 1>{idxConst});
365363

366364
// Skip mapping and the subsequent load if we're the final member or not
367365
// a type with a descriptor such as a pointer/allocatable. If we're a

flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,9 @@ class BoxedProcedurePass
348348
rewriter.setInsertionPoint(coor);
349349
auto toTy = typeConverter.convertType(ty);
350350
auto toBaseTy = typeConverter.convertType(baseTy);
351-
rewriter.replaceOpWithNewOp<CoordinateOp>(coor, toTy, coor.getRef(),
352-
coor.getCoor(), toBaseTy);
351+
rewriter.replaceOpWithNewOp<CoordinateOp>(
352+
coor, toTy, coor.getRef(), coor.getCoor(), toBaseTy,
353+
coor.getFieldIndicesAttr());
353354
opIsValid = false;
354355
}
355356
} else if (auto index = mlir::dyn_cast<FieldIndexOp>(op)) {

0 commit comments

Comments
 (0)