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