comparison mlir/docs/ConversionToLLVMDialect.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 2e18cbf3894f
comparison
equal deleted inserted replaced
172:9fbae9c8bf63 173:0572611fdcc8
1 # Conversion to the LLVM Dialect 1 # Conversion to the LLVM Dialect
2 2
3 Conversion from the Standard to the [LLVM Dialect](Dialects/LLVM.md) can be 3 Conversion from the Standard to the [LLVM Dialect](Dialects/LLVM.md) can be
4 performed by the specialized dialect conversion pass by running 4 performed by the specialized dialect conversion pass by running:
5 5
6 ```shell 6 ```shell
7 mlir-opt -convert-std-to-llvm <filename.mlir> 7 mlir-opt -convert-std-to-llvm <filename.mlir>
8 ``` 8 ```
9 9
17 ## Type Conversion 17 ## Type Conversion
18 18
19 ### Scalar Types 19 ### Scalar Types
20 20
21 Scalar types are converted to their LLVM counterparts if they exist. The 21 Scalar types are converted to their LLVM counterparts if they exist. The
22 following conversions are currently implemented. 22 following conversions are currently implemented:
23 23
24 - `i*` converts to `!llvm.i*` 24 - `i*` converts to `!llvm.i*`
25 - `f16` converts to `!llvm.half` 25 - `f16` converts to `!llvm.half`
26 - `f32` converts to `!llvm.float` 26 - `f32` converts to `!llvm.float`
27 - `f64` converts to `!llvm.double` 27 - `f64` converts to `!llvm.double`
50 50
51 ### Memref Types 51 ### Memref Types
52 52
53 Memref types in MLIR have both static and dynamic information associated with 53 Memref types in MLIR have both static and dynamic information associated with
54 them. The dynamic information comprises the buffer pointer as well as sizes and 54 them. The dynamic information comprises the buffer pointer as well as sizes and
55 strides of any dynamically sized dimensions. Memref types are normalized and 55 strides of any dynamically-sized dimensions. Memref types are normalized and
56 converted to a descriptor that is only dependent on the rank of the memref. The 56 converted to a descriptor that is only dependent on the rank of the memref. The
57 descriptor contains: 57 descriptor contains:
58 58
59 1. the pointer to the data buffer, followed by 59 1. the pointer to the data buffer, followed by
60 2. the pointer to properly aligned data payload that the memref indexes, 60 2. the pointer to properly aligned data payload that the memref indexes,
88 88
89 // Memref types can have vectors as element types 89 // Memref types can have vectors as element types
90 memref<1x? x vector<4xf32>> -> !llvm<"{ <4 x float>*, <4 x float>*, i64, [1 x i64], [1 x i64] }"> 90 memref<1x? x vector<4xf32>> -> !llvm<"{ <4 x float>*, <4 x float>*, i64, [1 x i64], [1 x i64] }">
91 ``` 91 ```
92 92
93 If the rank of the memref is unknown at compile time, the Memref is converted to 93 If the rank of the memref is unknown at compile time, the memref is converted to
94 an unranked descriptor that contains: 94 an unranked descriptor that contains:
95 95
96 1. a 64-bit integer representing the dynamic rank of the memref, followed by 96 1. a 64-bit integer representing the dynamic rank of the memref, followed by
97 2. a pointer to a ranked memref descriptor with the contents listed above. 97 2. a pointer to a ranked memref descriptor with the contents listed above.
98 98
126 individually according to these rules. The result types need to accommodate the 126 individually according to these rules. The result types need to accommodate the
127 fact that LLVM IR functions always have a return type, which may be a Void type. 127 fact that LLVM IR functions always have a return type, which may be a Void type.
128 The converted function always has a single result type. If the original function 128 The converted function always has a single result type. If the original function
129 type had no results, the converted function will have one result of the wrapped 129 type had no results, the converted function will have one result of the wrapped
130 `void` type. If the original function type had one result, the converted 130 `void` type. If the original function type had one result, the converted
131 function will have one result converted using these rules. Otherwise, the result 131 function will also have one result converted using these rules. Otherwise, the result
132 type will be a wrapped LLVM IR structure type where each element of the 132 type will be a wrapped LLVM IR structure type where each element of the
133 structure corresponds to one of the results of the original function, converted 133 structure corresponds to one of the results of the original function, converted
134 using these rules. In high-order functions, function-typed arguments and results 134 using these rules. In high-order functions, function-typed arguments and results
135 are converted to a wrapped LLVM IR function pointer type (since LLVM IR does not 135 are converted to a wrapped LLVM IR function pointer type (since LLVM IR does not
136 allow passing functions to functions without indirection) with the pointee type 136 allow passing functions to functions without indirection) with the pointee type
372 *This convention may or may not apply if the conversion of MemRef types is 372 *This convention may or may not apply if the conversion of MemRef types is
373 overridden by the user.* 373 overridden by the user.*
374 374
375 ### C-compatible wrapper emission 375 ### C-compatible wrapper emission
376 376
377 In practical cases, it may be desirable to have externally-facing functions 377 In practical cases, it may be desirable to have externally-facing functions with
378 with a single attribute corresponding to a MemRef argument. When interfacing 378 a single attribute corresponding to a MemRef argument. When interfacing with
379 with LLVM IR produced from C, the code needs to respect the corresponding 379 LLVM IR produced from C, the code needs to respect the corresponding calling
380 calling convention. The conversion to the LLVM dialect provides an option to 380 convention. The conversion to the LLVM dialect provides an option to generate
381 generate wrapper functions that take memref descriptors as pointers-to-struct 381 wrapper functions that take memref descriptors as pointers-to-struct compatible
382 compatible with data types produced by Clang when compiling C sources. 382 with data types produced by Clang when compiling C sources. The generation of
383 such wrapper functions can additionally be controlled at a function granularity
384 by setting the `llvm.emit_c_interface` unit attribute.
383 385
384 More specifically, a memref argument is converted into a pointer-to-struct 386 More specifically, a memref argument is converted into a pointer-to-struct
385 argument of type `{T*, T*, i64, i64[N], i64[N]}*` in the wrapper function, where 387 argument of type `{T*, T*, i64, i64[N], i64[N]}*` in the wrapper function, where
386 `T` is the converted element type and `N` is the memref rank. This type is 388 `T` is the converted element type and `N` is the memref rank. This type is
387 compatible with that produced by Clang for the following C++ structure template 389 compatible with that produced by Clang for the following C++ structure template
392 struct MemRefDescriptor { 394 struct MemRefDescriptor {
393 T *allocated; 395 T *allocated;
394 T *aligned; 396 T *aligned;
395 intptr_t offset; 397 intptr_t offset;
396 intptr_t sizes[N]; 398 intptr_t sizes[N];
397 intptr_t stides[N]; 399 intptr_t strides[N];
398 }; 400 };
399 ``` 401 ```
400 402
401 If enabled, the option will do the following. For _external_ functions declared 403 If enabled, the option will do the following. For _external_ functions declared
402 in the MLIR module. 404 in the MLIR module.
405 are converted to pointer-to-struct and the remaining arguments are converted 407 are converted to pointer-to-struct and the remaining arguments are converted
406 as usual. 408 as usual.
407 1. Add a body to the original function (making it non-external) that 409 1. Add a body to the original function (making it non-external) that
408 1. allocates a memref descriptor, 410 1. allocates a memref descriptor,
409 1. populates it, and 411 1. populates it, and
410 1. passes the pointer to it into the newly declared interface function 412 1. passes the pointer to it into the newly declared interface function, then
411 1. collects the result of the call and returns it to the caller. 413 1. collects the result of the call and returns it to the caller.
412 414
413 For (non-external) functions defined in the MLIR module. 415 For (non-external) functions defined in the MLIR module.
414 416
415 1. Define a new function `_mlir_ciface_<original name>` where memref arguments 417 1. Define a new function `_mlir_ciface_<original name>` where memref arguments
558 from the memref type. This descriptor holds all the necessary information to 560 from the memref type. This descriptor holds all the necessary information to
559 produce an address of a specific element. In particular, it holds dynamic values 561 produce an address of a specific element. In particular, it holds dynamic values
560 for static sizes, and they are expected to match at all times. 562 for static sizes, and they are expected to match at all times.
561 563
562 It is created by the allocation operation and is updated by the conversion 564 It is created by the allocation operation and is updated by the conversion
563 operations that may change static dimensions into dynamic and vice versa. 565 operations that may change static dimensions into dynamic dimensions and vice versa.
564 566
565 **Note**: LLVM IR conversion does not support `memref`s with layouts that are 567 **Note**: LLVM IR conversion does not support `memref`s with layouts that are
566 not amenable to the strided form. 568 not amenable to the strided form.
567 569
568 ### Index Linearization 570 ### Index Linearization