Successfully identified regression in *llvm* in CI configuration 
tcwg_bmk_llvm_apm/llvm-release-arm-spec2k6-Oz.  So far, this commit has 
regressed CI configurations:
 - tcwg_bmk_llvm_apm/llvm-release-arm-spec2k6-Oz

Culprit:
<cut>
commit 876de062f94650f9ded56a22b062236f711fcd18
Author: Marius Brehler <marius.breh...@iml.fraunhofer.de>
Date:   Wed Jun 9 13:38:10 2021 +0000

    [mlir] Add EmitC dialect
    
    This upstreams the EmitC dialect and the corresponding Cpp target, both
    initially presented with [1], from [2] to MLIR core. For the related
    discussion, see [3].
    
    [1] https://reviews.llvm.org/D76571
    [2] https://github.com/iml130/mlir-emitc
    [3] https://llvm.discourse.group/t/emitc-generating-c-c-from-mlir/3388
    
    Co-authored-by: Jacques Pienaar <jpien...@google.com>
    Co-authored-by: Simon Camphausen <simon.camphau...@iml.fraunhofer.de>
    Co-authored-by: Oliver Scherf <oliver.sch...@iml.fraunhofer.de>
    
    Reviewed By: rriddle
    
    Differential Revision: https://reviews.llvm.org/D103969
</cut>

Results regressed to (for first_bad == 876de062f94650f9ded56a22b062236f711fcd18)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set 
gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set 
gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -Oz_mthumb 
artifacts/build-876de062f94650f9ded56a22b062236f711fcd18/results_id:
1
# 470.lbm,lbm_base.default                                      regressed by 107

from (for last_good == 1bd4085e0bbc14ec61ab69c83464098622b2df56)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set 
gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set 
gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -Oz_mthumb 
artifacts/build-1bd4085e0bbc14ec61ab69c83464098622b2df56/results_id:
1

Artifacts of last_good build: 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/build-1bd4085e0bbc14ec61ab69c83464098622b2df56/
Results ID of last_good: 
apm_32/tcwg_bmk_llvm_apm/bisect-llvm-release-arm-spec2k6-Oz/4752
Artifacts of first_bad build: 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/build-876de062f94650f9ded56a22b062236f711fcd18/
Results ID of first_bad: 
apm_32/tcwg_bmk_llvm_apm/bisect-llvm-release-arm-spec2k6-Oz/4718
Build top page/logs: 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/

Configuration details:


Reproduce builds:
<cut>
mkdir investigate-llvm-876de062f94650f9ded56a22b062236f711fcd18
cd investigate-llvm-876de062f94650f9ded56a22b062236f711fcd18

git clone https://git.linaro.org/toolchain/jenkins-scripts

mkdir -p artifacts/manifests
curl -o artifacts/manifests/build-baseline.sh 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/manifests/build-baseline.sh
 --fail
curl -o artifacts/manifests/build-parameters.sh 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/manifests/build-parameters.sh
 --fail
curl -o artifacts/test.sh 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/test.sh
 --fail
chmod +x artifacts/test.sh

# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh

# Save baseline build state (which is then restored in artifacts/test.sh)
mkdir -p ./bisect
rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ 
--exclude /llvm/ ./ ./bisect/baseline/

cd llvm

# Reproduce first_bad build
git checkout --detach 876de062f94650f9ded56a22b062236f711fcd18
../artifacts/test.sh

# Reproduce last_good build
git checkout --detach 1bd4085e0bbc14ec61ab69c83464098622b2df56
../artifacts/test.sh

cd ..
</cut>

History of pending regressions and results: 
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/ci/tcwg_bmk_llvm_apm/llvm-release-arm-spec2k6-Oz

Artifacts: 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/artifact/artifacts/
Build log: 
https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-arm-spec2k6-Oz/4/consoleText

Full commit (up to 1000 lines):
<cut>
commit 876de062f94650f9ded56a22b062236f711fcd18
Author: Marius Brehler <marius.breh...@iml.fraunhofer.de>
Date:   Wed Jun 9 13:38:10 2021 +0000

    [mlir] Add EmitC dialect
    
    This upstreams the EmitC dialect and the corresponding Cpp target, both
    initially presented with [1], from [2] to MLIR core. For the related
    discussion, see [3].
    
    [1] https://reviews.llvm.org/D76571
    [2] https://github.com/iml130/mlir-emitc
    [3] https://llvm.discourse.group/t/emitc-generating-c-c-from-mlir/3388
    
    Co-authored-by: Jacques Pienaar <jpien...@google.com>
    Co-authored-by: Simon Camphausen <simon.camphau...@iml.fraunhofer.de>
    Co-authored-by: Oliver Scherf <oliver.sch...@iml.fraunhofer.de>
    
    Reviewed By: rriddle
    
    Differential Revision: https://reviews.llvm.org/D103969
---
 mlir/include/mlir/Dialect/CMakeLists.txt           |   1 +
 mlir/include/mlir/Dialect/EmitC/CMakeLists.txt     |   1 +
 mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt  |   7 +
 mlir/include/mlir/Dialect/EmitC/IR/EmitC.h         |  32 ++++
 mlir/include/mlir/Dialect/EmitC/IR/EmitC.td        | 148 ++++++++++++++
 .../mlir/Dialect/EmitC/IR/EmitCAttributes.td       |  45 +++++
 mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td    |  28 +++
 mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td   |  46 +++++
 mlir/include/mlir/InitAllDialects.h                |   2 +
 mlir/lib/Dialect/CMakeLists.txt                    |   1 +
 mlir/lib/Dialect/EmitC/CMakeLists.txt              |   1 +
 mlir/lib/Dialect/EmitC/IR/CMakeLists.txt           |  14 ++
 mlir/lib/Dialect/EmitC/IR/EmitC.cpp                | 212 +++++++++++++++++++++
 mlir/test/Dialect/EmitC/invalid_ops.mlir           |  79 ++++++++
 mlir/test/Dialect/EmitC/ops.mlir                   |  24 +++
 mlir/test/Dialect/EmitC/types.mlir                 |  18 ++
 mlir/test/mlir-opt/commandline.mlir                |   1 +
 17 files changed, 660 insertions(+)

diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt 
b/mlir/include/mlir/Dialect/CMakeLists.txt
index 2d6d04a52a9d..44a9249cef83 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(ArmSVE)
 add_subdirectory(AMX)
 add_subdirectory(Complex)
 add_subdirectory(DLTI)
+add_subdirectory(EmitC)
 add_subdirectory(GPU)
 add_subdirectory(Math)
 add_subdirectory(Linalg)
diff --git a/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt 
b/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt
new file mode 100644
index 000000000000..f33061b2d87c
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt 
b/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt
new file mode 100644
index 000000000000..09a9f7a2ec1c
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_mlir_dialect(EmitC emitc)
+add_mlir_doc(EmitC EmitC Dialects/ -gen-dialect-doc)
+
+set(LLVM_TARGET_DEFINITIONS EmitCAttributes.td)
+mlir_tablegen(EmitCAttributes.h.inc -gen-attrdef-decls)
+mlir_tablegen(EmitCAttributes.cpp.inc -gen-attrdef-defs)
+add_public_tablegen_target(MLIREmitCAttributesIncGen)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h 
b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
new file mode 100644
index 000000000000..857d1430f941
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -0,0 +1,32 @@
+//===- EmitC.h - EmitC Dialect ----------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares EmitC in MLIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITC_H
+#define MLIR_DIALECT_EMITC_IR_EMITC_H
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+#include "mlir/Dialect/EmitC/IR/EmitCDialect.h.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.h.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitC.h.inc"
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITC_H
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td 
b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
new file mode 100644
index 000000000000..78c682a80671
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -0,0 +1,148 @@
+//===- EmitC.td - EmitC operations--------------------------*- tablegen 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITC
+#define MLIR_DIALECT_EMITC_IR_EMITC
+
+include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
+include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
+
+include "mlir/Interfaces/SideEffectInterfaces.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC op definitions
+//===----------------------------------------------------------------------===//
+
+// Base class for EmitC dialect ops.
+class EmitC_Op<string mnemonic, list<OpTrait> traits = []>
+    : Op<EmitC_Dialect, mnemonic, traits> {
+  let verifier = "return ::verify(*this);";
+}
+
+def EmitC_ApplyOp : EmitC_Op<"apply", []> {
+  let summary = "Apply operation";
+  let description = [{
+    With the `apply` operation the operators & (address of) and * (contents of)
+    can be applied to a single operand.
+
+    Example:
+
+    ```mlir
+    // Custom form of applying the & operator.
+    %0 = emitc.apply "&"(%arg0) : (i32) -> !emitc.opaque<"int32_t*">
+
+    // Generic form of the same operation.
+    %0 = "emitc.apply"(%arg0) {applicableOperator = "&"}
+        : (i32) -> !emitc.opaque<"int32_t*">
+
+    ```
+  }];
+  let arguments = (ins
+    Arg<StrAttr, "the operator to apply">:$applicableOperator,
+    AnyType:$operand
+  );
+  let results = (outs AnyType:$result);
+  let assemblyFormat = [{
+    $applicableOperator `(` $operand `)` attr-dict `:` 
functional-type($operand, results)
+  }];
+}
+
+def EmitC_CallOp : EmitC_Op<"call", []> {
+  let summary = "Call operation";
+  let description = [{
+    The `call` operation represents a C++ function call. The call allows
+    specifying order of operands and attributes in the call as follows:
+
+    - integer value of index type refers to an operand;
+    - attribute which will get lowered to constant value in call;
+
+    Example:
+
+    ```mlir
+    // Custom form defining a call to `foo()`.
+    %0 = emitc.call "foo" () : () -> i32
+
+    // Generic form of the same operation.
+    %0 = "emitc.call"() {callee = "foo"} : () -> i32
+    ```
+  }];
+  let arguments = (ins
+    Arg<StrAttr, "the C++ function to call">:$callee,
+    Arg<OptionalAttr<ArrayAttr>, "the order of operands and further 
attributes">:$args,
+    Arg<OptionalAttr<ArrayAttr>, "template arguments">:$template_args,
+    Variadic<AnyType>:$operands
+  );
+  let results = (outs Variadic<AnyType>);
+  let assemblyFormat = [{
+    $callee `(` $operands `)` attr-dict `:` functional-type($operands, results)
+  }];
+}
+
+def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
+  let summary = "Constant operation";
+  let description = [{
+    The `constant` operation produces an SSA value equal to some constant
+    specified by an attribute. This can be used to form simple integer and
+    floating point constants, as well as more exotic things like tensor
+    constants. The `constant` operation also supports the EmitC opaque
+    attribute and the EmitC opaque type.
+
+    Example:
+
+    ```mlir
+    // Integer constant
+    %0 = "emitc.constant"(){value = 42 : i32} : () -> i32
+
+    // Constant emitted as `int32_t* = NULL;`
+    %1 = "emitc.constant"()
+        {value = #emitc.opaque<"NULL"> : !emitc.opaque<"int32_t*">}
+        : () -> !emitc.opaque<"int32_t*">
+    ```
+  }];
+
+  let arguments = (ins AnyAttr:$value);
+  let results = (outs AnyType);
+
+  let hasFolder = 1;
+}
+
+def EmitC_IncludeOp
+    : EmitC_Op<"include", [NoSideEffect, HasParent<"ModuleOp">]> {
+  let summary = "Include operation";
+  let description = [{
+    The `include` operation allows to define a source file inclusion via the
+    `#include` directive.
+
+    Example:
+
+    ```mlir
+    // Custom form defining the inclusion of `<myheader>`.
+    emitc.include "myheader.h" is_standard_include
+
+    // Generic form of the same operation.
+    "emitc.include" (){include = "myheader.h", is_standard_include} : () -> ()
+
+    // Generic form defining the inclusion of `"myheader"`.
+    "emitc.include" (){include = "myheader.h"} : () -> ()
+    ```
+  }];
+  let arguments = (ins
+    Arg<StrAttr, "source file to include">:$include,
+    UnitAttr:$is_standard_include
+  );
+  let assemblyFormat = [{
+    $include attr-dict (`is_standard_include` $is_standard_include^)?
+  }];
+  let verifier = ?;
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITC
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td 
b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
new file mode 100644
index 000000000000..2dd782ba49bf
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
@@ -0,0 +1,45 @@
+//===- EmitCAttributes.td - EmitC attributes ---------------*- tablegen 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
+#define MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
+
+include "mlir/Dialect/EmitC/IR/EmitCBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC attribute definitions
+//===----------------------------------------------------------------------===//
+
+class EmitC_Attr<string name, string attrMnemonic>
+    : AttrDef<EmitC_Dialect, name> {
+  let mnemonic = attrMnemonic;
+}
+
+def EmitC_OpaqueAttr : EmitC_Attr<"Opaque", "opaque"> {
+  let summary = "An opaque attribute";
+
+  let description = [{
+    An opaque attribute of which the value gets emitted as is.
+
+    Example:
+
+    ```mlir
+    #emitc.opaque<"">
+    #emitc.opaque<"NULL">
+    #emitc.opaque<"nullptr">
+    ```
+  }];
+
+  let parameters = (ins StringRefParameter<"the opaque value">:$value);
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td 
b/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td
new file mode 100644
index 000000000000..5b7e81e2833a
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td
@@ -0,0 +1,28 @@
+//===- EmitCBase.td - EmitC dialect ------------------------*- tablegen 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCBASE
+#define MLIR_DIALECT_EMITC_IR_EMITCBASE
+
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC dialect definition
+//===----------------------------------------------------------------------===//
+
+def EmitC_Dialect : Dialect {
+  let name = "emitc";
+  let cppNamespace = "::mlir::emitc";
+  let hasConstantMaterializer = 1;
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCBASE
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td 
b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
new file mode 100644
index 000000000000..d6fdd0fbf82d
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -0,0 +1,46 @@
+//===- EmitCTypes.td - EmitC types -------------------------*- tablegen 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC types.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCTYPES
+#define MLIR_DIALECT_EMITC_IR_EMITCTYPES
+
+include "mlir/Dialect/EmitC/IR/EmitCBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC type definitions
+//===----------------------------------------------------------------------===//
+
+class EmitC_Type<string name, string typeMnemonic>
+    : TypeDef<EmitC_Dialect, name> {
+  let mnemonic = typeMnemonic;
+}
+
+def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
+  let summary = "An opaque type";
+
+  let description = [{
+    An opaque data type of which the value gets emitted as is.
+
+    Example:
+
+    ```mlir
+    !emitc.opaque<"int">
+    !emitc.opaque<"float *">
+    !emitc.opaque<"std::vector<std::string>">
+    ```
+  }];
+
+  let parameters = (ins StringRefParameter<"the opaque value">:$value);
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES
diff --git a/mlir/include/mlir/InitAllDialects.h 
b/mlir/include/mlir/InitAllDialects.h
index e44f2e8f1ae0..c52dae3fd1b5 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -21,6 +21,7 @@
 #include "mlir/Dialect/Async/IR/Async.h"
 #include "mlir/Dialect/Complex/IR/Complex.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
 #include "mlir/Dialect/GPU/GPUDialect.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
@@ -57,6 +58,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
                   async::AsyncDialect,
                   complex::ComplexDialect,
                   DLTIDialect,
+                  emitc::EmitCDialect,
                   gpu::GPUDialect,
                   LLVM::LLVMDialect,
                   linalg::LinalgDialect,
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index f5124f7d138f..de946beef0d9 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(Async)
 add_subdirectory(AMX)
 add_subdirectory(Complex)
 add_subdirectory(DLTI)
+add_subdirectory(EmitC)
 add_subdirectory(GPU)
 add_subdirectory(Linalg)
 add_subdirectory(LLVMIR)
diff --git a/mlir/lib/Dialect/EmitC/CMakeLists.txt 
b/mlir/lib/Dialect/EmitC/CMakeLists.txt
new file mode 100644
index 000000000000..f33061b2d87c
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt 
b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
new file mode 100644
index 000000000000..6283441fdadf
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_mlir_dialect_library(MLIREmitC
+  EmitC.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/EmitC
+
+  DEPENDS
+  MLIREmitCIncGen
+  MLIREmitCAttributesIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRSideEffectInterfaces
+  )
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp 
b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
new file mode 100644
index 000000000000..364c247f75e4
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -0,0 +1,212 @@
+//===- EmitC.cpp - EmitC Dialect 
------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace mlir;
+using namespace mlir::emitc;
+
+//===----------------------------------------------------------------------===//
+// EmitCDialect
+//===----------------------------------------------------------------------===//
+
+void EmitCDialect::initialize() {
+  addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
+      >();
+  addTypes<
+#define GET_TYPEDEF_LIST
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
+      >();
+  addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
+      >();
+}
+
+/// Materialize a single constant operation from a given attribute value with
+/// the desired resultant type.
+Operation *EmitCDialect::materializeConstant(OpBuilder &builder,
+                                             Attribute value, Type type,
+                                             Location loc) {
+  return builder.create<ConstantOp>(loc, type, value);
+}
+
+//===----------------------------------------------------------------------===//
+// ApplyOp
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verify(ApplyOp op) {
+  StringRef applicableOperator = op.applicableOperator();
+
+  // Applicable operator must not be empty.
+  if (applicableOperator.empty())
+    return op.emitOpError("applicable operator must not be empty");
+
+  // Only `*` and `&` are supported.
+  if (applicableOperator != "&" && applicableOperator != "*")
+    return op.emitOpError("applicable operator is illegal");
+
+  return success();
+}
+
+//===----------------------------------------------------------------------===//
+// CallOp
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verify(emitc::CallOp op) {
+  // Callee must not be empty.
+  if (op.callee().empty())
+    return op.emitOpError("callee must not be empty");
+
+  if (Optional<ArrayAttr> argsAttr = op.args()) {
+    for (Attribute arg : argsAttr.getValue()) {
+      if (arg.getType().isa<IndexType>()) {
+        int64_t index = arg.cast<IntegerAttr>().getInt();
+        // Args with elements of type index must be in range
+        // [0..operands.size).
+        if ((index < 0) || (index >= 
static_cast<int64_t>(op.getNumOperands())))
+          return op.emitOpError("index argument is out of range");
+
+        // Args with elements of type ArrayAttr must have a type.
+      } else if (arg.isa<ArrayAttr>() && arg.getType().isa<NoneType>()) {
+        return op.emitOpError("array argument has no type");
+      }
+    }
+  }
+
+  if (Optional<ArrayAttr> templateArgsAttr = op.template_args()) {
+    for (Attribute tArg : templateArgsAttr.getValue()) {
+      if (!tArg.isa<TypeAttr>() && !tArg.isa<IntegerAttr>() &&
+          !tArg.isa<FloatAttr>() && !tArg.isa<emitc::OpaqueAttr>())
+        return op.emitOpError("template argument has invalid type");
+    }
+  }
+
+  return success();
+}
+
+//===----------------------------------------------------------------------===//
+// ConstantOp
+//===----------------------------------------------------------------------===//
+
+/// The constant op requires that the attribute's type matches the return type.
+static LogicalResult verify(emitc::ConstantOp &op) {
+  Attribute value = op.value();
+  Type type = op.getType();
+  if (!value.getType().isa<NoneType>() && type != value.getType())
+    return op.emitOpError() << "requires attribute's type (" << value.getType()
+                            << ") to match op's return type (" << type << ")";
+  return success();
+}
+
+OpFoldResult emitc::ConstantOp::fold(ArrayRef<Attribute> operands) {
+  assert(operands.empty() && "constant has no operands");
+  return value();
+}
+
+//===----------------------------------------------------------------------===//
+// TableGen'd op method definitions
+//===----------------------------------------------------------------------===//
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
+
+//===----------------------------------------------------------------------===//
+// EmitC Attributes
+//===----------------------------------------------------------------------===//
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
+
+Attribute emitc::OpaqueAttr::parse(MLIRContext *context,
+                                   DialectAsmParser &parser, Type type) {
+  if (parser.parseLess())
+    return Attribute();
+  StringRef value;
+  llvm::SMLoc loc = parser.getCurrentLocation();
+  if (parser.parseOptionalString(&value)) {
+    parser.emitError(loc) << "expected string";
+    return Attribute();
+  }
+  if (parser.parseGreater())
+    return Attribute();
+  return get(context, value);
+}
+
+Attribute EmitCDialect::parseAttribute(DialectAsmParser &parser,
+                                       Type type) const {
+  llvm::SMLoc typeLoc = parser.getCurrentLocation();
+  StringRef mnemonic;
+  if (parser.parseKeyword(&mnemonic))
+    return Attribute();
+  Attribute genAttr;
+  OptionalParseResult parseResult =
+      generatedAttributeParser(getContext(), parser, mnemonic, type, genAttr);
+  if (parseResult.hasValue())
+    return genAttr;
+  parser.emitError(typeLoc, "unknown attribute in EmitC dialect");
+  return Attribute();
+}
+
+void EmitCDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const 
{
+  if (failed(generatedAttributePrinter(attr, os)))
+    llvm_unreachable("unexpected 'EmitC' attribute kind");
+}
+
+void emitc::OpaqueAttr::print(DialectAsmPrinter &printer) const {
+  printer << "opaque<\"" << getValue() << "\">";
+}
+
+//===----------------------------------------------------------------------===//
+// EmitC Types
+//===----------------------------------------------------------------------===//
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
+
+Type emitc::OpaqueType::parse(MLIRContext *context, DialectAsmParser &parser) {
+  if (parser.parseLess())
+    return Type();
+  StringRef value;
+  llvm::SMLoc loc = parser.getCurrentLocation();
+  if (parser.parseOptionalString(&value) || value.empty()) {
+    parser.emitError(loc) << "expected non empty string";
+    return Type();
+  }
+  if (parser.parseGreater())
+    return Type();
+  return get(context, value);
+}
+
+Type EmitCDialect::parseType(DialectAsmParser &parser) const {
+  llvm::SMLoc typeLoc = parser.getCurrentLocation();
+  StringRef mnemonic;
+  if (parser.parseKeyword(&mnemonic))
+    return Type();
+  Type genType;
+  OptionalParseResult parseResult =
+      generatedTypeParser(getContext(), parser, mnemonic, genType);
+  if (parseResult.hasValue())
+    return genType;
+  parser.emitError(typeLoc, "unknown type in EmitC dialect");
+  return Type();
+}
+
+void EmitCDialect::printType(Type type, DialectAsmPrinter &os) const {
+  if (failed(generatedTypePrinter(type, os)))
+    llvm_unreachable("unexpected 'EmitC' type kind");
+}
+
+void emitc::OpaqueType::print(DialectAsmPrinter &printer) const {
+  printer << "opaque<\"" << getValue() << "\">";
+}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir 
b/mlir/test/Dialect/EmitC/invalid_ops.mlir
new file mode 100644
index 000000000000..e86664627c36
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -0,0 +1,79 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+func @const_attribute_return_type_1() {
+    // expected-error @+1 {{'emitc.constant' op requires attribute's type 
('i64') to match op's return type ('i32')}}
+    %c0 = "emitc.constant"(){value = 42: i64} : () -> i32
+    return
+}
+
+// -----
+
+func @const_attribute_return_type_2() {
+    // expected-error @+1 {{'emitc.constant' op requires attribute's type 
('!emitc.opaque<"int32_t*">') to match op's return type 
('!emitc.opaque<"int32_t">')}}
+    %c0 = "emitc.constant"(){value = "nullptr" : !emitc.opaque<"int32_t*">} : 
() -> !emitc.opaque<"int32_t">
+    return
+}
+
+// -----
+
+func @index_args_out_of_range_1() {
+    // expected-error @+1 {{'emitc.call' op index argument is out of range}}
+    emitc.call "test" () {args = [0 : index]} : () -> ()
+    return
+}
+
+// -----
+
+func @index_args_out_of_range_2(%arg : i32) {
+    // expected-error @+1 {{'emitc.call' op index argument is out of range}}
+    emitc.call "test" (%arg, %arg) {args = [2 : index]} : (i32, i32) -> ()
+    return
+}
+
+// -----
+
+func @empty_callee() {
+    // expected-error @+1 {{'emitc.call' op callee must not be empty}}
+    emitc.call "" () : () -> ()
+    return
+}
+
+// -----
+
+func @nonetype_arg(%arg : i32) {
+    // expected-error @+1 {{'emitc.call' op array argument has no type}}
+    emitc.call "nonetype_arg"(%arg) {args = [0 : index, [0, 1, 2]]} : (i32) -> 
i32
+    return
+}
+
+// -----
+
+func @array_template_arg(%arg : i32) {
+    // expected-error @+1 {{'emitc.call' op template argument has invalid 
type}}
+    emitc.call "nonetype_template_arg"(%arg) {template_args = [[0, 1, 2]]} : 
(i32) -> i32
+    return
+}
+
+// -----
+
+func @dense_template_argument(%arg : i32) {
+    // expected-error @+1 {{'emitc.call' op template argument has invalid 
type}}
+    emitc.call "dense_template_argument"(%arg) {template_args = [dense<[1.0, 
1.0]> : tensor<2xf32>]} : (i32) -> i32
+    return
+}
+
+// -----
+
+func @empty_operator(%arg : i32) {
+    // expected-error @+1 {{'emitc.apply' op applicable operator must not be 
empty}}
+    %2 = emitc.apply ""(%arg) : (i32) -> !emitc.opaque<"int32_t*">
+    return
+}
+
+// -----
+
+func @illegal_operator(%arg : i32) {
+    // expected-error @+1 {{'emitc.apply' op applicable operator is illegal}}
+    %2 = emitc.apply "+"(%arg) : (i32) -> !emitc.opaque<"int32_t*">
+    return
+}
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
new file mode 100644
index 000000000000..3a48ff447e1c
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt -verify-diagnostics %s | FileCheck %s
+
+"emitc.include" (){include = "test.h", is_standard_include} : () -> ()
+emitc.include "test.h" is_standard_include
+
+// 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(%arg0: i32) {
+  %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
+}
diff --git a/mlir/test/Dialect/EmitC/types.mlir 
b/mlir/test/Dialect/EmitC/types.mlir
new file mode 100644
index 000000000000..f1ffce74e4c2
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/types.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt -verify-diagnostics %s | FileCheck %s
+// check parser
+// RUN: mlir-opt -verify-diagnostics %s | mlir-opt -verify-diagnostics | 
FileCheck %s
+
+// CHECK-LABEL: func @opaque_types() {
+func @opaque_types() {
+  // CHECK-NEXT: !emitc.opaque<"int">
+  emitc.call "f"() {args = [!emitc<"opaque<\"int\">">]} : () -> ()
+  // CHECK-NEXT: !emitc.opaque<"byte">
+  emitc.call "f"() {args = [!emitc<"opaque<\"byte\">">]} : () -> ()
+  // CHECK-NEXT: !emitc.opaque<"unsigned">
+  emitc.call "f"() {args = [!emitc<"opaque<\"unsigned\">">]} : () -> ()
+  // CHECK-NEXT: !emitc.opaque<"status_t">
+  emitc.call "f"() {args = [!emitc<"opaque<\"status_t\">">]} : () -> ()
+  // CHECK-NEXT: !emitc.opaque<"std::vector<std::string>">
+  emitc.call "f"() {args = [!emitc.opaque<"std::vector<std::string>">]} : () 
-> ()
+  return
+}
diff --git a/mlir/test/mlir-opt/commandline.mlir 
b/mlir/test/mlir-opt/commandline.mlir
index 125d6b1d950b..95c476a84163 100644
--- a/mlir/test/mlir-opt/commandline.mlir
+++ b/mlir/test/mlir-opt/commandline.mlir
@@ -8,6 +8,7 @@
 // CHECK-NEXT: async
 // CHECK-NEXT: complex
 // CHECK-NEXT: dlti
+// CHECK-NEXT: emitc
 // CHECK-NEXT: gpu
 // CHECK-NEXT: linalg
 // CHECK-NEXT: llvm
</cut>
_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to