2018-06-22 00:49:33 +08:00
|
|
|
//===- mlir-opt.cpp - MLIR Optimizer Driver -------------------------------===//
|
|
|
|
//
|
2020-01-26 11:58:30 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
2019-12-24 01:35:36 +08:00
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-06-22 00:49:33 +08:00
|
|
|
//
|
2019-12-24 01:35:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2018-06-22 00:49:33 +08:00
|
|
|
//
|
2019-06-24 23:41:52 +08:00
|
|
|
// Main entry function for mlir-opt for when built as standalone binary.
|
2018-06-22 00:49:33 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Introduce memref bound checking.
Introduce analysis to check memref accesses (in MLFunctions) for out of bound
ones. It works as follows:
$ mlir-opt -memref-bound-check test/Transforms/memref-bound-check.mlir
/tmp/single.mlir:10:12: error: 'load' op memref out of upper bound access along dimension tensorflow/mlir#1
%x = load %A[%idxtensorflow/mlir#0, %idxtensorflow/mlir#1] : memref<9 x 9 x i32>
^
/tmp/single.mlir:10:12: error: 'load' op memref out of lower bound access along dimension tensorflow/mlir#1
%x = load %A[%idxtensorflow/mlir#0, %idxtensorflow/mlir#1] : memref<9 x 9 x i32>
^
/tmp/single.mlir:10:12: error: 'load' op memref out of upper bound access along dimension tensorflow/mlir#2
%x = load %A[%idxtensorflow/mlir#0, %idxtensorflow/mlir#1] : memref<9 x 9 x i32>
^
/tmp/single.mlir:10:12: error: 'load' op memref out of lower bound access along dimension tensorflow/mlir#2
%x = load %A[%idxtensorflow/mlir#0, %idxtensorflow/mlir#1] : memref<9 x 9 x i32>
^
/tmp/single.mlir:12:12: error: 'load' op memref out of upper bound access along dimension tensorflow/mlir#1
%y = load %B[%idy] : memref<128 x i32>
^
/tmp/single.mlir:12:12: error: 'load' op memref out of lower bound access along dimension tensorflow/mlir#1
%y = load %B[%idy] : memref<128 x i32>
^
#map0 = (d0, d1) -> (d0, d1)
#map1 = (d0, d1) -> (d0 * 128 - d1)
mlfunc @test() {
%0 = alloc() : memref<9x9xi32>
%1 = alloc() : memref<128xi32>
for %i0 = -1 to 9 {
for %i1 = -1 to 9 {
%2 = affine_apply #map0(%i0, %i1)
%3 = load %0[%2tensorflow/mlir#0, %2tensorflow/mlir#1] : memref<9x9xi32>
%4 = affine_apply #map1(%i0, %i1)
%5 = load %1[%4] : memref<128xi32>
}
}
return
}
- Improves productivity while manually / semi-automatically developing MLIR for
testing / prototyping; also provides an indirect way to catch errors in
transformations.
- This pass is an easy way to test the underlying affine analysis
machinery including low level routines.
Some code (in getMemoryRegion()) borrowed from @andydavis cl/218263256.
While on this:
- create mlir/Analysis/Passes.h; move Pass.h up from mlir/Transforms/ to mlir/
- fix a bug in AffineAnalysis.cpp::toAffineExpr
TODO: extend to non-constant loop bounds (straightforward). Will transparently
work for all accesses once floordiv, mod, ceildiv are supported in the
AffineMap -> FlatAffineConstraints conversion.
PiperOrigin-RevId: 219397961
2018-10-31 08:43:06 +08:00
|
|
|
#include "mlir/Analysis/Passes.h"
|
2020-02-12 17:03:40 +08:00
|
|
|
#include "mlir/InitAllDialects.h"
|
|
|
|
#include "mlir/InitAllPasses.h"
|
2020-02-19 06:56:45 +08:00
|
|
|
#include "mlir/IR/Dialect.h"
|
|
|
|
#include "mlir/IR/MLIRContext.h"
|
2019-02-28 06:45:36 +08:00
|
|
|
#include "mlir/Pass/Pass.h"
|
2019-02-28 02:59:29 +08:00
|
|
|
#include "mlir/Pass/PassManager.h"
|
2019-01-11 23:22:57 +08:00
|
|
|
#include "mlir/Support/FileUtilities.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "mlir/Support/MlirOptMain.h"
|
2018-06-22 00:49:33 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2018-07-08 10:12:22 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
2018-06-22 06:22:42 +08:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2018-08-31 08:35:15 +08:00
|
|
|
|
2018-06-22 06:22:42 +08:00
|
|
|
using namespace llvm;
|
2019-06-24 23:41:52 +08:00
|
|
|
using namespace mlir;
|
2018-06-22 06:22:42 +08:00
|
|
|
|
2020-02-12 17:03:40 +08:00
|
|
|
namespace mlir {
|
|
|
|
// Defined in the test directory, no public header.
|
|
|
|
void registerConvertToTargetEnvPass();
|
|
|
|
void registerInliner();
|
|
|
|
void registerMemRefBoundCheck();
|
|
|
|
void registerPassManagerTestPass();
|
|
|
|
void registerPatternsTestPass();
|
2020-02-25 02:35:33 +08:00
|
|
|
void registerPrintOpAvailabilityPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
void registerSimpleParametricTilingPass();
|
|
|
|
void registerSymbolTestPasses();
|
2020-02-15 05:41:01 +08:00
|
|
|
void registerTestAffineDataCopyPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
void registerTestAllReduceLoweringPass();
|
|
|
|
void registerTestCallGraphPass();
|
|
|
|
void registerTestConstantFold();
|
|
|
|
void registerTestFunc();
|
|
|
|
void registerTestGpuMemoryPromotionPass();
|
|
|
|
void registerTestLinalgTransforms();
|
|
|
|
void registerTestLivenessPass();
|
|
|
|
void registerTestLoopFusion();
|
|
|
|
void registerTestLoopMappingPass();
|
|
|
|
void registerTestMatchers();
|
|
|
|
void registerTestMemRefDependenceCheck();
|
|
|
|
void registerTestMemRefStrideCalculation();
|
|
|
|
void registerTestOpaqueLoc();
|
|
|
|
void registerTestParallelismDetection();
|
2020-02-21 23:18:22 +08:00
|
|
|
void registerTestGpuParallelLoopMappingPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
void registerTestVectorConversions();
|
|
|
|
void registerTestVectorToLoopsPass();
|
|
|
|
void registerVectorizerTestPass();
|
|
|
|
} // namespace mlir
|
|
|
|
|
2018-06-22 06:22:42 +08:00
|
|
|
static cl::opt<std::string>
|
2019-06-24 23:41:52 +08:00
|
|
|
inputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
|
2018-06-22 06:22:42 +08:00
|
|
|
|
2019-06-24 23:41:52 +08:00
|
|
|
static cl::opt<std::string> outputFilename("o", cl::desc("Output filename"),
|
|
|
|
cl::value_desc("filename"),
|
|
|
|
cl::init("-"));
|
2018-06-22 06:22:42 +08:00
|
|
|
|
2018-06-25 00:10:36 +08:00
|
|
|
static cl::opt<bool>
|
2018-09-03 13:01:45 +08:00
|
|
|
splitInputFile("split-input-file",
|
|
|
|
cl::desc("Split the input file into pieces and process each "
|
|
|
|
"chunk independently"),
|
|
|
|
cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
2019-06-20 02:21:41 +08:00
|
|
|
verifyDiagnostics("verify-diagnostics",
|
2018-09-03 13:01:45 +08:00
|
|
|
cl::desc("Check that emitted diagnostics match "
|
|
|
|
"expected-* lines on the corresponding line"),
|
|
|
|
cl::init(false));
|
2018-06-22 06:22:42 +08:00
|
|
|
|
2019-03-05 04:33:13 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
verifyPasses("verify-each",
|
|
|
|
cl::desc("Run the verifier after each transformation pass"),
|
|
|
|
cl::init(true));
|
|
|
|
|
2020-02-12 17:03:40 +08:00
|
|
|
void registerTestPasses() {
|
|
|
|
registerConvertToTargetEnvPass();
|
|
|
|
registerInliner();
|
|
|
|
registerMemRefBoundCheck();
|
|
|
|
registerPassManagerTestPass();
|
|
|
|
registerPatternsTestPass();
|
2020-02-25 02:35:33 +08:00
|
|
|
registerPrintOpAvailabilityPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
registerSimpleParametricTilingPass();
|
|
|
|
registerSymbolTestPasses();
|
2020-02-15 05:41:01 +08:00
|
|
|
registerTestAffineDataCopyPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
registerTestAllReduceLoweringPass();
|
|
|
|
registerTestCallGraphPass();
|
|
|
|
registerTestConstantFold();
|
|
|
|
registerTestFunc();
|
|
|
|
registerTestGpuMemoryPromotionPass();
|
|
|
|
registerTestLinalgTransforms();
|
|
|
|
registerTestLivenessPass();
|
|
|
|
registerTestLoopFusion();
|
|
|
|
registerTestLoopMappingPass();
|
|
|
|
registerTestMatchers();
|
|
|
|
registerTestMemRefDependenceCheck();
|
|
|
|
registerTestMemRefStrideCalculation();
|
|
|
|
registerTestOpaqueLoc();
|
|
|
|
registerTestParallelismDetection();
|
2020-02-21 23:18:22 +08:00
|
|
|
registerTestGpuParallelLoopMappingPass();
|
2020-02-12 17:03:40 +08:00
|
|
|
registerTestVectorConversions();
|
|
|
|
registerTestVectorToLoopsPass();
|
|
|
|
registerVectorizerTestPass();
|
|
|
|
|
|
|
|
// The following passes are using global initializers, just link them in.
|
|
|
|
if (std::getenv("bar") != (char *)-1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// TODO: move these to the test folder.
|
|
|
|
createTestMemRefBoundCheckPass();
|
|
|
|
createTestMemRefDependenceCheckPass();
|
|
|
|
}
|
|
|
|
|
2020-02-19 06:56:45 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
showDialects("show-dialects",
|
|
|
|
cl::desc("Print the list of registered dialects"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2018-06-25 00:10:36 +08:00
|
|
|
int main(int argc, char **argv) {
|
2020-02-12 17:03:40 +08:00
|
|
|
registerAllDialects();
|
|
|
|
registerAllPasses();
|
|
|
|
registerTestPasses();
|
2018-08-06 12:12:29 +08:00
|
|
|
InitLLVM y(argc, argv);
|
2018-06-23 13:03:48 +08:00
|
|
|
|
2019-03-17 11:34:23 +08:00
|
|
|
// Register any pass manager command line options.
|
|
|
|
registerPassManagerCLOptions();
|
2019-09-14 03:09:50 +08:00
|
|
|
PassPipelineCLParser passPipeline("", "Compiler passes to run");
|
2019-03-17 11:34:23 +08:00
|
|
|
|
2018-11-07 10:34:18 +08:00
|
|
|
// Parse pass names in main to ensure static initialization completed.
|
2018-06-22 06:22:42 +08:00
|
|
|
cl::ParseCommandLineOptions(argc, argv, "MLIR modular optimizer driver\n");
|
2018-06-22 00:49:33 +08:00
|
|
|
|
2020-02-19 06:56:45 +08:00
|
|
|
MLIRContext context;
|
|
|
|
if(showDialects) {
|
|
|
|
llvm::outs() << "Registered Dialects:\n";
|
|
|
|
for(Dialect *dialect : context.getRegisteredDialects()) {
|
|
|
|
llvm::outs() << dialect->getNamespace() << "\n";
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-06-23 01:39:19 +08:00
|
|
|
// Set up the input file.
|
2019-01-11 23:22:57 +08:00
|
|
|
std::string errorMessage;
|
|
|
|
auto file = openInputFile(inputFilename, &errorMessage);
|
|
|
|
if (!file) {
|
|
|
|
llvm::errs() << errorMessage << "\n";
|
2019-06-24 23:41:52 +08:00
|
|
|
return 1;
|
2018-06-23 01:39:19 +08:00
|
|
|
}
|
|
|
|
|
2019-06-24 23:41:52 +08:00
|
|
|
auto output = openOutputFile(outputFilename, &errorMessage);
|
|
|
|
if (!output) {
|
|
|
|
llvm::errs() << errorMessage << "\n";
|
|
|
|
exit(1);
|
|
|
|
}
|
2018-06-25 23:10:46 +08:00
|
|
|
|
2019-09-14 03:09:50 +08:00
|
|
|
return failed(MlirOptMain(output->os(), std::move(file), passPipeline,
|
2019-06-24 23:41:52 +08:00
|
|
|
splitInputFile, verifyDiagnostics, verifyPasses));
|
2018-06-22 00:49:33 +08:00
|
|
|
}
|