[flang] Fix type mismatch in verification error

FIR models Fortran intrinsic types with deliberate KIND values. Like
Fortran, COMPLEX and REAL have related KINDs in FIR. Lowering now
converts REAL types to floating point (MLIR) up front. This patch moves
the code to convert from FIR RealType to MLIR FloatType out of codegen
and into the builder, allowing FIR ComplexTypes to have their element
type returned as an MLIR FloatType.

We should consider whether to replace fir::ComplexType with
mlir::ComplexType at some point. I believe these types are presently
used to convey distinctins in the target ABIs in the Tilikum bridge
however.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D127636

Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This commit is contained in:
Eric Schweitz 2022-06-13 21:35:23 +02:00 committed by Valentin Clement
parent 3abaefe64c
commit f5b970c9ef
No known key found for this signature in database
GPG Key ID: 086D54783C928776
5 changed files with 64 additions and 30 deletions

View File

@ -16,6 +16,13 @@
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Type.h"
namespace fir {
class FIROpsDialect;
class KindMapping;
using KindTy = unsigned;
} // namespace fir
#define GET_TYPEDEF_CLASSES
#include "flang/Optimizer/Dialect/FIROpsTypes.h.inc"
@ -37,11 +44,6 @@ class ValueRange;
} // namespace mlir
namespace fir {
class FIROpsDialect;
using KindTy = unsigned;
namespace detail {
struct RecordTypeStorage;
} // namespace detail
@ -257,6 +259,14 @@ bool isCharacterProcedureTuple(mlir::Type type, bool acceptRawFunc = true);
/// Returns null on error.
mlir::Type applyPathToType(mlir::Type rootTy, mlir::ValueRange path);
/// Does this function type have a result that requires binding the result value
/// with storage in a fir.save_result operation in order to use the result?
bool hasAbstractResult(mlir::FunctionType ty);
/// Convert llvm::Type::TypeID to mlir::Type
mlir::Type fromRealTypeID(mlir::MLIRContext *context, llvm::Type::TypeID typeID,
fir::KindTy kind);
} // namespace fir
#endif // FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H

View File

@ -153,6 +153,7 @@ def fir_ComplexType : FIR_Type<"Complex", "complex"> {
using KindTy = unsigned;
mlir::Type getElementType() const;
mlir::Type getEleType(const fir::KindMapping &kindMap) const;
}];
}

View File

@ -338,7 +338,8 @@ public:
// convert a front-end kind value to either a std or LLVM IR dialect type
// fir.real<n> --> llvm.anyfloat where anyfloat is a kind mapping
mlir::Type convertRealType(fir::KindTy kind) {
return fromRealTypeID(kindMapping.getRealTypeID(kind), kind);
return fir::fromRealTypeID(&getContext(), kindMapping.getRealTypeID(kind),
kind);
}
// fir.array<c ... :any> --> llvm<"[...[c x any]]">
@ -369,28 +370,6 @@ public:
mlir::IntegerType::get(&getContext(), 8));
}
/// Convert llvm::Type::TypeID to mlir::Type
mlir::Type fromRealTypeID(llvm::Type::TypeID typeID, fir::KindTy kind) {
switch (typeID) {
case llvm::Type::TypeID::HalfTyID:
return mlir::FloatType::getF16(&getContext());
case llvm::Type::TypeID::BFloatTyID:
return mlir::FloatType::getBF16(&getContext());
case llvm::Type::TypeID::FloatTyID:
return mlir::FloatType::getF32(&getContext());
case llvm::Type::TypeID::DoubleTyID:
return mlir::FloatType::getF64(&getContext());
case llvm::Type::TypeID::X86_FP80TyID:
return mlir::FloatType::getF80(&getContext());
case llvm::Type::TypeID::FP128TyID:
return mlir::FloatType::getF128(&getContext());
default:
mlir::emitError(mlir::UnknownLoc::get(&getContext()))
<< "unsupported type: !fir.real<" << kind << ">";
return {};
}
}
KindMapping &getKindMap() { return kindMapping; }
private:

View File

@ -14,6 +14,8 @@
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Support/FIRContext.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "flang/Optimizer/Support/Utils.h"
#include "mlir/Dialect/CommonFolders.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
@ -3437,8 +3439,11 @@ mlir::Type fir::applyPathToType(mlir::Type eleTy, mlir::ValueRange path) {
return mlir::Type{};
})
.Case<fir::ComplexType>([&](fir::ComplexType ty) {
if (fir::isa_integer((*i++).getType()))
return ty.getElementType();
auto x = *i;
if (auto *op = (*i++).getDefiningOp())
if (fir::isa_integer(x.getType()))
return ty.getEleType(fir::getKindMapping(
op->getParentOfType<mlir::ModuleOp>()));
return mlir::Type{};
})
.Case<mlir::ComplexType>([&](mlir::ComplexType ty) {

View File

@ -12,6 +12,7 @@
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "flang/Tools/PointerModels.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinDialect.h"
@ -483,6 +484,13 @@ mlir::Type fir::ComplexType::getElementType() const {
return fir::RealType::get(getContext(), getFKind());
}
// Return the MLIR float type of the complex element type.
mlir::Type fir::ComplexType::getEleType(const fir::KindMapping &kindMap) const {
auto fkind = getFKind();
auto realTypeID = kindMap.getRealTypeID(fkind);
return fir::fromRealTypeID(getContext(), realTypeID, fkind);
}
//===----------------------------------------------------------------------===//
// HeapType
//===----------------------------------------------------------------------===//
@ -925,6 +933,37 @@ bool fir::isCharacterProcedureTuple(mlir::Type ty, bool acceptRawFunc) {
fir::isa_integer(tuple.getType(1));
}
bool fir::hasAbstractResult(mlir::FunctionType ty) {
if (ty.getNumResults() == 0)
return false;
auto resultType = ty.getResult(0);
return resultType.isa<fir::SequenceType, fir::BoxType, fir::RecordType>();
}
/// Convert llvm::Type::TypeID to mlir::Type. \p kind is provided for error
/// messages only.
mlir::Type fir::fromRealTypeID(mlir::MLIRContext *context,
llvm::Type::TypeID typeID, fir::KindTy kind) {
switch (typeID) {
case llvm::Type::TypeID::HalfTyID:
return mlir::FloatType::getF16(context);
case llvm::Type::TypeID::BFloatTyID:
return mlir::FloatType::getBF16(context);
case llvm::Type::TypeID::FloatTyID:
return mlir::FloatType::getF32(context);
case llvm::Type::TypeID::DoubleTyID:
return mlir::FloatType::getF64(context);
case llvm::Type::TypeID::X86_FP80TyID:
return mlir::FloatType::getF80(context);
case llvm::Type::TypeID::FP128TyID:
return mlir::FloatType::getF128(context);
default:
mlir::emitError(mlir::UnknownLoc::get(context))
<< "unsupported type: !fir.real<" << kind << ">";
return {};
}
}
//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//