llvm-project/mlir/lib/Transforms/Vectorize.cpp

77 lines
2.7 KiB
C++
Raw Normal View History

[MLIR] Basic infrastructure for vectorization test This CL implements a very simple loop vectorization **test** and the basic infrastructure to support it. The test simply consists in: 1. matching the loops in the MLFunction and all the Load/Store operations nested under the loop; 2. testing whether all the Load/Store are contiguous along the innermost memory dimension along that particular loop. If any reference is non-contiguous (i.e. the ForStmt SSAValue appears in the expression), then the loop is not-vectorizable. The simple test above can gradually be extended with more interesting behaviors to account for the fact that a layout permutation may exist that enables contiguity etc. All these will come in due time but it is worthwhile noting that the test already supports detection of outer-vetorizable loops. In implementing this test, I also added a recursive MLFunctionMatcher and some sugar that can capture patterns such as `auto gemmLike = Doall(Doall(Red(LoadStore())))` and allows iterating on the matched IR structures. For now it just uses in order traversal but post-order DFS will be useful in the future once IR rewrites start occuring. One may note that the memory management design decision follows a different pattern from MLIR. After evaluating different designs and how they quickly increase cognitive overhead, I decided to opt for the simplest solution in my view: a class-wide (threadsafe) RAII context. This way, a pass that needs MLFunctionMatcher can just have its own locally scoped BumpPtrAllocator and everything is cleaned up when the pass is destroyed. If passes are expected to have a longer lifetime, then the contexts can easily be scoped inside the runOnMLFunction call and storage lifetime reduced. Lastly, whatever the scope of threading (module, function, pass), this is expected to also be future-proof wrt concurrency (but this is a detail atm). PiperOrigin-RevId: 217622889
2018-10-18 09:01:44 +08:00
//===- Vectorize.cpp - Vectorize Pass Impl ----------------------*- 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 vectorization of loops, operations and data types to
// a target-independent, n-D virtual vector abstraction.
//
//===----------------------------------------------------------------------===//
#include "mlir/Analysis/LoopAnalysis.h"
#include "mlir/Analysis/MLFunctionMatcher.h"
#include "mlir/StandardOps/StandardOps.h"
#include "mlir/Transforms/Pass.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace mlir;
static cl::list<unsigned> clVirtualVectorSize(
"virtual-vector-size",
cl::desc("Specify n-D virtual vector size for vectorization"),
cl::ZeroOrMore);
namespace {
struct Vectorize : public MLFunctionPass {
PassResult runOnMLFunction(MLFunction *f) override;
// Thread-safe RAII contexts local to pass, BumpPtrAllocator freed on exit.
MLFunctionMatcherContext MLContext;
};
} // end anonymous namespace
PassResult Vectorize::runOnMLFunction(MLFunction *f) {
using matcher::Doall;
/// TODO(ntv): support at least 4 cases for each load/store:
/// 1. invariant along the loop index -> 1-D vectorizable with broadcast
/// 2. contiguous along the fastest varying dimension wrt the loop index
/// -> a. 1-D vectorizable via stripmine/sink if loop is not innermost
/// -> b. 1-D vectorizable if loop is innermost
/// 3. contiguous along non-fastest varying dimension wrt the loop index
/// -> needs data layout + copy to vectorize 1-D
/// 4. not contiguous => not vectorizable
auto pointwiseLike = Doall();
auto &matches = pointwiseLike.match(f);
for (auto loop : matches) {
auto *doall = cast<ForStmt>(loop.first);
if (!isVectorizableLoop(*doall)) {
outs() << "\nNon-vectorizable loop: ";
doall->print(outs());
continue;
}
outs() << "\nVectorizable loop: ";
doall->print(outs());
}
return PassResult::Success;
}
MLFunctionPass *mlir::createVectorizePass() { return new Vectorize(); }