
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.
91 lines
3.4 KiB
C++
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();
|
|
}
|
|
}
|