llvm-project/flang/lib/Optimizer/Transforms/OptimizeArrayRepacking.cpp
Slava Zakharin 4775b96898
[flang] Optimize redundant array repacking. (#147881)
This patch allows optimizing redundant array repacking, when
the source array is statically known to be contiguous.
This is part of the implementation plan for the array repacking
feature, though, it does not affect any real life use case
as long as FIR inlining is not a thing. I experimented with
simple cases of FIR inling using `-inline-all`, and I recorded
these cases in optimize-array-repacking.fir tests.
2025-07-14 09:41:42 -07:00

91 lines
3.4 KiB
C++

//===- OptimizeArrayRepacking.cpp -----------------------------------------===//
//
// 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 removes redundant fir.pack_array operations, if it can prove
/// that the source array is contiguous. In this case, it relink all uses
/// of fir.pack_array result to the source. If such a rewrite happens,
/// it may turn the using fir.unpack_array operation into one with the same
/// temp and original operands - these are also removed as redundant.
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Support/Utils.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
namespace fir {
#define GEN_PASS_DEF_OPTIMIZEARRAYREPACKING
#include "flang/Optimizer/Transforms/Passes.h.inc"
} // namespace fir
namespace {
class OptimizeArrayRepackingPass
: public fir::impl::OptimizeArrayRepackingBase<OptimizeArrayRepackingPass> {
public:
void runOnOperation() override;
};
/// Relinks all uses of redundant fir.pack_array to the source.
class PackingOfContiguous : public mlir::OpRewritePattern<fir::PackArrayOp> {
public:
using OpRewritePattern::OpRewritePattern;
mlir::LogicalResult matchAndRewrite(fir::PackArrayOp,
mlir::PatternRewriter &) const override;
};
/// Erases fir.unpack_array with have the matching temp and original
/// operands.
class NoopUnpacking : public mlir::OpRewritePattern<fir::UnpackArrayOp> {
public:
using OpRewritePattern::OpRewritePattern;
mlir::LogicalResult matchAndRewrite(fir::UnpackArrayOp,
mlir::PatternRewriter &) const override;
};
} // namespace
mlir::LogicalResult
PackingOfContiguous::matchAndRewrite(fir::PackArrayOp op,
mlir::PatternRewriter &rewriter) const {
mlir::Value box = op.getArray();
if (hlfir::isSimplyContiguous(box, !op.getInnermost())) {
rewriter.replaceAllUsesWith(op, box);
rewriter.eraseOp(op);
return mlir::success();
}
return mlir::failure();
}
mlir::LogicalResult
NoopUnpacking::matchAndRewrite(fir::UnpackArrayOp op,
mlir::PatternRewriter &rewriter) const {
if (op.getTemp() == op.getOriginal()) {
rewriter.eraseOp(op);
return mlir::success();
}
return mlir::failure();
}
void OptimizeArrayRepackingPass::runOnOperation() {
mlir::func::FuncOp funcOp = getOperation();
mlir::MLIRContext *context = &getContext();
mlir::RewritePatternSet patterns(context);
mlir::GreedyRewriteConfig config;
config.setRegionSimplificationLevel(
mlir::GreedySimplifyRegionLevel::Disabled);
patterns.insert<PackingOfContiguous>(context);
patterns.insert<NoopUnpacking>(context);
if (mlir::failed(
mlir::applyPatternsGreedily(funcOp, std::move(patterns), config))) {
mlir::emitError(funcOp.getLoc(), "failure in array repacking optimization");
signalPassFailure();
}
}