Adding std-to-vm conversion.
Designed to be used as a set of conversion patterns but also exposed as a pass for easy testing. Currently only handles types supported by the VM (I32) and I1 promotion, with rewrites that insert type conversion left for future CLs.
This was harder than I expected due to being near the front of the line in exercising new features:
* DialectConversion of module ops (only supported for nested modules, not top-level modules)
* Type conversions for functions and call ops.
* DRR rewrites not supported for DialectConversion (message sent to list and Lei is going to look into it).
PiperOrigin-RevId: 281205935
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/BUILD b/iree/compiler/Dialect/VM/Conversion/StandardToVM/BUILD
new file mode 100644
index 0000000..1b6d052
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/BUILD
@@ -0,0 +1,27 @@
+package(
+ default_visibility = ["//visibility:public"],
+ licenses = ["notice"], # Apache 2.0
+)
+
+cc_library(
+ name = "StandardToVM",
+ srcs = [
+ "ConvertStandardToVM.cpp",
+ "ConvertStandardToVMPass.cpp",
+ ],
+ hdrs = [
+ "ConvertStandardToVM.h",
+ ],
+ deps = [
+ "//iree/compiler/Dialect",
+ "//iree/compiler/Dialect/VM/IR",
+ "@llvm//:support",
+ "@local_config_mlir//:IR",
+ "@local_config_mlir//:Pass",
+ "@local_config_mlir//:StandardOps",
+ "@local_config_mlir//:Support",
+ "@local_config_mlir//:TransformUtils",
+ "@local_config_mlir//:Transforms",
+ ],
+ alwayslink = 1,
+)
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
new file mode 100644
index 0000000..3ad9eab
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
@@ -0,0 +1,376 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h"
+
+#include "iree/compiler/Dialect/VM/IR/VMOps.h"
+#include "mlir/Dialect/StandardOps/Ops.h"
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/Function.h"
+#include "mlir/IR/Matchers.h"
+#include "mlir/IR/Module.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+namespace iree_compiler {
+
+namespace {
+
+class VmTypeConverter : public TypeConverter {
+ public:
+ static TypeConverter &getInstance() {
+ static VmTypeConverter instance;
+ return instance;
+ }
+
+ private:
+ Type convertType(Type t) override {
+ if (auto integerType = t.dyn_cast<IntegerType>()) {
+ if (integerType.getIntOrFloatBitWidth() == 32) {
+ return t;
+ } else if (integerType.getIntOrFloatBitWidth() == 1) {
+ // Promote i1 -> i32.
+ return IntegerType::get(32, t.getContext());
+ }
+ }
+ // Default to not supporting the type. This dialect is very limited
+ // with respect to valid types and the above should be expanded as
+ // needed.
+ return {};
+ }
+};
+
+class ModuleOpConversion : public OpConversionPattern<ModuleOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ ModuleOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ // Do not attempt to convert the top level module.
+ // This mechanism can only support rewriting non top-level modules.
+ if (!srcOp.getParentOp()) {
+ return matchFailure();
+ }
+
+ StringRef name = srcOp.getName() ? *srcOp.getName() : "module";
+ auto newModuleOp =
+ rewriter.create<IREE::VM::ModuleOp>(srcOp.getLoc(), name);
+ newModuleOp.getBodyRegion().takeBody(srcOp.getBodyRegion());
+
+ // Replace the terminator.
+ Operation *srcTerminator =
+ newModuleOp.getBodyRegion().back().getTerminator();
+ rewriter.setInsertionPointToEnd(&newModuleOp.getBodyRegion().back());
+ rewriter.replaceOpWithNewOp<IREE::VM::ModuleEndOp>(srcTerminator);
+
+ rewriter.eraseOp(srcOp);
+ return matchSuccess();
+ }
+};
+
+class FuncOpConversion : public OpConversionPattern<FuncOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ FuncOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ FunctionType srcFuncType = srcOp.getType();
+ TypeConverter &typeConverter = VmTypeConverter::getInstance();
+ TypeConverter::SignatureConversion signatureConversion(
+ srcOp.getNumArguments());
+
+ // Convert function arguments.
+ for (unsigned i = 0, e = srcFuncType.getNumInputs(); i < e; ++i) {
+ if (failed(typeConverter.convertSignatureArg(i, srcFuncType.getInput(i),
+ signatureConversion))) {
+ return matchFailure();
+ }
+ }
+
+ // Convert function results.
+ SmallVector<Type, 1> convertedResultTypes;
+ if (failed(typeConverter.convertTypes(srcFuncType.getResults(),
+ convertedResultTypes))) {
+ return matchFailure();
+ }
+
+ // Create new function with converted argument and result types.
+ // Note that attributes are dropped. Consider preserving some if needed.
+ auto newFuncType =
+ mlir::FunctionType::get(signatureConversion.getConvertedTypes(),
+ convertedResultTypes, srcOp.getContext());
+ auto newFuncOp = rewriter.create<IREE::VM::FuncOp>(
+ srcOp.getLoc(), srcOp.getName(), newFuncType);
+
+ // Move the body region from src -> new.
+ auto &srcRegion = srcOp.getOperation()->getRegion(0);
+ auto &newRegion = newFuncOp.getOperation()->getRegion(0);
+ newRegion.takeBody(srcRegion);
+
+ // Tell the rewriter to convert the region signature.
+ rewriter.applySignatureConversion(&newFuncOp.getBody(),
+ signatureConversion);
+
+ rewriter.replaceOp(srcOp, llvm::None);
+ return matchSuccess();
+ }
+};
+
+class ReturnOpConversion : public OpConversionPattern<ReturnOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ ReturnOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ rewriter.replaceOpWithNewOp<IREE::VM::ReturnOp>(srcOp, operands);
+ return matchSuccess();
+ }
+};
+
+class ConstantOpConversion : public OpConversionPattern<ConstantOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ ConstantOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ auto integerAttr = srcOp.getValue().dyn_cast<IntegerAttr>();
+ // Only 32bit integer supported for now.
+ if (!integerAttr) {
+ srcOp.emitRemark() << "unsupported const type for dialect";
+ return matchFailure();
+ }
+ int numBits = integerAttr.getType().getIntOrFloatBitWidth();
+ if (numBits != 1 && numBits != 32) {
+ srcOp.emitRemark() << "unsupported bit width for dialect constant";
+ return matchFailure();
+ }
+
+ auto intValue = integerAttr.getInt();
+ if (intValue == 0) {
+ rewriter.replaceOpWithNewOp<IREE::VM::ConstI32ZeroOp>(srcOp);
+ } else {
+ rewriter.replaceOpWithNewOp<IREE::VM::ConstI32Op>(srcOp, intValue);
+ }
+ return matchSuccess();
+ }
+};
+
+class CmpIOpConversion : public OpConversionPattern<CmpIOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ CmpIOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ CmpIOpOperandAdaptor srcAdapter(operands);
+ auto returnType = rewriter.getIntegerType(32);
+ switch (srcOp.getPredicate()) {
+ case CmpIPredicate::eq:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpEQI32Op>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::ne:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpNEI32Op>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::slt:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpLTI32SOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::sle:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpLTEI32SOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::sgt:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpGTI32SOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::sge:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpGTEI32SOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::ult:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpLTI32UOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::ule:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpLTEI32UOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::ugt:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpGTI32UOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ case CmpIPredicate::uge:
+ rewriter.replaceOpWithNewOp<IREE::VM::CmpGTEI32UOp>(
+ srcOp, returnType, srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ }
+ }
+};
+
+template <typename SrcOpTy, typename DstOpTy>
+class BinaryArithmeticOpConversion : public OpConversionPattern<SrcOpTy> {
+ using OpConversionPattern<SrcOpTy>::OpConversionPattern;
+ using OpConversionPattern<SrcOpTy>::matchSuccess;
+
+ PatternMatchResult matchAndRewrite(
+ SrcOpTy srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ typename SrcOpTy::OperandAdaptor srcAdapter(operands);
+
+ rewriter.replaceOpWithNewOp<DstOpTy>(srcOp, srcOp.getType(),
+ srcAdapter.lhs(), srcAdapter.rhs());
+ return matchSuccess();
+ }
+};
+
+template <typename SrcOpTy, typename DstOpTy, unsigned kBits = 32>
+class ShiftArithmeticOpConversion : public OpConversionPattern<SrcOpTy> {
+ using OpConversionPattern<SrcOpTy>::OpConversionPattern;
+ using OpConversionPattern<SrcOpTy>::matchFailure;
+ using OpConversionPattern<SrcOpTy>::matchSuccess;
+
+ PatternMatchResult matchAndRewrite(
+ SrcOpTy srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ typename SrcOpTy::OperandAdaptor srcAdaptor(operands);
+ auto type = srcOp.getType();
+ if (!type.template isa<IntegerType>() ||
+ type.getIntOrFloatBitWidth() != kBits) {
+ return matchFailure();
+ }
+ APInt amount;
+ if (!matchPattern(srcAdaptor.rhs(), m_ConstantInt(&amount))) {
+ return matchFailure();
+ }
+ uint64_t amountRaw = amount.getZExtValue();
+ if (amountRaw > kBits) return matchFailure();
+ IntegerAttr amountAttr =
+ IntegerAttr::get(IntegerType::get(8, srcOp.getContext()), amountRaw);
+ rewriter.replaceOpWithNewOp<DstOpTy>(srcOp, srcOp.getType(),
+ srcAdaptor.lhs(), amountAttr);
+ return matchSuccess();
+ }
+};
+
+class SelectI32OpConversion : public OpConversionPattern<SelectOp> {
+ using OpConversionPattern::OpConversionPattern;
+ static constexpr unsigned kBits = 32;
+
+ PatternMatchResult matchAndRewrite(
+ SelectOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ SelectOpOperandAdaptor srcAdaptor(operands);
+ IntegerType requiredType = IntegerType::get(kBits, srcOp.getContext());
+ if (srcAdaptor.true_value()->getType() != requiredType)
+ return matchFailure();
+
+ rewriter.replaceOpWithNewOp<IREE::VM::SelectI32Op>(
+ srcOp, requiredType, srcAdaptor.condition(), srcAdaptor.true_value(),
+ srcAdaptor.false_value());
+ return matchSuccess();
+ }
+};
+
+class BranchOpConversion : public OpConversionPattern<BranchOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ BranchOp srcOp, ArrayRef<Value *> properOperands,
+ ArrayRef<Block *> destinations, ArrayRef<ArrayRef<Value *>> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ assert(destinations.size() == 1 && operands.size() == 1);
+ rewriter.replaceOpWithNewOp<IREE::VM::BranchOp>(srcOp, destinations[0],
+ operands[0]);
+ return matchSuccess();
+ }
+};
+
+class CondBranchOpConversion : public OpConversionPattern<CondBranchOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ CondBranchOp srcOp, ArrayRef<Value *> properOperands,
+ ArrayRef<Block *> destinations, ArrayRef<ArrayRef<Value *>> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ assert(destinations.size() == 2 && operands.size() == 2);
+ CondBranchOpOperandAdaptor srcAdaptor(properOperands);
+ rewriter.replaceOpWithNewOp<IREE::VM::CondBranchOp>(
+ srcOp, srcAdaptor.condition(), destinations[0], operands[0], // true
+ destinations[1], operands[1]); // false;
+ return matchSuccess();
+ }
+};
+
+class CallOpConversion : public OpConversionPattern<CallOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ PatternMatchResult matchAndRewrite(
+ CallOp srcOp, ArrayRef<Value *> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ CallOpOperandAdaptor srcAdaptor(operands);
+ // Convert function result types. The conversion framework will ensure
+ // that the callee has been equivalently converted.
+ auto &typeConverter = VmTypeConverter::getInstance();
+ SmallVector<Type, 4> resultTypes;
+ for (auto resultType : srcOp.getResultTypes()) {
+ resultType = typeConverter.convertType(resultType);
+ if (!resultType) {
+ return matchFailure();
+ }
+ resultTypes.push_back(resultType);
+ }
+ rewriter.replaceOpWithNewOp<IREE::VM::CallOp>(
+ srcOp, srcOp.getCallee(), resultTypes, srcAdaptor.operands());
+
+ return matchSuccess();
+ }
+};
+
+} // namespace
+
+void populateStandardToVMPatterns(MLIRContext *context,
+ OwningRewritePatternList &patterns) {
+ patterns
+ .insert<BranchOpConversion, CallOpConversion, CmpIOpConversion,
+ CondBranchOpConversion, ConstantOpConversion, ModuleOpConversion,
+ FuncOpConversion, ReturnOpConversion, SelectI32OpConversion>(
+ context);
+
+ // Binary arithmetic ops
+ patterns.insert<BinaryArithmeticOpConversion<AddIOp, IREE::VM::AddI32Op>,
+ BinaryArithmeticOpConversion<DivISOp, IREE::VM::DivI32SOp>,
+ BinaryArithmeticOpConversion<DivIUOp, IREE::VM::DivI32UOp>,
+ BinaryArithmeticOpConversion<MulIOp, IREE::VM::MulI32Op>,
+ BinaryArithmeticOpConversion<RemISOp, IREE::VM::RemI32SOp>,
+ BinaryArithmeticOpConversion<RemIUOp, IREE::VM::RemI32UOp>,
+ BinaryArithmeticOpConversion<SubIOp, IREE::VM::SubI32Op>,
+ BinaryArithmeticOpConversion<AndOp, IREE::VM::AndI32Op>,
+ BinaryArithmeticOpConversion<OrOp, IREE::VM::OrI32Op>,
+ BinaryArithmeticOpConversion<XOrOp, IREE::VM::XorI32Op>>(
+ context);
+
+ // Shift ops
+ // TODO(laurenzo): The standard dialect is missing shr ops. Add once in place.
+ patterns.insert<ShiftArithmeticOpConversion<ShlISOp, IREE::VM::ShlI32Op>>(
+ context);
+}
+
+TypeConverter *getStandardToVMTypeConverter() {
+ return &VmTypeConverter::getInstance();
+}
+
+} // namespace iree_compiler
+} // namespace mlir
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h
new file mode 100644
index 0000000..7c3e787
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h
@@ -0,0 +1,35 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef IREE_COMPILER_DIALECT_VM_CONVERSION_STANDARDTOVM_CONVERTSTANDARDTOVM_H_
+#define IREE_COMPILER_DIALECT_VM_CONVERSION_STANDARDTOVM_CONVERTSTANDARDTOVM_H_
+
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+namespace iree_compiler {
+
+// Appends standard dialect to vm dialect patterns to the given pattern list.
+void populateStandardToVMPatterns(MLIRContext *context,
+ OwningRewritePatternList &patterns);
+
+// Gets the TypeConverter that must be used for legalizing the standard to
+// VM dialect.
+TypeConverter *getStandardToVMTypeConverter();
+
+} // namespace iree_compiler
+} // namespace mlir
+
+#endif // IREE_COMPILER_DIALECT_VM_CONVERSION_STANDARDTOVM_CONVERTSTANDARDTOVM_H_
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMPass.cpp b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMPass.cpp
new file mode 100644
index 0000000..52f63b6
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMPass.cpp
@@ -0,0 +1,54 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h"
+#include "iree/compiler/Dialect/VM/IR/VMDialect.h"
+#include "mlir/Dialect/StandardOps/Ops.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+namespace iree_compiler {
+
+namespace {
+
+// A pass converting MLIR Standard operations into the IREE VM dialect.
+// Used only for testing as in the common case we only rely on rewrite patterns.
+class ConvertStandardToVMPass : public ModulePass<ConvertStandardToVMPass> {
+ void runOnModule() override {
+ OwningRewritePatternList patterns;
+ auto module = getModule();
+
+ populateStandardToVMPatterns(&getContext(), patterns);
+ ConversionTarget target(getContext());
+ target.addLegalDialect<IREE::VM::VMDialect>();
+ target.addIllegalDialect<StandardOpsDialect>();
+
+ // NOTE: we allow other dialects besides just VM during this pass as we are
+ // only trying to eliminate the std ops. When used as part of a larger set
+ // of rewrites a full conversion should be used instead.
+ if (failed(applyPartialConversion(module, target, patterns,
+ getStandardToVMTypeConverter()))) {
+ return signalPassFailure();
+ }
+ }
+};
+
+} // namespace
+
+static PassRegistration<ConvertStandardToVMPass> pass(
+ "iree-convert-std-to-vm", "Convert Standard Ops to the IREE VM dialect");
+
+} // namespace iree_compiler
+} // namespace mlir
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/BUILD b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/BUILD
new file mode 100644
index 0000000..dc90cdc
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/BUILD
@@ -0,0 +1,14 @@
+load("//iree:build_defs.bzl", "iree_glob_lit_tests", "iree_setup_lit_package")
+
+package(
+ default_visibility = ["//visibility:public"],
+ licenses = ["notice"], # Apache 2.0
+)
+
+iree_setup_lit_package(
+ data = [
+ "//iree/tools:iree-opt",
+ ],
+)
+
+iree_glob_lit_tests()
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/arithmetic_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/arithmetic_ops.mlir
new file mode 100644
index 0000000..d9f3984
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/arithmetic_ops.mlir
@@ -0,0 +1,202 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// CHECK-LABEL: @t001_addi
+module @t001_addi {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.add.i32 [[ARG0]], [[ARG1]]
+ %0 = addi %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t002_divis
+module @t002_divis {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.div.i32.s [[ARG0]], [[ARG1]]
+ %0 = divis %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t002_diviu
+module @t002_diviu {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.div.i32.u [[ARG0]], [[ARG1]]
+ %0 = diviu %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t003_muli
+module @t003_muli {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.mul.i32 [[ARG0]], [[ARG1]]
+ %0 = muli %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t004_remis
+module @t004_remis {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.rem.i32.s [[ARG0]], [[ARG1]]
+ %0 = remis %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t005_remiu
+module @t005_remiu {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.rem.i32.u [[ARG0]], [[ARG1]]
+ %0 = remiu %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t006_subi
+module @t006_subi {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.sub.i32 [[ARG0]], [[ARG1]]
+ %0 = subi %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t007_and
+module @t007_and {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.and.i32 [[ARG0]], [[ARG1]]
+ %0 = and %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t008_or
+module @t008_or {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.or.i32 [[ARG0]], [[ARG1]]
+ %0 = or %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t009_xor
+module @t009_xor {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1: i32) -> (i32) {
+ // CHECK: vm.xor.i32 [[ARG0]], [[ARG1]]
+ %0 = xor %arg0, %arg1 : i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t010_shift
+module @t010_shift {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32) -> (i32) {
+ %cst = constant 3 : i32
+ // CHECK: vm.shl.i32 [[ARG0]], 3 : i32
+ %1 = shlis %arg0, %cst : i32
+ return %1 : i32
+ }
+}
+
+}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/assignment_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/assignment_ops.mlir
new file mode 100644
index 0000000..7f5a412
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/assignment_ops.mlir
@@ -0,0 +1,36 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// CHECK-LABEL: @t001_cmp_select
+module @t001_cmp_select {
+
+module @my_module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i32, %arg1 : i32) -> (i32) {
+ // Note that in std, cmp returns an i1 and this relies on the dialect
+ // conversion framework promoting that to i32.
+ // CHECK: [[CMP:%[a-zA-Z0-9]+]] = vm.cmp.eq.i32
+ %1 = cmpi "eq", %arg0, %arg1 : i32
+ // CHECK: vm.select.i32 [[CMP]], [[ARG0]], [[ARG1]] : i32
+ %2 = select %1, %arg0, %arg1 : i32
+ return %2 : i32
+ }
+}
+
+}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/comparison_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/comparison_ops.mlir
new file mode 100644
index 0000000..482e42c
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/comparison_ops.mlir
@@ -0,0 +1,185 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// CHECK-LABEL: @t001_cmp_eq_i32
+module @t001_cmp_eq_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.eq.i32 [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "eq", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t002_cmp_ne_i32
+module @t002_cmp_ne_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.ne.i32 [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "ne", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t003_cmp_slt_i32
+module @t003_cmp_slt_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.lt.i32.s [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "slt", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t004_cmp_sle_i32
+module @t004_cmp_sle_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.lte.i32.s [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "sle", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t005_cmp_sgt_i32
+module @t005_cmp_sgt_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.gt.i32.s [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "sgt", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t006_cmp_sge_i32
+module @t006_cmp_sge_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.gte.i32.s [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "sge", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t007_cmp_ult_i32
+module @t007_cmp_ult_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.lt.i32.u [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "ult", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t008_cmp_ule_i32
+module @t008_cmp_ule_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.lte.i32.u [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "ule", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t009_cmp_ugt_i32
+module @t009_cmp_ugt_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.gt.i32.u [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "ugt", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t010_cmp_uge_i32
+module @t010_cmp_uge_i32 {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0: i32, %arg1 : i32) -> (i1) {
+ // CHECK: vm.cmp.gte.i32.u [[ARG0]], [[ARG1]] : i32
+ %1 = cmpi "uge", %arg0, %arg1 : i32
+ return %1 : i1
+ }
+}
+
+}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/const_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/const_ops.mlir
new file mode 100644
index 0000000..c39357b
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/const_ops.mlir
@@ -0,0 +1,43 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// CHECK-LABEL: @t001_const.i32.nonzero
+module @t001_const.i32.nonzero {
+
+module {
+ func @non_zero() -> (i32) {
+ // CHECK: vm.const.i32 1 : i32
+ %1 = constant 1 : i32
+ return %1 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t001_const.i32.zero
+module @t001_const.i32.zero {
+
+module {
+ func @zero() -> (i32) {
+ // CHECK: vm.const.i32.zero : i32
+ %1 = constant 0 : i32
+ return %1 : i32
+ }
+}
+
+}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/control_flow_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/control_flow_ops.mlir
new file mode 100644
index 0000000..7a97050
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/control_flow_ops.mlir
@@ -0,0 +1,122 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// CHECK-LABEL: @t001_br
+module @t001_br {
+
+module {
+ func @my_fn(%arg0 : i32) -> (i32) {
+ // CHECK: vm.br ^bb1
+ br ^bb1
+ ^bb1:
+ return %arg0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t002_cond_br
+module @t002_cond_br {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> (i32) {
+ // CHECK: vm.cond_br [[ARG0]], ^bb1, ^bb2
+ cond_br %arg0, ^bb1, ^bb2
+ ^bb1:
+ return %arg1 : i32
+ ^bb2:
+ return %arg2 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t003_br_args
+module @t003_br_args {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i32, %arg1 : i32) -> (i32) {
+ // CHECK: vm.br ^bb1([[ARG0]], [[ARG1]] : i32, i32)
+ br ^bb1(%arg0, %arg1 : i32, i32)
+ ^bb1(%0 : i32, %1 : i32):
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t004_cond_br_args
+module @t004_cond_br_args {
+
+module {
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG1:%[a-zA-Z0-9]+]]
+ // CHECK-SAME: [[ARG2:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> (i32) {
+ // CHECK: vm.cond_br [[ARG0]], ^bb1([[ARG1]] : i32), ^bb2([[ARG2]] : i32)
+ cond_br %arg0, ^bb1(%arg1 : i32), ^bb2(%arg2 : i32)
+ ^bb1(%0 : i32):
+ return %0 : i32
+ ^bb2(%1 : i32):
+ return %1 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t005_call
+module @t005_call {
+
+module {
+ func @import_fn(%arg0 : i32) -> i32
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i32) -> (i32) {
+ // CHECK: vm.call @import_fn([[ARG0]]) : (i32) -> i32
+ %0 = call @import_fn(%arg0) : (i32) -> i32
+ return %0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t005_call_int_promotion
+module @t005_call_int_promotion {
+
+module {
+ func @import_fn(%arg0 : i1) -> i1
+ // CHECK: func @my_fn
+ // CHECK-SAME: [[ARG0:%[a-zA-Z0-9]+]]
+ func @my_fn(%arg0 : i1) -> (i1) {
+ // CHECK: vm.call @import_fn([[ARG0]]) : (i32) -> i32
+ %0 = call @import_fn(%arg0) : (i1) -> i1
+ return %0 : i1
+ }
+}
+
+}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/structural_ops.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/structural_ops.mlir
new file mode 100644
index 0000000..bcf2ef7
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/structural_ops.mlir
@@ -0,0 +1,56 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | FileCheck %s --dump-input=fail
+
+// -----
+// Checks literal specifics of structural transforms (more verbose checks
+// than usual since the conversion code is manual).
+// CHECK-LABEL: @t001_module_all_options
+module @t001_module_all_options {
+
+// CHECK: module @my_module {
+module @my_module {
+ // CHECK: vm.func @my_fn([[ARG0:%[a-zA-Z0-9]+]]: i32) -> i32
+ func @my_fn(%arg0: i32) -> (i32) {
+ // CHECK: vm.return [[ARG0]] : i32
+ return %arg0 : i32
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t002_no_args_results
+module @t002_no_args_results {
+
+module @my_module {
+ // CHECK: vm.func @my_fn() {
+ func @my_fn() -> () {
+ // CHECK: vm.return
+ return
+ }
+}
+
+}
+
+// -----
+// CHECK-LABEL: @t003_unnamed_module
+module @t003_unnamed_module {
+
+// CHECK: module @module {
+module {
+}
+
+}
diff --git a/iree/tools/BUILD b/iree/tools/BUILD
index b0d1bdf..f9ae673 100644
--- a/iree/tools/BUILD
+++ b/iree/tools/BUILD
@@ -33,6 +33,7 @@
"//integrations/tensorflow/compiler:tensorflow",
"//iree/compiler/Dialect",
"//iree/compiler/Dialect/VM/Analysis",
+ "//iree/compiler/Dialect/VM/Conversion/StandardToVM",
"//iree/compiler/Dialect/VM/IR",
"//iree/compiler/Dialect/VM/Transforms",
"//iree/compiler/Transforms",