diff --git a/include/Transforms/Passes.h b/include/Transforms/Passes.h index c606a20..51d1e0c 100644 --- a/include/Transforms/Passes.h +++ b/include/Transforms/Passes.h @@ -19,6 +19,7 @@ std::unique_ptr createPragmaDSEPass(); std::unique_ptr createAffineLoopPerfectionPass(); std::unique_ptr createPartialAffineLoopTilePass(); std::unique_ptr createRemoveVarLoopBoundPass(); +std::unique_ptr createInsertPipelinePragmaPass(); void registerTransformsPasses(); diff --git a/include/Transforms/Passes.td b/include/Transforms/Passes.td index f60d13a..622a0d8 100644 --- a/include/Transforms/Passes.td +++ b/include/Transforms/Passes.td @@ -20,6 +20,21 @@ def PragmaDSE : Pass<"pragma-dse", "ModuleOp"> { let constructor = "mlir::scalehls::createPragmaDSEPass()"; } +def InsertPipelinePragma : Pass<"insert-pipeline-pragma", "ModuleOp"> { + let summary = "Insert pipeline pragma"; + let description = [{ + This insert-pipeline-pragma pass will insert pipeline pragma to the + innermost loop level. + }]; + + let constructor = "mlir::scalehls::createInsertPipelinePragmaPass()"; + + let options = [ + Option<"insertLevel", "insert-level", "unsigned", /*default=*/"1", + "Positive number: loop level to be pipelined (from innermost)"> + ]; +} + def AffineLoopPerfection : Pass<"affine-loop-perfection", "ModuleOp"> { let summary = "Try to perfect a nested loop"; let description = [{ @@ -43,7 +58,7 @@ def PartialAffineLoopTile : Pass<"partial-affine-loop-tile", "ModuleOp"> { let constructor = "mlir::scalehls::createPartialAffineLoopTilePass()"; - let options = [ + let options = [ Option<"tileLevel", "tile-level", "unsigned", /*default=*/"1", "Positive number: the level of loops to be tiles">, Option<"tileSize", "tile-size", "unsigned", /*default=*/"2", diff --git a/lib/Transforms/InsertPipelinePragma.cpp b/lib/Transforms/InsertPipelinePragma.cpp new file mode 100644 index 0000000..499a827 --- /dev/null +++ b/lib/Transforms/InsertPipelinePragma.cpp @@ -0,0 +1,43 @@ +//===------------------------------------------------------------*- C++ -*-===// +// +//===----------------------------------------------------------------------===// + +#include "Transforms/Passes.h" +#include "mlir/Dialect/Affine/IR/AffineOps.h" +#include "mlir/Dialect/Affine/Passes.h" +#include "mlir/IR/Builders.h" +#include "mlir/Transforms/LoopUtils.h" + +using namespace std; +using namespace mlir; +using namespace scalehls; + +namespace { +struct InsertPipelinePragma + : public InsertPipelinePragmaBase { + void runOnOperation() override; +}; +} // namespace + +void InsertPipelinePragma::runOnOperation() { + auto module = getOperation(); + auto builder = OpBuilder(module); + + // Walk through all functions and loops. + for (auto func : module.getOps()) { + for (auto forOp : func.getOps()) { + SmallVector nestedLoops; + getPerfectlyNestedLoops(nestedLoops, forOp); + + auto targetLoop = nestedLoops.front(); + if (nestedLoops.size() > insertLevel) + targetLoop = *std::prev(nestedLoops.end(), insertLevel); + + targetLoop.setAttr("pipeline", builder.getBoolAttr(true)); + } + } +} + +std::unique_ptr scalehls::createInsertPipelinePragmaPass() { + return std::make_unique(); +} diff --git a/test/Transforms/test_insert_pipeline_pragma.mlir b/test/Transforms/test_insert_pipeline_pragma.mlir new file mode 100644 index 0000000..007a77c --- /dev/null +++ b/test/Transforms/test_insert_pipeline_pragma.mlir @@ -0,0 +1,6 @@ +// RUN: scalehls-opt -insert-pipeline-pragma %s | FileCheck %s + +// CHECK-LABEL: func @test_for +func @test_for() { + return +}