From 3007c214ab1e4667fee0e4817bc8dc776ccf21a0 Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Tue, 23 Mar 2021 18:04:05 +0000 Subject: [PATCH 1/7] Sort descriptors as expected by the native module --- .../Dialect/VM/Target/C/CMakeLists.txt | 1 + .../Dialect/VM/Target/C/CModuleTarget.cpp | 47 +++++++++++++++++-- iree/vm/test/arithmetic_ops.mlir | 22 ++++----- iree/vm/test/arithmetic_ops_i64.mlir | 22 ++++----- iree/vm/test/assignment_ops.mlir | 2 - iree/vm/test/assignment_ops_i64.mlir | 2 - iree/vm/test/conversion_ops.mlir | 6 +-- iree/vm/test/conversion_ops_i64.mlir | 1 - iree/vm/test/shift_ops.mlir | 2 +- iree/vm/test/shift_ops_i64.mlir | 2 +- 10 files changed, 67 insertions(+), 40 deletions(-) diff --git a/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt b/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt index a98971d773b0..632aecf3f5c2 100644 --- a/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt +++ b/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt @@ -35,6 +35,7 @@ if(${IREE_ENABLE_EMITC}) iree::compiler::Dialect::VM::IR iree::compiler::Dialect::VM::Conversion::VMToEmitC iree::compiler::Dialect::VM::Target::CallingConventionUtils + iree::base::api INCLUDES "${PROJECT_SOURCE_DIR}/third_party/mlir-emitc/include" PUBLIC diff --git a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp index 894dea826982..7cb27450bba8 100644 --- a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp @@ -15,6 +15,7 @@ #include "iree/compiler/Dialect/VM/Target/C/CModuleTarget.h" #include "emitc/Target/Cpp.h" +#include "iree/base/api.h" #include "iree/compiler/Dialect/IREE/IR/IREEOps.h" #include "iree/compiler/Dialect/IREE/Transforms/Passes.h" #include "iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.h" @@ -300,12 +301,22 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, }; // exports - // TODO: Add sorting the module export table by name. This is already - // supported in the ByteCodeModuleTarget using `llvm::sort`. std::string exportName = moduleName + "_exports_"; output << "static const iree_vm_native_export_descriptor_t " << exportName << "[] = {\n"; - for (auto exportOp : moduleOp.getOps()) { + + // sort export ops + SmallVector exportOps( + moduleOp.getOps()); + llvm::sort(exportOps, [](auto &lhs, auto &rhs) { + iree_string_view_t lhsName = iree_make_string_view( + lhs.export_name().data(), lhs.export_name().size()); + iree_string_view_t rhsName = iree_make_string_view( + rhs.export_name().data(), rhs.export_name().size()); + return iree_string_view_compare(lhsName, rhsName) < 0; + }); + + for (auto exportOp : exportOps) { auto funcOp = symbolTable.lookup(exportOp.function_ref()); if (!funcOp) { return exportOp.emitError("Couldn't find referenced FuncOp"); @@ -327,7 +338,19 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, std::string importName = moduleName + "_imports_"; output << "static const iree_vm_native_import_descriptor_t " << importName << "[] = {\n"; - for (auto importOp : moduleOp.getOps()) { + + // sort import ops + SmallVector importOps( + moduleOp.getOps()); + llvm::sort(importOps, [](auto &lhs, auto &rhs) { + iree_string_view_t lhsName = + iree_make_string_view(lhs.getName().data(), lhs.getName().size()); + iree_string_view_t rhsName = + iree_make_string_view(rhs.getName().data(), rhs.getName().size()); + return iree_string_view_compare(lhsName, rhsName) < 0; + }); + + for (auto importOp : importOps) { output << "{" << printCStringView(importOp.getName().str()) << "},\n"; } output << "};\n"; @@ -337,7 +360,21 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, std::string functionName = moduleName + "_funcs_"; output << "static const iree_vm_native_function_ptr_t " << functionName << "[] = {\n"; - for (auto funcOp : moduleOp.getOps()) { + + // sort func ops + SmallVector funcOps(moduleOp.getOps()); + llvm::sort(funcOps, [&moduleOp](auto &lhs, auto &rhs) { + std::string lhsStr = + buildFunctionName(moduleOp, lhs, /*implSufffix=*/false); + std::string rhsStr = + buildFunctionName(moduleOp, rhs, /*implSufffix=*/false); + iree_string_view_t lhsName = + iree_make_string_view(lhsStr.data(), lhsStr.size()); + iree_string_view_t rhsName = + iree_make_string_view(rhsStr.data(), rhsStr.size()); + return iree_string_view_compare(lhsName, rhsName) < 0; + }); + for (auto funcOp : funcOps) { output << "{" << "(iree_vm_native_function_shim_t)"; diff --git a/iree/vm/test/arithmetic_ops.mlir b/iree/vm/test/arithmetic_ops.mlir index 43586980d75e..7d9edac52d4a 100644 --- a/iree/vm/test/arithmetic_ops.mlir +++ b/iree/vm/test/arithmetic_ops.mlir @@ -4,19 +4,7 @@ vm.module @arithmetic_ops { // Native integer arithmetic //===--------------------------------------------------------------------===// - // TODO: The CModuleTarget enforces exports to be ordered. vm.export @test_add_i32 - vm.export @test_and_i32 - vm.export @test_div_i32s - vm.export @test_div_i32u - vm.export @test_mul_i32 - vm.export @test_not_i32 - vm.export @test_or_i32 - vm.export @test_rem_i32s - vm.export @test_rem_i32u - vm.export @test_sub_i32 - vm.export @test_xor_i32 - vm.func @test_add_i32() { %c1 = vm.const.i32 1 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -26,6 +14,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_sub_i32 vm.func @test_sub_i32() { %c1 = vm.const.i32 3 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -37,6 +26,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_mul_i32 vm.func @test_mul_i32() { %c1 = vm.const.i32 2 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -46,6 +36,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_div_i32s vm.func @test_div_i32s() { %c1 = vm.const.i32 4 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -57,6 +48,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_div_i32u vm.func @test_div_i32u() { %c1 = vm.const.i32 4 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -68,6 +60,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_rem_i32s vm.func @test_rem_i32s() { %c1 = vm.const.i32 -3 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -79,6 +72,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_rem_i32u vm.func @test_rem_i32u() { %c1 = vm.const.i32 3 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -90,6 +84,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_not_i32 vm.func @test_not_i32() { %c1 = vm.const.i32 0 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -99,6 +94,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_and_i32 vm.func @test_and_i32() { %c1 = vm.const.i32 5 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -110,6 +106,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_or_i32 vm.func @test_or_i32() { %c1 = vm.const.i32 5 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -121,6 +118,7 @@ vm.module @arithmetic_ops { vm.return } + vm.export @test_xor_i32 vm.func @test_xor_i32() { %c1 = vm.const.i32 5 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 diff --git a/iree/vm/test/arithmetic_ops_i64.mlir b/iree/vm/test/arithmetic_ops_i64.mlir index d23be931462b..5058c3350ceb 100644 --- a/iree/vm/test/arithmetic_ops_i64.mlir +++ b/iree/vm/test/arithmetic_ops_i64.mlir @@ -4,19 +4,7 @@ vm.module @arithmetic_ops_i64 { // ExtI64: Native integer arithmetic //===--------------------------------------------------------------------===// - // TODO: The CModuleTarget enforces exports to be ordered. vm.export @test_add_i64 - vm.export @test_and_i64 - vm.export @test_div_i64s - vm.export @test_div_i64u - vm.export @test_mul_i64 - vm.export @test_not_i64 - vm.export @test_or_i64 - vm.export @test_rem_i64s - vm.export @test_rem_i64u - vm.export @test_sub_i64 - vm.export @test_xor_i64 - vm.func @test_add_i64() { %c1 = vm.const.i64 1 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -26,6 +14,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_sub_i64 vm.func @test_sub_i64() { %c1 = vm.const.i64 3 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -37,6 +26,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_mul_i64 vm.func @test_mul_i64() { %c1 = vm.const.i64 2 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -46,6 +36,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_div_i64s vm.func @test_div_i64s() { %c1 = vm.const.i64 4 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -57,6 +48,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_div_i64u vm.func @test_div_i64u() { %c1 = vm.const.i64 4 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -68,6 +60,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_rem_i64s vm.func @test_rem_i64s() { %c1 = vm.const.i64 -3 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -79,6 +72,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_rem_i64u vm.func @test_rem_i64u() { %c1 = vm.const.i64 3 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -90,6 +84,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_not_i64 vm.func @test_not_i64() { %c1 = vm.const.i64 0 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -99,6 +94,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_and_i64 vm.func @test_and_i64() { %c1 = vm.const.i64 5 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -110,6 +106,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_or_i64 vm.func @test_or_i64() { %c1 = vm.const.i64 5 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 @@ -121,6 +118,7 @@ vm.module @arithmetic_ops_i64 { vm.return } + vm.export @test_xor_i64 vm.func @test_xor_i64() { %c1 = vm.const.i64 5 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 diff --git a/iree/vm/test/assignment_ops.mlir b/iree/vm/test/assignment_ops.mlir index 544487d2a76f..ef10708d914c 100644 --- a/iree/vm/test/assignment_ops.mlir +++ b/iree/vm/test/assignment_ops.mlir @@ -4,9 +4,7 @@ vm.module @assignment_ops { // Conditional assignment //===--------------------------------------------------------------------===// - // TODO: The CModuleTarget enforces exports to be ordered. vm.export @test_select_i32 - vm.func @test_select_i32() { %c0 = vm.const.i32 0 : i32 %c0dno = iree.do_not_optimize(%c0) : i32 diff --git a/iree/vm/test/assignment_ops_i64.mlir b/iree/vm/test/assignment_ops_i64.mlir index 895efb0dec28..2e451ad959fa 100644 --- a/iree/vm/test/assignment_ops_i64.mlir +++ b/iree/vm/test/assignment_ops_i64.mlir @@ -4,9 +4,7 @@ vm.module @assignment_ops_i64 { // ExtI64: Conditional assignment //===--------------------------------------------------------------------===// - // TODO: The CModuleTarget enforces exports to be ordered. vm.export @test_select_i64 - vm.func @test_select_i64() { %c0 = vm.const.i32 0 : i32 %c0dno = iree.do_not_optimize(%c0) : i32 diff --git a/iree/vm/test/conversion_ops.mlir b/iree/vm/test/conversion_ops.mlir index 9c654f24f5a1..7f06df80ad6f 100644 --- a/iree/vm/test/conversion_ops.mlir +++ b/iree/vm/test/conversion_ops.mlir @@ -4,10 +4,7 @@ vm.module @conversion_ops { // Casting and type conversion/emulation //===----------------------------------------------------------------------===// - // TODO: The CModuleTarget enforces exports to be ordered. - vm.export @test_trunc_i32_i16 vm.export @test_trunc_i32_i8 - vm.func @test_trunc_i32_i8() { %c1 = vm.const.i32 2147483647 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 @@ -17,7 +14,8 @@ vm.module @conversion_ops { vm.return } - vm.func @test_trunc_i32_i16() { + vm.export @test_trunc_i32_i16 + vm.func @test_trunc_i32_i16() { %c1 = vm.const.i32 2147483647 : i32 %c1dno = iree.do_not_optimize(%c1) : i32 %v = vm.trunc.i32.i16 %c1dno : i32 -> i32 diff --git a/iree/vm/test/conversion_ops_i64.mlir b/iree/vm/test/conversion_ops_i64.mlir index 6d420c98a856..25cb3903b33d 100644 --- a/iree/vm/test/conversion_ops_i64.mlir +++ b/iree/vm/test/conversion_ops_i64.mlir @@ -5,7 +5,6 @@ vm.module @conversion_ops_i64 { //===----------------------------------------------------------------------===// vm.export @test_trunc_i64_i32 - vm.func @test_trunc_i64_i32() { %c1 = vm.const.i64 9223372036854775807 : i64 %c1dno = iree.do_not_optimize(%c1) : i64 diff --git a/iree/vm/test/shift_ops.mlir b/iree/vm/test/shift_ops.mlir index 34a54a2234bf..a5dc6da7320a 100644 --- a/iree/vm/test/shift_ops.mlir +++ b/iree/vm/test/shift_ops.mlir @@ -20,7 +20,7 @@ vm.module @shift_ops { %c1dno = iree.do_not_optimize(%c1) : i32 %v = vm.shr.i32.s %c1dno, 2 : i32 %c2 = vm.const.i32 -1 : i32 - vm.check.eq %v, %c2, "-1>>-1=-1" : i32 + vm.check.eq %v, %c2, "-1>>2=-1" : i32 vm.return } diff --git a/iree/vm/test/shift_ops_i64.mlir b/iree/vm/test/shift_ops_i64.mlir index 04da8af22fa3..a9ae22a7aefc 100644 --- a/iree/vm/test/shift_ops_i64.mlir +++ b/iree/vm/test/shift_ops_i64.mlir @@ -20,7 +20,7 @@ vm.module @shift_ops_i64 { %c1dno = iree.do_not_optimize(%c1) : i64 %v = vm.shr.i64.s %c1dno, 2 : i64 %c2 = vm.const.i64 -1 : i64 - vm.check.eq %v, %c2, "-1>>-1=-1" : i64 + vm.check.eq %v, %c2, "-1>>2=-1" : i64 vm.return } From e831d66a1f4166992bdc667eacc75a9fb7fc4839 Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Wed, 24 Mar 2021 08:42:40 +0000 Subject: [PATCH 2/7] Simplify comparison functions --- .../Dialect/VM/Target/C/CMakeLists.txt | 1 - .../Dialect/VM/Target/C/CModuleTarget.cpp | 19 +++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt b/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt index 632aecf3f5c2..a98971d773b0 100644 --- a/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt +++ b/iree/compiler/Dialect/VM/Target/C/CMakeLists.txt @@ -35,7 +35,6 @@ if(${IREE_ENABLE_EMITC}) iree::compiler::Dialect::VM::IR iree::compiler::Dialect::VM::Conversion::VMToEmitC iree::compiler::Dialect::VM::Target::CallingConventionUtils - iree::base::api INCLUDES "${PROJECT_SOURCE_DIR}/third_party/mlir-emitc/include" PUBLIC diff --git a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp index 7cb27450bba8..71367b7e83df 100644 --- a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp @@ -15,7 +15,6 @@ #include "iree/compiler/Dialect/VM/Target/C/CModuleTarget.h" #include "emitc/Target/Cpp.h" -#include "iree/base/api.h" #include "iree/compiler/Dialect/IREE/IR/IREEOps.h" #include "iree/compiler/Dialect/IREE/Transforms/Passes.h" #include "iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.h" @@ -309,11 +308,7 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, SmallVector exportOps( moduleOp.getOps()); llvm::sort(exportOps, [](auto &lhs, auto &rhs) { - iree_string_view_t lhsName = iree_make_string_view( - lhs.export_name().data(), lhs.export_name().size()); - iree_string_view_t rhsName = iree_make_string_view( - rhs.export_name().data(), rhs.export_name().size()); - return iree_string_view_compare(lhsName, rhsName) < 0; + return lhs.export_name().compare(rhs.export_name()) < 0; }); for (auto exportOp : exportOps) { @@ -343,11 +338,7 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, SmallVector importOps( moduleOp.getOps()); llvm::sort(importOps, [](auto &lhs, auto &rhs) { - iree_string_view_t lhsName = - iree_make_string_view(lhs.getName().data(), lhs.getName().size()); - iree_string_view_t rhsName = - iree_make_string_view(rhs.getName().data(), rhs.getName().size()); - return iree_string_view_compare(lhsName, rhsName) < 0; + return lhs.getName().compare(rhs.getName()) < 0; }); for (auto importOp : importOps) { @@ -368,11 +359,7 @@ static LogicalResult buildModuleDescriptors(IREE::VM::ModuleOp &moduleOp, buildFunctionName(moduleOp, lhs, /*implSufffix=*/false); std::string rhsStr = buildFunctionName(moduleOp, rhs, /*implSufffix=*/false); - iree_string_view_t lhsName = - iree_make_string_view(lhsStr.data(), lhsStr.size()); - iree_string_view_t rhsName = - iree_make_string_view(rhsStr.data(), rhsStr.size()); - return iree_string_view_compare(lhsName, rhsName) < 0; + return lhsStr.compare(rhsStr) < 0; }); for (auto funcOp : funcOps) { output << "{" From fa3a1cf4123db0a2f10d3a391ca1777230afac27 Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Tue, 23 Mar 2021 15:55:35 +0000 Subject: [PATCH 3/7] Support control flow ops in the vm to emitc path --- .../Conversion/VMToEmitC/ConvertVMToEmitC.cpp | 11 +- .../Dialect/VM/Target/C/CModuleTarget.cpp | 137 ++++++++++++++++-- iree/vm/ops.h | 20 +-- iree/vm/test/emitc/CMakeLists.txt | 13 ++ iree/vm/test/emitc/module_test.cc | 2 + 5 files changed, 156 insertions(+), 27 deletions(-) diff --git a/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp b/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp index 3173aa304d65..7a4ddbbac843 100644 --- a/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp +++ b/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp @@ -280,12 +280,6 @@ void populateVMToCPatterns(MLIRContext *context, patterns.insert>(context, "vm_cmp_nz_i32"); - // Check - // TODO(simon-camp): These conversions to macro calls should be deleted once - // support for control flow ops has landed in the c module target - patterns.insert>(context, - "VM_CHECK_EQ"); - // ExtI64: Constants patterns.insert>(context); patterns.insert>(context); @@ -369,7 +363,12 @@ class ConvertVMToEmitCPass target.addLegalOp(); // Control flow ops + target.addLegalOp(); target.addLegalOp(); + target.addLegalOp(); + // Note: We translate the fail op to two function calls in the end, but we + // can't simply convert it here because it is a terminator. + target.addLegalOp(); target.addLegalOp(); if (failed( diff --git a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp index 71367b7e83df..5bfec123785e 100644 --- a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp @@ -147,11 +147,88 @@ static LogicalResult initializeGlobals(IREE::VM::ModuleOp moduleOp, return success(); } +static LogicalResult translateBranchOp(IREE::VM::BranchOp branchOp, + mlir::emitc::CppEmitter &emitter) { + auto &output = emitter.ostream(); + Block &successor = *branchOp.getSuccessor(); + + for (auto pair : + llvm::zip(branchOp.getOperands(), successor.getArguments())) { + auto &operand = std::get<0>(pair); + auto &argument = std::get<1>(pair); + output << emitter.getOrCreateName(argument) << " = " + << emitter.getOrCreateName(operand) << ";\n"; + } + + output << "goto "; + if (!(emitter.hasBlockLabel(successor))) { + return branchOp.emitOpError() << "Unable to find label for successor block"; + } + output << emitter.getOrCreateName(successor) << ";\n"; + return success(); +} + static LogicalResult translateCallOpToC(IREE::VM::CallOp callOp, mlir::emitc::CppEmitter &emitter) { return success(); } +static LogicalResult translateCondBranchOp(IREE::VM::CondBranchOp condBranchOp, + mlir::emitc::CppEmitter &emitter) { + llvm::raw_ostream &output = emitter.ostream(); + + Block &trueSuccessor = *condBranchOp.getTrueDest(); + Block &falseSuccessor = *condBranchOp.getFalseDest(); + + output << "if (" << emitter.getOrCreateName(condBranchOp.getCondition()) + << ") {\n"; + + // If condition is true. + for (auto pair : llvm::zip(condBranchOp.getTrueOperands(), + trueSuccessor.getArguments())) { + auto &operand = std::get<0>(pair); + auto &argument = std::get<1>(pair); + output << emitter.getOrCreateName(argument) << " = " + << emitter.getOrCreateName(operand) << ";\n"; + } + + output << "goto "; + if (!(emitter.hasBlockLabel(trueSuccessor))) { + return condBranchOp.emitOpError() + << "Unable to find label for successor block"; + } + output << emitter.getOrCreateName(trueSuccessor) << ";\n"; + output << "} else {\n"; + // If condition is false. + for (auto pair : llvm::zip(condBranchOp.getFalseOperands(), + falseSuccessor.getArguments())) { + auto &operand = std::get<0>(pair); + auto &argument = std::get<1>(pair); + output << emitter.getOrCreateName(argument) << " = " + << emitter.getOrCreateName(operand) << ";\n"; + } + + output << "goto "; + if (!(emitter.hasBlockLabel(falseSuccessor))) { + return condBranchOp.emitOpError() + << "Unable to find label for successor block"; + } + output << emitter.getOrCreateName(falseSuccessor) << ";\n"; + output << "}\n"; + return success(); +} + +static LogicalResult translateFailOp(IREE::VM::FailOp failOp, + mlir::emitc::CppEmitter &emitter) { + llvm::raw_ostream &output = emitter.ostream(); + + auto status = failOp.status(); + + output << "return vm_fail_or_ok(" << emitter.getOrCreateName(status) + << ", iree_make_cstring_view(\"" << failOp.message() << "\"));\n"; + return success(); +} + static LogicalResult translateReturnOpToC( IREE::VM::ReturnOp returnOp, mlir::emitc::CppEmitter &emitter, SmallVector resultNames) { @@ -173,6 +250,10 @@ static LogicalResult translateOpToC(Operation &op, SmallVector resultNames) { if (auto callOp = dyn_cast(op)) return translateCallOpToC(callOp, emitter); + if (auto condBranchOp = dyn_cast(op)) + return translateCondBranchOp(condBranchOp, emitter); + if (auto failOp = dyn_cast(op)) + return translateFailOp(failOp, emitter); if (auto returnOp = dyn_cast(op)) return translateReturnOpToC(returnOp, emitter, resultNames); // Fall back to generic emitc printer @@ -222,9 +303,45 @@ static LogicalResult translateFunctionToC(IREE::VM::ModuleOp &moduleOp, // struct argument name here must not be changed. output << moduleName << "_state_t* state) {\n"; + // We forward declare all result variables including results for (auto &op : funcOp.getOps()) { - if (failed(translateOpToC(op, emitter, resultNames))) { - return failure(); + for (auto result : op.getResults()) { + if (failed(emitter.emitVariableDeclaration(result, + /*trailingSemicolon=*/true))) { + return op.emitError() << "Unable to declare result variable for op"; + } + } + } + + auto &blocks = funcOp.getBlocks(); + // Create label names for basic blocks. + for (auto &block : blocks) { + emitter.getOrCreateName(block); + } + + // Emit variables for basic block arguments. + for (auto it = std::next(blocks.begin()); it != blocks.end(); ++it) { + Block &block = *it; + for (auto &arg : block.getArguments()) { + if (emitter.hasValueInScope(arg)) return failure(); + if (failed(emitter.emitType(arg.getType()))) { + return failure(); + } + output << " " << emitter.getOrCreateName(arg) << ";\n"; + } + } + + for (auto &block : blocks) { + // Only print a label if there is more than one block. + if (blocks.size() > 1) { + if (failed(emitter.emitLabel(block))) { + return funcOp.emitOpError() << "Unable to print label for basic block"; + } + } + for (Operation &op : block.getOperations()) { + if (failed(translateOpToC(op, emitter, resultNames))) { + return failure(); + } } } @@ -459,11 +576,9 @@ static LogicalResult canonicalizeModule( for (auto *op : context->getRegisteredOperations()) { // Non-serializable ops must be removed prior to serialization. if (op->hasTrait()) { - // TODO(simon-camp): reenable pass once support for control flow ops has - // landed - // op->getCanonicalizationPatterns(patterns, context); - // target.setOpAction(OperationName(op->name, context), - // ConversionTarget::LegalizationAction::Illegal); + op->getCanonicalizationPatterns(patterns, context); + target.setOpAction(OperationName(op->name, context), + ConversionTarget::LegalizationAction::Illegal); } // Debug ops must not be present when stripping. @@ -485,11 +600,9 @@ static LogicalResult canonicalizeModule( if (targetOptions.optimize) { // TODO(benvanik): does this run until it quiesces? - // TODO(simon-camp): reenable pass once support for control flow ops has - // landed - // modulePasses.addPass(mlir::createInlinerPass()); + modulePasses.addPass(mlir::createInlinerPass()); modulePasses.addPass(mlir::createCSEPass()); - // modulePasses.addPass(mlir::createCanonicalizerPass()); + modulePasses.addPass(mlir::createCanonicalizerPass()); } // In the the Bytecode module the order is: @@ -546,7 +659,7 @@ LogicalResult translateModuleToC(IREE::VM::ModuleOp moduleOp, output << "\n"; mlir::emitc::CppEmitter emitter(output, /*restrictToC=*/true, - /*forwardDeclareVariables=*/false); + /*forwardDeclareVariables=*/true); mlir::emitc::CppEmitter::Scope scope(emitter); // build struct definitions diff --git a/iree/vm/ops.h b/iree/vm/ops.h index 6da8e5bb3ead..5b84cd0563f8 100644 --- a/iree/vm/ops.h +++ b/iree/vm/ops.h @@ -17,6 +17,8 @@ #include +#include "iree/vm/api.h" + //===------------------------------------------------------------------===// // Globals //===------------------------------------------------------------------===// @@ -125,17 +127,17 @@ static inline int32_t vm_cmp_nz_i32(int32_t operand) { } //===------------------------------------------------------------------===// -// Additional ops +// Control flow ops //===------------------------------------------------------------------===// -// Check ops -// TODO(simon-camp): These macros should be removed once control flow ops are -// supported in the c module target. -// Note that this will fail if message contains a comma -#define VM_CHECK_EQ(a, b, message) \ - if (a != b) { \ - return iree_status_allocate(IREE_STATUS_FAILED_PRECONDITION, "", 0, \ - iree_make_cstring_view(#message)); \ + +static inline iree_status_t vm_fail_or_ok(int32_t status_code, + iree_string_view_t message) { + if (status_code != 0) { + return iree_status_allocate(IREE_STATUS_FAILED_PRECONDITION, "", 0, + message); } + return iree_ok_status(); +} //===------------------------------------------------------------------===// // ExtI64: Conditional assignment diff --git a/iree/vm/test/emitc/CMakeLists.txt b/iree/vm/test/emitc/CMakeLists.txt index da6234dbaea0..205f68d2fb04 100644 --- a/iree/vm/test/emitc/CMakeLists.txt +++ b/iree/vm/test/emitc/CMakeLists.txt @@ -34,6 +34,7 @@ iree_cc_test( ::arithmetic_ops_i64_cc ::assignment_ops_cc ::assignment_ops_i64_cc + ::control_flow_ops_cc ::conversion_ops_cc ::conversion_ops_i64_cc ::global_ops_cc @@ -89,6 +90,18 @@ iree_bytecode_module( PUBLIC ) +iree_bytecode_module( + NAME + control_flow_ops + SRC + "../control_flow_ops.mlir" + CC_NAMESPACE + "iree::vm::test::emitc" + FLAGS + "-iree-vm-ir-to-c-module" + PUBLIC +) + iree_bytecode_module( NAME conversion_ops diff --git a/iree/vm/test/emitc/module_test.cc b/iree/vm/test/emitc/module_test.cc index a8341607823c..5b2b70dcb041 100644 --- a/iree/vm/test/emitc/module_test.cc +++ b/iree/vm/test/emitc/module_test.cc @@ -22,6 +22,7 @@ #include "iree/vm/test/emitc/arithmetic_ops_i64.vmfb" #include "iree/vm/test/emitc/assignment_ops.vmfb" #include "iree/vm/test/emitc/assignment_ops_i64.vmfb" +#include "iree/vm/test/emitc/control_flow_ops.vmfb" #include "iree/vm/test/emitc/conversion_ops.vmfb" #include "iree/vm/test/emitc/conversion_ops_i64.vmfb" #include "iree/vm/test/emitc/global_ops.vmfb" @@ -57,6 +58,7 @@ std::vector GetModuleTestParams() { {arithmetic_ops_i64_descriptor_, arithmetic_ops_i64_create}, {assignment_ops_descriptor_, assignment_ops_create}, {assignment_ops_i64_descriptor_, assignment_ops_i64_create}, + {control_flow_ops_descriptor_, control_flow_ops_create}, {conversion_ops_descriptor_, conversion_ops_create}, {conversion_ops_i64_descriptor_, conversion_ops_i64_create}, {global_ops_descriptor_, global_ops_create}, From 35ea5b883d9af82be5a5bbc1158387c31b3480ba Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Wed, 24 Mar 2021 10:47:58 +0000 Subject: [PATCH 4/7] Enable comparison ops --- iree/vm/test/BUILD | 7 ++ iree/vm/test/CMakeLists.txt | 11 ++ iree/vm/test/comparison_ops_i64.mlir | 172 +++++++++++++++++++++++++++ iree/vm/test/emitc/CMakeLists.txt | 26 ++++ iree/vm/test/emitc/module_test.cc | 4 + 5 files changed, 220 insertions(+) create mode 100644 iree/vm/test/comparison_ops_i64.mlir diff --git a/iree/vm/test/BUILD b/iree/vm/test/BUILD index 47bb1b0021c0..4068d6e696df 100644 --- a/iree/vm/test/BUILD +++ b/iree/vm/test/BUILD @@ -39,6 +39,7 @@ cc_embed_data( ":assignment_ops.vmfb", ":assignment_ops_i64.vmfb", ":comparison_ops.vmfb", + ":comparison_ops_i64.vmfb", ":control_flow_ops.vmfb", ":conversion_ops.vmfb", ":conversion_ops_i64.vmfb", @@ -83,6 +84,12 @@ iree_bytecode_module( flags = ["-iree-vm-ir-to-bytecode-module"], ) +iree_bytecode_module( + name = "comparison_ops_i64", + src = "comparison_ops_i64.mlir", + flags = ["-iree-vm-ir-to-bytecode-module"], +) + iree_bytecode_module( name = "control_flow_ops", src = "control_flow_ops.mlir", diff --git a/iree/vm/test/CMakeLists.txt b/iree/vm/test/CMakeLists.txt index 62472f67129b..52a9a8608ee2 100644 --- a/iree/vm/test/CMakeLists.txt +++ b/iree/vm/test/CMakeLists.txt @@ -23,6 +23,7 @@ iree_cc_embed_data( "assignment_ops.vmfb" "assignment_ops_i64.vmfb" "comparison_ops.vmfb" + "comparison_ops_i64.vmfb" "control_flow_ops.vmfb" "conversion_ops.vmfb" "conversion_ops_i64.vmfb" @@ -80,6 +81,16 @@ iree_bytecode_module( PUBLIC ) +iree_bytecode_module( + NAME + comparison_ops_i64 + SRC + "comparison_ops_i64.mlir" + FLAGS + "-iree-vm-ir-to-bytecode-module" + PUBLIC +) + iree_bytecode_module( NAME comparison_ops diff --git a/iree/vm/test/comparison_ops_i64.mlir b/iree/vm/test/comparison_ops_i64.mlir new file mode 100644 index 000000000000..3eca97859949 --- /dev/null +++ b/iree/vm/test/comparison_ops_i64.mlir @@ -0,0 +1,172 @@ +vm.module @comparison_ops_i64 { + + //===--------------------------------------------------------------------===// + // vm.cmp.lt.i64.s + //===--------------------------------------------------------------------===// + + vm.export @test_cmp_lt_s_0_i64 + vm.func @test_cmp_lt_s_0_i64() { + %lhs = vm.const.i64 4294967295 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 -4294967295 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.s %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 0 : i32 + vm.check.eq %actual, %expected, "4294967295 (UINT_MAX) < -4294967295 (UINT_MAX)" : i32 + vm.return + } + + vm.export @test_cmp_lt_s_1_i64 + vm.func @test_cmp_lt_s_1_i64() { + %lhs = vm.const.i64 -4294967295 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 4294967295 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.s %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 1 : i32 + vm.check.eq %actual, %expected, "-4294967295 (UINT_MAX) < 4294967295 (UINT_MAX)" : i32 + vm.return + } + + // Expect ULONG_MAX to be interpreted as -1 when doing a signed compare. + vm.export @test_cmp_lt_s_2_i64 + vm.func @test_cmp_lt_s_2_i64() { + %lhs = vm.const.i64 18446744073709551615 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 2 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.s %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 1 : i32 + vm.check.eq %actual, %expected, "18446744073709551615 (ULONG_MAX) < 2" : i32 + vm.return + } + + //===--------------------------------------------------------------------===// + // vm.cmp.lt.i64.u + //===--------------------------------------------------------------------===// + + vm.export @test_cmp_lt_u_0_i64 + vm.func @test_cmp_lt_u_0_i64() { + %lhs = vm.const.i64 2 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 -2 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.u %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 1 : i32 + vm.check.eq %actual, %expected, "2 < -2 (as unsigned)" : i32 + vm.return + } + + vm.export @test_cmp_lt_u_1_i64 + vm.func @test_cmp_lt_u_1_i64() { + %lhs = vm.const.i64 -2 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 2 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.u %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 0 : i32 + vm.check.eq %actual, %expected, "-2 < 2 (as unsigned)" : i32 + vm.return + } + + vm.export @test_cmp_lt_u_2_i64 + vm.func @test_cmp_lt_u_2_i64() { + %lhs = vm.const.i64 18446744073709551615 : i64 + %lhs_dno = iree.do_not_optimize(%lhs) : i64 + %rhs = vm.const.i64 2 : i64 + %rhs_dno = iree.do_not_optimize(%rhs) : i64 + %actual = vm.cmp.lt.i64.u %lhs_dno, %rhs_dno : i64 + %expected = vm.const.i32 0 : i32 + vm.check.eq %actual, %expected, "18446744073709551615 (ULONG_MAX) < 2 (as unsigned)" : i32 + vm.return + } + + //===--------------------------------------------------------------------===// + // vm.cmp.*.i64.* pseudo-ops + //===--------------------------------------------------------------------===// + // NOTE: all of these are turned in to some variants of vm.cmp.lt by the + // compiler and are here as a way to test the runtime behavior of the + // pseudo-op expansions. + + vm.export @test_cmp_lte_i64 + vm.func @test_cmp_lte_i64() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i64 -2 : i64 + %cn2_dno = iree.do_not_optimize(%cn2) : i64 + %c2 = vm.const.i64 2 : i64 + %c2_dno = iree.do_not_optimize(%c2) : i64 + + %cmp_0 = vm.cmp.lte.i64.s %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_0, %true, "-2 <= 2" : i32 + %cmp_1 = vm.cmp.lte.i64.s %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_1, %false, "2 <= -2" : i32 + %cmp_2 = vm.cmp.lte.i64.s %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_2, %true, "2 <= 2" : i32 + + %cmp_3 = vm.cmp.lte.i64.u %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_3, %false, "-2 <= 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.lte.i64.u %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_4, %true, "2 <= -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.lte.i64.u %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_5, %true, "2 <= 2 (unsigned)" : i32 + + vm.return + } + + vm.export @test_cmp_gt_i64 + vm.func @test_cmp_gt_i64() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i64 -2 : i64 + %cn2_dno = iree.do_not_optimize(%cn2) : i64 + %c2 = vm.const.i64 2 : i64 + %c2_dno = iree.do_not_optimize(%c2) : i64 + + %cmp_0 = vm.cmp.gt.i64.s %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_0, %false, "-2 > 2" : i32 + %cmp_1 = vm.cmp.gt.i64.s %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_1, %true, "2 > -2" : i32 + %cmp_2 = vm.cmp.gt.i64.s %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_2, %false, "2 > 2" : i32 + + %cmp_3 = vm.cmp.gt.i64.u %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_3, %true, "-2 > 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.gt.i64.u %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_4, %false, "2 > -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.gt.i64.u %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_5, %false, "2 > 2 (unsigned)" : i32 + + vm.return + } + + vm.export @test_cmp_gte_i64 + vm.func @test_cmp_gte_i64() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i64 -2 : i64 + %cn2_dno = iree.do_not_optimize(%cn2) : i64 + %c2 = vm.const.i64 2 : i64 + %c2_dno = iree.do_not_optimize(%c2) : i64 + + %cmp_0 = vm.cmp.gte.i64.s %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_0, %false, "-2 >= 2" : i32 + %cmp_1 = vm.cmp.gte.i64.s %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_1, %true, "2 >= -2" : i32 + %cmp_2 = vm.cmp.gte.i64.s %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_2, %true, "2 >= 2" : i32 + + %cmp_3 = vm.cmp.gte.i64.u %cn2_dno, %c2_dno : i64 + vm.check.eq %cmp_3, %true, "-2 >= 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.gte.i64.u %c2_dno, %cn2_dno : i64 + vm.check.eq %cmp_4, %false, "2 >= -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.gte.i64.u %c2_dno, %c2_dno : i64 + vm.check.eq %cmp_5, %true, "2 >= 2 (unsigned)" : i32 + + vm.return + } + +} diff --git a/iree/vm/test/emitc/CMakeLists.txt b/iree/vm/test/emitc/CMakeLists.txt index 205f68d2fb04..c89fc4a6d013 100644 --- a/iree/vm/test/emitc/CMakeLists.txt +++ b/iree/vm/test/emitc/CMakeLists.txt @@ -34,6 +34,8 @@ iree_cc_test( ::arithmetic_ops_i64_cc ::assignment_ops_cc ::assignment_ops_i64_cc + ::comparison_ops_cc + ::comparison_ops_i64_cc ::control_flow_ops_cc ::conversion_ops_cc ::conversion_ops_i64_cc @@ -90,6 +92,30 @@ iree_bytecode_module( PUBLIC ) +iree_bytecode_module( + NAME + comparison_ops + SRC + "../comparison_ops.mlir" + CC_NAMESPACE + "iree::vm::test::emitc" + FLAGS + "-iree-vm-ir-to-c-module" + PUBLIC +) + +iree_bytecode_module( + NAME + comparison_ops_i64 + SRC + "../comparison_ops_i64.mlir" + CC_NAMESPACE + "iree::vm::test::emitc" + FLAGS + "-iree-vm-ir-to-c-module" + PUBLIC +) + iree_bytecode_module( NAME control_flow_ops diff --git a/iree/vm/test/emitc/module_test.cc b/iree/vm/test/emitc/module_test.cc index 5b2b70dcb041..bf0c686ebfc2 100644 --- a/iree/vm/test/emitc/module_test.cc +++ b/iree/vm/test/emitc/module_test.cc @@ -22,6 +22,8 @@ #include "iree/vm/test/emitc/arithmetic_ops_i64.vmfb" #include "iree/vm/test/emitc/assignment_ops.vmfb" #include "iree/vm/test/emitc/assignment_ops_i64.vmfb" +#include "iree/vm/test/emitc/comparison_ops.vmfb" +#include "iree/vm/test/emitc/comparison_ops_i64.vmfb" #include "iree/vm/test/emitc/control_flow_ops.vmfb" #include "iree/vm/test/emitc/conversion_ops.vmfb" #include "iree/vm/test/emitc/conversion_ops_i64.vmfb" @@ -58,6 +60,8 @@ std::vector GetModuleTestParams() { {arithmetic_ops_i64_descriptor_, arithmetic_ops_i64_create}, {assignment_ops_descriptor_, assignment_ops_create}, {assignment_ops_i64_descriptor_, assignment_ops_i64_create}, + {comparison_ops_descriptor_, comparison_ops_create}, + {comparison_ops_i64_descriptor_, comparison_ops_i64_create}, {control_flow_ops_descriptor_, control_flow_ops_create}, {conversion_ops_descriptor_, conversion_ops_create}, {conversion_ops_i64_descriptor_, conversion_ops_i64_create}, From 18f685c398bd4142e3718dfab193554d70e72c17 Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Wed, 24 Mar 2021 10:59:23 +0000 Subject: [PATCH 5/7] Fix dependency --- iree/vm/BUILD | 3 +++ iree/vm/CMakeLists.txt | 2 ++ iree/vm/ops.h | 2 +- iree/vm/test/CMakeLists.txt | 8 ++++---- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/iree/vm/BUILD b/iree/vm/BUILD index b373fda56f08..ddc903f26a22 100644 --- a/iree/vm/BUILD +++ b/iree/vm/BUILD @@ -306,6 +306,9 @@ cc_library( hdrs = [ "ops.h", ], + deps = [ + "//iree/base:api", + ], ) cc_library( diff --git a/iree/vm/CMakeLists.txt b/iree/vm/CMakeLists.txt index 2e023084d92e..54e66c92e8db 100644 --- a/iree/vm/CMakeLists.txt +++ b/iree/vm/CMakeLists.txt @@ -265,6 +265,8 @@ iree_cc_library( ops HDRS "ops.h" + DEPS + iree::base::api PUBLIC ) diff --git a/iree/vm/ops.h b/iree/vm/ops.h index 5b84cd0563f8..7099f3847f4a 100644 --- a/iree/vm/ops.h +++ b/iree/vm/ops.h @@ -17,7 +17,7 @@ #include -#include "iree/vm/api.h" +#include "iree/base/api.h" //===------------------------------------------------------------------===// // Globals diff --git a/iree/vm/test/CMakeLists.txt b/iree/vm/test/CMakeLists.txt index 52a9a8608ee2..84789c552558 100644 --- a/iree/vm/test/CMakeLists.txt +++ b/iree/vm/test/CMakeLists.txt @@ -83,9 +83,9 @@ iree_bytecode_module( iree_bytecode_module( NAME - comparison_ops_i64 + comparison_ops SRC - "comparison_ops_i64.mlir" + "comparison_ops.mlir" FLAGS "-iree-vm-ir-to-bytecode-module" PUBLIC @@ -93,9 +93,9 @@ iree_bytecode_module( iree_bytecode_module( NAME - comparison_ops + comparison_ops_i64 SRC - "comparison_ops.mlir" + "comparison_ops_i64.mlir" FLAGS "-iree-vm-ir-to-bytecode-module" PUBLIC From a9f17ffd4b227a04f78c1db6d72d2a6cbbe0d62f Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Wed, 24 Mar 2021 12:51:08 +0000 Subject: [PATCH 6/7] Add lit test for control flow conversion Additionally fix several broken conversion tests --- .../Dialect/VM/Target/C/CModuleTarget.cpp | 2 + .../Dialect/VM/Target/C/test/add.mlir | 6 ++- .../VM/Target/C/test/calling_convention.mlir | 6 ++- .../VM/Target/C/test/control_flow.mlir | 44 +++++++++++++++++++ .../Dialect/VM/Target/C/test/global_ops.mlir | 12 +++-- 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 iree/compiler/Dialect/VM/Target/C/test/control_flow.mlir diff --git a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp index 5bfec123785e..829708c169f1 100644 --- a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp @@ -248,6 +248,8 @@ static LogicalResult translateReturnOpToC( static LogicalResult translateOpToC(Operation &op, mlir::emitc::CppEmitter &emitter, SmallVector resultNames) { + if (auto branchOp = dyn_cast(op)) + return translateBranchOp(branchOp, emitter); if (auto callOp = dyn_cast(op)) return translateCallOpToC(callOp, emitter); if (auto condBranchOp = dyn_cast(op)) diff --git a/iree/compiler/Dialect/VM/Target/C/test/add.mlir b/iree/compiler/Dialect/VM/Target/C/test/add.mlir index 839aa60ecc58..4d23bdf8dc08 100644 --- a/iree/compiler/Dialect/VM/Target/C/test/add.mlir +++ b/iree/compiler/Dialect/VM/Target/C/test/add.mlir @@ -4,9 +4,11 @@ vm.module @add_module { // CHECK: iree_status_t add_module_add_1_impl(int32_t v1, int32_t v2, int32_t *out0, int32_t *out1, add_module_state_t* state) { vm.func @add_1(%arg0 : i32, %arg1 : i32) -> (i32, i32) { - // CHECK-NEXT: int32_t v3 = vm_add_i32(v1, v2); + // CHECK-NEXT: int32_t v3; + // CHECK-NEXT: int32_t v4; + // CHECK-NEXT: v3 = vm_add_i32(v1, v2); %0 = vm.add.i32 %arg0, %arg1 : i32 - // CHECK-NEXT: int32_t v4 = vm_add_i32(v3, v3); + // CHECK-NEXT: v4 = vm_add_i32(v3, v3); %1 = vm.add.i32 %0, %0 : i32 // CHECK-NEXT: *out0 = v3; // CHECK-NEXT: *out1 = v4; diff --git a/iree/compiler/Dialect/VM/Target/C/test/calling_convention.mlir b/iree/compiler/Dialect/VM/Target/C/test/calling_convention.mlir index 4c9b87acb3c4..1fdd5ec0ed20 100644 --- a/iree/compiler/Dialect/VM/Target/C/test/calling_convention.mlir +++ b/iree/compiler/Dialect/VM/Target/C/test/calling_convention.mlir @@ -16,7 +16,8 @@ vm.module @calling_convention_test { // CHECK: iree_status_t calling_convention_test_no_in_i32_return_impl(int32_t *out0, calling_convention_test_state_t* state) { vm.func @no_in_i32_return() -> (i32) { - // CHECK-NEXT: int32_t v1 = vm_const_i32(32); + // CHECK-NEXT: int32_t v1; + // CHECK-NEXT: v1 = 32; %0 = vm.const.i32 32 : i32 // CHECK-NEXT: *out0 = v1; // CHECK-NEXT: return iree_ok_status(); @@ -25,7 +26,8 @@ vm.module @calling_convention_test { // CHECK: iree_status_t calling_convention_test_i32_in_i32_return_impl(int32_t v1, int32_t *out0, calling_convention_test_state_t* state) { vm.func @i32_in_i32_return(%arg0 : i32) -> (i32) { - // CHECK-NEXT: int32_t v2 = vm_const_i32(32); + // CHECK-NEXT: int32_t v2; + // CHECK-NEXT: v2 = 32; %0 = vm.const.i32 32 : i32 // CHECK-NEXT: *out0 = v2; // CHECK-NEXT: return iree_ok_status(); diff --git a/iree/compiler/Dialect/VM/Target/C/test/control_flow.mlir b/iree/compiler/Dialect/VM/Target/C/test/control_flow.mlir new file mode 100644 index 000000000000..071491cff790 --- /dev/null +++ b/iree/compiler/Dialect/VM/Target/C/test/control_flow.mlir @@ -0,0 +1,44 @@ +// RUN: iree-translate -iree-vm-ir-to-c-module -iree-vm-c-module-optimize=false %s | IreeFileCheck %s + +vm.module @control_flow_module { + vm.func @control_flow_test(%a: i32, %cond: i32) -> i32 { + vm.cond_br %cond, ^bb1, ^bb2 + ^bb1: + vm.br ^bb3(%a: i32) + ^bb2: + %b = vm.add.i32 %a, %a : i32 + vm.br ^bb3(%b: i32) + ^bb3(%c: i32): + vm.br ^bb4(%c, %a : i32, i32) + ^bb4(%d : i32, %e : i32): + %0 = vm.add.i32 %d, %e : i32 + vm.return %0 : i32 + } +} +// CHECK: iree_status_t control_flow_module_control_flow_test_impl(int32_t [[A:[^ ]*]], int32_t [[COND:[^ ]*]], int32_t *[[RESULT:[^ ]*]], control_flow_module_state_t* [[STATE:[^ ]*]]) { + // CHECK-NEXT: int32_t [[B:[^ ]*]]; + // CHECK-NEXT: int32_t [[V0:[^ ]*]]; + // CHECK-NEXT: int32_t [[C:[^ ]*]]; + // CHECK-NEXT: int32_t [[D:[^ ]*]]; + // CHECK-NEXT: int32_t [[E:[^ ]*]]; + // CHECK-NEXT: [[BB0:[^ ]*]]: + // CHECK-NEXT: if ([[COND]]) { + // CHECK-NEXT: goto [[BB1:[^ ]*]]; + // CHECK-NEXT: } else { + // CHECK-NEXT: goto [[BB2:[^ ]*]]; + // CHECK-NEXT: } + // CHECK-NEXT: [[BB1]]: + // CHECK-NEXT: [[C]] = [[A]]; + // CHECK-NEXT: goto [[BB3:[^ ]*]]; + // CHECK-NEXT: [[BB2]]: + // CHECK-NEXT: [[B]] = vm_add_i32([[A]], [[A]]); + // CHECK-NEXT: [[C]] = [[B]]; + // CHECK-NEXT: goto [[BB3]]; + // CHECK-NEXT: [[BB3]]: + // CHECK-NEXT: [[D]] = [[C]]; + // CHECK-NEXT: [[E]] = [[A]]; + // CHECK-NEXT: goto [[BB4:[^ ]*]]; + // CHECK-NEXT: [[BB4]]: + // CHECK-NEXT: [[V0]] = vm_add_i32([[D]], [[E]]); + // CHECK-NEXT: *[[RESULT]] = [[V0]]; + // CHECK-NEXT: return iree_ok_status(); diff --git a/iree/compiler/Dialect/VM/Target/C/test/global_ops.mlir b/iree/compiler/Dialect/VM/Target/C/test/global_ops.mlir index c35714564b5d..629252cb9966 100644 --- a/iree/compiler/Dialect/VM/Target/C/test/global_ops.mlir +++ b/iree/compiler/Dialect/VM/Target/C/test/global_ops.mlir @@ -1,10 +1,11 @@ -// RUN: iree-translate -iree-vm-ir-to-c-module %s | IreeFileCheck %s +// RUN: iree-translate -iree-vm-ir-to-c-module -iree-vm-c-module-optimize=false %s | IreeFileCheck %s vm.module @global_ops { // check the generated state struct // CHECK-LABEL: struct global_ops_state_s { // CHECK-NEXT: iree_allocator_t allocator; // CHECK-NEXT: uint8_t rwdata[8]; + // CHECK-NEXT: iree_vm_ref_t refs[0]; // CHECK-NEXT: }; vm.global.i32 @c42 42 : i32 @@ -13,7 +14,8 @@ vm.module @global_ops { vm.export @test_global_load_i32 // CHECK-LABEL: iree_status_t global_ops_test_global_load_i32_impl( vm.func @test_global_load_i32() -> i32 { - // CHECK-NEXT: int32_t v1 = vm_global_load_i32(state->rwdata, 0); + // CHECK-NEXT: int32_t v1; + // CHECK-NEXT: v1 = vm_global_load_i32(state->rwdata, 0); %value = vm.global.load.i32 @c42 : i32 vm.return %value : i32 } @@ -21,11 +23,13 @@ vm.module @global_ops { vm.export @test_global_store_i32 // CHECK-LABEL: iree_status_t global_ops_test_global_store_i32_impl( vm.func @test_global_store_i32() -> i32 { - // CHECK-NEXT: int32_t v1 = vm_const_i32(17); + // CHECK-NEXT: int32_t v1; + // CHECK-NEXT: int32_t v2; + // CHECK-NEXT: v1 = 17; %c17 = vm.const.i32 17 : i32 // CHECK-NEXT: vm_global_store_i32(state->rwdata, 4, v1); vm.global.store.i32 %c17, @c107_mut : i32 - // CHECK-NEXT: int32_t v2 = vm_global_load_i32(state->rwdata, 4); + // CHECK-NEXT: v2 = vm_global_load_i32(state->rwdata, 4); %value = vm.global.load.i32 @c107_mut : i32 vm.return %value : i32 } From 7459c8f127fbe83f78369b0093f0f70c48e0e0ac Mon Sep 17 00:00:00 2001 From: Simon Camphausen Date: Wed, 24 Mar 2021 13:25:19 +0000 Subject: [PATCH 7/7] Fix comment --- iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp index 829708c169f1..58fead54eeac 100644 --- a/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/C/CModuleTarget.cpp @@ -305,7 +305,7 @@ static LogicalResult translateFunctionToC(IREE::VM::ModuleOp &moduleOp, // struct argument name here must not be changed. output << moduleName << "_state_t* state) {\n"; - // We forward declare all result variables including results + // We forward declare all result variables. for (auto &op : funcOp.getOps()) { for (auto result : op.getResults()) { if (failed(emitter.emitVariableDeclaration(result,