diff --git a/include/scalehls/Support/Utils.h b/include/scalehls/Support/Utils.h index 308027d..5418c05 100644 --- a/include/scalehls/Support/Utils.h +++ b/include/scalehls/Support/Utils.h @@ -4,8 +4,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SCALEHLS_ANALYSIS_UTILS_H -#define SCALEHLS_ANALYSIS_UTILS_H +#ifndef SCALEHLS_SUPPORT_UTILS_H +#define SCALEHLS_SUPPORT_UTILS_H #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/IR/AffineValueMap.h" @@ -157,4 +157,4 @@ template <> struct DenseMapInfo { } // namespace llvm -#endif // SCALEHLS_ANALYSIS_UTILS_H +#endif // SCALEHLS_SUPPORT_UTILS_H diff --git a/include/scalehls/Transforms/Passes.td b/include/scalehls/Transforms/Passes.td index facdf3e..0521755 100644 --- a/include/scalehls/Transforms/Passes.td +++ b/include/scalehls/Transforms/Passes.td @@ -106,17 +106,6 @@ def SplitFunction : Pass<"scalehls-split-function", "ModuleOp"> { let constructor = "mlir::scalehls::createSplitFunctionPass()"; } -def ConvertCopyToAffineLoops : - Pass<"scalehls-convert-copy-to-affine-loops", "FuncOp"> { - let summary = "Convert copy and assign to affine loops"; - let description = [{ - This convert-copy-to-affine-loops pass will first remove redundant copies - and lower assigns to copies, and then convert copies to affine loops. - }]; - - let constructor = "mlir::scalehls::createConvertCopyToAffineLoopsPass()"; -} - //===----------------------------------------------------------------------===// // Runtime-related Passes //===----------------------------------------------------------------------===// @@ -164,6 +153,17 @@ def LegalizeToHLSCpp : Pass<"scalehls-legalize-to-hlscpp", "FuncOp"> { // Loop Optimization Passes //===----------------------------------------------------------------------===// +def ConvertCopyToAffineLoops : + Pass<"scalehls-convert-copy-to-affine-loops", "FuncOp"> { + let summary = "Convert copy and assign to affine loops"; + let description = [{ + This convert-copy-to-affine-loops pass will first remove redundant copies + and lower assigns to copies, and then convert copies to affine loops. + }]; + + let constructor = "mlir::scalehls::createConvertCopyToAffineLoopsPass()"; +} + def MaterializeReduction : Pass<"scalehls-materialize-reduction", "FuncOp"> { let summary = "Materialize loop reductions"; let description = [{ @@ -213,23 +213,6 @@ def AffineLoopTile : Pass<"scalehls-affine-loop-tile", "FuncOp"> { ]; } -def CreateMemrefSubview : Pass<"scalehls-create-memref-subview", "FuncOp"> { - let summary = "Create subviews based on loop analysis"; - let description = [{ - Through loop analysis, this pass can identify the memory partition that each - sub-function is accessing. Then, by creating subview operations, the program - in each sub-function can access the memory subview rather than the original - memory. - }]; - let constructor = "mlir::scalehls::createCreateMemrefSubviewPass()"; -} - -def PromoteBuffer : Pass<"scalehls-promote-buffer", "FuncOp"> { - let summary = "Promote external buffer to on-chip buffer"; - - let constructor = "mlir::scalehls::createPromoteBufferPass()"; -} - def AffineLoopOrderOpt : Pass<"scalehls-affine-loop-order-opt", "FuncOp"> { let summary = "Optimize the order of affine loop nests"; let description = [{ @@ -261,6 +244,17 @@ def AffineLoopUnrollJam : Pass<"scalehls-affine-loop-unroll-jam", "FuncOp"> { ]; } +def SimplifyAffineIf : Pass<"scalehls-simplify-affine-if", "FuncOp"> { + let summary = "Simplify affine if operations"; + let description = [{ + This simplify-affine-if pass will eliminate all redundant affine if + operations which will always take then or else branch, and merge all affine + if operations that having the same statement. + }]; + + let constructor = "mlir::scalehls::createSimplifyAffineIfPass()"; +} + //===----------------------------------------------------------------------===// // Directive Optimization Passes //===----------------------------------------------------------------------===// @@ -321,18 +315,24 @@ def CreateHLSCppPrimitive : Pass<"scalehls-create-hlscpp-primitive", "FuncOp"> { } //===----------------------------------------------------------------------===// -// Simplification Passes +// Memory Optimization Passes //===----------------------------------------------------------------------===// -def SimplifyAffineIf : Pass<"scalehls-simplify-affine-if", "FuncOp"> { - let summary = "Simplify affine if operations"; +def CreateMemrefSubview : Pass<"scalehls-create-memref-subview", "FuncOp"> { + let summary = "Create subviews based on loop analysis"; let description = [{ - This simplify-affine-if pass will eliminate all redundant affine if - operations which will always take then or else branch, and merge all affine - if operations that having the same statement. + Through loop analysis, this pass can identify the memory partition that each + sub-function is accessing. Then, by creating subview operations, the program + in each sub-function can access the memory subview rather than the original + memory. }]; + let constructor = "mlir::scalehls::createCreateMemrefSubviewPass()"; +} - let constructor = "mlir::scalehls::createSimplifyAffineIfPass()"; +def PromoteBuffer : Pass<"scalehls-promote-buffer", "FuncOp"> { + let summary = "Promote external buffer to on-chip buffer"; + + let constructor = "mlir::scalehls::createPromoteBufferPass()"; } def AffineStoreForward : Pass<"scalehls-affine-store-forward", "FuncOp"> { diff --git a/include/scalehls/Transforms/QoREstimation.h b/include/scalehls/Transforms/QoREstimation.h index a09102a..5501b83 100644 --- a/include/scalehls/Transforms/QoREstimation.h +++ b/include/scalehls/Transforms/QoREstimation.h @@ -4,8 +4,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SCALEHLS_ANALYSIS_QORESTIMATION_H -#define SCALEHLS_ANALYSIS_QORESTIMATION_H +#ifndef SCALEHLS_TRANSFORMS_QORESTIMATION_H +#define SCALEHLS_TRANSFORMS_QORESTIMATION_H #include "mlir/Dialect/Affine/Analysis/AffineAnalysis.h" #include "mlir/IR/BuiltinOps.h" @@ -133,4 +133,4 @@ private: } // namespace scalehls } // namespace mlir -#endif // SCALEHLS_ANALYSIS_QORESTIMATION_H +#endif // SCALEHLS_TRANSFORMS_QORESTIMATION_H diff --git a/include/scalehls/Transforms/Utils.h b/include/scalehls/Transforms/Utils.h index 5090f74..73af74a 100644 --- a/include/scalehls/Transforms/Utils.h +++ b/include/scalehls/Transforms/Utils.h @@ -14,7 +14,7 @@ namespace mlir { namespace scalehls { //===----------------------------------------------------------------------===// -// HLSCpp transform utils +// HLSCpp attribute transform utils //===----------------------------------------------------------------------===// using namespace hlscpp; @@ -50,16 +50,6 @@ void setTopFuncAttr(FuncOp func); // Loop transform utils //===----------------------------------------------------------------------===// -using TileList = SmallVector; - -/// Legalize the dataflow of "block", whose parent operation must be a function -/// or affine loop. Return false if the legalization failed, for example, the -/// dataflow has cycles. -bool applyLegalizeDataflow(Block &block, int64_t minGran, bool insertCopy); - -/// Split each dataflow stage of "block" into a separate sub-function. -bool applySplitFunction(Block &block); - /// Apply loop perfection. Try to sink all operations between loop statements /// into the innermost loop of the input loop band. bool applyAffineLoopPerfection(AffineLoopBand &band); @@ -76,19 +66,15 @@ bool applyRemoveVariableBound(AffineLoopBand &band); /// Apply loop tiling to the input loop band and sink all intra-tile loops to /// the innermost loop with the original loop order. +using TileList = SmallVector; bool applyLoopTiling(AffineLoopBand &band, TileList tileList, bool annotatePointLoop = false); -bool applyLegalizeToHLSCpp(FuncOp func, bool topFunc, bool axiInterf = false); - /// Apply loop pipelining to the pipelineLoc of the input loop band, all inner /// loops are automatically fully unrolled. bool applyLoopPipelining(AffineLoopBand &band, unsigned pipelineLoc, unsigned targetII); -/// Apply simplification optimizations. -bool applySimplificationOpts(FuncOp func); - /// Fully unroll all loops insides of a loop block. bool applyFullyLoopUnrolling(Block &block, unsigned maxIterNum = 10); @@ -97,10 +83,27 @@ bool applyArrayPartition(Value array, ArrayRef factors, ArrayRef kinds, bool updateFuncSignature = true); +/// Apply simplification optimizations. +bool applySimplificationOpts(FuncOp func); + /// Find the suitable array partition factors and kinds for all arrays in the /// targeted function. bool applyAutoArrayPartition(FuncOp func); +bool applyLegalizeToHLSCpp(FuncOp func, bool topFunc, bool axiInterf = false); + +//===----------------------------------------------------------------------===// +// Graph transform utils +//===----------------------------------------------------------------------===// + +/// Legalize the dataflow of "block", whose parent operation must be a function +/// or affine loop. Return false if the legalization failed, for example, the +/// dataflow has cycles. +bool applyLegalizeDataflow(Block &block, int64_t minGran, bool insertCopy); + +/// Split each dataflow stage of "block" into a separate sub-function. +bool applySplitFunction(Block &block); + /// Apply optimization strategy to a loop band. The ancestor function is also /// passed in because the post-tiling optimizations have to take function as /// target, e.g. canonicalizer and array partition. diff --git a/lib/Transforms/CMakeLists.txt b/lib/Transforms/CMakeLists.txt index 8978bac..36ca884 100644 --- a/lib/Transforms/CMakeLists.txt +++ b/lib/Transforms/CMakeLists.txt @@ -3,7 +3,6 @@ add_mlir_library(MLIRScaleHLSTransforms Directive/CreateHLSCppPrimitive.cpp Directive/FuncPipelining.cpp Directive/LoopPipelining.cpp - Graph/ConvertCopyToAffineLoops.cpp Graph/FakeQuantize.cpp Graph/LegalizeDataflow.cpp Graph/SimplifyTosaGraph.cpp @@ -12,14 +11,15 @@ add_mlir_library(MLIRScaleHLSTransforms Loop/AffineLoopPerfection.cpp Loop/AffineLoopTile.cpp Loop/AffineLoopUnrollJam.cpp - Loop/CreateMemrefSubview.cpp + Loop/ConvertCopyToAffineLoops.cpp Loop/MaterializeReduction.cpp - Loop/PromoteBuffer.cpp Loop/RemoveVariableBound.cpp - Simplification/AffineStoreForward.cpp - Simplification/ReduceInitialInterval.cpp - Simplification/SimplifyAffineIf.cpp - Simplification/SimplifyMemrefAccess.cpp + Loop/SimplifyAffineIf.cpp + Memory/AffineStoreForward.cpp + Memory/CreateMemrefSubview.cpp + Memory/PromoteBuffer.cpp + Memory/ReduceInitialInterval.cpp + Memory/SimplifyMemrefAccess.cpp CreateRuntimeMain.cpp LegalizeToHLSCpp.cpp MultipleLevelDSE.cpp diff --git a/lib/Transforms/Loop/AffineLoopUnrollJam.cpp b/lib/Transforms/Loop/AffineLoopUnrollJam.cpp index 0d5621a..48c2ec6 100644 --- a/lib/Transforms/Loop/AffineLoopUnrollJam.cpp +++ b/lib/Transforms/Loop/AffineLoopUnrollJam.cpp @@ -13,6 +13,24 @@ using namespace mlir; using namespace scalehls; +/// Fully unroll all loops insides of a block. +bool scalehls::applyFullyLoopUnrolling(Block &block, unsigned maxIterNum) { + for (unsigned i = 0; i < maxIterNum; ++i) { + bool hasFullyUnrolled = true; + block.walk([&](AffineForOp loop) { + if (failed(loopUnrollFull(loop))) + hasFullyUnrolled = false; + }); + + if (hasFullyUnrolled) + break; + + if (i == 7) + return false; + } + return true; +} + namespace { struct AffineLoopUnrollJam : public AffineLoopUnrollJamBase { diff --git a/lib/Transforms/Graph/ConvertCopyToAffineLoops.cpp b/lib/Transforms/Loop/ConvertCopyToAffineLoops.cpp similarity index 100% rename from lib/Transforms/Graph/ConvertCopyToAffineLoops.cpp rename to lib/Transforms/Loop/ConvertCopyToAffineLoops.cpp diff --git a/lib/Transforms/Simplification/SimplifyAffineIf.cpp b/lib/Transforms/Loop/SimplifyAffineIf.cpp similarity index 100% rename from lib/Transforms/Simplification/SimplifyAffineIf.cpp rename to lib/Transforms/Loop/SimplifyAffineIf.cpp diff --git a/lib/Transforms/Simplification/AffineStoreForward.cpp b/lib/Transforms/Memory/AffineStoreForward.cpp similarity index 100% rename from lib/Transforms/Simplification/AffineStoreForward.cpp rename to lib/Transforms/Memory/AffineStoreForward.cpp diff --git a/lib/Transforms/Loop/CreateMemrefSubview.cpp b/lib/Transforms/Memory/CreateMemrefSubview.cpp similarity index 100% rename from lib/Transforms/Loop/CreateMemrefSubview.cpp rename to lib/Transforms/Memory/CreateMemrefSubview.cpp diff --git a/lib/Transforms/Loop/PromoteBuffer.cpp b/lib/Transforms/Memory/PromoteBuffer.cpp similarity index 100% rename from lib/Transforms/Loop/PromoteBuffer.cpp rename to lib/Transforms/Memory/PromoteBuffer.cpp diff --git a/lib/Transforms/Simplification/ReduceInitialInterval.cpp b/lib/Transforms/Memory/ReduceInitialInterval.cpp similarity index 100% rename from lib/Transforms/Simplification/ReduceInitialInterval.cpp rename to lib/Transforms/Memory/ReduceInitialInterval.cpp diff --git a/lib/Transforms/Simplification/SimplifyMemrefAccess.cpp b/lib/Transforms/Memory/SimplifyMemrefAccess.cpp similarity index 100% rename from lib/Transforms/Simplification/SimplifyMemrefAccess.cpp rename to lib/Transforms/Memory/SimplifyMemrefAccess.cpp diff --git a/lib/Transforms/Utils.cpp b/lib/Transforms/Utils.cpp index 9368afa..5dbbac7 100644 --- a/lib/Transforms/Utils.cpp +++ b/lib/Transforms/Utils.cpp @@ -123,24 +123,6 @@ bool scalehls::applySimplificationOpts(FuncOp func) { return true; } -/// Fully unroll all loops insides of a block. -bool scalehls::applyFullyLoopUnrolling(Block &block, unsigned maxIterNum) { - for (unsigned i = 0; i < maxIterNum; ++i) { - bool hasFullyUnrolled = true; - block.walk([&](AffineForOp loop) { - if (failed(loopUnrollFull(loop))) - hasFullyUnrolled = false; - }); - - if (hasFullyUnrolled) - break; - - if (i == 7) - return false; - } - return true; -} - /// Apply optimization strategy to a loop band. The ancestor function is also /// passed in because the post-tiling optimizations have to take function as /// target, e.g. canonicalizer and array partition.