Skip to content

Commit c099ca4

Browse files
committed
[flang][optimizer] support aggregate types inside tuple and record type
This patch allows: - fir.box type to be a member of tuple<> or fir.type<> types, - tuple<> type to be a member of tuple<> type. When a fir.box types are nested in tuple<> or fir.type<>, it is translated to the struct type of a Fortran runtime descriptor, and not a pointer to a descriptor. This is because the fir.box is owned by the tuple or fir.type. FIR type translation was also flattening nested tuple while lowering to LLVM dialect types. There does not seem to be a deep reason for doing that and doing it causes issues in fir.coordinate_of generated on such tuple (a fir.coordinate_of getting tuple<B, C> in tuple<A, tuple<B, C>> ended-up lowered to an LLVM GEP getting B). Differential Revision: https://reviews.llvm.org/D118701
1 parent 7d926b7 commit c099ca4

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

flang/lib/Optimizer/CodeGen/TypeConverter.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,15 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
111111
});
112112
addConversion([&](mlir::TupleType tuple) {
113113
LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n');
114-
llvm::SmallVector<mlir::Type> inMembers;
115-
tuple.getFlattenedTypes(inMembers);
116114
llvm::SmallVector<mlir::Type> members;
117-
for (auto mem : inMembers)
118-
members.push_back(convertType(mem).cast<mlir::Type>());
115+
for (auto mem : tuple.getTypes()) {
116+
// Prevent fir.box from degenerating to a pointer to a descriptor in the
117+
// context of a tuple type.
118+
if (auto box = mem.dyn_cast<fir::BoxType>())
119+
members.push_back(convertBoxTypeAsStruct(box));
120+
else
121+
members.push_back(convertType(mem).cast<mlir::Type>());
122+
}
119123
return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members,
120124
/*isPacked=*/false);
121125
});
@@ -140,7 +144,12 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
140144
}
141145
llvm::SmallVector<mlir::Type> members;
142146
for (auto mem : derived.getTypeList()) {
143-
members.push_back(convertType(mem.second).cast<mlir::Type>());
147+
// Prevent fir.box from degenerating to a pointer to a descriptor in the
148+
// context of a record type.
149+
if (auto box = mem.second.dyn_cast<fir::BoxType>())
150+
members.push_back(convertBoxTypeAsStruct(box));
151+
else
152+
members.push_back(convertType(mem.second).cast<mlir::Type>());
144153
}
145154
if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
146155
return failure();
@@ -227,6 +236,14 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
227236
/*isPacked=*/false));
228237
}
229238

239+
/// Convert fir.box type to the corresponding llvm struct type instead of a
240+
/// pointer to this struct type.
241+
mlir::Type convertBoxTypeAsStruct(BoxType box) {
242+
return convertBoxType(box)
243+
.cast<mlir::LLVM::LLVMPointerType>()
244+
.getElementType();
245+
}
246+
230247
unsigned characterBitsize(fir::CharacterType charTy) {
231248
return kindMapping.getCharacterBitsize(charTy.getFKind());
232249
}

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ static bool isaIntegerType(mlir::Type ty) {
6161
}
6262

6363
bool verifyRecordMemberType(mlir::Type ty) {
64-
return !(ty.isa<BoxType>() || ty.isa<BoxCharType>() ||
65-
ty.isa<BoxProcType>() || ty.isa<ShapeType>() ||
66-
ty.isa<ShapeShiftType>() || ty.isa<ShiftType>() ||
67-
ty.isa<SliceType>() || ty.isa<FieldType>() || ty.isa<LenType>() ||
68-
ty.isa<ReferenceType>() || ty.isa<TypeDescType>());
64+
return !(ty.isa<BoxCharType>() || ty.isa<BoxProcType>() ||
65+
ty.isa<ShapeType>() || ty.isa<ShapeShiftType>() ||
66+
ty.isa<ShiftType>() || ty.isa<SliceType>() || ty.isa<FieldType>() ||
67+
ty.isa<LenType>() || ty.isa<ReferenceType>() ||
68+
ty.isa<TypeDescType>());
6969
}
7070

7171
bool verifySameLists(llvm::ArrayRef<RecordType::TypePair> a1,

flang/test/Fir/types-to-llvm.fir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,21 @@ func private @foo2(%arg : !fir.tdesc<f32>)
400400
func private @foo3(%arg : !fir.tdesc<!fir.type<derived7{f1:f32,f2:f32}>>)
401401
// CHECK-LABEL: foo3
402402
// CHECK-SAME: !llvm.ptr<i8>
403+
404+
// -----
405+
406+
// Test nested tuple types
407+
func private @foo0(%arg0: tuple<i64, tuple<f32, i64>>)
408+
// CHECK-LABEL: foo0
409+
// CHECK-SAME: !llvm.struct<(i64, struct<(f32, i64)>)>
410+
411+
// -----
412+
413+
// Test that fir.box inside tuple and derived type are lowered to struct type.
414+
func private @foo0(%arg0: tuple<i64, !fir.box<i32>>)
415+
// CHECK-LABEL: foo0
416+
// CHECK-SAME: !llvm.struct<(i64, struct<(ptr<i32>, i{{.*}})>)>
417+
418+
func private @foo1(%arg0: !fir.type<derived8{a:i64,b:!fir.box<i32>}>)
419+
// CHECK-LABEL: foo1
420+
// CHECK-SAME: !llvm.struct<"derived8", (i64, struct<(ptr<i32>, i{{.*}})>)>

0 commit comments

Comments
 (0)