[pydm] Plumb through RTL and finish conversions for basic program. (#7244)
* I haven't yet figured out the best way to e2e test this. For now, putting e2e tests in the samples repo: https://github.com/google/iree-samples/tree/main/pydm/simple
diff --git a/bindings/python/iree/runtime/vm.cc b/bindings/python/iree/runtime/vm.cc
index ae39185..d49cf01 100644
--- a/bindings/python/iree/runtime/vm.cc
+++ b/bindings/python/iree/runtime/vm.cc
@@ -690,6 +690,30 @@
.def_property_readonly(
"stashed_flatbuffer_blob",
[](VmModule& self) { return self.get_stashed_flatbuffer_blob(); })
+ .def_property_readonly(
+ "function_names",
+ [](VmModule& self) {
+ py::list names;
+ iree_vm_module_signature_t sig =
+ iree_vm_module_signature(self.raw_ptr());
+ for (size_t ordinal = 0; ordinal < sig.export_function_count;
+ ++ordinal) {
+ iree_vm_function_t f;
+ iree_string_view_t linkage_name;
+ auto status = iree_vm_module_lookup_function_by_ordinal(
+ self.raw_ptr(), IREE_VM_FUNCTION_LINKAGE_EXPORT, ordinal, &f,
+ &linkage_name);
+ if (iree_status_is_not_found(status)) {
+ iree_status_ignore(status);
+ break;
+ }
+ CheckApiStatus(status, "Error enumerating module");
+ iree_string_view_t fname = iree_vm_function_name(&f);
+ py::str name(fname.data, fname.size);
+ names.append(name);
+ }
+ return names;
+ })
.def("__repr__", [](VmModule& self) {
std::string repr("<VmModule ");
iree_string_view_t name = iree_vm_module_name(self.raw_ptr());
diff --git a/llvm-external-projects/iree-compiler-api/include/iree-compiler-c/Compiler.h b/llvm-external-projects/iree-compiler-api/include/iree-compiler-c/Compiler.h
index 6e946e8..2be688c 100644
--- a/llvm-external-projects/iree-compiler-api/include/iree-compiler-c/Compiler.h
+++ b/llvm-external-projects/iree-compiler-api/include/iree-compiler-c/Compiler.h
@@ -21,6 +21,7 @@
typedef struct name name
DEFINE_C_API_STRUCT(IreeCompilerOptions, void);
+#undef DEFINE_C_API_STRUCT
//===----------------------------------------------------------------------===//
// Registration.
diff --git a/llvm-external-projects/iree-compiler-api/lib/CAPI/Compiler.cpp b/llvm-external-projects/iree-compiler-api/lib/CAPI/Compiler.cpp
index 3b6ae8d..d13028d 100644
--- a/llvm-external-projects/iree-compiler-api/lib/CAPI/Compiler.cpp
+++ b/llvm-external-projects/iree-compiler-api/lib/CAPI/Compiler.cpp
@@ -44,7 +44,10 @@
void ireeCompilerRegisterTargetBackends() { registerHALTargetBackends(); }
IreeCompilerOptions ireeCompilerOptionsCreate() {
- return wrap(new CompilerOptions);
+ auto options = new CompilerOptions;
+ // TODO: Make configurable.
+ options->vmTargetOptions.f32Extension = true;
+ return wrap(options);
}
void ireeCompilerOptionsDestroy(IreeCompilerOptions options) {
diff --git a/llvm-external-projects/iree-dialects/BUILD b/llvm-external-projects/iree-dialects/BUILD
index df10347..ff9cbdf 100644
--- a/llvm-external-projects/iree-dialects/BUILD
+++ b/llvm-external-projects/iree-dialects/BUILD
@@ -312,5 +312,6 @@
":IREEPyDMTransforms",
"@llvm-project//mlir:CAPIIR",
"@llvm-project//mlir:IR",
+ "@llvm-project//mlir:Support",
],
)
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 613df95..da8701a 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
@@ -27,6 +27,28 @@
MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(IREEPyDM, iree_pydm);
+#define DEFINE_C_API_STRUCT(name, storage) \
+ struct name { \
+ storage *ptr; \
+ }; \
+ typedef struct name name
+
+DEFINE_C_API_STRUCT(IREEPyDMSourceBundle, void);
+DEFINE_C_API_STRUCT(IREEPyDMLoweringOptions, void);
+#undef DEFINE_C_API_STRUCT
+
+/// Creates a PyDM source bundle from an ASM string.
+MLIR_CAPI_EXPORTED IREEPyDMSourceBundle
+ireePyDMSourceBundleCreateAsm(MlirStringRef asmString);
+
+/// Creates a PyDM source bundle from a file path.
+MLIR_CAPI_EXPORTED IREEPyDMSourceBundle
+ireePyDMSourceBundleCreateFile(MlirStringRef filePath);
+
+/// Destroys a created source bundle.
+MLIR_CAPI_EXPORTED void ireePyDMSourceBundleDestroy(
+ IREEPyDMSourceBundle bundle);
+
MLIR_CAPI_EXPORTED bool mlirTypeIsAIREEPyDMPrimitiveType(MlirType type);
#define IREEPYDM_DECLARE_NULLARY_TYPE(Name) \
@@ -51,9 +73,20 @@
MLIR_CAPI_EXPORTED MlirType mlirIREEPyDMObjectTypeGet(MlirContext context,
MlirType primitive);
+/// Creates a lowering options struct.
+MLIR_CAPI_EXPORTED IREEPyDMLoweringOptions ireePyDMLoweringOptionsCreate();
+
+/// Sets the RTL link source bundle to the lowering options.
+MLIR_CAPI_EXPORTED void ireePyDMLoweringOptionsLinkRtl(
+ IREEPyDMLoweringOptions options, IREEPyDMSourceBundle source);
+
+/// Destroys a created lowering options struct.
+MLIR_CAPI_EXPORTED void ireePyDMLoweringOptionsDestroy(
+ IREEPyDMLoweringOptions options);
+
/// Builds a pass pipeline which lowers the iree_pydm dialect to IREE.
MLIR_CAPI_EXPORTED void mlirIREEPyDMBuildLowerToIREEPassPipeline(
- MlirOpPassManager passManager);
+ MlirOpPassManager passManager, IREEPyDMLoweringOptions options);
#ifdef __cplusplus
}
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h
index c3670e0..a169051 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h
@@ -7,8 +7,11 @@
#ifndef IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_TRANSFORMS_PASSES_H
#define IREE_LLVM_EXTERNAL_PROJECTS_IREE_DIALECTS_DIALECT_IREEPYDM_TRANSFORMS_PASSES_H
+#include <memory>
+
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Pass/Pass.h"
+#include "mlir/Support/LLVM.h"
namespace mlir {
@@ -18,9 +21,25 @@
namespace iree_pydm {
+/// References sources, either passed literally or by reference to a file.
+/// One of `asmBlob` or `asmFilePath` should be populated.
+struct SourceBundle {
+ std::shared_ptr<std::string> asmBlob;
+ Optional<std::string> asmFilePath;
+};
+
+/// Options for lowering to IREE.
+struct LowerToIREEOptions {
+ Optional<SourceBundle> linkRtlSource;
+};
+
std::unique_ptr<OperationPass<ModuleOp>> createConvertIREEPyDMToIREEPass();
std::unique_ptr<OperationPass<ModuleOp>> createLowerIREEPyDMToRTLPass();
-std::unique_ptr<OperationPass<ModuleOp>> createLinkIREEPyDMRTLPass();
+std::unique_ptr<OperationPass<ModuleOp>> createLinkIREEPyDMRTLPass(
+ Optional<SourceBundle> linkRtlSourceBundle = None);
+
+void buildLowerToIREEPassPipeline(OpPassManager& passManager,
+ const LowerToIREEOptions& options);
#define GEN_PASS_REGISTRATION
#include "iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h.inc"
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.h
index 69dd0e1..daef405 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.h
@@ -26,6 +26,10 @@
Type getWeakIntegerType(Builder b) const;
Type getWeakFloatType(Builder b) const;
+ // Whether the given type is a valid lowered type.
+ bool isTypeLegal(Type t) const;
+ bool areTypesLegal(TypeRange types) const;
+
private:
bool boolBits = 32;
int weakIntegerBits = 32;
diff --git a/llvm-external-projects/iree-dialects/lib/CAPI/CMakeLists.txt b/llvm-external-projects/iree-dialects/lib/CAPI/CMakeLists.txt
index 66682e5..75be3ec 100644
--- a/llvm-external-projects/iree-dialects/lib/CAPI/CMakeLists.txt
+++ b/llvm-external-projects/iree-dialects/lib/CAPI/CMakeLists.txt
@@ -5,7 +5,7 @@
MLIRIR
IREEDialectsIREEDialect
IREEDialectsIREEPyDMDialect
- IREEDialectsIREEPyDMToIREEPasses
+ IREEDialectsIREEPyDMPasses
)
iree_dialects_target_includes(IREEDialectsCAPI)
diff --git a/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp b/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
index ad5e546..d316fbe 100644
--- a/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
+++ b/llvm-external-projects/iree-dialects/lib/CAPI/Dialects.cpp
@@ -15,6 +15,9 @@
#include "mlir/CAPI/Support.h"
#include "mlir/CAPI/Utils.h"
#include "mlir/CAPI/Wrap.h"
+#include "mlir/Support/LLVM.h"
+
+using namespace mlir;
//===----------------------------------------------------------------------===//
// IREEDialect
@@ -29,6 +32,10 @@
MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(IREEPyDM, iree_pydm,
mlir::iree_pydm::IREEPyDMDialect)
+DEFINE_C_API_PTR_METHODS(IREEPyDMSourceBundle, mlir::iree_pydm::SourceBundle)
+DEFINE_C_API_PTR_METHODS(IREEPyDMLoweringOptions,
+ mlir::iree_pydm::LowerToIREEOptions)
+
bool mlirTypeIsAIREEPyDMPrimitiveType(MlirType type) {
return unwrap(type).isa<mlir::iree_pydm::PrimitiveType>();
}
@@ -66,8 +73,40 @@
return wrap(mlir::iree_pydm::ObjectType::get(unwrap(ctx), cppType));
}
-void mlirIREEPyDMBuildLowerToIREEPassPipeline(MlirOpPassManager passManager) {
+void mlirIREEPyDMBuildLowerToIREEPassPipeline(MlirOpPassManager passManager,
+ IREEPyDMLoweringOptions options) {
auto *passManagerCpp = unwrap(passManager);
- // TODO: Should be a pass pipeline, not loose passes in the C impl.
- passManagerCpp->addPass(mlir::iree_pydm::createConvertIREEPyDMToIREEPass());
+ mlir::iree_pydm::buildLowerToIREEPassPipeline(*passManagerCpp,
+ *unwrap(options));
+}
+
+// SourceBundle
+IREEPyDMSourceBundle ireePyDMSourceBundleCreateAsm(MlirStringRef asmString) {
+ auto bundle = std::make_unique<mlir::iree_pydm::SourceBundle>();
+ bundle->asmBlob = std::make_shared<std::string>(unwrap(asmString));
+ return wrap(bundle.release());
+}
+
+IREEPyDMSourceBundle ireePyDMSourceBundleCreateFile(MlirStringRef filePath) {
+ auto bundle = std::make_unique<mlir::iree_pydm::SourceBundle>();
+ bundle->asmFilePath = std::string(unwrap(filePath));
+ return wrap(bundle.release());
+}
+
+void ireePyDMSourceBundleDestroy(IREEPyDMSourceBundle bundle) {
+ delete unwrap(bundle);
+}
+
+// LoweringOptions
+IREEPyDMLoweringOptions ireePyDMLoweringOptionsCreate() {
+ return wrap(new mlir::iree_pydm::LowerToIREEOptions);
+}
+
+void ireePyDMLoweringOptionsLinkRtl(IREEPyDMLoweringOptions options,
+ IREEPyDMSourceBundle source) {
+ unwrap(options)->linkRtlSource = *unwrap(source);
+}
+
+void ireePyDMLoweringOptionsDestroy(IREEPyDMLoweringOptions options) {
+ delete unwrap(options);
}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/CMakeLists.txt b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/CMakeLists.txt
index 37db9a5..44fe3b2 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/CMakeLists.txt
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/CMakeLists.txt
@@ -1,2 +1,15 @@
add_subdirectory(RTL)
add_subdirectory(ToIREE)
+
+add_mlir_library(IREEDialectsIREEPyDMPasses
+ Passes.cpp
+
+ DEPENDS
+ MLIRIREEPyDMTransformsPassesIncGen
+
+ LINK_LIBS PUBLIC
+ IREEDialectsIREEPyDMRTLPasses
+ IREEDialectsIREEPyDMToIREEPasses
+)
+
+iree_dialects_target_includes(IREEDialectsIREEPyDMPasses)
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/Passes.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/Passes.cpp
new file mode 100644
index 0000000..caaaf14
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/Passes.cpp
@@ -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
+
+#include "iree-dialects/Dialect/IREEPyDM/Transforms/Passes.h"
+
+#include "mlir/Pass/PassManager.h"
+
+using namespace mlir;
+using namespace mlir::iree_pydm;
+
+void mlir::iree_pydm::buildLowerToIREEPassPipeline(
+ OpPassManager& passManager, const LowerToIREEOptions& options) {
+ // TODO: Needs to be iterative, support optimization passes, etc.
+ passManager.addPass(createLowerIREEPyDMToRTLPass());
+ if (options.linkRtlSource) {
+ passManager.addPass(createLinkIREEPyDMRTLPass(options.linkRtlSource));
+ }
+ passManager.addPass(createConvertIREEPyDMToIREEPass());
+}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/RTL/LinkRTLPass.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/RTL/LinkRTLPass.cpp
index 9608edf..7803d65 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/RTL/LinkRTLPass.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/RTL/LinkRTLPass.cpp
@@ -35,22 +35,38 @@
namespace {
class LinkIREEPyDMRTLPass : public LinkIREEPyDMRTLBase<LinkIREEPyDMRTLPass> {
+ public:
+ LinkIREEPyDMRTLPass() = default;
+ LinkIREEPyDMRTLPass(Optional<SourceBundle> linkRtlSourceBundle)
+ : linkRtlSourceBundle(std::move(linkRtlSourceBundle)) {}
+
+ private:
LogicalResult initialize(MLIRContext *context) override {
- // Already initialized in some way.
- if (!rtlModule && rtlFile.empty()) {
+ SourceBundle localSource;
+ if (linkRtlSourceBundle) {
+ localSource = *linkRtlSourceBundle;
+ } else {
+ // Get it from the cli options.
+ localSource.asmFilePath = rtlFile;
+ }
+
+ if (localSource.asmBlob) {
+ // Parse from inline asm.
+ auto owningOp = parseSourceString(*localSource.asmBlob, context);
+ if (!owningOp) return failure();
+ rtlModule = std::make_shared<OwningModuleRef>(std::move(owningOp));
+ } else if (localSource.asmFilePath) {
+ // Parse from a file.
+ auto owningOp = parseSourceFile(*localSource.asmFilePath, context);
+ if (!owningOp) return failure();
+ rtlModule = std::make_shared<OwningModuleRef>(std::move(owningOp));
+ } else {
return emitError(UnknownLoc::get(context))
<< "pass " << getArgument()
<< "must be initialized with an RTL module (did you mean to "
"add an rtl-file option?)";
}
- if (!rtlFile.empty()) {
- // Parse from a file.
- auto owningOp = parseSourceFile(rtlFile, context);
- if (!owningOp) return failure();
- rtlModule = std::make_shared<OwningModuleRef>(std::move(owningOp));
- }
-
ModuleOp parentModule = rtlModule->get();
// Walk the module and build a SymbolTable for each sub-module.
parentModule->walk([&](ModuleOp importModule) {
@@ -187,11 +203,15 @@
// A SymbolTable for each sub module.
SmallVector<SymbolTable> importModules;
+
+ // ASM source of RTL modules to link (otherwise will use pass options).
+ Optional<SourceBundle> linkRtlSourceBundle;
};
} // namespace
std::unique_ptr<OperationPass<ModuleOp>>
-mlir::iree_pydm::createLinkIREEPyDMRTLPass() {
- return std::make_unique<LinkIREEPyDMRTLPass>();
+mlir::iree_pydm::createLinkIREEPyDMRTLPass(
+ Optional<SourceBundle> linkRtlSourceBundle) {
+ return std::make_unique<LinkIREEPyDMRTLPass>(std::move(linkRtlSourceBundle));
}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/ConversionPass.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/ConversionPass.cpp
index 661a237..2d4d88d 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/ConversionPass.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/ConversionPass.cpp
@@ -40,6 +40,16 @@
target.addLegalDialect<mlir::iree::IREEDialect>();
target.addLegalDialect<mlir::math::MathDialect>();
target.addLegalDialect<StandardOpsDialect>();
+
+ // Some CFG ops can be present in the original pydm program. Need to
+ // verify legality based on types.
+ target.addDynamicallyLegalOp<BranchOp>([&](BranchOp op) -> bool {
+ return typeConverter.areTypesLegal(op.getOperandTypes());
+ });
+ target.addDynamicallyLegalOp<CondBranchOp>([&](CondBranchOp op) -> bool {
+ return typeConverter.areTypesLegal(op.getOperandTypes());
+ });
+
if (failed(applyPartialConversion(moduleOp, target, std::move(patterns)))) {
return signalPassFailure();
}
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/LoweringPatterns.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/LoweringPatterns.cpp
index 6214709..9b3e1fd 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/LoweringPatterns.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/LoweringPatterns.cpp
@@ -17,6 +17,7 @@
using namespace mlir;
using namespace mlir::iree_pydm;
+namespace arith_d = mlir;
namespace iree_d = mlir::iree;
namespace builtin_d = mlir;
namespace std_d = mlir;
@@ -101,6 +102,60 @@
return list;
}
+static Value castIntegerValue(Location loc, Value input,
+ builtin_d::IntegerType resultType,
+ OpBuilder &builder) {
+ builtin_d::IntegerType inputType =
+ input.getType().cast<builtin_d::IntegerType>();
+ if (inputType.getWidth() == resultType.getWidth()) {
+ return input;
+ } else if (inputType.getWidth() < resultType.getWidth()) {
+ return builder.create<arith_d::SignExtendIOp>(loc, resultType, input);
+ } else {
+ return builder.create<arith_d::TruncateIOp>(loc, resultType, input);
+ }
+}
+
+static Optional<arith_d::CmpIPredicate> convertIntegerComparePredicate(
+ StringAttr dunderName, bool isSigned, Builder &builder) {
+ StringRef v = dunderName.getValue();
+ if (v == "lt") {
+ return isSigned ? arith_d::CmpIPredicate::slt : arith_d::CmpIPredicate::ult;
+ } else if (v == "le") {
+ return isSigned ? arith_d::CmpIPredicate::sle : arith_d::CmpIPredicate::ule;
+ } else if (v == "eq" || v == "is") {
+ return arith_d::CmpIPredicate::eq;
+ } else if (v == "ne" || v == "isnot") {
+ return arith_d::CmpIPredicate::ne;
+ } else if (v == "gt") {
+ return isSigned ? arith_d::CmpIPredicate::sgt : arith_d::CmpIPredicate::ugt;
+ } else if (v == "ge") {
+ return isSigned ? arith_d::CmpIPredicate::sge : arith_d::CmpIPredicate::uge;
+ }
+
+ return {};
+}
+
+static Optional<arith_d::CmpFPredicate> convertFpComparePredicate(
+ StringAttr dunderName, Builder &builder) {
+ StringRef v = dunderName.getValue();
+ if (v == "lt") {
+ return arith_d::CmpFPredicate::OLT;
+ } else if (v == "le") {
+ return arith_d::CmpFPredicate::OLE;
+ } else if (v == "eq" || v == "is") {
+ return arith_d::CmpFPredicate::OEQ;
+ } else if (v == "ne" || v == "isnot") {
+ return arith_d::CmpFPredicate::ONE;
+ } else if (v == "gt") {
+ return arith_d::CmpFPredicate::OGT;
+ } else if (v == "ge") {
+ return arith_d::CmpFPredicate::OGE;
+ }
+
+ return {};
+}
+
namespace {
class AllocFreeVarOpConversion
@@ -120,6 +175,53 @@
}
};
+class ApplyCompareNumericConversion
+ : public OpConversionPattern<pydm_d::ApplyCompareOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult matchAndRewrite(
+ pydm_d::ApplyCompareOp srcOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ Type leftType = adaptor.left().getType();
+ Type rightType = adaptor.right().getType();
+ if (leftType != rightType) {
+ return rewriter.notifyMatchFailure(srcOp, "not same type operands");
+ }
+ if (leftType.isa<builtin_d::IntegerType>()) {
+ bool isSigned = true; // TODO: Unsigned.
+ auto predicate = convertIntegerComparePredicate(adaptor.dunder_name(),
+ isSigned, rewriter);
+ if (!predicate)
+ return rewriter.notifyMatchFailure(srcOp, "unsupported predicate");
+ rewriter.replaceOpWithNewOp<arith_d::CmpIOp>(
+ srcOp, *predicate, adaptor.left(), adaptor.right());
+ return success();
+ } else if (leftType.isa<builtin_d::FloatType>()) {
+ auto predicate =
+ convertFpComparePredicate(adaptor.dunder_name(), rewriter);
+ if (!predicate)
+ return rewriter.notifyMatchFailure(srcOp, "unsupported predicate");
+ rewriter.replaceOpWithNewOp<arith_d::CmpFOp>(
+ srcOp, *predicate, adaptor.left(), adaptor.right());
+ return success();
+ }
+
+ return rewriter.notifyMatchFailure(srcOp, "non numeric type");
+ }
+};
+
+class BoolToPredConversion : public OpConversionPattern<pydm_d::BoolToPredOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult matchAndRewrite(
+ pydm_d::BoolToPredOp srcOp, ArrayRef<Value> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ pydm_d::BoolToPredOp::Adaptor adaptor(operands);
+ rewriter.replaceOp(srcOp, adaptor.value());
+ return success();
+ }
+};
+
class BoxOpConversion : public OpConversionPattern<pydm_d::BoxOp> {
using OpConversionPattern::OpConversionPattern;
@@ -140,6 +242,95 @@
}
};
+class BranchConversion : public OpConversionPattern<std_d::BranchOp> {
+ using OpConversionPattern::OpConversionPattern;
+ LogicalResult matchAndRewrite(
+ std_d::BranchOp srcOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ rewriter.replaceOpWithNewOp<std_d::BranchOp>(srcOp, srcOp.dest(),
+ adaptor.destOperands());
+ return success();
+ }
+};
+
+class CallOpConversion : public OpConversionPattern<pydm_d::CallOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult matchAndRewrite(
+ pydm_d::CallOp srcOp, ArrayRef<Value> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ pydm_d::CallOp::Adaptor adaptor(operands);
+ SmallVector<Type> resultTypes;
+ if (failed(getTypeConverter()->convertTypes(srcOp.getResultTypes(),
+ resultTypes))) {
+ return rewriter.notifyMatchFailure(srcOp,
+ "result types could not be converted");
+ }
+ rewriter.replaceOpWithNewOp<std_d::CallOp>(srcOp, srcOp.callee(),
+ resultTypes, adaptor.operands());
+ return success();
+ }
+};
+
+class CondBranchConversion : public OpConversionPattern<std_d::CondBranchOp> {
+ using OpConversionPattern::OpConversionPattern;
+ LogicalResult matchAndRewrite(
+ std_d::CondBranchOp srcOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ rewriter.replaceOpWithNewOp<std_d::CondBranchOp>(
+ srcOp, adaptor.condition(), srcOp.trueDest(),
+ adaptor.trueDestOperands(), srcOp.falseDest(),
+ adaptor.falseDestOperands());
+ return success();
+ }
+};
+
+class ConstantOpConversion : public OpConversionPattern<pydm_d::ConstantOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult matchAndRewrite(
+ pydm_d::ConstantOp srcOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ auto loc = srcOp.getLoc();
+ Type resultType = typeConverter->convertType(srcOp.getResult().getType());
+ if (!resultType)
+ return rewriter.notifyMatchFailure(
+ srcOp, "constant type could not be converted");
+ Attribute newValue = adaptor.value();
+ // Fixup widths of integer types that may be wider/narrower than the
+ // stored attribute (which tends to be stored in high precision in pydm
+ // constants).
+ TypeSwitch<Type>(resultType)
+ .Case([&](builtin_d::IntegerType t) {
+ APInt intValue =
+ newValue.cast<IntegerAttr>().getValue().sextOrTrunc(t.getWidth());
+ newValue = rewriter.getIntegerAttr(t, intValue);
+ })
+ .Case([&](builtin_d::FloatType t) {
+ APFloat fpValue = newValue.cast<FloatAttr>().getValue();
+ if (APFloat::SemanticsToEnum(fpValue.getSemantics()) !=
+ APFloat::SemanticsToEnum(t.getFloatSemantics())) {
+ // Convert.
+ APFloat newFpValue = fpValue;
+ bool losesInfo;
+ newFpValue.convert(t.getFloatSemantics(),
+ APFloat::rmNearestTiesToEven, &losesInfo);
+ if (losesInfo) {
+ emitWarning(loc) << "conversion of " << newValue << " to " << t
+ << " loses information";
+ }
+ newValue = rewriter.getFloatAttr(t, newFpValue);
+ }
+ });
+
+ if (!newValue)
+ return rewriter.notifyMatchFailure(
+ srcOp, "constant cannot be represented as a standard constant");
+ rewriter.replaceOpWithNewOp<std_d::ConstantOp>(srcOp, resultType, newValue);
+ return success();
+ }
+};
+
class FuncOpConversion : public OpConversionPattern<pydm_d::FuncOp> {
using OpConversionPattern::OpConversionPattern;
@@ -172,6 +363,7 @@
convertedResultTypes);
auto newFuncOp = rewriter.create<mlir::FuncOp>(
srcOp.getLoc(), srcOp.getName(), newFuncType);
+ newFuncOp.setVisibility(srcOp.getVisibility());
rewriter.inlineRegionBefore(srcOp.getBody(), newFuncOp.getBody(),
newFuncOp.end());
@@ -187,6 +379,33 @@
}
};
+class GetTypeCodeConversion
+ : public OpConversionPattern<pydm_d::GetTypeCodeOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult matchAndRewrite(
+ pydm_d::GetTypeCodeOp srcOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ auto loc = srcOp.getLoc();
+ // Gets the 0'th element of the object list, optionally casting it to the
+ // converted integer type.
+ Type resultType = typeConverter->convertType(srcOp.getResult().getType());
+ if (!resultType)
+ return rewriter.notifyMatchFailure(srcOp,
+ "result type could not be converted");
+ Type i32Type = rewriter.getIntegerType(32);
+ Value index0 =
+ rewriter.create<std_d::ConstantOp>(loc, rewriter.getIndexAttr(0));
+ Value typeCode = rewriter.create<iree_d::ListGetOp>(
+ loc, i32Type, adaptor.value(), index0);
+ rewriter.replaceOp(
+ srcOp,
+ castIntegerValue(loc, typeCode,
+ resultType.cast<builtin_d::IntegerType>(), rewriter));
+ return success();
+ }
+};
+
class LoadVarOpConversion : public OpConversionPattern<pydm_d::LoadVarOp> {
using OpConversionPattern::OpConversionPattern;
@@ -237,8 +456,8 @@
auto loc = srcOp.getLoc();
Value status = operands[0];
- // Get the containing function return type so that we can create a suitable
- // null return value.
+ // Get the containing function return type so that we can create a
+ // suitable null return value.
auto parentFunc = srcOp->getParentOfType<builtin_d::FuncOp>();
if (!parentFunc)
return rewriter.notifyMatchFailure(srcOp, "not contained by a func");
@@ -390,10 +609,13 @@
MLIRContext *context, TypeConverter &typeConverter,
RewritePatternSet &patterns) {
// Structural.
- patterns.insert<AllocFreeVarOpConversion, BoxOpConversion, FuncOpConversion,
- LoadVarOpConversion, RaiseOnFailureOpConversion,
- ReturnOpConversion, StoreVarOpConversion, UnboxOpConversion>(
- typeConverter, context);
+ patterns.insert<AllocFreeVarOpConversion, ApplyCompareNumericConversion,
+ BoolToPredConversion, BoxOpConversion, BranchConversion,
+ CallOpConversion, CondBranchConversion, ConstantOpConversion,
+ FuncOpConversion, GetTypeCodeConversion, LoadVarOpConversion,
+ RaiseOnFailureOpConversion, ReturnOpConversion,
+ StoreVarOpConversion, UnboxOpConversion>(typeConverter,
+ context);
// Constants and constructors.
patterns.insert<NoneOpConversion>(typeConverter, context);
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.cpp
index 9416b2a..0ee4fb7 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/IREEPyDM/Transforms/ToIREE/TypeConverter.cpp
@@ -37,12 +37,23 @@
return getVariantListType(b);
});
+ // Bool.
+ addConversion([&](pydm_d::BoolType t) -> Optional<Type> {
+ return builtin_d::IntegerType::get(t.getContext(), 1);
+ });
+
// Integer type hierarchy.
addConversion([&](pydm_d::IntegerType t) -> Optional<Type> {
Builder b(t.getContext());
return getWeakIntegerType(b);
});
+ // Real type hierarchy.
+ addConversion([&](pydm_d::RealType t) -> Optional<Type> {
+ Builder b(t.getContext());
+ return getWeakFloatType(b);
+ });
+
// Variable references.
addConversion([](pydm_d::FreeVarRefType t) -> Optional<Type> {
// Just an object record.
@@ -73,3 +84,15 @@
return b.getF64Type();
}
}
+
+bool LoweringTypeConverter::isTypeLegal(Type t) const {
+ return t.isa<builtin_d::IntegerType, builtin_d::FloatType,
+ builtin_d::IndexType, iree_d::ListType>();
+}
+
+bool LoweringTypeConverter::areTypesLegal(TypeRange types) const {
+ for (Type t : types) {
+ if (!isTypeLegal(t)) return false;
+ }
+ return true;
+}
diff --git a/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp b/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
index 0b235ee..067c565 100644
--- a/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
+++ b/llvm-external-projects/iree-dialects/python/IREEDialectsModule.cpp
@@ -15,6 +15,36 @@
namespace py = pybind11;
using namespace mlir::python::adaptors;
+namespace {
+
+struct PyIREEPyDMSourceBundle {
+ PyIREEPyDMSourceBundle(IREEPyDMSourceBundle wrapped) : wrapped(wrapped) {}
+ PyIREEPyDMSourceBundle(PyIREEPyDMSourceBundle &&other)
+ : wrapped(other.wrapped) {
+ other.wrapped.ptr = nullptr;
+ }
+ PyIREEPyDMSourceBundle(const PyIREEPyDMSourceBundle &) = delete;
+ ~PyIREEPyDMSourceBundle() {
+ if (wrapped.ptr) ireePyDMSourceBundleDestroy(wrapped);
+ }
+ IREEPyDMSourceBundle wrapped;
+};
+
+struct PyIREEPyDMLoweringOptions {
+ PyIREEPyDMLoweringOptions() : wrapped(ireePyDMLoweringOptionsCreate()) {}
+ PyIREEPyDMLoweringOptions(PyIREEPyDMLoweringOptions &&other)
+ : wrapped(other.wrapped) {
+ other.wrapped.ptr = nullptr;
+ }
+ PyIREEPyDMLoweringOptions(const PyIREEPyDMLoweringOptions &) = delete;
+ ~PyIREEPyDMLoweringOptions() {
+ if (wrapped.ptr) ireePyDMLoweringOptionsDestroy(wrapped);
+ }
+ IREEPyDMLoweringOptions wrapped;
+};
+
+} // namespace
+
PYBIND11_MODULE(_ireeDialects, m) {
m.doc() = "iree-dialects main python extension";
@@ -63,6 +93,37 @@
//===--------------------------------------------------------------------===//
auto iree_pydm_m = m.def_submodule("iree_pydm");
+ py::class_<PyIREEPyDMSourceBundle>(
+ iree_pydm_m, "SourceBundle", py::module_local(),
+ "Contains raw assembly source or a reference to a file")
+ .def_static(
+ "from_asm",
+ [](std::string asmBlob) {
+ return PyIREEPyDMSourceBundle(ireePyDMSourceBundleCreateAsm(
+ {asmBlob.data(), asmBlob.size()}));
+ },
+ py::arg("asm_blob"),
+ "Creates a SourceBundle from an ASM blob (string or bytes)")
+ .def_static(
+ "from_file",
+ [](std::string asmFile) {
+ return PyIREEPyDMSourceBundle(ireePyDMSourceBundleCreateFile(
+ {asmFile.data(), asmFile.size()}));
+ },
+ py::arg("asm_file"),
+ "Creates a SourceBundle from a file containing ASM");
+ py::class_<PyIREEPyDMLoweringOptions>(iree_pydm_m, "LoweringOptions",
+ py::module_local(),
+ "Lowering options to compile to IREE")
+ .def(py::init<>())
+ .def(
+ "link_rtl",
+ [](PyIREEPyDMLoweringOptions &self,
+ PyIREEPyDMSourceBundle &sourceBundle) {
+ ireePyDMLoweringOptionsLinkRtl(self.wrapped, sourceBundle.wrapped);
+ },
+ "Enables linking against a runtime-library module");
+
iree_pydm_m.def(
"register_dialect",
[](MlirContext context, bool load) {
@@ -76,12 +137,13 @@
iree_pydm_m.def(
"build_lower_to_iree_pass_pipeline",
- [](MlirPassManager passManager) {
+ [](MlirPassManager passManager, PyIREEPyDMLoweringOptions &options) {
MlirOpPassManager opPassManager =
mlirPassManagerGetAsOpPassManager(passManager);
- mlirIREEPyDMBuildLowerToIREEPassPipeline(opPassManager);
+ mlirIREEPyDMBuildLowerToIREEPassPipeline(opPassManager,
+ options.wrapped);
},
- py::arg("pass_manager"));
+ py::arg("pass_manager"), py::arg("link_rtl_asm") = py::none());
#define DEFINE_IREEPYDM_NULLARY_TYPE(Name) \
mlir_type_subclass(iree_pydm_m, #Name "Type", mlirTypeIsAIREEPyDM##Name, \
diff --git a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/importer/util.py b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/importer/util.py
index 8eb41b1..d8bfd1c 100644
--- a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/importer/util.py
+++ b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/importer/util.py
@@ -361,8 +361,10 @@
f"implemented for this compiler")
-def create_context() -> ir.Context:
+def create_context(*, debug: bool = False) -> ir.Context:
context = ir.Context()
+ if debug:
+ context.enable_multithreading(False)
d.register_dialect(context)
return context
diff --git a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/__init__.py b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/__init__.py
index 7bea5c5..1255fc0 100644
--- a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/__init__.py
+++ b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/__init__.py
@@ -3,3 +3,22 @@
# 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
+
+import functools as _functools
+
+from typing import Sequence
+from .base import RtlBuilder, RtlModule
+
+
+def _get_std_rtl_modules() -> Sequence[RtlModule]:
+ from .modules import (
+ booleans,
+ numerics,
+ )
+ return [m.RTL_MODULE for m in (booleans, numerics)]
+
+
+STD_RTL_MODULES = _get_std_rtl_modules()
+
+# Source bundle for the standard RTL.
+get_std_rtl_source_bundle = RtlBuilder.lazy_build_source_bundle(STD_RTL_MODULES)
diff --git a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/base.py b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/base.py
index 240317a..ae23206 100644
--- a/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/base.py
+++ b/llvm-external-projects/iree-dialects/python/iree/compiler/dialects/iree_pydm/rtl/base.py
@@ -5,9 +5,10 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Base helpers for the RTL DSL."""
-from typing import List, Optional
+from typing import Callable, List, Optional, Sequence
import functools
+import threading
from ..importer import (
create_context,
@@ -18,8 +19,15 @@
ImportStage,
)
-from ... import builtin as builtin_d
-from .... import (ir, passmanager, transforms as unused_transforms)
+from ... import (
+ builtin as builtin_d,
+ iree_pydm as pydm_d,
+)
+from .... import (
+ ir,
+ passmanager,
+ transforms as unused_transforms,
+)
class RtlModule:
@@ -88,6 +96,36 @@
ir.Location.unknown(context=self.context))
self.module_op = self.root_module.operation
+ @staticmethod
+ def build_modules(rtl_modules: Sequence[RtlModule]) -> bytes:
+ """One shot build modules and return assembly."""
+ b = RtlBuilder()
+ b.emit_modules(rtl_modules)
+ b.optimize()
+ return b.root_module.operation.get_asm(binary=True, enable_debug_info=True)
+
+ @staticmethod
+ def lazy_build_source_bundle(
+ rtl_modules: Sequence[RtlModule]) -> Callable[[], pydm_d.SourceBundle]:
+ """Returns a function to lazily build RTL modules.
+
+ Modules will only be built once and cached for the life of the function.
+ Since RTL asm is typically passed unsafely to compiler passes, caching
+ forever is important.
+ """
+ rtl_modules = tuple(rtl_modules)
+ cache = []
+ lock = threading.Lock()
+
+ def get() -> pydm_d.SourceBundle:
+ with lock:
+ if not cache:
+ asm_blob = RtlBuilder.build_modules(rtl_modules)
+ cache.append(pydm_d.SourceBundle.from_asm(asm_blob))
+ return cache[0]
+
+ return get
+
def emit_module(self, rtl_module: RtlModule):
root_body = self.module_op.regions[0].blocks[0]
with ir.InsertionPoint(root_body), ir.Location.unknown():
@@ -101,6 +139,10 @@
# Getting the symbol implies exporting it into the module.
f.get_or_create_provided_func_symbol(stage)
+ def emit_modules(self, rtl_modules: Sequence[RtlModule]):
+ for rtl_module in rtl_modules:
+ self.emit_module(rtl_module)
+
def optimize(self):
"""Optimizes the RTL modules by running through stage 1 compilation."""
with self.context:
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/constants.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/constants.mlir
new file mode 100644
index 0000000..d8fcb91
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/constants.mlir
@@ -0,0 +1,24 @@
+// RUN: iree-dialects-opt -split-input-file -convert-iree-pydm-to-iree %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @none_constant
+iree_pydm.func @none_constant() -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ // CHECK: %[[CST0:.*]] = constant 0 : i32
+ // CHECK: %[[CST1:.*]] = constant 0 : i32
+ // CHECK: return %[[CST1]], %[[CST0]]
+ %0 = none
+ return %0 : !iree_pydm.none
+}
+
+// CHECK-LABEL: @constant_integer_trunc
+iree_pydm.func @constant_integer_trunc() -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ // CHECK: constant -10 : i32
+ %0 = constant -10 : i64 -> !iree_pydm.integer
+ return %0 : !iree_pydm.integer
+}
+
+// CHECK-LABEL: @constant_real_trunc
+iree_pydm.func @constant_real_trunc() -> (!iree_pydm.exception_result, !iree_pydm.real) {
+ // CHECK: constant -2.000000e+00 : f32
+ %0 = constant -2.0 : f64 -> !iree_pydm.real
+ return %0 : !iree_pydm.real
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/integer_compare.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/integer_compare.mlir
new file mode 100644
index 0000000..dfd387c
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/integer_compare.mlir
@@ -0,0 +1,65 @@
+// RUN: iree-dialects-opt -convert-iree-pydm-to-iree %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @lt
+iree_pydm.func @lt(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi slt, %arg0, %arg1 : i32
+ %0 = apply_compare "lt", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @le
+iree_pydm.func @le(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi sle, %arg0, %arg1 : i32
+ %0 = apply_compare "le", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @eq
+iree_pydm.func @eq(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi eq, %arg0, %arg1 : i32
+ %0 = apply_compare "eq", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @is
+iree_pydm.func @is(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi eq, %arg0, %arg1 : i32
+ %0 = apply_compare "is", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @ne
+iree_pydm.func @ne(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi ne, %arg0, %arg1 : i32
+ %0 = apply_compare "ne", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @isnot
+iree_pydm.func @isnot(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi ne, %arg0, %arg1 : i32
+ %0 = apply_compare "isnot", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @gt
+iree_pydm.func @gt(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi sgt, %arg0, %arg1 : i32
+ %0 = apply_compare "gt", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @ge
+iree_pydm.func @ge(%arg0 : !iree_pydm.integer, %arg1 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpi sge, %arg0, %arg1 : i32
+ %0 = apply_compare "ge", %arg0, %arg1 : !iree_pydm.integer, !iree_pydm.integer
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/real_compare.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/real_compare.mlir
new file mode 100644
index 0000000..83601c1
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/real_compare.mlir
@@ -0,0 +1,65 @@
+// RUN: iree-dialects-opt -convert-iree-pydm-to-iree %s | FileCheck --enable-var-scope --dump-input-filter=all %s
+
+// CHECK-LABEL: @lt
+iree_pydm.func @lt(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf olt, %arg0, %arg1 : f32
+ %0 = apply_compare "lt", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @le
+iree_pydm.func @le(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf ole, %arg0, %arg1 : f32
+ %0 = apply_compare "le", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @eq
+iree_pydm.func @eq(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf oeq, %arg0, %arg1 : f32
+ %0 = apply_compare "eq", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @is
+iree_pydm.func @is(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf oeq, %arg0, %arg1 : f32
+ %0 = apply_compare "is", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @ne
+iree_pydm.func @ne(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf one, %arg0, %arg1 : f32
+ %0 = apply_compare "ne", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @isnot
+iree_pydm.func @isnot(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf one, %arg0, %arg1 : f32
+ %0 = apply_compare "isnot", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @gt
+iree_pydm.func @gt(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf ogt, %arg0, %arg1 : f32
+ %0 = apply_compare "gt", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
+
+// CHECK-LABEL: @ge
+iree_pydm.func @ge(%arg0 : !iree_pydm.real, %arg1 : !iree_pydm.real) -> (!iree_pydm.exception_result, !iree_pydm.bool) {
+ // CHECK: %[[R:.*]] = cmpf oge, %arg0, %arg1 : f32
+ %0 = apply_compare "ge", %arg0, %arg1 : !iree_pydm.real, !iree_pydm.real
+ // CHECK: return {{.*}}, %[[R]]
+ return %0 : !iree_pydm.bool
+}
diff --git a/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/structural.mlir b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/structural.mlir
index 35566e8..46cafc7 100644
--- a/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/structural.mlir
+++ b/llvm-external-projects/iree-dialects/test/iree_pydm/to_iree/structural.mlir
@@ -1,12 +1,27 @@
// RUN: iree-dialects-opt -split-input-file -convert-iree-pydm-to-iree %s | FileCheck --enable-var-scope --dump-input-filter=all %s
-// CHECK-LABEL: @none_constant
-iree_pydm.func @none_constant() -> (!iree_pydm.exception_result, !iree_pydm.none) {
- // CHECK: %[[CST0:.*]] = constant 0 : i32
- // CHECK: %[[CST1:.*]] = constant 0 : i32
- // CHECK: return %[[CST1]], %[[CST0]]
+// CHECK-LABEL: @bool_to_pred
+// NOTE: Also tests cond_br conversion.
+iree_pydm.func @bool_to_pred(%arg0 : !iree_pydm.bool) -> (!iree_pydm.exception_result, !iree_pydm.none) {
+ %0 = bool_to_pred %arg0
+ %1 = none
+ // CHECK: cond_br %arg0
+ cond_br %0, ^bb1, ^bb2
+^bb1:
+ return %1 : !iree_pydm.none
+^bb2:
+ return %1 : !iree_pydm.none
+}
+
+// -----
+// CHECK-LABEL: @br
+iree_pydm.func @br() -> (!iree_pydm.exception_result, !iree_pydm.none) {
%0 = none
- return %0 : !iree_pydm.none
+ // CHECK: br ^bb1({{.*}} : i32)
+ br ^bb1(%0 : !iree_pydm.none)
+ // CHECK: ^bb1(%0: i32):
+^bb1(%1 : !iree_pydm.none):
+ return %1 : !iree_pydm.none
}
// -----
@@ -109,3 +124,25 @@
raise_on_failure %arg0 : !iree_pydm.exception_result
return %arg1 : !iree_pydm.integer
}
+
+// -----
+// CHECK-LABEL: @call_and_visibility
+iree_pydm.func @call_and_visibility(%arg0 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ // CHECK: %[[R:.*]]:2 = call @callee(%arg0) : (i32) -> (i32, i32)
+ %0:2 = call @callee(%arg0) : (!iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer)
+ return %0#1 : !iree_pydm.integer
+}
+
+// CHECK: func private @callee
+iree_pydm.func private @callee(%arg0 : !iree_pydm.integer) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ return %arg0 : !iree_pydm.integer
+}
+
+// -----
+// CHECK-LABEL: @get_type_code
+iree_pydm.func @get_type_code(%arg0 : !iree_pydm.object) -> (!iree_pydm.exception_result, !iree_pydm.integer) {
+ // CHECK: %[[c0:.*]] = constant 0 : index
+ // CHECK: %[[R:.*]] = iree.list.get %arg0[%[[c0]]] : !iree.list<!iree.variant> -> i32
+ %0 = get_type_code %arg0 : !iree_pydm.object
+ return %0 : !iree_pydm.integer
+}
diff --git a/llvm-external-projects/iree-dialects/test/python/iree_pydm/rtl.py b/llvm-external-projects/iree-dialects/test/python/iree_pydm/rtl.py
new file mode 100644
index 0000000..9337da9
--- /dev/null
+++ b/llvm-external-projects/iree-dialects/test/python/iree_pydm/rtl.py
@@ -0,0 +1,6 @@
+# RUN: %PYTHON %s
+
+from iree.compiler.dialects.iree_pydm import rtl
+
+# Ensures that we can compile the standard library to a SourceModule.
+print(rtl.get_std_rtl_source_bundle())