13#ifndef FORTRAN_OPTIMIZER_SUPPORT_UTILS_H
14#define FORTRAN_OPTIMIZER_SUPPORT_UTILS_H
16#include "flang/Optimizer/Builder/FIRBuilder.h"
17#include "flang/Optimizer/Builder/Todo.h"
18#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
19#include "flang/Optimizer/Dialect/FIROps.h"
20#include "flang/Optimizer/Dialect/FIRType.h"
21#include "flang/Optimizer/Support/FatalError.h"
22#include "flang/Support/default-kinds.h"
23#include "mlir/Dialect/Arith/IR/Arith.h"
24#include "mlir/Dialect/Func/IR/FuncOps.h"
25#include "mlir/IR/BuiltinAttributes.h"
26#include "mlir/IR/BuiltinOps.h"
27#include "mlir/Interfaces/FunctionInterfaces.h"
28#include "llvm/ADT/DenseMap.h"
29#include "llvm/ADT/StringRef.h"
32#include "flang/Optimizer/CodeGen/TypeConverter.h"
36inline std::int64_t
toInt(mlir::arith::ConstantOp cop) {
37 return mlir::cast<mlir::IntegerAttr>(cop.getValue())
43inline std::vector<fir::KindTy>
45 return {
static_cast<fir::KindTy
>(defKinds.GetDefaultKind(
46 Fortran::common::TypeCategory::Character)),
47 static_cast<fir::KindTy
>(
48 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Complex)),
49 static_cast<fir::KindTy
>(defKinds.doublePrecisionKind()),
50 static_cast<fir::KindTy
>(
51 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Integer)),
52 static_cast<fir::KindTy
>(
53 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Logical)),
54 static_cast<fir::KindTy
>(
55 defKinds.GetDefaultKind(Fortran::common::TypeCategory::Real))};
58inline std::string mlirTypeToString(mlir::Type type) {
60 llvm::raw_string_ostream sstream(result);
65inline std::optional<int> mlirFloatTypeToKind(mlir::Type type) {
68 else if (type.isBF16())
70 else if (type.isF32())
72 else if (type.isF64())
74 else if (type.isF80())
76 else if (type.isF128())
81inline std::string mlirTypeToIntrinsicFortran(fir::FirOpBuilder &builder,
84 const llvm::Twine &name) {
85 if (
auto floatTy = mlir::dyn_cast<mlir::FloatType>(type)) {
86 if (std::optional<int> kind = mlirFloatTypeToKind(type))
87 return "REAL(KIND="s + std::to_string(*kind) +
")";
88 }
else if (
auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(type)) {
89 if (std::optional<int> kind = mlirFloatTypeToKind(cplxTy.getElementType()))
90 return "COMPLEX(KIND="s + std::to_string(*kind) +
")";
91 }
else if (type.isUnsignedInteger()) {
92 if (type.isInteger(8))
93 return "UNSIGNED(KIND=1)";
94 else if (type.isInteger(16))
95 return "UNSIGNED(KIND=2)";
96 else if (type.isInteger(32))
97 return "UNSIGNED(KIND=4)";
98 else if (type.isInteger(64))
99 return "UNSIGNED(KIND=8)";
100 else if (type.isInteger(128))
101 return "UNSIGNED(KIND=16)";
102 }
else if (type.isInteger(8))
103 return "INTEGER(KIND=1)";
104 else if (type.isInteger(16))
105 return "INTEGER(KIND=2)";
106 else if (type.isInteger(32))
107 return "INTEGER(KIND=4)";
108 else if (type.isInteger(64))
109 return "INTEGER(KIND=8)";
110 else if (type.isInteger(128))
111 return "INTEGER(KIND=16)";
112 else if (type == fir::LogicalType::get(builder.getContext(), 1))
113 return "LOGICAL(KIND=1)";
114 else if (type == fir::LogicalType::get(builder.getContext(), 2))
115 return "LOGICAL(KIND=2)";
116 else if (type == fir::LogicalType::get(builder.getContext(), 4))
117 return "LOGICAL(KIND=4)";
118 else if (type == fir::LogicalType::get(builder.getContext(), 8))
119 return "LOGICAL(KIND=8)";
122 fir::mlirTypeToString(type));
125inline void intrinsicTypeTODO(fir::FirOpBuilder &builder, mlir::Type type,
127 const llvm::Twine &intrinsicName) {
130 fir::mlirTypeToIntrinsicFortran(builder, type, loc, intrinsicName) +
131 " in " + intrinsicName);
134inline void intrinsicTypeTODO2(fir::FirOpBuilder &builder, mlir::Type type1,
135 mlir::Type type2, mlir::Location loc,
136 const llvm::Twine &intrinsicName) {
139 fir::mlirTypeToIntrinsicFortran(builder, type2, loc, intrinsicName) +
141 fir::mlirTypeToIntrinsicFortran(builder, type2, loc, intrinsicName) +
142 "} in " + intrinsicName);
145inline std::pair<Fortran::common::TypeCategory, KindMapping::KindTy>
146mlirTypeToCategoryKind(mlir::Location loc, mlir::Type type) {
147 if (
auto floatTy = mlir::dyn_cast<mlir::FloatType>(type)) {
148 if (std::optional<int> kind = mlirFloatTypeToKind(type))
149 return {Fortran::common::TypeCategory::Real, *kind};
150 }
else if (
auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(type)) {
151 if (std::optional<int> kind = mlirFloatTypeToKind(cplxTy.getElementType()))
152 return {Fortran::common::TypeCategory::Complex, *kind};
153 }
else if (type.isInteger(8))
154 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
155 : Fortran::common::TypeCategory::Integer,
157 else if (type.isInteger(16))
158 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
159 : Fortran::common::TypeCategory::Integer,
161 else if (type.isInteger(32))
162 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
163 : Fortran::common::TypeCategory::Integer,
165 else if (type.isInteger(64))
166 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
167 : Fortran::common::TypeCategory::Integer,
169 else if (type.isInteger(128))
170 return {type.isUnsignedInteger() ? Fortran::common::TypeCategory::Unsigned
171 : Fortran::common::TypeCategory::Integer,
173 else if (
auto logicalType = mlir::dyn_cast<fir::LogicalType>(type))
174 return {Fortran::common::TypeCategory::Logical, logicalType.getFKind()};
175 else if (
auto charType = mlir::dyn_cast<fir::CharacterType>(type))
176 return {Fortran::common::TypeCategory::Character, charType.getFKind()};
177 else if (mlir::isa<fir::RecordType>(type))
178 return {Fortran::common::TypeCategory::Derived, 0};
188 const mlir::SymbolTable *symbolTable =
nullptr);
196 const mlir::SymbolTable *symbolTable =
nullptr);
202 fir::RecordType recordType, llvm::StringRef component,
203 mlir::ModuleOp module,
const mlir::SymbolTable *symbolTable =
nullptr);
209 const mlir::SymbolTable *symbolTable =
nullptr);
212mlir::LLVM::ConstantOp
214 mlir::ConversionPatternRewriter &rewriter,
215 std::int64_t offset);
222 mlir::Type llvmObjectType, mlir::Type idxTy,
223 mlir::ConversionPatternRewriter &rewriter,
224 const mlir::DataLayout &dataLayout);
230mlir::Value genAllocationScaleSize(mlir::Location loc, mlir::Type dataTy,
232 mlir::ConversionPatternRewriter &rewriter);
238mlir::Value
integerCast(
const fir::LLVMTypeConverter &converter,
240 mlir::ConversionPatternRewriter &rewriter,
241 mlir::Type ty, mlir::Value val,
bool fold =
false);
Definition default-kinds.h:26
Definition AbstractConverter.h:37
mlir::Value integerCast(const fir::LLVMTypeConverter &converter, mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, mlir::Type ty, mlir::Value val, bool fold=false)
Definition Utils.cpp:110
std::string getPresentableFunctionName(mlir::FunctionOpInterface func)
Definition Utils.cpp:152
std::optional< bool > isNewAllocationResult(mlir::OpResult result)
Definition Utils.cpp:135
std::optional< bool > isRecordWithFinalRoutine(fir::RecordType recordType, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:55
std::optional< llvm::ArrayRef< int64_t > > getComponentLowerBoundsIfNonDefault(fir::RecordType recordType, llvm::StringRef component, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:40
std::int64_t toInt(mlir::arith::ConstantOp cop)
Return the integer value of a arith::ConstantOp.
Definition Utils.h:36
fir::TypeInfoOp lookupTypeInfoOp(fir::RecordType recordType, mlir::ModuleOp module, const mlir::SymbolTable *symbolTable=nullptr)
Definition Utils.cpp:18
mlir::LLVM::ConstantOp genConstantIndex(mlir::Location loc, mlir::Type ity, mlir::ConversionPatternRewriter &rewriter, std::int64_t offset)
Generate a LLVM constant value of type ity, using the provided offset.
Definition Utils.cpp:65
void emitFatalError(mlir::Location loc, const llvm::Twine &message, bool genCrashDiag=true)
Definition FatalError.h:25
mlir::Value computeElementDistance(mlir::Location loc, mlir::Type llvmObjectType, mlir::Type idxTy, mlir::ConversionPatternRewriter &rewriter, const mlir::DataLayout &dataLayout)
Definition Utils.cpp:73