Mercurial > hg > CbC > CbC_llvm
comparison mlir/docs/EDSC.md @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | 1d019706d866 |
children |
comparison
equal
deleted
inserted
replaced
172:9fbae9c8bf63 | 173:0572611fdcc8 |
---|---|
1 # Background: declarative builders API | 1 # Background: declarative builders API |
2 | 2 |
3 The main purpose of the declarative builders API is to provide an intuitive way | 3 The main purpose of the declarative builders API is to provide an intuitive way |
4 of constructing MLIR programmatically. In the majority of cases, the IR we wish | 4 of constructing MLIR programmatically. In the majority of cases, the IR we wish |
5 to construct exhibits structured control-flow. Declarative builders provide an | 5 to construct exhibits structured control-flow. The Declarative builders in the |
6 API to make MLIR construction and manipulation very idiomatic, for the | 6 `EDSC` library (Embedded Domain Specific Constructs) provide an API to make MLIR |
7 structured control-flow case, in C++. | 7 construction and manipulation very idiomatic, for the structured control-flow |
8 case, in C++. | |
8 | 9 |
9 ## ScopedContext | 10 ## ScopedContext |
10 | 11 |
11 `mlir::edsc::ScopedContext` provides an implicit thread-local context, | 12 `mlir::edsc::ScopedContext` provides an implicit thread-local context, |
12 supporting a simple declarative API with globally accessible builders. These | 13 supporting a simple declarative API with globally accessible builders. These |
13 declarative builders are available within the lifetime of a `ScopedContext`. | 14 declarative builders are available within the lifetime of a `ScopedContext`. |
14 | 15 |
15 ## ValueHandle and IndexHandle | |
16 | |
17 `mlir::edsc::ValueHandle` and `mlir::edsc::IndexHandle` provide typed | |
18 abstractions around an `mlir::Value`. These abstractions are "delayed", in the | |
19 sense that they allow separating declaration from definition. They may capture | |
20 IR snippets, as they are built, for programmatic manipulation. Intuitive | |
21 operators are provided to allow concise and idiomatic expressions. | |
22 | |
23 ```c++ | |
24 ValueHandle zero = std_constant_index(0); | |
25 IndexHandle i, j, k; | |
26 ``` | |
27 | |
28 ## Intrinsics | 16 ## Intrinsics |
29 | 17 |
30 `mlir::edsc::ValueBuilder` is a generic wrapper for the `mlir::Builder::create` | 18 `mlir::ValueBuilder` is a generic wrapper for the `mlir::OpBuilder::create` |
31 method that operates on `ValueHandle` objects and return a single ValueHandle. | 19 method that operates on `Value` objects and return a single Value. For |
32 For instructions that return no values or that return multiple values, the | 20 instructions that return no values or that return multiple values, the |
33 `mlir::edsc::InstructionBuilder` can be used. Named intrinsics are provided as | 21 `mlir::edsc::OperationBuilder` can be used. Named intrinsics are provided as |
34 syntactic sugar to further reduce boilerplate. | 22 syntactic sugar to further reduce boilerplate. |
35 | 23 |
36 ```c++ | 24 ```c++ |
37 using load = ValueBuilder<LoadOp>; | 25 using load = ValueBuilder<LoadOp>; |
38 using store = InstructionBuilder<StoreOp>; | 26 using store = OperationBuilder<StoreOp>; |
39 ``` | 27 ``` |
40 | 28 |
41 ## LoopBuilder and AffineLoopNestBuilder | 29 ## LoopBuilder and AffineLoopNestBuilder |
42 | 30 |
43 `mlir::edsc::AffineLoopNestBuilder` provides an interface to allow writing | 31 `mlir::edsc::AffineLoopNestBuilder` provides an interface to allow writing |
44 concise and structured loop nests. | 32 concise and structured loop nests. |
45 | 33 |
46 ```c++ | 34 ```c++ |
47 ScopedContext scope(f.get()); | 35 ScopedContext scope(f.get()); |
48 ValueHandle i(indexType), | 36 Value i, j, lb(f->getArgument(0)), ub(f->getArgument(1)); |
49 j(indexType), | 37 Value f7(std_constant_float(llvm::APFloat(7.0f), f32Type)), |
50 lb(f->getArgument(0)), | 38 f13(std_constant_float(llvm::APFloat(13.0f), f32Type)), |
51 ub(f->getArgument(1)); | 39 i7(constant_int(7, 32)), |
52 ValueHandle f7(std_constant_float(llvm::APFloat(7.0f), f32Type)), | 40 i13(constant_int(13, 32)); |
53 f13(std_constant_float(llvm::APFloat(13.0f), f32Type)), | |
54 i7(constant_int(7, 32)), | |
55 i13(constant_int(13, 32)); | |
56 AffineLoopNestBuilder(&i, lb, ub, 3)([&]{ | 41 AffineLoopNestBuilder(&i, lb, ub, 3)([&]{ |
57 lb * index_type(3) + ub; | 42 lb * index_type(3) + ub; |
58 lb + index_type(3); | 43 lb + index_type(3); |
59 AffineLoopNestBuilder(&j, lb, ub, 2)([&]{ | 44 AffineLoopNestBuilder(&j, lb, ub, 2)([&]{ |
60 ceilDiv(index_type(31) * floorDiv(i + j * index_type(3), index_type(32)), | 45 ceilDiv(index_type(31) * floorDiv(i + j * index_type(3), index_type(32)), |
81 ```c++ | 66 ```c++ |
82 def AddOp : Op<"x.add">, | 67 def AddOp : Op<"x.add">, |
83 Arguments<(ins Tensor:$A, Tensor:$B)>, | 68 Arguments<(ins Tensor:$A, Tensor:$B)>, |
84 Results<(outs Tensor: $C)> { | 69 Results<(outs Tensor: $C)> { |
85 code referenceImplementation = [{ | 70 code referenceImplementation = [{ |
86 auto ivs = makeIndexHandles(view_A.rank()); | 71 SmallVector<Value, 4> ivs(view_A.rank()); |
87 auto pivs = makePIndexHandles(ivs); | |
88 IndexedValue A(arg_A), B(arg_B), C(arg_C); | 72 IndexedValue A(arg_A), B(arg_B), C(arg_C); |
89 AffineLoopNestBuilder(pivs, view_A.getLbs(), view_A.getUbs(), view_A.getSteps())( | 73 AffineLoopNestBuilder( |
90 [&]{ | 74 ivs, view_A.getLbs(), view_A.getUbs(), view_A.getSteps())([&]{ |
91 C(ivs) = A(ivs) + B(ivs) | 75 C(ivs) = A(ivs) + B(ivs) |
92 }); | 76 }); |
93 }]; | 77 }]; |
94 } | 78 } |
95 ``` | 79 ``` |
117 // CHECK: {{.*}} = load %arg0[] : memref<f32> | 101 // CHECK: {{.*}} = load %arg0[] : memref<f32> |
118 // CHECK: {{.*}} = addf {{.*}}, {{.*}} : f32 | 102 // CHECK: {{.*}} = addf {{.*}}, {{.*}} : f32 |
119 // CHECK: store {{.*}}, %arg2[] : memref<f32> | 103 // CHECK: store {{.*}}, %arg2[] : memref<f32> |
120 ``` | 104 ``` |
121 | 105 |
122 Similar APIs are provided to emit the lower-level `loop.for` op with | 106 Similar APIs are provided to emit the lower-level `scf.for` op with |
123 `LoopNestBuilder`. See the `builder-api-test.cpp` test for more usage examples. | 107 `LoopNestBuilder`. See the `builder-api-test.cpp` test for more usage examples. |
124 | 108 |
125 Since the implementation of declarative builders is in C++, it is also available | 109 Since the implementation of declarative builders is in C++, it is also available |
126 to program the IR with an embedded-DSL flavor directly integrated in MLIR. We | 110 to program the IR with an embedded-DSL flavor directly integrated in MLIR. |
127 make use of these properties in the tutorial. | |
128 | |
129 Spoiler: MLIR also provides Python bindings for these builders, and a | |
130 full-fledged Python machine learning DSL with automatic differentiation | |
131 targeting MLIR was built as an early research collaboration. | |
132 |