This adds a variable op, emitted as C/C++ locale variable, which can be
used if the `emitc.constant` op is not sufficient.
As an example, the canonicalization pass would transform
```mlir
%0 = "emitc.constant"() {value = 0 : i32} : () -> i32
%1 = "emitc.constant"() {value = 0 : i32} : () -> i32
%2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
%3 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
emitc.call "write"(%2, %3) : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
```
into
```mlir
%0 = "emitc.constant"() {value = 0 : i32} : () -> i32
%1 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
%2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
emitc.call "write"(%1, %2) : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
```
resulting in pointer aliasing, as %1 and %2 point to the same address.
In such a case, the `emitc.variable` operation can be used instead.
Reviewed By: jpienaar
Differential Revision: https://reviews.llvm.org/D120098
25 lines
680 B
MLIR
25 lines
680 B
MLIR
// RUN: mlir-opt %s | mlir-opt | FileCheck %s
|
|
|
|
emitc.include <"test.h">
|
|
emitc.include "test.h"
|
|
|
|
// CHECK-LABEL: func @f(%{{.*}}: i32, %{{.*}}: !emitc.opaque<"int32_t">) {
|
|
func @f(%arg0: i32, %f: !emitc.opaque<"int32_t">) {
|
|
%1 = "emitc.call"() {callee = "blah"} : () -> i64
|
|
emitc.call "foo" (%1) {args = [
|
|
0 : index, dense<[0, 1]> : tensor<2xi32>, 0 : index
|
|
]} : (i64) -> ()
|
|
return
|
|
}
|
|
|
|
func @c() {
|
|
%1 = "emitc.constant"(){value = 42 : i32} : () -> i32
|
|
return
|
|
}
|
|
|
|
func @a(%arg0: i32, %arg1: i32) {
|
|
%1 = "emitc.apply"(%arg0) {applicableOperator = "&"} : (i32) -> !emitc.opaque<"int32_t*">
|
|
%2 = emitc.apply "&"(%arg1) : (i32) -> !emitc.opaque<"int32_t*">
|
|
return
|
|
}
|