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.brehler@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 jpienaar@google.com Co-authored-by: Simon Camphausen simon.camphausen@iml.fraunhofer.de Co-authored-by: Oliver Scherf oliver.scherf@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-... 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-... 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-...
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-... --fail curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-... --fail curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-... --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/c...
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-... Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-release-...
Full commit (up to 1000 lines): <cut> commit 876de062f94650f9ded56a22b062236f711fcd18 Author: Marius Brehler marius.brehler@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 jpienaar@google.com Co-authored-by: Simon Camphausen simon.camphausen@iml.fraunhofer.de Co-authored-by: Oliver Scherf oliver.scherf@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::vectorstd::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 ®istry) { 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.isaemitc::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::vectorstd::string"> + emitc.call "f"() {args = [!emitc.opaque<"std::vectorstd::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>