[flang-commits] [flang] [flang] Added fir.is_contiguous_box and fir.box_total_elements ops. (PR #131047)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Thu Mar 13 11:56:53 PDT 2025
================
@@ -0,0 +1,157 @@
+//===- SimplifyFIROperations.cpp -- simplify complex FIR operations ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass transforms some FIR operations into their equivalent
+/// implementations using other FIR operations. The transformation
+/// can legally use SCF dialect and generate Fortran runtime calls.
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/CUFCommon.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/LowLevelIntrinsics.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
+#include "flang/Optimizer/Transforms/Passes.h"
+#include "flang/Optimizer/Transforms/Utils.h"
+#include "flang/Runtime/entry-names.h"
+#include "flang/Support/Fortran.h"
+#include "mlir/IR/Matchers.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
+
+namespace fir {
+#define GEN_PASS_DEF_SIMPLIFYFIROPERATIONS
+#include "flang/Optimizer/Transforms/Passes.h.inc"
+} // namespace fir
+
+#define DEBUG_TYPE "flang-simplify-fir-operations"
+
+namespace {
+/// Pass runner.
+class SimplifyFIROperationsPass
+ : public fir::impl::SimplifyFIROperationsBase<SimplifyFIROperationsPass> {
+public:
+ using fir::impl::SimplifyFIROperationsBase<
+ SimplifyFIROperationsPass>::SimplifyFIROperationsBase;
+
+ void runOnOperation() override final;
+};
+
+/// Base class for all conversions holding the pass options.
+template <typename Op>
+class ConversionBase : public mlir::OpRewritePattern<Op> {
+public:
+ using mlir::OpRewritePattern<Op>::OpRewritePattern;
+
+ template <typename... Args>
+ ConversionBase(mlir::MLIRContext *context, Args &&...args)
+ : mlir::OpRewritePattern<Op>(context),
+ options{std::forward<Args>(args)...} {}
+
+ mlir::LogicalResult matchAndRewrite(Op,
+ mlir::PatternRewriter &) const override;
+
+protected:
+ fir::SimplifyFIROperationsOptions options;
+};
+
+/// fir::IsContiguousBoxOp converter.
+using IsContiguousBoxCoversion = ConversionBase<fir::IsContiguousBoxOp>;
+
+/// fir::BoxTotalElementsOp converter.
+using BoxTotalElementsConversion = ConversionBase<fir::BoxTotalElementsOp>;
+} // namespace
+
+/// Generate a call to IsContiguous/IsContiguousUpTo function or an inline
+/// sequence reading extents/strides from the box and checking them.
+/// This conversion may produce fir.box_elesize and a loop (for assumed
+/// rank).
+template <>
+mlir::LogicalResult IsContiguousBoxCoversion::matchAndRewrite(
+ fir::IsContiguousBoxOp op, mlir::PatternRewriter &rewriter) const {
+ mlir::Location loc = op.getLoc();
+ fir::FirOpBuilder builder(rewriter, op.getOperation());
+ // TODO: support preferInlineImplementation.
+ bool doInline = options.preferInlineImplementation && false;
+ if (!doInline) {
+ // Generate Fortran runtime call.
+ mlir::Value result;
+ if (op.getInnermost()) {
+ mlir::Value one =
+ builder.createIntegerConstant(loc, builder.getI8Type(), 1);
+ result =
+ fir::runtime::genIsContiguousUpTo(builder, loc, op.getBox(), one);
+ } else {
+ result = fir::runtime::genIsContiguous(builder, loc, op.getBox());
+ }
+ result = builder.createConvert(loc, op.getType(), result);
+ rewriter.replaceOp(op, result);
+ return mlir::success();
+ }
+
+ // Generate inline implementation.
+ TODO(loc, "inline IsContiguousBoxOp");
+ return mlir::success();
+}
+
+/// Generate a call to Size runtime function or an inline
+/// sequence reading extents from the box an multiplying them.
+/// This conversion may produce a loop (for assumed rank).
+template <>
+mlir::LogicalResult BoxTotalElementsConversion::matchAndRewrite(
+ fir::BoxTotalElementsOp op, mlir::PatternRewriter &rewriter) const {
+ mlir::Location loc = op.getLoc();
+ fir::FirOpBuilder builder(rewriter, op.getOperation());
+ // TODO: support preferInlineImplementation.
+ // Reading the extent from the box for 1D arrays probably
+ // results in less code than the call, so we can always
+ // inline it.
+ bool doInline = options.preferInlineImplementation && false;
+ if (!doInline) {
+ // Generate Fortran runtime call.
+ mlir::Value result = fir::runtime::genSize(builder, loc, op.getBox());
+ result = builder.createConvert(loc, op.getType(), result);
+ rewriter.replaceOp(op, result);
+ return mlir::success();
+ }
+
+ // Generate inline implementation.
+ TODO(loc, "inline BoxTotalElementsOp");
+ return mlir::success();
+}
+
+void SimplifyFIROperationsPass::runOnOperation() {
+ mlir::ModuleOp module = getOperation();
+ mlir::MLIRContext &context = getContext();
+ mlir::ConversionTarget target(context);
+ target.addIllegalOp<fir::IsContiguousBoxOp>();
+ target.addIllegalOp<fir::BoxTotalElementsOp>();
+ mlir::RewritePatternSet patterns(&context);
+ fir::populateSimplifyFIROperationsPatterns(patterns,
+ preferInlineImplementation);
+ if (mlir::failed(
+ mlir::applyPartialConversion(module, target, std::move(patterns)))) {
----------------
vzakhari wrote:
Thanks! I will use the greedy rewriter.
https://github.com/llvm/llvm-project/pull/131047
More information about the flang-commits
mailing list