Health and welfare on the iree_pydm dialect. (#6978)
Dialect changes:
* Simplify file naming to limit repetition.
* Add PythonTypeInterface, implemented by all Python types (currently used for some identity and numeric promotion rules).
* Apply previous recommendation and rework var alloc/load/store into a !free_var_ref type, alloc_free_var, load_var, store_var. Cell variables will need something different but this should generalize (i.e. cell vars need to be resolved symbolically, inter-procedurally).
* Add a UnionType in order to support type refinement (not yet used, and still needs some refinement).
* Forked scf.if into `functional_if` for the specific case where we are emitting conditional Python code of a functional nature (shows up in conditionals and short-circuit evals a lot, but most Python control flow is naturally CFG based). With this change, the pydm dialect is self-complete, not relying on ops from outside of itself. This will help with type inference, etc.
* Implemented OpAsmOpInterface::getDefaultDialect on `func` and `functional_if`, making all pydm ops able to be used prefix-free, cleaning up IR a lot.
* Made `none` ConstantLike. Added `success` and `failure` ops to produce `ExceptionResults`.
* Added `make_tuple` op (not yet used).
* Added `promote_numeric` op.
* Implemented simple folders for `constant`, `none`, `success`, `as_bool`, `bool_to_pred`, `raise_on_failure`, `select`.
* Implemented static numeric promotion with: a folder+canonicalizer on `promote_numeric`, a canonicalizer on `dynamic_binary_promote` which reduces it to primitives for static cases.
* Implemented no-op box/unbox canonicalizations.
With this, the dialect is in good shape to start building out the optimization and lowering pipelines.
diff --git a/llvm-external-projects/iree-dialects/BUILD b/llvm-external-projects/iree-dialects/BUILD
index 1531434..eb4db6e 100644
--- a/llvm-external-projects/iree-dialects/BUILD
+++ b/llvm-external-projects/iree-dialects/BUILD
@@ -92,31 +92,31 @@
tbl_outs = [
(
["-gen-dialect-decls"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsDialect.h.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.h.inc",
),
(
["-gen-dialect-defs"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsDialect.cpp.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.cpp.inc",
),
(
["-gen-op-decls"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Ops.h.inc",
),
(
["-gen-op-defs"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Ops.cpp.inc",
),
(
["-gen-typedef-decls"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsTypes.h.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Types.h.inc",
),
(
["-gen-typedef-defs"],
- "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsTypes.cpp.inc",
+ "include/iree-dialects/Dialect/IREEPyDM/IR/Types.cpp.inc",
),
],
tblgen = "@llvm-project//mlir:mlir-tblgen",
- td_file = "include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.td",
+ td_file = "include/iree-dialects/Dialect/IREEPyDM/IR/Ops.td",
deps = [
":TdFiles",
"@llvm-project//mlir:CallInterfacesTdFiles",
@@ -124,6 +124,26 @@
],
)
+gentbl_cc_library(
+ name = "IREEPyDMInterfacesIncGen",
+ strip_include_prefix = "include",
+ tbl_outs = [
+ (
+ ["-gen-type-interface-decls"],
+ "include/iree-dialects/Dialect/IREEPyDM/IR/TypeInterfaces.h.inc",
+ ),
+ (
+ ["-gen-type-interface-defs"],
+ "include/iree-dialects/Dialect/IREEPyDM/IR/TypeInterfaces.cpp.inc",
+ ),
+ ],
+ tblgen = "@llvm-project//mlir:mlir-tblgen",
+ td_file = "include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.td",
+ deps = [
+ ":TdFiles",
+ ],
+)
+
cc_library(
name = "IREEPyDMDialect",
srcs = glob([
@@ -132,6 +152,7 @@
hdrs = glob(["include/iree-dialects/Dialect/IREEPyDM/IR/*.h"]),
includes = ["include"],
deps = [
+ ":IREEPyDMInterfacesIncGen",
":IREEPyDMOpsIncGen",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:CallOpInterfaces",
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects-c/Dialects.h b/llvm-external-projects/iree-dialects/include/iree-dialects-c/Dialects.h
index ac17a04..27a1ba2 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects-c/Dialects.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects-c/Dialects.h
@@ -36,6 +36,7 @@
IREEPYDM_DECLARE_NULLARY_TYPE(Bytes)
IREEPYDM_DECLARE_NULLARY_TYPE(Integer)
IREEPYDM_DECLARE_NULLARY_TYPE(ExceptionResult)
+IREEPYDM_DECLARE_NULLARY_TYPE(FreeVarRef)
IREEPYDM_DECLARE_NULLARY_TYPE(List)
IREEPYDM_DECLARE_NULLARY_TYPE(None)
IREEPYDM_DECLARE_NULLARY_TYPE(Real)
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMBase.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Base.td
similarity index 92%
rename from llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMBase.td
rename to llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Base.td
index 40071d7..4ebc3de 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMBase.td
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Base.td
@@ -30,12 +30,13 @@
optimization benefits compared to fully untyped programs.
}];
let cppNamespace = "::mlir::iree_pydm";
+ let hasConstantMaterializer = 1;
}
class IREEPyDM_Op<string mnemonic, list<OpTrait> traits = []> :
Op<IREEPyDM_Dialect, mnemonic, traits>;
class IREEPyDM_PureOp<string mnemonic, list<OpTrait> traits = []> :
Op<IREEPyDM_Dialect, mnemonic, !listconcat(traits, [NoSideEffect])>;
-class IREEPyDM_TypeDef<string name> : TypeDef<IREEPyDM_Dialect, name>;
+class IREEPyDM_TypeDef<string name, list<Trait> traits = []> : TypeDef<IREEPyDM_Dialect, name, traits>;
#endif // IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_BASE_TD
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/CMakeLists.txt b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/CMakeLists.txt
index 5d94ff9..be5a935 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/CMakeLists.txt
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/CMakeLists.txt
@@ -1,3 +1,22 @@
-add_mlir_dialect(IREEPyDMOps iree_pydm)
-add_mlir_doc(IREEPyDMDialect IREEPyDMDialect IREEPyDM/ -gen-dialect-doc)
-add_mlir_doc(IREEPyDMOps IREEPyDMOps IREEPyDM/ -gen-op-doc)
+function(_add_interfaces)
+ set(LLVM_TARGET_DEFINITIONS Interfaces.td)
+ mlir_tablegen(TypeInterfaces.h.inc -gen-type-interface-decls)
+ mlir_tablegen(TypeInterfaces.cpp.inc -gen-type-interface-defs)
+ add_public_tablegen_target(MLIRIREEPyDMInterfacesIncGen)
+endfunction()
+
+function(_add_dialect)
+ set(LLVM_TARGET_DEFINITIONS Ops.td)
+ mlir_tablegen(Ops.h.inc -gen-op-decls)
+ mlir_tablegen(Ops.cpp.inc -gen-op-defs)
+ mlir_tablegen(Types.h.inc -gen-typedef-decls)
+ mlir_tablegen(Types.cpp.inc -gen-typedef-defs)
+ mlir_tablegen(Dialect.h.inc -gen-dialect-decls -dialect=iree_pydm)
+ mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs -dialect=iree_pydm)
+ add_public_tablegen_target(MLIRIREEPyDMOpsIncGen)
+ add_dependencies(MLIRIREEPyDMOpsIncGen MLIRIREEPyDMInterfacesIncGen)
+ add_dependencies(mlir-headers MLIRIREEPyDMOpsIncGen)
+endfunction()
+
+_add_dialect()
+_add_interfaces()
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.h
similarity index 70%
rename from llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h
rename to llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.h
index fb714cb..642898a 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.h
@@ -7,12 +7,32 @@
#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_DIALECT_H
#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_DIALECT_H
+#include "iree-dialects/Dialect/IREEPyDM/IR/Interfaces.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/Types.h"
namespace mlir {
namespace iree_pydm {
+// Each built-in (to the compiler) type has a unique code, enumerated here.
+// Generally, the closed part of the type system will have type codes <
+// FirstCustom.
+enum class BuiltinTypeCode : int {
+ Bool = 1,
+ Bytes,
+ ExceptionResult,
+ Integer,
+ List,
+ None,
+ Object,
+ Real,
+ Str,
+ Tuple,
+ Type,
+
+ FirstCustom = 100,
+};
+
/// Base class for all unboxed primitive types.
class PrimitiveType : public mlir::Type {
public:
@@ -25,10 +45,10 @@
// Include generated dialect code (this comment blocks clang-format from
// clobbering order).
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsDialect.h.inc"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h.inc"
#define GET_TYPEDEF_CLASSES
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsTypes.h.inc"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Types.h.inc"
namespace mlir {
namespace iree_pydm {
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.td
similarity index 70%
rename from llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.td
rename to llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.td
index 3bc6167..7cab375 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.td
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Dialect.td
@@ -7,7 +7,26 @@
#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_DIALECT_TD
#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_DIALECT_TD
-include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMBase.td"
+include "iree-dialects/Dialect/IREEPyDM/IR/Base.td"
+include "iree-dialects/Dialect/IREEPyDM/IR/Interfaces.td"
+
+//===----------------------------------------------------------------------===//
+// Variable Types
+//===----------------------------------------------------------------------===//
+
+def IREEPyDM_FreeVarRef : IREEPyDM_TypeDef<"FreeVarRef"> {
+ let mnemonic = "free_var_ref";
+ let summary = "A direct access 'free' variable slot within a func";
+ let description = [{
+ A 'free variable' is a non-shared, direct access variable in a function.
+ Other languages would call these 'locals'. In Python, they are distinguished
+ from 'cell variables'.
+ }];
+}
+
+def IREEPyDM_AnyVarRef : AnyTypeOf<[
+ IREEPyDM_FreeVarRef,
+], "Python variable reference">;
//===----------------------------------------------------------------------===//
// Unboxed Primitive Types
@@ -16,8 +35,11 @@
// Declare a new primitive type.
// When adding a new one, update the PrimitiveType::classof method in
// IREEPyDMDialect.h.
-class IREEPyDM_PrimitiveTypeDef<string name> :
- TypeDef<IREEPyDM_Dialect, name, /*traits=*/[],
+class IREEPyDM_PrimitiveTypeDef<
+ string name, list<string> overridenMethods = []> :
+ TypeDef<IREEPyDM_Dialect, name, /*traits=*/[
+ DeclareTypeInterfaceMethods<PythonTypeInterface, overridenMethods>
+ ],
/*baseCppClass=*/"::mlir::iree_pydm::PrimitiveType"> {
}
@@ -26,7 +48,7 @@
"unboxed primitive type",
"::mlir::iree_pydm::PrimitiveType">;
-def IREEPyDM_BoolType : IREEPyDM_PrimitiveTypeDef<"Bool"> {
+def IREEPyDM_BoolType : IREEPyDM_PrimitiveTypeDef<"Bool", ["getNumericPromotionOrder"]> {
let mnemonic = "bool";
let summary = "Type of bool values";
@@ -62,7 +84,7 @@
}];
}
-def IREEPyDM_IntegerType : IREEPyDM_PrimitiveTypeDef<"Integer"> {
+def IREEPyDM_IntegerType : IREEPyDM_PrimitiveTypeDef<"Integer", ["getNumericPromotionOrder"]> {
let mnemonic = "integer";
let summary = "Type of integer values";
@@ -95,7 +117,7 @@
}];
}
-def IREEPyDM_RealType : IREEPyDM_PrimitiveTypeDef<"Real"> {
+def IREEPyDM_RealType : IREEPyDM_PrimitiveTypeDef<"Real", ["getNumericPromotionOrder"]> {
let mnemonic = "real";
let summary = "Type of floating point values";
@@ -143,7 +165,8 @@
// Boxed objects
//===----------------------------------------------------------------------===//
-def IREEPyDM_ObjectType : IREEPyDM_TypeDef<"Object"> {
+def IREEPyDM_ObjectType : IREEPyDM_TypeDef<
+ "Object", [DeclareTypeInterfaceMethods<PythonTypeInterface>]> {
let mnemonic = "object";
let summary = "Core data type having an identity, type and value";
@@ -198,6 +221,52 @@
}
//===----------------------------------------------------------------------===//
+// Union type
+//===----------------------------------------------------------------------===//
+
+def IREEPyDM_UnionType : IREEPyDM_TypeDef<"Union"> {
+ let mnemonic = "union";
+
+ let summary = "Represents a union of types";
+
+ let description = [{
+ Unions show up naturally in Python data-flows and this type represents
+ them. Note that it is not a "real" type in that it has not runtime
+ realization. However, most ops can be parameterized in terms of unions, and
+ it is generally the job of the compiler to do something sensible with them
+ before lowering.
+ }];
+
+ let parameters = (ins
+ ArrayRefParameter<"::mlir::Type">:$alternatives
+ );
+
+ let genVerifyDecl = 1;
+ let printer = [{
+ $_printer << getMnemonic();
+ llvm::interleaveComma(getAlternatives(), $_printer);
+ }];
+
+ let parser = [{
+ if (parser.parseOptionalLess())
+ return get($_ctxt, {});
+
+ SmallVector<::mlir::Type> alternatives;
+
+ do {
+ Type type;
+ if ($_parser.parseType(type))
+ return Type();
+ alternatives.push_back(type);
+ } while (succeeded($_parser.parseOptionalComma()));
+
+ return getChecked([&]() {
+ return $_parser.emitError($_parser.getNameLoc());
+ }, $_ctxt, alternatives);
+ }];
+}
+
+//===----------------------------------------------------------------------===//
// Predicates and aggregate definitions
//===----------------------------------------------------------------------===//
@@ -210,6 +279,12 @@
IREEPyDM_PrimitiveType,
], "Python boxed or unboxed value">;
+def IREEPyDM_AnyNumericType : AnyTypeOf<[
+ IREEPyDM_BoolType,
+ IREEPyDM_IntegerType,
+ IREEPyDM_RealType,
+], "Python numeric type">;
+
def IREEPyDM_GenericObjectType : Type<
CPred<"::mlir::iree_pydm::ObjectType::isGenericObjectType($_self)">,
"generic object",
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.h
new file mode 100644
index 0000000..0dd249b
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.h
@@ -0,0 +1,22 @@
+// Copyright 2021 The IREE Authors
+//
+// Licensed 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
+
+#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_H
+#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_H
+
+#include "mlir/IR/Types.h"
+
+namespace mlir {
+namespace iree_pydm {
+
+enum class BuiltinTypeCode;
+
+} // namespace iree_pydm
+} // namespace mlir
+
+#include "iree-dialects/Dialect/IREEPyDM/IR/TypeInterfaces.h.inc"
+
+#endif // IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_H
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.td
new file mode 100644
index 0000000..804ded8
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Interfaces.td
@@ -0,0 +1,42 @@
+// Copyright 2021 The IREE Authors
+//
+// Licensed 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
+
+#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_TD
+#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_TD
+
+include "mlir/IR/OpBase.td"
+
+def PythonTypeInterface : TypeInterface<"PythonTypeInterface"> {
+ let description = [{
+ Interface implemented by all Python types which represent a value in the
+ data model.
+ }];
+ let cppNamespace = "::mlir::iree_pydm";
+
+ let methods = [
+ InterfaceMethod<[{
+ Gets the type code.
+ }], "BuiltinTypeCode", "getTypeCode", (ins)>,
+
+ InterfaceMethod<[{
+ Gets a Python-relevant type name for this type.
+
+ This is used for both diagnostic messages and sorting order. No two
+ MLIR types can have the same name.
+ }], "llvm::StringRef", "getPythonTypeName", (ins)>,
+
+ InterfaceMethod<[{
+ For numeric types, returns the promotion order.
+ Types with a lower promotion order will be promoted to the higher order
+ for most binary functions.
+ }], "llvm::Optional<int>", "getNumericPromotionOrder", (ins),
+ /*methodBody=*/[{}], /*defaultImplementation=*/[{
+ return {};
+ }]>
+ ];
+}
+
+#endif // IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_INTERFACES_TD
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.h
similarity index 83%
rename from llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h
rename to llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.h
index d08b0d2..487cedc 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.h
@@ -7,17 +7,18 @@
#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_IREEPYDM_IR_OPS_H
#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_IREEPYDM_IR_OPS_H
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
+#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#define GET_OP_CLASSES
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h.inc"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Ops.h.inc"
#endif // IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_IREEPYDM_IR_OPS_H
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.td
similarity index 76%
rename from llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.td
rename to llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.td
index 2a887f9..bc961ff 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.td
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/IR/Ops.td
@@ -7,13 +7,62 @@
#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_OPS_TD
#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_IR_OPS_TD
-include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.td"
+include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
+include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/SymbolInterfaces.td"
//===----------------------------------------------------------------------===//
+// Variable access
+//===----------------------------------------------------------------------===//
+
+def IREEPyDM_AllocFreeVarOp : IREEPyDM_PureOp<"alloc_free_var", [
+ MemoryEffects<[MemAlloc]>,
+ DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
+ let summary = "Declares a 'free variable' by name and instance number";
+ let description = [{
+ Free variables represent allocated storage for a single value. By default
+ it is a variant which can store anything.
+ }];
+
+ let arguments = (ins
+ StrAttr:$name,
+ OptionalAttr<IndexAttr>:$index);
+ let results = (outs IREEPyDM_FreeVarRef:$free_var);
+ let assemblyFormat = [{
+ $name (`[` $index^ `]`)? `->` type($free_var) attr-dict
+ }];
+}
+
+def IREEPyDM_LoadVarOp : IREEPyDM_PureOp<"load_var", [MemoryEffects<[MemRead]>]> {
+ let summary = "Loads a value from a variable";
+ let description = [{
+ Loads a value from a variables. The value is implicitly cast to the given
+ result type, which must be legal.
+ }];
+
+ let arguments = (ins IREEPyDM_AnyVarRef:$var);
+ let results = (outs IREEPyDM_AnyValueType);
+
+ let assemblyFormat = [{
+ $var `:` type($var) `->` type(results) attr-dict
+ }];
+}
+
+def IREEPyDM_StoreVarOp : IREEPyDM_Op<"store_var", [MemoryEffects<[MemWrite]>]> {
+ let summary = "Stores a value to a variable";
+
+ let arguments = (ins
+ IREEPyDM_AnyVarRef:$var,
+ IREEPyDM_AnyValueType:$value);
+ let assemblyFormat = [{
+ $var `=` $value `:` type(operands) attr-dict
+ }];
+}
+
+//===----------------------------------------------------------------------===//
// Functions
//===----------------------------------------------------------------------===//
@@ -23,7 +72,8 @@
IsolatedFromAbove,
FunctionLike,
CallableOpInterface,
- Symbol]> {
+ Symbol,
+ DeclareOpInterfaceMethods<OpAsmOpInterface, ["getDefaultDialect"]>]> {
let summary = "Python func";
let description = [{
Python functions map arguments to results and have the following additional
@@ -45,9 +95,9 @@
let arguments = (ins SymbolNameAttr:$sym_name,
TypeAttr:$type,
- StrArrayAttr:$arg_names,
- StrArrayAttr:$free_vars,
- StrArrayAttr:$cell_vars,
+ OptionalAttr<StrArrayAttr>:$arg_names,
+ OptionalAttr<StrArrayAttr>:$free_vars,
+ OptionalAttr<StrArrayAttr>:$cell_vars,
OptionalAttr<StrAttr>:$sym_visibility);
let regions = (region AnyRegion:$body);
@@ -126,6 +176,8 @@
let assemblyFormat = [{
$exc_result `:` type($exc_result) attr-dict
}];
+
+ let hasFolder = 1;
}
def IREEPyDM_CallOp : IREEPyDM_Op<"call", [
@@ -238,10 +290,13 @@
reference primitives, the providence must be tracked and the original boxed
value used (vs boxing a new one). Failure to do so will result in aliased
objects.
+
+ Note that this operation allows to box object->object but canonicalizes
+ away in such a case (this is a convenience for IR construction).
}];
let arguments = (ins
- IREEPyDM_AnyPrimitiveType:$primitive
+ IREEPyDM_AnyValueType:$primitive
);
let results = (outs
IREEPyDM_ObjectType:$object
@@ -250,6 +305,8 @@
let assemblyFormat = [{
$primitive `:` type($primitive) `->` type($object) attr-dict
}];
+
+ let hasCanonicalizeMethod = 1;
}
def IREEPyDM_UnboxOp : IREEPyDM_PureOp<"unbox"> {
@@ -270,87 +327,8 @@
let assemblyFormat = [{
$object `:` type($object) `->` type($primitive) attr-dict
}];
-}
-//===----------------------------------------------------------------------===//
-// Name access
-// While the CPython nomenclature is a bit inconsistent, we follow it where
-// it makes sense. Names are split into a few categories:
-// - Free Variables: Local variables that are not visible outside of the
-// containing (actual, not lexical) function. CPython bytecode refers
-// to operations on these as "FAST" (i.e. LOAD_FAST, STORE_FAST, DEL_FAST).
-// - Cell Variables: Variables that exist as part of the function closure
-// and are resolved through a level of indirection (cell).
-// - Global Variables: Variables that are resolved via the function's
-// globals().
-// At this level, all operations are done by name (at the CPython instruction
-// level, it is by ordinal).
-//===----------------------------------------------------------------------===//
-
-// TODO: Consider adding a dedicated free_var op to bind free variables and
-// move the string attribute there.
-def IREEPyDM_LoadFreeVarOp : IREEPyDM_PureOp<"load_free_var"> {
- let summary = "Loads a boxed free variable";
- let description = [{
- Loads the boxed object for a free variable. This is not failable at
- runtime, and if the slot is not initialized, it will contain a special
- NotInitialized primitive which cannot convert to anything else.
-
- When importing Python programs, they must use boxed accessors to free
- variable storage. Further analysis and transformation can promote these
- to unboxed access.
- }];
-
- let arguments = (ins StrAttr:$name);
- let results = (outs IREEPyDM_ObjectType:$value);
-
- let assemblyFormat = [{
- $name `->` type($value) attr-dict
- }];
-}
-
-def IREEPyDM_StoreFreeVarOp : IREEPyDM_Op<"store_free_var"> {
- let summary = "Stores a boxed free variable";
- let description = [{
- Stores a boxed value to a free variable slot.
- }];
-
- let arguments = (ins StrAttr:$name, IREEPyDM_ObjectType:$value);
-
- let assemblyFormat = [{
- $name `,` $value `:` type($value) attr-dict
- }];
-}
-
-def IREEPyDM_LoadFreeVarUnboxedOp : IREEPyDM_PureOp<"load_free_var_unboxed"> {
- let summary = "Loads an unboxed free variable";
- let description = [{
- Loads an unboxed value from a free variable slot. This will not be
- emitted in regular programs but can be used in intrinsics and by
- optimizations to remove boxing when types are guaranteed. It is a
- program error to load a mismatched type and will produce undefined
- behavior.
- }];
-
- let arguments = (ins StrAttr:$name);
- let results = (outs IREEPyDM_PrimitiveType:$value);
-
- let assemblyFormat = [{
- $name `->` type($value) attr-dict
- }];
-}
-
-def IREEPyDM_StoreFreeVarUnboxedOp : IREEPyDM_Op<"store_free_var_unboxed"> {
- let summary = "Stores an unboxed free variable";
- let description = [{
- Stores an unboxed value to a free variable slot.
- }];
-
- let arguments = (ins StrAttr:$name, IREEPyDM_PrimitiveType:$value);
-
- let assemblyFormat = [{
- $name `,` $value `:` type($value) attr-dict
- }];
+ let hasCanonicalizeMethod = 1;
}
//===----------------------------------------------------------------------===//
@@ -363,9 +341,9 @@
This op supports immutable value types that have direct coding as MLIR
attributes:
IntType -> IntegerAttr<i64>
- FloatType -> FloatAttr<double>
+ RealType -> FloatAttr<double>
StrType -> StringAttr
- BytesType -> BytesAttr
+ BytesType -> StringAttr
BoolType -> IntegerAttr<i1>
}];
@@ -379,14 +357,37 @@
let extraClassDeclaration = [{
Attribute getValue() { return (*this)->getAttr("value"); }
}];
+ let hasFolder = 1;
}
-def IREEPyDM_NoneOp : IREEPyDM_PureOp<"none"> {
+def IREEPyDM_NoneOp : IREEPyDM_PureOp<"none", [ConstantLike]> {
let summary = "Gets the singleton NoneType primitive value";
let results = (outs IREEPyDM_NoneType:$value);
let assemblyFormat = [{
- `->` type($value) attr-dict
+ attr-dict
}];
+ let hasFolder = 1;
+}
+
+// TODO: Make ConstantLike
+def IREEPyDM_FailureOp : IREEPyDM_PureOp<"failure", []> {
+ let summary = "Generates a constant failure ExceptionResult";
+ let results = (outs IREEPyDM_ExceptionResultType);
+ let assemblyFormat = [{
+ `->` type(results) attr-dict
+ }];
+}
+
+def IREEPyDM_SuccessOp : IREEPyDM_PureOp<"success", [ConstantLike]> {
+ let summary = "Generates a constant success ExceptionResult";
+ let description = [{
+ A successful ExceptionResultType folds to a UnitAttr.
+ }];
+ let results = (outs IREEPyDM_ExceptionResultType);
+ let assemblyFormat = [{
+ `->` type(results) attr-dict
+ }];
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -400,6 +401,8 @@
let assemblyFormat = [{
$value `:` type($value) `->` type(results) attr-dict
}];
+ let hasCanonicalizer = 1;
+ let hasFolder = 1;
}
def IREEPyDM_BoolToPredOp : IREEPyDM_PureOp<"bool_to_pred"> {
@@ -411,7 +414,20 @@
let arguments = (ins IREEPyDM_BoolType:$value);
let results = (outs I1);
let assemblyFormat = [{
- $value `:` type($value) `->` type(results) attr-dict
+ $value attr-dict
+ }];
+ let hasFolder = 1;
+}
+
+def IREEPyDM_MakeTupleOp : IREEPyDM_PureOp<"make_tuple"> {
+ let summary = "Makes a tuple from a static list of values";
+ let description = [{
+ Used for static construction of a tuple when the exact nature is known.
+ }];
+ let arguments = (ins Variadic<IREEPyDM_AnyValueType>:$slots);
+ let results = (outs IREEPyDM_TupleType:$tuple);
+ let assemblyFormat = [{
+ $slots `:` type($slots) `->` type(results) attr-dict
}];
}
@@ -431,6 +447,7 @@
let assemblyFormat = [{
$condition `,` $true_value `,` $false_value `:` type($result) attr-dict
}];
+ let hasFolder = 1;
}
def IREEPyDM_ExprStatementDiscardOp : IREEPyDM_Op<"expr_statement_discard"> {
@@ -445,6 +462,34 @@
}];
}
+def FunctionalIfOp : IREEPyDM_Op<"functional_if", [
+ DeclareOpInterfaceMethods<RegionBranchOpInterface>,
+ SingleBlockImplicitTerminator<"iree_pydm::YieldOp">, RecursiveSideEffects,
+ NoRegionArguments,
+ DeclareOpInterfaceMethods<OpAsmOpInterface, ["getDefaultDialect"]>]> {
+ let summary = "A functional if construct";
+ let description = [{
+ This is similar to `scf.if` but adapted for this dialect. It has a required
+ then region and an optional else region. Types yielded from both must
+ match the result types of the `functional_if` op.
+ }];
+ let arguments = (ins IREEPyDM_BoolType:$condition);
+ let results = (outs Variadic<AnyType>:$results);
+ let regions = (region SizedRegion<1>:$thenRegion, AnyRegion:$elseRegion);
+
+ let printer = [{ return ::print(p, *this); }];
+ let verifier = [{ return ::verify(*this); }];
+ let parser = [{ return ::parse$cppClass(parser, result); }];
+}
+
+def YieldOp : IREEPyDM_Op<"yield", [NoSideEffect, ReturnLike, Terminator,
+ ParentOneOf<["FunctionalIfOp"]>]> {
+ let summary = "Yields a value from a functional control flow region";
+ let arguments = (ins Variadic<AnyType>:$results);
+ let assemblyFormat =
+ [{ attr-dict ($results^ `:` type($results))? }];
+}
+
//===----------------------------------------------------------------------===//
// Computation
//===----------------------------------------------------------------------===//
@@ -477,6 +522,22 @@
let assemblyFormat = [{
$left `,` $right `:` type($left) `,` type($right) attr-dict
}];
+ let hasCanonicalizeMethod = 1;
+}
+
+def IREEPyDM_PromoteNumericOp : IREEPyDM_PureOp<"promote_numeric"> {
+ let summary = "Promotes one numeric type to another higher on the hierarchy";
+ let description = [{
+ Given a numeric value of lower promotion order, promotes it to a higher
+ order.
+ }];
+ let arguments = (ins IREEPyDM_AnyNumericType:$input);
+ let results = (outs IREEPyDM_AnyNumericType);
+ let assemblyFormat = [{
+ $input `:` type(operands) `->` type(results) attr-dict
+ }];
+ let hasFolder = 1;
+ let hasCanonicalizeMethod = 1;
}
def IREEPyDM_ApplyBinaryOp : IREEPyDM_PureOp<"apply_binary"> {
diff --git a/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp b/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
index 650a2c3..56b053a 100644
--- a/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
+++ b/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
@@ -7,7 +7,7 @@
#include "iree-dialects-c/Dialects.h"
#include "iree-dialects/Dialect/IREE/IREEDialect.h"
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h"
#include "mlir/CAPI/Registration.h"
//===----------------------------------------------------------------------===//
@@ -39,6 +39,7 @@
IREEPYDM_DEFINE_NULLARY_TYPE(Bytes)
IREEPYDM_DEFINE_NULLARY_TYPE(Integer)
IREEPYDM_DEFINE_NULLARY_TYPE(ExceptionResult)
+IREEPYDM_DEFINE_NULLARY_TYPE(FreeVarRef)
IREEPYDM_DEFINE_NULLARY_TYPE(List)
IREEPYDM_DEFINE_NULLARY_TYPE(None)
IREEPYDM_DEFINE_NULLARY_TYPE(Real)
@@ -51,6 +52,10 @@
}
MlirType mlirIREEPyDMObjectTypeGet(MlirContext ctx, MlirType primitive) {
+ if (!primitive.ptr) {
+ return wrap(mlir::iree_pydm::ObjectType::get(unwrap(ctx), nullptr));
+ }
+
auto cppType = unwrap(primitive).cast<mlir::iree_pydm::PrimitiveType>();
return wrap(mlir::iree_pydm::ObjectType::get(unwrap(ctx), cppType));
}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/CMakeLists.txt b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/CMakeLists.txt
index cb991b8..b6293fe 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/CMakeLists.txt
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/CMakeLists.txt
@@ -1,6 +1,6 @@
add_mlir_library(IREEDialectsIREEPyDMDialect
- IREEPyDMDialect.cpp
- IREEPyDMOps.cpp
+ Dialect.cpp
+ Ops.cpp
ADDITIONAL_HEADER_DIRS
${IREE_DIALECTS_SOURCE_DIR}/include
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Dialect.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Dialect.cpp
new file mode 100644
index 0000000..4b6870d
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Dialect.cpp
@@ -0,0 +1,200 @@
+// Copyright 2021 The IREE Authors
+//
+// Licensed 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 "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h"
+
+#include "iree-dialects/Dialect/IREEPyDM/IR/Interfaces.h"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Ops.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "mlir/Support/LLVM.h"
+
+using namespace mlir;
+using namespace mlir::iree_pydm;
+
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.cpp.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "iree-dialects/Dialect/IREEPyDM/IR/TypeInterfaces.cpp.inc"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Types.cpp.inc"
+
+//------------------------------------------------------------------------------
+// Dialect implementation
+//------------------------------------------------------------------------------
+
+using BuiltinIntegerType = mlir::IntegerType;
+
+using PyBoolType = mlir::iree_pydm::BoolType;
+using PyConstantOp = mlir::iree_pydm::ConstantOp;
+using PyIntegerType = mlir::iree_pydm::IntegerType;
+using PyRealType = mlir::iree_pydm::RealType;
+
+void IREEPyDMDialect::initialize() {
+ addTypes<
+#define GET_TYPEDEF_LIST
+#include "iree-dialects/Dialect/IREEPyDM/IR/Types.cpp.inc"
+ >();
+ addOperations<
+#define GET_OP_LIST
+#include "iree-dialects/Dialect/IREEPyDM/IR/Ops.cpp.inc"
+ >();
+}
+
+Operation *IREEPyDMDialect::materializeConstant(OpBuilder &builder,
+ Attribute value, Type type,
+ Location loc) {
+ // Since we support materialization of builtin types too, explicitly
+ // allow these.
+ if (type.isa<PyBoolType, BytesType, PyIntegerType, PyRealType, StrType,
+ BuiltinIntegerType>()) {
+ return builder.create<iree_pydm::ConstantOp>(loc, type, value);
+ }
+
+ if (type.isa<NoneType>()) {
+ return builder.create<iree_pydm::NoneOp>(loc, type);
+ }
+
+ if (type.isa<ExceptionResultType>() && value.isa<UnitAttr>()) {
+ return builder.create<iree_pydm::SuccessOp>(loc, type);
+ }
+
+ llvm_unreachable("unhandled iree_pydm constant materialization");
+}
+
+Type IREEPyDMDialect::parseType(DialectAsmParser &parser) const {
+ StringRef typeTag;
+ if (succeeded(parser.parseKeyword(&typeTag))) {
+ Type genType;
+ auto parseResult =
+ generatedTypeParser(getContext(), parser, typeTag, genType);
+ if (parseResult.hasValue()) {
+ if (*parseResult) {
+ return Type();
+ }
+ return genType;
+ }
+ }
+
+ parser.emitError(parser.getNameLoc(), "unknown dialect type");
+ return Type();
+}
+
+void IREEPyDMDialect::printType(Type type, DialectAsmPrinter &printer) const {
+ (void)generatedTypePrinter(type, printer);
+}
+
+//------------------------------------------------------------------------------
+// Python type implementation
+//------------------------------------------------------------------------------
+
+BuiltinTypeCode iree_pydm::BoolType::getTypeCode() const {
+ return BuiltinTypeCode::Bool;
+}
+
+StringRef iree_pydm::BoolType::getPythonTypeName() const { return "bool"; }
+
+Optional<int> iree_pydm::BoolType::getNumericPromotionOrder() const {
+ return 1;
+}
+
+BuiltinTypeCode iree_pydm::BytesType::getTypeCode() const {
+ return BuiltinTypeCode::Bytes;
+}
+
+StringRef iree_pydm::BytesType::getPythonTypeName() const { return "bytes"; }
+
+BuiltinTypeCode iree_pydm::ExceptionResultType::getTypeCode() const {
+ return BuiltinTypeCode::ExceptionResult;
+}
+
+StringRef iree_pydm::ExceptionResultType::getPythonTypeName() const {
+ return "Exception";
+}
+
+BuiltinTypeCode iree_pydm::IntegerType::getTypeCode() const {
+ return BuiltinTypeCode::Integer;
+}
+
+StringRef iree_pydm::IntegerType::getPythonTypeName() const { return "int"; }
+
+Optional<int> iree_pydm::IntegerType::getNumericPromotionOrder() const {
+ return 2;
+}
+
+BuiltinTypeCode iree_pydm::ListType::getTypeCode() const {
+ return BuiltinTypeCode::List;
+}
+
+StringRef iree_pydm::ListType::getPythonTypeName() const { return "list"; }
+
+BuiltinTypeCode iree_pydm::NoneType::getTypeCode() const {
+ return BuiltinTypeCode::None;
+}
+
+StringRef iree_pydm::NoneType::getPythonTypeName() const { return "None"; }
+
+BuiltinTypeCode iree_pydm::ObjectType::getTypeCode() const {
+ return BuiltinTypeCode::Object;
+}
+
+StringRef iree_pydm::ObjectType::getPythonTypeName() const { return "object"; }
+
+BuiltinTypeCode iree_pydm::RealType::getTypeCode() const {
+ return BuiltinTypeCode::Real;
+}
+
+StringRef iree_pydm::RealType::getPythonTypeName() const { return "float"; }
+
+Optional<int> iree_pydm::RealType::getNumericPromotionOrder() const {
+ return 3;
+}
+
+BuiltinTypeCode iree_pydm::StrType::getTypeCode() const {
+ return BuiltinTypeCode::Str;
+}
+
+StringRef iree_pydm::StrType::getPythonTypeName() const { return "str"; }
+
+BuiltinTypeCode iree_pydm::TupleType::getTypeCode() const {
+ return BuiltinTypeCode::Tuple;
+}
+
+StringRef iree_pydm::TupleType::getPythonTypeName() const { return "tuple"; }
+
+BuiltinTypeCode iree_pydm::TypeType::getTypeCode() const {
+ return BuiltinTypeCode::Type;
+}
+
+StringRef iree_pydm::TypeType::getPythonTypeName() const { return "type"; }
+
+//------------------------------------------------------------------------------
+// Union type implementation
+//------------------------------------------------------------------------------
+
+LogicalResult iree_pydm::UnionType::verify(
+ llvm::function_ref<InFlightDiagnostic()> emitError,
+ ArrayRef<Type> alternatives) {
+ int lastTypeCode = 0;
+ for (Type alternative : alternatives) {
+ if (auto pythonType =
+ alternative.dyn_cast<iree_pydm::PythonTypeInterface>()) {
+ int thisTypeCode = static_cast<int>(pythonType.getTypeCode());
+ // TODO: This doesn't account for parameterized types.
+ if (thisTypeCode <= lastTypeCode) {
+ return emitError() << "expected total order of union to be normative. "
+ "got out of order: "
+ << alternative;
+ }
+ } else {
+ return emitError() << "expected a python type in union. got: "
+ << alternative;
+ }
+ }
+
+ return failure();
+}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMDialect.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMDialect.cpp
deleted file mode 100644
index 50043ae..0000000
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMDialect.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2021 The IREE Authors
-//
-// Licensed 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 "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h"
-
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h"
-#include "llvm/ADT/TypeSwitch.h"
-#include "mlir/IR/DialectImplementation.h"
-#include "mlir/Support/LLVM.h"
-
-using namespace mlir;
-using namespace mlir::iree_pydm;
-
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsDialect.cpp.inc"
-
-#define GET_TYPEDEF_CLASSES
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsTypes.cpp.inc"
-
-void IREEPyDMDialect::initialize() {
- addTypes<
-#define GET_TYPEDEF_LIST
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOpsTypes.cpp.inc"
- >();
- addOperations<
-#define GET_OP_LIST
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp.inc"
- >();
-}
-
-Type IREEPyDMDialect::parseType(DialectAsmParser &parser) const {
- StringRef typeTag;
- Type genType;
- if (succeeded(parser.parseKeyword(&typeTag)))
- generatedTypeParser(getContext(), parser, typeTag, genType);
- return genType;
-}
-
-void IREEPyDMDialect::printType(Type type, DialectAsmPrinter &printer) const {
- (void)generatedTypePrinter(type, printer);
-}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp
deleted file mode 100644
index 1bb1fa4..0000000
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2021 The IREE Authors
-//
-// Licensed 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 "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.h"
-
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/FunctionImplementation.h"
-#include "mlir/IR/OpImplementation.h"
-#include "mlir/IR/TypeUtilities.h"
-
-using namespace mlir;
-using namespace mlir::iree_pydm;
-
-using PyCallOp = mlir::iree_pydm::CallOp;
-using PyFuncOp = mlir::iree_pydm::FuncOp;
-
-//===----------------------------------------------------------------------===//
-// FuncOp
-//===----------------------------------------------------------------------===//
-
-LogicalResult PyFuncOp::verifyType() {
- // TODO: Enforce arg/result invariants.
- return success();
-}
-
-static ParseResult parseFuncOp(OpAsmParser &parser, OperationState &result) {
- auto buildFuncType = [](Builder &builder, ArrayRef<Type> argTypes,
- ArrayRef<Type> results,
- function_like_impl::VariadicFlag, std::string &) {
- return builder.getFunctionType(argTypes, results);
- };
-
- return function_like_impl::parseFunctionLikeOp(
- parser, result, /*allowVariadic=*/false, buildFuncType);
-}
-
-static void print(PyFuncOp op, OpAsmPrinter &p) {
- FunctionType fnType = op.getType();
- function_like_impl::printFunctionLikeOp(
- p, op, fnType.getInputs(), /*isVariadic=*/false, fnType.getResults());
-}
-
-static LogicalResult verify(PyFuncOp op) {
- // TODO: Enforce invariants.
- return success();
-}
-
-//===----------------------------------------------------------------------===//
-// PatternMatchCallOp
-//===----------------------------------------------------------------------===//
-
-LogicalResult PatternMatchCallOp::verifySymbolUses(
- SymbolTableCollection &symbolTable) {
- auto verifySymbols = [&](ArrayAttr symbols) -> LogicalResult {
- for (auto symbolAttr : symbols) {
- auto symbol = symbolAttr.cast<FlatSymbolRefAttr>();
- PyFuncOp fn =
- symbolTable.lookupNearestSymbolFrom<PyFuncOp>(*this, symbol);
- if (!fn)
- return emitOpError() << "'" << symbol.getValue()
- << "' does not reference a valid function";
- }
- return success();
- };
- auto genericsAttr = (*this)->getAttrOfType<ArrayAttr>("generic_match");
- if (!genericsAttr)
- return emitOpError(
- "requires a 'generic_match' array of symbol reference attributes");
- if (failed(verifySymbols(genericsAttr))) return failure();
-
- auto specificsAttr = (*this)->getAttrOfType<ArrayAttr>("specific_match");
- if (!specificsAttr)
- return emitOpError(
- "requires a 'specific_match' array of symbol reference attributes");
- if (failed(verifySymbols(specificsAttr))) return failure();
-
- return success();
-}
-
-//===----------------------------------------------------------------------===//
-// CallOp
-//===----------------------------------------------------------------------===//
-
-LogicalResult PyCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
- // Check that the callee attribute was specified.
- auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
- if (!fnAttr)
- return emitOpError("requires a 'callee' symbol reference attribute");
- PyFuncOp fn = symbolTable.lookupNearestSymbolFrom<PyFuncOp>(*this, fnAttr);
- if (!fn)
- return emitOpError() << "'" << fnAttr.getValue()
- << "' does not reference a valid function";
-
- // Verify that the operand and result types match the callee.
- auto fnType = fn.getType();
- if (fnType.getNumInputs() != getNumOperands())
- return emitOpError("incorrect number of operands for callee");
-
- for (unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i) {
- if (getOperand(i).getType() != fnType.getInput(i)) {
- return emitOpError("operand type mismatch: expected operand type ")
- << fnType.getInput(i) << ", but provided "
- << getOperand(i).getType() << " for operand number " << i;
- }
- }
-
- if (fnType.getNumResults() != getNumResults())
- return emitOpError("incorrect number of results for callee");
-
- for (unsigned i = 0, e = fnType.getNumResults(); i != e; ++i) {
- if (getResult(i).getType() != fnType.getResult(i)) {
- auto diag = emitOpError("result type mismatch at index ") << i;
- diag.attachNote() << " op result types: " << getResultTypes();
- diag.attachNote() << "function result types: " << fnType.getResults();
- return diag;
- }
- }
-
- return success();
-}
-
-FunctionType PyCallOp::getCalleeType() {
- return FunctionType::get(getContext(), getOperandTypes(), getResultTypes());
-}
-
-//===----------------------------------------------------------------------===//
-// DynamicCallOp
-//===----------------------------------------------------------------------===//
-
-LogicalResult DynamicCallOp::verifySymbolUses(
- SymbolTableCollection &symbolTable) {
- // Check that the callee attribute was specified.
- auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
- if (!fnAttr)
- return emitOpError("requires a 'callee' symbol reference attribute");
- Operation *fn = symbolTable.lookupNearestSymbolFrom(*this, fnAttr);
- if (!fn || !isa<PyFuncOp>(fn))
- return emitOpError() << "'" << fnAttr.getValue()
- << "' does not reference a valid function";
- return success();
-}
-
-#define GET_OP_CLASSES
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.cpp.inc"
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Ops.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Ops.cpp
new file mode 100644
index 0000000..245e6be
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/IR/Ops.cpp
@@ -0,0 +1,525 @@
+// Copyright 2021 The IREE Authors
+//
+// Licensed 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 "iree-dialects/Dialect/IREEPyDM/IR/Ops.h"
+
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/FunctionImplementation.h"
+#include "mlir/IR/OpImplementation.h"
+#include "mlir/IR/TypeUtilities.h"
+
+using namespace mlir;
+using namespace mlir::iree_pydm;
+
+using PyBoolType = mlir::iree_pydm::BoolType;
+using PyConstantOp = mlir::iree_pydm::ConstantOp;
+using PyIntegerType = mlir::iree_pydm::IntegerType;
+using PyRealType = mlir::iree_pydm::RealType;
+using PyCallOp = mlir::iree_pydm::CallOp;
+using PyFuncOp = mlir::iree_pydm::FuncOp;
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+static Value getNumericZeroConstant(Location loc, Type numericType,
+ OpBuilder &builder) {
+ return TypeSwitch<Type, Value>(numericType)
+ .Case([&](PyBoolType t) -> Value {
+ return builder.create<PyConstantOp>(loc, t, builder.getBoolAttr(false));
+ })
+ .Case([&](PyIntegerType t) -> Value {
+ return builder.create<PyConstantOp>(loc, t,
+ builder.getI64IntegerAttr(0));
+ })
+ .Case([&](PyRealType t) -> Value {
+ return builder.create<PyConstantOp>(loc, t,
+ builder.getF64FloatAttr(0.0));
+ });
+}
+
+static Value getBoolConstant(Location loc, bool pred, OpBuilder &builder) {
+ return builder.create<PyConstantOp>(loc, builder.getType<BoolType>(),
+ builder.getBoolAttr(pred));
+}
+
+//===----------------------------------------------------------------------===//
+// Constants
+//===----------------------------------------------------------------------===//
+
+OpFoldResult PyConstantOp::fold(ArrayRef<Attribute> operands) {
+ assert(operands.empty() && "constant has no operands");
+ return getValue();
+}
+
+OpFoldResult NoneOp::fold(ArrayRef<Attribute> operands) {
+ assert(operands.empty() && "constant has no operands");
+ return UnitAttr::get(getContext());
+}
+
+OpFoldResult SuccessOp::fold(ArrayRef<Attribute> operands) {
+ assert(operands.empty() && "constant has no operands");
+ return UnitAttr::get(getContext());
+}
+
+//===----------------------------------------------------------------------===//
+// Variables
+//===----------------------------------------------------------------------===//
+
+void AllocFreeVarOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
+ setNameFn(getResult(), name());
+}
+
+//===----------------------------------------------------------------------===//
+// AsBoolOp
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct FoldAsBoolFromBool : public OpRewritePattern<AsBoolOp> {
+ public:
+ using OpRewritePattern::OpRewritePattern;
+ LogicalResult matchAndRewrite(AsBoolOp op,
+ PatternRewriter &rewriter) const override {
+ if (op.value().getType().isa<BoolType>()) {
+ rewriter.replaceOp(op, op.value());
+ return success();
+ }
+ return failure();
+ }
+};
+
+struct FoldAsBoolFromNumeric : public OpRewritePattern<AsBoolOp> {
+ public:
+ using OpRewritePattern::OpRewritePattern;
+ LogicalResult matchAndRewrite(AsBoolOp op,
+ PatternRewriter &rewriter) const override {
+ auto loc = op.getLoc();
+ auto ptType = op.value().getType().dyn_cast<PythonTypeInterface>();
+ if (!ptType) return failure();
+ if (!ptType.getNumericPromotionOrder()) return failure();
+
+ auto boolType = rewriter.getType<BoolType>();
+ Value zeroValue =
+ getNumericZeroConstant(loc, op.value().getType(), rewriter);
+ Value trueValue = getBoolConstant(loc, true, rewriter);
+ Value falseValue = getBoolConstant(loc, false, rewriter);
+ Value cmpResult = rewriter.create<ApplyCompareOp>(
+ loc, boolType, rewriter.getStringAttr("eq"), op.value(), zeroValue);
+ rewriter.replaceOpWithNewOp<SelectOp>(op, boolType, cmpResult, falseValue,
+ trueValue);
+ return success();
+ }
+};
+
+} // namespace
+
+void AsBoolOp::getCanonicalizationPatterns(RewritePatternSet &patterns,
+ MLIRContext *context) {
+ patterns.add<FoldAsBoolFromBool, FoldAsBoolFromNumeric>(context);
+}
+
+OpFoldResult AsBoolOp::fold(ArrayRef<Attribute> operands) {
+ Builder b(getContext());
+ // Fold NoneType to False.
+ if (value().getType().isa<NoneType>()) {
+ return b.getBoolAttr(false);
+ }
+
+ return {};
+}
+
+//===----------------------------------------------------------------------===//
+// BoolToPredOp
+//===----------------------------------------------------------------------===//
+
+OpFoldResult BoolToPredOp::fold(ArrayRef<Attribute> operands) {
+ if (!operands[0]) return {};
+ // Since both BoolType and I1 share the attribute form (an IntegerAttr of I1),
+ // we can just return it.
+ return operands[0];
+}
+
+//===----------------------------------------------------------------------===//
+// BoxOp and UnboxOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult BoxOp::canonicalize(BoxOp op, PatternRewriter &rewriter) {
+ // Sometimes boxes are emitted when the input is an object. Just remove.
+ if (op.primitive().getType().isa<ObjectType>()) {
+ rewriter.replaceOp(op, op.primitive());
+ return success();
+ }
+
+ return failure();
+}
+
+LogicalResult UnboxOp::canonicalize(UnboxOp unboxOp,
+ PatternRewriter &rewriter) {
+ auto loc = unboxOp.getLoc();
+
+ // Handle the case of an immediate BoxOp producer.
+ if (auto boxProducer =
+ dyn_cast_or_null<BoxOp>(unboxOp.object().getDefiningOp())) {
+ // If the producer is boxing to the same type we are unboxing, then
+ // just elide everything.
+ if (boxProducer.primitive().getType() == unboxOp.primitive().getType()) {
+ auto successValue = rewriter.create<SuccessOp>(
+ loc, rewriter.getType<ExceptionResultType>());
+ rewriter.replaceOp(unboxOp, {successValue, boxProducer.primitive()});
+ return success();
+ }
+ }
+ return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// DynamicBinaryPromoteOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult DynamicBinaryPromoteOp::canonicalize(DynamicBinaryPromoteOp op,
+ PatternRewriter &rewriter) {
+ auto loc = op.getLoc();
+ auto leftType = op.left().getType();
+ auto rightType = op.right().getType();
+ auto leftResultType = op.getResultTypes()[0];
+ auto rightResultType = op.getResultTypes()[1];
+ auto leftPt = leftType.dyn_cast<PythonTypeInterface>();
+ auto rightPt = rightType.dyn_cast<PythonTypeInterface>();
+ if (!leftPt || !rightPt) return failure();
+
+ Optional<int> leftOrder = leftPt.getNumericPromotionOrder();
+ Optional<int> rightOrder = rightPt.getNumericPromotionOrder();
+ Value newLeft = op.left();
+ Value newRight = op.right();
+
+ // Simple case: same types pass through.
+ if (leftType == rightType) {
+ // Nothing - pass-through rewrite.
+ } else if (leftOrder && rightOrder) {
+ // Both numeric.
+ if (*leftOrder > *rightOrder) {
+ newRight = rewriter.create<PromoteNumericOp>(loc, leftType, newRight);
+ }
+ if (*rightOrder > *leftOrder) {
+ newLeft = rewriter.create<PromoteNumericOp>(loc, rightType, newLeft);
+ }
+ } else {
+ return failure();
+ }
+
+ // Need to box back to the original type (which will always be a generic
+ // object).
+ newLeft = rewriter.create<BoxOp>(loc, leftResultType, newLeft);
+ newRight = rewriter.create<BoxOp>(loc, rightResultType, newRight);
+
+ rewriter.replaceOp(op, {newLeft, newRight});
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionalIfOp
+//===----------------------------------------------------------------------===//
+
+::llvm::StringRef FunctionalIfOp::getDefaultDialect() { return "iree_pydm"; }
+
+static LogicalResult verify(FunctionalIfOp op) {
+ if (op.getNumResults() != 0 && op.elseRegion().empty())
+ return op.emitOpError("must have an else block if defining values");
+
+ return RegionBranchOpInterface::verifyTypes(op);
+}
+
+static ParseResult parseFunctionalIfOp(OpAsmParser &parser,
+ OperationState &result) {
+ // Create the regions for 'then'.
+ result.regions.reserve(2);
+ Region *thenRegion = result.addRegion();
+ Region *elseRegion = result.addRegion();
+
+ auto &builder = parser.getBuilder();
+ OpAsmParser::OperandType cond;
+ Type conditionType = builder.getType<PyBoolType>();
+ if (parser.parseOperand(cond) ||
+ parser.resolveOperand(cond, conditionType, result.operands))
+ return failure();
+ // Parse optional results type list.
+ if (parser.parseOptionalArrowTypeList(result.types)) return failure();
+ // Parse the 'then' region.
+ if (parser.parseRegion(*thenRegion, /*arguments=*/{}, /*argTypes=*/{}))
+ return failure();
+ // IfOp::ensureTerminator(*thenRegion, parser.getBuilder(), result.location);
+
+ // If we find an 'else' keyword then parse the 'else' region.
+ if (!parser.parseOptionalKeyword("else")) {
+ if (parser.parseRegion(*elseRegion, /*arguments=*/{}, /*argTypes=*/{}))
+ return failure();
+ // IfOp::ensureTerminator(*elseRegion, parser.getBuilder(),
+ // result.location);
+ }
+
+ // Parse the optional attribute list.
+ if (parser.parseOptionalAttrDict(result.attributes)) return failure();
+ return success();
+}
+
+static void print(OpAsmPrinter &p, FunctionalIfOp op) {
+ bool printBlockTerminators = false;
+
+ p << " " << op.condition();
+ if (!op.results().empty()) {
+ p << " -> (" << op.getResultTypes() << ")";
+ // Print yield explicitly if the op defines values.
+ printBlockTerminators = true;
+ }
+ p.printRegion(op.thenRegion(),
+ /*printEntryBlockArgs=*/false,
+ /*printBlockTerminators=*/printBlockTerminators);
+
+ // Print the 'else' regions if it exists and has a block.
+ auto &elseRegion = op.elseRegion();
+ if (!elseRegion.empty()) {
+ p << " else";
+ p.printRegion(elseRegion,
+ /*printEntryBlockArgs=*/false,
+ /*printBlockTerminators=*/printBlockTerminators);
+ }
+
+ p.printOptionalAttrDict(op->getAttrs());
+}
+
+/// Given the region at `index`, or the parent operation if `index` is None,
+/// return the successor regions. These are the regions that may be selected
+/// during the flow of control. `operands` is a set of optional attributes that
+/// correspond to a constant value for each operand, or null if that operand is
+/// not a constant.
+void FunctionalIfOp::getSuccessorRegions(
+ Optional<unsigned> index, ArrayRef<Attribute> operands,
+ SmallVectorImpl<RegionSuccessor> ®ions) {
+ // The `then` and the `else` region branch back to the parent operation.
+ if (index.hasValue()) {
+ regions.push_back(RegionSuccessor(getResults()));
+ return;
+ }
+
+ // Don't consider the else region if it is empty.
+ Region *elseRegion = &this->elseRegion();
+ if (elseRegion->empty()) elseRegion = nullptr;
+
+ // Otherwise, the successor is dependent on the condition.
+ if (auto condAttr = operands.front().dyn_cast_or_null<BoolAttr>()) {
+ bool condition = condAttr.getValue();
+ // Add the successor regions using the condition.
+ regions.push_back(RegionSuccessor(condition ? &thenRegion() : elseRegion));
+ } else {
+ // If the condition isn't constant, both regions may be executed.
+ regions.push_back(RegionSuccessor(&thenRegion()));
+ // If the else region does not exist, it is not a viable successor.
+ if (elseRegion) regions.push_back(RegionSuccessor(elseRegion));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// FuncOp
+//===----------------------------------------------------------------------===//
+
+::llvm::StringRef PyFuncOp::getDefaultDialect() { return "iree_pydm"; }
+
+LogicalResult PyFuncOp::verifyType() {
+ // TODO: Enforce arg/result invariants.
+ return success();
+}
+
+static ParseResult parseFuncOp(OpAsmParser &parser, OperationState &result) {
+ auto buildFuncType = [](Builder &builder, ArrayRef<Type> argTypes,
+ ArrayRef<Type> results,
+ function_like_impl::VariadicFlag, std::string &) {
+ return builder.getFunctionType(argTypes, results);
+ };
+
+ return function_like_impl::parseFunctionLikeOp(
+ parser, result, /*allowVariadic=*/false, buildFuncType);
+}
+
+static void print(PyFuncOp op, OpAsmPrinter &p) {
+ FunctionType fnType = op.getType();
+ function_like_impl::printFunctionLikeOp(
+ p, op, fnType.getInputs(), /*isVariadic=*/false, fnType.getResults());
+}
+
+static LogicalResult verify(PyFuncOp op) {
+ // TODO: Enforce invariants.
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// PatternMatchCallOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult PatternMatchCallOp::verifySymbolUses(
+ SymbolTableCollection &symbolTable) {
+ auto verifySymbols = [&](ArrayAttr symbols) -> LogicalResult {
+ for (auto symbolAttr : symbols) {
+ auto symbol = symbolAttr.cast<FlatSymbolRefAttr>();
+ PyFuncOp fn =
+ symbolTable.lookupNearestSymbolFrom<PyFuncOp>(*this, symbol);
+ if (!fn)
+ return emitOpError() << "'" << symbol.getValue()
+ << "' does not reference a valid function";
+ }
+ return success();
+ };
+ auto genericsAttr = (*this)->getAttrOfType<ArrayAttr>("generic_match");
+ if (!genericsAttr)
+ return emitOpError(
+ "requires a 'generic_match' array of symbol reference attributes");
+ if (failed(verifySymbols(genericsAttr))) return failure();
+
+ auto specificsAttr = (*this)->getAttrOfType<ArrayAttr>("specific_match");
+ if (!specificsAttr)
+ return emitOpError(
+ "requires a 'specific_match' array of symbol reference attributes");
+ if (failed(verifySymbols(specificsAttr))) return failure();
+
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// PromoteNumericOp
+//===----------------------------------------------------------------------===//
+
+OpFoldResult PromoteNumericOp::fold(ArrayRef<Attribute> operands) {
+ if (!operands[0]) return {};
+
+ Builder b(getContext());
+ Attribute fromAttr = operands[0];
+ return TypeSwitch<Type, OpFoldResult>(getResult().getType())
+ .Case([&](PyIntegerType toType) -> OpFoldResult {
+ return TypeSwitch<Attribute, OpFoldResult>(fromAttr)
+ .Case([&](BoolAttr fromBool) -> OpFoldResult {
+ return b.getI64IntegerAttr(fromBool.getValue() ? 1 : 0);
+ })
+ .Default([](Attribute) -> OpFoldResult { return {}; });
+ })
+ .Case([&](PyRealType toType) -> OpFoldResult {
+ return TypeSwitch<Attribute, OpFoldResult>(fromAttr)
+ .Case([&](BoolAttr fromBool) -> OpFoldResult {
+ return b.getF64FloatAttr(fromBool.getValue() ? 1.0 : 0.0);
+ })
+ .Case([&](IntegerAttr fromInteger) -> OpFoldResult {
+ APInt value = fromInteger.getValue();
+ return b.getF64FloatAttr(value.getSExtValue());
+ })
+ .Default([](Attribute) -> OpFoldResult { return {}; });
+ })
+ .Default([](Type) -> OpFoldResult { return {}; });
+}
+
+LogicalResult PromoteNumericOp::canonicalize(PromoteNumericOp op,
+ PatternRewriter &rewriter) {
+ if (op.input().getType() == op.getResult().getType()) {
+ rewriter.replaceOp(op, op.input());
+ return success();
+ }
+ return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// RaiseOnFailureOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult iree_pydm::RaiseOnFailureOp::fold(
+ ArrayRef<Attribute> operands, SmallVectorImpl<OpFoldResult> &results) {
+ assert(operands.size() == 1 && "expected one fold operand");
+ // Unit exception result is success. Just elide.
+ if (operands[0] && operands[0].isa<UnitAttr>()) {
+ erase();
+ return success();
+ }
+ return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// SelectOp
+//===----------------------------------------------------------------------===//
+
+OpFoldResult SelectOp::fold(ArrayRef<Attribute> operands) {
+ if (!operands[0]) return {};
+
+ BoolAttr boolAttr = operands[0].cast<BoolAttr>();
+ if (boolAttr.getValue())
+ return true_value();
+ else
+ return false_value();
+}
+
+//===----------------------------------------------------------------------===//
+// CallOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult PyCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
+ // Check that the callee attribute was specified.
+ auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
+ if (!fnAttr)
+ return emitOpError("requires a 'callee' symbol reference attribute");
+ PyFuncOp fn = symbolTable.lookupNearestSymbolFrom<PyFuncOp>(*this, fnAttr);
+ if (!fn)
+ return emitOpError() << "'" << fnAttr.getValue()
+ << "' does not reference a valid function";
+
+ // Verify that the operand and result types match the callee.
+ auto fnType = fn.getType();
+ if (fnType.getNumInputs() != getNumOperands())
+ return emitOpError("incorrect number of operands for callee");
+
+ for (unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i) {
+ if (getOperand(i).getType() != fnType.getInput(i)) {
+ return emitOpError("operand type mismatch: expected operand type ")
+ << fnType.getInput(i) << ", but provided "
+ << getOperand(i).getType() << " for operand number " << i;
+ }
+ }
+
+ if (fnType.getNumResults() != getNumResults())
+ return emitOpError("incorrect number of results for callee");
+
+ for (unsigned i = 0, e = fnType.getNumResults(); i != e; ++i) {
+ if (getResult(i).getType() != fnType.getResult(i)) {
+ auto diag = emitOpError("result type mismatch at index ") << i;
+ diag.attachNote() << " op result types: " << getResultTypes();
+ diag.attachNote() << "function result types: " << fnType.getResults();
+ return diag;
+ }
+ }
+
+ return success();
+}
+
+FunctionType PyCallOp::getCalleeType() {
+ return FunctionType::get(getContext(), getOperandTypes(), getResultTypes());
+}
+
+//===----------------------------------------------------------------------===//
+// DynamicCallOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult DynamicCallOp::verifySymbolUses(
+ SymbolTableCollection &symbolTable) {
+ // Check that the callee attribute was specified.
+ auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
+ if (!fnAttr)
+ return emitOpError("requires a 'callee' symbol reference attribute");
+ Operation *fn = symbolTable.lookupNearestSymbolFrom(*this, fnAttr);
+ if (!fn || !isa<PyFuncOp>(fn))
+ return emitOpError() << "'" << fnAttr.getValue()
+ << "' does not reference a valid function";
+ return success();
+}
+
+#define GET_OP_CLASSES
+#include "iree-dialects/Dialect/IREEPyDM/IR/Ops.cpp.inc"
diff --git a/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp b/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
index 8bf5864..00d280a 100644
--- a/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
+++ b/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
@@ -87,6 +87,7 @@
DEFINE_IREEPYDM_NULLARY_TYPE(Bool)
DEFINE_IREEPYDM_NULLARY_TYPE(Bytes)
DEFINE_IREEPYDM_NULLARY_TYPE(ExceptionResult)
+ DEFINE_IREEPYDM_NULLARY_TYPE(FreeVarRef)
DEFINE_IREEPYDM_NULLARY_TYPE(Integer)
DEFINE_IREEPYDM_NULLARY_TYPE(List)
DEFINE_IREEPYDM_NULLARY_TYPE(None)
diff --git a/llvm-external-projects/iree-dialects/python/mlir/dialects/IreePyDmBinding.td b/llvm-external-projects/iree-dialects/python/mlir/dialects/IreePyDmBinding.td
index 900c7d1..ff6371f 100644
--- a/llvm-external-projects/iree-dialects/python/mlir/dialects/IreePyDmBinding.td
+++ b/llvm-external-projects/iree-dialects/python/mlir/dialects/IreePyDmBinding.td
@@ -8,6 +8,6 @@
#define PYTHON_BINDINGS_IREE_PYDM_OPS
include "mlir/Bindings/Python/Attributes.td"
-include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMOps.td"
+include "iree-dialects/Dialect/IREEPyDM/IR/Ops.td"
#endif // PYTHON_BINDINGS_IREE_PYDM_OPS
diff --git a/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/importer.py b/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/importer.py
index 9cae4d6..a52edbb 100644
--- a/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/importer.py
+++ b/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/importer.py
@@ -4,7 +4,7 @@
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-from typing import Optional, Sequence, Tuple, List, Union
+from typing import Dict, Optional, Sequence, Set, Tuple, List, Union
import ast
import inspect
@@ -99,6 +99,7 @@
host_closure_vars=inspect.getclosurevars(f))
body_importer = FunctionDefBodyImporter(fctx)
with ic.scoped_ip(ir.InsertionPoint(entry_block)):
+ body_importer.declare_variables()
body_importer.import_body(fd_node)
return f_op
@@ -118,6 +119,7 @@
"free_vars",
"cell_vars",
"host_closure_vars",
+ "variable_value_map",
]
def __init__(self,
@@ -134,13 +136,32 @@
# Keep sets of free and cell var names so that we know what kinds of
# loads to issue.
- self.arg_names = set(
+ self.arg_names: Set[str] = set(
[ir.StringAttr(attr).value for attr in self.f_op.arg_names])
- self.free_vars = set(
+ self.free_vars: Set[str] = set(
[ir.StringAttr(attr).value for attr in self.f_op.free_vars])
- self.cell_vars = set(
+ self.cell_vars: Set[str] = set(
[ir.StringAttr(attr).value for attr in self.f_op.cell_vars])
+ self.variable_value_map: Dict[str, ir.Value] = {}
+
+ def declare_free_var(self, name: str):
+ """Declares a free-variable SSA value for the given name."""
+ ic = self.ic
+ if name in self.variable_value_map:
+ ic.abort(f"attempt to duplicate declare variable {name}")
+ with ic.ip, ic.loc:
+ t = d.FreeVarRefType.get()
+ self.variable_value_map[name] = (d.AllocFreeVarOp(t,
+ ir.StringAttr.get(name),
+ index=None).result)
+
+ def find_variable(self, name: str) -> ir.Value:
+ try:
+ return self.variable_value_map[name]
+ except KeyError:
+ self.ic.abort(f"attempt to reference variable not declared: {name}")
+
def update_loc(self, ast_node):
self.ic.set_file_line_col(self.filename, ast_node.lineno,
ast_node.col_offset)
@@ -204,6 +225,11 @@
self.successor_block = successor_block
self._last_was_return = False
+ def declare_variables(self):
+ fctx = self.fctx
+ for name in fctx.free_vars:
+ fctx.declare_free_var(name)
+
def import_body(self, ast_fd: ast.FunctionDef):
ic = self.fctx.ic
# Function prologue: Initialize arguments.
@@ -237,7 +263,7 @@
arg_value = entry_block.arguments[index]
arg_value = ic.box(arg_value)
with ic.loc, ic.ip:
- d.StoreFreeVarOp(ir.StringAttr.get(name), arg_value)
+ d.StoreVarOp(fctx.find_variable(name), arg_value)
def visit_Pass(self, ast_node):
pass
@@ -268,7 +294,7 @@
boxed = ic.box(expr.get_immediate())
with ic.loc, ic.ip:
target_id = target.id # pytype: disable=attribute-error
- d.StoreFreeVarOp(ir.StringAttr.get(target_id), boxed)
+ d.StoreVarOp(fctx.find_variable(target_id), boxed)
def visit_Expr(self, node: ast.Expr):
fctx = self.fctx
@@ -397,9 +423,9 @@
with ic.loc:
if node.id in self.fctx.free_vars:
self._set_result(
- d.LoadFreeVarOp(d.ObjectType.get(),
- ir.StringAttr.get(node.id),
- ip=ic.ip).result)
+ d.LoadVarOp(d.ObjectType.get(),
+ fctx.find_variable(node.id),
+ ip=ic.ip).result)
return
# Fall-back to global resolution.
@@ -463,24 +489,23 @@
if not next_nodes:
return next_value
- bool_value = d.AsBoolOp(d.BoolType.get(), next_value, ip=ic.ip).result
- condition_value = d.BoolToPredOp(ir.IntegerType.get_signless(1),
- bool_value,
- ip=ic.ip).result
+ condition_value = d.AsBoolOp(d.BoolType.get(), next_value,
+ ip=ic.ip).result
# TODO: See if we can re-organize this to not force boxing through the
# if.
- if_op, then_ip, else_ip = ic.scf_IfOp([d.ObjectType.get()],
- condition_value, True)
+ if_op, then_ip, else_ip = ic.create_functional_if_op([d.ObjectType.get()],
+ condition_value,
+ True)
# Short-circuit return case.
with ic.scoped_ip(then_ip if return_first_true else else_ip):
next_value_casted = ic.box(next_value)
- ic.scf_YieldOp([next_value_casted])
+ d.YieldOp([next_value_casted], loc=ic.loc, ip=ic.ip)
# Nested evaluate next case.
with ic.scoped_ip(else_ip if return_first_true else then_ip):
nested_value = emit_next(next_nodes)
nested_value_casted = next_value_casted = ic.box(nested_value)
- ic.scf_YieldOp([nested_value_casted])
+ d.YieldOp([nested_value_casted], loc=ic.loc, ip=ic.ip)
return if_op.result
@@ -531,18 +556,17 @@
# Emit if for short circuit eval.
# Since this is an 'and', all else clauses yield a false value.
with ic.ip, ic.loc:
- compare_result_i1 = d.BoolToPredOp(ir.IntegerType.get_signless(1),
- compare_result).result
- if_op, then_ip, else_ip = ic.scf_IfOp([d.BoolType.get()],
- compare_result_i1, True)
+ if_op, then_ip, else_ip = ic.create_functional_if_op([d.BoolType.get()],
+ compare_result,
+ True)
# Build the else clause.
with ic.scoped_ip(else_ip):
- ic.scf_YieldOp([false_value])
+ d.YieldOp([false_value], loc=ic.loc, ip=ic.ip)
# Build the then clause.
with ic.scoped_ip(then_ip):
nested_result = emit_next(right_value, comparisons)
- ic.scf_YieldOp([nested_result])
+ d.YieldOp([nested_result], loc=ic.loc, ip=ic.ip)
return if_op.result
@@ -606,30 +630,26 @@
# Interpret as bool.
test_bool = d.AsBoolOp(d.BoolType.get(), test_value, ip=ic.ip,
loc=ic.loc).result
- test_pred = d.BoolToPredOp(ir.IntegerType.get_signless(1),
- test_bool,
- ip=ic.ip,
- loc=ic.loc).result
# TODO: There is a hazard here if then and else refine to different
# boxed types. Needs a derefine cast. Also we are boxing to type erased
# types to satisfy scf.if verifier. Do something better.
- if_op, then_ip, else_ip = ic.scf_IfOp([d.ObjectType.get(ic.context)],
- test_pred, True)
+ if_op, then_ip, else_ip = ic.create_functional_if_op(
+ [d.ObjectType.get(ic.context)], test_bool, True)
# Build the then clause
with ic.scoped_ip(then_ip):
# Evaluate the true clause within the if body.
sub_expression = ExpressionImporter(fctx)
sub_expression.visit(node.body)
then_result = sub_expression.get_immediate()
- ic.scf_YieldOp([ic.box(then_result, to_typed=False)])
+ d.YieldOp([ic.box(then_result, to_typed=False)], loc=ic.loc, ip=ic.ip)
# Build the then clause.
with ic.scoped_ip(else_ip):
sub_expression = ExpressionImporter(fctx)
sub_expression.visit(node.orelse)
orelse_result = sub_expression.get_immediate()
- ic.scf_YieldOp([ic.box(orelse_result, to_typed=False)])
+ d.YieldOp([ic.box(orelse_result, to_typed=False)], loc=ic.loc, ip=ic.ip)
self._set_result(if_op.result)
diff --git a/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/util.py b/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/util.py
index 5fcdc5f..23f7934 100644
--- a/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/util.py
+++ b/llvm-external-projects/iree-dialects/python/mlir/dialects/iree_pydm/importer/util.py
@@ -137,7 +137,7 @@
elif isinstance(value, int):
return d.ConstantOp(
d.IntegerType.get(),
- ir.IntegerAttr.get(ir.IntegerType.get_signed(64), value)).result
+ ir.IntegerAttr.get(ir.IntegerType.get_signless(64), value)).result
elif isinstance(value, float):
return d.ConstantOp(d.RealType.get(),
ir.FloatAttr.get(ir.F64Type.get(), value)).result
@@ -148,13 +148,14 @@
self.abort(
f"unsupported Python constant value '{value}' (an {value.__class__}))")
- # TODO: Map the SCF dialect properly upstream.
- def scf_IfOp(self, results, condition: ir.Value, with_else_region: bool):
- """Creates an SCF if op.
+ def create_functional_if_op(self, results, condition: ir.Value,
+ with_else_region: bool):
+ """Sugar to create a `functional_if`.
Returns:
(if_op, then_ip, else_ip) if with_else_region, otherwise (if_op, then_ip)
"""
- op = ir.Operation.create("scf.if",
+ # TODO: ODS for these style of ops with variable regions needs work.
+ op = ir.Operation.create("iree_pydm.functional_if",
results=results,
operands=[condition],
regions=2 if with_else_region else 1,
@@ -169,12 +170,6 @@
else:
return op, ir.InsertionPoint(then_block)
- def scf_YieldOp(self, operands):
- return ir.Operation.create("scf.yield",
- operands=operands,
- loc=self.loc,
- ip=self.ip)
-
class ImportStage:
"""Base class for activities representing isolated import activity.
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/booleans.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/booleans.mlir
new file mode 100644
index 0000000..921d167
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/booleans.mlir
@@ -0,0 +1,64 @@
+// RUN: iree-dialects-opt -split-input-file --allow-unregistered-dialect -canonicalize %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @fold_none
+iree_pydm.func @fold_none(%arg0 : !iree_pydm.none) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[F:.*]] = constant false -> !iree_pydm.bool
+ // CHECK: return %[[F]]
+ %0 = as_bool %arg0 : !iree_pydm.none -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
+
+// -----
+// CHECK-LABEL: @elide_as_bool_from_bool
+iree_pydm.func @elide_as_bool_from_bool(%arg0 : !iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: return %arg0
+ %0 = as_bool %arg0 : !iree_pydm.bool -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
+
+// -----
+// CHECK-LABEL: @as_bool_from_integer_to_compare
+iree_pydm.func @as_bool_from_integer_to_compare(%arg0 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[Z:.*]] = constant 0 : i64 -> !iree_pydm.integer
+ // CHECK: %[[T:.*]] = constant true -> !iree_pydm.bool
+ // CHECK: %[[F:.*]] = constant false -> !iree_pydm.bool
+ // CHECK: %[[CMP:.*]] = apply_compare "eq", %arg0, %[[Z]]
+ // CHECK: %[[SEL:.*]] = select %[[CMP]], %[[F]], %[[T]] : !iree_pydm.bool
+ // CHECK: return %[[SEL]]
+ %0 = as_bool %arg0 : !iree_pydm.integer -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
+
+// -----
+// CHECK-LABEL: @as_bool_from_real_to_compare
+iree_pydm.func @as_bool_from_real_to_compare(%arg0 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[Z:.*]] = constant 0.000000e+00 : f64 -> !iree_pydm.real
+ // CHECK: %[[T:.*]] = constant true -> !iree_pydm.bool
+ // CHECK: %[[F:.*]] = constant false -> !iree_pydm.bool
+ // CHECK: %[[CMP:.*]] = apply_compare "eq", %arg0, %[[Z]]
+ // CHECK: %[[SEL:.*]] = select %[[CMP]], %[[F]], %[[T]] : !iree_pydm.bool
+ // CHECK: return %[[SEL]]
+ %0 = as_bool %arg0 : !iree_pydm.real -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
+
+// -----
+// CHECK-LABEL: @fold_bool_to_pred_from_constant
+iree_pydm.func @fold_bool_to_pred_from_constant() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ %0 = iree_pydm.constant true -> !iree_pydm.bool
+ // CHECK: %[[P:.*]] = constant true -> i1
+ // CHECK: "custom.donotoptimize"(%[[P]])
+ %1 = bool_to_pred %0
+ "custom.donotoptimize"(%1) : (i1) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @as_bool_from_real_to_compare
+iree_pydm.func @as_bool_from_real_to_compare(%arg0: !iree_pydm.integer, %arg1: !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ // CHECK: return %arg0
+ %0 = constant true -> !iree_pydm.bool
+ %1 = select %0, %arg0, %arg1 : !iree_pydm.integer
+ return %1 : !iree_pydm.integer
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/boxing.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/boxing.mlir
new file mode 100644
index 0000000..7df0433
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/boxing.mlir
@@ -0,0 +1,39 @@
+// RUN: iree-dialects-opt -split-input-file --allow-unregistered-dialect -canonicalize %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @elide_boxing_noop
+iree_pydm.func @elide_boxing_noop(%arg0 : !iree_pydm.object) -> (!iree_pydm.exception_result, !iree_pydm.object) {
+ %0 = box %arg0 : !iree_pydm.object -> !iree_pydm.object
+ // CHECK: return %arg0
+ return %0 : !iree_pydm.object
+}
+
+// -----
+// CHECK-LABEL: @preserves_boxing
+iree_pydm.func @preserves_boxing(%arg0 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.object) {
+ // CHECK: %[[BOXED:.*]] = box %arg0
+ %0 = box %arg0 : !iree_pydm.integer -> !iree_pydm.object
+ // CHECK: return %[[BOXED]]
+ return %0 : !iree_pydm.object
+}
+
+// -----
+// CHECK-LABEL: @elide_unboxing_from_boxed_noop
+iree_pydm.func @elide_unboxing_from_boxed_noop(%arg0 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ // CHECK-NOT: raise_on_failure
+ %0 = box %arg0 : !iree_pydm.integer -> !iree_pydm.object
+ %exc_result, %1 = unbox %0 : !iree_pydm.object -> !iree_pydm.integer
+ raise_on_failure %exc_result : !iree_pydm.exception_result
+ // CHECK: return %arg0
+ return %1 : !iree_pydm.integer
+}
+
+// -----
+// CHECK-LABEL: @preserve_unboxing
+iree_pydm.func @preserve_unboxing(%arg0 : !iree_pydm.object) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ %0 = box %arg0 : !iree_pydm.object -> !iree_pydm.object
+ // CHECK: %[[STATUS:.*]], %[[UNBOXED:.*]] = unbox
+ %exc_result, %1 = unbox %0 : !iree_pydm.object -> !iree_pydm.integer
+ raise_on_failure %exc_result : !iree_pydm.exception_result
+ // CHECK: return %[[UNBOXED]]
+ return %1 : !iree_pydm.integer
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/exceptions.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/exceptions.mlir
new file mode 100644
index 0000000..363af77
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/exceptions.mlir
@@ -0,0 +1,29 @@
+// RUN: iree-dialects-opt -split-input-file --allow-unregistered-dialect -canonicalize %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @elide_raise_on_failure_success
+iree_pydm.func @elide_raise_on_failure_success() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK-NOT: raise_on_failure
+ %0 = success -> !iree_pydm.exception_result
+ raise_on_failure %0 : !iree_pydm.exception_result
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @preserve_raise_on_failure_failure
+iree_pydm.func @preserve_raise_on_failure_failure() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: raise_on_failure
+ %0 = failure -> !iree_pydm.exception_result
+ raise_on_failure %0 : !iree_pydm.exception_result
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @preserve_raise_on_failure_unknown
+iree_pydm.func @preserve_raise_on_failure_unknown(%arg0 : !iree_pydm.exception_result) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: raise_on_failure
+ raise_on_failure %arg0 : !iree_pydm.exception_result
+ %none = none
+ return %none : !iree_pydm.none
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/numerics.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/numerics.mlir
new file mode 100644
index 0000000..e302baa
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/canonicalize/numerics.mlir
@@ -0,0 +1,111 @@
+// RUN: iree-dialects-opt -split-input-file --allow-unregistered-dialect -canonicalize %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @dynamic_binary_promote_same_type
+iree_pydm.func @dynamic_binary_promote_same_type(%arg0 : !iree_pydm.bool, %arg1 : !iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // Note: it is important that types are not modified as part of canonicalization,
+ // since the legality of that requires more analysis. Therefore, this must
+ // produce unrefined objects, like the original.
+ // CHECK: %[[LEFT:.*]] = box %arg0 : !iree_pydm.bool -> !iree_pydm.object
+ // CHECK: %[[RIGHT:.*]] = box %arg1 : !iree_pydm.bool -> !iree_pydm.object
+ // CHECK: "custom.donotoptimize"(%[[LEFT]], %[[RIGHT]])
+ %0, %1 = dynamic_binary_promote %arg0, %arg1 : !iree_pydm.bool, !iree_pydm.bool
+ "custom.donotoptimize"(%0, %1) : (!iree_pydm.object, !iree_pydm.object) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @dynamic_binary_promote_promote_left
+iree_pydm.func @dynamic_binary_promote_promote_left(%arg0 : !iree_pydm.bool, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[LEFT:.*]] = promote_numeric %arg0 : !iree_pydm.bool -> !iree_pydm.integer
+ // CHECK: %[[LEFT_BOXED:.*]] = box %[[LEFT]] : !iree_pydm.integer -> !iree_pydm.object
+ // CHECK: %[[RIGHT_BOXED:.*]] = box %arg1 : !iree_pydm.integer -> !iree_pydm.object
+ // CHECK: "custom.donotoptimize"(%[[LEFT_BOXED]], %[[RIGHT_BOXED]])
+ %0, %1 = dynamic_binary_promote %arg0, %arg1 : !iree_pydm.bool, !iree_pydm.integer
+ "custom.donotoptimize"(%0, %1) : (!iree_pydm.object, !iree_pydm.object) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @dynamic_binary_promote_promote_right
+iree_pydm.func @dynamic_binary_promote_promote_right(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[RIGHT:.*]] = promote_numeric %arg1 : !iree_pydm.integer -> !iree_pydm.real
+ // CHECK: %[[LEFT_BOXED:.*]] = box %arg0 : !iree_pydm.real -> !iree_pydm.object
+ // CHECK: %[[RIGHT_BOXED:.*]] = box %[[RIGHT]] : !iree_pydm.real -> !iree_pydm.object
+ // CHECK: "custom.donotoptimize"(%[[LEFT_BOXED]], %[[RIGHT_BOXED]])
+ %0, %1 = dynamic_binary_promote %arg0, %arg1 : !iree_pydm.real, !iree_pydm.integer
+ "custom.donotoptimize"(%0, %1) : (!iree_pydm.object, !iree_pydm.object) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @elide_promote_numeric_identity
+iree_pydm.func @elide_promote_numeric_identity(%arg0: !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: "custom.donotoptimize"(%arg0)
+ %0 = promote_numeric %arg0 : !iree_pydm.integer -> !iree_pydm.integer
+ "custom.donotoptimize"(%0) : (!iree_pydm.integer) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @fold_promote_numeric_true_to_integer
+iree_pydm.func @fold_promote_numeric_true_to_integer() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST:.*]] = constant 1 : i64 -> !iree_pydm.integer
+ // CHECK: "custom.donotoptimize"(%[[CST]])
+ %0 = constant true -> !iree_pydm.bool
+ %1 = promote_numeric %0 : !iree_pydm.bool -> !iree_pydm.integer
+ "custom.donotoptimize"(%1) : (!iree_pydm.integer) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @fold_promote_numeric_false_to_integer
+iree_pydm.func @fold_promote_numeric_false_to_integer() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST:.*]] = constant 0 : i64 -> !iree_pydm.integer
+ // CHECK: "custom.donotoptimize"(%[[CST]])
+ %0 = constant false -> !iree_pydm.bool
+ %1 = promote_numeric %0 : !iree_pydm.bool -> !iree_pydm.integer
+ "custom.donotoptimize"(%1) : (!iree_pydm.integer) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @fold_promote_numeric_true_to_real
+iree_pydm.func @fold_promote_numeric_true_to_real() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST:.*]] = constant 1.000000e+00 : f64 -> !iree_pydm.real
+ // CHECK: "custom.donotoptimize"(%[[CST]])
+ %0 = constant true -> !iree_pydm.bool
+ %1 = promote_numeric %0 : !iree_pydm.bool -> !iree_pydm.real
+ "custom.donotoptimize"(%1) : (!iree_pydm.real) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @fold_promote_numeric_false_to_real
+iree_pydm.func @fold_promote_numeric_false_to_real() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST:.*]] = constant 0.000000e+00 : f64 -> !iree_pydm.real
+ // CHECK: "custom.donotoptimize"(%[[CST]])
+ %0 = constant false -> !iree_pydm.bool
+ %1 = promote_numeric %0 : !iree_pydm.bool -> !iree_pydm.real
+ "custom.donotoptimize"(%1) : (!iree_pydm.real) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @fold_promote_numeric_integet_to_real
+iree_pydm.func @fold_promote_numeric_integet_to_real() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST:.*]] = constant 2.000000e+00 : f64 -> !iree_pydm.real
+ // CHECK: "custom.donotoptimize"(%[[CST]])
+ %0 = constant 2 : i64 -> !iree_pydm.integer
+ %1 = promote_numeric %0 : !iree_pydm.integer -> !iree_pydm.real
+ "custom.donotoptimize"(%1) : (!iree_pydm.real) -> ()
+ %none = none
+ return %none : !iree_pydm.none
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/ops_types_parse.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/ops_types_parse.mlir
new file mode 100644
index 0000000..5b908ce
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/ops_types_parse.mlir
@@ -0,0 +1,15 @@
+// RUN: iree-dialects-opt %s | iree-dialects-opt
+
+iree_pydm.func @free_var(%arg0 : !iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ %var = alloc_free_var "foo" -> !iree_pydm.free_var_ref
+ store_var %var = %arg0 : !iree_pydm.free_var_ref, !iree_pydm.bool
+ %0 = load_var %var : !iree_pydm.free_var_ref -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
+
+iree_pydm.func @free_var_index(%arg0 : !iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ %var = alloc_free_var "foo"[1] -> !iree_pydm.free_var_ref
+ store_var %var = %arg0 : !iree_pydm.free_var_ref, !iree_pydm.bool
+ %0 = load_var %var : !iree_pydm.free_var_ref -> !iree_pydm.bool
+ return %0 : !iree_pydm.bool
+}
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/assignment.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/assignment.py
index 8b32f08..a8d116f 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/assignment.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/assignment.py
@@ -5,9 +5,9 @@
# CHECK-LABEL: @assign_free_var_not_arg
-# CHECK: %[[CST:.*]] = iree_pydm.constant 1
-# CHECK: %[[BOXED:.*]] = iree_pydm.box %[[CST]] : !iree_pydm.integer -> !iree_pydm.object<!iree_pydm.integer>
-# CHECK: iree_pydm.store_free_var "x", %[[BOXED]]
+# CHECK: %[[CST:.*]] = constant 1
+# CHECK: %[[BOXED:.*]] = box %[[CST]] : !iree_pydm.integer -> !iree_pydm.object<!iree_pydm.integer>
+# CHECK: store_var %x = %[[BOXED]]
@test_import_global
def assign_free_var_not_arg():
x = 1
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/binary.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/binary.py
index 888536b..d9d3d29 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/binary.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/binary.py
@@ -5,94 +5,94 @@
# CHECK-LABEL: @binary_add
-# CHECK: %[[L:.*]] = iree_pydm.load_free_var "a"
-# CHECK: %[[R:.*]] = iree_pydm.load_free_var "b"
-# CHECK: %[[LP:.*]], %[[RP:.*]] = iree_pydm.dynamic_binary_promote %[[L]], %[[R]]
-# CHECK: iree_pydm.apply_binary "add", %[[LP]], %[[RP]]
+# CHECK: %[[L:.*]] = load_var %a
+# CHECK: %[[R:.*]] = load_var %b
+# CHECK: %[[LP:.*]], %[[RP:.*]] = dynamic_binary_promote %[[L]], %[[R]]
+# CHECK: apply_binary "add", %[[LP]], %[[RP]]
@test_import_global
def binary_add(a, b):
return a + b
# CHECK-LABEL: @binary_sub
-# CHECK: iree_pydm.apply_binary "sub"
+# CHECK: apply_binary "sub"
@test_import_global
def binary_sub(a, b):
return a - b
# CHECK-LABEL: @binary_mul
-# CHECK: iree_pydm.apply_binary "mul"
+# CHECK: apply_binary "mul"
@test_import_global
def binary_mul(a, b):
return a * b
# CHECK-LABEL: @binary_matmul
-# CHECK: iree_pydm.apply_binary "matmul"
+# CHECK: apply_binary "matmul"
@test_import_global
def binary_matmul(a, b):
return a @ b
# CHECK-LABEL: @binary_truediv
-# CHECK: iree_pydm.apply_binary "truediv"
+# CHECK: apply_binary "truediv"
@test_import_global
def binary_truediv(a, b):
return a / b
# CHECK-LABEL: @binary_floordiv
-# CHECK: iree_pydm.apply_binary "floordiv"
+# CHECK: apply_binary "floordiv"
@test_import_global
def binary_floordiv(a, b):
return a // b
# CHECK-LABEL: @binary_mod
-# CHECK: iree_pydm.apply_binary "mod"
+# CHECK: apply_binary "mod"
@test_import_global
def binary_mod(a, b):
return a % b
# CHECK-LABEL: @binary_pow
-# CHECK: iree_pydm.apply_binary "pow"
+# CHECK: apply_binary "pow"
@test_import_global
def binary_pow(a, b):
return a**b
# CHECK-LABEL: @binary_lshift
-# CHECK: iree_pydm.apply_binary "lshift"
+# CHECK: apply_binary "lshift"
@test_import_global
def binary_lshift(a, b):
return a << b
# CHECK-LABEL: @binary_rshift
-# CHECK: iree_pydm.apply_binary "rshift"
+# CHECK: apply_binary "rshift"
@test_import_global
def binary_rshift(a, b):
return a >> b
# CHECK-LABEL: @binary_and
-# CHECK: iree_pydm.apply_binary "and"
+# CHECK: apply_binary "and"
@test_import_global
def binary_and(a, b):
return a & b
# CHECK-LABEL: @binary_or
-# CHECK: iree_pydm.apply_binary "or"
+# CHECK: apply_binary "or"
@test_import_global
def binary_or(a, b):
return a | b
# CHECK-LABEL: @binary_xor
-# CHECK: iree_pydm.apply_binary "xor"
+# CHECK: apply_binary "xor"
@test_import_global
def binary_xor(a, b):
return a ^ b
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/booleans.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/booleans.py
index 63461b4..93f547a 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/booleans.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/booleans.py
@@ -5,22 +5,20 @@
# CHECK-LABEL: @logical_and
-# CHECK: %[[XVAL:.*]] = iree_pydm.load_free_var "x"
-# CHECK: %[[XBOOL:.*]] = iree_pydm.as_bool %[[XVAL]]
-# CHECK: %[[XPRED:.*]] = iree_pydm.bool_to_pred %[[XBOOL]]
-# CHECK: %[[R1:.*]] = scf.if %[[XPRED]] {{.*}} {
-# CHECK: %[[YVAL:.*]] = iree_pydm.load_free_var "y"
-# CHECK: %[[YBOOL:.*]] = iree_pydm.as_bool %[[YVAL]]
-# CHECK: %[[YPRED:.*]] = iree_pydm.bool_to_pred %[[YBOOL]]
-# CHECK: %[[R2:.*]] = scf.if %[[YPRED]] {{.*}} {
-# CHECK: %[[ZVAL:.*]] = iree_pydm.load_free_var "z"
-# CHECK: scf.yield %[[ZVAL]]
+# CHECK: %[[XVAL:.*]] = load_var %x
+# CHECK: %[[XBOOL:.*]] = as_bool %[[XVAL]]
+# CHECK: %[[R1:.*]] = functional_if %[[XBOOL]] {{.*}} {
+# CHECK: %[[YVAL:.*]] = load_var %y
+# CHECK: %[[YBOOL:.*]] = as_bool %[[YVAL]]
+# CHECK: %[[R2:.*]] = functional_if %[[YBOOL]] {{.*}} {
+# CHECK: %[[ZVAL:.*]] = load_var %z
+# CHECK: yield %[[ZVAL]]
# CHECK: } else {
-# CHECK: scf.yield %[[YVAL]]
+# CHECK: yield %[[YVAL]]
# CHECK: }
-# CHECK: scf.yield %[[R2]]
+# CHECK: yield %[[R2]]
# CHECK: } else {
-# CHECK: scf.yield %[[XVAL]]
+# CHECK: yield %[[XVAL]]
# CHECK: }
@test_import_global
def logical_and():
@@ -31,22 +29,20 @@
# # CHECK-LABEL: @logical_or
-# CHECK: %[[XVAL:.*]] = iree_pydm.load_free_var "x"
-# CHECK: %[[XBOOL:.*]] = iree_pydm.as_bool %[[XVAL]]
-# CHECK: %[[XPRED:.*]] = iree_pydm.bool_to_pred %[[XBOOL]]
-# CHECK: %[[R1:.*]] = scf.if %[[XPRED]] {{.*}} {
-# CHECK: scf.yield %[[XVAL]]
+# CHECK: %[[XVAL:.*]] = load_var %x
+# CHECK: %[[XBOOL:.*]] = as_bool %[[XVAL]]
+# CHECK: %[[R1:.*]] = functional_if %[[XBOOL]] {{.*}} {
+# CHECK: yield %[[XVAL]]
# CHECK: } else {
-# CHECK: %[[YVAL:.*]] = iree_pydm.load_free_var "y"
-# CHECK: %[[YBOOL:.*]] = iree_pydm.as_bool %[[YVAL]]
-# CHECK: %[[YPRED:.*]] = iree_pydm.bool_to_pred %[[YBOOL]]
-# CHECK: %[[R2:.*]] = scf.if %[[YPRED]] {{.*}} {
-# CHECK: scf.yield %[[YVAL]]
+# CHECK: %[[YVAL:.*]] = load_var %y
+# CHECK: %[[YBOOL:.*]] = as_bool %[[YVAL]]
+# CHECK: %[[R2:.*]] = functional_if %[[YBOOL]] {{.*}} {
+# CHECK: yield %[[YVAL]]
# CHECK: } else {
-# CHECK: %[[ZVAL:.*]] = iree_pydm.load_free_var "z"
-# CHECK: scf.yield %[[ZVAL]]
+# CHECK: %[[ZVAL:.*]] = load_var %z
+# CHECK: yield %[[ZVAL]]
# CHECK: }
-# CHECK: scf.yield %[[R2]]
+# CHECK: yield %[[R2]]
# CHECK: }
@test_import_global
def logical_or():
@@ -57,11 +53,11 @@
# CHECK-LABEL: func @logical_not
-# CHECK: %[[XVAL:.*]] = iree_pydm.load_free_var "x"
-# CHECK: %[[XBOOL:.*]] = iree_pydm.as_bool %[[XVAL]]
-# CHECK: %[[T:.*]] = iree_pydm.constant true
-# CHECK: %[[F:.*]] = iree_pydm.constant false
-# CHECK: %[[R:.*]] = iree_pydm.select %[[XBOOL]], %[[F]], %[[T]]
+# CHECK: %[[XVAL:.*]] = load_var %x
+# CHECK: %[[XBOOL:.*]] = as_bool %[[XVAL]]
+# CHECK: %[[T:.*]] = constant true
+# CHECK: %[[F:.*]] = constant false
+# CHECK: %[[R:.*]] = select %[[XBOOL]], %[[F]], %[[T]]
@test_import_global
def logical_not():
x = 1
@@ -69,17 +65,16 @@
# CHECK-LABEL: func @conditional
-# CHECK: %[[XVAL:.*]] = iree_pydm.load_free_var "x"
-# CHECK: %[[XBOOL:.*]] = iree_pydm.as_bool %[[XVAL]]
-# CHECK: %[[XPRED:.*]] = iree_pydm.bool_to_pred %[[XBOOL]]
-# CHECK: %[[R1:.*]] = scf.if %[[XPRED]] {{.*}} {
-# CHECK: %[[TWOVAL:.*]] = iree_pydm.constant 2
-# CHECK: %[[TWOBOXED:.*]] = iree_pydm.box %[[TWOVAL]] : !iree_pydm.integer -> !iree_pydm.object
-# CHECK: scf.yield %[[TWOBOXED]]
+# CHECK: %[[XVAL:.*]] = load_var %x
+# CHECK: %[[XBOOL:.*]] = as_bool %[[XVAL]]
+# CHECK: %[[R1:.*]] = functional_if %[[XBOOL]] {{.*}} {
+# CHECK: %[[TWOVAL:.*]] = constant 2
+# CHECK: %[[TWOBOXED:.*]] = box %[[TWOVAL]] : !iree_pydm.integer -> !iree_pydm.object
+# CHECK: yield %[[TWOBOXED]]
# CHECK: } else {
-# CHECK: %[[THREEVAL:.*]] = iree_pydm.constant 3
-# CHECK: %[[THREEBOXED:.*]] = iree_pydm.box %[[THREEVAL]] : !iree_pydm.integer -> !iree_pydm.object
-# CHECK: scf.yield %[[THREEBOXED]]
+# CHECK: %[[THREEVAL:.*]] = constant 3
+# CHECK: %[[THREEBOXED:.*]] = box %[[THREEVAL]] : !iree_pydm.integer -> !iree_pydm.object
+# CHECK: yield %[[THREEBOXED]]
# CHECK: }
@test_import_global
def conditional():
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/comparison.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/comparison.py
index 213c9f5..4c85035 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/comparison.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/comparison.py
@@ -8,10 +8,10 @@
# CHECK-LABEL: func @binary_lt_
-# CHECK-DAG: %[[L:.*]] = iree_pydm.load_free_var "x"
-# CHECK-DAG: %[[R:.*]] = iree_pydm.load_free_var "y"
-# CHECK: %[[LP:.*]], %[[RP:.*]] = iree_pydm.dynamic_binary_promote %[[L]], %[[R]]
-# CHECK: iree_pydm.apply_compare "lt", %[[LP]], %[[RP]]
+# CHECK-DAG: %[[L:.*]] = load_var %x
+# CHECK-DAG: %[[R:.*]] = load_var %y
+# CHECK: %[[LP:.*]], %[[RP:.*]] = dynamic_binary_promote %[[L]], %[[R]]
+# CHECK: apply_compare "lt", %[[LP]], %[[RP]]
@test_import_global
def binary_lt_():
x = 1
@@ -20,8 +20,8 @@
# CHECK-LABEL: func @binary_gt_
-# CHECK: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "gt"
+# CHECK: dynamic_binary_promote
+# CHECK: apply_compare "gt"
@test_import_global
def binary_gt_():
x = 1
@@ -30,8 +30,8 @@
# CHECK-LABEL: func @binary_lte_
-# CHECK: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "le"
+# CHECK: dynamic_binary_promote
+# CHECK: apply_compare "le"
@test_import_global
def binary_lte_():
x = 1
@@ -40,8 +40,8 @@
# CHECK-LABEL: func @binary_gte_
-# CHECK: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "ge"
+# CHECK: dynamic_binary_promote
+# CHECK: apply_compare "ge"
@test_import_global
def binary_gte_():
x = 1
@@ -50,8 +50,8 @@
# CHECK-LABEL: func @binary_eq_
-# CHECK: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "eq"
+# CHECK: dynamic_binary_promote
+# CHECK: apply_compare "eq"
@test_import_global
def binary_eq_():
x = 1
@@ -60,8 +60,8 @@
# CHECK-LABEL: func @binary_neq_
-# CHECK: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "ne"
+# CHECK: dynamic_binary_promote
+# CHECK: apply_compare "ne"
@test_import_global
def binary_neq_():
x = 1
@@ -70,8 +70,8 @@
# CHECK-LABEL: func @binary_is_
-# CHECK-NOT: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "is"
+# CHECK-NOT: dynamic_binary_promote
+# CHECK: apply_compare "is"
@test_import_global
def binary_is_():
x = 1
@@ -80,8 +80,8 @@
# CHECK-LABEL: func @binary_is_not_
-# CHECK-NOT: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "isnot"
+# CHECK-NOT: dynamic_binary_promote
+# CHECK: apply_compare "isnot"
@test_import_global
def binary_is_not_():
x = 1
@@ -90,8 +90,8 @@
# CHECK-LABEL: func @binary_in_
-# CHECK-NOT: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "in"
+# CHECK-NOT: dynamic_binary_promote
+# CHECK: apply_compare "in"
@test_import_global
def binary_in_():
x = 1
@@ -100,8 +100,8 @@
# CHECK-LABEL: func @binary_not_in_
-# CHECK-NOT: iree_pydm.dynamic_binary_promote
-# CHECK: iree_pydm.apply_compare "notin"
+# CHECK-NOT: dynamic_binary_promote
+# CHECK: apply_compare "notin"
@test_import_global
def binary_not_in_():
x = 1
@@ -110,30 +110,28 @@
# CHECK-LABEL: @short_circuit
-# CHECK-DAG: %[[FALSE:.*]] = iree_pydm.constant false
-# CHECK-DAG: %[[X:.*]] = iree_pydm.load_free_var "x"
-# CHECK-DAG: %[[Y:.*]] = iree_pydm.load_free_var "y"
-# CHECK: %[[XP:.*]], %[[YP:.*]] = iree_pydm.dynamic_binary_promote %[[X]], %[[Y]]
-# CHECK: %[[R1:.*]] = iree_pydm.apply_compare "lt", %[[XP]], %[[YP]]
-# CHECK: %[[RP1:.*]] = iree_pydm.bool_to_pred %[[R1]]
-# CHECK: %[[RESULT:.*]] = scf.if %[[RP1]] {{.*}} {
-# CHECK: %[[Z:.*]] = iree_pydm.load_free_var "z"
+# CHECK-DAG: %[[FALSE:.*]] = constant false
+# CHECK-DAG: %[[X:.*]] = load_var %x
+# CHECK-DAG: %[[Y:.*]] = load_var %y
+# CHECK: %[[XP:.*]], %[[YP:.*]] = dynamic_binary_promote %[[X]], %[[Y]]
+# CHECK: %[[R1:.*]] = apply_compare "lt", %[[XP]], %[[YP]]
+# CHECK: %[[RESULT:.*]] = functional_if %[[R1]] {{.*}} {
+# CHECK: %[[Z:.*]] = load_var %z
# NOTE: Promotion happens on original loaded values, not already promoted
# values.
-# CHECK: %[[YP1:.*]], %[[ZP1:.*]] = iree_pydm.dynamic_binary_promote %[[Y]], %[[Z]]
-# CHECK: %[[R2:.*]] = iree_pydm.apply_compare "eq", %[[YP1]], %[[ZP1]]
-# CHECK: %[[RP2:.*]] = iree_pydm.bool_to_pred %[[R2]]
-# CHECK: %[[RESULT1:.*]] = scf.if %[[RP2]] {{.*}} {
-# CHECK: %[[OMEGA:.*]] = iree_pydm.load_free_var "omega"
-# CHECK: %[[ZP2:.*]], %[[OMEGAP2:.*]] = iree_pydm.dynamic_binary_promote %[[Z]], %[[OMEGA]]
-# CHECK: %[[R3:.*]] = iree_pydm.apply_compare "ge", %[[ZP2]], %[[OMEGAP2]]
-# CHECK: scf.yield %[[R3]]
+# CHECK: %[[YP1:.*]], %[[ZP1:.*]] = dynamic_binary_promote %[[Y]], %[[Z]]
+# CHECK: %[[R2:.*]] = apply_compare "eq", %[[YP1]], %[[ZP1]]
+# CHECK: %[[RESULT1:.*]] = functional_if %[[R2]] {{.*}} {
+# CHECK: %[[OMEGA:.*]] = load_var %omega
+# CHECK: %[[ZP2:.*]], %[[OMEGAP2:.*]] = dynamic_binary_promote %[[Z]], %[[OMEGA]]
+# CHECK: %[[R3:.*]] = apply_compare "ge", %[[ZP2]], %[[OMEGAP2]]
+# CHECK: yield %[[R3]]
# CHECK: } else {
-# CHECK: scf.yield %[[FALSE]]
+# CHECK: yield %[[FALSE]]
# CHECK: }
-# CHECK: scf.yield %[[RESULT1]]
+# CHECK: yield %[[RESULT1]]
# CHECK: } else {
-# CHECK: scf.yield %[[FALSE]]
+# CHECK: yield %[[FALSE]]
# CHECK: }
@test_import_global
def short_circuit():
@@ -146,8 +144,8 @@
# CHECK-LABEL: nested_short_circuit_expression
# Verify that the nested expression is evaluated in the context of the if.
-# CHECK: scf.if {{.*}} {
-# CHECK: iree_pydm.apply_binary "add"
+# CHECK: functional_if {{.*}} {
+# CHECK: apply_binary "add"
# CHECK: } else {
@test_import_global
def nested_short_circuit_expression():
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/constants.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/constants.py
index 1a2c268..05218d2 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/constants.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/constants.py
@@ -5,49 +5,49 @@
# CHECK-LABEL: @const_integer
-# CHECK: iree_pydm.constant 1 : si64 -> !iree_pydm.integer
+# CHECK: = constant 1 : i64 -> !iree_pydm.integer
@test_import_global
def const_integer():
return 1
# CHECK-LABEL: @const_float
-# CHECK: iree_pydm.constant 2.200000e+00 : f64 -> !iree_pydm.real
+# CHECK: = constant 2.200000e+00 : f64 -> !iree_pydm.real
@test_import_global
def const_float():
return 2.2
# CHECK-LABEL: @const_str
-# CHECK: iree_pydm.constant "Hello" -> !iree_pydm.str
+# CHECK: = constant "Hello" -> !iree_pydm.str
@test_import_global
def const_str():
return "Hello"
# CHECK-LABEL: @const_bytes
-# CHECK: iree_pydm.constant "Bonjour" -> !iree_pydm.bytes
+# CHECK: = constant "Bonjour" -> !iree_pydm.bytes
@test_import_global
def const_bytes():
return b"Bonjour"
# CHECK-LABEL: @const_none
-# CHECK: iree_pydm.none -> !iree_pydm.none
+# CHECK: = none
@test_import_global
def const_none():
return None
# CHECK-LABEL: @const_true
-# CHECK: iree_pydm.constant true -> !iree_pydm.bool
+# CHECK: = constant true -> !iree_pydm.bool
@test_import_global
def const_true():
return True
# CHECK-LABEL: @const_false
-# CHECK: iree_pydm.constant false -> !iree_pydm.bool
+# CHECK: = constant false -> !iree_pydm.bool
@test_import_global
def const_false():
return False
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/flow_control.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/flow_control.py
index 7101dde..fa568d1 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/flow_control.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/flow_control.py
@@ -5,15 +5,15 @@
# CHECK-LABEL: @simple_if
-# CHECK: %[[COND:.*]] = iree_pydm.load_free_var "cond"
-# CHECK: %[[COND_BOOL:.*]] = iree_pydm.as_bool %[[COND]]
-# CHECK: %[[COND_PRED:.*]] = iree_pydm.bool_to_pred %[[COND_BOOL]]
+# CHECK: %[[COND:.*]] = load_var %cond
+# CHECK: %[[COND_BOOL:.*]] = as_bool %[[COND]]
+# CHECK: %[[COND_PRED:.*]] = bool_to_pred %[[COND_BOOL]]
# CHECK: cond_br %2, ^bb1, ^bb2
# CHECK: ^bb1:
-# CHECK: %[[A:.*]] = iree_pydm.load_free_var "a"
+# CHECK: %[[A:.*]] = load_var %a
# CHECK: return %[[A]]
# CHECK: ^bb2:
-# CHECK: %[[B:.*]] = iree_pydm.load_free_var "b"
+# CHECK: %[[B:.*]] = load_var %b
# CHECK: return %[[B]]
@test_import_global
def simple_if(cond, a, b):
@@ -30,7 +30,7 @@
# CHECK: ^bb2:
# CHECK: br ^bb3
# CHECK: ^bb3:
-# CHECK: iree_pydm.return
+# CHECK: return
@test_import_global
def if_fallthrough(cond, a, b):
if cond:
@@ -45,7 +45,7 @@
# CHECK: ^bb1:
# CHECK: br ^bb2
# CHECK: ^bb2:
-# CHECK: iree_pydm.return
+# CHECK: return
@test_import_global
def if_noelse(cond, a, b):
c = 1
@@ -67,7 +67,7 @@
# CHECK: ^bb5:
# CHECK: br ^bb6
# CHECK: ^bb6:
-# CHECK: iree_pydm.return
+# CHECK: return
@test_import_global
def if_elif(cond, a, b):
if cond:
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/function_def.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/function_def.py
index fc251347..5bb592a 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/function_def.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/function_def.py
@@ -4,18 +4,18 @@
from mlir.dialects.iree_pydm.importer.test_util import *
-# CHECK-LABEL: iree_pydm.func @fully_typed_with_return
+# CHECK-LABEL: func @fully_typed_with_return
# CHECK-SAME: (%arg0: !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer)
# CHECK-SAME: attributes {arg_names = ["a"], cell_vars = [], free_vars = ["a"]}
-# CHECK: iree_pydm.return {{.*}} : !iree_pydm.integer
+# CHECK: return {{.*}} : !iree_pydm.integer
@test_import_global
def fully_typed_with_return(a: int) -> int:
return a
-# CHECK-LABEL: iree_pydm.func @no_return
-# CHECK: %[[NONE:.*]] = iree_pydm.none
-# CHECK: iree_pydm.return %[[NONE]]
+# CHECK-LABEL: func @no_return
+# CHECK: %[[NONE:.*]] = none
+# CHECK: return %[[NONE]]
@test_import_global
def no_return():
pass
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/intrinsics.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/intrinsics.py
index b561c45..ad7e2b0 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/intrinsics.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/intrinsics.py
@@ -23,8 +23,8 @@
# CHECK-LABEL: @test_intrinsic_function_no_args
-# CHECK: iree_pydm.dynamic_call @__return_one() : () -> (!iree_pydm.exception_result, !iree_pydm.object)
-# CHECK: iree_pydm.func private @__return_one()
+# CHECK: dynamic_call @__return_one() : () -> (!iree_pydm.exception_result, !iree_pydm.object)
+# CHECK: func private @__return_one()
@test_import_global
def test_intrinsic_function_no_args():
value = intrinsic_return_one()
@@ -41,10 +41,10 @@
# CHECK-LABEL: @test_intrinsic_function_args
-# CHECK: %[[ZERO:.*]] = iree_pydm.constant 0 : si64 -> !iree_pydm.integer
-# CHECK: %[[ONE:.*]] = iree_pydm.constant 1 : si64 -> !iree_pydm.integer
-# CHECK: iree_pydm.dynamic_call @__return_first_true(%[[ZERO]], %[[ONE]]) : (!iree_pydm.integer, !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.object)
-# CHECK: iree_pydm.func private @__return_first_true
+# CHECK: %[[ZERO:.*]] = constant 0 : i64 -> !iree_pydm.integer
+# CHECK: %[[ONE:.*]] = constant 1 : i64 -> !iree_pydm.integer
+# CHECK: dynamic_call @__return_first_true(%[[ZERO]], %[[ONE]]) : (!iree_pydm.integer, !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.object)
+# CHECK: func private @__return_first_true
@test_import_global
def test_intrinsic_function_args():
value = intrinsic_return_first_true(0, 1)
@@ -68,8 +68,8 @@
# CHECK-LABEL: @test_intrinsic_macro_no_args
-# CHECK: %[[ONE:.*]] = iree_pydm.constant 1
-# CHECK: iree_pydm.box %[[ONE]] : !iree_pydm.integer -> !iree_pydm.object<!iree_pydm.integer>
+# CHECK: %[[ONE:.*]] = constant 1
+# CHECK: box %[[ONE]] : !iree_pydm.integer -> !iree_pydm.object<!iree_pydm.integer>
@test_import_global
def test_intrinsic_macro_no_args() -> int:
return macro_box_arg(1)
@@ -95,11 +95,11 @@
# CHECK-LABEL: @test_pattern_call
-# CHECK: %[[TRUE:.*]] = iree_pydm.constant true
-# CHECK: iree_pydm.pattern_match_call(%[[TRUE]]) : (!iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.object)
+# CHECK: %[[TRUE:.*]] = constant true
+# CHECK: pattern_match_call(%[[TRUE]]) : (!iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.object)
# CHECK-SAME: matching generic [@__logical_not_generic] specific [@__logical_not_bool]
-# CHECK-DAG: iree_pydm.func private @__logical_not_generic
-# CHECK-DAG: iree_pydm.func private @__logical_not_bool
+# CHECK-DAG: func private @__logical_not_generic
+# CHECK-DAG: func private @__logical_not_bool
@test_import_global
def test_pattern_call():
return logical_not(True)
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/structural.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/structural.py
index 35a6ac0..0dda414 100644
--- a/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/structural.py
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/importer/structural.py
@@ -5,8 +5,8 @@
# CHECK-LABEL @expr_statement
-# CHECK: %[[XVAL:.*]] = iree_pydm.load_free_var "x"
-# CHECK: iree_pydm.expr_statement_discard %[[XVAL]]
+# CHECK: %[[XVAL:.*]] = load_var %x
+# CHECK: expr_statement_discard %[[XVAL]]
@test_import_global
def expr_statement(x: int):
x
diff --git a/llvm-external-projects/iree-dialects/tools/iree-dialects-opt/iree-dialects-opt.cpp b/llvm-external-projects/iree-dialects/tools/iree-dialects-opt/iree-dialects-opt.cpp
index afc7e09..8f1dc39 100644
--- a/llvm-external-projects/iree-dialects/tools/iree-dialects-opt/iree-dialects-opt.cpp
+++ b/llvm-external-projects/iree-dialects/tools/iree-dialects-opt/iree-dialects-opt.cpp
@@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "iree-dialects/Dialect/IREE/IREEDialect.h"
-#include "iree-dialects/Dialect/IREEPyDM/IR/IREEPyDMDialect.h"
+#include "iree-dialects/Dialect/IREEPyDM/IR/Dialect.h"
#include "mlir/Dialect/SCF/SCF.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/IR/AsmState.h"