2019-11-12 10:31:56 +08:00
|
|
|
//===--------------------------- main.cpp ---------------------------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The IBM Research Authors.
|
|
|
|
//
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-20 03:24:37 +08:00
|
|
|
#include <cmath>
|
|
|
|
#include <iostream>
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
#include "llvm/Bitcode/BitcodeWriter.h"
|
2019-12-23 09:33:33 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2019-11-16 02:10:41 +08:00
|
|
|
#include "llvm/Support/FileUtilities.h"
|
2019-12-23 09:33:33 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2019-11-16 02:10:41 +08:00
|
|
|
#include "llvm/Support/Regex.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
|
2019-11-02 05:09:48 +08:00
|
|
|
#include "src/builder/frontend_dialect_transformer.hpp"
|
2019-12-23 13:13:52 +08:00
|
|
|
#include "src/dialect/krnl/krnl_ops.hpp"
|
|
|
|
#include "src/dialect/onnx/onnx_ops.hpp"
|
|
|
|
#include "src/pass/passes.hpp"
|
2019-10-09 07:25:59 +08:00
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
#include "mlir/Conversion/LoopToStandard/ConvertLoopToStandard.h"
|
2019-11-08 00:42:40 +08:00
|
|
|
#include "mlir/ExecutionEngine/ExecutionEngine.h"
|
|
|
|
#include "mlir/ExecutionEngine/OptUtils.h"
|
|
|
|
#include "mlir/IR/MLIRContext.h"
|
2019-10-09 07:25:59 +08:00
|
|
|
#include "mlir/IR/Module.h"
|
2019-11-08 00:42:40 +08:00
|
|
|
#include "mlir/Parser.h"
|
|
|
|
#include "mlir/Pass/Pass.h"
|
|
|
|
#include "mlir/Pass/PassManager.h"
|
|
|
|
#include "mlir/Target/LLVMIR.h"
|
|
|
|
#include "mlir/Transforms/Passes.h"
|
2019-10-09 07:25:59 +08:00
|
|
|
|
2019-12-23 09:49:29 +08:00
|
|
|
void EmitLLVMBitCode(const mlir::OwningModuleRef &module);
|
|
|
|
|
2019-12-20 03:24:37 +08:00
|
|
|
using namespace std;
|
2019-10-30 01:57:56 +08:00
|
|
|
using namespace onnf;
|
2019-12-20 03:24:37 +08:00
|
|
|
|
2019-12-23 09:33:33 +08:00
|
|
|
void LoadMLIR(string inputFilename, mlir::MLIRContext &context,
|
|
|
|
mlir::OwningModuleRef &module) {
|
2019-11-19 08:37:58 +08:00
|
|
|
// Handle '.mlir' input to the ONNF frontend.
|
2019-11-16 02:10:41 +08:00
|
|
|
// The mlir format indicates that one or more of the supported
|
|
|
|
// representations are used in the file.
|
|
|
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
|
|
|
|
llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);
|
|
|
|
if (std::error_code EC = fileOrErr.getError()) {
|
|
|
|
llvm::errs() << "Could not open input file: " << EC.message() << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the input mlir.
|
|
|
|
llvm::SourceMgr sourceMgr;
|
|
|
|
sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc());
|
|
|
|
module = mlir::parseSourceFile(sourceMgr, &context);
|
|
|
|
if (!module) {
|
|
|
|
llvm::errs() << "Error can't load file " << inputFilename << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-23 09:49:29 +08:00
|
|
|
void EmitLLVMBitCode(const mlir::OwningModuleRef &module) {
|
|
|
|
error_code error;
|
|
|
|
llvm::raw_fd_ostream moduleBitcodeStream("model.bc", error,
|
|
|
|
llvm::sys::fs::F_None);
|
|
|
|
llvm::WriteBitcodeToFile(*mlir::translateModuleToLLVMIR(*module),
|
|
|
|
moduleBitcodeStream);
|
|
|
|
moduleBitcodeStream.flush();
|
|
|
|
}
|
|
|
|
|
2019-12-23 09:33:33 +08:00
|
|
|
int main(int argc, char *argv[]) {
|
2019-11-02 05:09:48 +08:00
|
|
|
mlir::registerDialect<mlir::ONNXOpsDialect>();
|
2019-11-12 10:31:56 +08:00
|
|
|
mlir::registerDialect<mlir::KrnlOpsDialect>();
|
2019-11-02 05:09:48 +08:00
|
|
|
|
2019-12-23 09:33:33 +08:00
|
|
|
llvm::cl::OptionCategory OnnfOptions("ONNF Options",
|
|
|
|
"These are frontend options.");
|
2019-12-23 09:49:29 +08:00
|
|
|
llvm::cl::opt<string> inputFilename(
|
2019-12-23 09:33:33 +08:00
|
|
|
llvm::cl::Positional, llvm::cl::desc("<input file>"), llvm::cl::init("-"),
|
|
|
|
llvm::cl::cat(OnnfOptions));
|
2019-12-23 12:52:49 +08:00
|
|
|
|
|
|
|
enum EmissionTargetType {
|
|
|
|
EmitONNXIR,
|
|
|
|
EmitMLIR,
|
|
|
|
EmitLLVMIR,
|
|
|
|
EmitLLVMBC,
|
|
|
|
};
|
|
|
|
llvm::cl::opt<EmissionTargetType> emissionTarget(
|
|
|
|
llvm::cl::desc("Choose target to emit:"),
|
|
|
|
llvm::cl::values(
|
2019-12-23 14:14:35 +08:00
|
|
|
clEnumVal(EmitONNXIR,
|
|
|
|
"Ingest ONNX and emit corresponding ONNX dialect."),
|
|
|
|
clEnumVal(EmitMLIR,
|
|
|
|
"Lower model to MLIR built-in transformation dialect."),
|
|
|
|
clEnumVal(EmitLLVMIR, "Lower model to LLVM IR (LLVM dialect)."),
|
|
|
|
clEnumVal(EmitLLVMBC, "Lower model to LLVM IR and emit (to file) "
|
|
|
|
"LLVM bitcode for model.")),
|
2019-12-23 12:52:49 +08:00
|
|
|
llvm::cl::init(EmitLLVMBC), llvm::cl::cat(OnnfOptions));
|
|
|
|
|
2019-12-23 09:33:33 +08:00
|
|
|
llvm::cl::HideUnrelatedOptions(OnnfOptions);
|
|
|
|
llvm::cl::ParseCommandLineOptions(argc, argv,
|
|
|
|
"ONNF MLIR modular optimizer driver\n");
|
|
|
|
|
2019-11-16 02:10:41 +08:00
|
|
|
// Decide if the input file is an ONNX model or a model specified
|
|
|
|
// in MLIR. The extension of the file is the decider.
|
2019-12-23 09:49:29 +08:00
|
|
|
string extension = inputFilename.substr(inputFilename.find_last_of(".") + 1);
|
|
|
|
bool inputIsONNX = (extension == "onnx");
|
|
|
|
bool inputIsMLIR = (extension == "mlir");
|
|
|
|
assert(inputIsONNX != inputIsMLIR &&
|
|
|
|
"Either ONNX model or MLIR file needs to be provided.");
|
2019-12-23 12:52:49 +08:00
|
|
|
|
|
|
|
mlir::MLIRContext context;
|
|
|
|
mlir::OwningModuleRef module;
|
2019-12-23 09:49:29 +08:00
|
|
|
if (inputIsONNX) {
|
|
|
|
ImportFrontendModelFile(inputFilename, context, module);
|
2019-11-16 02:10:41 +08:00
|
|
|
} else {
|
2019-12-23 09:49:29 +08:00
|
|
|
LoadMLIR(inputFilename, context, module);
|
2019-11-16 02:10:41 +08:00
|
|
|
}
|
2019-11-08 00:42:40 +08:00
|
|
|
|
|
|
|
mlir::PassManager pm(&context);
|
|
|
|
pm.addPass(mlir::createShapeInferencePass());
|
2019-11-13 02:37:46 +08:00
|
|
|
pm.addPass(mlir::createCanonicalizerPass());
|
2019-12-23 12:52:49 +08:00
|
|
|
|
|
|
|
if (emissionTarget >= EmitMLIR) {
|
|
|
|
pm.addPass(mlir::createLowerToKrnlPass());
|
|
|
|
pm.addPass(mlir::createLowerKrnlPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emissionTarget >= EmitLLVMIR) {
|
|
|
|
pm.addPass(mlir::createLowerAffinePass());
|
|
|
|
pm.addPass(mlir::createLowerToCFGPass());
|
|
|
|
pm.addPass(mlir::createKrnlLowerToLLVMPass());
|
|
|
|
pm.addPass(mlir::createCanonicalizerPass());
|
|
|
|
}
|
2019-10-09 07:25:59 +08:00
|
|
|
|
2019-12-23 09:49:29 +08:00
|
|
|
if (mlir::failed(pm.run(*module)))
|
|
|
|
return 4;
|
2019-11-28 11:56:34 +08:00
|
|
|
|
2019-12-23 12:52:49 +08:00
|
|
|
|
2020-01-21 01:30:08 +08:00
|
|
|
if (emissionTarget == EmitLLVMBC) {
|
|
|
|
// Write LLVM bitcode to disk.
|
|
|
|
EmitLLVMBitCode(module);
|
|
|
|
printf("LLVM bitcode written to ./model.bc");
|
|
|
|
} else
|
|
|
|
module->dump();
|
|
|
|
|
2019-12-20 03:24:37 +08:00
|
|
|
return 0;
|
|
|
|
}
|