[LoopPipelining] recursively fully unroll all inner loops until no failure are met

This commit is contained in:
Hanchen Ye 2021-01-18 17:27:24 -06:00
parent 47837eee6e
commit 4a594c9303
7 changed files with 25 additions and 13 deletions

View File

@ -40,7 +40,7 @@ $ # Loop and pragma-level optimizations, performance estimation, and C++ code ge
$ scalehls-opt samples/polybench/syrk.mlir \
-affine-loop-perfection -remove-variable-bound -affine-loop-normalize \
-partial-affine-loop-tile="tile-level=1 tile-size=4" \
-legalize-to-hlscpp="top-function=test_syrk" -loop-pipelining="pipeline-level=1" \
-legalize-to-hlscpp="top-func=test_syrk" -loop-pipelining="pipeline-level=1" \
-affine-store-forward -simplify-memref-access -array-partition -cse -canonicalize \
-qor-estimation="target-spec=config/target-spec.ini" \
| scalehls-translate -emit-hlscpp
@ -55,7 +55,7 @@ $ benchmark-gen -type "cnn" -config "config/cnn-config.ini" -number 1 \
| scalehls-opt -legalize-dataflow -split-function \
-hlskernel-bufferize -hlskernel-to-affine -func-bufferize \
-affine-loop-perfection -affine-loop-normalize \
-legalize-to-hlscpp="top-function=auto_gen_cnn" \
-legalize-to-hlscpp="top-func=auto_gen_cnn" \
-affine-store-forward -simplify-memref-access -cse -canonicalize \
-qor-estimation="target-spec=config/target-spec.ini" \
| scalehls-translate -emit-hlscpp
@ -85,7 +85,7 @@ $ # Legalize the output of ONNX-MLIR, optimize and emit C++ code.
$ scalehls-opt resnet18.mlir -legalize-onnx -affine-loop-normalize -canonicalize \
-legalize-dataflow="min-gran=2 insert-copy=false" -split-function \
-convert-linalg-to-affine-loops -affine-loop-fusion \
-legalize-to-hlscpp="top-function=main_graph" \
-legalize-to-hlscpp="top-func=main_graph" \
| scalehls-translate -emit-hlscpp
```

View File

@ -22,7 +22,7 @@ def LegalizeToHLSCpp : Pass<"legalize-to-hlscpp", "FuncOp"> {
let constructor = "mlir::scalehls::createLegalizeToHLSCppPass()";
let options = [
Option<"topFunction", "top-function", "std::string", /*default=*/"\"main\"",
Option<"topFunc", "top-func", "std::string", /*default=*/"\"main\"",
"The top function for HLS synthesis">,
];
}

View File

@ -66,7 +66,7 @@ def FuncPipelining : Pass<"func-pipelining", "FuncOp"> {
let constructor = "mlir::scalehls::createFuncPipeliningPass()";
let options = [
Option<"targetFunction", "target-function", "std::string",
Option<"targetFunc", "target-func", "std::string",
/*default=*/"\"main\"", "The target function to be pipelined">
];
}

View File

@ -29,7 +29,7 @@ void LegalizeToHLSCpp::runOnOperation() {
if (!func->getAttr("dataflow"))
func->setAttr("dataflow", builder.getBoolAttr(false));
if (func.getName() == topFunction)
if (func.getName() == topFunc)
func->setAttr("top_function", builder.getBoolAttr(true));
else
func->setAttr("top_function", builder.getBoolAttr(false));

View File

@ -18,7 +18,7 @@ struct FuncPipelining : public FuncPipeliningBase<FuncPipelining> {
auto func = getOperation();
auto builder = OpBuilder(func);
if (func.getName() == targetFunction) {
if (func.getName() == targetFunc) {
applyFuncPipelining(func, builder);
// Canonicalize the IR after function pipelining.
@ -35,7 +35,14 @@ struct FuncPipelining : public FuncPipeliningBase<FuncPipelining> {
/// Apply function pipelining to the input function, all contained loops are
/// automatically fully unrolled.
bool scalehls::applyFuncPipelining(FuncOp func, OpBuilder &builder) {
func.walk([&](AffineForOp loop) { loopUnrollFull(loop); });
bool hasFullyUnrolled = false;
while (hasFullyUnrolled == false) {
hasFullyUnrolled = true;
func.walk([&](AffineForOp loop) {
if (failed(loopUnrollFull(loop)))
hasFullyUnrolled = false;
});
}
func->setAttr("pipeline", builder.getBoolAttr(true));
func->setAttr("dataflow", builder.getBoolAttr(false));

View File

@ -63,10 +63,15 @@ bool scalehls::applyLoopPipelining(AffineForOp targetLoop, OpBuilder &builder) {
targetLoop->setAttr("pipeline", builder.getBoolAttr(true));
// All inner loops of the pipelined loop are automatically unrolled.
targetLoop.walk([&](AffineForOp loop) {
if (loop != targetLoop)
loopUnrollFull(loop);
});
bool hasFullyUnrolled = false;
while (hasFullyUnrolled == false) {
hasFullyUnrolled = true;
targetLoop.walk([&](AffineForOp loop) {
if (loop != targetLoop)
if (failed(loopUnrollFull(loop)))
hasFullyUnrolled = false;
});
}
// All outer loops that perfect nest the pipelined loop can be flattened.
SmallVector<AffineForOp, 4> flattenedLoops;

View File

@ -1,4 +1,4 @@
// RUN: scalehls-opt -legalize-to-hlscpp="top-function=test_assign" %s | FileCheck %s
// RUN: scalehls-opt -legalize-to-hlscpp="top-func=test_assign" %s | FileCheck %s
// CHECK-LABEL: func @test_assign(
// CHECK-SAME: %arg0: f32, %arg1: memref<16xf32, 1>) -> (f32, memref<16xf32, 1>, i32, memref<2x2xi32, 1>) attributes {dataflow = false, top_function = true} {