[flang-commits] [flang] [flang][NFC] Extract FIROpConversion to its own files (PR #86213)
via flang-commits
flang-commits at lists.llvm.org
Thu Mar 21 15:57:01 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Valentin Clement (バレンタイン クレメン) (clementval)
<details>
<summary>Changes</summary>
This PR extract `FIROpConversion` and `FIROpAndTypeConversion` 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 named `ConvertFIRToLLVMPattern`.
This move is done so the `FIROpConversion` pattern and all its utility functions can be reused outside of the codegen pass.
The code is only moved to the new files and not modified.
This split is done in a similar way for the `ConvertOpToLLVMPattern` base pattern that is based on the `ConvertToLLVMPattern` base class in `mlir/include/mlir/Conversion/LLVMCommon/Pattern.h`.
---
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:
- (added) flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h (+249)
- (modified) flang/include/flang/Optimizer/CodeGen/TypeConverter.h (+2-2)
- (modified) flang/lib/Optimizer/CodeGen/CMakeLists.txt (+1)
- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+94-415)
- (added) flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp (+315)
``````````diff
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/86213
More information about the flang-commits
mailing list