diff options
| author | Uday Bondhugula <bondhugula@google.com> | 2018-09-28 12:17:26 -0700 |
|---|---|---|
| committer | jpienaar <jpienaar@google.com> | 2019-03-29 13:21:26 -0700 |
| commit | 041817a45e49a914f807b220e1a3b88e3fb45072 (patch) | |
| tree | d643315c0ff7478a1eeb40757f9aa8541c898048 /mlir/tools/mlir-opt/mlir-opt.cpp | |
| parent | ec35e51f6dda0227c829cc40d7c0a24c3e0295cf (diff) | |
| download | bcm5719-llvm-041817a45e49a914f807b220e1a3b88e3fb45072.tar.gz bcm5719-llvm-041817a45e49a914f807b220e1a3b88e3fb45072.zip | |
Introduce loop body skewing / loop pipelining / loop shifting utility.
- loopBodySkew shifts statements of a loop body by stmt-wise delays, and is
typically meant to be used to:
- allow overlap of non-blocking start/wait until completion operations with
other computation
- allow shifting of statements (for better register
reuse/locality/parallelism)
- software pipelining (when applied to the innermost loop)
- an additional argument specifies whether to unroll the prologue and epilogue.
- add method to check SSA dominance preservation.
- add a fake loop pipeline pass to test this utility.
Sample input/output are below. While on this, fix/add following:
- fix minor bug in getAddMulPureAffineExpr
- add additional builder methods for common affine map cases
- fix const_operand_iterator's for ForStmt, etc. When there is no such thing
as 'const MLValue', the iterator shouldn't be returning const MLValue's.
Returning MLValue is const correct.
Sample input/output examples:
1) Simplest case: shift second statement by one.
Input:
for %i = 0 to 7 {
%y = "foo"(%i) : (affineint) -> affineint
%x = "bar"(%i) : (affineint) -> affineint
}
Output:
#map0 = (d0) -> (d0 - 1)
mlfunc @loop_nest_simple1() {
%c8 = constant 8 : affineint
%c0 = constant 0 : affineint
%0 = "foo"(%c0) : (affineint) -> affineint
for %i0 = 1 to 7 {
%1 = "foo"(%i0) : (affineint) -> affineint
%2 = affine_apply #map0(%i0)
%3 = "bar"(%2) : (affineint) -> affineint
}
%4 = affine_apply #map0(%c8)
%5 = "bar"(%4) : (affineint) -> affineint
return
}
2) DMA overlap: shift dma.wait and compute by one.
Input
for %i = 0 to 7 {
%pingpong = affine_apply (d0) -> (d0 mod 2) (%i)
"dma.enqueue"(%pingpong) : (affineint) -> affineint
%pongping = affine_apply (d0) -> (d0 mod 2) (%i)
"dma.wait"(%pongping) : (affineint) -> affineint
"compute1"(%pongping) : (affineint) -> affineint
}
Output
#map0 = (d0) -> (d0 mod 2)
#map1 = (d0) -> (d0 - 1)
#map2 = ()[s0] -> (s0 + 7)
mlfunc @loop_nest_dma() {
%c8 = constant 8 : affineint
%c0 = constant 0 : affineint
%0 = affine_apply #map0(%c0)
%1 = "dma.enqueue"(%0) : (affineint) -> affineint
for %i0 = 1 to 7 {
%2 = affine_apply #map0(%i0)
%3 = "dma.enqueue"(%2) : (affineint) -> affineint
%4 = affine_apply #map1(%i0)
%5 = affine_apply #map0(%4)
%6 = "dma.wait"(%5) : (affineint) -> affineint
%7 = "compute1"(%5) : (affineint) -> affineint
}
%8 = affine_apply #map1(%c8)
%9 = affine_apply #map0(%8)
%10 = "dma.wait"(%9) : (affineint) -> affineint
%11 = "compute1"(%9) : (affineint) -> affineint
return
}
3) With arbitrary affine bound maps:
Shift last two statements by two.
Input:
for %i = %N to ()[s0] -> (s0 + 7)()[%N] {
%y = "foo"(%i) : (affineint) -> affineint
%x = "bar"(%i) : (affineint) -> affineint
%z = "foo_bar"(%i) : (affineint) -> (affineint)
"bar_foo"(%i) : (affineint) -> (affineint)
}
Output
#map0 = ()[s0] -> (s0 + 1)
#map1 = ()[s0] -> (s0 + 2)
#map2 = ()[s0] -> (s0 + 7)
#map3 = (d0) -> (d0 - 2)
#map4 = ()[s0] -> (s0 + 8)
#map5 = ()[s0] -> (s0 + 9)
for %i0 = %arg0 to #map0()[%arg0] {
%0 = "foo"(%i0) : (affineint) -> affineint
%1 = "bar"(%i0) : (affineint) -> affineint
}
for %i1 = #map1()[%arg0] to #map2()[%arg0] {
%2 = "foo"(%i1) : (affineint) -> affineint
%3 = "bar"(%i1) : (affineint) -> affineint
%4 = affine_apply #map3(%i1)
%5 = "foo_bar"(%4) : (affineint) -> affineint
%6 = "bar_foo"(%4) : (affineint) -> affineint
}
for %i2 = #map4()[%arg0] to #map5()[%arg0] {
%7 = affine_apply #map3(%i2)
%8 = "foo_bar"(%7) : (affineint) -> affineint
%9 = "bar_foo"(%7) : (affineint) -> affineint
}
4) Shift one by zero, second by one, third by two
for %i = 0 to 7 {
%y = "foo"(%i) : (affineint) -> affineint
%x = "bar"(%i) : (affineint) -> affineint
%z = "foobar"(%i) : (affineint) -> affineint
}
#map0 = (d0) -> (d0 - 1)
#map1 = (d0) -> (d0 - 2)
#map2 = ()[s0] -> (s0 + 7)
%c9 = constant 9 : affineint
%c8 = constant 8 : affineint
%c1 = constant 1 : affineint
%c0 = constant 0 : affineint
%0 = "foo"(%c0) : (affineint) -> affineint
%1 = "foo"(%c1) : (affineint) -> affineint
%2 = affine_apply #map0(%c1)
%3 = "bar"(%2) : (affineint) -> affineint
for %i0 = 2 to 7 {
%4 = "foo"(%i0) : (affineint) -> affineint
%5 = affine_apply #map0(%i0)
%6 = "bar"(%5) : (affineint) -> affineint
%7 = affine_apply #map1(%i0)
%8 = "foobar"(%7) : (affineint) -> affineint
}
%9 = affine_apply #map0(%c8)
%10 = "bar"(%9) : (affineint) -> affineint
%11 = affine_apply #map1(%c8)
%12 = "foobar"(%11) : (affineint) -> affineint
%13 = affine_apply #map1(%c9)
%14 = "foobar"(%13) : (affineint) -> affineint
5) SSA dominance violated; no shifting if a shift is specified for the second
statement.
for %i = 0 to 7 {
%x = "foo"(%i) : (affineint) -> affineint
"bar"(%x) : (affineint) -> affineint
}
PiperOrigin-RevId: 214975731
Diffstat (limited to 'mlir/tools/mlir-opt/mlir-opt.cpp')
| -rw-r--r-- | mlir/tools/mlir-opt/mlir-opt.cpp | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp index bd2136c2926..965d889c521 100644 --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -70,6 +70,7 @@ enum Passes { ConvertToCFG, LoopUnroll, LoopUnrollAndJam, + PipelineDataTransfer, PrintCFGGraph, SimplifyAffineExpr, TFRaiseControlFlow, @@ -85,6 +86,9 @@ static cl::list<Passes> passList( clEnumValN(LoopUnroll, "loop-unroll", "Unroll loops"), clEnumValN(LoopUnrollAndJam, "loop-unroll-jam", "Unroll and jam loops"), + clEnumValN(PipelineDataTransfer, "pipeline-data-transfer", + "Pipeline non-blocking data transfers between" + "explicitly managed levels of the memory hierarchy"), clEnumValN(PrintCFGGraph, "print-cfg-graph", "Print CFG graph per function"), clEnumValN(SimplifyAffineExpr, "simplify-affine-expr", @@ -179,6 +183,9 @@ static OptResult performActions(SourceMgr &sourceMgr, MLIRContext *context) { case LoopUnrollAndJam: pass = createLoopUnrollAndJamPass(); break; + case PipelineDataTransfer: + pass = createPipelineDataTransferPass(); + break; case PrintCFGGraph: pass = createPrintCFGGraphPass(); break; |

