Refactor the passes name for slir lowering
This commit is contained in:
parent
2634fdb5f4
commit
10015683f5
|
@ -77,7 +77,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
|||
-Werror
|
||||
-fno-rtti
|
||||
-fno-builtin-strlen
|
||||
-flto=thin
|
||||
|
||||
# Dedicate a section to each function, so the linker
|
||||
# can do a better job on dead code elimination
|
||||
-ffunction-sections
|
||||
|
@ -92,15 +92,21 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
|||
|
||||
$<$<CONFIG:DEBUG>:-fno-omit-frame-pointer>
|
||||
$<$<CONFIG:RELEASE>:-fomit-frame-pointer>
|
||||
$<$<CONFIG:DEBUG>:-fsanitize=address>
|
||||
|
||||
$<$<CONFIG:RELEASE>:-O3>
|
||||
$<$<CONFIG:RELEASE>:-fmerge-all-constants>
|
||||
$<$<CONFIG:RELEASE>:-flto=thin>
|
||||
|
||||
)
|
||||
|
||||
add_link_options(
|
||||
# We enforce the lld linker
|
||||
-fuse-ld=lld
|
||||
$<$<CONFIG:RELEASE>:-fsanitize-address-globals-dead-stripping>
|
||||
$<$<CONFIG:DEBUG>:-fsanitize=address>
|
||||
|
||||
$<$<CONFIG:RELEASE>:-flto=thin>
|
||||
$<$<CONFIG:RELEASE>:-s>
|
||||
# Do not link against shared libraries
|
||||
#--static
|
||||
)
|
||||
|
|
2
builder
2
builder
|
@ -80,7 +80,7 @@ function clean() {
|
|||
|
||||
function run() {
|
||||
pushed_build
|
||||
"$BUILD_DIR"/bin/serenec "$@"
|
||||
"$BUILD_DIR"/src/serenec/serenec "$@"
|
||||
popd_build
|
||||
}
|
||||
|
||||
|
|
5
dev.org
5
dev.org
|
@ -108,8 +108,11 @@ on ADF
|
|||
|
||||
* TODOs
|
||||
** Bootstrap*
|
||||
*** TODO Create different pass pipeline for different compilation phases
|
||||
So we can use them directly via command line, like -O1 for example
|
||||
|
||||
*** TODO Investigate the huge size of serenec
|
||||
- Checkout -ffunction-sections -fdata-sections flags of lld
|
||||
So far it seems that the static linking and the lack of tree shaking is the issue
|
||||
*** DONE Add the support for =ns-paths= :serenecli:context:
|
||||
CLOSED: [2021-09-25 Sat 19:22]
|
||||
:LOGBOOK:
|
||||
|
|
|
@ -377,7 +377,8 @@ define i64 @main1(i64 %0, i64 %1, i64 %2) !dbg !9 {
|
|||
- https://mlir.llvm.org/docs/LangRef
|
||||
- https://en.wikipedia.org/wiki/Basic_block
|
||||
|
||||
* Episode 9 - IR (SLIR) generation
|
||||
* DONE Episode 9 - IR (SLIR) generation
|
||||
CLOSED: [2021-10-01 Fri 18:56]
|
||||
** Updates:
|
||||
- Source manager
|
||||
- Diagnostic Engine
|
||||
|
@ -402,3 +403,99 @@ There will be an episode dedicated to eache of these
|
|||
- [X] Setup the tablegen
|
||||
- [X] Define the operations
|
||||
- [X] Walk the AST and generate the operations
|
||||
|
||||
* Episode 10 - Pass Infrastructure
|
||||
** The next Step
|
||||
** Updates:
|
||||
*** CMake changes
|
||||
** What is a Pass
|
||||
*** Passes are the unit of abstraction for optimization and transformation in LLVM/MLIR
|
||||
*** Compilation is all about transforming the input data and produce an output
|
||||
|
||||
Source code -> IR X -> IR Y -> IR Z -> ... -> Target Code
|
||||
|
||||
*** Almost like a function composition
|
||||
*** The big picture
|
||||
*** Pass Managers (Pipelines) are made out of a collection of passes and can be nested
|
||||
*** The most of the interesting parts of the compiler reside in Passes.
|
||||
*** We will probably spend most of our time working with passes
|
||||
|
||||
** Pass Infrastructure
|
||||
*** ODS or C++
|
||||
*** Operation is the main abstract unit of transformation
|
||||
*** OperationPass is the base class for all the passes.
|
||||
*** We need to override =runOnOperation=
|
||||
*** There's some rules you need to follow when defining your Pass
|
||||
**** Must not maintain any global mutable state
|
||||
**** Must not modify the state of another operation not nested within the current operation being operated on
|
||||
**** ...
|
||||
|
||||
*** Passes are either OpSpecific or OpAgnostic
|
||||
**** OpSpecific
|
||||
#+BEGIN_SRC C++
|
||||
struct MyFunctionPass : public PassWrapper<MyFunctionPass,
|
||||
OperationPass<FuncOp>> {
|
||||
void runOnOperation() override {
|
||||
// Get the current FuncOp operation being operated on.
|
||||
FuncOp f = getOperation();
|
||||
|
||||
// Walk the operations within the function.
|
||||
f.walk([](Operation *inst) {
|
||||
// ....
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/// Register this pass so that it can be built via from a textual pass pipeline.
|
||||
/// (Pass registration is discussed more below)
|
||||
void registerMyPass() {
|
||||
PassRegistration<MyFunctionPass>();
|
||||
}
|
||||
#+END_SRC
|
||||
**** OpAgnostic
|
||||
#+BEGIN_SRC C++
|
||||
struct MyOperationPass : public PassWrapper<MyOperationPass, OperationPass<>> {
|
||||
void runOnOperation() override {
|
||||
// Get the current operation being operated on.
|
||||
Operation *op = getOperation();
|
||||
// ...
|
||||
}
|
||||
};
|
||||
#+END_SRC
|
||||
*** How transformation works?
|
||||
*** Analyses and Passes
|
||||
*** Pass management and nested pass managers
|
||||
#+BEGIN_SRC C++
|
||||
// Create a top-level `PassManager` class. If an operation type is not
|
||||
// explicitly specific, the default is the builtin `module` operation.
|
||||
PassManager pm(ctx);
|
||||
|
||||
// Note: We could also create the above `PassManager` this way.
|
||||
PassManager pm(ctx, /*operationName=*/"builtin.module");
|
||||
|
||||
// Add a pass on the top-level module operation.
|
||||
pm.addPass(std::make_unique<MyModulePass>());
|
||||
|
||||
// Nest a pass manager that operates on `spirv.module` operations nested
|
||||
// directly under the top-level module.
|
||||
OpPassManager &nestedModulePM = pm.nest<spirv::ModuleOp>();
|
||||
nestedModulePM.addPass(std::make_unique<MySPIRVModulePass>());
|
||||
|
||||
// Nest a pass manager that operates on functions within the nested SPIRV
|
||||
// module.
|
||||
OpPassManager &nestedFunctionPM = nestedModulePM.nest<FuncOp>();
|
||||
nestedFunctionPM.addPass(std::make_unique<MyFunctionPass>());
|
||||
|
||||
// Run the pass manager on the top-level module.
|
||||
ModuleOp m = ...;
|
||||
if (failed(pm.run(m))) {
|
||||
// Handle the failure
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
* Episode 11 - Lowering SLIR
|
||||
** Dialect lowering
|
||||
*** Why?
|
||||
*** Transforming a dialect to another dialect or LLVM IR
|
||||
*** The goal is to lower SLIR to LLVM IR directly or indirectly.
|
||||
** Dealing with Pass failures
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
|
||||
namespace serene::passes {
|
||||
|
||||
std::unique_ptr<mlir::Pass> createSLIRLowerToAffinePass();
|
||||
/// Return a pass to convert SLIR dialect to built-in dialects
|
||||
/// of MLIR.
|
||||
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass();
|
||||
|
||||
/// Return a pass to convert different dialects of MLIR to LLVM dialect.
|
||||
std::unique_ptr<mlir::Pass> createSLIRLowerToLLVMDialectPass();
|
||||
|
||||
} // namespace serene::passes
|
||||
|
|
|
@ -71,7 +71,7 @@ void SereneContext::setOperationPhase(CompilationPhase phase) {
|
|||
}
|
||||
|
||||
if (phase >= CompilationPhase::MLIR) {
|
||||
pm.addPass(serene::passes::createSLIRLowerToAffinePass());
|
||||
pm.addPass(serene::passes::createSLIRLowerToMLIRPass());
|
||||
}
|
||||
|
||||
if (phase >= CompilationPhase::LIR) {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "serene/slir/dialect.h"
|
||||
|
||||
#include <llvm/Support/Casting.h>
|
||||
#include <mlir/Dialect/Affine/IR/AffineOps.h>
|
||||
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
|
||||
#include <mlir/Dialect/MemRef/IR/MemRef.h>
|
||||
#include <mlir/Dialect/StandardOps/IR/Ops.h>
|
||||
|
@ -102,7 +101,7 @@ FnOpLowering::matchAndRewrite(serene::slir::FnOp op,
|
|||
auto attr = std::get<1>(arg).dyn_cast<mlir::TypeAttr>();
|
||||
|
||||
if (!attr) {
|
||||
llvm::outs() << "It's not a type attr\n";
|
||||
op.emitError("It's not a type attr");
|
||||
return mlir::failure();
|
||||
}
|
||||
arg_types.push_back(attr.getValue());
|
||||
|
@ -110,13 +109,15 @@ FnOpLowering::matchAndRewrite(serene::slir::FnOp op,
|
|||
|
||||
auto func_type = rewriter.getFunctionType(arg_types, rewriter.getI64Type());
|
||||
auto fn = rewriter.create<mlir::FuncOp>(loc, name, func_type);
|
||||
|
||||
if (!fn) {
|
||||
llvm::outs() << "Value Rewrite fn is null\n";
|
||||
op.emitError("Value Rewrite fn is null");
|
||||
return mlir::failure();
|
||||
}
|
||||
|
||||
auto &entryBlock = *fn.addEntryBlock();
|
||||
rewriter.setInsertionPointToStart(&entryBlock);
|
||||
auto *entryBlock = fn.addEntryBlock();
|
||||
|
||||
rewriter.setInsertionPointToStart(entryBlock);
|
||||
auto retVal =
|
||||
rewriter
|
||||
.create<mlir::ConstantIntOp>(loc, (int64_t)3, rewriter.getI64Type())
|
||||
|
@ -125,7 +126,8 @@ FnOpLowering::matchAndRewrite(serene::slir::FnOp op,
|
|||
mlir::ReturnOp returnOp = rewriter.create<mlir::ReturnOp>(loc, retVal);
|
||||
|
||||
if (!returnOp) {
|
||||
llvm::outs() << "Value Rewrite returnOp is null\n";
|
||||
op.emitError("Value Rewrite returnOp is null");
|
||||
rewriter.eraseOp(fn);
|
||||
return mlir::failure();
|
||||
}
|
||||
|
||||
|
@ -138,8 +140,8 @@ FnOpLowering::matchAndRewrite(serene::slir::FnOp op,
|
|||
}
|
||||
|
||||
// SLIR lowering pass
|
||||
struct SLIRToAffinePass
|
||||
: public mlir::PassWrapper<SLIRToAffinePass,
|
||||
struct SLIRToMLIRPass
|
||||
: public mlir::PassWrapper<SLIRToMLIRPass,
|
||||
mlir::OperationPass<mlir::ModuleOp>> {
|
||||
void getDependentDialects(mlir::DialectRegistry ®istry) const override;
|
||||
void runOnOperation() final;
|
||||
|
@ -147,17 +149,17 @@ struct SLIRToAffinePass
|
|||
mlir::ModuleOp getModule();
|
||||
};
|
||||
|
||||
void SLIRToAffinePass::getDependentDialects(
|
||||
void SLIRToMLIRPass::getDependentDialects(
|
||||
mlir::DialectRegistry ®istry) const {
|
||||
registry.insert<mlir::StandardOpsDialect>();
|
||||
};
|
||||
|
||||
/// Return the current function being transformed.
|
||||
mlir::ModuleOp SLIRToAffinePass::getModule() { return this->getOperation(); }
|
||||
mlir::ModuleOp SLIRToMLIRPass::getModule() { return this->getOperation(); }
|
||||
|
||||
void SLIRToAffinePass::runOnOperation() { runOnModule(); }
|
||||
void SLIRToMLIRPass::runOnOperation() { runOnModule(); }
|
||||
|
||||
void SLIRToAffinePass::runOnModule() {
|
||||
void SLIRToMLIRPass::runOnModule() {
|
||||
|
||||
auto module = getModule();
|
||||
|
||||
|
@ -190,7 +192,7 @@ void SLIRToAffinePass::runOnModule() {
|
|||
signalPassFailure();
|
||||
};
|
||||
|
||||
std::unique_ptr<mlir::Pass> createSLIRLowerToAffinePass() {
|
||||
return std::make_unique<SLIRToAffinePass>();
|
||||
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass() {
|
||||
return std::make_unique<SLIRToMLIRPass>();
|
||||
};
|
||||
} // namespace serene::passes
|
||||
|
|
Loading…
Reference in New Issue