mirror of
https://github.com/intel/llvm.git
synced 2026-01-30 14:07:28 +08:00
This CL follows up on a memory leak issue related to SmallVector growth that escapes the BumpPtrAllocator. The fix is to properly use ArrayRef and placement new to define away the issue. The following renaming is also applied: 1. MLFunctionMatcher -> NestedPattern 2. MLFunctionMatches -> NestedMatch As a consequence all allocations are now guaranteed to live on the BumpPtrAllocator. PiperOrigin-RevId: 231047766
104 lines
3.6 KiB
C++
104 lines
3.6 KiB
C++
//===- ComposeAffineMaps.cpp - MLIR Affine Transform Class-----*- C++ -*-===//
|
|
//
|
|
// Copyright 2019 The MLIR Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// =============================================================================
|
|
//
|
|
// This file implements a testing pass which composes affine maps from
|
|
// AffineApplyOps in a Function, by forward subtituting results from an
|
|
// AffineApplyOp into any of its users which are also AffineApplyOps.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/Analysis/AffineAnalysis.h"
|
|
#include "mlir/Analysis/NestedMatcher.h"
|
|
#include "mlir/IR/AffineMap.h"
|
|
#include "mlir/IR/Attributes.h"
|
|
#include "mlir/IR/Builders.h"
|
|
#include "mlir/IR/BuiltinOps.h"
|
|
#include "mlir/IR/InstVisitor.h"
|
|
#include "mlir/Pass.h"
|
|
#include "mlir/StandardOps/StandardOps.h"
|
|
#include "mlir/Transforms/Passes.h"
|
|
#include "mlir/Transforms/Utils.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace mlir;
|
|
|
|
namespace {
|
|
|
|
// ComposeAffineMaps walks inst blocks in a Function, and for each
|
|
// AffineApplyOp, forward substitutes its results into any users which are
|
|
// also AffineApplyOps. After forward subtituting its results, AffineApplyOps
|
|
// with no remaining uses are collected and erased after the walk.
|
|
// TODO(andydavis) Remove this when Chris adds instruction combiner pass.
|
|
struct ComposeAffineMaps : public FunctionPass {
|
|
explicit ComposeAffineMaps() : FunctionPass(&ComposeAffineMaps::passID) {}
|
|
PassResult runOnFunction(Function *f) override;
|
|
|
|
// Thread-safe RAII contexts local to pass, BumpPtrAllocator freed on exit.
|
|
NestedPatternContext MLContext;
|
|
|
|
static char passID;
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
char ComposeAffineMaps::passID = 0;
|
|
|
|
FunctionPass *mlir::createComposeAffineMapsPass() {
|
|
return new ComposeAffineMaps();
|
|
}
|
|
|
|
static bool affineApplyOp(const Instruction &inst) {
|
|
const auto &opInst = cast<OperationInst>(inst);
|
|
return opInst.isa<AffineApplyOp>();
|
|
}
|
|
|
|
PassResult ComposeAffineMaps::runOnFunction(Function *f) {
|
|
using matcher::Op;
|
|
|
|
auto pattern = Op(affineApplyOp);
|
|
auto apps = pattern.match(f);
|
|
for (auto m : apps) {
|
|
auto app = cast<OperationInst>(m.first)->cast<AffineApplyOp>();
|
|
SmallVector<Value *, 8> operands(app->getOperands());
|
|
FuncBuilder b(m.first);
|
|
auto newApp = makeComposedAffineApply(&b, app->getLoc(),
|
|
app->getAffineMap(), operands);
|
|
unsigned idx = 0;
|
|
for (auto *v : app->getResults()) {
|
|
v->replaceAllUsesWith(newApp->getResult(idx++));
|
|
}
|
|
}
|
|
{
|
|
auto pattern = Op(affineApplyOp);
|
|
auto apps = pattern.match(f);
|
|
std::reverse(apps.begin(), apps.end());
|
|
for (auto m : apps) {
|
|
auto app = cast<OperationInst>(m.first)->cast<AffineApplyOp>();
|
|
bool hasNonEmptyUse = llvm::any_of(
|
|
app->getResults(), [](Value *r) { return !r->use_empty(); });
|
|
if (!hasNonEmptyUse) {
|
|
m.first->erase();
|
|
}
|
|
}
|
|
}
|
|
return success();
|
|
}
|
|
|
|
static PassRegistration<ComposeAffineMaps> pass("compose-affine-maps",
|
|
"Compose affine maps");
|