-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][NFC] Extract FIROpConversion to its own files #86213
Conversation
@llvm/pr-subscribers-flang-codegen @llvm/pr-subscribers-flang-fir-hlfir Author: Valentin Clement (バレンタイン クレメン) (clementval) ChangesThis PR extract The code is only moved to the new files and not modified. This split is done in a similar way for the Patch is 67.40 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/86213.diff 5 Files Affected:
diff --git a/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h
new file mode 100644
index 00000000000000..5339917af7e08c
--- /dev/null
+++ b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h
@@ -0,0 +1,249 @@
+//===-- FIROpPatterns.h -- FIR operation conversion patterns ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H
+#define FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H
+
+#include "flang/Optimizer/CodeGen/TypeConverter.h"
+#include "mlir/Conversion/LLVMCommon/Pattern.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+
+namespace fir {
+
+struct FIRToLLVMPassOptions;
+
+// TODO: This should really be recovered from the specified target.
+static constexpr unsigned defaultAddressSpace = 0u;
+
+class ConvertFIRToLLVMPattern : public mlir::ConvertToLLVMPattern {
+public:
+ ConvertFIRToLLVMPattern(llvm::StringRef rootOpName,
+ mlir::MLIRContext *context,
+ const fir::LLVMTypeConverter &typeConverter,
+ const fir::FIRToLLVMPassOptions &options,
+ mlir::PatternBenefit benefit = 1);
+
+protected:
+ mlir::Type convertType(mlir::Type ty) const {
+ return lowerTy().convertType(ty);
+ }
+
+ // Convert FIR type to LLVM without turning fir.box<T> into memory
+ // reference.
+ mlir::Type convertObjectType(mlir::Type firType) const;
+
+ mlir::LLVM::ConstantOp
+ genI32Constant(mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
+ int value) const;
+
+ mlir::LLVM::ConstantOp
+ genConstantOffset(mlir::Location loc,
+ mlir::ConversionPatternRewriter &rewriter,
+ int offset) const;
+
+ /// Perform an extension or truncation as needed on an integer value. Lowering
+ /// to the specific target may involve some sign-extending or truncation of
+ /// values, particularly to fit them from abstract box types to the
+ /// appropriate reified structures.
+ mlir::Value integerCast(mlir::Location loc,
+ mlir::ConversionPatternRewriter &rewriter,
+ mlir::Type ty, mlir::Value val) const;
+ struct TypePair {
+ mlir::Type fir;
+ mlir::Type llvm;
+ };
+
+ TypePair getBoxTypePair(mlir::Type firBoxTy) const;
+
+ /// Construct code sequence to extract the specific value from a `fir.box`.
+ mlir::Value getValueFromBox(mlir::Location loc, TypePair boxTy,
+ mlir::Value box, mlir::Type resultTy,
+ mlir::ConversionPatternRewriter &rewriter,
+ int boxValue) const;
+
+ /// Method to construct code sequence to get the triple for dimension `dim`
+ /// from a box.
+ llvm::SmallVector<mlir::Value, 3>
+ getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys,
+ TypePair boxTy, mlir::Value box, mlir::Value dim,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ llvm::SmallVector<mlir::Value, 3>
+ getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys,
+ TypePair boxTy, mlir::Value box, int dim,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ mlir::Value
+ loadDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box,
+ mlir::Value dim, int off, mlir::Type ty,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ mlir::Value
+ getDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box,
+ int dim, int off, mlir::Type ty,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ mlir::Value getStrideFromBox(mlir::Location loc, TypePair boxTy,
+ mlir::Value box, unsigned dim,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ /// Read base address from a fir.box. Returned address has type ty.
+ mlir::Value
+ getBaseAddrFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ mlir::Value
+ getElementSizeFromBox(mlir::Location loc, mlir::Type resultTy, TypePair boxTy,
+ mlir::Value box,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ // Get the element type given an LLVM type that is of the form
+ // (array|struct|vector)+ and the provided indexes.
+ mlir::Type getBoxEleTy(mlir::Type type,
+ llvm::ArrayRef<std::int64_t> indexes) const;
+
+ // Return LLVM type of the object described by a fir.box of \p boxType.
+ mlir::Type getLlvmObjectTypeFromBoxType(mlir::Type boxType) const;
+
+ /// Read the address of the type descriptor from a box.
+ mlir::Value
+ loadTypeDescAddress(mlir::Location loc, TypePair boxTy, mlir::Value box,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ // Load the attribute from the \p box and perform a check against \p maskValue
+ // The final comparison is implemented as `(attribute & maskValue) != 0`.
+ mlir::Value genBoxAttributeCheck(mlir::Location loc, TypePair boxTy,
+ mlir::Value box,
+ mlir::ConversionPatternRewriter &rewriter,
+ unsigned maskValue) const;
+
+ template <typename... ARGS>
+ mlir::LLVM::GEPOp genGEP(mlir::Location loc, mlir::Type ty,
+ mlir::ConversionPatternRewriter &rewriter,
+ mlir::Value base, ARGS... args) const {
+ llvm::SmallVector<mlir::LLVM::GEPArg> cv = {args...};
+ auto llvmPtrTy =
+ mlir::LLVM::LLVMPointerType::get(ty.getContext(), /*addressSpace=*/0);
+ return rewriter.create<mlir::LLVM::GEPOp>(loc, llvmPtrTy, ty, base, cv);
+ }
+
+ // Find the Block in which the alloca should be inserted.
+ // The order to recursively find the proper block:
+ // 1. An OpenMP Op that will be outlined.
+ // 2. A LLVMFuncOp
+ // 3. The first ancestor that is an OpenMP Op or a LLVMFuncOp
+ mlir::Block *getBlockForAllocaInsert(mlir::Operation *op) const;
+
+ // Generate an alloca of size 1 for an object of type \p llvmObjectTy in the
+ // allocation address space provided for the architecture in the DataLayout
+ // specification. If the address space is different from the devices
+ // program address space we perform a cast. In the case of most architectures
+ // the program and allocation address space will be the default of 0 and no
+ // cast will be emitted.
+ mlir::Value
+ genAllocaAndAddrCastWithType(mlir::Location loc, mlir::Type llvmObjectTy,
+ unsigned alignment,
+ mlir::ConversionPatternRewriter &rewriter) const;
+
+ const fir::LLVMTypeConverter &lowerTy() const {
+ return *static_cast<const fir::LLVMTypeConverter *>(
+ this->getTypeConverter());
+ }
+
+ void attachTBAATag(mlir::LLVM::AliasAnalysisOpInterface op,
+ mlir::Type baseFIRType, mlir::Type accessFIRType,
+ mlir::LLVM::GEPOp gep) const {
+ lowerTy().attachTBAATag(op, baseFIRType, accessFIRType, gep);
+ }
+
+ unsigned
+ getAllocaAddressSpace(mlir::ConversionPatternRewriter &rewriter) const;
+
+ unsigned
+ getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) const;
+
+ const fir::FIRToLLVMPassOptions &options;
+
+ using ConvertToLLVMPattern::match;
+ using ConvertToLLVMPattern::matchAndRewrite;
+};
+
+template <typename SourceOp>
+class FIROpConversion : public ConvertFIRToLLVMPattern {
+public:
+ using OpAdaptor = typename SourceOp::Adaptor;
+
+ explicit FIROpConversion(const LLVMTypeConverter &typeConverter,
+ const fir::FIRToLLVMPassOptions &options,
+ mlir::PatternBenefit benefit = 1)
+ : ConvertFIRToLLVMPattern(SourceOp::getOperationName(),
+ &typeConverter.getContext(), typeConverter,
+ options, benefit) {}
+
+ /// Wrappers around the RewritePattern methods that pass the derived op type.
+ void rewrite(mlir::Operation *op, mlir::ArrayRef<mlir::Value> operands,
+ mlir::ConversionPatternRewriter &rewriter) const final {
+ rewrite(mlir::cast<SourceOp>(op),
+ OpAdaptor(operands, mlir::cast<SourceOp>(op)), rewriter);
+ }
+ mlir::LogicalResult match(mlir::Operation *op) const final {
+ return match(mlir::cast<SourceOp>(op));
+ }
+ mlir::LogicalResult
+ matchAndRewrite(mlir::Operation *op, mlir::ArrayRef<mlir::Value> operands,
+ mlir::ConversionPatternRewriter &rewriter) const final {
+ return matchAndRewrite(mlir::cast<SourceOp>(op),
+ OpAdaptor(operands, mlir::cast<SourceOp>(op)),
+ rewriter);
+ }
+
+ /// Rewrite and Match methods that operate on the SourceOp type. These must be
+ /// overridden by the derived pattern class.
+ virtual mlir::LogicalResult match(SourceOp op) const {
+ llvm_unreachable("must override match or matchAndRewrite");
+ }
+ virtual void rewrite(SourceOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ llvm_unreachable("must override rewrite or matchAndRewrite");
+ }
+ virtual mlir::LogicalResult
+ matchAndRewrite(SourceOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ if (mlir::failed(match(op)))
+ return mlir::failure();
+ rewrite(op, adaptor, rewriter);
+ return mlir::success();
+ }
+
+private:
+ using ConvertFIRToLLVMPattern::matchAndRewrite;
+ using ConvertToLLVMPattern::match;
+};
+
+/// FIR conversion pattern template
+template <typename FromOp>
+class FIROpAndTypeConversion : public FIROpConversion<FromOp> {
+public:
+ using FIROpConversion<FromOp>::FIROpConversion;
+ using OpAdaptor = typename FromOp::Adaptor;
+
+ mlir::LogicalResult
+ matchAndRewrite(FromOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const final {
+ mlir::Type ty = this->convertType(op.getType());
+ return doRewrite(op, ty, adaptor, rewriter);
+ }
+
+ virtual mlir::LogicalResult
+ doRewrite(FromOp addr, mlir::Type ty, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const = 0;
+};
+
+} // namespace fir
+
+#endif // FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H
diff --git a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
index 396c1363925554..79b3bfe4e80e09 100644
--- a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h
@@ -94,8 +94,8 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
// to LLVM IR dialect here.
//
// fir.complex<T> | std.complex<T> --> llvm<"{t,t}">
- template <typename C> mlir::Type convertComplexType(C cmplx) const {
- LLVM_DEBUG(llvm::dbgs() << "type convert: " << cmplx << '\n');
+ template <typename C>
+ mlir::Type convertComplexType(C cmplx) const {
auto eleTy = cmplx.getElementType();
return convertType(specifics->complexMemoryType(eleTy));
}
diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
index 175ab9fefda2ae..879bc28d017a35 100644
--- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt
+++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
@@ -3,6 +3,7 @@ add_flang_library(FIRCodeGen
CGOps.cpp
CodeGen.cpp
CodeGenOpenMP.cpp
+ FIROpPatterns.cpp
PreCGRewrite.cpp
TBAABuilder.cpp
Target.cpp
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index faf90ef6b50a9b..b29a8b7a6f24e9 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -14,6 +14,8 @@
#include "CGOps.h"
#include "flang/Optimizer/CodeGen/CodeGenOpenMP.h"
+#include "flang/Optimizer/CodeGen/FIROpPatterns.h"
+#include "flang/Optimizer/CodeGen/TypeConverter.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
@@ -58,41 +60,38 @@ namespace fir {
#define DEBUG_TYPE "flang-codegen"
-// fir::LLVMTypeConverter for converting to LLVM IR dialect types.
-#include "flang/Optimizer/CodeGen/TypeConverter.h"
-
// TODO: This should really be recovered from the specified target.
static constexpr unsigned defaultAlign = 8;
-static constexpr unsigned defaultAddressSpace = 0u;
+// static constexpr unsigned defaultAddressSpace = 0u;
/// `fir.box` attribute values as defined for CFI_attribute_t in
/// flang/ISO_Fortran_binding.h.
static constexpr unsigned kAttrPointer = CFI_attribute_pointer;
static constexpr unsigned kAttrAllocatable = CFI_attribute_allocatable;
-static inline unsigned
-getAllocaAddressSpace(mlir::ConversionPatternRewriter &rewriter) {
- mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
- assert(parentOp != nullptr &&
- "expected insertion block to have parent operation");
- if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
- if (mlir::Attribute addrSpace =
- mlir::DataLayout(module).getAllocaMemorySpace())
- return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
- return defaultAddressSpace;
-}
-
-static inline unsigned
-getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) {
- mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
- assert(parentOp != nullptr &&
- "expected insertion block to have parent operation");
- if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
- if (mlir::Attribute addrSpace =
- mlir::DataLayout(module).getProgramMemorySpace())
- return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
- return defaultAddressSpace;
-}
+// static inline unsigned
+// getAllocaAddressSpace(mlir::ConversionPatternRewriter &rewriter) {
+// mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
+// assert(parentOp != nullptr &&
+// "expected insertion block to have parent operation");
+// if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
+// if (mlir::Attribute addrSpace =
+// mlir::DataLayout(module).getAllocaMemorySpace())
+// return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
+// return defaultAddressSpace;
+// }
+
+// static inline unsigned
+// getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) {
+// mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
+// assert(parentOp != nullptr &&
+// "expected insertion block to have parent operation");
+// if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
+// if (mlir::Attribute addrSpace =
+// mlir::DataLayout(module).getProgramMemorySpace())
+// return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
+// return defaultAddressSpace;
+// }
static inline mlir::Type getLlvmPtrType(mlir::MLIRContext *context,
unsigned addressSpace = 0) {
@@ -151,333 +150,9 @@ static unsigned getLenParamFieldId(mlir::Type ty) {
return getTypeDescFieldId(ty) + 1;
}
-namespace {
-/// FIR conversion pattern template
-template <typename FromOp>
-class FIROpConversion : public mlir::ConvertOpToLLVMPattern<FromOp> {
-public:
- explicit FIROpConversion(const fir::LLVMTypeConverter &lowering,
- const fir::FIRToLLVMPassOptions &options)
- : mlir::ConvertOpToLLVMPattern<FromOp>(lowering), options(options) {}
-
-protected:
- mlir::Type convertType(mlir::Type ty) const {
- return lowerTy().convertType(ty);
- }
-
- // Convert FIR type to LLVM without turning fir.box<T> into memory
- // reference.
- mlir::Type convertObjectType(mlir::Type firType) const {
- if (auto boxTy = firType.dyn_cast<fir::BaseBoxType>())
- return lowerTy().convertBoxTypeAsStruct(boxTy);
- return lowerTy().convertType(firType);
- }
-
- mlir::LLVM::ConstantOp
- genI32Constant(mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
- int value) const {
- mlir::Type i32Ty = rewriter.getI32Type();
- mlir::IntegerAttr attr = rewriter.getI32IntegerAttr(value);
- return rewriter.create<mlir::LLVM::ConstantOp>(loc, i32Ty, attr);
- }
-
- mlir::LLVM::ConstantOp
- genConstantOffset(mlir::Location loc,
- mlir::ConversionPatternRewriter &rewriter,
- int offset) const {
- mlir::Type ity = lowerTy().offsetType();
- mlir::IntegerAttr cattr = rewriter.getI32IntegerAttr(offset);
- return rewriter.create<mlir::LLVM::ConstantOp>(loc, ity, cattr);
- }
-
- /// Perform an extension or truncation as needed on an integer value. Lowering
- /// to the specific target may involve some sign-extending or truncation of
- /// values, particularly to fit them from abstract box types to the
- /// appropriate reified structures.
- mlir::Value integerCast(mlir::Location loc,
- mlir::ConversionPatternRewriter &rewriter,
- mlir::Type ty, mlir::Value val) const {
- auto valTy = val.getType();
- // If the value was not yet lowered, lower its type so that it can
- // be used in getPrimitiveTypeSizeInBits.
- if (!valTy.isa<mlir::IntegerType>())
- valTy = convertType(valTy);
- auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty);
- auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy);
- if (toSize < fromSize)
- return rewriter.create<mlir::LLVM::TruncOp>(loc, ty, val);
- if (toSize > fromSize)
- return rewriter.create<mlir::LLVM::SExtOp>(loc, ty, val);
- return val;
- }
-
- struct TypePair {
- mlir::Type fir;
- mlir::Type llvm;
- };
-
- TypePair getBoxTypePair(mlir::Type firBoxTy) const {
- mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(
- mlir::cast<fir::BaseBoxType>(firBoxTy));
- return TypePair{firBoxTy, llvmBoxTy};
- }
-
- /// Construct code sequence to extract the specific value from a `fir.box`.
- mlir::Value getValueFromBox(mlir::Location loc, TypePair boxTy,
- mlir::Value box, mlir::Type resultTy,
- mlir::ConversionPatternRewriter &rewriter,
- int boxValue) const {
- if (box.getType().isa<mlir::LLVM::LLVMPointerType>()) {
- auto pty = ::getLlvmPtrType(resultTy.getContext());
- auto p = rewriter.create<mlir::LLVM::GEPOp>(
- loc, pty, boxTy.llvm, box,
- llvm::ArrayRef<mlir::LLVM::GEPArg>{0, boxValue});
- auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, resultTy, p);
- attachTBAATag(loadOp, boxTy.fir, nullptr, p);
- return loadOp;
- }
- return rewriter.create<mlir::LLVM::ExtractValueOp>(loc, box, boxValue);
- }
-
- /// Method to construct code sequence to get the triple for dimension `dim`
- /// from a box.
- llvm::SmallVector<mlir::Value, 3>
- getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys,
- TypePair boxTy, mlir::Value box, mlir::Value dim,
- mlir::ConversionPatternRewriter &rewriter) const {
- mlir::Value l0 =
- loadDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter);
- mlir::Value l1 =
- loadDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter);
- mlir::Value l2 =
- loadDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter);
- return {l0, l1, l2};
- }
-
- llvm::SmallVector<mlir::Value, 3>
- getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys,
- TypePair boxTy, mlir::Value box, int dim,
- mlir::ConversionPatternRewriter &rewriter) const {
- mlir::Value l0 =
- getDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter);
- mlir::Value l1 =
- getDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter);
- mli...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this cleanup!
This PR extracts
FIROpConversion
andFIROpAndTypeConversion
templated base patterns to a header file. All the functions from FIROpConversion that do not require the template argument are moved to a base class namedConvertFIRToLLVMPattern
.This move is done so the
FIROpConversion
pattern and all its utility functions can be reused outside of the codegen pass.For the most part the code is only moved to the new files and not modified. The only update is that addition of the PatternBenefit argument with a default value to the constructor so it can be forwarded to the
ConversionPattern
ctor.This split is done in a similar way for the
ConvertOpToLLVMPattern
base pattern that is based on theConvertToLLVMPattern
base class inmlir/include/mlir/Conversion/LLVMCommon/Pattern.h
.