[flang-commits] [flang] [mlir] [flang][AIX] BIND(C) derived type alignment for AIX (PR #121505)
Kelvin Li via flang-commits
flang-commits at lists.llvm.org
Thu Jan 9 14:22:26 PST 2025
https://github.com/kkwli updated https://github.com/llvm/llvm-project/pull/121505
>From aefe5ee2d158cf4a82c8ff039884baa91f8829b5 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Wed, 21 Aug 2024 08:55:30 -0400
Subject: [PATCH 1/5] [flang] BIND(C) derived type alignment for AIX
---
.../flang/Optimizer/CodeGen/TypeConverter.h | 2 +-
.../flang/Optimizer/Dialect/FIRTypes.td | 3 +
flang/lib/Lower/ConvertType.cpp | 42 +++++++
flang/lib/Optimizer/CodeGen/TypeConverter.cpp | 10 +-
flang/lib/Optimizer/Dialect/FIRType.cpp | 10 +-
flang/lib/Semantics/compute-offsets.cpp | 82 +++++++++++++-
flang/test/Lower/derived-types-bindc.f90 | 44 ++++++++
flang/test/Semantics/offsets04.f90 | 105 ++++++++++++++++++
.../mlir/Transforms/DialectConversion.h | 15 +++
9 files changed, 302 insertions(+), 11 deletions(-)
create mode 100644 flang/test/Lower/derived-types-bindc.f90
create mode 100644 flang/test/Semantics/offsets04.f90
diff --git a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
index 7c317ddeea1fa4..20270d41b1e9a1 100644
--- a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
@@ -62,7 +62,7 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
std::optional<llvm::LogicalResult>
convertRecordType(fir::RecordType derived,
- llvm::SmallVectorImpl<mlir::Type> &results);
+ llvm::SmallVectorImpl<mlir::Type> &results, bool isPacked);
// Is an extended descriptor needed given the element type of a fir.box type ?
// Extended descriptors are required for derived types.
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 3919c9191c2122..4d832a49236bf1 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -346,6 +346,9 @@ def fir_RecordType : FIR_Type<"Record", "type"> {
void finalize(llvm::ArrayRef<TypePair> lenPList,
llvm::ArrayRef<TypePair> typeList);
+ bool isPacked() const;
+ void pack(bool);
+
detail::RecordTypeStorage const *uniqueKey() const;
}];
}
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 452ddda426fa10..40dbaa28ce7cac 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -20,6 +20,8 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/Support/Debug.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#define DEBUG_TYPE "flang-lower-type"
@@ -385,9 +387,19 @@ struct TypeBuilderImpl {
// with dozens of components/parents (modern Fortran).
derivedTypeInConstruction.try_emplace(&derivedScope, rec);
+ auto targetTriple{llvm::Triple(
+ llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))};
+ // Always generate packed FIR struct type for bind(c) derived type for AIX
+ if (targetTriple.getOS() == llvm::Triple::OSType::AIX &&
+ tySpec.typeSymbol().attrs().test(Fortran::semantics::Attr::BIND_C) &&
+ !IsIsoCType(&tySpec)) {
+ rec.pack(true);
+ }
+
// Gather the record type fields.
// (1) The data components.
if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
+ size_t prev_offset{0};
// In HLFIR the parent component is the first fir.type component.
for (const auto &componentName :
typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
@@ -397,7 +409,37 @@ struct TypeBuilderImpl {
"failed to find derived type component symbol");
const Fortran::semantics::Symbol &component = scopeIter->second.get();
mlir::Type ty = genSymbolType(component);
+ if (rec.isPacked()) {
+ auto compSize{component.size()};
+ auto compOffset{component.offset()};
+
+ if (prev_offset < compOffset) {
+ size_t pad{compOffset - prev_offset};
+ mlir::Type i8Ty{mlir::IntegerType::get(context, 8)};
+ fir::SequenceType::Shape shape{static_cast<int64_t>(pad)};
+ mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)};
+ prev_offset += pad;
+ cs.emplace_back("", padTy);
+ }
+ prev_offset += compSize;
+ }
cs.emplace_back(converter.getRecordTypeFieldName(component), ty);
+ if (rec.isPacked()) {
+ // For the last component, determine if any padding is needed.
+ if (componentName ==
+ typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
+ .componentNames()
+ .back()) {
+ auto compEnd{component.offset() + component.size()};
+ if (compEnd < derivedScope.size()) {
+ size_t pad{derivedScope.size() - compEnd};
+ mlir::Type i8Ty{mlir::IntegerType::get(context, 8)};
+ fir::SequenceType::Shape shape{static_cast<int64_t>(pad)};
+ mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)};
+ cs.emplace_back("", padTy);
+ }
+ }
+ }
}
} else {
for (const auto &component :
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
index c23203efcd3df2..0eace903720f03 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
@@ -82,7 +82,7 @@ LLVMTypeConverter::LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA,
[&](fir::PointerType pointer) { return convertPointerLike(pointer); });
addConversion(
[&](fir::RecordType derived, llvm::SmallVectorImpl<mlir::Type> &results) {
- return convertRecordType(derived, results);
+ return convertRecordType(derived, results, derived.isPacked());
});
addConversion(
[&](fir::ReferenceType ref) { return convertPointerLike(ref); });
@@ -133,8 +133,10 @@ mlir::Type LLVMTypeConverter::indexType() const {
}
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
-std::optional<llvm::LogicalResult> LLVMTypeConverter::convertRecordType(
- fir::RecordType derived, llvm::SmallVectorImpl<mlir::Type> &results) {
+std::optional<llvm::LogicalResult>
+LLVMTypeConverter::convertRecordType(fir::RecordType derived,
+ llvm::SmallVectorImpl<mlir::Type> &results,
+ bool isPacked) {
auto name = fir::NameUniquer::dropTypeConversionMarkers(derived.getName());
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
@@ -156,7 +158,7 @@ std::optional<llvm::LogicalResult> LLVMTypeConverter::convertRecordType(
else
members.push_back(mlir::cast<mlir::Type>(convertType(mem.second)));
}
- if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
+ if (mlir::failed(st.setBody(members, isPacked)))
return mlir::failure();
results.push_back(st);
return mlir::success();
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index cba7fa64128502..ea06eb092ed918 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -165,16 +165,20 @@ struct RecordTypeStorage : public mlir::TypeStorage {
setTypeList(typeList);
}
+ bool isPacked() const { return packed; }
+ void pack(bool p) { packed = p; }
+
protected:
std::string name;
bool finalized;
+ bool packed;
std::vector<RecordType::TypePair> lens;
std::vector<RecordType::TypePair> types;
private:
RecordTypeStorage() = delete;
explicit RecordTypeStorage(llvm::StringRef name)
- : name{name}, finalized{false} {}
+ : name{name}, finalized{false}, packed{false} {}
};
} // namespace detail
@@ -973,6 +977,10 @@ RecordType::TypeList fir::RecordType::getLenParamList() const {
bool fir::RecordType::isFinalized() const { return getImpl()->isFinalized(); }
+void fir::RecordType::pack(bool p) { getImpl()->pack(p); }
+
+bool fir::RecordType::isPacked() const { return getImpl()->isPacked(); }
+
detail::RecordTypeStorage const *fir::RecordType::uniqueKey() const {
return getImpl();
}
diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index 94640fa30baa54..7d516b3e8df54a 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -17,6 +17,8 @@
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <vector>
@@ -51,9 +53,12 @@ class ComputeOffsetsHelper {
SymbolAndOffset Resolve(const SymbolAndOffset &);
std::size_t ComputeOffset(const EquivalenceObject &);
// Returns amount of padding that was needed for alignment
- std::size_t DoSymbol(Symbol &);
+ std::size_t DoSymbol(Symbol &,
+ std::optional<const size_t> newAlign = std::nullopt);
SizeAndAlignment GetSizeAndAlignment(const Symbol &, bool entire);
std::size_t Align(std::size_t, std::size_t);
+ std::optional<size_t> CompAlignment(const Symbol &);
+ std::optional<size_t> HasSpecialAlign(const Symbol &, Scope &);
SemanticsContext &context_;
std::size_t offset_{0};
@@ -65,6 +70,60 @@ class ComputeOffsetsHelper {
equivalenceBlock_;
};
+static bool isReal8OrLarger(const Fortran::semantics::DeclTypeSpec *type) {
+ return ((type->IsNumeric(common::TypeCategory::Real) ||
+ type->IsNumeric(common::TypeCategory::Complex)) &&
+ evaluate::ToInt64(type->numericTypeSpec().kind()) > 4);
+}
+
+std::optional<size_t> ComputeOffsetsHelper::CompAlignment(const Symbol &sym) {
+ size_t max_align{0};
+ bool contain_double{false};
+ const auto derivedTypeSpec{sym.GetType()->AsDerived()};
+ DirectComponentIterator directs{*derivedTypeSpec};
+ for (auto it = directs.begin(); it != directs.end(); ++it) {
+ auto type{it->GetType()};
+ auto s{GetSizeAndAlignment(*it, true)};
+ if (isReal8OrLarger(type)) {
+ max_align = std::max(max_align, 4UL);
+ contain_double = true;
+ } else if (type->AsDerived()) {
+ if (const auto newAlgin = CompAlignment(*it)) {
+ max_align = std::max(max_align, s.alignment);
+ } else {
+ return std::nullopt;
+ }
+ } else {
+ max_align = std::max(max_align, s.alignment);
+ }
+ }
+
+ if (contain_double)
+ return max_align;
+ else
+ return std::nullopt;
+}
+
+std::optional<size_t> ComputeOffsetsHelper::HasSpecialAlign(const Symbol &sym,
+ Scope &scope) {
+ // On AIX, if the component that is not the first component and is
+ // a float of 8 bytes or larger, it has the 4-byte alignment.
+ // Only set the special alignment for bind(c) derived type on that platform.
+ if (const auto type = sym.GetType()) {
+ auto &symOwner{sym.owner()};
+ if (symOwner.symbol() && symOwner.IsDerivedType() &&
+ symOwner.symbol()->attrs().HasAny({semantics::Attr::BIND_C}) &&
+ &sym != &(*scope.GetSymbols().front())) {
+ if (isReal8OrLarger(type)) {
+ return 4UL;
+ } else if (type->AsDerived()) {
+ return CompAlignment(sym);
+ }
+ }
+ }
+ return std::nullopt;
+}
+
void ComputeOffsetsHelper::Compute(Scope &scope) {
for (Scope &child : scope.children()) {
ComputeOffsets(context_, child);
@@ -113,7 +172,15 @@ void ComputeOffsetsHelper::Compute(Scope &scope) {
if (!FindCommonBlockContaining(*symbol) &&
dependents_.find(symbol) == dependents_.end() &&
equivalenceBlock_.find(symbol) == equivalenceBlock_.end()) {
- DoSymbol(*symbol);
+
+ std::optional<size_t> newAlign{std::nullopt};
+ // Handle special alignment requirement for AIX
+ auto triple{llvm::Triple(llvm::Triple::normalize(
+ llvm::sys::getDefaultTargetTriple()))};
+ if (triple.getOS() == llvm::Triple::OSType::AIX) {
+ newAlign = HasSpecialAlign(*symbol, scope);
+ }
+ DoSymbol(*symbol, newAlign);
if (auto *generic{symbol->detailsIf<GenericDetails>()}) {
if (Symbol * specific{generic->specific()};
specific && !FindCommonBlockContaining(*specific)) {
@@ -313,7 +380,8 @@ std::size_t ComputeOffsetsHelper::ComputeOffset(
return result;
}
-std::size_t ComputeOffsetsHelper::DoSymbol(Symbol &symbol) {
+std::size_t ComputeOffsetsHelper::DoSymbol(Symbol &symbol,
+ std::optional<const size_t> newAlign) {
if (!symbol.has<ObjectEntityDetails>() && !symbol.has<ProcEntityDetails>()) {
return 0;
}
@@ -322,12 +390,16 @@ std::size_t ComputeOffsetsHelper::DoSymbol(Symbol &symbol) {
return 0;
}
std::size_t previousOffset{offset_};
- offset_ = Align(offset_, s.alignment);
+ size_t alignVal{s.alignment};
+ if (newAlign) {
+ alignVal = newAlign.value();
+ }
+ offset_ = Align(offset_, alignVal);
std::size_t padding{offset_ - previousOffset};
symbol.set_size(s.size);
symbol.set_offset(offset_);
offset_ += s.size;
- alignment_ = std::max(alignment_, s.alignment);
+ alignment_ = std::max(alignment_, alignVal);
return padding;
}
diff --git a/flang/test/Lower/derived-types-bindc.f90 b/flang/test/Lower/derived-types-bindc.f90
new file mode 100644
index 00000000000000..309b2b7f5f4929
--- /dev/null
+++ b/flang/test/Lower/derived-types-bindc.f90
@@ -0,0 +1,44 @@
+! Test padding for BIND(C) derived types lowering for AIX target
+! RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s
+
+! REQUIRES: target={{.+}}-aix{{.*}}
+
+subroutine s1()
+ use, intrinsic :: iso_c_binding
+ type, bind(c) :: t0
+ character(c_char) :: x1
+ real(c_double) :: x2
+ end type
+ type(t0) :: xt0
+! CHECK-DAG: %_QFs1Tt0 = type <{ [1 x i8], [3 x i8], double }>
+
+ type, bind(c) :: t1
+ integer(c_short) :: x1
+ real(c_double) :: x2
+ end type
+ type(t1) :: xt1
+! CHECK-DAG: %_QFs1Tt1 = type <{ i16, [2 x i8], double }>
+
+ type, bind(c) :: t2
+ integer(c_short) :: x1
+ real(c_double) :: x2
+ character(c_char) :: x3
+ end type
+ type(t2) :: xt2
+! CHECK-DAG: %_QFs1Tt2 = type <{ i16, [2 x i8], double, [1 x i8], [3 x i8] }>
+
+ type, bind(c) :: t3
+ character(c_char) :: x1
+ complex(c_double_complex) :: x2
+ end type
+ type(t3) :: xt3
+! CHECK-DAG: %_QFs1Tt3 = type <{ [1 x i8], [3 x i8], { double, double } }>
+
+ type, bind(c) :: t4
+ integer(c_short) :: x1
+ complex(c_double_complex) :: x2
+ character(c_char) :: x3
+ end type
+ type(t4) :: xt4
+! CHECK-DAG: %_QFs1Tt4 = type <{ i16, [2 x i8], { double, double }, [1 x i8], [3 x i8] }>
+end subroutine s1
diff --git a/flang/test/Semantics/offsets04.f90 b/flang/test/Semantics/offsets04.f90
new file mode 100644
index 00000000000000..d0d871a981c175
--- /dev/null
+++ b/flang/test/Semantics/offsets04.f90
@@ -0,0 +1,105 @@
+!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s
+
+!REQUIRES: target={{.+}}-aix{{.*}}
+
+! Size and alignment of bind(c) derived types
+subroutine s1()
+ use, intrinsic :: iso_c_binding
+ type, bind(c) :: dt1
+ character(c_char) :: x1 !CHECK: x1 size=1 offset=0:
+ real(c_double) :: x2 !CHECK: x2 size=8 offset=4:
+ end type
+ type, bind(c) :: dt2
+ character(c_char) :: x1(9) !CHECK: x1 size=9 offset=0:
+ real(c_double) :: x2 !CHECK: x2 size=8 offset=12:
+ end type
+ type, bind(c) :: dt3
+ integer(c_short) :: x1 !CHECK: x1 size=2 offset=0:
+ real(c_double) :: x2 !CHECK: x2 size=8 offset=4:
+ end type
+ type, bind(c) :: dt4
+ integer(c_int) :: x1 !CHECK: x1 size=4 offset=0:
+ real(c_double) :: x2 !CHECK: x2 size=8 offset=4:
+ end type
+ type, bind(c) :: dt5
+ real(c_double) :: x1 !CHECK: x1 size=8 offset=0:
+ real(c_double) :: x2 !CHECK: x2 size=8 offset=8:
+ end type
+ type, bind(c) :: dt6
+ integer(c_long) :: x1 !CHECK: x1 size=8 offset=0:
+ character(c_char) :: x2 !CHECK: x2 size=1 offset=8:
+ real(c_double) :: x3 !CHECK: x3 size=8 offset=12:
+ end type
+ type, bind(c) :: dt7
+ integer(c_long) :: x1 !CHECK: x1 size=8 offset=0:
+ integer(c_long) :: x2 !CHECK: x2 size=8 offset=8:
+ character(c_char) :: x3 !CHECK: x3 size=1 offset=16:
+ real(c_double) :: x4 !CHECK: x4 size=8 offset=20:
+ end type
+ type, bind(c) :: dt8
+ character(c_char) :: x1 !CHECK: x1 size=1 offset=0:
+ complex(c_double_complex) :: x2 !CHECK: x2 size=16 offset=4:
+ end type
+end subroutine
+
+subroutine s2()
+ use, intrinsic :: iso_c_binding
+ type, bind(c) :: dt10
+ character(c_char) :: x1
+ real(c_double) :: x2
+ end type
+ type, bind(c) :: dt11
+ type(dt10) :: y1 !CHECK: y1 size=12 offset=0:
+ real(c_double) :: y2 !CHECK: y2 size=8 offset=12:
+ end type
+ type, bind(c) :: dt12
+ character(c_char) :: y1 !CHECK: y1 size=1 offset=0:
+ type(dt10) :: y2 !CHECK: y2 size=12 offset=4:
+ character(c_char) :: y3 !CHECK: y3 size=1 offset=16:
+ end type
+ type, bind(c) :: dt13
+ integer(c_short) :: y1 !CHECK: y1 size=2 offset=0:
+ type(dt10) :: y2 !CHECK: y2 size=12 offset=4:
+ character(c_char) :: y3 !CHECK: y3 size=1 offset=16:
+ end type
+
+ type, bind(c) :: dt20
+ character(c_char) :: x1
+ integer(c_short) :: x2
+ end type
+ type, bind(c) :: dt21
+ real(c_double) :: y1 !CHECK: y1 size=8 offset=0:
+ type(dt20) :: y2 !CHECK: y2 size=4 offset=8:
+ real(c_double) :: y3 !CHECK: y3 size=8 offset=12:
+ end type
+
+ type, bind(c) :: dt30
+ character(c_char) :: x1
+ character(c_char) :: x2
+ end type
+ type, bind(c) :: dt31
+ integer(c_long) :: y1 !CHECK: y1 size=8 offset=0:
+ type(dt30) :: y2 !CHECK: y2 size=2 offset=8:
+ real(c_double) :: y3 !CHECK: y3 size=8 offset=12:
+ end type
+
+ type, bind(c) :: dt40
+ integer(c_short) :: x1
+ real(c_double) :: x2
+ end type
+ type, bind(c) :: dt41
+ real(c_double) :: y1 !CHECK: y1 size=8 offset=0:
+ type(dt40) :: y2 !CHECK: y2 size=12 offset=8:
+ real(c_double) :: y3 !CHECK: y3 size=8 offset=20:
+ end type
+
+ type, bind(c) :: dt50
+ integer(c_short) :: x1
+ complex(c_double_complex) :: x2
+ end type
+ type, bind(c) :: dt51
+ real(c_double) :: y1 !CHECK: y1 size=8 offset=0:
+ type(dt50) :: y2 !CHECK: y2 size=20 offset=8:
+ complex(c_double_complex) :: y3 !CHECK: y3 size=16 offset=28:
+ end type
+end subroutine
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h b/mlir/include/mlir/Transforms/DialectConversion.h
index 28150e886913e3..99826cdebb343d 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -391,6 +391,21 @@ class TypeConverter {
return callback(derivedType, results);
};
}
+ /// With callback of form: `std::optional<LogicalResult>(
+ /// T, SmallVectorImpl<Type> &, bool)`.
+ template <typename T, typename FnT>
+ std::enable_if_t<std::is_invocable_v<FnT, T, SmallVectorImpl<Type> &, bool>,
+ ConversionCallbackFn>
+ wrapCallback(FnT &&callback) const {
+ return [callback = std::forward<FnT>(callback)](
+ Type type, SmallVectorImpl<Type> &results,
+ bool isPacked) -> std::optional<LogicalResult> {
+ T derivedType = dyn_cast<T>(type);
+ if (!derivedType)
+ return std::nullopt;
+ return callback(derivedType, results, isPacked);
+ };
+ }
/// Register a type conversion.
void registerConversion(ConversionCallbackFn callback) {
>From af540fab1049437c4c5df6bc3a8520cd5a2dd449 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 2 Jan 2025 12:39:50 -0500
Subject: [PATCH 2/5] Fixed format
---
flang/lib/Semantics/compute-offsets.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index 7d516b3e8df54a..19718afabcb135 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -53,8 +53,8 @@ class ComputeOffsetsHelper {
SymbolAndOffset Resolve(const SymbolAndOffset &);
std::size_t ComputeOffset(const EquivalenceObject &);
// Returns amount of padding that was needed for alignment
- std::size_t DoSymbol(Symbol &,
- std::optional<const size_t> newAlign = std::nullopt);
+ std::size_t DoSymbol(
+ Symbol &, std::optional<const size_t> newAlign = std::nullopt);
SizeAndAlignment GetSizeAndAlignment(const Symbol &, bool entire);
std::size_t Align(std::size_t, std::size_t);
std::optional<size_t> CompAlignment(const Symbol &);
@@ -72,8 +72,8 @@ class ComputeOffsetsHelper {
static bool isReal8OrLarger(const Fortran::semantics::DeclTypeSpec *type) {
return ((type->IsNumeric(common::TypeCategory::Real) ||
- type->IsNumeric(common::TypeCategory::Complex)) &&
- evaluate::ToInt64(type->numericTypeSpec().kind()) > 4);
+ type->IsNumeric(common::TypeCategory::Complex)) &&
+ evaluate::ToInt64(type->numericTypeSpec().kind()) > 4);
}
std::optional<size_t> ComputeOffsetsHelper::CompAlignment(const Symbol &sym) {
@@ -175,8 +175,8 @@ void ComputeOffsetsHelper::Compute(Scope &scope) {
std::optional<size_t> newAlign{std::nullopt};
// Handle special alignment requirement for AIX
- auto triple{llvm::Triple(llvm::Triple::normalize(
- llvm::sys::getDefaultTargetTriple()))};
+ auto triple{llvm::Triple(
+ llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))};
if (triple.getOS() == llvm::Triple::OSType::AIX) {
newAlign = HasSpecialAlign(*symbol, scope);
}
@@ -380,8 +380,8 @@ std::size_t ComputeOffsetsHelper::ComputeOffset(
return result;
}
-std::size_t ComputeOffsetsHelper::DoSymbol(Symbol &symbol,
- std::optional<const size_t> newAlign) {
+std::size_t ComputeOffsetsHelper::DoSymbol(
+ Symbol &symbol, std::optional<const size_t> newAlign) {
if (!symbol.has<ObjectEntityDetails>() && !symbol.has<ProcEntityDetails>()) {
return 0;
}
>From 15c165a712e6f681e422ec680138ec5b50f00d0c Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 2 Jan 2025 12:48:58 -0500
Subject: [PATCH 3/5] Fixed format
---
flang/lib/Semantics/compute-offsets.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index 19718afabcb135..31bce0ae92ba9a 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -104,8 +104,8 @@ std::optional<size_t> ComputeOffsetsHelper::CompAlignment(const Symbol &sym) {
return std::nullopt;
}
-std::optional<size_t> ComputeOffsetsHelper::HasSpecialAlign(const Symbol &sym,
- Scope &scope) {
+std::optional<size_t> ComputeOffsetsHelper::HasSpecialAlign(
+ const Symbol &sym, Scope &scope) {
// On AIX, if the component that is not the first component and is
// a float of 8 bytes or larger, it has the 4-byte alignment.
// Only set the special alignment for bind(c) derived type on that platform.
>From 664f8b87e3d4f0f7fbd611e48603a587f9f37722 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 2 Jan 2025 18:23:15 -0500
Subject: [PATCH 4/5] Address review comments
---
flang/lib/Semantics/compute-offsets.cpp | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index 31bce0ae92ba9a..a1f97018781ab9 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -70,25 +70,29 @@ class ComputeOffsetsHelper {
equivalenceBlock_;
};
+// This function is only called if the target platform is AIX.
static bool isReal8OrLarger(const Fortran::semantics::DeclTypeSpec *type) {
return ((type->IsNumeric(common::TypeCategory::Real) ||
type->IsNumeric(common::TypeCategory::Complex)) &&
evaluate::ToInt64(type->numericTypeSpec().kind()) > 4);
}
+// This function is only called if the target platform is AIX.
+// It determines the alignment of a component. If the component is a derived
+// type, the alignment is computed accordingly.
std::optional<size_t> ComputeOffsetsHelper::CompAlignment(const Symbol &sym) {
size_t max_align{0};
bool contain_double{false};
- const auto derivedTypeSpec{sym.GetType()->AsDerived()};
+ auto derivedTypeSpec{sym.GetType()->AsDerived()};
DirectComponentIterator directs{*derivedTypeSpec};
- for (auto it = directs.begin(); it != directs.end(); ++it) {
+ for (auto it{directs.begin()}; it != directs.end(); ++it) {
auto type{it->GetType()};
auto s{GetSizeAndAlignment(*it, true)};
if (isReal8OrLarger(type)) {
max_align = std::max(max_align, 4UL);
contain_double = true;
} else if (type->AsDerived()) {
- if (const auto newAlgin = CompAlignment(*it)) {
+ if (const auto newAlgin{CompAlignment(*it)}) {
max_align = std::max(max_align, s.alignment);
} else {
return std::nullopt;
@@ -98,18 +102,22 @@ std::optional<size_t> ComputeOffsetsHelper::CompAlignment(const Symbol &sym) {
}
}
- if (contain_double)
+ if (contain_double) {
return max_align;
- else
+ } else {
return std::nullopt;
+ }
}
+// This function is only called if the target platform is AIX.
+// Special alignment is needed only if it is a bind(c) derived type
+// and contain real type components that have larger than 4 bytes.
std::optional<size_t> ComputeOffsetsHelper::HasSpecialAlign(
const Symbol &sym, Scope &scope) {
// On AIX, if the component that is not the first component and is
// a float of 8 bytes or larger, it has the 4-byte alignment.
// Only set the special alignment for bind(c) derived type on that platform.
- if (const auto type = sym.GetType()) {
+ if (const auto type{sym.GetType()}) {
auto &symOwner{sym.owner()};
if (symOwner.symbol() && symOwner.IsDerivedType() &&
symOwner.symbol()->attrs().HasAny({semantics::Attr::BIND_C}) &&
@@ -390,10 +398,7 @@ std::size_t ComputeOffsetsHelper::DoSymbol(
return 0;
}
std::size_t previousOffset{offset_};
- size_t alignVal{s.alignment};
- if (newAlign) {
- alignVal = newAlign.value();
- }
+ size_t alignVal{newAlign.value_or(s.alignment)};
offset_ = Align(offset_, alignVal);
std::size_t padding{offset_ - previousOffset};
symbol.set_size(s.size);
>From 5a4b9abb9e6e237b82abd31700ce550cb928c318 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 9 Jan 2025 17:21:28 -0500
Subject: [PATCH 5/5] Address review comments
---
.../flang/Optimizer/Dialect/FIRTypes.td | 3 +++
flang/lib/Lower/ConvertType.cpp | 5 +++--
flang/lib/Optimizer/Dialect/FIRType.cpp | 16 +++++++++++++--
flang/test/Lower/CUDA/cuda-devptr.cuf | 4 ++--
.../test/Lower/HLFIR/bindc-value-derived.f90 | 18 ++++++++---------
flang/test/Lower/OpenMP/copyin.f90 | 2 +-
flang/test/Lower/intentout-deallocate.f90 | 20 +++++++++----------
.../mlir/Transforms/DialectConversion.h | 16 ---------------
8 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 4d832a49236bf1..6ae74f16a72d37 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -346,6 +346,9 @@ def fir_RecordType : FIR_Type<"Record", "type"> {
void finalize(llvm::ArrayRef<TypePair> lenPList,
llvm::ArrayRef<TypePair> typeList);
+ // fir.type is unpacked by default. If the flag is set, the packed fir.type
+ // is generated and the alignment is enforced by explicit padding by i8
+ // array fields.
bool isPacked() const;
void pack(bool);
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 40dbaa28ce7cac..b0c4546f021e9a 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -400,6 +400,7 @@ struct TypeBuilderImpl {
// (1) The data components.
if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
size_t prev_offset{0};
+ unsigned padCounter{0};
// In HLFIR the parent component is the first fir.type component.
for (const auto &componentName :
typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
@@ -419,7 +420,7 @@ struct TypeBuilderImpl {
fir::SequenceType::Shape shape{static_cast<int64_t>(pad)};
mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)};
prev_offset += pad;
- cs.emplace_back("", padTy);
+ cs.emplace_back("__padding"+std::to_string(padCounter++), padTy);
}
prev_offset += compSize;
}
@@ -436,7 +437,7 @@ struct TypeBuilderImpl {
mlir::Type i8Ty{mlir::IntegerType::get(context, 8)};
fir::SequenceType::Shape shape{static_cast<int64_t>(pad)};
mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)};
- cs.emplace_back("", padTy);
+ cs.emplace_back("__padding"+std::to_string(padCounter++), padTy);
}
}
}
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index ea06eb092ed918..acd07ea10b3c91 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -904,6 +904,10 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
}
RecordType::TypeList typeList;
+ if (!parser.parseOptionalLess()) {
+ result.pack(true);
+ }
+
if (!parser.parseOptionalLBrace()) {
while (true) {
llvm::StringRef field;
@@ -917,8 +921,10 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
if (parser.parseOptionalComma())
break;
}
- if (parser.parseRBrace())
- return {};
+ if (parser.parseOptionalGreater()) {
+ if (parser.parseRBrace())
+ return {};
+ }
}
if (parser.parseGreater())
@@ -945,6 +951,9 @@ void fir::RecordType::print(mlir::AsmPrinter &printer) const {
printer << ')';
}
if (getTypeList().size()) {
+ if (isPacked()) {
+ printer << '<';
+ }
char ch = '{';
for (auto p : getTypeList()) {
printer << ch << p.first << ':';
@@ -952,6 +961,9 @@ void fir::RecordType::print(mlir::AsmPrinter &printer) const {
ch = ',';
}
printer << '}';
+ if (isPacked()) {
+ printer << '>';
+ }
}
recordTypeVisited.erase(uniqueKey());
}
diff --git a/flang/test/Lower/CUDA/cuda-devptr.cuf b/flang/test/Lower/CUDA/cuda-devptr.cuf
index 2eac890970d52b..561d92ecd3e2e7 100644
--- a/flang/test/Lower/CUDA/cuda-devptr.cuf
+++ b/flang/test/Lower/CUDA/cuda-devptr.cuf
@@ -38,8 +38,8 @@ end
! CHECK-LABEL: func.func @_QPsub2()
! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
-! CHECK: %[[CPTR:.*]] = fir.field_index cptr, !fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>
-! CHECK: %[[CPTR_COORD:.*]] = fir.coordinate_of %{{.*}}#1, %[[CPTR]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.field) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
+! CHECK: %[[CPTR:.*]] = fir.field_index cptr, !fir.type<_QM__fortran_builtinsT__builtin_c_devptr{{[<]?}}{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}{{[>]?}}>
+! CHECK: %[[CPTR_COORD:.*]] = fir.coordinate_of %{{.*}}#1, %[[CPTR]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{{[<]?}}{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}{{[>]?}}>>, !fir.field) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
! CHECK: %[[ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
! CHECK: %[[ADDRESS_COORD:.*]] = fir.coordinate_of %[[CPTR_COORD]], %[[ADDRESS]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
! CHECK: %[[ADDRESS_LOADED:.*]] = fir.load %[[ADDRESS_COORD]] : !fir.ref<i64>
diff --git a/flang/test/Lower/HLFIR/bindc-value-derived.f90 b/flang/test/Lower/HLFIR/bindc-value-derived.f90
index 7a2196dfc8bf12..5af9f8edc804c9 100644
--- a/flang/test/Lower/HLFIR/bindc-value-derived.f90
+++ b/flang/test/Lower/HLFIR/bindc-value-derived.f90
@@ -14,11 +14,11 @@ subroutine test(x) bind(c)
call use_it(x%i)
end subroutine
! CHECK-LABEL: func.func @test(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.type<_QMbindc_byvalTt{i:i32}>
-! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMbindc_byvalTt{i:i32}>
-! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>
-! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QMbindc_byvalFtestEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>)
-! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_2]]#0{"i"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>) -> !fir.ref<i32>
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>
+! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QMbindc_byvalFtestEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>)
+! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_2]]#0{"i"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) -> !fir.ref<i32>
! CHECK: fir.call @_QPuse_it(%[[VAL_3]]) fastmath<contract> : (!fir.ref<i32>) -> ()
! CHECK: return
! CHECK: }
@@ -28,10 +28,10 @@ subroutine call_it(x)
call test(x)
end subroutine
! CHECK-LABEL: func.func @_QMbindc_byvalPcall_it(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>
-! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMbindc_byvalFcall_itEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>)
-! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#1 : !fir.ref<!fir.type<_QMbindc_byvalTt{i:i32}>>
-! CHECK: fir.call @test(%[[VAL_2]]) proc_attrs<bind_c> fastmath<contract> : (!fir.type<_QMbindc_byvalTt{i:i32}>) -> ()
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]}} {uniq_name = "_QMbindc_byvalFcall_itEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>)
+! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#1 : !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>
+! CHECK: fir.call @test(%[[VAL_2]]) proc_attrs<bind_c> fastmath<contract> : (!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>) -> ()
! CHECK: return
! CHECK: }
end module
diff --git a/flang/test/Lower/OpenMP/copyin.f90 b/flang/test/Lower/OpenMP/copyin.f90
index f3d147c10668f4..9e9ccf8e3d9142 100644
--- a/flang/test/Lower/OpenMP/copyin.f90
+++ b/flang/test/Lower/OpenMP/copyin.f90
@@ -86,7 +86,7 @@ subroutine copyin_char_chararray()
end
! CHECK-LABEL: func.func @_QPcopyin_derived_type() {
-! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFcopyin_derived_typeE.b.my_type.t_arr) : !fir.ref<!fir.array<2x1x!fir.type<_QM__fortran_type_infoTvalue{genre:i8,__padding0:!fir.array<7xi8>,value:i64}>>>
+! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFcopyin_derived_typeE.b.my_type.t_arr) : !fir.ref<!fir.array<2x1x!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>>>
! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_2:.*]] = arith.constant 2 : index
! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index
diff --git a/flang/test/Lower/intentout-deallocate.f90 b/flang/test/Lower/intentout-deallocate.f90
index 8e7ccbcc9fdb9d..931cf7d48885f3 100644
--- a/flang/test/Lower/intentout-deallocate.f90
+++ b/flang/test/Lower/intentout-deallocate.f90
@@ -123,24 +123,24 @@ subroutine sub5(t)
! on the caller side.
! CHECK-LABEL: func.func @_QMmod1Psub4()
-! FIR: %[[BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub4Et"}
+! FIR: %[[BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub4Et"}
! HLFIR: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub4Et"
! CHECK-NOT: fir.call @_FortranAAllocatableDeallocate
-! CHECK: fir.call @_QMmod1Psub5(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>>) -> ()
+! CHECK: fir.call @_QMmod1Psub5(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>) -> ()
! Check deallocation of allocatble intent(out) on the callee side. Deallocation
! is done with a runtime call.
! CHECK-LABEL: func.func @_QMmod1Psub5(
-! FIR-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>> {fir.bindc_name = "t"})
+! FIR-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>> {fir.bindc_name = "t"})
! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub5Et"
-! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#1]*}} : !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>>
-! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>) -> !fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>
-! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>) -> i64
+! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#1]*}} : !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>) -> !fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>
+! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>) -> i64
! CHECK: %[[C0:.*]] = arith.constant 0 : i64
! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64
! CHECK: fir.if %[[IS_ALLOCATED]] {
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]]{{[#1]*}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]]{{[#1]*}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
subroutine sub6()
@@ -152,11 +152,11 @@ subroutine sub6()
! Deallocation is done with a runtime call.
! CHECK-LABEL: func.func @_QMmod1Psub6()
-! FIR: %[[BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub6Et"}
+! FIR: %[[BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub6Et"}
! HLFIR: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub6Et"
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOX]]{{[#1]*}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOX]]{{[#1]*}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
-! CHECK: fir.call @sub7(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{i:i32}>>>>) -> ()
+! CHECK: fir.call @sub7(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>) -> ()
subroutine sub8()
integer, allocatable :: a(:)
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h b/mlir/include/mlir/Transforms/DialectConversion.h
index 99826cdebb343d..9ed63f7ee5b814 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -391,22 +391,6 @@ class TypeConverter {
return callback(derivedType, results);
};
}
- /// With callback of form: `std::optional<LogicalResult>(
- /// T, SmallVectorImpl<Type> &, bool)`.
- template <typename T, typename FnT>
- std::enable_if_t<std::is_invocable_v<FnT, T, SmallVectorImpl<Type> &, bool>,
- ConversionCallbackFn>
- wrapCallback(FnT &&callback) const {
- return [callback = std::forward<FnT>(callback)](
- Type type, SmallVectorImpl<Type> &results,
- bool isPacked) -> std::optional<LogicalResult> {
- T derivedType = dyn_cast<T>(type);
- if (!derivedType)
- return std::nullopt;
- return callback(derivedType, results, isPacked);
- };
- }
-
/// Register a type conversion.
void registerConversion(ConversionCallbackFn callback) {
conversions.emplace_back(std::move(callback));
More information about the flang-commits
mailing list