Merge remote-tracking branch 'origin/main' into bazel-gpu
diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index 123f5a4..457da97 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml
@@ -33,9 +33,6 @@ uses: actions/checkout@v2 with: token: ${{ secrets.GITHUB_WRITE_ACCESS_TOKEN }} - - name: Fetching gh-pages branch - run: | - git fetch origin gh-pages - name: Initializing submodules run: ./scripts/git/submodule_versions.py init - name: Installing Ninja build @@ -45,6 +42,9 @@ ./build_tools/cmake/build_docs.sh # Patch the MarkDown files with front matter for rendering ./scripts/prepare_doc_publication.py ${IREE_DOC_BUILD_DIR}/doc + - name: Fetching gh-pages branch + run: | + git fetch origin gh-pages - name: Updating gh-pages branch run: | git checkout -f gh-pages
diff --git a/.github/workflows/update_tf.yml b/.github/workflows/update_tf.yml index 86c55d9..b116f99 100644 --- a/.github/workflows/update_tf.yml +++ b/.github/workflows/update_tf.yml
@@ -54,6 +54,4 @@ Automated submodule bump from .github/workflows/update_tf.yml committer: "Submodule Update Action <iree-github-actions-bot@google.com>" - # TODO(gcmn): Figure out a way to assign this to someone dynamically. - reviewers: gmngeoffrey branch: "auto_submodule_update"
diff --git a/.gitmodules b/.gitmodules index 13d12e9..3bde2de 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -50,3 +50,6 @@ [submodule "third_party/marl"] path = third_party/marl url = https://github.com/google/marl.git +[submodule "third_party/flatcc"] + path = third_party/flatcc + url = https://github.com/dvidelabs/flatcc.git
diff --git a/.style.yapf b/.style.yapf new file mode 100644 index 0000000..9ef1dc1 --- /dev/null +++ b/.style.yapf
@@ -0,0 +1,4 @@ +[style] + based_on_style = google + column_limit = 80 + indent_width = 2
diff --git a/CMakeLists.txt b/CMakeLists.txt index 22bb32f..155f08d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -93,6 +93,10 @@ if( IREE_HAL_DRIVERS_TO_BUILD STREQUAL "all" ) set( IREE_HAL_DRIVERS_TO_BUILD ${IREE_ALL_HAL_DRIVERS} ) + # For cross compilation towords Android, we don't want LLVM JIT HAL driver. + if(ANDROID) + list(REMOVE_ITEM IREE_HAL_DRIVERS_TO_BUILD LLVM) + endif() endif() message(STATUS "Building HAL drivers ${IREE_HAL_DRIVERS_TO_BUILD}") @@ -112,8 +116,8 @@ # List of all target backends to be built by default: set(IREE_ALL_TARGET_BACKENDS # TODO(scotttodd): LLVMAOT - LLVMIR - Vulkan_SPIRV + LLVM-IR + Vulkan-SPIRV VMLA ) @@ -201,10 +205,7 @@ include(iree_tablegen_doc) include(iree_cc_embed_data) include(iree_bytecode_module) -include(iree_pybind_cc_library) -include(iree_py_extension) -include(iree_py_library) -include(iree_py_test) +include(iree_multipy) include(iree_lit_test) include(iree_add_all_subdirs) include(iree_check_test) @@ -251,7 +252,6 @@ # dependency is added prior to including this configuration. #------------------------------------------------------------------------------- - # Adds bundled projects that must be included after the LLVM directory has # been added and within the scope of its settings (i.e. build type override, # etc). @@ -314,7 +314,6 @@ add_bundled_mlir_dependent_projects() endif() - #------------------------------------------------------------------------------- # Non-LLVM Dependencies #------------------------------------------------------------------------------- @@ -329,7 +328,8 @@ find_package(PythonInterp 3 REQUIRED) endif() if(${IREE_BUILD_PYTHON_BINDINGS}) - find_package(PythonLibs 3 REQUIRED) + # Note: Optional because python libs can be manually specified. + find_package(PythonLibs 3) endif() list(APPEND CMAKE_MODULE_PATH @@ -337,20 +337,24 @@ ) include(external_cc_library) +include(flatbuffer_c_library) include(flatbuffer_cc_library) +add_subdirectory(build_tools/third_party/flatcc EXCLUDE_FROM_ALL) +add_subdirectory(build_tools/third_party/renderdoc_api EXCLUDE_FROM_ALL) add_subdirectory(build_tools/third_party/ruy EXCLUDE_FROM_ALL) add_subdirectory(third_party/googletest EXCLUDE_FROM_ALL) add_subdirectory(third_party/abseil-cpp EXCLUDE_FROM_ALL) add_subdirectory(third_party/flatbuffers EXCLUDE_FROM_ALL) +add_subdirectory(third_party/flatcc EXCLUDE_FROM_ALL) add_subdirectory(third_party/vulkan_headers EXCLUDE_FROM_ALL) -add_subdirectory(build_tools/third_party/renderdoc_api EXCLUDE_FROM_ALL) if(CMAKE_CROSSCOMPILING) # We need flatc to generate some source code. When cross-compiling, we need # to make sure the flatc binary is configured under host environment. iree_declare_host_excutable(flatc BUILDONLY) + iree_declare_host_excutable(flatcc BUILDONLY) # Set the FLATBUFFERS_FLATC_EXECUTABLE. It controls where to find the flatc # binary in BuildFlatBuffers(). @@ -358,12 +362,21 @@ # Add a custom target to copy the flatc to the binary directory. add_custom_target(iree_host_flatc - COMMAND "${CMAKE_COMMAND}" -E copy_if_different - "${IREE_HOST_BINARY_ROOT}/third_party/flatbuffers/flatc${IREE_HOST_EXECUTABLE_SUFFIX}" - "${IREE_HOST_BINARY_ROOT}/bin" + COMMAND + "${CMAKE_COMMAND}" -E copy_if_different + "${IREE_HOST_BINARY_ROOT}/third_party/flatbuffers/flatc${IREE_HOST_EXECUTABLE_SUFFIX}" + "${IREE_HOST_BINARY_ROOT}/bin" DEPENDS iree_host_build_flatc COMMENT "Installing host flatc..." ) + add_custom_target(iree_host_flatcc + COMMAND + "${CMAKE_COMMAND}" -E copy_if_different + "${IREE_HOST_BINARY_ROOT}/third_party/flatcc/flatcc${IREE_HOST_EXECUTABLE_SUFFIX}" + "${IREE_HOST_BINARY_ROOT}/bin" + DEPENDS iree_host_build_flatcc + COMMENT "Installing host flatcc..." + ) endif() if(${IREE_BUILD_COMPILER}) @@ -387,7 +400,10 @@ endif() if(${IREE_BUILD_PYTHON_BINDINGS}) + # NOTE: The multipy defaults come from pybind's configuration and must come + # after. This should be pulled in locally at some point. add_subdirectory(third_party/pybind11 EXCLUDE_FROM_ALL) + iree_multipy_configure() endif() #-------------------------------------------------------------------------------
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a906067..0f7897d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md
@@ -58,7 +58,7 @@ ## Peculiarities Our documentation on -[repository management](https://github.com/google/iree/blob/main/docs/repository_management.md) +[repository management](https://github.com/google/iree/blob/main/docs/developing_iree/repository_management.md) has more information on some of the oddities in our repository setup and workflows. For the most part, these should be transparent to normal developer workflows.
diff --git a/README.md b/README.md index e6de0e2..b1fd668 100644 --- a/README.md +++ b/README.md
@@ -37,8 +37,8 @@ working on enabling macOS support. For deployment, IREE aims to additionally cover Android and iOS. -Please see the [Getting Started](https://google.github.io/iree/GetStarted) pages -on IREE's [documentation hub](https://google.github.io/iree) to configure, +Please see the [Getting Started](https://google.github.io/iree/get_started) +pages on IREE's [documentation hub](https://google.github.io/iree) to configure, compile, and run IREE in your favorite development environment! ## Documentation and Talks @@ -68,7 +68,7 @@ The architecture of IREE is best illustrated by the following picture: - + Being compilation-based means IREE does not have a traditional runtime that dispatches "ops" to their fat kernel implementations. What IREE provides is a @@ -100,8 +100,8 @@ ## Roadmap and Milestones IREE is still at its early stage; we have lots of exciting future plans. Please -check out the [long-term design roadmap](./docs/roadmap_design.md) and -[short-term focus areas](./docs/roadmap.md). +check out the [long-term design roadmap](./docs/design_roadmap.md) and +[short-term focus areas](./docs/milestones.md). We use [GitHub Projects](https://github.com/google/iree/projects) to track various IREE components and
diff --git a/SUBMODULE_VERSIONS b/SUBMODULE_VERSIONS index 1e315f6..b802f7d 100644 --- a/SUBMODULE_VERSIONS +++ b/SUBMODULE_VERSIONS
@@ -2,8 +2,9 @@ daff5fead3fbe22c6fc58310ca3f49caf117f185 third_party/benchmark 4c13807b7d43ff0946b7ffea0ae3aee9e611d778 third_party/dear_imgui a5d9d0f7d368054fd1691aedf1db4116efcc233e third_party/flatbuffers +4fb0ff7069bd88ee85902f4d0bb62794e5f6d021 third_party/flatcc f2fb48c3b3d79a75a88a99fba6576b25d42ec528 third_party/googletest -de0c6bd56b41081f1b89a1c7a0bf2597fd6d0104 third_party/llvm-project +99ad956fdaee5398fdcf46fa49cb433cf52dc461 third_party/llvm-project 17b12a4481daa150e2d1ea3ada086b551b856707 third_party/marl 67f3ccebee84f3488b46a8d3ac005178c52ff264 third_party/mlir-emitc 80d452484c5409444b0ec19383faa84bb7a4d351 third_party/pybind11 @@ -11,7 +12,7 @@ b73f111094da3e380a1774b56b15f16c90ae8e23 third_party/sdl2 f8bf11a0253a32375c32cad92c841237b96696c0 third_party/spirv_headers 57eb48aed36160c4876bc8310d9ca84d42ee9e2a third_party/swiftshader -e36aca0132fbcde0bc820d56185e3078f97a879d third_party/tensorflow +e4a48da690fac3443825b535ec02cb31c5625337 third_party/tensorflow 864d86e8b6d21449474db5e9313dbff90aa9c24f third_party/tracy 9bd3f561bcee3f01d22912de10bb07ce4e23d378 third_party/vulkan_headers 909f36b714c9239ee0b112a321220213a474ba53 third_party/vulkan_memory_allocator
diff --git a/WORKSPACE b/WORKSPACE index 507a82a..cf098ce 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -63,7 +63,7 @@ rbe_autoconfig( name = "rbe_default", base_container_digest = "sha256:1a8ed713f40267bb51fe17de012fa631a20c52df818ccb317aaed2ee068dfc61", - digest = "sha256:b59d8cc422b03524394d4d05e443bf38d4fe96fab06197b34174de01572e8161", + digest = "sha256:bc2d61ad05453928e67b434ae019e7d050dda46c091270f2b81b2f09da2276ce", registry = "gcr.io", repository = "iree-oss/rbe-toolchain", use_checked_in_confs = "Force", @@ -183,6 +183,13 @@ path = "third_party/flatbuffers", ) +maybe( + new_local_repository, + name = "com_github_dvidelabs_flatcc", + build_file = "build_tools/third_party/flatcc/BUILD.overlay", + path = "third_party/flatcc", +) + # TODO(scotttodd): TensorFlow is squatting on the vulkan_headers repo name, so # we use a temporary one until resolved. Theirs is set to an outdated version. maybe(
diff --git a/bindings/java/com/google/iree/Context.java b/bindings/java/com/google/iree/Context.java index b2a4399..2b42c79 100644 --- a/bindings/java/com/google/iree/Context.java +++ b/bindings/java/com/google/iree/Context.java
@@ -54,6 +54,15 @@ } } + public Function resolveFunction(String name) throws Exception { + Function function = new Function(); + Status status = Status.fromCode(nativeResolveFunction(function.getNativeAddress(), name)); + if (!status.isOk()) { + throw status.toException("Could not resolve function"); + } + return function; + } + public int getId() { return nativeGetId(); } @@ -82,6 +91,8 @@ private native int nativeRegisterModules(long[] moduleAddresses); + private native int nativeResolveFunction(long functionAddress, String name); + private native void nativeFree(); private native int nativeGetId();
diff --git a/bindings/java/com/google/iree/Function.java b/bindings/java/com/google/iree/Function.java new file mode 100644 index 0000000..bf9c02a --- /dev/null +++ b/bindings/java/com/google/iree/Function.java
@@ -0,0 +1,38 @@ +/* + * Copyright 2020 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 + * + * http://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. + */ + +package com.google.iree; + +/** A function reference. */ +final class Function { + public Function() { + nativeAddress = nativeNew(); + } + + public long getNativeAddress() { + return nativeAddress; + } + + public void free() { + nativeFree(); + } + + private final long nativeAddress; + + private native long nativeNew(); + + private native void nativeFree(); +}
diff --git a/bindings/java/com/google/iree/native/context_jni.cc b/bindings/java/com/google/iree/native/context_jni.cc index 341dad2..de11e74 100644 --- a/bindings/java/com/google/iree/native/context_jni.cc +++ b/bindings/java/com/google/iree/native/context_jni.cc
@@ -15,6 +15,7 @@ #include <jni.h> #include "bindings/java/com/google/iree/native/context_wrapper.h" +#include "bindings/java/com/google/iree/native/function_wrapper.h" #include "bindings/java/com/google/iree/native/instance_wrapper.h" #include "bindings/java/com/google/iree/native/module_wrapper.h" #include "iree/base/logging.h" @@ -23,6 +24,7 @@ #define JNI_PREFIX(METHOD) Java_com_google_iree_Context_##METHOD using iree::java::ContextWrapper; +using iree::java::FunctionWrapper; using iree::java::InstanceWrapper; using iree::java::ModuleWrapper; @@ -101,6 +103,21 @@ return (jint)status.code(); } +JNI_FUNC jint JNI_PREFIX(nativeResolveFunction)(JNIEnv* env, jobject thiz, + jlong functionAddress, + jstring name) { + ContextWrapper* context = GetContextWrapper(env, thiz); + CHECK_NE(context, nullptr); + + auto function = (FunctionWrapper*)functionAddress; + const char* native_name = env->GetStringUTFChars(name, /*isCopy=*/nullptr); + + auto status = context->ResolveFunction( + *function, iree_string_view_t{native_name, strlen(native_name)}); + env->ReleaseStringUTFChars(name, native_name); + return (jint)status.code(); +} + JNI_FUNC jint JNI_PREFIX(nativeGetId)(JNIEnv* env, jobject thiz) { ContextWrapper* context = GetContextWrapper(env, thiz); CHECK_NE(context, nullptr);
diff --git a/bindings/java/com/google/iree/native/context_wrapper.cc b/bindings/java/com/google/iree/native/context_wrapper.cc index eb3d354..f329644 100644 --- a/bindings/java/com/google/iree/native/context_wrapper.cc +++ b/bindings/java/com/google/iree/native/context_wrapper.cc
@@ -70,6 +70,13 @@ IREE_LOC); } +Status ContextWrapper::ResolveFunction(const FunctionWrapper& function_wrapper, + iree_string_view_t name) { + return FromApiStatus(iree_vm_context_resolve_function( + context_, name, function_wrapper.function()), + IREE_LOC); +} + int ContextWrapper::id() const { return iree_vm_context_id(context_); } ContextWrapper::~ContextWrapper() {
diff --git a/bindings/java/com/google/iree/native/context_wrapper.h b/bindings/java/com/google/iree/native/context_wrapper.h index 380d587..3924a8c 100644 --- a/bindings/java/com/google/iree/native/context_wrapper.h +++ b/bindings/java/com/google/iree/native/context_wrapper.h
@@ -15,6 +15,7 @@ #ifndef IREE_BINDINGS_JAVA_COM_GOOGLE_IREE_NATIVE_CONTEXT_WRAPPER_H_ #define IREE_BINDINGS_JAVA_COM_GOOGLE_IREE_NATIVE_CONTEXT_WRAPPER_H_ +#include "bindings/java/com/google/iree/native/function_wrapper.h" #include "bindings/java/com/google/iree/native/instance_wrapper.h" #include "bindings/java/com/google/iree/native/module_wrapper.h" #include "iree/base/status.h" @@ -34,6 +35,9 @@ Status RegisterModules(const std::vector<ModuleWrapper*>& module_wrappers); + Status ResolveFunction(const FunctionWrapper& function_wrapper, + iree_string_view_t name); + int id() const; ~ContextWrapper();
diff --git a/bindings/java/com/google/iree/native/function_jni.cc b/bindings/java/com/google/iree/native/function_jni.cc new file mode 100644 index 0000000..5b9542f --- /dev/null +++ b/bindings/java/com/google/iree/native/function_jni.cc
@@ -0,0 +1,49 @@ +// Copyright 2020 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 <jni.h> + +#include "bindings/java/com/google/iree/native/function_wrapper.h" +#include "iree/base/logging.h" + +#define JNI_FUNC extern "C" JNIEXPORT +#define JNI_PREFIX(METHOD) Java_com_google_iree_Function_##METHOD + +using iree::java::FunctionWrapper; + +namespace { + +// Returns a pointer to the native IREE function stored by the FunctionWrapper +// object. +static FunctionWrapper* GetFunctionWrapper(JNIEnv* env, jobject obj) { + jclass clazz = env->GetObjectClass(obj); + CHECK(clazz); + + jfieldID field = env->GetFieldID(clazz, "nativeAddress", "J"); + CHECK(field); + + return reinterpret_cast<FunctionWrapper*>(env->GetLongField(obj, field)); +} + +} // namespace + +JNI_FUNC jlong JNI_PREFIX(nativeNew)(JNIEnv* env, jobject thiz) { + return reinterpret_cast<jlong>(new FunctionWrapper()); +} + +JNI_FUNC void JNI_PREFIX(nativeFree)(JNIEnv* env, jobject thiz) { + FunctionWrapper* function = GetFunctionWrapper(env, thiz); + CHECK_NE(function, nullptr); + delete function; +}
diff --git a/bindings/java/com/google/iree/native/function_wrapper.cc b/bindings/java/com/google/iree/native/function_wrapper.cc new file mode 100644 index 0000000..2dfcd62 --- /dev/null +++ b/bindings/java/com/google/iree/native/function_wrapper.cc
@@ -0,0 +1,25 @@ +// Copyright 2020 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 "bindings/java/com/google/iree/native/function_wrapper.h" + +namespace iree { +namespace java { + +iree_vm_function_t* FunctionWrapper::function() const { + return function_.get(); +} + +} // namespace java +} // namespace iree
diff --git a/bindings/java/com/google/iree/native/function_wrapper.h b/bindings/java/com/google/iree/native/function_wrapper.h new file mode 100644 index 0000000..8c71dc0 --- /dev/null +++ b/bindings/java/com/google/iree/native/function_wrapper.h
@@ -0,0 +1,37 @@ +// Copyright 2020 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_BINDINGS_JAVA_COM_GOOGLE_IREE_NATIVE_FUNCTION_WRAPPER_H_ +#define IREE_BINDINGS_JAVA_COM_GOOGLE_IREE_NATIVE_FUNCTION_WRAPPER_H_ + +#include <memory> + +#include "iree/vm/module.h" + +namespace iree { +namespace java { + +class FunctionWrapper { + public: + iree_vm_function_t* function() const; + + private: + std::unique_ptr<iree_vm_function_t> function_ = + std::make_unique<iree_vm_function_t>(); +}; + +} // namespace java +} // namespace iree + +#endif // IREE_BINDINGS_JAVA_COM_GOOGLE_IREE_NATIVE_FUNCTION_WRAPPER_H_
diff --git a/bindings/javatests/com/google/iree/IntegrationTest.java b/bindings/javatests/com/google/iree/IntegrationTest.java index 499a9c8..13f3fbb 100644 --- a/bindings/javatests/com/google/iree/IntegrationTest.java +++ b/bindings/javatests/com/google/iree/IntegrationTest.java
@@ -60,6 +60,12 @@ assertNotEquals(ireeContext.getId(), -1); + String functionName = "module.simple_mul"; + Function function = ireeContext.resolveFunction(functionName); + + // TODO(jennik): Invoke the function. + + function.free(); module.free(); ireeContext.free(); instance.free(); @@ -83,6 +89,10 @@ modules.add(module); ireeContext.registerModules(modules); + String functionName = "module.simple_mul"; + Function function = ireeContext.resolveFunction(functionName); + + function.free(); module.free(); ireeContext.free(); instance.free();
diff --git a/bindings/python/build_tools/cmake/iree_py_extension.cmake b/bindings/python/build_tools/cmake/iree_py_extension.cmake deleted file mode 100644 index f3c36b8..0000000 --- a/bindings/python/build_tools/cmake/iree_py_extension.cmake +++ /dev/null
@@ -1,259 +0,0 @@ -# Copyright 2020 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(CMakeParseArguments) - -if (NOT DEFINED _IREE_PY_EXTENSION_NAMES) - set(_IREE_PY_EXTENSION_NAMES "") -endif() - -# iree_py_extension() -# -# CMake function to imitate Bazel's iree_py_extension rule. -# -# Parameters: -# NAME: name of target -# HDRS: List of public header files for the library -# SRCS: List of source files for the library -# DEPS: List of other libraries to be linked in to the py extension targets -# COPTS: List of private compile options -# DEFINES: List of public defines -# INCLUDES: Include directories to add to dependencies -# LINKOPTS: List of link options -# TYPE: Type of library to be crated: either "MODULE", "SHARED" or "STATIC" (default). -# TESTONLY: When added, this target will only be built if user passes -DIREE_BUILD_TESTS=ON to CMake. - -function(iree_py_extension) - - cmake_parse_arguments( - _RULE - "TESTONLY" - "NAME" - "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS;INCLUDES;TYPE" - ${ARGN} - ) - - iree_package_ns(_PACKAGE_NS) - # Replace dependencies passed by ::name with ::iree::package::name - list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::") - - if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS) - # Prefix the library with the package name, so we get: iree_package_name. - iree_package_name(_PACKAGE_NAME) - set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") - - if(NOT _RULE_TYPE) - set(_RULE_TYPE "STATIC") - endif() - - string(TOUPPER "${_RULE_TYPE}" _uppercase_RULE_TYPE) - if(NOT _uppercase_RULE_TYPE MATCHES "^(STATIC|SHARED|MODULE)") - message(FATAL_ERROR "Unsported library TYPE for iree_pybind_cc_library: ${_RULE_TYPE}") - endif() - - - add_library(${_NAME} ${_uppercase_RULE_TYPE} "") - target_sources(${_NAME} - PRIVATE - ${_RULE_SRCS} - ${_RULE_TEXTUAL_HDRS} - ${_RULE_HDRS} - ) - - target_include_directories(${_NAME} - PUBLIC - "$<BUILD_INTERFACE:${IREE_COMMON_INCLUDE_DIRS}>" - "$<BUILD_INTERFACE:${_RULE_INCLUDES}>" - PRIVATE - ${PYBIND11_INCLUDE_DIR} - ${PYTHON_INCLUDE_DIR} - ) - - target_compile_options(${_NAME} - PRIVATE - ${_RULE_COPTS} - ${IREE_DEFAULT_COPTS} - ) - - target_compile_definitions(${_NAME} - PUBLIC - ${_RULE_DEFINES} - ) - - set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_NAME}") - - if(NOT _uppercase_RULE_TYPE MATCHES "STATIC") - set_property(TARGET ${_NAME} PROPERTY PREFIX "${PYTHON_MODULE_PREFIX}") - set_property(TARGET ${_NAME} PROPERTY SUFFIX "${PYTHON_MODULE_EXTENSION}") - endif() - - # Alias the iree_package_name library to iree::package::name. - # This lets us more clearly map to Bazel and makes it possible to - # disambiguate the underscores in paths vs. the separators. - add_library(${_PACKAGE_NS}::${_RULE_NAME} ALIAS ${_NAME}) - iree_package_dir(_PACKAGE_DIR) - if(${_RULE_NAME} STREQUAL ${_PACKAGE_DIR}) - # If the library name matches the package then treat it as a default. - # For example, foo/bar/ library 'bar' would end up as 'foo::bar'. - add_library(${_PACKAGE_NS} ALIAS ${_NAME}) - endif() - # Defer computing transitive dependencies and calling target_link_libraries() - # until all libraries have been declared. - # Track target and deps, use in iree_complete_py_extension_link_options() later. - set_property(GLOBAL APPEND PROPERTY _IREE_PY_EXTENSION_NAMES "${_NAME}") - set_property(TARGET ${_NAME} PROPERTY DIRECT_DEPS ${_RULE_DEPS}) - endif() -endfunction() - -# Lists all transitive dependencies of DIRECT_DEPS in TRANSITIVE_DEPS. -function(_iree_transitive_dependencies DIRECT_DEPS TRANSITIVE_DEPS) - set(_TRANSITIVE "") - - foreach(_DEP ${DIRECT_DEPS}) - _iree_transitive_dependencies_helper(${_DEP} _TRANSITIVE) - endforeach(_DEP) - - set(${TRANSITIVE_DEPS} "${_TRANSITIVE}" PARENT_SCOPE) -endfunction() - -# Recursive helper function for _iree_transitive_dependencies. -# Performs a depth-first search through the dependency graph, appending all -# dependencies of TARGET to the TRANSITIVE_DEPS list. -function(_iree_transitive_dependencies_helper TARGET TRANSITIVE_DEPS) - if (NOT TARGET "${TARGET}") - # Excluded from the project, or invalid name? Just ignore. - return() - endif() - - # Resolve aliases, canonicalize name formatting. - get_target_property(_ALIASED_TARGET ${TARGET} ALIASED_TARGET) - if(_ALIASED_TARGET) - set(_TARGET_NAME ${_ALIASED_TARGET}) - else() - string(REPLACE "::" "_" _TARGET_NAME ${TARGET}) - endif() - - set(_RESULT "${${TRANSITIVE_DEPS}}") - if (${_TARGET_NAME} IN_LIST _RESULT) - # Already visited, ignore. - return() - endif() - - # Append this target to the list. Dependencies of this target will be added - # (if valid and not already visited) in recursive function calls. - list(APPEND _RESULT ${_TARGET_NAME}) - - # Check for non-target identifiers again after resolving the alias. - if (NOT TARGET ${_TARGET_NAME}) - return() - endif() - - # Get the list of direct dependencies for this target. - get_target_property(_TARGET_TYPE ${_TARGET_NAME} TYPE) - if(NOT ${_TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY") - get_target_property(_TARGET_DEPS ${_TARGET_NAME} LINK_LIBRARIES) - else() - get_target_property(_TARGET_DEPS ${_TARGET_NAME} INTERFACE_LINK_LIBRARIES) - endif() - - if(_TARGET_DEPS) - # Recurse on each dependency. - foreach(_TARGET_DEP ${_TARGET_DEPS}) - _iree_transitive_dependencies_helper(${_TARGET_DEP} _RESULT) - endforeach(_TARGET_DEP) - endif() - - # Propagate the augmented list up to the parent scope. - set(${TRANSITIVE_DEPS} "${_RESULT}" PARENT_SCOPE) -endfunction() - -# Sets target_link_libraries() on all registered py extensions. -# This must be called after all libraries have been declared. -function(iree_complete_py_extension_link_options) - get_property(_NAMES GLOBAL PROPERTY _IREE_PY_EXTENSION_NAMES) - - foreach(_NAME ${_NAMES}) - get_target_property(_DIRECT_DEPS ${_NAME} DIRECT_DEPS) - - # List all dependencies, including transitive dependencies, then split the - # dependency list into one for whole archive (ALWAYSLINK) and one for - # standard linking (which only links in symbols that are directly used). - _iree_transitive_dependencies("${_DIRECT_DEPS}" _TRANSITIVE_DEPS) - set(_ALWAYS_LINK_DEPS "") - set(_STANDARD_DEPS "") - foreach(_DEP ${_TRANSITIVE_DEPS}) - # Check if _DEP is a library with the ALWAYSLINK property set. - set(_DEP_IS_ALWAYSLINK OFF) - if (TARGET ${_DEP}) - get_target_property(_DEP_TYPE ${_DEP} TYPE) - if(${_DEP_TYPE} STREQUAL "INTERFACE_LIBRARY") - # Can't be ALWAYSLINK since it's an INTERFACE library. - # We also can't even query for the property, since it isn't allowlisted. - else() - get_target_property(_DEP_IS_ALWAYSLINK ${_DEP} ALWAYSLINK) - endif() - endif() - - # Append to the corresponding list of deps. - if(_DEP_IS_ALWAYSLINK) - list(APPEND _ALWAYS_LINK_DEPS ${_DEP}) - - # For MSVC, also add a `-WHOLEARCHIVE:` version of the dep. - # CMake treats -WHOLEARCHIVE[:lib] as a link flag and will not actually - # try to link the library in, so we need the flag *and* the dependency. - # For macOS, also add a `-Wl,-force_load` version of the dep. - if(MSVC) - get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET) - if (_ALIASED_TARGET) - list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_ALIASED_TARGET}") - else() - list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_DEP}") - endif() - elseif(APPLE) - get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET) - if (_ALIASED_TARGET) - list(APPEND _ALWAYS_LINK_DEPS "-Wl,-force_load $<TARGET_FILE:${_ALIASED_TARGET}>") - else() - list(APPEND _ALWAYS_LINK_DEPS "-Wl,-force_load $<TARGET_FILE:${_DEP}>") - endif() - endif() - else() - list(APPEND _STANDARD_DEPS ${_DEP}) - endif() - endforeach(_DEP) - - # Call into target_link_libraries with the lists of deps. - if(MSVC OR APPLE) - target_link_libraries(${_NAME} - PUBLIC - ${_ALWAYS_LINK_DEPS} - ${_STANDARD_DEPS} - PRIVATE - ${_RULE_LINKOPTS} - ${PYTHON_LIBRARY} - ) - else() - target_link_libraries(${_NAME} - PUBLIC - "-Wl,--whole-archive" - ${_ALWAYS_LINK_DEPS} - "-Wl,--no-whole-archive" - ${_STANDARD_DEPS} - PRIVATE - ${_RULE_LINKOPTS} - ${PYTHON_LIBRARY} - ) - endif() - endforeach(_NAME) -endfunction()
diff --git a/bindings/python/build_tools/cmake/iree_py_library.cmake b/bindings/python/build_tools/cmake/iree_py_library.cmake deleted file mode 100644 index 8bc8fdf..0000000 --- a/bindings/python/build_tools/cmake/iree_py_library.cmake +++ /dev/null
@@ -1,51 +0,0 @@ -# Copyright 2020 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(CMakeParseArguments) - -# iree_py_library() -# -# CMake function to imitate Bazel's iree_py_library rule. -# -# Parameters: -# NAME: name of target -# SRCS: List of source files for the library -# DEPS: List of other targets the test python libraries require - -function(iree_py_library) - - cmake_parse_arguments( - _RULE - "" - "NAME" - "SRCS;DEPS" - ${ARGN} - ) - - iree_package_ns(_PACKAGE_NS) - # Replace dependencies passed by ::name with ::iree::package::name - list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::") - - iree_package_name(_PACKAGE_NAME) - set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") - - # Add path to each source file - list(TRANSFORM _RULE_SRCS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") - - add_custom_target(${_NAME} ALL - COMMAND ${CMAKE_COMMAND} -E copy "${_RULE_SRCS}" "${CMAKE_CURRENT_BINARY_DIR}/" - DEPENDS ${_RULE_DEPS} - ) - -endfunction()
diff --git a/bindings/python/build_tools/cmake/iree_py_test.cmake b/bindings/python/build_tools/cmake/iree_py_test.cmake deleted file mode 100644 index 0fbb6f0..0000000 --- a/bindings/python/build_tools/cmake/iree_py_test.cmake +++ /dev/null
@@ -1,60 +0,0 @@ -# Copyright 2020 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(CMakeParseArguments) - -# iree_py_test() -# -# CMake function to imitate Bazel's iree_py_test rule. -# -# Parameters: -# NAME: name of test -# SRCS: List of source file -# DEPS: List of deps the test requires -# LABELS: Additional labels to apply to the test. The package path is added -# automatically. - -function(iree_py_test) - if(NOT IREE_BUILD_TESTS) - return() - endif() - - cmake_parse_arguments( - _RULE - "" - "NAME" - "SRCS;DEPS;LABELS" - ${ARGN} - ) - - iree_package_name(_PACKAGE_NAME) - set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") - - iree_package_ns(_PACKAGE_NS) - string(REPLACE "::" "/" _PACKAGE_PATH ${_PACKAGE_NS}) - set(_NAME_PATH "${_PACKAGE_PATH}:${_RULE_NAME}") - - add_test( - NAME ${_NAME_PATH} - COMMAND ${CMAKE_SOURCE_DIR}/build_tools/cmake/run_test.sh ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/${_RULE_SRCS}" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - - list(APPEND _RULE_LABELS "${_PACKAGE_PATH}") - set_property(TEST ${_NAME_PATH} PROPERTY LABELS "${_RULE_LABELS}") - set_property(TEST ${_NAME_PATH} PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/bindings/python:$ENV{PYTHONPATH};TEST_TMPDIR=${_NAME}_test_tmpdir") - # TODO(marbre): Find out how to add deps to tests. - # Similar to _RULE_DATA in iree_lit_test(). - -endfunction()
diff --git a/bindings/python/build_tools/cmake/iree_pybind_cc_library.cmake b/bindings/python/build_tools/cmake/iree_pybind_cc_library.cmake deleted file mode 100644 index 589f768..0000000 --- a/bindings/python/build_tools/cmake/iree_pybind_cc_library.cmake +++ /dev/null
@@ -1,127 +0,0 @@ -# Copyright 2020 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(CMakeParseArguments) - -# iree_pybind_cc_library() -# -# CMake function to imitate Bazel's pybind_cc_library rule. -# -# Parameters: -# NAME: name of target -# HDRS: List of public header files for the library -# SRCS: List of source files for the library -# DEPS: List of other libraries to be linked in to the binary targets -# COPTS: List of private compile options -# DEFINES: List of public defines -# INCLUDES: Include directories to add to dependencies -# LINKOPTS: List of link options -# TYPE: Type of library to be crated: either "MODULE", "SHARED" or "STATIC" (default). -# TESTONLY: When added, this target will only be built if user passes -DIREE_BUILD_TESTS=ON to CMake. - -function(iree_pybind_cc_library) - - cmake_parse_arguments( - _RULE - "TESTONLY" - "NAME" - "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS;INCLUDES;TYPE" - ${ARGN} - ) - - iree_package_ns(_PACKAGE_NS) - # Replace dependencies passed by ::name with ::iree::package::name - list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::") - - if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS) - # Prefix the library with the package name, so we get: iree_package_name. - iree_package_name(_PACKAGE_NAME) - set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") - - if(NOT _RULE_TYPE) - set(_RULE_TYPE "STATIC") - endif() - - string(TOUPPER "${_RULE_TYPE}" _uppercase_RULE_TYPE) - if(NOT _uppercase_RULE_TYPE MATCHES "^(STATIC|SHARED|MODULE)") - message(FATAL_ERROR "Unsported library TYPE for iree_pybind_cc_library: ${_RULE_TYPE}") - endif() - - add_library(${_NAME} ${_uppercase_RULE_TYPE} "") - target_sources(${_NAME} - PRIVATE - ${_RULE_SRCS} - ${_RULE_HDRS} - ) - target_include_directories(${_NAME} - PUBLIC - "$<BUILD_INTERFACE:${IREE_COMMON_INCLUDE_DIRS}>" - "$<BUILD_INTERFACE:${_RULE_INCLUDES}>" - PRIVATE - ${PYBIND11_INCLUDE_DIR} - ${PYTHON_INCLUDE_DIR} - ) - target_compile_options(${_NAME} - PRIVATE - ${_RULE_COPTS} - ${PYBIND_COPTS} - ${IREE_DEFAULT_COPTS} - ) - - target_link_libraries(${_NAME} - PUBLIC - ${_RULE_DEPS} - PRIVATE - pybind11 - ${PYTHON_LIBRARY} - ${_RULE_LINKOPTS} - ${IREE_DEFAULT_LINKOPTS} - ) - target_compile_definitions(${_NAME} - PUBLIC - ${_RULE_DEFINES} - ) - - # Add all IREE targets to a folder in the IDE for organization. - if(_RULE_PUBLIC) - set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER}) - elseif(_RULE_TESTONLY) - set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER}/test) - else() - set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER}/internal) - endif() - - # INTERFACE libraries can't have the CXX_STANDARD property set. - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${IREE_CXX_STANDARD}) - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) - - set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_NAME}") - - if(NOT _uppercase_RULE_TYPE MATCHES "STATIC") - set_property(TARGET ${_NAME} PROPERTY PREFIX "${PYTHON_MODULE_PREFIX}") - set_property(TARGET ${_NAME} PROPERTY SUFFIX "${PYTHON_MODULE_EXTENSION}") - endif() - - # Alias the iree_package_name library to iree::package::name. - # This lets us more clearly map to Bazel and makes it possible to - # disambiguate the underscores in paths vs. the separators. - add_library(${_PACKAGE_NS}::${_RULE_NAME} ALIAS ${_NAME}) - iree_package_dir(_PACKAGE_DIR) - if(${_RULE_NAME} STREQUAL ${_PACKAGE_DIR}) - # If the library name matches the package then treat it as a default. - # For example, foo/bar/ library 'bar' would end up as 'foo::bar'. - add_library(${_PACKAGE_NS} ALIAS ${_NAME}) - endif() - endif() -endfunction()
diff --git a/bindings/python/pyiree/common/.skip_bazel_to_cmake b/bindings/python/pyiree/common/.skip_bazel_to_cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bindings/python/pyiree/common/.skip_bazel_to_cmake
diff --git a/bindings/python/pyiree/common/CMakeLists.txt b/bindings/python/pyiree/common/CMakeLists.txt index 19f318a..a067903 100644 --- a/bindings/python/pyiree/common/CMakeLists.txt +++ b/bindings/python/pyiree/common/CMakeLists.txt
@@ -12,13 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -iree_pybind_cc_library( +iree_pyext_library( NAME - common - HDRS + PyextCommonLib + SRCS "binding.h" "status_utils.h" - SRCS "status_utils.cc" DEPS iree::base::api
diff --git a/bindings/python/pyiree/compiler/.skip_bazel_to_cmake b/bindings/python/pyiree/compiler/.skip_bazel_to_cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bindings/python/pyiree/compiler/.skip_bazel_to_cmake
diff --git a/bindings/python/pyiree/compiler/CMakeLists.txt b/bindings/python/pyiree/compiler/CMakeLists.txt index 35dbc6f..b7bc2cc 100644 --- a/bindings/python/pyiree/compiler/CMakeLists.txt +++ b/bindings/python/pyiree/compiler/CMakeLists.txt
@@ -17,41 +17,41 @@ compiler SRCS "__init__.py" - DEPS - ::binding + PYEXT_DEPS + ::PyExtCompiler ) -iree_py_extension( +iree_pyext_module( NAME + PyExtCompiler + MODULE_NAME binding SRCS "initialize_module.cc" - DEPS - ::compiler_library - bindings::python::pyiree::common - COPTS - ${PYBIND_COPTS} - ${PYBIND_EXTENSION_COPTS} - TYPE - SHARED + PYEXT_DEPS + ::PyExtCompilerLib + bindings::python::pyiree::common::PyextCommonLib ) -iree_pybind_cc_library( +iree_pyext_library( NAME - compiler_library - HDRS - "compiler.h" + PyExtCompilerLib SRCS + "compiler.h" "compiler.cc" + PYEXT_DEPS + bindings::python::pyiree::common::PyextCommonLib + COPTS + ${PYBIND_REGISTER_MLIR_PASSES} DEPS - # Transforms. Adopted from the Bazel variable COMPILER_DEPS. + # Transforms. Adopted from the Bazel variable COMPILER::DEPS. iree::compiler::Dialect::Flow::Transforms iree::compiler::Dialect::HAL::Transforms iree::compiler::Dialect::HAL::Target iree::compiler::Dialect::Shape::IR iree::compiler::Dialect::Shape::Transforms iree::compiler::Dialect::VM::Transforms - # Targets. Adopted from the Bazel variable COMPILER_DEPS. + # Targets. Adopted from the Bazel variable COMPILER::DEPS. iree::compiler::Dialect::HAL::Target::VMLA iree::compiler::Dialect::HAL::Target::LLVM::LLVMAOT iree::compiler::Dialect::HAL::Target::LLVM::LLVMIR @@ -62,16 +62,11 @@ iree::tools::init_iree_passes_and_dialects iree::tools::init_mlir_passes_and_dialects iree::tools::init_targets - bindings::python::pyiree::common LLVMSupport MLIRIR MLIRSCFTransforms MLIRParser MLIRPass - COPTS - ${PYBIND_REGISTER_MLIR_PASSES} - TYPE - STATIC ) iree_py_test(
diff --git a/bindings/python/pyiree/rt/.skip_bazel_to_cmake b/bindings/python/pyiree/rt/.skip_bazel_to_cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bindings/python/pyiree/rt/.skip_bazel_to_cmake
diff --git a/bindings/python/pyiree/rt/BUILD b/bindings/python/pyiree/rt/BUILD index ac5a93b..6d77a7f 100644 --- a/bindings/python/pyiree/rt/BUILD +++ b/bindings/python/pyiree/rt/BUILD
@@ -92,9 +92,9 @@ "//iree/vm", "//iree/vm:bytecode_module", "//iree/vm:invocation", + "//iree/vm:list", "//iree/vm:module", "//iree/vm:ref", - "//iree/vm:variant_list", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings",
diff --git a/bindings/python/pyiree/rt/CMakeLists.txt b/bindings/python/pyiree/rt/CMakeLists.txt index cf883ac..1ec5eaf 100644 --- a/bindings/python/pyiree/rt/CMakeLists.txt +++ b/bindings/python/pyiree/rt/CMakeLists.txt
@@ -12,50 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -iree_py_library( +iree_pyext_library( NAME - rt + PyExtRtLib SRCS - "__init__.py" - # "system_api.py" - DEPS - ::binding -) - -iree_py_extension( - NAME - binding - SRCS - "initialize_module.cc" - DEPS - iree::hal::vulkan::vulkan_driver_module - iree::hal::llvmjit::llvmjit_driver_module - iree::hal::vmla::vmla_driver_module - ::rt_library - bindings::python::pyiree::common - iree::base::initializer - COPTS - ${PYBIND_COPTS} - ${PYBIND_EXTENSION_COPTS} - TYPE - SHARED -) - -iree_pybind_cc_library( - NAME - rt_library - HDRS "function_abi.h" "hal.h" "host_types.h" "vm.h" - SRCS "function_abi.cc" "hal.cc" "host_types.cc" "vm.cc" + PYEXT_DEPS + bindings::python::pyiree::common::PyextCommonLib DEPS - bindings::python::pyiree::common iree::base::api iree::base::signature_mangle iree::hal::api @@ -66,23 +37,37 @@ iree::vm::bytecode_module iree::vm::invocation iree::vm::ref - iree::vm::variant_list absl::inlined_vector absl::memory absl::strings absl::optional absl::span - TYPE - STATIC +) + +iree_pyext_module( + NAME + PyExtRt + MODULE_NAME binding + SRCS + "initialize_module.cc" + PYEXT_DEPS + ::PyExtRtLib + bindings::python::pyiree::common::PyextCommonLib + DEPS + iree::hal::vulkan::vulkan_driver_module + iree::hal::llvmjit::llvmjit_driver_module + iree::hal::vmla::vmla_driver_module + iree::base::initializer ) iree_py_library( NAME - system_api + rt SRCS + "__init__.py" "system_api.py" - DEPS - ::binding + PYEXT_DEPS + ::PyExtRt ) iree_py_test(
diff --git a/bindings/python/pyiree/rt/function_abi.cc b/bindings/python/pyiree/rt/function_abi.cc index 6b8c01d..58a0295 100644 --- a/bindings/python/pyiree/rt/function_abi.cc +++ b/bindings/python/pyiree/rt/function_abi.cc
@@ -24,8 +24,8 @@ #include "iree/base/signature_mangle.h" #include "iree/hal/api.h" #include "iree/modules/hal/hal_module.h" +#include "iree/vm/list.h" #include "iree/vm/ref.h" -#include "iree/vm/variant_list.h" namespace iree { namespace python { @@ -184,12 +184,12 @@ default: throw RaisePyError(PyExc_NotImplementedError, "Unsupported scalar type"); } - CheckApiStatus(iree_vm_variant_list_append_value(f_args.raw_ptr(), value), + CheckApiStatus(iree_vm_list_push_value(f_args.raw_ptr(), &value), "Could not pack scalar argument"); } py::object UnpackScalar(const RawSignatureParser::Description& desc, - iree_vm_variant_t& f_result) { + const iree_vm_variant_t& f_result) { switch (desc.scalar.type) { case AbiConstants::ScalarType::kUint8: case AbiConstants::ScalarType::kUint16: @@ -296,12 +296,15 @@ } for (size_t i = 0, e = descs.size(); i < e; ++i) { const Description& desc = descs[i]; - iree_vm_variant_t* f_result = - iree_vm_variant_list_get(f_results.raw_ptr(), i); + iree_vm_variant_t f_result = iree_vm_variant_empty(); + if (!iree_status_is_ok( + iree_vm_list_get_variant(f_results.raw_ptr(), i, &f_result))) { + throw RaiseValueError("Could not get result from list"); + } switch (desc.type) { case RawSignatureParser::Type::kBuffer: { iree_hal_buffer_view_t* buffer_view = - iree_hal_buffer_view_deref(&f_result->ref); + iree_hal_buffer_view_deref(&f_result.ref); if (!buffer_view) { throw RaiseValueError( "Could not deref result buffer view (wrong type?)"); @@ -340,7 +343,7 @@ "Ref objects not yet supported"); break; case RawSignatureParser::Type::kScalar: - py_results[i] = UnpackScalar(desc, *f_result); + py_results[i] = UnpackScalar(desc, f_result); break; default: throw RaisePyError(PyExc_NotImplementedError, @@ -397,9 +400,9 @@ iree_hal_buffer_release(raw_buffer); iree_vm_ref_t buffer_view_ref = iree_hal_buffer_view_move_ref(buffer_view); - CheckApiStatus(iree_vm_variant_list_append_ref_move(f_results.raw_ptr(), - &buffer_view_ref), - "Error moving buffer"); + CheckApiStatus( + iree_vm_list_push_ref_move(f_results.raw_ptr(), &buffer_view_ref), + "Error moving buffer"); break; } case RawSignatureParser::Type::kRefObject: @@ -484,9 +487,8 @@ "Error allocating buffer_view"); iree_hal_buffer_release(raw_buffer); iree_vm_ref_t buffer_view_ref = iree_hal_buffer_view_move_ref(buffer_view); - CheckApiStatus( - iree_vm_variant_list_append_ref_move(f_args.raw_ptr(), &buffer_view_ref), - "Error moving buffer view"); + CheckApiStatus(iree_vm_list_push_ref_move(f_args.raw_ptr(), &buffer_view_ref), + "Error moving buffer view"); } void SetupFunctionAbiBindings(pybind11::module m) {
diff --git a/bindings/python/pyiree/rt/function_abi_test.py b/bindings/python/pyiree/rt/function_abi_test.py index 9f34fb6..cb8c804 100644 --- a/bindings/python/pyiree/rt/function_abi_test.py +++ b/bindings/python/pyiree/rt/function_abi_test.py
@@ -49,9 +49,15 @@ def setUpClass(cls): super().setUpClass() driver_names = rt.HalDriver.query() - print("DRIVER_NAMES =", driver_names) - cls.driver = rt.HalDriver.create("vulkan") - cls.device = cls.driver.create_default_device() + for driver_name in driver_names: + print("Try create driver:", driver_name) + try: + cls.driver = rt.HalDriver.create(driver_name) + cls.device = cls.driver.create_default_device() + except Exception: + print("Could not create driver:", driver_name) + else: + break def setUp(self): super().setUp()
diff --git a/bindings/python/pyiree/rt/system_api.py b/bindings/python/pyiree/rt/system_api.py index b7deef6..aaea01f 100644 --- a/bindings/python/pyiree/rt/system_api.py +++ b/bindings/python/pyiree/rt/system_api.py
@@ -64,9 +64,6 @@ continue try: driver = _binding.HalDriver.create(driver_name) - print( - "Created IREE driver %s: %r" % (driver_name, driver), file=sys.stderr) - return driver # TODO(laurenzo): Remove these prints to stderr (for now, more information # is better and there is no better way to report it yet). except Exception as ex: # pylint: disable=broad-except @@ -74,6 +71,23 @@ "Could not create default driver %s: %r" % (driver_name, ex), file=sys.stderr) driver_exceptions[driver_name] = ex + continue + + # Sanity check creation of the default device and skip the driver if + # this fails (this works around issues where the driver is present + # but there are no devices). This default initialization scheme needs + # to be improved. + try: + device = driver.create_default_device() + except Exception as ex: + print( + "Could not create default driver device %s: %r" % (driver_name, ex), + file=sys.stderr) + driver_exceptions[driver_name] = ex + continue + + print("Created IREE driver %s: %r" % (driver_name, driver), file=sys.stderr) + return driver # All failed. raise RuntimeError("Could not create any requested driver "
diff --git a/bindings/python/pyiree/rt/vm.cc b/bindings/python/pyiree/rt/vm.cc index 9674b16..0f79099 100644 --- a/bindings/python/pyiree/rt/vm.cc +++ b/bindings/python/pyiree/rt/vm.cc
@@ -197,21 +197,25 @@ absl::StrAppend(&s, "<VmVariantList(", size(), "): ["); for (iree_host_size_t i = 0, e = size(); i < e; ++i) { - iree_vm_variant_t* variant = - iree_vm_variant_list_get(mutable_this->raw_ptr(), i); + iree_vm_variant_t variant = iree_vm_variant_empty(); + if (!iree_status_is_ok( + iree_vm_list_get_variant(mutable_this->raw_ptr(), i, &variant))) { + absl::StrAppend(&s, "Error"); + continue; + } if (i > 0) absl::StrAppend(&s, ", "); - if (IREE_VM_VARIANT_IS_VALUE(variant)) { - absl::StrAppend(&s, variant->i32); - } else if (IREE_VM_VARIANT_IS_REF(variant)) { + if (iree_vm_variant_is_value(variant)) { + absl::StrAppend(&s, variant.i32); + } else if (iree_vm_variant_is_ref(variant)) { // Pretty print a subset of ABI impacting known types. - if (iree_hal_buffer_isa(&variant->ref)) { - auto* hal_buffer = iree_hal_buffer_deref(&variant->ref); + if (iree_hal_buffer_isa(&variant.ref)) { + auto* hal_buffer = iree_hal_buffer_deref(&variant.ref); assert(hal_buffer); absl::StrAppend(&s, "HalBuffer(", iree_hal_buffer_byte_length(hal_buffer), ")"); - } else if (iree_hal_buffer_view_isa(&variant->ref)) { - auto hal_bv = iree_hal_buffer_view_deref(&variant->ref); + } else if (iree_hal_buffer_view_isa(&variant.ref)) { + auto hal_bv = iree_hal_buffer_view_deref(&variant.ref); absl::StrAppend(&s, "HalBufferView("); absl::InlinedVector<int32_t, 5> shape( iree_hal_buffer_view_shape_rank(hal_bv)); @@ -221,7 +225,7 @@ iree_hal_buffer_view_element_type(hal_bv))), ")"); } else { - absl::StrAppend(&s, "Unknown(", variant->ref_type, ")"); + absl::StrAppend(&s, "Unknown(", variant.type.ref_type, ")"); } } else { absl::StrAppend(&s, "None");
diff --git a/bindings/python/pyiree/rt/vm.h b/bindings/python/pyiree/rt/vm.h index e281f2a..1e7f984 100644 --- a/bindings/python/pyiree/rt/vm.h +++ b/bindings/python/pyiree/rt/vm.h
@@ -21,7 +21,7 @@ #include "iree/base/api.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/variant_list.h" +#include "iree/vm/list.h" namespace iree { namespace python { @@ -67,7 +67,7 @@ VmVariantList() : list_(nullptr) {} ~VmVariantList() { if (list_) { - iree_vm_variant_list_free(list_); + iree_vm_list_release(list_); } } @@ -80,28 +80,29 @@ VmVariantList(const VmVariantList&) = delete; static VmVariantList Create(iree_host_size_t capacity) { - iree_vm_variant_list_t* list; - CheckApiStatus( - iree_vm_variant_list_alloc(capacity, IREE_ALLOCATOR_SYSTEM, &list), - "Error allocating variant list"); + iree_vm_list_t* list; + CheckApiStatus(iree_vm_list_create(/*element_type=*/nullptr, capacity, + IREE_ALLOCATOR_SYSTEM, &list), + "Error allocating variant list"); return VmVariantList(list); } - iree_host_size_t size() const { return iree_vm_variant_list_size(list_); } + iree_host_size_t size() const { return iree_vm_list_size(list_); } - iree_vm_variant_list_t* raw_ptr() { return list_; } - const iree_vm_variant_list_t* raw_ptr() const { return list_; } + iree_vm_list_t* raw_ptr() { return list_; } + const iree_vm_list_t* raw_ptr() const { return list_; } void AppendNullRef() { - CheckApiStatus(iree_vm_variant_list_append_null_ref(raw_ptr()), + iree_vm_ref_t null_ref = {0}; + CheckApiStatus(iree_vm_list_push_ref_move(raw_ptr(), &null_ref), "Error appending to list"); } std::string DebugString() const; private: - VmVariantList(iree_vm_variant_list_t* list) : list_(list) {} - iree_vm_variant_list_t* list_; + VmVariantList(iree_vm_list_t* list) : list_(list) {} + iree_vm_list_t* list_; }; //------------------------------------------------------------------------------
diff --git a/build_tools/bazel/iree_flatcc.bzl b/build_tools/bazel/iree_flatcc.bzl new file mode 100644 index 0000000..e091af6 --- /dev/null +++ b/build_tools/bazel/iree_flatcc.bzl
@@ -0,0 +1,57 @@ +# Copyright 2020 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. + +"""Generates flatbuffer source files with flatcc.""" + +def iree_flatbuffer_c_library( + name, + srcs, + flatcc_args = ["--common", "--reader"], + testonly = False, + **kwargs): + flatcc = "@com_github_dvidelabs_flatcc//:flatcc" + flatcc_rt = "@com_github_dvidelabs_flatcc//:runtime" + + flags = [ + "-o$(RULEDIR)", + ] + flatcc_args + + out_stem = "%s" % (srcs[0].replace(".fbs", "")) + + outs = [] + for arg in flags: + if arg == "--reader": + outs += ["%s_reader.h" % (out_stem)] + if arg == "--builder": + outs += ["%s_builder.h" % (out_stem)] + if arg == "--verifier": + outs += ["%s_verifier.h" % (out_stem)] + + native.genrule( + name = name + "_gen", + srcs = srcs, + outs = outs, + tools = [flatcc], + cmd = "$(location %s) %s $(SRCS)" % (flatcc, " ".join(flags)), + testonly = testonly, + ) + native.cc_library( + name = name, + hdrs = outs, + deps = [ + flatcc_rt, + ], + testonly = testonly, + **kwargs + )
diff --git a/build_tools/bazel/third_party_import/llvm-project/overlay/llvm/BUILD.bazel b/build_tools/bazel/third_party_import/llvm-project/overlay/llvm/BUILD.bazel index bade7ab..befc20c 100644 --- a/build_tools/bazel/third_party_import/llvm-project/overlay/llvm/BUILD.bazel +++ b/build_tools/bazel/third_party_import/llvm-project/overlay/llvm/BUILD.bazel
@@ -155,10 +155,10 @@ name = "InstCombineTableGen", tbl_outs = [( "-gen-searchable-tables", - "lib/Transforms/InstCombine/InstCombineTables.inc", + "lib/Target/AMDGPU/InstCombineTables.inc", )], tblgen = ":llvm-tblgen", - td_file = "lib/Transforms/InstCombine/InstCombineTables.td", + td_file = "lib/Target/AMDGPU/InstCombineTables.td", td_srcs = glob([ "include/llvm/CodeGen/*.td", "include/llvm/IR/Intrinsics*.td", @@ -721,6 +721,7 @@ "lib/Analysis/*.h", ], exclude = [ + "lib/Analysis/DevelopmentModeInlineAdvisor.cpp", "lib/Analysis/MLInlineAdvisor.cpp", "lib/Analysis/ReleaseModeModelRunner.cpp", "lib/Analysis/TFUtils.cpp", @@ -3187,6 +3188,7 @@ ]), copts = llvm_copts, deps = [ + ":BinaryFormat", ":DebugInfoCodeView", ":MC", ":Object",
diff --git a/build_tools/bazel/third_party_import/llvm-project/overlay/mlir/BUILD.bazel b/build_tools/bazel/third_party_import/llvm-project/overlay/mlir/BUILD.bazel index ec0574f..ae413a1 100644 --- a/build_tools/bazel/third_party_import/llvm-project/overlay/mlir/BUILD.bazel +++ b/build_tools/bazel/third_party_import/llvm-project/overlay/mlir/BUILD.bazel
@@ -387,7 +387,7 @@ "include/mlir/Interfaces/CallInterfaces.td", "include/mlir/Interfaces/ControlFlowInterfaces.td", "include/mlir/Interfaces/SideEffectInterfaces.td", - "include/mlir/Interfaces/VectorUnrollInterface.td", + "include/mlir/Interfaces/VectorInterfaces.td", "include/mlir/Interfaces/ViewLikeInterface.td", ":OpBaseTdFiles", ], @@ -500,6 +500,7 @@ deps = [ ":Affine", ":IR", + ":Support", "@llvm-project//llvm:Support", ], ) @@ -647,13 +648,13 @@ ) cc_library( - name = "VectorUnrollInterface", - srcs = ["lib/Interfaces/VectorUnrollInterface.cpp"], - hdrs = ["include/mlir/Interfaces/VectorUnrollInterface.h"], + name = "VectorInterfaces", + srcs = ["lib/Interfaces/VectorInterfaces.cpp"], + hdrs = ["include/mlir/Interfaces/VectorInterfaces.h"], includes = ["include"], deps = [ ":IR", - ":VectorUnrollInterfaceIncGen", + ":VectorInterfacesIncGen", ], ) @@ -855,7 +856,7 @@ ":SideEffectInterfaces", ":StandardOpsIncGen", ":Support", - ":VectorUnrollInterface", + ":VectorInterfaces", ":ViewLikeInterface", "@llvm-project//llvm:Support", ], @@ -918,9 +919,9 @@ ":SideEffectInterfaces", ":StandardOps", ":Support", + ":VectorInterfaces", ":VectorOpsIncGen", ":VectorTransformPatternsIncGen", - ":VectorUnrollInterface", "@llvm-project//llvm:Support", ], ) @@ -2127,20 +2128,20 @@ ) gentbl( - name = "VectorUnrollInterfaceIncGen", + name = "VectorInterfacesIncGen", strip_include_prefix = "include", tbl_outs = [ ( "-gen-op-interface-decls", - "include/mlir/Interfaces/VectorUnrollInterface.h.inc", + "include/mlir/Interfaces/VectorInterfaces.h.inc", ), ( "-gen-op-interface-defs", - "include/mlir/Interfaces/VectorUnrollInterface.cpp.inc", + "include/mlir/Interfaces/VectorInterfaces.cpp.inc", ), ], tblgen = ":mlir-tblgen", - td_file = "include/mlir/Interfaces/VectorUnrollInterface.td", + td_file = "include/mlir/Interfaces/VectorInterfaces.td", td_srcs = [ ":OpBaseTdFiles", ], @@ -3271,6 +3272,7 @@ ":QuantPassIncGen", ":SideEffectInterfaces", ":StandardOps", + ":TransformUtils", "@llvm-project//llvm:Support", ], ) @@ -3586,7 +3588,7 @@ name = "VectorOpsTdFiles", srcs = [ "include/mlir/Dialect/Vector/VectorOps.td", - "include/mlir/Interfaces/VectorUnrollInterface.td", + "include/mlir/Interfaces/VectorInterfaces.td", ":AffineOpsTdFiles", ":OpBaseTdFiles", ], @@ -3716,7 +3718,7 @@ "include/mlir/Interfaces/ControlFlowInterfaces.h", "include/mlir/Interfaces/ControlFlowInterfaces.td", "include/mlir/Interfaces/SideEffectInterfaces.td", - "include/mlir/Interfaces/VectorUnrollInterface.td", + "include/mlir/Interfaces/VectorInterfaces.td", "include/mlir/Interfaces/ViewLikeInterface.td", "include/mlir/Dialect/LLVMIR/LLVMOpBase.td", "include/mlir/Dialect/StandardOps/IR/Ops.td",
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake.py b/build_tools/bazel_to_cmake/bazel_to_cmake.py index ed70b9c..51e559c 100755 --- a/build_tools/bazel_to_cmake/bazel_to_cmake.py +++ b/build_tools/bazel_to_cmake/bazel_to_cmake.py
@@ -103,11 +103,12 @@ if not os.path.isdir(directory_path): raise FileNotFoundError(f"Cannot find directory '{directory_path}'") + skip_file_path = os.path.join(directory_path, ".skip_bazel_to_cmake") build_file_path = os.path.join(directory_path, "BUILD") cmakelists_file_path = os.path.join(directory_path, "CMakeLists.txt") - if not os.path.isfile(build_file_path): - # No Bazel BUILD file in this directory to convert, skip. + if os.path.isfile(skip_file_path) or not os.path.isfile(build_file_path): + # No Bazel BUILD file in this directory or explicit skip. return global repo_root
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py index 34e09a8..bc40c97 100644 --- a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py +++ b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py
@@ -234,6 +234,13 @@ flatc_args = "\n".join([f' "{flatc_arg}"' for flatc_arg in flatc_args]) return f" FLATC_ARGS\n{flatc_args}\n" + def _convert_flatcc_args_block(self, flatcc_args): + if not flatcc_args: + return "" + flatcc_args = "\n".join( + [f' "{flatcc_arg}"' for flatcc_arg in flatcc_args]) + return f" FLATCC_ARGS\n{flatcc_args}\n" + def _convert_unimplemented_function(self, function, details=""): message = f"Unimplemented {function}: {details}" if not self.converter.first_error: @@ -481,6 +488,17 @@ f"{flags_block}" f" PUBLIC\n)\n\n") + def iree_flatbuffer_c_library(self, name, srcs, flatcc_args=None): + name_block = self._convert_name_block(name) + srcs_block = self._convert_srcs_block(srcs) + flatcc_args_block = self._convert_flatcc_args_block(flatcc_args) + + self.converter.body += (f"flatbuffer_c_library(\n" + f"{name_block}" + f"{srcs_block}" + f"{flatcc_args_block}" + f" PUBLIC\n)\n\n") + def iree_flatbuffer_cc_library(self, name, srcs, flatc_args=None): name_block = self._convert_name_block(name) srcs_block = self._convert_srcs_block(srcs)
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py index 7f9b497..19a0fd3 100644 --- a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py +++ b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py
@@ -64,6 +64,8 @@ # Misc single targets "@com_google_benchmark//:benchmark": ["benchmark"], "@com_github_google_flatbuffers//:flatbuffers": ["flatbuffers"], + "@com_github_dvidelabs_flatcc//:flatcc": ["flatcc"], + "@com_github_dvidelabs_flatcc//:runtime": ["flatcc::runtime"], "@com_google_googletest//:gtest": ["gmock", "gtest"], "@renderdoc_api//:renderdoc_app": ["renderdoc_api::renderdoc_app"], "@sdl2//:SDL2": ["SDL2-static"]
diff --git a/build_tools/cmake/build_docs.sh b/build_tools/cmake/build_docs.sh index d4a3c84..191ed17 100755 --- a/build_tools/cmake/build_docs.sh +++ b/build_tools/cmake/build_docs.sh
@@ -49,34 +49,12 @@ cd ${ROOT_DIR?} +cp README.md ${BUILD_DIR}/doc/index.md +cp -rf docs/* ${BUILD_DIR}/doc/ + # Update op_coverage.md scripts/update_op_coverage.py ${BUILD_DIR} # Update e2e_coverage.md PYTHON_BIN=`which python3` scripts/update_e2e_coverage.py ${BUILD_DIR} -# Copy a curated list of docs to publish. This is expected to cover all docs -# under docs/ after they are refreshed. - -cp README.md ${BUILD_DIR}/doc/index.md -cp docs/IREE-Architecture.svg ${BUILD_DIR}/doc/ - -cp docs/roadmap.md ${BUILD_DIR}/doc/ -cp docs/roadmap_design.md ${BUILD_DIR}/doc/ -cp docs/developer_overview.md ${BUILD_DIR}/doc/ -cp docs/testing_guide.md ${BUILD_DIR}/doc/ -cp docs/iree_community.md ${BUILD_DIR}/doc/ - -mkdir -p ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_windows_bazel.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_windows_cmake.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_windows_vulkan.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_linux_bazel.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_linux_cmake.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_linux_vulkan.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_macos_bazel.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_macos_cmake.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_android_cmake.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/getting_started_python.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/generic_vulkan_env_setup.md ${BUILD_DIR}/doc/GetStarted/ -cp docs/GetStarted/cmake_options_and_variables.md ${BUILD_DIR}/doc/GetStarted/
diff --git a/build_tools/cmake/flatbuffer_c_library.cmake b/build_tools/cmake/flatbuffer_c_library.cmake new file mode 100644 index 0000000..916cfd9 --- /dev/null +++ b/build_tools/cmake/flatbuffer_c_library.cmake
@@ -0,0 +1,158 @@ +# Copyright 2020 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(CMakeParseArguments) + +# flatbuffer_c_library() +# +# CMake function to invoke the flatcc compiler. +# +# Parameters: +# NAME: name of target (see Note) +# SRCS: List of source files for the library +# DEPS: List of other libraries to be linked in to the binary targets +# COPTS: List of private compile options +# DEFINES: List of public defines +# LINKOPTS: List of link options +# FLATCC_ARGS: List of flattbuffers arguments. Default: +# "--common" +# "--reader" +# PUBLIC: Add this so that this library will be exported under iree:: +# Also in IDE, target will appear in IREE folder while non PUBLIC will be in IREE/internal. +# TESTONLY: When added, this target will only be built if user passes -DIREE_BUILD_TESTS=ON to CMake. +# +# Note: +# By default, flatbuffer_c_library will always create a library named ${NAME}, +# and alias target iree::${NAME}. The iree:: form should always be used. +# This is to reduce namespace pollution. +# +# flatbuffer_c_library( +# NAME +# base_schema +# SRCS +# "a.fbs" +# ) +# flatbuffer_c_library( +# NAME +# other_schemas +# SRCS +# "b.fbs" +# DEPS +# iree::schemas::base_schema +# PUBLIC +# ) +# +# iree_cc_binary( +# NAME +# main_lib +# ... +# DEPS +# iree::schemas::other_schemas +# ) +function(flatbuffer_c_library) + cmake_parse_arguments(_RULE + "PUBLIC;TESTONLY" + "NAME" + "SRCS;COPTS;DEFINES;LINKOPTS;DEPS;FLATCC_ARGS" + ${ARGN} + ) + + if(_RULE_TESTONLY AND NOT IREE_BUILD_TESTS) + return() + endif() + + # Prefix the library with the package name, so we get: iree_package_name + iree_package_name(_PACKAGE_NAME) + set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") + + if(NOT DEFINED _RULE_FLATCC_ARGS) + set(_RULE_FLATCC_ARGS + "--common" + "--reader" + ) + else() + set(_RULE_FLATCC_ARGS ${_RULE_FLATCC_ARGS}) + endif() + + set(_OUTS "") + foreach(_SRC ${_RULE_SRCS}) + get_filename_component(_SRC_FILENAME ${_SRC} NAME_WE) + foreach(_ARG ${_RULE_FLATCC_ARGS}) + if(_ARG STREQUAL "--reader") + list(APPEND _OUTS "${_SRC_FILENAME}_reader.h") + elseif(_ARG STREQUAL "--builder") + list(APPEND _OUTS "${_SRC_FILENAME}_builder.h") + elseif(_ARG STREQUAL "--verifier") + list(APPEND _OUTS "${_SRC_FILENAME}_verifier.h") + endif() + endforeach() + endforeach() + list(TRANSFORM _OUTS PREPEND "${CMAKE_CURRENT_BINARY_DIR}/") + + iree_get_executable_path(_FLATCC_BIN flatcc) + add_custom_command( + OUTPUT + ${_OUTS} + COMMAND + "${_FLATCC_BIN}" + -o "${CMAKE_CURRENT_BINARY_DIR}" + -I "${IREE_ROOT_DIR}" + ${_RULE_FLATCC_ARGS} + "${_RULE_SRCS}" + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + MAIN_DEPENDENCY + ${_RULE_SRCS} + DEPENDS + ${_FLATCC_BIN} + ${_RULE_SRCS} + COMMAND_EXPAND_LISTS + ) + + set(_GEN_TARGET "${_NAME}_gen") + add_custom_target( + ${_GEN_TARGET} + DEPENDS + ${_OUTS} + ${_RULE_DEPS} + ) + + add_library(${_NAME} INTERFACE) + add_dependencies(${_NAME} ${_GEN_TARGET}) + target_include_directories(${_NAME} + INTERFACE + "$<BUILD_INTERFACE:${IREE_COMMON_INCLUDE_DIRS}>" + ${CMAKE_CURRENT_BINARY_DIR} + ) + target_link_libraries(${_NAME} + INTERFACE + flatcc::runtime + ${_RULE_LINKOPTS} + ${IREE_DEFAULT_LINKOPTS} + ) + target_compile_definitions(${_NAME} + INTERFACE + ${_RULE_DEFINES} + ) + target_compile_options(${_NAME} + INTERFACE + "-I${IREE_ROOT_DIR}/third_party/flatcc/include/flatcc/reflection/" + ) + + # Alias the iree_package_name library to iree::package::name. + # This lets us more clearly map to Bazel and makes it possible to + # disambiguate the underscores in paths vs. the separators. + iree_package_ns(_PACKAGE_NS) + add_library(${_PACKAGE_NS}::${_RULE_NAME} ALIAS ${_NAME}) +endfunction()
diff --git a/build_tools/cmake/flatbuffer_cc_library.cmake b/build_tools/cmake/flatbuffer_cc_library.cmake index febf234..86c38fc 100644 --- a/build_tools/cmake/flatbuffer_cc_library.cmake +++ b/build_tools/cmake/flatbuffer_cc_library.cmake
@@ -44,7 +44,7 @@ # NAME # base_schema # SRCS -# "a.cc" +# "a.fbs" # ) # flatbuffer_cc_library( # NAME @@ -52,11 +52,11 @@ # SRCS # "b.fbs" # DEPS -# iree::schemas::base_schema # not "awesome" ! +# iree::schemas::base_schema # PUBLIC # ) # -# flatbuffer_cc_library( +# iree_cc_binary( # NAME # main_lib # ...
diff --git a/build_tools/cmake/iree_check_test.cmake b/build_tools/cmake/iree_check_test.cmake index aa794bd..93fd934 100644 --- a/build_tools/cmake/iree_check_test.cmake +++ b/build_tools/cmake/iree_check_test.cmake
@@ -173,6 +173,17 @@ ${ARGN} ) + + string(TOUPPER ${_RULE_DRIVER} _UPPERCASE_DRIVER) + if(NOT IREE_HAL_DRIVER_${_UPPERCASE_DRIVER}) + return() + endif() + + string(TOUPPER ${_RULE_TARGET_BACKEND} _UPPERCASE_TARGET_BACKEND) + if(NOT IREE_TARGET_BACKEND_${_UPPERCASE_TARGET_BACKEND}) + return() + endif() + foreach(_SRC IN LISTS _RULE_SRCS) set(_TEST_NAME "${_RULE_NAME}_${_SRC}") iree_check_test(
diff --git a/build_tools/cmake/iree_copts.cmake b/build_tools/cmake/iree_copts.cmake index 7b18183..c39db21 100644 --- a/build_tools/cmake/iree_copts.cmake +++ b/build_tools/cmake/iree_copts.cmake
@@ -183,10 +183,19 @@ list(APPEND IREE_DEFAULT_COPTS ${FLATBUFFERS_COPTS}) #------------------------------------------------------------------------------- -# Third party: glslang +# Third party: flatcc #------------------------------------------------------------------------------- -set(ENABLE_CTEST OFF CACHE BOOL "" FORCE) +set(FLATCC_TEST OFF CACHE BOOL "" FORCE) +set(FLATCC_CXX_TEST OFF CACHE BOOL "" FORCE) +set(FLATCC_REFLECTION OFF CACHE BOOL "" FORCE) +set(FLATCC_ALLOW_WERROR OFF CACHE BOOL "" FORCE) + +if(CMAKE_CROSSCOMPILING) + set(FLATCC_RTONLY ON CACHE BOOL "" FORCE) +else() + set(FLATCC_RTONLY OFF CACHE BOOL "" FORCE) +endif() #------------------------------------------------------------------------------- # Third party: gtest
diff --git a/build_tools/cmake/iree_multipy.cmake b/build_tools/cmake/iree_multipy.cmake new file mode 100644 index 0000000..a7fd1f1 --- /dev/null +++ b/build_tools/cmake/iree_multipy.cmake
@@ -0,0 +1,462 @@ +# Copyright 2020 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(CMakeParseArguments) + +############################################################################### +# Configuration +############################################################################### + +function(iree_multipy_configure) + # Configure the defaults. + # Note that this is using the pybind11 configuration vars, which creates + # a fragile dependency. It would be better to derive these locally. + if(PYTHONLIBS_FOUND) + set(IREE_MULTIPY_DEFAULT_EXECUTABLE "${PYTHON_EXECUTABLE}" CACHE INTERNAL "Python executable" ) + set(IREE_MULTIPY_DEFAULT_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}" CACHE INTERNAL "Python include dirs" ) + set(IREE_MULTIPY_DEFAULT_LIBRARIES "${PYTHON_LIBRARIES}" CACHE INTERNAL "Python libraries") + set(IREE_MULTIPY_DEFAULT_PREFIX "${PYTHON_MODULE_PREFIX}" CACHE INTERNAL "Python module prefix") + set(IREE_MULTIPY_DEFAULT_SUFFIX "${PYTHON_MODULE_SUFFIX}" CACHE INTERNAL "Python module suffix") + set(IREE_MULTIPY_DEFAULT_EXTENSION "${PYTHON_MODULE_EXTENSION}" CACHE INTERNAL "Python module extension") + endif() + + if(IREE_MULTIPY_VERSIONS) + set(IREE_MULTIPY_VERSIONS_EFFECTIVE "${IREE_MULTIPY_VERSIONS}" CACHE INTERNAL "Python extension versions") + else() + message(STATUS "Multi-python extension versions not found: using defaults") + set(IREE_MULTIPY_VERSIONS_EFFECTIVE "DEFAULT" CACHE INTERNAL "Python extension versions") + endif() + + # Report the multipy config. + message(STATUS "Multipy extension versions: ${IREE_MULTIPY_VERSIONS_EFFECTIVE}") + foreach(V ${IREE_MULTIPY_VERSIONS_EFFECTIVE}) + message(STATUS " - Multipy version ${V}") + message(STATUS " : EXECUTABLE = ${IREE_MULTIPY_${V}_EXECUTABLE}") + message(STATUS " : INCLUDE_DIRS = ${IREE_MULTIPY_${V}_INCLUDE_DIRS}") + message(STATUS " : LIBRARIES = ${IREE_MULTIPY_${V}_LIBRARIES}") + message(STATUS " : PREFIX = ${IREE_MULTIPY_${V}_PREFIX}") + message(STATUS " : SUFFIX = ${IREE_MULTIPY_${V}_SUFFIX}") + message(STATUS " : EXTENSION = ${IREE_MULTIPY_${V}_EXTENSION}") + + # Check for required settings. + if(NOT IREE_MULTIPY_${V}_INCLUDE_DIRS) + message(FATAL " MULTIPY version ${V}: No IREE_MULTIPY_${VER}_EXECUTABLE var") + endif() + if(NOT IREE_MULTIPY_${V}_INCLUDE_DIRS) + message(FATAL " MULTIPY version ${V}: No IREE_MULTIPY_${VER}_INCLUDE_DIRS var") + endif() + if(NOT IREE_MULTIPY_${V}_EXTENSION) + message(FATAL " MULTIPY version ${V}: No IREE_MULTIPY_${VER}_EXTENSION var") + endif() + endforeach() +endfunction() + +macro(_setup_iree_pyext_names) + iree_package_ns(_PACKAGE_NS) + # Replace dependencies passed by ::name with ::iree::package::name + list(TRANSFORM ARG_DEPS REPLACE "^::" "${_PACKAGE_NS}::") + list(TRANSFORM ARG_PYEXT_DEPS REPLACE "^::" "${_PACKAGE_NS}::") + # Prefix the library with the package name, so we get: iree_package_name. + iree_package_name(_PACKAGE_NAME) + set(_NAME "${_PACKAGE_NAME}_${ARG_NAME}") +endmacro() + +macro(_alias_iree_pyext_library declared_name version target) + # Alias the iree_package_name library to iree::package::name. + # This lets us more clearly map to Bazel and makes it possible to + # disambiguate the underscores in paths vs. the separators. + add_library(${_PACKAGE_NS}::${ARG_NAME}__${version} ALIAS ${target}) + iree_package_dir(_PACKAGE_DIR) +endmacro() + +############################################################################### +# Main user rules +############################################################################### + +# iree_pyext_module() +# +# Builds a native python module (.so/.dylib/.pyd). +# +# Parameters: +# NAME: name of target +# MODULE_NAME: Base-name of the module. +# SRCS: List of source files for the library +# COPTS: C options +# DEPS: List of other targets the test python libraries require +# PYEXT_DEPS: List of deps of extensions built with iree_pyext_(library|module) +function(iree_pyext_module) + cmake_parse_arguments(ARG + "" + "NAME;MODULE_NAME" + "SRCS;COPTS;DEPS;PYEXT_DEPS" + ${ARGN}) + _setup_iree_pyext_names() + + add_custom_target(${_NAME}) + + foreach(V ${IREE_MULTIPY_VERSIONS_EFFECTIVE}) + set(VER_NAME "${_NAME}__${V}") + + # If configured to link against libraries, build in SHARED mode (which + # disallows undefined symbols). Otherwise, build in MODULE mode, which + # does not enforce that. This should naturally do the right thing on + # each platform based on whether configured with a list of libraries to + # link or not. + set(LIBRARY_TYPE MODULE) + if(IREE_MULTIPY_${V}_LIBRARIES) + set(LIBRARY_TYPE SHARED) + endif() + + add_library(${VER_NAME} ${LIBRARY_TYPE} ${ARG_SRCS}) + add_dependencies(${_NAME} ${VER_NAME}) + set_target_properties( + ${VER_NAME} PROPERTIES + OUTPUT_NAME "${ARG_MODULE_NAME}" + PREFIX "${IREE_MULTIPY_${V}_PREFIX}" + SUFFIX "${IREE_MULTIPY_${V}_SUFFIX}${IREE_MULTIPY_${V}_EXTENSION}" + ) + + iree_pyext_pybind11_options(${VER_NAME}) + target_include_directories(${VER_NAME} + PUBLIC + "${IREE_MULTIPY_${V}_INCLUDE_DIRS}" + "$<BUILD_INTERFACE:${IREE_COMMON_INCLUDE_DIRS}>" + ) + target_link_libraries(${VER_NAME} + PRIVATE + ${IREE_DEFAULT_LINKOPTS} + ${IREE_MULTIPY_${V}_LIBRARIES} + ) + target_compile_options(${VER_NAME} + INTERFACE + ${IREE_DEFAULT_COPTS} + PRIVATE + ${ARG_COPTS} + ) + + # Defer computing transitive dependencies and calling target_link_libraries() + # until all libraries have been declared. + # Track target and deps, use in iree_complete_py_extension_link_options() later. + # See iree_complete_py_extension_link_options() in iree_py_extension.cmake + # TODO: Move that implementation here. + set(TRANSFORMED_PYEXT_DEPS "${ARG_PYEXT_DEPS}") + list(TRANSFORM TRANSFORMED_PYEXT_DEPS APPEND "__${V}") + set_property(GLOBAL APPEND PROPERTY _IREE_PY_EXTENSION_NAMES "${VER_NAME}") + set_property(TARGET ${VER_NAME} PROPERTY DIRECT_DEPS ${ARG_DEPS} ${TRANSFORMED_PYEXT_DEPS}) + _alias_iree_pyext_library("${ARG_NAME}" "${V}" ${VER_NAME}) + endforeach() +endfunction() + +# iree_pyext_library() +# +# Builds a C++ library to be included in an iree_pyext_module. +# +# Parameters: +# NAME: name of target +# SRCS: List of source files for the library +# COPTS: C options +# DEPS: List of other targets the test python libraries require +# PYEXT_DEPS: List of deps of extensions built with iree_pyext_(library|module) +function(iree_pyext_library) + cmake_parse_arguments(ARG + "" + "NAME" + "SRCS;COPTS;DEPS;PYEXT_DEPS" + ${ARGN}) + _setup_iree_pyext_names() + + foreach(V ${IREE_MULTIPY_VERSIONS_EFFECTIVE}) + set(VER_NAME "${_NAME}__${V}") + add_library(${VER_NAME} STATIC ${ARG_SRCS}) + iree_pyext_pybind11_options(${VER_NAME}) + target_include_directories(${VER_NAME} + PUBLIC + "${IREE_MULTIPY_${V}_INCLUDE_DIRS}" + "$<BUILD_INTERFACE:${IREE_COMMON_INCLUDE_DIRS}>" + ) + set(TRANSFORMED_PYEXT_DEPS "${ARG_PYEXT_DEPS}") + list(TRANSFORM TRANSFORMED_PYEXT_DEPS APPEND "__${V}") + target_link_libraries(${VER_NAME} + PUBLIC + ${ARG_DEPS} + ${TRANSFORMED_PYEXT_DEPS} + PRIVATE + ${IREE_DEFAULT_LINKOPTS} + ) + target_compile_options(${VER_NAME} + INTERFACE + ${IREE_DEFAULT_COPTS} + PRIVATE + ${ARG_COPTS} + ) + _alias_iree_pyext_library("${ARG_NAME}" "${V}" ${VER_NAME}) + endforeach() +endfunction() + +# iree_py_library() +# +# CMake function to imitate Bazel's iree_py_library rule. +# +# Parameters: +# NAME: name of target +# SRCS: List of source files for the library +# DEPS: List of other targets the test python libraries require +# PYEXT_DEPS: List of deps of extensions built with iree_pyext_module +function(iree_py_library) + cmake_parse_arguments( + ARG + "" + "NAME" + "SRCS;DEPS;PYEXT_DEPS" + ${ARGN} + ) + + iree_package_ns(_PACKAGE_NS) + # Replace dependencies passed by ::name with ::iree::package::name + list(TRANSFORM ARG_DEPS REPLACE "^::" "${_PACKAGE_NS}::") + + iree_package_name(_PACKAGE_NAME) + set(_NAME "${_PACKAGE_NAME}_${ARG_NAME}") + + # Add path to each source file + list(TRANSFORM ARG_SRCS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") + + add_custom_target(${_NAME} ALL + COMMAND ${CMAKE_COMMAND} -E copy ${ARG_SRCS} "${CMAKE_CURRENT_BINARY_DIR}/" + DEPENDS ${ARG_DEPS} + ) + + # Add PYEXT_DEPS. + if(${ARG_PYEXT_DEPS}) + foreach(V ${IREE_MULTIPY_VERSIONS_EFFECTIVE}) + list(TRANSFORM ARG_PYEXT_DEPS APPEND "__${V}") + add_dependencies(${_NAME} ${ARG_PYEXT_DEPS}) + endforeach() + endif() +endfunction() + +function(iree_pyext_pybind11_options name) + target_include_directories(${name} + PRIVATE + ${PYBIND11_INCLUDE_DIR} + ) + target_compile_options(${name} + PRIVATE + $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>: + -frtti -fexceptions + # Noisy pybind warnings + -Wno-unused-value + -Wno-covered-switch-default + > + $<$<CXX_COMPILER_ID:MSVC>: + # Enable RTTI and exceptions. + /EHsc /GR> + ) + set_target_properties( + ${name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") +endfunction() + +# iree_py_test() +# +# CMake function to imitate Bazel's iree_py_test rule. +# +# Parameters: +# NAME: name of test +# SRCS: List of source file +# DEPS: List of deps the test requires +# LABELS: Additional labels to apply to the test. The package path is added +# automatically. + +function(iree_py_test) + if(NOT IREE_BUILD_TESTS) + return() + endif() + + cmake_parse_arguments( + _RULE + "" + "NAME" + "SRCS;DEPS;LABELS" + ${ARGN} + ) + + iree_package_name(_PACKAGE_NAME) + set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") + + iree_package_ns(_PACKAGE_NS) + string(REPLACE "::" "/" _PACKAGE_PATH ${_PACKAGE_NS}) + set(_NAME_PATH "${_PACKAGE_PATH}:${_RULE_NAME}") + list(APPEND _RULE_LABELS "${_PACKAGE_PATH}") + + foreach(V ${IREE_MULTIPY_VERSIONS_EFFECTIVE}) + set(VER_NAME "${_NAME_PATH}__${V}") + add_test( + NAME ${VER_NAME} + COMMAND + "${CMAKE_SOURCE_DIR}/build_tools/cmake/run_test.${IREE_HOST_SCRIPT_EXT}" + "${IREE_MULTIPY_${V}_EXECUTABLE}" + "${CMAKE_CURRENT_SOURCE_DIR}/${_RULE_SRCS}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + + set_property(TEST ${VER_NAME} PROPERTY LABELS "${_RULE_LABELS}") + set_property(TEST ${VER_NAME} PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/bindings/python:$ENV{PYTHONPATH};TEST_TMPDIR=${_NAME}_${V}_test_tmpdir") + # TODO(marbre): Find out how to add deps to tests. + # Similar to _RULE_DATA in iree_lit_test(). + endforeach() +endfunction() + +############################################################################### +# Always-link/transitive dependency management +############################################################################### + +# Lists all transitive dependencies of DIRECT_DEPS in TRANSITIVE_DEPS. +function(_iree_transitive_dependencies DIRECT_DEPS TRANSITIVE_DEPS) + set(_TRANSITIVE "") + + foreach(_DEP ${DIRECT_DEPS}) + _iree_transitive_dependencies_helper(${_DEP} _TRANSITIVE) + endforeach(_DEP) + + set(${TRANSITIVE_DEPS} "${_TRANSITIVE}" PARENT_SCOPE) +endfunction() + +# Recursive helper function for _iree_transitive_dependencies. +# Performs a depth-first search through the dependency graph, appending all +# dependencies of TARGET to the TRANSITIVE_DEPS list. +function(_iree_transitive_dependencies_helper TARGET TRANSITIVE_DEPS) + if (NOT TARGET "${TARGET}") + # Excluded from the project, or invalid name? Just ignore. + return() + endif() + + # Resolve aliases, canonicalize name formatting. + get_target_property(_ALIASED_TARGET ${TARGET} ALIASED_TARGET) + if(_ALIASED_TARGET) + set(_TARGET_NAME ${_ALIASED_TARGET}) + else() + string(REPLACE "::" "_" _TARGET_NAME ${TARGET}) + endif() + + set(_RESULT "${${TRANSITIVE_DEPS}}") + if (${_TARGET_NAME} IN_LIST _RESULT) + # Already visited, ignore. + return() + endif() + + # Append this target to the list. Dependencies of this target will be added + # (if valid and not already visited) in recursive function calls. + list(APPEND _RESULT ${_TARGET_NAME}) + + # Check for non-target identifiers again after resolving the alias. + if (NOT TARGET ${_TARGET_NAME}) + return() + endif() + + # Get the list of direct dependencies for this target. + get_target_property(_TARGET_TYPE ${_TARGET_NAME} TYPE) + if(NOT ${_TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY") + get_target_property(_TARGET_DEPS ${_TARGET_NAME} LINK_LIBRARIES) + else() + get_target_property(_TARGET_DEPS ${_TARGET_NAME} INTERFACE_LINK_LIBRARIES) + endif() + + if(_TARGET_DEPS) + # Recurse on each dependency. + foreach(_TARGET_DEP ${_TARGET_DEPS}) + _iree_transitive_dependencies_helper(${_TARGET_DEP} _RESULT) + endforeach(_TARGET_DEP) + endif() + + # Propagate the augmented list up to the parent scope. + set(${TRANSITIVE_DEPS} "${_RESULT}" PARENT_SCOPE) +endfunction() + +# Sets target_link_libraries() on all registered py extensions. +# This must be called after all libraries have been declared. +function(iree_complete_py_extension_link_options) + get_property(_NAMES GLOBAL PROPERTY _IREE_PY_EXTENSION_NAMES) + + foreach(_NAME ${_NAMES}) + get_target_property(_DIRECT_DEPS ${_NAME} DIRECT_DEPS) + + # List all dependencies, including transitive dependencies, then split the + # dependency list into one for whole archive (ALWAYSLINK) and one for + # standard linking (which only links in symbols that are directly used). + _iree_transitive_dependencies("${_DIRECT_DEPS}" _TRANSITIVE_DEPS) + set(_ALWAYS_LINK_DEPS "") + set(_STANDARD_DEPS "") + foreach(_DEP ${_TRANSITIVE_DEPS}) + # Check if _DEP is a library with the ALWAYSLINK property set. + set(_DEP_IS_ALWAYSLINK OFF) + if (TARGET ${_DEP}) + get_target_property(_DEP_TYPE ${_DEP} TYPE) + if(${_DEP_TYPE} STREQUAL "INTERFACE_LIBRARY") + # Can't be ALWAYSLINK since it's an INTERFACE library. + # We also can't even query for the property, since it isn't allowlisted. + else() + get_target_property(_DEP_IS_ALWAYSLINK ${_DEP} ALWAYSLINK) + endif() + endif() + + # Append to the corresponding list of deps. + if(_DEP_IS_ALWAYSLINK) + list(APPEND _ALWAYS_LINK_DEPS ${_DEP}) + + # For MSVC, also add a `-WHOLEARCHIVE:` version of the dep. + # CMake treats -WHOLEARCHIVE[:lib] as a link flag and will not actually + # try to link the library in, so we need the flag *and* the dependency. + # For macOS, also add a `-Wl,-force_load` version of the dep. + if(MSVC) + get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET) + if (_ALIASED_TARGET) + list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_ALIASED_TARGET}") + else() + list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_DEP}") + endif() + elseif(APPLE) + get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET) + if (_ALIASED_TARGET) + list(APPEND _ALWAYS_LINK_DEPS "-Wl,-force_load $<TARGET_FILE:${_ALIASED_TARGET}>") + else() + list(APPEND _ALWAYS_LINK_DEPS "-Wl,-force_load $<TARGET_FILE:${_DEP}>") + endif() + endif() + else() + list(APPEND _STANDARD_DEPS ${_DEP}) + endif() + endforeach(_DEP) + + # Call into target_link_libraries with the lists of deps. + if(MSVC OR APPLE) + target_link_libraries(${_NAME} + PUBLIC + ${_ALWAYS_LINK_DEPS} + ${_STANDARD_DEPS} + PRIVATE + ${_RULE_LINKOPTS} + ) + else() + target_link_libraries(${_NAME} + PUBLIC + "-Wl,--whole-archive" + ${_ALWAYS_LINK_DEPS} + "-Wl,--no-whole-archive" + ${_STANDARD_DEPS} + PRIVATE + ${_RULE_LINKOPTS} + ) + endif() + endforeach(_NAME) +endfunction()
diff --git a/build_tools/cmake/run_android_test.sh b/build_tools/cmake/run_android_test.sh index 292890c..0c7510d 100755 --- a/build_tools/cmake/run_android_test.sh +++ b/build_tools/cmake/run_android_test.sh
@@ -35,7 +35,7 @@ set -x set -e -adb push $TEST_EXECUTABLE $TEST_ANDROID_ABS_DIR/$(basename $TEST_EXECUTABLE) +adb push $TEST_EXECUTABLE $TEST_ANDROID_ABS_DIR/$(basename $TEST_EXECUTABLE) 1>/dev/null if [ -n "$TEST_DATA" ]; then adb push $TEST_DATA $TEST_ANDROID_ABS_DIR/$(basename $TEST_DATA)
diff --git a/build_tools/docker/bazel/Dockerfile b/build_tools/docker/bazel/Dockerfile index e9a587c..c42521a 100644 --- a/build_tools/docker/bazel/Dockerfile +++ b/build_tools/docker/bazel/Dockerfile
@@ -27,40 +27,49 @@ FROM ubuntu:18.04 WORKDIR /usr/src/iree -RUN apt-get update - # Set environment variables. ENV CXX clang++ ENV CC clang ENV PYTHON_BIN /usr/bin/python3 ENV IREE_LLVMAOT_LINKER_PATH /usr/bin/ld -# Install git for updating IREE's submodules. -RUN apt-get install -y git +RUN apt-get update \ + && apt-get install -y \ + # git for updating IREE's submodules. + git \ + # utilities for later installations + unzip \ + zip \ + wget \ + # core IREE dependencies. + clang \ + libsdl2-dev + +# Disable apt-key parse waring. If someone knows how to do whatever the "proper" +# thing is then feel free. The warning complains about parsing apt-key output, +# which we're not even doing. +ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 # Install Bazel. # https://docs.bazel.build/versions/master/install-ubuntu.html -ARG BAZEL_VERSION=2.1.0 -RUN apt-get install -y unzip zip wget \ - && wget "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION?}/bazel-${BAZEL_VERSION?}-installer-linux-x86_64.sh" \ - && chmod +x "bazel-${BAZEL_VERSION?}-installer-linux-x86_64.sh" \ - && "./bazel-${BAZEL_VERSION?}-installer-linux-x86_64.sh" --user \ - && rm "bazel-${BAZEL_VERSION?}-installer-linux-x86_64.sh" -# Install a newer version of Bazel. We don't need the full installation now. -# Just need to provide a different version for the version-identification -# wrapper script to find in /root/.bazel/bin +ARG BAZEL_VERSION=3.3.1 +# Change to a new version if upgrading Bazel. ARG NEW_BAZEL_VERSION=3.3.1 -RUN cd "/root/.bazel/bin" \ - && wget "https://releases.bazel.build/${NEW_BAZEL_VERSION?}/release/bazel-${NEW_BAZEL_VERSION?}-linux-x86_64" \ - && chmod +x "bazel-${NEW_BAZEL_VERSION?}-linux-x86_64" -# ENV does not allow ${variable?} syntax. -ENV PATH "/root/bin:${PATH}" +RUN wget -qO - https://bazel.build/bazel-release.pub.gpg | apt-key add - \ + && echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" \ + | tee /etc/apt/sources.list.d/bazel.list \ + && apt-get update \ + # Install Bazel pinned at the version we want. Optionally install an + # additional version of Bazel to ease upgrades (modify NEW_BAZEL_VERSION + # above). Bazel does some shenanigans to select the correct version based on + # your .bazelversion file. When upgrading, we therefore need to have both the + # old and new version. When the versions are the same this second installation + # is effectively a noop. + && apt-get install "bazel=${BAZEL_VERSION?}" "bazel-${NEW_BAZEL_VERSION?}" -# Install core IREE dependencies. -RUN apt-get install -y clang libsdl2-dev - -# Install python2 numpy. Temporary fix for issue #1737: -# https://github.com/google/iree/issues/1737 -RUN apt-get install -y python-pip \ - && python -m pip install --upgrade pip \ - && python -m pip install numpy +# TF requires python2 numpy at configure time... +# TODO(#1737): Remove this +RUN apt-get update \ + && apt-get install -y python-pip \ + && python -m pip install --upgrade pip \ + && python -m pip install numpy
diff --git a/build_tools/docker/bazel_bindings/Dockerfile b/build_tools/docker/bazel_bindings/Dockerfile index f7ef30f..8f07958 100644 --- a/build_tools/docker/bazel_bindings/Dockerfile +++ b/build_tools/docker/bazel_bindings/Dockerfile
@@ -27,6 +27,11 @@ FROM gcr.io/iree-oss/bazel # Install python3 and numpy. -RUN apt-get install -y python3 python3-dev python3-pip python3-setuptools \ +RUN apt-get update \ + && apt-get install -y \ + python3 \ + python3-dev \ + python3-pip \ + python3-setuptools \ && python3 -m pip install --upgrade pip \ && python3 -m pip install numpy
diff --git a/build_tools/docker/bazel_tensorflow/Dockerfile b/build_tools/docker/bazel_tensorflow/Dockerfile index a117990..0c37354 100644 --- a/build_tools/docker/bazel_tensorflow/Dockerfile +++ b/build_tools/docker/bazel_tensorflow/Dockerfile
@@ -24,9 +24,7 @@ # gcr.io/iree-oss/bazel-tensorflow # Set up the image and working directory. -FROM gcr.io/iree-oss/bazel +FROM gcr.io/iree-oss/bazel-bindings -# Install python3, tensorflow and numpy. -RUN apt-get install -y python3 python3-dev python3-pip python3-setuptools \ - && python3 -m pip install --upgrade pip \ - && python3 -m pip install numpy tf-nightly +# Install tensorflow. +RUN python3 -m pip install tf-nightly
diff --git a/build_tools/docker/build_and_update_gcr.py b/build_tools/docker/build_and_update_gcr.py index 90c7454..531088f 100755 --- a/build_tools/docker/build_and_update_gcr.py +++ b/build_tools/docker/build_and_update_gcr.py
@@ -20,30 +20,33 @@ """ import argparse +import functools import os import subprocess +import sys IREE_GCR_URL = 'gcr.io/iree-oss/' DOCKER_DIR = 'build_tools/docker/' -IMAGES = [ - 'bazel', - 'bazel-bindings', - 'bazel-tensorflow', - 'cmake', - 'cmake-android', - 'cmake-nvidia', - 'rbe-toolchain', -] -IMAGES_HELP = [f'`{name}`' for name in IMAGES] -IMAGES_HELP = f'{", ".join(IMAGES_HELP[:-1])} or {IMAGES_HELP[-1]}' - -# Map from image names to images that depend on them. -IMAGES_TO_DEPENDENT_IMAGES = { - 'bazel': ['bazel-bindings', 'bazel-tensorflow'], - 'cmake': ['cmake-android', 'cmake-nvidia'], +# Map from image names to images that they depend on. +IMAGES_TO_DEPENDENCIES = { + 'bazel': [], + 'bazel-bindings': ['bazel'], + 'bazel-tensorflow': ['bazel-bindings'], + 'cmake': [], + 'cmake-android': ['cmake'], + 'cmake-nvidia': ['cmake'], + 'rbe-toolchain': [], } +IMAGES_TO_DEPENDENT_IMAGES = {k: [] for k in IMAGES_TO_DEPENDENCIES.keys()} +for image, dependencies in IMAGES_TO_DEPENDENCIES.items(): + for dependency in dependencies: + IMAGES_TO_DEPENDENT_IMAGES[dependency].append(image) + +IMAGES_HELP = [f'`{name}`' for name in IMAGES_TO_DEPENDENCIES.keys()] +IMAGES_HELP = f'{", ".join(IMAGES_HELP)} or `all`' + RBE_MESSAGE = """ Remember to update the `rbe_default` digest in the `WORKSPACE` file to reflect the new digest for the container. @@ -57,8 +60,10 @@ description="Build IREE's Docker images and optionally push them to GCR.") parser.add_argument( '--image', + dest='images', type=str, required=True, + action='append', help=f'Name of the image to build: {IMAGES_HELP}.') parser.add_argument( '--tag', @@ -73,34 +78,77 @@ help='Push the built images to GCR. Requires gcloud authorization.') args = parser.parse_args() - if args.image not in IMAGES: - raise parser.error('Expected --image to be one of:\n' - f' {IMAGES_HELP}\n' - f'but got `{args.image}`.') - + for image in args.images: + if image == 'all': + args.images = IMAGES_TO_DEPENDENCIES.keys() + elif image not in IMAGES_TO_DEPENDENCIES.keys(): + raise parser.error('Expected --image to be one of:\n' + f' {IMAGES_HELP}\n' + f'but got `{image}`.') return args +def cmp_images_by_dependency(image1, image2): + if image2 in IMAGES_TO_DEPENDENT_IMAGES[image1]: + return -1 + if image1 in IMAGES_TO_DEPENDENT_IMAGES[image2]: + return 1 + return (image1 > image2) - (image1 < image2) + + +def run_command(command): + print(f'Running: {" ".join(command)}') + process = subprocess.Popen( + command, + bufsize=1, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + text=True) + for line in process.stdout: + print(line, end='') + + return process.poll() + + +def check_command(command): + exit_code = run_command(command) + if exit_code != 0: + print(f'Command failed: {" ".join(command)}') + sys.exit(exit_code) + + if __name__ == '__main__': args = parse_arguments() # Ensure the user has the correct authorization if they try to push to GCR. if args.push: - subprocess.check_output(['gcloud', 'auth', 'configure-docker']) + if run_command(['which', 'gcloud']) != 0: + print('gcloud not found.' + ' See https://cloud.google.com/sdk/install for installation.') + sys.exit(1) + check_command(['gcloud', 'auth', 'configure-docker']) - # Check if any images depend on `args.image` and update them if they do. - images_to_update = [args.image] - if args.image in IMAGES_TO_DEPENDENT_IMAGES: - images_to_update.extend(IMAGES_TO_DEPENDENT_IMAGES[args.image]) + # Check if any images depend on `args.images` and update them if they do. + images_to_update_set = set() + to_check = list(args.images) + while to_check: + image = to_check.pop() + if image not in images_to_update_set: + images_to_update_set.add(image) + to_check.extend(IMAGES_TO_DEPENDENT_IMAGES[image]) + # Topo sort by image dependency + images_to_update = sorted( + images_to_update_set, key=functools.cmp_to_key(cmp_images_by_dependency)) + + print(f'Also updating dependent images. Will update: {images_to_update}') for image in images_to_update: print(f'Updating image {image}') image_url = os.path.join(IREE_GCR_URL, f'{image}:{args.tag}') image_path = os.path.join(DOCKER_DIR, image.replace('-', '_')) - subprocess.check_output( - ['docker', 'build', '--tag', image_url, image_path]) + check_command(['docker', 'build', '--tag', image_url, image_path]) if args.push: - subprocess.check_output(['docker', 'push', image_url]) + check_command(['docker', 'push', image_url]) if 'rbe-toolchain' in images_to_update: print(RBE_MESSAGE)
diff --git a/build_tools/docker/cmake/Dockerfile b/build_tools/docker/cmake/Dockerfile index 92cece8..bde1f4d 100644 --- a/build_tools/docker/cmake/Dockerfile +++ b/build_tools/docker/cmake/Dockerfile
@@ -27,14 +27,25 @@ FROM ubuntu:18.04 WORKDIR /usr/src/iree/ -RUN apt-get update -# TODO: Remove this if the `apt-get install` below works without it again. -RUN apt update +RUN apt-get update \ + && apt-get install -y \ + # git for updating IREE's submodules. + git \ + # For later installations + wget \ + # For building with ninja + ninja-build \ + # For bootstrapping the cmake installation + cmake \ + # core IREE dependencies. + clang \ + libsdl2-dev \ + libssl-dev # Update cmake to v3.13+, which is ahead of apt-get's version (3.10.2). # Install dependencies, including an old version of cmake to bootstrap. ENV CMAKE_VERSION 3.13.5 -RUN apt-get install -y clang cmake libssl-dev wget \ +RUN apt-get update \ && mkdir ./cmake_install \ && cd cmake_install \ && wget "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION?}/cmake-${CMAKE_VERSION?}.tar.gz" \ @@ -44,14 +55,12 @@ && make \ && make install -# Install dependencies. -RUN apt-get install -y \ - git \ - ninja-build \ - python3 \ - python3-pip \ - python3-setuptools \ - # Install dependencies for the python bindings tests. +# Dependencies for the python bindings tests. +RUN apt-get update \ + && apt-get install -y \ + python3 \ + python3-pip \ + python3-setuptools \ && python3 -m pip install --upgrade pip \ && python3 -m pip install numpy absl-py
diff --git a/build_tools/docker/cmake_nvidia/Dockerfile b/build_tools/docker/cmake_nvidia/Dockerfile index 8679656..c25519f 100644 --- a/build_tools/docker/cmake_nvidia/Dockerfile +++ b/build_tools/docker/cmake_nvidia/Dockerfile
@@ -40,13 +40,15 @@ ARG VULKAN_SDK_VERSION=1.2.141 -# Disable apt-key parse waring. -ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 +# Disable apt-key parse waring. If someone knows how to do whatever the "proper" +# thing is then feel free. The warning complains about parsing apt-key output, +# which we're not even doing. +ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -# Disable prompt during keyboard configuration. -ENV DEBIAN_FRONTEND=noninteractive - -RUN wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc | apt-key add - \ - && wget -qO /etc/apt/sources.list.d/lunarg-vulkan-$VULKAN_SDK_VERSION-bionic.list http://packages.lunarg.com/vulkan/$VULKAN_SDK_VERSION/lunarg-vulkan-$VULKAN_SDK_VERSION-bionic.list \ +RUN wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc \ + | apt-key add - \ + && wget -qO \ + "/etc/apt/sources.list.d/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \ + "http://packages.lunarg.com/vulkan/${VULKAN_SDK_VERSION?}/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \ && apt-get update \ && apt-get install -y vulkan-sdk nvidia-driver-440
diff --git a/build_tools/docker/rbe_toolchain/Dockerfile b/build_tools/docker/rbe_toolchain/Dockerfile index c2df299..878aca3 100755 --- a/build_tools/docker/rbe_toolchain/Dockerfile +++ b/build_tools/docker/rbe_toolchain/Dockerfile
@@ -21,23 +21,29 @@ FROM gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:1a8ed713f40267bb51fe17de012fa631a20c52df818ccb317aaed2ee068dfc61 -RUN apt-get update -RUN apt-get install -y python3 python3-pip -RUN python3 -m pip install --upgrade pip -RUN python3 -m pip install numpy +RUN apt-get update \ + && apt-get install -y \ + python3 \ + python3-pip \ + && python3 -m pip install --upgrade pip \ + && python3 -m pip install numpy -# Install dependencies for python3.6-dev -RUN apt-get install -y software-properties-common +# Dependency for python3.6-dev. Needs to be installed separately from the above +# for... some reason +RUN apt-get update && apt-get install -y software-properties-common + # apt-add-repository requires a version of python with the softwareproperties # module. To use this command, we: # 1. remove the symlink to python3 from python3.6 and symlink it to python3.5 # 2. run apt-add-repository with python3 = python3.5 # 3. resymlink python3 to /opt/python3.6/bin/python3.6 # See https://github.com/google/iree/issues/1966 for more information. -RUN rm /usr/bin/python3 && ln -s /usr/bin/python3.5 /usr/bin/python3 -RUN add-apt-repository ppa:deadsnakes/ppa -RUN rm /usr/bin/python3 && ln -s /opt/python3.6/bin/python3.6 /usr/bin/python3 +RUN rm /usr/bin/python3 \ + && ln -s /usr/bin/python3.5 /usr/bin/python3 \ + && add-apt-repository ppa:deadsnakes/ppa \ + && rm /usr/bin/python3 \ + && ln -s /opt/python3.6/bin/python3.6 /usr/bin/python3 # Install python3.6-dev -RUN apt-get update -RUN apt-get install -y python3.6 python3.6-dev +RUN apt-get update \ + && apt-get install -y python3.6 python3.6-dev
diff --git a/kokoro/gcp_ubuntu/bazel/bindings/build.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build.sh similarity index 100% rename from kokoro/gcp_ubuntu/bazel/bindings/build.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build.sh
diff --git a/kokoro/gcp_ubuntu/bazel/bindings/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build_kokoro.sh old mode 100644 new mode 100755 similarity index 73% rename from kokoro/gcp_ubuntu/bazel/bindings/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build_kokoro.sh index e2a9bd3..24cbabf --- a/kokoro/gcp_ubuntu/bazel/bindings/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build_kokoro.sh
@@ -16,28 +16,28 @@ # Build and test IREE's bindings within the gcr.io/iree-oss/bazel-bindings # image using Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR="${KOKORO_ARTIFACTS_DIR?}/github/iree" +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the bazel-bindings image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ gcr.io/iree-oss/bazel-bindings:prod \ - kokoro/gcp_ubuntu/bazel/bindings/build.sh + build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build.sh # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/common.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/common.cfg new file mode 100644 index 0000000..8a49430 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/common.cfg
@@ -0,0 +1,20 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Common configuration for Kokoro builds that run the bindings build with bazel +# on linux. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/google.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/google.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/main.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/main.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/presubmit.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/bazel/core/build.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build.sh similarity index 100% rename from kokoro/gcp_ubuntu/bazel/core/build.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build.sh
diff --git a/kokoro/gcp_ubuntu/bazel/core/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build_kokoro.sh old mode 100644 new mode 100755 similarity index 72% rename from kokoro/gcp_ubuntu/bazel/core/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build_kokoro.sh index 031eab8..da07cdd --- a/kokoro/gcp_ubuntu/bazel/core/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build_kokoro.sh
@@ -16,28 +16,28 @@ # Build and test IREE's core within the gcr.io/iree-oss/bazel image using # Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR="${KOKORO_ARTIFACTS_DIR?}/github/iree" +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the bazel image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ gcr.io/iree-oss/bazel:prod \ - kokoro/gcp_ubuntu/bazel/core/build.sh + build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build.sh # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/common.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/common.cfg new file mode 100755 index 0000000..3a22d10 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/common.cfg
@@ -0,0 +1,20 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Common configuration for Kokoro builds that run the core build with bazel on +# linux. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg new file mode 100755 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/google.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/google.cfg new file mode 100755 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/main.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/main.cfg new file mode 100755 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/presubmit.cfg new file mode 100755 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/bazel/integrations/build.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build.sh similarity index 100% rename from kokoro/gcp_ubuntu/bazel/integrations/build.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build.sh
diff --git a/kokoro/gcp_ubuntu/bazel/integrations/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh old mode 100644 new mode 100755 similarity index 73% rename from kokoro/gcp_ubuntu/bazel/integrations/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh index 1716266..c35d897 --- a/kokoro/gcp_ubuntu/bazel/integrations/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh
@@ -16,28 +16,28 @@ # Build and test IREE's integrations within the gcr.io/iree-oss/bazel-tensorflow # image using Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR="${KOKORO_ARTIFACTS_DIR?}/github/iree" +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the bazel-tensorflow image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ gcr.io/iree-oss/bazel-tensorflow:prod \ - kokoro/gcp_ubuntu/bazel/integrations/build.sh + build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build.sh # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/common.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/common.cfg new file mode 100644 index 0000000..eb31e55 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/common.cfg
@@ -0,0 +1,20 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Common configuration for Kokoro builds that run the integrations build with +# bazel on linux. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/google.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/google.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/main.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/main.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/presubmit.cfg new file mode 100644 index 0000000..50a7eed --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh old mode 100644 new mode 100755 similarity index 73% rename from kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh index f912073..329e226 --- a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh
@@ -16,28 +16,28 @@ # Cross-compile the project towards Android arm64-v8a with the # gcr.io/iree-oss/cmake-android image using Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR=${KOKORO_ARTIFACTS_DIR?}/github/iree +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the cmake-android image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ gcr.io/iree-oss/cmake-android:prod \ - kokoro/gcp_ubuntu/cmake/android/build.sh arm64-v8a + build_tools/kokoro/gcp_ubuntu/cmake/android/build.sh arm64-v8a # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg new file mode 100644 index 0000000..1376e08 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg
@@ -0,0 +1,20 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Common configuration for Kokoro builds that cross-compile IREE towards +# Android arm64-v8a using CMake. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/google.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/google.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/main.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/main.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/presubmit.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/android/build.sh b/build_tools/kokoro/gcp_ubuntu/cmake/android/build.sh similarity index 100% rename from kokoro/gcp_ubuntu/cmake/android/build.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/android/build.sh
diff --git a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh similarity index 87% rename from kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh index a56c847..f44aa82 100755 --- a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh
@@ -30,8 +30,8 @@ python3 --version # Print Vulkan related information: SDK version and GPU ICD version -vulkaninfo 2>/dev/null | grep "Vulkan Instance" -vulkaninfo 2>/dev/null | grep -A7 "VkPhysicalDeviceProperties" +vulkaninfo 2>/dev/null | grep "Vulkan Instance" || echo "Vulkan Instance not found!" +vulkaninfo 2>/dev/null | grep -A7 "VkPhysicalDeviceProperties" || echo "VkPhysicalDeviceProperties not found!" echo "Initializing submodules" ./scripts/git/submodule_versions.py init
diff --git a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh similarity index 64% rename from kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh index 051c0d0..0b2364a 100755 --- a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh
@@ -14,32 +14,32 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Build and test the project within the gcr.io/iree-oss/cmake using Kokoro. +# Build and test the project within the gcr.io/iree-oss/cmake image using +# Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR=${KOKORO_ARTIFACTS_DIR?}/github/iree +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the cmake image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ --env IREE_VULKAN_DISABLE=0 \ --gpus all \ gcr.io/iree-oss/cmake-nvidia:prod \ - kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh + build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build.sh # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -# TODO: enable this after making it work -#sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. -#ls -1a "${KOKORO_ARTIFACTS_DIR?}/" +ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg new file mode 100644 index 0000000..bdb9163 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Common configuration for Kokoro builds that run cmake on linux. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/google.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/google.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/main.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/main.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/presubmit.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/build.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build.sh similarity index 100% rename from kokoro/gcp_ubuntu/cmake/build.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build.sh
diff --git a/kokoro/gcp_ubuntu/cmake/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build_kokoro.sh similarity index 72% rename from kokoro/gcp_ubuntu/cmake/build_kokoro.sh rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build_kokoro.sh index 8c35e60..ee459ff 100755 --- a/kokoro/gcp_ubuntu/cmake/build_kokoro.sh +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build_kokoro.sh
@@ -15,28 +15,28 @@ # limitations under the License. # Build and test the project within the gcr.io/iree-oss/cmake using Kokoro. +# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which +# are set by Kokoro. -set -e set -x +set -e +set -o pipefail # Print the UTC time when set -x is on export PS4='[$(date -u "+%T %Z")] ' -# Kokoro checks out the repository here. -WORKDIR=${KOKORO_ARTIFACTS_DIR?}/github/iree +source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh" -# Mount the checked out repository, make that the working directory and run the -# tests in the cmake image. -docker run \ - --volume "${WORKDIR?}:${WORKDIR?}" \ - --workdir="${WORKDIR?}" \ - --rm \ +# Sets DOCKER_RUN_ARGS +docker_setup + +docker run "${DOCKER_RUN_ARGS[@]?}" \ gcr.io/iree-oss/cmake:prod \ - kokoro/gcp_ubuntu/cmake/build.sh + build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build.sh # Kokoro will rsync this entire directory back to the executor orchestrating the # build which takes forever and is totally useless. -sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* +rm -rf "${KOKORO_ARTIFACTS_DIR?}"/* # Print out artifacts dir contents after deleting them as a coherence check. ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/common.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/common.cfg new file mode 100644 index 0000000..49e6865 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/common.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Common configuration for Kokoro builds that run cmake on linux. + +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/google.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/google.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/google.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/main.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/main.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/main.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/presubmit.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/presubmit.cfg new file mode 100644 index 0000000..e4cc270 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/presubmit.cfg
@@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Copyright 2020 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. + +# Deliberately blank as everything necessary is configured in common files, but +# file must still exist to match corresponding (Google internal) job +# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/docker_common.sh b/build_tools/kokoro/gcp_ubuntu/docker_common.sh new file mode 100644 index 0000000..81dc0b3 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/docker_common.sh
@@ -0,0 +1,64 @@ +# Copyright 2020 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. + +# Functions for setting up Docker containers to run on Kokoro + +# Sets up files and environment to enable running all our Kokoro docker scripts. +# In particular, does some shenanigans to enable running with the current user. +# Some of this setup is only strictly necessary for Bazel, but it doesn't hurt +# for anything else. +# Requires that KOKORO_ROOT and KOKORO_ARTIFACTS_DIR have been set +# Sets the environment variable DOCKER_RUN_ARGS to be used by subsequent +# `docker run` invocations. +function docker_setup() { + # Setup to run docker as the current user. + # Provide a place to mount files that would normally be under /etc/ + # We don't just mount the real /etc/passwd and /etc/group because Google + # Linux workstations do some interesting stuff with user/group permissions + # such that they don't contain the information about normal users and we + # want these scripts to be runnable locally for debugging. + local fake_etc_dir="${KOKORO_ROOT?}/fake_etc" + mkdir -p "${fake_etc_dir?}" + + local fake_group="${fake_etc_dir?}/group" + local fake_passwd="${fake_etc_dir?}/group" + + cp /etc/passwd "${fake_group?}" + cp /etc/group "${fake_passwd?}" + getent group "$(id -g)" >> "${fake_group?}" + getent passwd "$(id -u)" >> "${fake_passwd?}" + + + local workdir="${KOKORO_ARTIFACTS_DIR?}/github/iree" + + DOCKER_RUN_ARGS=( + # Run as the current user and group + --user="$(id -u):$(id -g)" + # Make the source repository available + --volume="${workdir?}:${workdir?}" + --workdir="${workdir?}" + # Tell docker about the host users and groups. Bazel needs this + # information, but it also makes some other things more pleasant. + --volume="${fake_group?}:/etc/group:ro" + --volume="${fake_passwd?}:/etc/passwd:ro" + # Allow Bazel to write its special cache directories. This is the + # default path Bazel will write to. + --volume="${HOME?}/.cache/bazel:${HOME?}/.cache/bazel" + # Make gcloud credentials available. This isn't necessary when running + # in GCE but enables using this script locally with RBE. + --volume="${HOME?}/.config/gcloud:${HOME?}/.config/gcloud:ro" + # Delete the container after + --rm + ) +}
diff --git a/build_tools/kokoro/gcp_ubuntu/simulate_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/simulate_kokoro.sh new file mode 100755 index 0000000..38c6782 --- /dev/null +++ b/build_tools/kokoro/gcp_ubuntu/simulate_kokoro.sh
@@ -0,0 +1,54 @@ +#!/bin/bash + +# Copyright 2020 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. + +# Simulates the behavior of Kokoro on a local machine. +# Usage: +# ./kokoro/gcp_ubuntu/simulate_kokoro.sh build_tools/kokoro/gcp_ubuntu/bazel/core/build.sh +# +# Just does the part of the Kokoro setup that we care about and invokes the +# given build script. +# An optional second parameter can be used to specify a different repo to clone +# from. Especially useful for cloning the current git repo. +# ./kokoro/gcp_ubuntu/simulate_kokoro.sh build_tools/kokoro/gcp_ubuntu/bazel/core/build.sh "$PWD/.git" + +set -x +set -e +set -o pipefail + +RELATIVE_KOKORO_BUILD_SCRIPT="${1?}" +REPO_TO_CLONE="${2:-git@github.com:google/iree.git}" + +# Set up the temporary Kokoro directories +export KOKORO_ROOT="$(mktemp --directory --tmpdir kokoro-root-XXXXXX)" +mkdir -p "${KOKORO_ROOT?}/src/github" +export KOKORO_ARTIFACTS_DIR="${KOKORO_ROOT?}/src" +cd "${KOKORO_ARTIFACTS_DIR?}/github" + +# Clone the repo +git clone "${REPO_TO_CLONE?}" + +# The build script is assumed to be relative to the iree repo root. +KOKORO_BUILD_SCRIPT="${KOKORO_ARTIFACTS_DIR?}/github/iree/${RELATIVE_KOKORO_BUILD_SCRIPT?}" +chmod +x "${KOKORO_BUILD_SCRIPT?}" + +# This is where Kokoro starts its execution. +cd "${KOKORO_ARTIFACTS_DIR?}" + +# Run the actual script. +"${KOKORO_BUILD_SCRIPT?}" + +# Clean up after ourselves. +rm -rf "${KOKORO_ROOT?}"
diff --git a/build_tools/manylinux_py_setup.py b/build_tools/manylinux_py_setup.py new file mode 100755 index 0000000..abdd11d --- /dev/null +++ b/build_tools/manylinux_py_setup.py
@@ -0,0 +1,86 @@ +#!/opt/python/cp38-cp38/bin/python3 +# Copyright 2020 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. +"""Generates CMake arguments to build all manylinux python versions. + +manylinux containers have all python version linked under /opt/python. +This script scrapes them to get configuration, install deps, etc. + +Usage: + Install dependencies: + manylinux_py_setup.py deps + Get CMake arguments to build (typically via $() expansion): + manylinux_py_setup.py args +""" + +import os +from pathlib import Path +import subprocess +import sys +import sysconfig + + +def _get_python_exes(): + PYTHON_PARENT_PATH = Path("/opt/python") + return PYTHON_PARENT_PATH.glob("*/bin/python") + + +def install_deps(): + for python_exe in _get_python_exes(): + args = [ + str(python_exe), + "-m", + "pip", + "install", + "absl-py", + "numpy", + ] + print("EXEC:", " ".join(args)) + subprocess.check_call(args) + + +def dump_current(identifier): + print("-DIREE_MULTIPY_{}_EXECUTABLE='{}'".format(identifier, sys.executable)) + print("-DIREE_MULTIPY_{}_INCLUDE_DIRS='{}'".format( + identifier, sysconfig.get_config_var("INCLUDEPY"))) + # TODO: Print LIBRARIES for Windows and OSX + print("-DIREE_MULTIPY_{}_EXTENSION='{}'".format( + identifier, sysconfig.get_config_var("EXT_SUFFIX"))) + + +def dump_all(): + versions_ids = [] + for python_exe in _get_python_exes(): + identifier = python_exe.parent.parent.name + versions_ids.append(identifier) + # Invoke ourselves with a different interpreter/args to dump config. + subprocess.check_call( + [str(python_exe), __file__, "_current_args", identifier]) + print("-DIREE_MULTIPY_VERSIONS='{}'".format(";".join(versions_ids))) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("SYNTAX: mainlinux_py_setup.py {deps|args}") + sys.exit(1) + command = sys.argv[1] + if command == "args": + dump_all() + elif command == "_current_args": + dump_current(sys.argv[2]) + elif command == "deps": + install_deps() + else: + print("Unexpected command") + sys.exit(1)
diff --git a/build_tools/third_party/flatcc/BUILD.overlay b/build_tools/third_party/flatcc/BUILD.overlay new file mode 100644 index 0000000..3481995 --- /dev/null +++ b/build_tools/third_party/flatcc/BUILD.overlay
@@ -0,0 +1,99 @@ +# Copyright 2020 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. + +package(default_visibility = ["//visibility:public"]) + +# NOTE: we exclude JSON parsing/printing to avoid additional dependencies. +cc_library( + name = "runtime", + srcs = [ + "config/config.h", + "src/runtime/builder.c", + "src/runtime/emitter.c", + "src/runtime/refmap.c", + "src/runtime/verifier.c", + ], + hdrs = [ + "include/flatcc/flatcc_accessors.h", + "include/flatcc/flatcc_alloc.h", + "include/flatcc/flatcc_assert.h", + "include/flatcc/flatcc_builder.h", + "include/flatcc/flatcc_emitter.h", + "include/flatcc/flatcc_endian.h", + "include/flatcc/flatcc_epilogue.h", + "include/flatcc/flatcc_flatbuffers.h", + "include/flatcc/flatcc_identifier.h", + "include/flatcc/flatcc_iov.h", + "include/flatcc/flatcc_portable.h", + "include/flatcc/flatcc_prologue.h", + "include/flatcc/flatcc_refmap.h", + "include/flatcc/flatcc_rtconfig.h", + "include/flatcc/flatcc_types.h", + "include/flatcc/flatcc_unaligned.h", + "include/flatcc/flatcc_verifier.h", + "include/flatcc/reflection/flatbuffers_common_builder.h", + "include/flatcc/reflection/flatbuffers_common_reader.h", + ] + glob(["include/flatcc/portable/**/*.h"]), + copts = [ + "-Iexternal/com_github_dvidelabs_flatcc/config/", + "-Iexternal/com_github_dvidelabs_flatcc/include/", + ], + includes = [ + "include/", + ], + strip_include_prefix = "include", +) + +cc_library( + name = "compiler", + srcs = glob([ + "external/**/*.c", + "external/**/*.h", + "src/compiler/**/*.c", + "src/compiler/**/*.h", + ], exclude = [ + "external/lex/luthor.c", + "**/*_test.c", + ]), + hdrs = glob([ + "config/config.h", + "include/**/*.h", + ]), + textual_hdrs = [ + "external/lex/luthor.c", + ] + glob([ + "external/**/*.h", + ]), + copts = [ + "-Iexternal/com_github_dvidelabs_flatcc/config/", + "-Iexternal/com_github_dvidelabs_flatcc/external/", + "-Iexternal/com_github_dvidelabs_flatcc/include/", + ], +) + +cc_binary( + name = "flatcc", + srcs = [ + "src/cli/flatcc_cli.c", + ], + deps = [ + ":compiler", + ":runtime", + ], + copts = [ + "-Iexternal/com_github_dvidelabs_flatcc/config/", + "-Iexternal/com_github_dvidelabs_flatcc/external/", + "-Iexternal/com_github_dvidelabs_flatcc/include/", + ], +)
diff --git a/build_tools/third_party/flatcc/CMakeLists.txt b/build_tools/third_party/flatcc/CMakeLists.txt new file mode 100644 index 0000000..82b1cb2 --- /dev/null +++ b/build_tools/third_party/flatcc/CMakeLists.txt
@@ -0,0 +1,53 @@ +# Copyright 2020 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. + +set(FLATCC_ROOT "${IREE_ROOT_DIR}/third_party/flatcc/") + +# NOTE: we exclude JSON parsing/printing to avoid additional dependencies. +external_cc_library( + PACKAGE + flatcc + NAME + runtime + ROOT + ${FLATCC_ROOT} + INCLUDES + "${FLATCC_ROOT}/include" + SRCS + "src/runtime/builder.c" + "src/runtime/emitter.c" + "src/runtime/refmap.c" + "src/runtime/verifier.c" + HDRS + "include/flatcc/flatcc_accessors.h" + "include/flatcc/flatcc_alloc.h" + "include/flatcc/flatcc_assert.h" + "include/flatcc/flatcc_builder.h" + "include/flatcc/flatcc_emitter.h" + "include/flatcc/flatcc_endian.h" + "include/flatcc/flatcc_epilogue.h" + "include/flatcc/flatcc_flatbuffers.h" + "include/flatcc/flatcc_identifier.h" + "include/flatcc/flatcc_iov.h" + "include/flatcc/flatcc_portable.h" + "include/flatcc/flatcc_prologue.h" + "include/flatcc/flatcc_refmap.h" + "include/flatcc/flatcc_rtconfig.h" + "include/flatcc/flatcc_types.h" + "include/flatcc/flatcc_unaligned.h" + "include/flatcc/flatcc_verifier.h" + "include/flatcc/reflection/flatbuffers_common_builder.h" + "include/flatcc/reflection/flatbuffers_common_reader.h" + PUBLIC +)
diff --git a/build_tools/third_party/swiftshader/build_vk_swiftshader.sh b/build_tools/third_party/swiftshader/build_vk_swiftshader.sh old mode 100644 new mode 100755
diff --git a/colab/README.md b/colab/README.md index d35df2a..b0bfe52 100644 --- a/colab/README.md +++ b/colab/README.md
@@ -1,7 +1,7 @@ # Google Colaboratory (Colab) Notebooks To run these notebooks with a local runtime, refer to the -[Using Colab docs](../docs/using_colab.md). +[Using Colab docs](../docs/using_iree/using_colab.md). Hosted/remote runtimes are not yet supported.
diff --git a/docs/design_docs/codegen_passes.md b/docs/design_docs/codegen_passes.md new file mode 100644 index 0000000..e3fd371 --- /dev/null +++ b/docs/design_docs/codegen_passes.md
@@ -0,0 +1,640 @@ +# IREE CPU/GPU Code Generation Pipeline + +This document is intended to provide an overview of the codegen pipeline within +IREE used to generate CPU/GPU code. It intends to give an overview of the main +passes used, the objective of the pass, the current implementation, and what it +is expected to achieve in the long term. + +Note that while the code generation pipeline supports dynamic shapes, this work +is very preliminary. The description of this is not covered here. + +## Input to the codegen pipeline + +The input to the code generation pipeline is the module within the +`hal.executable.target` operation. Functions within this module that do __not__ +have `Visibility::Private` are the *entry point* functions of the dispatch +region. These are the functions that are *invoked* by the IREE runtime. In +addition, each dispatch region also contains a `hal.interface` operation that +describes the ABI to use for the dispatch region. Two examples of the input to +the code generation pipeline are shown below. In both of these, a single +dispatch function contains a sequence of MHLO operations that the dispatch +region creation has grouped into a single region. Ideally the grouped operations +are fused into a single kernel. + +```mlir +hal.executable.target "vulkan*" { + module attributes {spv.target_env = ...} { + func @main_ex_dispatch() { + %c0 = constant 0 : index + %0 = hal.interface.load.tensor @legacy_io::@arg0, + offset = %c0 : tensor<4x5xf32> + %1 = hal.interface.load.tensor @legacy_io::@arg1, + offset = %c0 : tensor<5x10xf32> + %2 = "mhlo.dot"(%0, %1) {precision_config = ["DEFAULT", "DEFAULT"]} : + (tensor<4x5xf32>, tensor<5x10xf32>) -> tensor<4x10xf32> + hal.interface.store.tensor %2, @legacy_io::@ret0, + offset = %c0 : tensor<4x10xf32> + return + } + hal.interface @legacy_io attributes {sym_visibility = "private"} { + hal.interface.binding @arg0, set=0, binding=0, + type="StorageBuffer", access="Read" + hal.interface.binding @arg1, set=0, binding=1, + type="StorageBuffer", access="Read" + hal.interface.binding @ret0, set=0, binding=2, + type="StorageBuffer", access="Write|Discard" + } + } +} +``` +<a name="snippet1"></a> +Snippet 1 : Dispatch region with matrix-matrix multiply operation. + +```mlir +hal.executable.target "vulkan*" { + module attributes {spv.target_env = ...} { + func @main_ex_dispatch() { + %c0 = constant 0 : index + %0 = hal.interface.load.tensor @legacy_io::@arg0, + offset = %c0 : tensor<10x5xf32> + %1 = hal.interface.load.tensor @legacy_io::@arg1, + offset = %c0 : tensor<10x5xf32> + %2 = hal.interface.load.tensor @legacy_io::@arg2, + offset = %c0 : tensor<10x5xf32> + %3 = "mhlo.add"(%0, %1) : + (tensor<10x5xf32>, tensor<10x5xf32>) -> tensor<10x5xf32> + %4 = "mhlo.multiply"(%3, %2) : + (tensor<10x5xf32>, tensor<10x5xf32>) -> tensor<10x5xf32> + hal.interface.store.tensor %4, @legacy_io::@ret0, + offset = %c0 : tensor<10x5xf32> + return + } + hal.interface @legacy_io attributes {sym_visibility = "private"} { + hal.interface.binding @arg0, set=0, binding=0, + type="StorageBuffer", access="Read" + hal.interface.binding @arg1, set=0, binding=1, + type="StorageBuffer", access="Read" + hal.interface.binding @arg2, set=0, binding=2, + type="StorageBuffer", access="Read" + hal.interface.binding @ret0, set=0, binding=3, + type="StorageBuffer", access="Write|Discard" + } + } +} +``` +<a name="snippet2"></a> +Snippet 2 : Dispatch region with element-wise operations. + +__Roadmap Note__: The current implementation might not actually fuse the +operations grouped into a dispatch region into a single kernel. It is possible +to end up with multiple kernels per dispatch region. Over time we plan to address +this by using fusion at different levels (see below). + +The inputs to the dispatch region are materialized within the entry point +function using the `hal.interface.load.tensor` operation, This operation returns +a `tensor` view of the buffer used to store the inputs. Similarly the result of +the dispatch region are *written* out using the `hal.interface.store.tensor` +operation. + +The main constraint that the code generation operates under is that it should +not require additional (temporary) buffers to execute the operations grouped +together within a dispatch region. The rationale behind this constraint is that +buffer allocation/synchronization in IREE happens at the granularity of dispatch +regions, allowing the scheduler to make better decision about where to insert +appropriate synchronizations. + +The IR after all the passes used in the lowering from MHLO to SPIR-V for the +above two examples can be found here ([matrix-matrix multiply op][DotAfterAll], +[elementwise ops][PwAfterAll]). Below is a description of the major passes used. + +## Conversion from MHLO dialect to Linalg on buffers + +The code generation pipeline heavily relies on use of [Structured +Operations][LinalgRationale], specifically the [Linalg Dialect][LinalgDialect]. +Both, the Linalg operations on `tensor`s and on `memref`s are central to the +progressive lowering approach followed here. The first part of the code +generation pipeline is to convert the MHLO operations on `tensor`s to Linalg +operation on `memref`s. This part of the pipeline is common to both CPU and GPU +code generation. + +The steps involved in this conversion is shown below. Each of the arrows +represents a pass in the pipeline: + + + +The next sections describe each of these passes in more detail. + + +### MHLO to Linalg on tensors + +The first step is to convert MHLO operations to Linalg on tensors. This is done +using the [HLOToLinalgPass][HLOToLinalgPass] from Tensorflow. An example of the +conversion is shown below, where each of the `mhlo.add` and `mhlo.multiply` +operations are converted to `linalg.generic` operations on tensors. + +```mlir +#map0 = affine_map<(d0, d1) -> (d0, d1)> +%3 = linalg.generic + {args_in = 2 : i64, args_out = 1 : i64, + indexing_maps = [#map0, #map0, #map0], + iterator_types = ["parallel", "parallel"]} %0, %1 { + ^bb0(%arg0: f32, %arg1: f32): // no predecessors + %5 = addf %arg0, %arg1 : f32 + linalg.yield %5 : f32 + } : tensor<10x5xf32>, tensor<10x5xf32> -> tensor<10x5xf32> +%4 = linalg.generic + {args_in = 2 : i64, args_out = 1 : i64, + indexing_maps = [#map0, #map0, #map0], + iterator_types = ["parallel", "parallel"]} %3, %2 { + ^bb0(%arg0: f32, %arg1: f32): // no predecessors + %5 = mulf %arg0, %arg1 : f32 + linalg.yield %5 : f32 + }: tensor<10x5xf32>, tensor<10x5xf32> -> tensor<10x5xf32> +``` +<a name="snippet3"></a> +Snippet 3 : MHLO to Linalg conversion for [element-wise operations](#snippet2) + +At the time of writing the representation of Linalg on `tensor`s does not model +reduction iterator types completely. Specifically, the reduction in Linalg is +modeled using read-modify-write approach, i.e. each iteration of the reduction +loop reads the value stored in the output, adds its contribution, and writes +back to the same location. This means the output has to be *initialized* to the +null element of the reduction operator (i.e. 0 if the reduction is done using +addition). This works for operations on buffers. Since tensors are SSA values +they cannot be updated in-place. As a result, the reduction semantics does not +map as well to `tensor`s. For now it is treated as a convention that when the +Linalg operation is converted to use `memref`s it has to be initialized +appropriately before performing the reduction. Due to this, the conversion from +MHLO op to Linalg op is only done for operations which do not need a *reduction* +iterator type in the converted Linalg op. Consequently, only element-wise +operations, broadcast operations and data movement operations (like copy and +transpose) are converted to Linalg operations at this stage. + +__Roadmap note__: One long term solution for the above is to have operations on +tensors that have *reduction* iterator type to take an additional argument that +contains the initial value of the result tensor. When the operation is converted +to use `memref`s, the buffer for the initial value operand can be reused for the +result. The details involved have not been fully worked out yet. + +### Fusion of Linalg on tensor operations + +The Linalg on `tensor` operations generated at the previous step are fused using +the [LinalgFusionOfTensorOps][LinalgFusionOfTensorOps] from MLIR. Since +`tensor`s are SSA values, fusion at this stage can be done without using alias +analysis or dependence analysis based on reads and writes. Instead the use-def +chains for the `tensor` values can be used to implement producer-consumer +fusion. This stage fuses most elementwise operations, broadcast operations and +data movement operations. An example of the fused op is shown below. + +```mlir +#map0 = affine_map<(d0, d1) -> (d0, d1)> +%3 = linalg.generic + {args_in = 3 : i64, args_out = 1 : i64, + indexing_maps = [#map0, #map0, #map0, #map0], + iterator_types = ["parallel", "parallel"]} %0, %1, %2 { + ^bb0(%arg0: f32, %arg1: f32, %arg2: f32): // no predecessors + %4 = addf %arg0, %arg1 : f32 + %5 = mulf %4, %arg2 : f32 + linalg.yield %5 : f32 + }: tensor<?x5xf32>, tensor<?x5xf32>, tensor<?x5xf32> -> tensor<?x5xf32> +``` +<a name="snippet4"></a> +Snippet 4: Fusion of Linalg operation on tensors for element-wise operations +shown in [Snippet 3](#snippet3) + +### Conversion of Linalg on tensors to Linalg on buffers + +Post fusion all the operation on `tensor`s are converted to analogous operations +on `memref`s. In general, this requires a buffer allocation pass. In IREE, +buffer allocation happens at the granularity of dispatch region, and as +mentioned [earlier](#input-to-the-codegen-pipeline), the dispatch region is not +expected to use any additional temporary buffers. So instead of having another +buffer allocation pass within the code generation pipeline, a simpler approach +is used within IREE: + +- For each `hal.interface.store.tensor` an `iree.placeholder` operation is + created. The latter uses the same `hal.interface.binding` as the former, but + returns a `memref` view of the output of the dispatch region instead of a + `tensor` view. This `iree.placeholder` operation is added to start of the + entry point function. + +- A map is constructed that for a given `tensor` records the `memref` value to + use during the conversion. In this map the `tensor` value used in the + `hal.interface.store.tensor` is mapped to the `memref` value returned by the + created `iree.placeholder` operation. + +- The Dialect Conversion framework is used to implement a set of patterns that + convert from operations on `tensor`s to operation on `memref`s, + + - A `hal.interface.load.tensor`, is replaced with an `iree.placeholder` to + get the `memref` view of the input to the dispatch region. + - All Linalg operation on `tensor`s (expected to be just `linalg.generic` + or `linalg.indexed_generic` operations) are converted to the + corresponding operation on `memref`s. Instead of returning a `tensor` + value the converted operation takes an additional `memref` operand as + argument. This `memref` is where the result of the operation is + populated. Current implementation looks for the `memref` to use from the + map constructed previously. If there is no `memref` associated with the + result `tensor` the conversion fails. + - At this stage, any `mhlo` operation not converted to a Linalg operation + are directly converted to a Linalg operation on buffers. This is done + for operations that when converted to Linalg have a *reduction* iterator + type. Some examples of ops converted this way are + + - `mhlo.dot` + - `mhlo.reduce` + - `mhlo.conv` + - `mhlo.reduce_window`. + + Since the specification of the Linalg operations require the output + `memref` to be initialized appropriately, a `linalg.fill` operation is + used to achieve this. + +__Roadmap Note__ : Right now the code-generation pipeline relies on fusion of +operations on tensor level. In the near future, we want to be able to fuse +operations like `linalg.matmul` and `linalg.conv` with consumers/producers that +are element-wise operations using the [fusion of Linalg operation on +`memref`s][LinalgFusionOnBuffers]. + +At this stage of the compilation all operations must have been converted to +Linalg operations on buffers. Shown below are the IR at the end of this stage +for the two examples in Snippets 1 and 2. + +```mlir +func @main_ex_dispatch() { + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<4x10xf32> + %c0 = constant 0 : index + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<4x5xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<5x10xf32> + %cst = constant 0.000000e+00 : f32 + linalg.matmul(%1, %2, %0) : + memref<4x5xf32>, memref<5x10xf32>, memref<4x10xf32> + return +} +``` +<a name="snippet5"></a> +Snippet 5 : Matrix-matrix multiply after conversion to +Linalg operation on `memref`s. + +```mlir +#map0 = affine_map<(d0, d1) -> (d0, d1)> +func @main_ex_dispatch() { + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<10x5xf32> + %c0 = constant 0 : index + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<10x5xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<10x5xf32> + %3 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg2} : memref<10x5xf32> + linalg.generic + {args_in = 3 : i64, args_out = 1 : i64, + indexing_maps = [#map0, #map0, #map0], + iterator_types = ["parallel", "parallel"]} %1, %2, %3, %0 { + ^bb0(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32): // no predecessors + %4 = addf %arg0, %arg1 : f32 + %5 = mulf %4, %arg2 : f32 + linalg.yield %5 : f32 + }: memref<10x5xf32>, memref<10x5xf32>, memref<10x5xf32>, memref<10x5xf32> + return +} +``` +<a name="snippet6"></a> +Snippet 6 : Elementwise operations after conversion to Linalg operation on +`memref`s + +The rest of the code-generation differs on whether the compilation is for CPU +(using LLVM) or for GPU (using SPIR-V). + +## Conversion from Linalg on buffers to SPIR-V dialect + +The following sections describe the progressive lowering of Linalg operation on +buffers to SPIR-V dialect. Once lowered to the SPIR-V dialect, it can be +serialized into a SPIR-V binary using the [serialization mechanism provided by +the SPIR-V dialect][SpirvSerialization]. The steps involved in the lowering are +described below, with each of the arrows representing a pass. + + + +These passes are described below in more detail. + +### Tiling and fusion on buffer operations + +The GPU hardware typically provides multiple-levels of compute hierarchy, namely +*workgroup* level, *subgroup* level and *workitem* level. These map to blocks, +warps and threads, respectively, in CUDA terminology. Tiling is a way to map the +computations to each level of the compute hierarchy. For example 3-D tiling a +`linalg.matmul` operation decomposes the computation into several tiled +matrix-matrix multiplies. [Tiling transformation in Linalg +dialect][LinalgTiling] generates the outer-loops that iterate over tiled +`linalg.matmul` operations. These outer loops can be mapped to different +workgroups, if they are parallel. The tiled `linalg.matmul` operation can be +further tiled to map to subgroups. Finally, the tiled operation can be lowered +to loops with individual iterations mapped to workitems. The +[LinalgTileAndFusePass][LinalgTileAndFuse] uses the Linalg Tiling patterns +([defined here][LinalgTilingPatterns]) to tile operations like `linalg.matmul`, +`linalg.conv` and `linalg.*_pooling`. The result of tiling the code in Snippet 5 +is shown below. As expected there are 2-parallel loops that iterate over tiles +of the original iteration space (i.e. inter-tile loops) and can be distributed +to workgroups. + +```mlir +func @main_ex_dispatch_0() + attributes { + spv.entry_point_abi = {local_size = dense<[8, 8, 1]> : vector<3xi32>}} { + %cst = constant 0.000000e+00 : f32 + %c0 = constant 0 : index + %c4 = constant 4 : index + %c10 = constant 10 : index + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<4x10xf32> + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<4x5xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<5x10xf32> + linalg.fill(%0, %cst) : memref<4x10xf32>, f32 + scf.parallel (%arg0, %arg1) = (%c0, %c0) to (%c4, %c10) step (%c8, %c8) { + scf.for %arg2 = %c0 to %c5 step %c4 { + ... + %5 = subview %1[%arg0, %arg2]... + ... + %8 = subview %2[%arg2, %arg1]... + ... + %11 = subview %0[%arg0, %arg1].. + linalg.matmul {__internal_linalg_transform__ = "workgroup"} %5, %8, %11... + } + scf.yield + } + return +} +``` +<a name="snippet7"></a> +Snippet 7 : `linalg.matmul` after tiling. + +#### Tile Size and Workgroup Size + +When operations that are to be tiled exist within the dispatch function (like +`linalg.matmul` or `linalg.conv`), this pass also decides the +1. Tile size to be used for the tiling. +1. The workgroup size to be used. + +The tile size and workgroup size are closely linked since the code within the +tiled loops are to be collectively executed by the entire workgroup. In other +words, all workitems in the workgroup collaborate to execute the tiled +`linalg.matmul`. + +__Roadmap Note__ : Currently the tile sizes used in this pass are hard-wired. +Not much effort has been put into finding ideal tile size for each operation on +different hardware. The value used is meant to be a baseline to test +functionality, with performance considerations addressed over time. + +#### Markers + +Downstream passes have to handle tiled Linalg operations and untiled Linalg +operation that might exist in the same function in different ways. For example, +while the former are to be executed collectively by workitems within a +workgroup, the latter have to be executed by all workitems across +workgroups. One way to distinguish these two operations is to use the marker +mechanism in Linalg ([LinalgMarker][LinalgTilingPatterns]). This is a `StrAttr` +whose value can be used to encode the scope of the operation. For example, in +Snippet 7 above, the tiled `linalg.matmul` operation has a marker `workgroup` to +indicate that this operation needs to be executed by a workgroup in a collective +manner. At this time, the code-generation pipeline uses only the `workgroup` +marker. + +__Roadmap Note__ : Markers are meant to be short-lived, ideally set and consumed +within the same pass. In the current pipeline the lifetime spans passes to allow +lowering to different hierarchies. The separate passes that implement the +lowering from Linalg to SPIR-V can be combined into a single pass, relying A -> +B -> C translation mechanism of the Dialect Conversion framework to implement +the progressive lowering. In interest of separation of concerns and for better +debuggability these passes are kept separate at the cost of having lifetimes of +markers span passes. + +#### Promoting subviews to use workgroup local memory and use of synchronizations + +`Workgroup` memory (or `shared memory` in CUDA terminology) can be used to +prefetch the inputs to the tiled operation. For example in the matrix-matrix +multiply case, the same data row (column) of the LHS (RHS) matrix is read by +multiple workitems. Prefetching the data into `Workgroup` memory can reduce the +number of loads to `StorageClass` memory by an order of magnitude. This +transformation can be achieved by using the [`Linalg +Promotion`][LinalgPromotionPatterns] which modifies the `subview`s that are the +operands to the tiled Linalg operation to use a new `memref` object. The size of +this `memref` is computed from the size of the `subview`. This `memref` object +is later lowered to use `Workgroup` memory Storage Class. The snippet below +shows this transformation when applied to `linalg.matmul` (along with +tiling). The newly created `memref` objects are annotated with the memory space +`3` to indicate that they are to be lowered to use `Workgroup` memory. The copy +of data from the original `memref` into the new `memref`, as well as the +necessary synchronization constructs are generated as well. Note the memory +space annotation used here is consistent with what [address space annotations +used in NVVM][NVVMAddressSpace]. + +```mlir +func @matmul_tile() + attributes { + spv.entry_point_abi = {local_size = dense<[8, 8, 1]> : vector<3xi32>}} { + %c96 = constant 96 : index + %c4 = constant 4 : index + %c8 = constant 8 : index + %c0 = constant 0 : index + %c1 = constant 1 : index + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<96x96xf32> + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<96x96xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<96x96xf32> + scf.parallel (%arg0, %arg1) = (%c0, %c0) to (%c96, %c96) step (%c8, %c8) { + scf.for %arg2 = %c0 to %c96 step %c4 { + ... + %5 = subview %0[%arg0, %arg2]... + ... + %8 = subview %1[%arg2, %arg1]... + ... + %11 = subview %2[%arg0, %arg1]... + %12 = alloc(%c8, %c4) : memref<?x?xf32, 3> + %13 = subview %12[%c0, %c0]... + %14 = alloc(%c4, %c8) : memref<?x?xf32, 3> + %15 = subview %14[%c0, %c0]... + linalg.copy(%5, %13) {__internal_linalg_transform__ = "workgroup"} + : memref<?x?xf32, #map2>, memref<?x?xf32, #map2, 3> + spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" + linalg.copy(%8, %15) {__internal_linalg_transform__ = "workgroup"} + : memref<?x?xf32, #map2>, memref<?x?xf32, #map2, 3> + spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" + linalg.matmul {__internal_linalg_transform__ = "workgroup"} %13, %15, %11... + spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" + dealloc %12 : memref<?x?xf32, 3> + dealloc %14 : memref<?x?xf32, 3> + } + scf.yield + } + return +} +``` + +<a name="snippet8"></a> +Snippet 8: `linalg.matmul` after tiling and promotion of operand subviews to use +`Workgroup` memory. + +### Distributing to workgroups and workitems + +After tiling the operations within the dispatch functions are either +`scf.parallel` operations or Linalg operations. + +- The outer `scf.parallel` operations represent parallel loops that are to be + distributed across workgroups. The distribution here assumes that the number + of workgroups along each dimension is equal to the number of iterations of the + `scf.parallel` operation. + +- Linalg operations that are not tiled, and are therefore __not within__ `scf` + operations, are lowered to loops. The resulting outer `scf.parallel` operations are + collapsed to have a single induction variable. This loop is then distributed + across workitems using their `GlobalInvocationId`, (which is same as + `blockIdx * blockDim + threadIdx` in CUDA terminology). + +- Linalg operations that are tiled, and are therefore __within__ `scf` + operations, are lowered to loops and the iterations of the `scf.parallel` + operations are mapped to workitems using their `LocalInvocationId` (which is + same as `threadIdx` in CUDA terminology). Note that these operations are + tagged with the `workgroup` marker which makes it easy to disambiguate from + the case where Linalg operations are outside of `scf` operations. Here too, + the distribution assumes that the workgroup size is greater than or equal to + the number of iterations of the partitioned loop. + +These transformations are applied by the +[`ConvertToGPUPass`][ConvertToGPU]. Below is the result of applying this pass to +Snippet 7. The outer `scf.parallel` loop is distributed across workgroups. The +tiled `linalg.matmul` operation is lowered to loops, and the outer +`scf.parallel` operation generated during this lowering are distributed across +workitems within the workgroup. + +```mlir +func @main_ex_dispatch_0_dispatch_1() + attributes { + spv.entry_point_abi = {local_size = dense<[8, 8, 1]> : vector<3xi32>}} { + %c5 = constant 5 : index + %c8 = constant 8 : index + %c4 = constant 4 : index + %c0 = constant 0 : index + %c1 = constant 1 : index + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<4x10xf32> + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<4x5xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<5x10xf32> + %3 = "gpu.block_id"() {dimension = "x"} : () -> index + %4 = muli %3, %c8 : index + scf.for %arg0 = %c0 to %c5 step %c4 { + ... + %9 = subview %1[0, %arg0] + ... + %14 = subview %2[%arg0, %4] + %15 = subview %0[0, %4] + %16 = "gpu.thread_id"() {dimension = "x"} : () -> index + %17 = "gpu.thread_id"() {dimension = "y"} : () -> index + %18 = cmpi "slt", %17, %c4 : index + %19 = cmpi "slt", %16, %13 : index + %20 = and %18, %19 : i1 + scf.if %20 { + scf.for %arg1 = %c0 to %8 step %c1 { + %21 = load %9[%17, %arg1] : memref<4x?xf32, #map0> + %22 = load %14[%arg1, %16] : memref<?x?xf32, #map1> + %23 = load %15[%17, %16] : memref<4x?xf32, #map1> + %24 = mulf %21, %22 : f32 + %25 = addf %23, %24 : f32 + store %25, %15[%17, %16] : memref<4x?xf32, #map1> + } + } + } + return +} +``` +<a name="snippet9"></a> +Snippet 9: `linalg.matmul` after distributing parallel inter-tile loops to +workgroups and intra-tile loops to workitems. + +[Snippet 6](#snippet6) shows the fused element-wise operations represented using +a `linalg.generic` operation. This operation is not tiled in the +`LinalgTileAndFusePass`. So the `ConvertToGPUPass` lowers this operation to +`scf.parallel` loops, which are collapsed into a `scf.parallel` operation with a +single induction variable. This loop is then distributed across workitems using +the `GlobalInvocationId`. The resulting IR is shown below. + +```mlir +func @main_ex_dispatch_0() + attributes { + spv.entry_point_abi = {local_size = dense<[32, 1, 1]> : vector<3xi32>}} { + %c50 = constant 50 : index + %c5 = constant 5 : index + %0 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@ret0} : memref<10x5xf32> + %1 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg0} : memref<10x5xf32> + %2 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg1} : memref<10x5xf32> + %3 = iree.placeholder for "interface buffer" + {binding = @legacy_io::@arg2} : memref<10x5xf32> + %4 = "gpu.block_id"() {dimension = "x"} : () -> index + %5 = "gpu.block_dim"() {dimension = "x"} : () -> index + %6 = "gpu.thread_id"() {dimension = "x"} : () -> index + %7 = muli %4, %5 : index + %8 = addi %7, %6 : index + %9 = cmpi "slt", %8, %c50 : index + scf.if %9 { + %10 = divi_signed %8, %c5 : index + %11 = remi_signed %8, %c5 : index + %12 = load %1[%10, %11] : memref<10x5xf32> + %13 = load %2[%10, %11] : memref<10x5xf32> + %14 = load %3[%10, %11] : memref<10x5xf32> + %15 = addf %12, %13 : f32 + %16 = mulf %15, %14 : f32 + store %16, %0[%10, %11] : memref<10x5xf32> + } + return +} +``` +<a name="snippet10"></a> +Snippet 10: Distributing the iterations for pointwise operations for GPU execution. + +### Lowering to SPIR-V dialect + +The last step is to take the result of the previous pass and lowering it to +SPIR-V dialect. Since SPIR-V dialect is *closed*, i.e. it has a separate type +system, its best to lower all the operations to SPIR-V in one step. This is done +by applying all the patterns that lower all the different IR constructs into +SPIR-V within the [`ConvertToSPIRVPass`][ConvertToSPIRV]. These are + +- [GPU dialect to SPIR-V conversion][GPUToSPIRV]. +- [SCF dialect to SPIR-V conversion][SCFToSPIRV]. +- [Standard dialect to SPIR-V conversion][StandardToSPIRV]. +- Patterns that lower the `iree.placeholder` instruction into a SPIR-V. + +Once applied the resulting IR is in SPIR-V dialect that can be serialized to a +SPIR-V binary. + +[ConvertToGPU]: https://github.com/google/iree/blob/main/iree/compiler/Conversion/LinalgToSPIRV/ConvertToGPUPass.cpp +[ConvertToSPIRV]: https://github.com/google/iree/blob/main/iree/compiler/Conversion/LinalgToSPIRV/ConvertToSPIRVPass.cpp +[DotAfterAll]: https://gist.github.com/MaheshRavishankar/9e2d406296f469515c4a79bf1e7eef44 +[GPUToSPIRV]: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/Conversion/GPUToSPIRV/ConvertGPUToSPIRV.h +[HLOToLinalgPass]: https://github.com/tensorflow/tensorflow/blob/75c40f6bff2faa3d90a375dfa4025b2e6e2d7a3d/tensorflow/compiler/mlir/xla/transforms/passes.h#L67 +[LinalgDialect]: https://mlir.llvm.org/docs/Dialects/Linalg/ +[LinalgFusionOnBuffers]: https://github.com/llvm/llvm-project/blob/ef868a848e6def288d2df7a1b3ebe09463afc8d0/mlir/include/mlir/Dialect/Linalg/Utils/Utils.h#L86 +[LinalgFusionOfTensorOps]: https://github.com/llvm/llvm-project/blob/80cb25cbd555f9634836b766c86aead435b60eaa/mlir/include/mlir/Dialect/Linalg/Passes.td#L30 +[LinalgPromotionPatterns]: https://github.com/llvm/llvm-project/blob/303a7f7a26e2aae1cb85f49dccbc0b5d14e0b2e0/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h#L358 +[LinalgRationale]: https://mlir.llvm.org/docs/Rationale/RationaleLinalgDialect/ +[LinalgTileAndFuse]: https://github.com/google/iree/blob/main/iree/compiler/Conversion/LinalgToSPIRV/LinalgTileAndFusePass.cpp +[LinalgTiling]: https://mlir.llvm.org/docs/Dialects/Linalg/#set-of-key-transformationsa-namekey_transformationsa +[LinalgTilingPatterns]: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h +[NVVMAddressSpace]: https://docs.nvidia.com/cuda/nvvm-ir-spec/index.html#address-space +[PwAfterAll]: https://gist.github.com/MaheshRavishankar/02cdd22f7c99e568f933244b5a679510 +[SCFToSPIRV]: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/Conversion/SCFToSPIRV/SCFToSPIRV.h +[SpirvSerialization]: https://mlir.llvm.org/docs/Dialects/SPIR-V/#serialization-and-deserialization +[StandardToSPIRV]: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/Conversion/StandardToSPIRV/ConvertStandardToSPIRV.h
diff --git a/docs/dynamic_shapes.md b/docs/design_docs/dynamic_shapes.md similarity index 100% rename from docs/dynamic_shapes.md rename to docs/design_docs/dynamic_shapes.md
diff --git a/docs/function_abi.md b/docs/design_docs/function_abi.md similarity index 99% rename from docs/function_abi.md rename to docs/design_docs/function_abi.md index 797f2f6..71d91bb 100644 --- a/docs/function_abi.md +++ b/docs/design_docs/function_abi.md
@@ -1,4 +1,4 @@ -# Function signatures +# Function Signatures A key job of the IREE compiler and runtime is capturing function call semantics from the originating system and providing mechanisms so that invocations can be
diff --git a/docs/design_docs/hlo_to_linalg.png b/docs/design_docs/hlo_to_linalg.png new file mode 100755 index 0000000..469ed26 --- /dev/null +++ b/docs/design_docs/hlo_to_linalg.png Binary files differ
diff --git a/docs/design_docs/linalg_to_spirv.png b/docs/design_docs/linalg_to_spirv.png new file mode 100755 index 0000000..fd6aee7 --- /dev/null +++ b/docs/design_docs/linalg_to_spirv.png Binary files differ
diff --git a/docs/simple_ir_walkthrough.md b/docs/design_docs/simple_ir_walkthrough.md similarity index 99% rename from docs/simple_ir_walkthrough.md rename to docs/design_docs/simple_ir_walkthrough.md index 1dfcb49..68f51a8 100644 --- a/docs/simple_ir_walkthrough.md +++ b/docs/design_docs/simple_ir_walkthrough.md
@@ -1,5 +1,7 @@ # Simple IR Walkthrough +Note that this doc is quite outdated. We expect to update it soon. + ## Overview This walks through the process of lowering TensorFlow python to an IREE module,
diff --git a/docs/roadmap_design.md b/docs/design_roadmap.md similarity index 100% rename from docs/roadmap_design.md rename to docs/design_roadmap.md
diff --git a/docs/benchmarking.md b/docs/developing_iree/benchmarking.md similarity index 100% rename from docs/benchmarking.md rename to docs/developing_iree/benchmarking.md
diff --git a/docs/contributor_tips.md b/docs/developing_iree/contributor_tips.md similarity index 89% rename from docs/contributor_tips.md rename to docs/developing_iree/contributor_tips.md index 05fb52e..03ddffc 100644 --- a/docs/contributor_tips.md +++ b/docs/developing_iree/contributor_tips.md
@@ -2,11 +2,11 @@ This is an opinionated guide documenting workflows that some members of the team have found useful. It is focused on meta-tooling, not on IREE code specifically -(you will find the latter in the [Developer Overview](../developer_overview.md)) -It is certainly possible to use workflows other than these, but some common -tasks, especially for maintainers will likely be made easier if you use these -flows. It assumes a basic knowledge of `git` and GitHub and suggests some -specific ways of using it. +(you will find the latter in the [Developer Overview](developer_overview.md)) It +is certainly possible to use workflows other than these, but some common tasks, +especially for maintainers will likely be made easier if you use these flows. It +assumes a basic knowledge of `git` and GitHub and suggests some specific ways of +using it. ## Git Structure
diff --git a/docs/developer_overview.md b/docs/developing_iree/developer_overview.md similarity index 89% rename from docs/developer_overview.md rename to docs/developing_iree/developer_overview.md index 56fb5f8..ec900f5 100644 --- a/docs/developer_overview.md +++ b/docs/developing_iree/developer_overview.md
@@ -150,7 +150,7 @@ and executes it as a series of [googletest](https://github.com/google/googletest) tests. This is the test runner for the IREE -[check framework](https://github.com/google/iree/tree/main/docs/testing_guide.md#end-to-end-tests). +[check framework](https://github.com/google/iree/tree/main/docs/developing_iree/testing_guide.md#end-to-end-tests). ```shell $ bazel run iree/tools:iree-translate -- \ @@ -207,6 +207,28 @@ accept a number where 0, 1, 2, 3 stands for info, warning, error, and fatal error respectively. +#### Read inputs from a file + +All the IREE tools support reading input values from a file. This is quite +useful for debugging. Use `-help` for each tool to see what the flag to set. The +inputs are expected to be newline-separated. Each input should be either a +scalar or a buffer. Scalars should be in the format `type=value` and buffers +should be in the format `[shape]xtype=[value]`. For example: + +``` +1x5xf32=1,-2,-3,4,-5 +1x5x3x1xf32=15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 +``` + +#### `iree-flow-trace-dispatch-tensors` + +This flag will enable tracing inputs and outputs for each dispatch function. It +is easier to narrow down test cases, since IREE breaks a ML workload into +multiple dispatch function. When the flag is on, IREE will insert trace points +before and after each dispatch function. The first trace op is for inputs, and +the second trace op is for outputs. There will be two events for one dispatch +function. + ### Useful Vulkan driver flags For IREE's Vulkan runtime driver, there are a few useful
diff --git a/docs/repository_management.md b/docs/developing_iree/repository_management.md similarity index 100% rename from docs/repository_management.md rename to docs/developing_iree/repository_management.md
diff --git a/docs/testing_guide.md b/docs/developing_iree/testing_guide.md similarity index 98% rename from docs/testing_guide.md rename to docs/developing_iree/testing_guide.md index 3be690d..5f57c9c 100644 --- a/docs/testing_guide.md +++ b/docs/developing_iree/testing_guide.md
@@ -30,7 +30,7 @@ To use the Vulkan backend as test driver, you may need to select between a Vulkan implementation from SwiftShader and multiple Vulkan-capable hardware devices. This can be done via environment variables. See the -[generic Vulkan setup](GetStarted/generic_vulkan_env_setup.md#useful-environment-variables) +[generic Vulkan setup](get_started/generic_vulkan_env_setup.md#useful-environment-variables) page for details regarding these variables. For Bazel, you can persist the configuration in `user.bazelrc` to save typing.
diff --git a/docs/GetStarted/cmake_options_and_variables.md b/docs/get_started/cmake_options_and_variables.md similarity index 91% rename from docs/GetStarted/cmake_options_and_variables.md rename to docs/get_started/cmake_options_and_variables.md index 8e121fc..3f3dbdd 100644 --- a/docs/GetStarted/cmake_options_and_variables.md +++ b/docs/get_started/cmake_options_and_variables.md
@@ -63,17 +63,21 @@ #### `IREE_HAL_DRIVERS_TO_BUILD`:STRING -*This does not have any effect at the moment, but will be supported in the -future!* Semicolon-separated list of HAL drivers to build, or `all` for building -all HAL drivers. Case-insensitive. Defaults to `all`. Example: +*Righ now this only affects whether tests are enabled when compiling for +Android; it will be fully supported in the future!* + +Semicolon-separated list of HAL drivers to build, or `all` for building all HAL +drivers. Case-insensitive. Defaults to `all`. Example: `-DIREE_HAL_DRIVERS_TO_BUILD="Vulkan;VMLA"`. #### `IREE_TARGET_BACKENDS_TO_BUILD`:STRING -*This does not have any effect at the moment, but will be supported in the -future!* Semicolon-separated list of HAL drivers to build, or `all` for building -all HAL drivers. Case-insensitive. Defaults to `all`. Example: -`-DIREE_HAL_DRIVERS_TO_BUILD="Vulkan_SPIRV;VMLA"`. +*Righ now this only affects whether tests are enabled when compiling for +Android; it will be fully supported in the future!* + +Semicolon-separated list of HAL drivers to build, or `all` for building all +compiler target backends. Case-insensitive. Defaults to `all`. Example: +`-DIREE_HAL_DRIVERS_TO_BUILD="Vulkan-SPIRV;VMLA"`. #### `IREE_ENABLE_LLD`:BOOL
diff --git a/docs/GetStarted/generic_vulkan_env_setup.md b/docs/get_started/generic_vulkan_env_setup.md similarity index 100% rename from docs/GetStarted/generic_vulkan_env_setup.md rename to docs/get_started/generic_vulkan_env_setup.md
diff --git a/docs/GetStarted/getting_started_android_cmake.md b/docs/get_started/getting_started_android_cmake.md similarity index 100% rename from docs/GetStarted/getting_started_android_cmake.md rename to docs/get_started/getting_started_android_cmake.md
diff --git a/docs/GetStarted/getting_started_linux_bazel.md b/docs/get_started/getting_started_linux_bazel.md similarity index 97% rename from docs/GetStarted/getting_started_linux_bazel.md rename to docs/get_started/getting_started_linux_bazel.md index 8d4a9dc..7f8b688 100644 --- a/docs/GetStarted/getting_started_linux_bazel.md +++ b/docs/get_started/getting_started_linux_bazel.md
@@ -123,7 +123,7 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) + [Developer Overview](../developing_iree/developer_overview.md) * To target GPUs using Vulkan, see [Getting Started on Linux with Vulkan](getting_started_linux_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_linux_cmake.md b/docs/get_started/getting_started_linux_cmake.md similarity index 97% rename from docs/GetStarted/getting_started_linux_cmake.md rename to docs/get_started/getting_started_linux_cmake.md index 70da146..127a80c 100644 --- a/docs/GetStarted/getting_started_linux_cmake.md +++ b/docs/get_started/getting_started_linux_cmake.md
@@ -110,7 +110,7 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) + [Developer Overview](../developing_iree/developer_overview.md) * To target GPUs using Vulkan, see [Getting Started on Linux with Vulkan](getting_started_linux_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_linux_vulkan.md b/docs/get_started/getting_started_linux_vulkan.md similarity index 100% rename from docs/GetStarted/getting_started_linux_vulkan.md rename to docs/get_started/getting_started_linux_vulkan.md
diff --git a/docs/GetStarted/getting_started_macos_bazel.md b/docs/get_started/getting_started_macos_bazel.md similarity index 95% rename from docs/GetStarted/getting_started_macos_bazel.md rename to docs/get_started/getting_started_macos_bazel.md index 2b285eb..3fc3dcb 100644 --- a/docs/GetStarted/getting_started_macos_bazel.md +++ b/docs/get_started/getting_started_macos_bazel.md
@@ -126,8 +126,8 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) <!-- TODO: Link to macOS - versions of these guides once they are developed. + [Developer Overview](../developing_iree/developer_overview.md) <!-- TODO: + Link to macOS versions of these guides once they are developed. * To target GPUs using Vulkan, see [Getting Started on Linux with Vulkan](getting_started_linux_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_macos_cmake.md b/docs/get_started/getting_started_macos_cmake.md similarity index 95% rename from docs/GetStarted/getting_started_macos_cmake.md rename to docs/get_started/getting_started_macos_cmake.md index 51ef0ab..7b916cd 100644 --- a/docs/GetStarted/getting_started_macos_cmake.md +++ b/docs/get_started/getting_started_macos_cmake.md
@@ -110,8 +110,8 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) <!-- TODO: Link to macOS - versions of these guides once they are developed. + [Developer Overview](../developing_iree/developer_overview.md) <!-- TODO: + Link to macOS versions of these guides once they are developed. * To target GPUs using Vulkan, see [Getting Started on Linux with Vulkan](getting_started_linux_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_python.md b/docs/get_started/getting_started_python.md similarity index 100% rename from docs/GetStarted/getting_started_python.md rename to docs/get_started/getting_started_python.md
diff --git a/docs/GetStarted/getting_started_windows_bazel.md b/docs/get_started/getting_started_windows_bazel.md similarity index 97% rename from docs/GetStarted/getting_started_windows_bazel.md rename to docs/get_started/getting_started_windows_bazel.md index d3f01c3..8cf0f87 100644 --- a/docs/GetStarted/getting_started_windows_bazel.md +++ b/docs/get_started/getting_started_windows_bazel.md
@@ -118,7 +118,7 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) + [Developer Overview](../developing_iree/developer_overview.md) * To target GPUs using Vulkan, see [Getting Started on Windows with Vulkan](getting_started_windows_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_windows_cmake.md b/docs/get_started/getting_started_windows_cmake.md similarity index 97% rename from docs/GetStarted/getting_started_windows_cmake.md rename to docs/get_started/getting_started_windows_cmake.md index dcab418..da5218f 100644 --- a/docs/GetStarted/getting_started_windows_cmake.md +++ b/docs/get_started/getting_started_windows_cmake.md
@@ -107,7 +107,7 @@ ### Further Reading * For an introduction to IREE's project structure and developer tools, see - [Developer Overview](../developer_overview.md) + [Developer Overview](../developing_iree/developer_overview.md) * To target GPUs using Vulkan, see [Getting Started on Windows with Vulkan](getting_started_windows_vulkan.md) * To use IREE's Python bindings, see
diff --git a/docs/GetStarted/getting_started_windows_vulkan.md b/docs/get_started/getting_started_windows_vulkan.md similarity index 100% rename from docs/GetStarted/getting_started_windows_vulkan.md rename to docs/get_started/getting_started_windows_vulkan.md
diff --git a/docs/IREE-Architecture.svg b/docs/iree_architecture.svg similarity index 100% rename from docs/IREE-Architecture.svg rename to docs/iree_architecture.svg
diff --git a/docs/roadmap.md b/docs/milestones.md similarity index 94% rename from docs/roadmap.md rename to docs/milestones.md index b979de7..322fa7e 100644 --- a/docs/roadmap.md +++ b/docs/milestones.md
@@ -1,11 +1,11 @@ -# IREE Roadmap +# IREE Milestones ## Design Though many of the core dialects are now in place enough for correctness testing a large majority of the features we are most excited to demonstrate are still TODO and will be coming over the next few quarters. You can find a highlighted -set of coming features in the [design roadmap](roadmap_design.md). +set of coming features in the [design roadmap](design_roadmap.md). ## Spring/Summer 2020 Focus Areas @@ -37,7 +37,7 @@ ### HAL: Marl CPU Scheduling We want to plug in [marl](https://github.com/google/marl) to provide -[CPU-side work scheduling](roadmap_design.md#gpu-like-cpu-scheduling) that +[CPU-side work scheduling](design_roadmap.md#gpu-like-cpu-scheduling) that matches GPU semantics. This will enable improved CPU utilization and allow us to verify the approach with benchmarks.
diff --git a/docs/mnist_example.md b/docs/mnist_example.md deleted file mode 100644 index 93cd23a..0000000 --- a/docs/mnist_example.md +++ /dev/null
@@ -1,254 +0,0 @@ -# MNIST IR Example - -This shows the MNIST MLP model as it is compiled from Keras, lowered to XLA HLO, -and then lowered to an IREE module with SPIR-V. Several steps are omitted for -brevity. - -## TensorFlow Keras Model - -```python -def simple_mnist_model(input_shape): - """Creates a simple (multi-layer perceptron) MNIST model.""" - model = tf.keras.models.Sequential() - # Flatten to a 1d array (e.g. 28x28 -> 784) - model.add(tf.keras.layers.Flatten(input_shape=input_shape)) - # Fully-connected neural layer with 128 neurons, RELU activation - model.add(tf.keras.layers.Dense(128, activation='relu')) - # Fully-connected neural layer returning probability scores for each class - model.add(tf.keras.layers.Dense(10, activation='softmax')) - return model -``` - -## XLA HLO - -**NOTE**: this uses placeholder weights to keep the page from being a few -thousand lines of floats. - -```mlir -module { - func @main(%arg0: tensor<1x28x28x1xf32>) -> tuple<tensor<1x10xf32>> - attributes {iree.module.export} { - %cst = constant {name = "constant.9"} dense<0.5> : tensor<f32> - %0 = "mhlo.broadcast_in_dim"(%cst) {name = "broadcast.10"} : (tensor<f32>) -> tensor<1x128xf32> - %1 = "mhlo.copy"(%arg0) {name = "copy.1"} : (tensor<1x28x28x1xf32>) -> tensor<1x28x28x1xf32> - %2 = "mhlo.reshape"(%1) {name = "reshape.2"} : (tensor<1x28x28x1xf32>) -> tensor<1x28x28x1xf32> - %3 = "mhlo.reshape"(%2) {name = "reshape.3"} : (tensor<1x28x28x1xf32>) -> tensor<1x784xf32> - %cst_0 = constant {name = "constant.4"} dense<0.5> : tensor<784x128xf32> - %4 = "mhlo.dot"(%3, %cst_0) {name = "dot.5", precision_config = ["DEFAULT", "DEFAULT"]} : (tensor<1x784xf32>, tensor<784x128xf32>) -> tensor<1x128xf32> - %cst_1 = constant {name = "constant.6"} dense<0.5> : tensor<128xf32> - %5 = "mhlo.broadcast_in_dim"(%cst_1) {broadcast_dimensions = dense<1> : tensor<1xi64>, name = "broadcast.7"} : (tensor<128xf32>) -> tensor<1x128xf32> - %6 = "mhlo.add"(%4, %5) {name = "add.8"} : (tensor<1x128xf32>, tensor<1x128xf32>) -> tensor<1x128xf32> - %7 = "mhlo.maximum"(%0, %6) {name = "maximum.11"} : (tensor<1x128xf32>, tensor<1x128xf32>) -> tensor<1x128xf32> - %cst_2 = constant {name = "constant.12"} dense<0.5> : tensor<128x10xf32> - %8 = "mhlo.dot"(%7, %cst_2) {name = "dot.13", precision_config = ["DEFAULT", "DEFAULT"]} : (tensor<1x128xf32>, tensor<128x10xf32>) -> tensor<1x10xf32> - %cst_3 = constant {name = "constant.14"} dense<0.5> : tensor<10xf32> - %9 = "mhlo.broadcast_in_dim"(%cst_3) {broadcast_dimensions = dense<1> : tensor<1xi64>, name = "broadcast.15"} : (tensor<10xf32>) -> tensor<1x10xf32> - %10 = "mhlo.add"(%8, %9) {name = "add.16"} : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32> - %cst_4 = constant {name = "constant.17"} dense<0xFF800000> : tensor<f32> - %11 = "mhlo.reduce"(%10, %cst_4) ( { - ^bb0(%arg1: tensor<f32>, %arg2: tensor<f32>): // no predecessors - %20 = "mhlo.maximum"(%arg1, %arg2) {name = "maximum.21"} : (tensor<f32>, tensor<f32>) -> tensor<f32> - "mhlo.return"(%20) : (tensor<f32>) -> () - }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32> - %12 = "mhlo.broadcast_in_dim"(%11) {broadcast_dimensions = dense<0> : tensor<1xi64>, name = "broadcast.23"} : (tensor<1xf32>) -> tensor<1x10xf32> - %13 = "mhlo.subtract"(%10, %12) {name = "subtract.24"} : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32> - %14 = "mhlo.exponential"(%13) {name = "exponential.25"} : (tensor<1x10xf32>) -> tensor<1x10xf32> - %cst_5 = constant {name = "constant.27"} dense<0.5> : tensor<f32> - %15 = "mhlo.reduce"(%14, %cst_5) ( { - ^bb0(%arg3: tensor<f32>, %arg4: tensor<f32>): // no predecessors - %21 = "mhlo.add"(%arg3, %arg4) {name = "add.31"} : (tensor<f32>, tensor<f32>) -> tensor<f32> - "mhlo.return"(%21) : (tensor<f32>) -> () - }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32> - %16 = "mhlo.broadcast_in_dim"(%15) {broadcast_dimensions = dense<0> : tensor<1xi64>, name = "broadcast.34"} : (tensor<1xf32>) -> tensor<1x10xf32> - %17 = "mhlo.divide"(%14, %16) {name = "divide.35"} : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32> - %18 = "mhlo.reshape"(%17) {name = "reshape.36"} : (tensor<1x10xf32>) -> tensor<1x10xf32> - %19 = "mhlo.tuple"(%18) {name = "tuple.37"} : (tensor<1x10xf32>) -> tuple<tensor<1x10xf32>> - return %19 : tuple<tensor<1x10xf32>> - } -} -``` - -## IREE IR (pre-backend lowering) - -Here's the lowered, outlined, and compiler-annotated version of the above in the -IREE sequencer dialect. - -```mlir -module { - iree.multi_arch_executable @main_ex_dispatch_0[0]() { - iree.executable[0](Unspecified) { - module { - func @main_entry_dispatch_0(%arg0: memref<1x28x28x1xf32>, %arg1: memref<1x784xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[784, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x28x28x1xf32>) : tensor<1x28x28x1xf32> - %1 = "mhlo.copy"(%0) {name = "copy.1"} : (tensor<1x28x28x1xf32>) -> tensor<1x28x28x1xf32> - %2 = "mhlo.reshape"(%1) {name = "reshape.3"} : (tensor<1x28x28x1xf32>) -> tensor<1x784xf32> - iree.store_output(%2 : tensor<1x784xf32>, %arg1 : memref<1x784xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_1[1]() { - iree.executable[1](Unspecified) { - module { - func @main_entry_dispatch_1(%arg0: memref<1x784xf32>, %arg1: memref<784x128xf32>, %arg2: memref<1x128xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[128, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x784xf32>) : tensor<1x784xf32> - %1 = iree.load_input(%arg1 : memref<784x128xf32>) : tensor<784x128xf32> - %2 = "mhlo.dot"(%0, %1) {name = "dot.5", precision_config = ["DEFAULT", "DEFAULT"]} : (tensor<1x784xf32>, tensor<784x128xf32>) -> tensor<1x128xf32> - iree.store_output(%2 : tensor<1x128xf32>, %arg2 : memref<1x128xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_2[2]() { - iree.executable[2](Unspecified) { - module { - func @main_entry_dispatch_2(%arg0: memref<1x128xf32>, %arg1: memref<1x128xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[128, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x128xf32>) : tensor<1x128xf32> - %cst = constant dense<5.000000e-01> : tensor<128xf32> - %cst_0 = constant dense<5.000000e-01> : tensor<f32> - %1 = "mhlo.broadcast_in_dim"(%cst_0) {name = "broadcast.10"} : (tensor<f32>) -> tensor<1x128xf32> - %2 = "mhlo.broadcast_in_dim"(%cst) {broadcast_dimensions = dense<1> : tensor<1xi64>, name = "broadcast.7"} : (tensor<128xf32>) -> tensor<1x128xf32> - %3 = addf %0, %2 : tensor<1x128xf32> - %4 = mhlo.maximum %1, %3 {name = "maximum.11"} : tensor<1x128xf32> - iree.store_output(%4 : tensor<1x128xf32>, %arg1 : memref<1x128xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_3[3]() { - iree.executable[3](Unspecified) { - module { - func @main_entry_dispatch_3(%arg0: memref<1x128xf32>, %arg1: memref<128x10xf32>, %arg2: memref<1x10xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[10, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x128xf32>) : tensor<1x128xf32> - %1 = iree.load_input(%arg1 : memref<128x10xf32>) : tensor<128x10xf32> - %2 = "mhlo.dot"(%0, %1) {name = "dot.13", precision_config = ["DEFAULT", "DEFAULT"]} : (tensor<1x128xf32>, tensor<128x10xf32>) -> tensor<1x10xf32> - iree.store_output(%2 : tensor<1x10xf32>, %arg2 : memref<1x10xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_4[4]() { - iree.executable[4](Unspecified) { - module { - func @main_entry_dispatch_4(%arg0: memref<1x10xf32>, %arg1: memref<1x10xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[10, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x10xf32>) : tensor<1x10xf32> - %cst = constant dense<5.000000e-01> : tensor<10xf32> - %1 = "mhlo.broadcast_in_dim"(%cst) {broadcast_dimensions = dense<1> : tensor<1xi64>, name = "broadcast.15"} : (tensor<10xf32>) -> tensor<1x10xf32> - %2 = addf %0, %1 : tensor<1x10xf32> - iree.store_output(%2 : tensor<1x10xf32>, %arg1 : memref<1x10xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_5[5]() { - iree.executable[5](Unspecified) { - module { - func @main_entry_dispatch_5(%arg0: memref<1x10xf32>, %arg1: memref<1xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<1> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x10xf32>) : tensor<1x10xf32> - %cst = constant dense<0xFF800000> : tensor<f32> - %1 = "mhlo.reduce"(%0, %cst) ( { - ^bb0(%arg2: tensor<f32>, %arg3: tensor<f32>): // no predecessors - %2 = mhlo.maximum %arg2, %arg3 {name = "maximum.21"} : tensor<f32> - "mhlo.return"(%2) : (tensor<f32>) -> () - }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32> - iree.store_output(%1 : tensor<1xf32>, %arg1 : memref<1xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_6[6]() { - iree.executable[6](Unspecified) { - module { - func @main_entry_dispatch_6(%arg0: memref<1x10xf32>, %arg1: memref<1xf32>, %arg2: memref<1x10xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[10, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x10xf32>) : tensor<1x10xf32> - %1 = iree.load_input(%arg1 : memref<1xf32>) : tensor<1xf32> - %2 = "mhlo.broadcast_in_dim"(%1) {broadcast_dimensions = dense<0> : tensor<1xi64>, name = "broadcast.23"} : (tensor<1xf32>) -> tensor<1x10xf32> - %3 = subf %0, %2 : tensor<1x10xf32> - %4 = "mhlo.exponential"(%3) {name = "exponential.25"} : (tensor<1x10xf32>) -> tensor<1x10xf32> - iree.store_output(%4 : tensor<1x10xf32>, %arg2 : memref<1x10xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_7[7]() { - iree.executable[7](Unspecified) { - module { - func @main_entry_dispatch_7(%arg0: memref<1x10xf32>, %arg1: memref<1xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<1> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1x10xf32>) : tensor<1x10xf32> - %cst = constant dense<5.000000e-01> : tensor<f32> - %1 = "mhlo.reduce"(%0, %cst) ( { - ^bb0(%arg2: tensor<f32>, %arg3: tensor<f32>): // no predecessors - %2 = addf %arg2, %arg3 : tensor<f32> - "mhlo.return"(%2) : (tensor<f32>) -> () - }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32> - iree.store_output(%1 : tensor<1xf32>, %arg1 : memref<1xf32>) - iree.return - } - } - } - } - iree.multi_arch_executable @main_ex_dispatch_8[8]() { - iree.executable[8](Unspecified) { - module { - func @main_entry_dispatch_8(%arg0: memref<1xf32>, %arg1: memref<1x10xf32>, %arg2: memref<1x10xf32>) - attributes {iree.executable.export, iree.executable.workload = dense<[10, 1, 1]> : tensor<3xi32>, iree.ordinal = 0 : i32} { - %0 = iree.load_input(%arg0 : memref<1xf32>) : tensor<1xf32> - %1 = iree.load_input(%arg1 : memref<1x10xf32>) : tensor<1x10xf32> - %2 = "mhlo.broadcast_in_dim"(%0) {broadcast_dimensions = dense<0> : tensor<1xi64>, name = "broadcast.34"} : (tensor<1xf32>) -> tensor<1x10xf32> - %3 = divf %1, %2 : tensor<1x10xf32> - iree.store_output(%3 : tensor<1x10xf32>, %arg2 : memref<1x10xf32>) - iree.return - } - } - } - } - func @main(%arg0: memref<1x28x28x1xf32>) -> memref<1x10xf32> - attributes {iree.module.export} { - %0 = "iree_ll_seq.constant"() {value = dense<5.000000e-01> : tensor<784x128xf32>} : () -> memref<784x128xf32> - %1 = "iree_ll_seq.constant"() {value = dense<5.000000e-01> : tensor<128x10xf32>} : () -> memref<128x10xf32> - %2 = "iree_ll_seq.alloc_heap"() : () -> memref<1x784xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_0::main_entry_dispatch_0[dense<[784, 1, 1]> : tensor<3xi32>](%arg0, %2) : (memref<1x28x28x1xf32>, memref<1x784xf32>) -> () - %3 = "iree_ll_seq.alloc_heap"() : () -> memref<1x128xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_1::main_entry_dispatch_1[dense<[128, 1, 1]> : tensor<3xi32>](%2, %0, %3) : (memref<1x784xf32>, memref<784x128xf32>, memref<1x128xf32>) -> () - %4 = "iree_ll_seq.alloc_heap"() : () -> memref<1x128xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_2::main_entry_dispatch_2[dense<[128, 1, 1]> : tensor<3xi32>](%3, %4) : (memref<1x128xf32>, memref<1x128xf32>) -> () - %5 = "iree_ll_seq.alloc_heap"() : () -> memref<1x10xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_3::main_entry_dispatch_3[dense<[10, 1, 1]> : tensor<3xi32>](%4, %1, %5) : (memref<1x128xf32>, memref<128x10xf32>, memref<1x10xf32>) -> () - %6 = "iree_ll_seq.alloc_heap"() : () -> memref<1x10xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_4::main_entry_dispatch_4[dense<[10, 1, 1]> : tensor<3xi32>](%5, %6) : (memref<1x10xf32>, memref<1x10xf32>) -> () - %7 = "iree_ll_seq.alloc_heap"() : () -> memref<1xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_5::main_entry_dispatch_5[dense<1> : tensor<3xi32>](%6, %7) : (memref<1x10xf32>, memref<1xf32>) -> () - %8 = "iree_ll_seq.alloc_heap"() : () -> memref<1x10xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_6::main_entry_dispatch_6[dense<[10, 1, 1]> : tensor<3xi32>](%6, %7, %8) : (memref<1x10xf32>, memref<1xf32>, memref<1x10xf32>) -> () - %9 = "iree_ll_seq.alloc_heap"() : () -> memref<1xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_7::main_entry_dispatch_7[dense<1> : tensor<3xi32>](%8, %9) : (memref<1x10xf32>, memref<1xf32>) -> () - %10 = "iree_ll_seq.alloc_heap"() : () -> memref<1x10xf32> - iree_ll_seq.static_dispatch main_ex_dispatch_8::main_entry_dispatch_8[dense<[10, 1, 1]> : tensor<3xi32>](%9, %8, %10) : (memref<1xf32>, memref<1x10xf32>, memref<1x10xf32>) -> () - iree_ll_seq.return %10 : memref<1x10xf32> - } -} -``` - -**NOTE**: this is effectively compiling in -O0, which is why the buffers are not -aliased and some dispatch region fusing is not performed. As we get things going -we'll be adding simple optimizations that can operate on this IR to elide almost -all copies and externalize allocations to transient pooled memory. - -## Final IREE Module with SPIR-V - -TODO(benvanik): once reductions are done.
diff --git a/docs/using_colab.md b/docs/using_iree/using_colab.md similarity index 100% rename from docs/using_colab.md rename to docs/using_iree/using_colab.md
diff --git a/experimental/ModelBuilder/ModelRunner.h b/experimental/ModelBuilder/ModelRunner.h index 3539dbe..8afb37a 100644 --- a/experimental/ModelBuilder/ModelRunner.h +++ b/experimental/ModelBuilder/ModelRunner.h
@@ -116,7 +116,10 @@ } // Direct invocation based on MemRefType which automatically packs the data. template <typename... Args> - llvm::Error invoke(StringRef funcName, Args &... args) { + // TODO(suderman): Re-enable clang-format when new version migrates. + // clang-format off + llvm::Error invoke(StringRef funcName, Args &...args) { + // clang-format on const std::string adapterName = std::string("_mlir_ciface_") + funcName.str(); void *argsArray[] = {getData(args)...};
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/compiler/saved_model_test.py b/integrations/tensorflow/bindings/python/pyiree/tf/compiler/saved_model_test.py index 92f9c43..a7aba66 100644 --- a/integrations/tensorflow/bindings/python/pyiree/tf/compiler/saved_model_test.py +++ b/integrations/tensorflow/bindings/python/pyiree/tf/compiler/saved_model_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - import importlib import os import sys
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/compiler/signature_def_saved_model_test.py b/integrations/tensorflow/bindings/python/pyiree/tf/compiler/signature_def_saved_model_test.py index da94f6f..8a2e1cb 100644 --- a/integrations/tensorflow/bindings/python/pyiree/tf/compiler/signature_def_saved_model_test.py +++ b/integrations/tensorflow/bindings/python/pyiree/tf/compiler/signature_def_saved_model_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - import importlib import os import sys
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_test_utils.py b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_test_utils.py index f032772..f2c6151 100644 --- a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_test_utils.py +++ b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_test_utils.py
@@ -264,24 +264,22 @@ return self.multi() reinitialized_modules = [ - tf_utils.CompiledModule.from_existing(module) - for module in compiled_backends.values() + module.create_reinitialized() for module in compiled_backends.values() ] return VirtualBackendsClass(*reinitialized_modules) -def compile_module(module_ctor, exported_names=()): - """SavedModelTestCase decorator that compiles a tf.Module. +def compile_module(module_class, exported_names=()): + """CompiledModuleTestCase decorator that compiles a tf.Module. A CompiledModule is created for each backend in --target_backends. They can be accessed individually via self.compiled_modules.backend_name or as a union via self.get_module(). Args: - module_ctor: tf.Module subclass or function which returns a tf.Module - subclass instance. + module_class: the tf.Module subclass to compile. exported_names: optional iterable of strings representing which of - module_ctor's functions to compile. If exported_names is empty all + module_class's functions to compile. If exported_names is empty all functions will be compiled. Returns: @@ -290,11 +288,11 @@ def decorator(cls): """Decorator Function.""" - if not issubclass(cls, SavedModelTestCase): + if not issubclass(cls, CompiledModuleTestCase): logging.exception( "The 'compile_module' decorator must be applied to a " - "SavedModelTestCase derived class, which %s is not.", cls) - cls._module_ctor = module_ctor + "CompiledModuleTestCase derived class, which %s is not.", cls) + cls._module_class = module_class cls._exported_names = exported_names return cls @@ -336,11 +334,11 @@ return backends -class SavedModelTestCase(tf.test.TestCase): - """Tests against a SavedModel.""" +class CompiledModuleTestCase(tf.test.TestCase): + """Compiles a tf.Module to multiple backends to test their correctness.""" # Will be initialized by the @compile_module decorator. - _module_ctor = None + _module_class = None _exported_names = () # Will be initialized in setUpClass to a dict of @@ -350,27 +348,33 @@ @classmethod def setUpClass(cls): super().setUpClass() - if cls._module_ctor is not None: - # Setup the debug directory for this test. Creates a global variable - # `global_debug_dir`. - _setup_test_debug_dir(test_name=cls.__name__) + if cls._module_class is None: + raise AttributeError( + "setUpClass was called but no module was specified. Specify a module " + "to compile via the @tf_test_utils.compile_module decorator.") - # Setup crash reproducer for the test. - crash_reproducer_path = os.path.join(global_debug_dir, "reproducer.mlir") - compiler.Context.default_crash_reproducer_path = crash_reproducer_path + # Setup the debug directory for this test. Creates a global variable + # `global_debug_dir`. + _setup_test_debug_dir(test_name=cls.__name__) - # Create a CompiledModule for each backend. - try: - backends = get_backends() - cls._compiled_backends_dict = {} - for backend in backends: - compiled_backend = tf_utils.CompiledModule.compile( - cls._module_ctor, backend, cls._exported_names, global_debug_dir) - cls._compiled_backends_dict[backend.name] = compiled_backend - finally: - # Disable crash reproducer (to avoid inadvertently overwriting this - # path on a subsequent interaction). - compiler.Context.default_crash_reproducer_path = None + # Setup crash reproducer for the test. + crash_reproducer_path = os.path.join(global_debug_dir, "reproducer.mlir") + compiler.Context.default_crash_reproducer_path = crash_reproducer_path + + # Create a CompiledModule for each backend. + try: + backends = get_backends() + cls._compiled_backends_dict = {} + for backend_info in backends: + compiled_backend = backend_info.CompiledModule(cls._module_class, + backend_info, + cls._exported_names, + global_debug_dir) + cls._compiled_backends_dict[backend_info.name] = compiled_backend + finally: + # Disable crash reproducer (to avoid inadvertently overwriting this + # path on a subsequent interaction). + compiler.Context.default_crash_reproducer_path = None @classmethod def tearDownClass(cls):
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils.py b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils.py index 2752629..46a3785 100644 --- a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils.py +++ b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils.py
@@ -39,22 +39,32 @@ np.random.seed(seed) +def backends_to_str(target_backends): + """Creates a flattened and normalized string representing target_backends.""" + normalized_backends = [] + for backend in target_backends: + # Remove unusual characters and ensure names don't end or start in "_". + backend = re.sub("[^0-9a-zA-Z_]+", "_", backend) + normalized_backends.append(backend.strip("_")) + return "__".join(normalized_backends) + + def compile_tf_module(tf_module, target_backends=(), exported_names=(), artifacts_dir=None): """Compiles a TensorFlow tf.Module and optionally saves compilation artifacts. - The artifact this creates is not callable. See IreeCompiledModule.compile(...) - for an API that returns a module that can be called without any further steps. + The artifact this creates is not callable. See IreeCompiledModule for an API + that returns a module that can be called without any further steps. If artifacts_dir is provided then the following artifacts will be saved: saved_model: A TF SavedModel directory containing the files used translate the tf.Module into an IREE module. - tf_input__backends.mlir: + tf_input.mlir: MLIR for the module in TF's input dialect. - iree_input__backends.mlir: + iree_input.mlir: The MLIR above translated to IREE via compiler.TF_IMPORT_PASS_PIPELINE. compiled__backends.vmfb: A VM FlatBuffer compiled to the target backends from the IREE MLIR above. @@ -77,14 +87,6 @@ # We break up the compilation here so we can save intermediary artifacts. compiler_context = compiler.Context() - if artifacts_dir is not None: - normalized_backends = [] - for backend in target_backends: - # Remove unusual characters and ensure names don't end or start in "_". - backend = re.sub("[^0-9a-zA-Z_]+", "_", backend) - normalized_backends.append(backend.strip("_")) - backends_string = "__".join(normalized_backends) - # Convert the tf_module into raw TF input MLIR. compiler_module = compiler.tf_load_saved_model( sm_path, @@ -93,8 +95,7 @@ pass_pipeline=()) if artifacts_dir is not None: - tf_mlir_path = os.path.join(artifacts_dir, - f"tf_input__{backends_string}.mlir") + tf_mlir_path = os.path.join(artifacts_dir, "tf_input.mlir") logging.info("Saving raw TF input MLIR to: %s", tf_mlir_path) with open(tf_mlir_path, "w") as f: f.write(compiler_module.to_asm()) @@ -103,16 +104,15 @@ compiler_module.run_pass_pipeline(compiler.TF_IMPORT_PASS_PIPELINE) if artifacts_dir is not None: - iree_mlir_path = os.path.join(artifacts_dir, - f"iree_input__{backends_string}.mlir") + iree_mlir_path = os.path.join(artifacts_dir, "iree_input.mlir") logging.info("Saving IREE input MLIR to: %s", iree_mlir_path) with open(iree_mlir_path, "w") as f: f.write(compiler_module.to_asm()) compiled_module = compiler_module.compile(target_backends=target_backends) if artifacts_dir is not None: - compiled_path = os.path.join(artifacts_dir, - f"compiled__{backends_string}.vmfb") + compiled_name = f"compiled__{backends_to_str(target_backends)}.vmfb" + compiled_path = os.path.join(artifacts_dir, compiled_name) logging.info("Saving compiled IREE module to: %s", compiled_path) with open(compiled_path, "wb") as f: f.write(compiled_module) @@ -133,97 +133,67 @@ class CompiledModule(object): - """Base class for the TF and IREE compiled module facades.""" + """Base class for the TF and IREE compiled modules.""" - @staticmethod - def compile(constructor, backend_info, exported_names=(), artifacts_dir=None): - """Compile a tf.Module using the CompiledModule subclass in backend_info. - - Args: - constructor: a tf.Module subclass or function which returns a tf.Module - subclass instance. - backend_info: an element of BackendInfo corresponding to the backend to - compile to. If a TF 'backend' is provided then the module is wrapped in - a TfCompiledModule. - exported_names: an optional iterable of strings representing which of the - tf.Module's functions to compile. If exported_names is empty all - functions will be compiled. - artifacts_dir: an optional path to save compilation artifacts to. - """ - compile = backend_info.CompiledModule.compile - return compile(constructor, backend_info, exported_names, artifacts_dir) - - @staticmethod - def from_existing(module): - """Duplicates 'module' with the tf.Module's state without recompiling.""" - # Use the backend_info attr to determine which subclass' constructor to use. - from_existing = module._backend_info.CompiledModule.from_existing - return from_existing(module) - - def __init__(self, constructor, backend_info, exported_names, artifacts_dir): - """Default constructor – use `compile` or `from_existing` instead.""" - self._constructor = constructor + def __init__(self, module_class, backend_info, exported_names, artifacts_dir): + """Shared base constructor – not useful on its own.""" + self._module_class = module_class self._backend_info = backend_info self._exported_names = exported_names self._artifacts_dir = artifacts_dir + def create_reinitialized(self): + """Duplicates this module with its initial state without recompiling.""" + raise NotImplementedError() + class IreeCompiledModule(CompiledModule): """Iree compiled module.""" - @staticmethod - def compile(constructor, backend_info, exported_names=(), artifacts_dir=None): + def __init__(self, + module_class, + backend_info, + exported_names=[], + artifacts_dir=None, + _create_reinitialized_args=None): """Compile a tf.Module to the target backend in backend_info. Args: - constructor: a tf.Module subclass or function which returns a tf.Module - subclass instance. + module_class: the tf.Module subclass to compile. backend_info: an element of BackendInfo corresponding to the IREE backend to compile to. exported_names: an optional iterable of strings representing which of the - tf.Module's functions to compile. If exported_names is empty all + module_class's functions to compile. If exported_names is empty all functions will be compiled. artifacts_dir: an optional path to save compilation artifacts to. """ - return IreeCompiledModule(constructor, backend_info, exported_names, - artifacts_dir) + super().__init__(module_class, backend_info, exported_names, artifacts_dir) - @staticmethod - def from_existing(module): - """Duplicates 'module' with the tf.Module's state without recompiling.""" - default_args = [ - module._constructor, module._backend_info, module._exported_names, - module._artifacts_dir - ] - from_existing_args = [module._module_blob, module._module, module._config] - return IreeCompiledModule(*default_args, from_existing_args) - - def __init__(self, - constructor, - backend_info, - exported_names, - artifacts_dir, - _from_existing_args=None): - """Default constructor – use `compile` or `from_existing` instead.""" - super().__init__(constructor, backend_info, exported_names, artifacts_dir) - - if _from_existing_args is None: - # Called from IreeCompiledModule.compile(...) + if _create_reinitialized_args is None: self._module_blob = compile_tf_module( - tf_module=constructor(), + tf_module=module_class(), target_backends=backend_info.iree_compiler_targets, exported_names=exported_names, artifacts_dir=artifacts_dir) self._module = rt.VmModule.from_flatbuffer(self._module_blob) self._config = rt.Config(driver_name=backend_info.iree_driver) else: - # Called from IreeCompiledModule.from_existing(module) - self._module_blob, self._module, self._config = _from_existing_args + # Called from self.create_reinitialized() + self._module_blob, self._module, self._config = _create_reinitialized_args # Holds all of the module's mutable state. self._context = rt.SystemContext( modules=[self._module], config=self._config) + def create_reinitialized(self): + """Duplicates this module with its initial state without recompiling.""" + default_args = [ + self._module_class, self._backend_info, self._exported_names, + self._artifacts_dir + ] + create_reinitialized_args = [self._module_blob, self._module, self._config] + return IreeCompiledModule(*default_args, create_reinitialized_args) + def __getattr__(self, attr): # Try to resolve it as a function. m = self._context.modules[self._module.name] @@ -249,36 +219,29 @@ normalize TensorFlow's output to Numpy. """ - @staticmethod - def compile(constructor, backend_info, exported_names=(), artifacts_dir=None): + def __init__(self, + module_class, + backend_info, + exported_names=[], + artifacts_dir=None): """Wrap a tf.Module in a TFCompiledModule facade. Args: - constructor: a tf.Module subclass or function which returns a tf.Module - subclass instance. + module_class: the tf.Module subclass to 'compile'. backend_info: one of the 'tf*' elements in BackendInfo. - exported_names: an optional iterable of strings representing the which of - the tf.Module's functions should be callable. If exported_names is empty - then all functions are callable. + exported_names: an optional iterable of strings representing which of the + module_class's functions should be callable. If exported_names is empty + then all functions will be callable. artifacts_dir: an optional path to save compilation artifacts to. Has no effect for this subclass as nothing is compiled. """ - return TfCompiledModule(constructor, backend_info, exported_names, - artifacts_dir) + super().__init__(module_class, backend_info, exported_names, artifacts_dir) + self._tf_module = module_class() - @staticmethod - def from_existing(module): - """Duplicates 'module's facade with the starting state of constructor.""" - duplicate_module = TfCompiledModule(module._constructor, - module._backend_info, - module._exported_names, - module._artifacts_dir) - return duplicate_module - - def __init__(self, constructor, backend_info, exported_names, artifacts_dir): - """Default constructor – use `compile` or `from_existing` instead.""" - super().__init__(constructor, backend_info, exported_names, artifacts_dir) - self._tf_module = constructor() + def create_reinitialized(self): + """Duplicates this module with the starting state of module_class.""" + return TfCompiledModule(self._module_class, self._backend_info, + self._exported_names, self._artifacts_dir) def __getattr__(self, attr): # Try to resolve it as a function.
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py index dcc3aec..fe25f97 100644 --- a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py +++ b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py
@@ -17,6 +17,7 @@ import os import tempfile +from absl import logging from absl.testing import parameterized from pyiree.tf.support import tf_utils import tensorflow as tf @@ -52,7 +53,7 @@ }, { 'testcase_name': 'multiple_backends', - 'target_backends': ['vmla', 'llvm'], + 'target_backends': ['vmla', 'llvm-ir'], }, ]) def test_artifact_saving(self, target_backends): @@ -64,13 +65,13 @@ artifacts_dir=artifacts_dir) artifacts_to_check = [ - 'saved_model', - f'tf_input__{"__".join(target_backends)}.mlir', - f'iree_input__{"__".join(target_backends)}.mlir', - f'compiled__{"__".join(target_backends)}.vmfb', + 'saved_model', 'tf_input.mlir', 'iree_input.mlir', + f'compiled__{tf_utils.backends_to_str(target_backends)}.vmfb', ] for artifact in artifacts_to_check: - self.assertTrue(os.path.exists(os.path.join(artifacts_dir, artifact))) + artifact_path = os.path.join(artifacts_dir, artifact) + logging.info('Checking path: %s', artifact_path) + self.assertTrue(os.path.exists(artifact_path)) @parameterized.named_parameters([ { @@ -83,15 +84,15 @@ }, ]) def test_unaltered_state(self, backend_name): - info = tf_utils.BackendInfo.ALL[backend_name] - module = tf_utils.CompiledModule.compile(StatefulCountingModule, info) + backend_info = tf_utils.BackendInfo.ALL[backend_name] + module = backend_info.CompiledModule(StatefulCountingModule, backend_info) # Test that incrementing works properly. self.assertEqual([0.], module.get_count()) module.increment() self.assertEqual([1.], module.get_count()) - reinitialized_module = tf_utils.CompiledModule.from_existing(module) + reinitialized_module = module.create_reinitialized() # Test reinitialization. self.assertEqual([0.], reinitialized_module.get_count()) # Test independent state.
diff --git a/integrations/tensorflow/bindings/python/pyiree/xla/compiler/xla_module_proto_test.py b/integrations/tensorflow/bindings/python/pyiree/xla/compiler/xla_module_proto_test.py index eac1288..02aeb39 100644 --- a/integrations/tensorflow/bindings/python/pyiree/xla/compiler/xla_module_proto_test.py +++ b/integrations/tensorflow/bindings/python/pyiree/xla/compiler/xla_module_proto_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - from absl.testing import absltest import numpy as np from pyiree.xla import compiler
diff --git a/integrations/tensorflow/e2e/README.md b/integrations/tensorflow/e2e/README.md index 341aa56..04604d8 100644 --- a/integrations/tensorflow/e2e/README.md +++ b/integrations/tensorflow/e2e/README.md
@@ -26,10 +26,10 @@ ## Compiling `tf.Module`s Compatible TensorFlow modules can be compiled to specific IREE backends using -`IreeCompiledModule.compile(...)`. This also optionally saves compilation -artifacts to a specified directory. These artifacts include: MLIR across various -lowerings, a TensorFlow SavedModel, and the compiled VM FlatBuffer. A basic -example of creating and calling an `IreeCompiledModule` can be found in +`IreeCompiledModule`. This also optionally saves compilation artifacts to a +specified directory. These artifacts include: MLIR across various lowerings, a +TensorFlow SavedModel, and the compiled VM FlatBuffer. A basic example of +creating and calling an `IreeCompiledModule` can be found in [`tf_utils_test.py`](https://github.com/google/iree/blob/main/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py) When using Keras models or tf.Modules with functions that IREE can't compile, @@ -38,7 +38,7 @@ ```python from pyiree.tf.support import tf_utils vmla_module = tf_utils.IreeCompiledModule( - constructor=KerasTFModuleClass, + module_class=KerasTFModuleClass, backend_info=tf_utils.BackendInfo.ALL['iree_vmla'], exported_names=['predict']) vmla_module.predict(...)
diff --git a/integrations/tensorflow/e2e/batch_norm_test.py b/integrations/tensorflow/e2e/batch_norm_test.py index f9f8d8c..75de16d 100644 --- a/integrations/tensorflow/e2e/batch_norm_test.py +++ b/integrations/tensorflow/e2e/batch_norm_test.py
@@ -39,7 +39,7 @@ @tf_test_utils.compile_module(BatchNormModule) -class BatchNormTest(tf_test_utils.SavedModelTestCase): +class BatchNormTest(tf_test_utils.CompiledModuleTestCase): def test_batch_norm_inference(self): np.random.seed(12345)
diff --git a/integrations/tensorflow/e2e/broadcasting_test.py b/integrations/tensorflow/e2e/broadcasting_test.py index cde2fd6..74880bd 100644 --- a/integrations/tensorflow/e2e/broadcasting_test.py +++ b/integrations/tensorflow/e2e/broadcasting_test.py
@@ -29,7 +29,7 @@ @tf_test_utils.compile_module(BroadcastingModule) -class BroadcastingTest(tf_test_utils.SavedModelTestCase): +class BroadcastingTest(tf_test_utils.CompiledModuleTestCase): def test_add_same_shape(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/concat_test.py b/integrations/tensorflow/e2e/concat_test.py index a9f9759..b7a348c 100644 --- a/integrations/tensorflow/e2e/concat_test.py +++ b/integrations/tensorflow/e2e/concat_test.py
@@ -51,7 +51,7 @@ @tf_test_utils.compile_module(ConcatOpsModule) -class ConcatOpsTest(tf_test_utils.SavedModelTestCase): +class ConcatOpsTest(tf_test_utils.CompiledModuleTestCase): def test_concat_zero_dim(self): tf_utils.set_random_seed()
diff --git a/integrations/tensorflow/e2e/control_flow_test.py b/integrations/tensorflow/e2e/control_flow_test.py index 0223e8c..0c25fd6 100644 --- a/integrations/tensorflow/e2e/control_flow_test.py +++ b/integrations/tensorflow/e2e/control_flow_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - import numpy from pyiree.tf.support import tf_test_utils import tensorflow.compat.v2 as tf @@ -39,7 +35,7 @@ @tf_test_utils.compile_module(ControlFlowModule) -class ControlFlowTest(tf_test_utils.SavedModelTestCase): +class ControlFlowTest(tf_test_utils.CompiledModuleTestCase): def test_short_sequence(self): input_array = numpy.array(9., dtype=numpy.float32)
diff --git a/integrations/tensorflow/e2e/conv_test.py b/integrations/tensorflow/e2e/conv_test.py index f72b11d..61c46cf 100644 --- a/integrations/tensorflow/e2e/conv_test.py +++ b/integrations/tensorflow/e2e/conv_test.py
@@ -99,7 +99,7 @@ @tf_test_utils.compile_module(Conv2dModule) -class ConvTest(tf_test_utils.SavedModelTestCase): +class ConvTest(tf_test_utils.CompiledModuleTestCase): def test_id_batch_size_1(self): i = np.arange(20, dtype=np.float32).reshape([1, 4, 5, 1])
diff --git a/integrations/tensorflow/e2e/depth_conv_test.py b/integrations/tensorflow/e2e/depth_conv_test.py index cdf4d1e..1e8a002 100644 --- a/integrations/tensorflow/e2e/depth_conv_test.py +++ b/integrations/tensorflow/e2e/depth_conv_test.py
@@ -39,7 +39,7 @@ @tf_test_utils.compile_module(Conv2dModule) -class ConvTest(tf_test_utils.SavedModelTestCase): +class ConvTest(tf_test_utils.CompiledModuleTestCase): def test_batched_feature_unpadded(self): i = np.arange(80, dtype=np.float32).reshape([2, 4, 5, 2])
diff --git a/integrations/tensorflow/e2e/dynamic_mlp_relu_test.py b/integrations/tensorflow/e2e/dynamic_mlp_relu_test.py index 04de603..64c51e9 100644 --- a/integrations/tensorflow/e2e/dynamic_mlp_relu_test.py +++ b/integrations/tensorflow/e2e/dynamic_mlp_relu_test.py
@@ -66,7 +66,7 @@ @tf_test_utils.compile_module(Mlp, exported_names=["predict"]) -class DynamicMlpTest(tf_test_utils.SavedModelTestCase): +class DynamicMlpTest(tf_test_utils.CompiledModuleTestCase): def test_dynamic_batch(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/dynamic_mlp_test.py b/integrations/tensorflow/e2e/dynamic_mlp_test.py index 66f3c06..72d7f1f 100644 --- a/integrations/tensorflow/e2e/dynamic_mlp_test.py +++ b/integrations/tensorflow/e2e/dynamic_mlp_test.py
@@ -62,7 +62,7 @@ @tf_test_utils.compile_module(Mlp, exported_names=["predict"]) -class DynamicMlpTest(tf_test_utils.SavedModelTestCase): +class DynamicMlpTest(tf_test_utils.CompiledModuleTestCase): def test_dynamic_batch(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/explicit_backend_test.py b/integrations/tensorflow/e2e/explicit_backend_test.py index 903b34c..bdcdd79 100644 --- a/integrations/tensorflow/e2e/explicit_backend_test.py +++ b/integrations/tensorflow/e2e/explicit_backend_test.py
@@ -30,7 +30,7 @@ @tf_test_utils.compile_module(SimpleArithmeticModule) -class ExplicitBackendTest(tf_test_utils.SavedModelTestCase): +class ExplicitBackendTest(tf_test_utils.CompiledModuleTestCase): def test_explicit(self): a = np.array([1., 2., 3., 4.], dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/fill_test.py b/integrations/tensorflow/e2e/fill_test.py index 8ef96a9..8d912a4 100644 --- a/integrations/tensorflow/e2e/fill_test.py +++ b/integrations/tensorflow/e2e/fill_test.py
@@ -31,7 +31,7 @@ @tf_test_utils.compile_module(FillModule) -class FillTest(tf_test_utils.SavedModelTestCase): +class FillTest(tf_test_utils.CompiledModuleTestCase): def test_fill(self): dims = np.array([2, 3], dtype=np.int32)
diff --git a/integrations/tensorflow/e2e/gather_test.py b/integrations/tensorflow/e2e/gather_test.py index 8d2a0ba..67f5acf 100644 --- a/integrations/tensorflow/e2e/gather_test.py +++ b/integrations/tensorflow/e2e/gather_test.py
@@ -49,7 +49,7 @@ @tf_test_utils.compile_module(GatherModule) -class GatherTest(tf_test_utils.SavedModelTestCase): +class GatherTest(tf_test_utils.CompiledModuleTestCase): def test_gather_axis0_scalar(self): indices = np.array(2, dtype=np.int32)
diff --git a/integrations/tensorflow/e2e/keras/lstm_static_test.py b/integrations/tensorflow/e2e/keras/lstm_static_test.py index 0d34d97..fb7a58c 100644 --- a/integrations/tensorflow/e2e/keras/lstm_static_test.py +++ b/integrations/tensorflow/e2e/keras/lstm_static_test.py
@@ -27,21 +27,23 @@ INPUT_SHAPE = [NUM_BATCH, NUM_TIMESTEPS, NUM_UNITS] -def lstm_module(): - tf_utils.set_random_seed() - inputs = tf.keras.layers.Input(batch_size=NUM_BATCH, shape=INPUT_SHAPE[1:]) - outputs = tf.keras.layers.LSTM(units=NUM_UNITS, return_sequences=True)(inputs) - model = tf.keras.Model(inputs, outputs) - module = tf.Module() - module.m = model - module.predict = tf.function( - input_signature=[tf.TensorSpec(INPUT_SHAPE, tf.float32)])( - model.call) - return module +class LstmStatic(tf.Module): + + def __init__(self): + super(LstmStatic, self).__init__() + tf_utils.set_random_seed() + inputs = tf.keras.layers.Input(batch_size=NUM_BATCH, shape=INPUT_SHAPE[1:]) + outputs = tf.keras.layers.LSTM( + units=NUM_UNITS, return_sequences=True)( + inputs) + self.m = tf.keras.Model(inputs, outputs) + self.predict = tf.function( + input_signature=[tf.TensorSpec(INPUT_SHAPE, tf.float32)])( + self.m.call) -@tf_test_utils.compile_module(lstm_module, exported_names=["predict"]) -class LstmTest(tf_test_utils.SavedModelTestCase): +@tf_test_utils.compile_module(LstmStatic, exported_names=["predict"]) +class LstmTest(tf_test_utils.CompiledModuleTestCase): def test_lstm(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/keras/lstm_test.py b/integrations/tensorflow/e2e/keras/lstm_test.py index 671c31b..9409d04 100644 --- a/integrations/tensorflow/e2e/keras/lstm_test.py +++ b/integrations/tensorflow/e2e/keras/lstm_test.py
@@ -24,21 +24,23 @@ INPUT_SHAPE = [None, None, NUM_UNITS] -def lstm_module(): - tf_utils.set_random_seed() - inputs = tf.keras.layers.Input(batch_size=None, shape=INPUT_SHAPE[1:]) - outputs = tf.keras.layers.LSTM(units=NUM_UNITS, return_sequences=True)(inputs) - model = tf.keras.Model(inputs, outputs) - module = tf.Module() - module.m = model - module.predict = tf.function( - input_signature=[tf.TensorSpec(INPUT_SHAPE, tf.float32)])( - model.call) - return module +class Lstm(tf.Module): + + def __init__(self): + super(Lstm, self).__init__() + tf_utils.set_random_seed() + inputs = tf.keras.layers.Input(batch_size=None, shape=INPUT_SHAPE[1:]) + outputs = tf.keras.layers.LSTM( + units=NUM_UNITS, return_sequences=True)( + inputs) + self.m = tf.keras.Model(inputs, outputs) + self.predict = tf.function( + input_signature=[tf.TensorSpec(INPUT_SHAPE, tf.float32)])( + self.m.call) -@tf_test_utils.compile_module(lstm_module, exported_names=["predict"]) -class LstmTest(tf_test_utils.SavedModelTestCase): +@tf_test_utils.compile_module(Lstm, exported_names=["predict"]) +class LstmTest(tf_test_utils.CompiledModuleTestCase): def test_lstm(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/keras/train/model_train_test.py b/integrations/tensorflow/e2e/keras/train/model_train_test.py index 6675956..e30bd57 100644 --- a/integrations/tensorflow/e2e/keras/train/model_train_test.py +++ b/integrations/tensorflow/e2e/keras/train/model_train_test.py
@@ -77,7 +77,7 @@ @tf_test_utils.compile_module( ModelTrain.CreateModule, exported_names=["TrainStep"]) -class ModelTrainTest(tf_test_utils.SavedModelTestCase): +class ModelTrainTest(tf_test_utils.CompiledModuleTestCase): def generate_regression_data(self, size=8): x = np.arange(size) - size // 2
diff --git a/integrations/tensorflow/e2e/keras/train_vision_models_on_cifar.py b/integrations/tensorflow/e2e/keras/train_vision_models_on_cifar.py index 0a79452..887bfb8 100644 --- a/integrations/tensorflow/e2e/keras/train_vision_models_on_cifar.py +++ b/integrations/tensorflow/e2e/keras/train_vision_models_on_cifar.py
@@ -13,9 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """Train vision models on CIFAR10.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function import os from absl import flags
diff --git a/integrations/tensorflow/e2e/keras/vision_model_test.py b/integrations/tensorflow/e2e/keras/vision_model_test.py index 1804739..54374ff 100644 --- a/integrations/tensorflow/e2e/keras/vision_model_test.py +++ b/integrations/tensorflow/e2e/keras/vision_model_test.py
@@ -14,6 +14,8 @@ # limitations under the License. """Test all applications models in Keras.""" import os + +from absl import app from absl import flags import numpy as np from pyiree.tf.support import tf_test_utils @@ -72,74 +74,84 @@ } -def get_input_shape(data, model): - if data == 'imagenet': - if (model == 'InceptionV3' or model == 'Xception' or - model == 'InceptionResNetV2'): +def get_input_shape(): + if FLAGS.data == 'imagenet': + if FLAGS.model in ['InceptionV3', 'Xception', 'InceptionResNetV2']: return (1, 299, 299, 3) - elif model == 'NASNetLarge': + elif FLAGS.model == 'NASNetLarge': return (1, 331, 331, 3) else: return (1, 224, 224, 3) - elif data == 'cifar10': + elif FLAGS.data == 'cifar10': return (1, 32, 32, 3) else: - raise ValueError('Not supported data ', data) + raise ValueError(f'Data not supported: {FLAGS.data}') -def models(): - tf.keras.backend.set_learning_phase(False) +def load_cifar10_weights(model): + file_name = 'cifar10' + FLAGS.model + # get_file will download the model weights from a publicly available folder, + # save them to cache_dir=~/.keras/models/ and return a path to them. + url = os.path.join( + FLAGS.url, f'cifar10_include_top_{FLAGS.include_top}_{FLAGS.model}.h5') + weights_path = tf.keras.utils.get_file(file_name, url) + model.load_weights(weights_path) + return model + + +def initialize_model(): tf_utils.set_random_seed() + tf.keras.backend.set_learning_phase(False) - input_shape = get_input_shape(FLAGS.data, FLAGS.model) - # keras model receives images size as input, - # where batch size is not specified - by default it is dynamic - if FLAGS.model in APP_MODELS: - weights = 'imagenet' if FLAGS.data == 'imagenet' else None + # Keras applications models receive input shapes without a batch dimension, as + # the batch size is dynamic by default. This selects just the image size. + input_shape = get_input_shape()[1:] - # if weights == 'imagenet' it will load weights from external tf.keras URL - model = APP_MODELS[FLAGS.model]( - weights=weights, - include_top=FLAGS.include_top, - input_shape=input_shape[1:]) + # If weights == 'imagenet', the model will load the appropriate weights from + # an external tf.keras URL. + weights = 'imagenet' if FLAGS.data == 'imagenet' else None - if FLAGS.data == 'cifar10' and FLAGS.url: - file_name = 'cifar10' + FLAGS.model - # it will download model weights from publically available folder: PATH - # and save it to cache_dir=~/.keras and return path to it - weights_path = tf.keras.utils.get_file( - file_name, - os.path.join( - FLAGS.url, - 'cifar10_include_top_{}_{}'.format(FLAGS.include_top, - FLAGS.model + '.h5'))) + model = APP_MODELS[FLAGS.model]( + weights=weights, include_top=FLAGS.include_top, input_shape=input_shape) - model.load_weights(weights_path) - else: - raise ValueError('Unsupported model', FLAGS.model) - - module = tf.Module() - module.m = model - # specify input size with static batch size - # TODO(b/142948097): with support of dynamic shape - # replace input_shape by model.input_shape, so batch size will be dynamic (-1) - module.predict = tf.function(input_signature=[tf.TensorSpec(input_shape)])( - model.call) - return module + if FLAGS.data == 'cifar10' and FLAGS.url: + model = load_cifar10_weights(model) + return model -@tf_test_utils.compile_module(models, exported_names=['predict']) -class AppTest(tf_test_utils.SavedModelTestCase): +class VisionModule(tf.Module): + + def __init__(self): + super(VisionModule, self).__init__() + self.m = initialize_model() + # Specify input shape with a static batch size. + # TODO(b/142948097): Add support for dynamic shapes in SPIR-V lowering. + # Replace input_shape with m.input_shape to make the batch size dynamic. + self.predict = tf.function( + input_signature=[tf.TensorSpec(get_input_shape())])( + self.m.call) + + +@tf_test_utils.compile_module(VisionModule, exported_names=['predict']) +class AppTest(tf_test_utils.CompiledModuleTestCase): def test_application(self): - input_shape = get_input_shape(FLAGS.data, FLAGS.model) - input_data = np.random.rand(np.prod(np.array(input_shape))).astype( - np.float32) - input_data = input_data.reshape(input_shape) + input_data = np.random.rand(*get_input_shape()).astype(np.float32) self.get_module().predict(input_data).print().assert_all_close(atol=1e-6) -if __name__ == '__main__': +def main(argv): + del argv # Unused if hasattr(tf, 'enable_v2_behavior'): tf.enable_v2_behavior() + + if FLAGS.model not in APP_MODELS: + raise ValueError(f'Unsupported model: {FLAGS.model}') + # Override VisionModule's __name__ to be more specific. + VisionModule.__name__ = FLAGS.model + tf.test.main() + + +if __name__ == '__main__': + app.run(main)
diff --git a/integrations/tensorflow/e2e/linspace_test.py b/integrations/tensorflow/e2e/linspace_test.py index d326db5..aa49f5b 100644 --- a/integrations/tensorflow/e2e/linspace_test.py +++ b/integrations/tensorflow/e2e/linspace_test.py
@@ -34,7 +34,7 @@ @tf_test_utils.compile_module(LinSpaceModule) -class LinspaceTest(tf_test_utils.SavedModelTestCase): +class LinspaceTest(tf_test_utils.CompiledModuleTestCase): def test_linspace(self): start = np.array(10., dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/mandelbrot_test.py b/integrations/tensorflow/e2e/mandelbrot_test.py index 4886b7a..2b3a8d9 100644 --- a/integrations/tensorflow/e2e/mandelbrot_test.py +++ b/integrations/tensorflow/e2e/mandelbrot_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - from pyiree.tf.support import tf_test_utils import tensorflow.compat.v2 as tf @@ -95,7 +91,7 @@ @tf_test_utils.compile_module(MandelbrotModule) -class MandelbrotTest(tf_test_utils.SavedModelTestCase): +class MandelbrotTest(tf_test_utils.CompiledModuleTestCase): def test_mandelbrot(self): mandelbrot = self.get_module()
diff --git a/integrations/tensorflow/e2e/math_test.py b/integrations/tensorflow/e2e/math_test.py index b27d1d1..a33ac7c 100644 --- a/integrations/tensorflow/e2e/math_test.py +++ b/integrations/tensorflow/e2e/math_test.py
@@ -39,7 +39,7 @@ @tf_test_utils.compile_module(MathModule) -class MathTest(tf_test_utils.SavedModelTestCase): +class MathTest(tf_test_utils.CompiledModuleTestCase): def test_abs(self): a = np.array([-0.5, 0.0, 0.5, 1.0], dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/matrix_ops_test.py b/integrations/tensorflow/e2e/matrix_ops_test.py index b29a198..d04ce3a 100644 --- a/integrations/tensorflow/e2e/matrix_ops_test.py +++ b/integrations/tensorflow/e2e/matrix_ops_test.py
@@ -71,7 +71,7 @@ @tf_test_utils.compile_module(MatrixOpsModule) -class MatrixOpsTest(tf_test_utils.SavedModelTestCase): +class MatrixOpsTest(tf_test_utils.CompiledModuleTestCase): def test_basic_matmul(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/resource_ops_test.py b/integrations/tensorflow/e2e/resource_ops_test.py index 1d703c0..8daa6cf 100644 --- a/integrations/tensorflow/e2e/resource_ops_test.py +++ b/integrations/tensorflow/e2e/resource_ops_test.py
@@ -29,7 +29,7 @@ @tf_test_utils.compile_module(ResourcesOpsModule) -class ResourcesOpsTest(tf_test_utils.SavedModelTestCase): +class ResourcesOpsTest(tf_test_utils.CompiledModuleTestCase): def test_add_assign(self): result = self.get_module().add_assign(np.array(9., dtype=np.float32))
diff --git a/integrations/tensorflow/e2e/ring_buffer_test.py b/integrations/tensorflow/e2e/ring_buffer_test.py index ea48711..3af1502 100644 --- a/integrations/tensorflow/e2e/ring_buffer_test.py +++ b/integrations/tensorflow/e2e/ring_buffer_test.py
@@ -179,7 +179,7 @@ @tf_test_utils.compile_module( StatefulRingBufferModule, exported_names=["predict"]) -class StatefulRingBufferTest(tf_test_utils.SavedModelTestCase): +class StatefulRingBufferTest(tf_test_utils.CompiledModuleTestCase): def test_stateful_ringbuffer(self): input1 = np.array([[1.0, 2.0]], dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/scatter_update_test.py b/integrations/tensorflow/e2e/scatter_update_test.py index cdd3277..ab5ab91 100644 --- a/integrations/tensorflow/e2e/scatter_update_test.py +++ b/integrations/tensorflow/e2e/scatter_update_test.py
@@ -49,7 +49,7 @@ @tf_test_utils.compile_module(ScatterUpdateModule) -class ScatterUpdateTest(tf_test_utils.SavedModelTestCase): +class ScatterUpdateTest(tf_test_utils.CompiledModuleTestCase): def test_scatter_update_1D(self): tensor = tf.ones([8], dtype=tf.int32)
diff --git a/integrations/tensorflow/e2e/simple_arithmetic_test.py b/integrations/tensorflow/e2e/simple_arithmetic_test.py index 0c5941d..d3ea327 100644 --- a/integrations/tensorflow/e2e/simple_arithmetic_test.py +++ b/integrations/tensorflow/e2e/simple_arithmetic_test.py
@@ -37,7 +37,7 @@ @tf_test_utils.compile_module(SimpleArithmeticModule) -class SimpleArithmeticTest(tf_test_utils.SavedModelTestCase): +class SimpleArithmeticTest(tf_test_utils.CompiledModuleTestCase): def test_simple_mul(self): a = np.array([1., 2., 3., 4.], dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/simple_stateful_test.py b/integrations/tensorflow/e2e/simple_stateful_test.py index 45eba4f..24dd23e 100644 --- a/integrations/tensorflow/e2e/simple_stateful_test.py +++ b/integrations/tensorflow/e2e/simple_stateful_test.py
@@ -33,7 +33,7 @@ @tf_test_utils.compile_module(Stateful) -class StatefulTest(tf_test_utils.SavedModelTestCase): +class StatefulTest(tf_test_utils.CompiledModuleTestCase): def test_stateful(self): m = self.get_module()
diff --git a/integrations/tensorflow/e2e/sliding_window_test.py b/integrations/tensorflow/e2e/sliding_window_test.py index b663fc8..f206d86 100644 --- a/integrations/tensorflow/e2e/sliding_window_test.py +++ b/integrations/tensorflow/e2e/sliding_window_test.py
@@ -76,7 +76,7 @@ @tf_test_utils.compile_module(SlidingWindowModule, exported_names=["predict"]) -class SlidingWindowTest(tf_test_utils.SavedModelTestCase): +class SlidingWindowTest(tf_test_utils.CompiledModuleTestCase): def test_slidingwindow(self): input1 = np.array([[1.0, 2.0]], dtype=np.float32)
diff --git a/integrations/tensorflow/e2e/strings_test.py b/integrations/tensorflow/e2e/strings_test.py index ac590ff..ce0787e 100644 --- a/integrations/tensorflow/e2e/strings_test.py +++ b/integrations/tensorflow/e2e/strings_test.py
@@ -41,7 +41,7 @@ @tf_test_utils.compile_module(StringsModule) -class StringsTest(tf_test_utils.SavedModelTestCase): +class StringsTest(tf_test_utils.CompiledModuleTestCase): def test_print_ids(self): input_ids = np.asarray(
diff --git a/integrations/tensorflow/e2e/tensorlist_test.py b/integrations/tensorflow/e2e/tensorlist_test.py index f8ea811..9b1330c 100644 --- a/integrations/tensorflow/e2e/tensorlist_test.py +++ b/integrations/tensorflow/e2e/tensorlist_test.py
@@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - from pyiree.tf.support import tf_test_utils import tensorflow.compat.v2 as tf @@ -69,7 +65,7 @@ @tf_test_utils.compile_module(TensorListModule) -class TensorListTest(tf_test_utils.SavedModelTestCase): +class TensorListTest(tf_test_utils.CompiledModuleTestCase): def test_identity_through_tensorlist(self): m = self.get_module()
diff --git a/iree/base/BUILD b/iree/base/BUILD index b8c81ed..8d6b446 100644 --- a/iree/base/BUILD +++ b/iree/base/BUILD
@@ -43,6 +43,7 @@ ":file_mapping", ":init", ":tracing", + "@com_google_absl//absl/time", ], ) @@ -60,7 +61,6 @@ ":status", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:inlined_vector", - "@com_google_absl//absl/time", ], ) @@ -431,7 +431,16 @@ name = "time", hdrs = ["time.h"], deps = [ - "@com_google_absl//absl/time", + ":api", + ], +) + +cc_test( + name = "time_test", + srcs = ["time_test.cc"], + deps = [ + ":time", + "//iree/testing:gtest_main", ], )
diff --git a/iree/base/CMakeLists.txt b/iree/base/CMakeLists.txt index 3a6ca54..322bf43 100644 --- a/iree/base/CMakeLists.txt +++ b/iree/base/CMakeLists.txt
@@ -38,6 +38,7 @@ ::file_mapping ::init ::tracing + absl::time PUBLIC ) @@ -519,10 +520,20 @@ HDRS "time.h" DEPS - absl::time + ::api PUBLIC ) +iree_cc_test( + NAME + time_test + SRCS + "time_test.cc" + DEPS + ::time + iree::testing::gtest_main +) + if(${IREE_ENABLE_RUNTIME_TRACING}) iree_cc_library( NAME
diff --git a/iree/base/api.cc b/iree/base/api.cc index ed74804..be992c4 100644 --- a/iree/base/api.cc +++ b/iree/base/api.cc
@@ -18,6 +18,7 @@ #include <cstring> #include <string> +#include "absl/time/clock.h" #include "iree/base/api_util.h" #include "iree/base/file_mapping.h" #include "iree/base/init.h" @@ -91,6 +92,24 @@ } //===----------------------------------------------------------------------===// +// iree_time_t and iree_duration_t +//===----------------------------------------------------------------------===// + +IREE_API_EXPORT iree_time_t iree_time_now() { + return absl::GetCurrentTimeNanos(); +} + +IREE_API_EXPORT iree_time_t +iree_relative_timeout_to_deadline_ns(iree_duration_t timeout_ns) { + if (timeout_ns == IREE_DURATION_ZERO) { + return IREE_TIME_INFINITE_PAST; + } else if (timeout_ns == IREE_DURATION_INFINITE) { + return IREE_TIME_INFINITE_FUTURE; + } + return iree_time_now() + timeout_ns; +} + +//===----------------------------------------------------------------------===// // iree_allocator_t //===----------------------------------------------------------------------===//
diff --git a/iree/base/api.h b/iree/base/api.h index 3bfcdf3..ba8ec9b 100644 --- a/iree/base/api.h +++ b/iree/base/api.h
@@ -167,21 +167,6 @@ // Whole length of the underlying buffer. #define IREE_WHOLE_BUFFER (iree_device_size_t(-1)) -// Like absl::Time, represented as nanoseconds since unix epoch. -// TODO(benvanik): pick something easy to get into/outof time_t/etc. -typedef int64_t iree_time_t; -// Like absl::InfinitePast. -#define IREE_TIME_INFINITE_PAST INT64_MIN -// Like absl::InfiniteFuture. -#define IREE_TIME_INFINITE_FUTURE INT64_MAX - -// Like absl::Duration, represented as relative nanoseconds. -typedef int64_t iree_duration_t; -// Like absl::InfiniteDuration. -#define IREE_DURATION_INFINITE INT64_MIN -// Like absl::ZeroDuration. -#define IREE_DURATION_ZERO 0 - // A span of mutable bytes (ala std::span of uint8_t). typedef struct { uint8_t* data; @@ -375,6 +360,43 @@ #endif // IREE_API_NO_PROTOTYPES //===----------------------------------------------------------------------===// +// iree_time_t and iree_duration_t +//===----------------------------------------------------------------------===// + +// Like absl::Time, represented as nanoseconds since unix epoch. +// TODO(benvanik): pick something easy to get into/outof time_t/etc. +typedef int64_t iree_time_t; +// Like absl::InfinitePast. +#define IREE_TIME_INFINITE_PAST INT64_MIN +// Like absl::InfiniteFuture. +#define IREE_TIME_INFINITE_FUTURE INT64_MAX + +// Like absl::Duration, represented as relative nanoseconds. +typedef int64_t iree_duration_t; +// Like absl::InfiniteDuration. +#define IREE_DURATION_INFINITE INT64_MAX +// Like absl::ZeroDuration. +#define IREE_DURATION_ZERO 0 + +#ifndef IREE_API_NO_PROTOTYPES + +// Returns the current system time in unix nanoseconds. +// Depending on the system architecture and power mode this time may have a +// very coarse granularity (on the order of microseconds to milliseconds). +// +// The system timer may not be monotonic; users should ensure when comparing +// times they check for negative values in case the time moves backwards. +IREE_API_EXPORT iree_time_t iree_time_now(); + +// Converts a relative timeout duration to an absolute deadline time. +// This handles the special cases of IREE_DURATION_ZERO and +// IREE_DURATION_INFINITE to avoid extraneous time queries. +IREE_API_EXPORT iree_time_t +iree_relative_timeout_to_deadline_ns(iree_duration_t timeout_ns); + +#endif // IREE_API_NO_PROTOTYPES + +//===----------------------------------------------------------------------===// // iree_allocator_t (std::allocator-like interface) //===----------------------------------------------------------------------===//
diff --git a/iree/base/api_util.h b/iree/base/api_util.h index 279a6fa..5ec86a5 100644 --- a/iree/base/api_util.h +++ b/iree/base/api_util.h
@@ -17,7 +17,6 @@ #include "absl/base/macros.h" #include "absl/container/inlined_vector.h" -#include "absl/time/time.h" #include "iree/base/api.h" #include "iree/base/logging.h" #include "iree/base/status.h" @@ -100,39 +99,6 @@ } \ lhs = std::move(statusor).value() -// Converts an iree_duration_t to its equivalent absl::Duration. -inline absl::Duration ToAbslDuration(iree_duration_t duration) { - if (duration == IREE_DURATION_ZERO) { - return absl::ZeroDuration(); - } else if (duration == IREE_DURATION_INFINITE) { - return absl::InfiniteDuration(); - } else { - return absl::Nanoseconds(duration); - } -} - -// Converts an iree_time_t to its equivalent absl::Time. -inline absl::Time ToAbslTime(iree_time_t time) { - if (time == IREE_TIME_INFINITE_PAST) { - return absl::InfinitePast(); - } else if (time == IREE_TIME_INFINITE_FUTURE) { - return absl::InfiniteFuture(); - } else { - return absl::FromUnixNanos(time); - } -} - -// Converts an absl::Time to an iree_time_t. -inline iree_time_t FromAbslTime(absl::Time time) { - if (time == absl::InfinitePast()) { - return IREE_TIME_INFINITE_PAST; - } else if (time == absl::InfiniteFuture()) { - return IREE_TIME_INFINITE_FUTURE; - } else { - return absl::ToUnixNanos(time); - } -} - // Returns a vector initialized with the contents of a C-style list query. // For functions of the form (..., capacity, out_values, out_count) this will // try to fetch the items and resize as needed such that the returned value
diff --git a/iree/base/atomics.h b/iree/base/atomics.h index 0bd99c7..47587dc 100644 --- a/iree/base/atomics.h +++ b/iree/base/atomics.h
@@ -39,7 +39,7 @@ #endif #if defined(IREE_COMPILER_CLANG) - +// Emulate C11 atomics with builtins. typedef _Atomic intptr_t iree_atomic_intptr_t; #define IREE_ATOMIC_VAR_INIT(value) (value) #define iree_atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST) @@ -51,7 +51,7 @@ __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) #elif defined(IREE_COMPILER_MSVC) - +// Emulate C11 atomics with Interlocked win32 APIs. // NOTE: currently assumes sizeof(intptr_t) == 8. typedef struct { intptr_t __val; @@ -68,19 +68,27 @@ InterlockedExchangeAdd64((volatile LONGLONG*)object, -(operand)) #elif defined(IREE_COMPILER_GCC) - -typedef _Atomic __INTPTR_TYPE__ iree_atomic_intptr_t; +// Emulate atomics for GCC in a way that is compatible for inclusion in +// both C and C++ modes. +#ifdef __cplusplus +// Equiv to C++ auto keyword in C++ mode. +#define __iree_auto_type auto +#else +// Only defined in C mode. +#define __iree_auto_type __auto_type +#endif +typedef __INTPTR_TYPE__ iree_atomic_intptr_t; #define IREE_ATOMIC_VAR_INIT(value) (value) #define iree_atomic_load(object) \ __atomic_load_ptr(object, __ATOMIC_SEQ_CST) __extension__({ \ - __auto_type __atomic_load_ptr = (object); \ + __iree_auto_type __atomic_load_ptr = (object); \ __typeof__(*__atomic_load_ptr) __atomic_load_tmp; \ __atomic_load(__atomic_load_ptr, &__atomic_load_tmp, (__ATOMIC_SEQ_CST)); \ __atomic_load_tmp; \ }) #define iree_atomic_store(object, desired) \ __extension__({ \ - __auto_type __atomic_store_ptr = (object); \ + __iree_auto_type __atomic_store_ptr = (object); \ __typeof__(*__atomic_store_ptr) __atomic_store_tmp = (desired); \ __atomic_store(__atomic_store_ptr, &__atomic_store_tmp, \ (__ATOMIC_SEQ_CST)); \
diff --git a/iree/base/signature_mangle.h b/iree/base/signature_mangle.h index 948dbb5..8afb4b5 100644 --- a/iree/base/signature_mangle.h +++ b/iree/base/signature_mangle.h
@@ -156,7 +156,7 @@ // ----------------------------------------------------------------------------- // Mangles raw function signatures. -// See function_abi.md. +// See docs/design_docs/function_abi.md. class RawSignatureMangler { public: static SignatureBuilder ToFunctionSignature(const SignatureBuilder& inputs, @@ -364,7 +364,8 @@ // Mangles function signatures according to the Sip (Structured Index Path) V1 // scheme. // -// Mangler for the 'sip' ABI. See function_abi.md in the documentation. +// Mangler for the 'sip' ABI. See docs/design_docs/function_abi.md in the +// documentation. class SipSignatureMangler { public: enum class IndexMode { @@ -443,7 +444,8 @@ // Parser for signatures generated by SipSignatureMangler. // This uses a Visitor interface to walk either input or result structs. // -// Mangler for the 'sip' ABI. See function_abi.md in the documentation. +// Mangler for the 'sip' ABI. See docs/design_docs/function_abi.md in the +// documentation. class SipSignatureParser { public: enum class StructType {
diff --git a/iree/base/time.h b/iree/base/time.h index 81f9809..e51a5b1 100644 --- a/iree/base/time.h +++ b/iree/base/time.h
@@ -15,31 +15,143 @@ #ifndef IREE_BASE_TIME_H_ #define IREE_BASE_TIME_H_ -#include <chrono> // NOLINT -#include <thread> // NOLINT +#include <type_traits> +#include <utility> -#include "absl/time/clock.h" -#include "absl/time/time.h" +#include "iree/base/api.h" namespace iree { +namespace impl { +template <class Tag, typename T> +class ChronoType { + public: + ChronoType() : value_() {} + explicit ChronoType(const T& value) : value_(value) {} + explicit ChronoType(T&& value) noexcept( + std::is_nothrow_move_constructible<T>::value) + : value_(std::move(value)) {} -// Converts a relative timeout duration to an absolute deadline time. -// This handles the special cases of absl::ZeroDuration and -// absl::InfiniteDuration to avoid extraneous time queries. -inline absl::Time RelativeTimeoutToDeadline(absl::Duration timeout) { - if (timeout == absl::ZeroDuration()) { - return absl::InfinitePast(); - } else if (timeout == absl::InfiniteDuration()) { - return absl::InfiniteFuture(); + explicit operator T&() noexcept { return value_; } + explicit operator const T&() const noexcept { return value_; } + + friend void swap(ChronoType& a, ChronoType& b) noexcept { + using std::swap; + swap(static_cast<T&>(a), static_cast<T&>(b)); } - return absl::Now() + timeout; + + friend inline bool operator==(const ChronoType& lhs, const ChronoType& rhs) { + return lhs.value_ == rhs.value_; + } + friend inline bool operator!=(const ChronoType& lhs, const ChronoType& rhs) { + return !(lhs == rhs); + } + friend inline bool operator<(const ChronoType& lhs, const ChronoType& rhs) { + return lhs.value_ < rhs.value_; + } + friend inline bool operator>(const ChronoType& lhs, const ChronoType& rhs) { + return rhs < lhs; + } + friend inline bool operator<=(const ChronoType& lhs, const ChronoType& rhs) { + return !(lhs > rhs); + } + friend inline bool operator>=(const ChronoType& lhs, const ChronoType& rhs) { + return !(lhs < rhs); + } + + friend ChronoType& operator+=(ChronoType& lhs, const ChronoType& rhs) { + static_cast<T&>(lhs) += static_cast<const T&>(rhs); + return lhs; + } + friend ChronoType operator+(const ChronoType& lhs, const ChronoType& rhs) { + return ChronoType(static_cast<const T&>(lhs) + static_cast<const T&>(rhs)); + } + + friend ChronoType& operator-=(ChronoType& lhs, const ChronoType& rhs) { + static_cast<T&>(lhs) -= static_cast<const T&>(rhs); + return lhs; + } + friend ChronoType operator-(const ChronoType& lhs, const ChronoType& rhs) { + return ChronoType(static_cast<const T&>(lhs) - static_cast<const T&>(rhs)); + } + + private: + T value_; +}; +} // namespace impl + +struct Duration : public impl::ChronoType<Duration, iree_duration_t> { + using ChronoType::ChronoType; + explicit operator uint64_t() const noexcept { + if (static_cast<iree_duration_t>(*this) == IREE_DURATION_INFINITE) { + return UINT64_MAX; + } + int64_t relative_ns = static_cast<int64_t>(*this); + return relative_ns <= 0 ? 0 : static_cast<uint64_t>(relative_ns); + } +}; + +static inline Duration InfiniteDuration() { + return Duration(IREE_DURATION_INFINITE); +} +static inline Duration ZeroDuration() { return Duration(IREE_DURATION_ZERO); } + +struct Time : public impl::ChronoType<Time, iree_time_t> { + using ChronoType::ChronoType; + friend Duration operator+(const Time& lhs, const Time& rhs) { + if (static_cast<iree_time_t>(lhs) == IREE_TIME_INFINITE_FUTURE || + static_cast<iree_time_t>(rhs) == IREE_TIME_INFINITE_FUTURE) { + return InfiniteDuration(); + } else if (static_cast<iree_time_t>(lhs) == IREE_TIME_INFINITE_PAST || + static_cast<iree_time_t>(rhs) == IREE_TIME_INFINITE_PAST) { + return ZeroDuration(); + } + return Duration(static_cast<const iree_time_t&>(lhs) + + static_cast<const iree_time_t&>(rhs)); + } + friend Duration operator-(const Time& lhs, const Time& rhs) { + if (static_cast<iree_time_t>(lhs) == IREE_TIME_INFINITE_FUTURE || + static_cast<iree_time_t>(rhs) == IREE_TIME_INFINITE_FUTURE) { + return InfiniteDuration(); + } else if (static_cast<iree_time_t>(lhs) == IREE_TIME_INFINITE_PAST || + static_cast<iree_time_t>(rhs) == IREE_TIME_INFINITE_PAST) { + return ZeroDuration(); + } + return Duration(static_cast<const iree_time_t&>(lhs) - + static_cast<const iree_time_t&>(rhs)); + } +}; + +static inline Time InfinitePast() { return Time(IREE_TIME_INFINITE_PAST); } +static inline Time InfiniteFuture() { return Time(IREE_TIME_INFINITE_FUTURE); } + +static inline Duration Milliseconds(int64_t millis) { + return Duration(millis * 1000000ull); } -// Suspends execution of the calling thread for the given |duration|. -// Depending on platform this may have an extremely coarse resolution (upwards -// of several to dozens of milliseconds). -inline void Sleep(absl::Duration duration) { - std::this_thread::sleep_for(absl::ToChronoMilliseconds(duration)); +// Returns the current system time in unix nanoseconds. +// Depending on the system architecture and power mode this time may have a +// very coarse granularity (on the order of microseconds to milliseconds). +// +// The system timer may not be monotonic; users should ensure when comparing +// times they check for negative values in case the time moves backwards. +static inline Time Now() { return Time(iree_time_now()); } + +// Converts a relative timeout duration to an absolute deadline time. +// This handles the special cases of IREE_DURATION_ZERO and +// IREE_DURATION_INFINITE to avoid extraneous time queries. +static inline Time RelativeTimeoutToDeadlineNanos(Duration timeout_ns) { + return Time(iree_relative_timeout_to_deadline_ns( + static_cast<iree_duration_t>(timeout_ns))); +} + +static inline Duration DeadlineToRelativeTimeoutNanos(Time deadline_ns) { + if (deadline_ns == InfiniteFuture()) { + return InfiniteDuration(); + } else if (deadline_ns == InfinitePast()) { + return ZeroDuration(); + } else { + return Duration(static_cast<uint64_t>(deadline_ns - Now())); + } } } // namespace iree
diff --git a/iree/base/time_test.cc b/iree/base/time_test.cc new file mode 100644 index 0000000..114cd4e --- /dev/null +++ b/iree/base/time_test.cc
@@ -0,0 +1,45 @@ +// Copyright 2020 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/base/time.h" + +#include "iree/testing/gtest.h" + +namespace iree { +namespace { + +TEST(Time, DurationComparisons) { + EXPECT_TRUE(Milliseconds(123) == Milliseconds(123)); + EXPECT_FALSE(Milliseconds(123) == Milliseconds(456)); + EXPECT_FALSE(Milliseconds(123) != Milliseconds(123)); + EXPECT_TRUE(Milliseconds(123) != Milliseconds(456)); + + EXPECT_TRUE(Milliseconds(123) < Milliseconds(456)); + EXPECT_FALSE(Milliseconds(123) > Milliseconds(456)); + EXPECT_FALSE(Milliseconds(123) > Milliseconds(123)); + EXPECT_FALSE(Milliseconds(123) < Milliseconds(123)); + + EXPECT_TRUE(Milliseconds(123) <= Milliseconds(123)); + EXPECT_TRUE(Milliseconds(123) >= Milliseconds(123)); + EXPECT_TRUE(Milliseconds(123) <= Milliseconds(456)); + EXPECT_FALSE(Milliseconds(123) >= Milliseconds(456)); +} + +TEST(Time, DurationArithmetic) { + EXPECT_EQ(Milliseconds(150), Milliseconds(100) + Milliseconds(50)); + EXPECT_EQ(Milliseconds(50), Milliseconds(100) - Milliseconds(50)); +} + +} // namespace +} // namespace iree
diff --git a/iree/base/wait_handle.cc b/iree/base/wait_handle.cc index 2c67f31..9f00a33 100644 --- a/iree/base/wait_handle.cc +++ b/iree/base/wait_handle.cc
@@ -76,7 +76,7 @@ // ppoll is preferred as it has a much better timing mechanism; poll can have a // large slop on the deadline. // Documentation: https://linux.die.net/man/2/poll -StatusOr<int> SystemPoll(absl::Span<pollfd> poll_fds, absl::Time deadline) { +StatusOr<int> SystemPoll(absl::Span<pollfd> poll_fds, Time deadline_ns) { // Convert the deadline into a tmo_p struct for ppoll that controls whether // the call is blocking or non-blocking. Note that we must do this every // iteration of the loop as a previous ppoll may have taken some of the @@ -86,16 +86,16 @@ // http://man7.org/linux/man-pages/man2/poll.2.html timespec timeout_spec; timespec* tmo_p; - if (deadline == absl::InfinitePast()) { + if (deadline == InfinitePast()) { // 0 for non-blocking. timeout_spec = {0}; tmo_p = &timeout_spec; - } else if (deadline == absl::InfiniteFuture()) { + } else if (deadline == InfiniteFuture()) { // nullptr to ppoll() to block forever. tmo_p = nullptr; } else { // Wait only for as much time as we have before the deadline is exceeded. - absl::Duration remaining_time = deadline - absl::Now(); + absl::Duration remaining_time = deadline - Now(); if (remaining_time < absl::ZeroDuration()) { // Note: we likely have already bailed before getting here with a negative // duration. @@ -111,16 +111,16 @@ // poll(), present pretty much everywhere. // Documentation: https://linux.die.net/man/2/poll -StatusOr<int> SystemPoll(absl::Span<pollfd> poll_fds, absl::Time deadline) { +StatusOr<int> SystemPoll(absl::Span<pollfd> poll_fds, Time deadline_ns) { int timeout; - if (deadline == absl::InfinitePast()) { + if (deadline == InfinitePast()) { // Don't block. timeout = 0; - } else if (deadline == absl::InfiniteFuture()) { + } else if (deadline == InfiniteFuture()) { // Block forever. timeout = -1; } else { - absl::Duration remaining_time = deadline - absl::Now(); + absl::Duration remaining_time = deadline - Now(); if (remaining_time < absl::ZeroDuration()) { return DeadlineExceededErrorBuilder(IREE_LOC); } @@ -139,7 +139,7 @@ // The provided deadline will be observed if any of the wait handles needs to // block for acquiring an fd. StatusOr<absl::FixedArray<pollfd>> AcquireWaitHandles( - WaitHandle::WaitHandleSpan wait_handles, absl::Time deadline) { + WaitHandle::WaitHandleSpan wait_handles, Time deadline_ns) { absl::FixedArray<pollfd> poll_fds{wait_handles.size()}; for (int i = 0; i < wait_handles.size(); ++i) { poll_fds[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; @@ -160,7 +160,7 @@ poll_fds[i].fd = fd_info.second; // Abort if deadline exceeded. - if (deadline != absl::InfinitePast() && deadline < absl::Now()) { + if (deadline != InfinitePast() && deadline < Now()) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline exceeded acquiring for fds"; } @@ -204,7 +204,7 @@ // Performs a single poll on multiple fds and returns information about the // signaled fds, if any. Status MultiPoll(WaitHandle::WaitHandleSpan wait_handles, - absl::Span<pollfd> poll_fds, absl::Time deadline, + absl::Span<pollfd> poll_fds, Time deadline_ns, int* out_any_signaled_index, int* out_unsignaled_count) { *out_any_signaled_index = -1; *out_unsignaled_count = 0; @@ -293,7 +293,7 @@ public: std::string DebugString() const override { return "signal"; } StatusOr<std::pair<FdType, int>> AcquireFdForWait( - absl::Time deadline) override { + Time deadline_ns) override { return std::make_pair(FdType::kPermanent, kSignaledFd); } StatusOr<bool> TryResolveWakeOnFd(int fd) override { return true; } @@ -308,7 +308,7 @@ public: std::string DebugString() const override { return "fail"; } StatusOr<std::pair<FdType, int>> AcquireFdForWait( - absl::Time deadline) override { + Time deadline_ns) override { return InternalErrorBuilder(IREE_LOC) << "AlwaysFailingObject"; } StatusOr<bool> TryResolveWakeOnFd(int fd) override { @@ -320,7 +320,7 @@ } // static -Status WaitHandle::WaitAll(WaitHandleSpan wait_handles, absl::Time deadline) { +Status WaitHandle::WaitAll(WaitHandleSpan wait_handles, Time deadline_ns) { if (wait_handles.empty()) return OkStatus(); // Build the list of pollfds to wait on. @@ -332,7 +332,7 @@ int any_signaled_index = 0; RETURN_IF_ERROR(MultiPoll(wait_handles, absl::MakeSpan(poll_fds), deadline, &any_signaled_index, &unsignaled_count)); - } while (unsignaled_count > 0 && absl::Now() < deadline); + } while (unsignaled_count > 0 && Now() < deadline); if (unsignaled_count == 0) { // All waits resolved. @@ -345,7 +345,7 @@ // static StatusOr<bool> WaitHandle::TryWaitAll(WaitHandleSpan wait_handles) { - auto status = WaitAll(wait_handles, absl::InfinitePast()); + auto status = WaitAll(wait_handles, InfinitePast()); if (status.ok()) { return true; } else if (IsDeadlineExceeded(status)) { @@ -356,7 +356,7 @@ // static StatusOr<int> WaitHandle::WaitAny(WaitHandleSpan wait_handles, - absl::Time deadline) { + Time deadline_ns) { if (wait_handles.empty()) { return InvalidArgumentErrorBuilder(IREE_LOC) << "At least one wait handle is required for WaitAny"; @@ -379,7 +379,7 @@ // static StatusOr<int> WaitHandle::TryWaitAny(WaitHandleSpan wait_handles) { - auto status_or = WaitAny(wait_handles, absl::InfinitePast()); + auto status_or = WaitAny(wait_handles, InfinitePast()); return IsDeadlineExceeded(status_or.status()) ? -1 : status_or; } @@ -418,7 +418,7 @@ } StatusOr<bool> WaitHandle::TryWait() { - auto status = WaitAll({this}, absl::InfinitePast()); + auto status = WaitAll({this}, InfinitePast()); if (status.ok()) { return true; } else if (IsDeadlineExceeded(status)) {
diff --git a/iree/base/wait_handle.h b/iree/base/wait_handle.h index d051e51..7d9a4af 100644 --- a/iree/base/wait_handle.h +++ b/iree/base/wait_handle.h
@@ -20,8 +20,6 @@ #include <string> #include <utility> -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "absl/types/span.h" #include "iree/base/ref_ptr.h" #include "iree/base/status.h" @@ -42,7 +40,7 @@ // } // private: // StatusOr<std::pair<FdType, int>> AcquireFdForWait( -// absl::Time deadline) override { +// Time deadline_ns) override { // // If blocking traditionally do so now and then return this: // return std::make_pair(FdType::kPermanent, kSignaledFd); // // Otherwise, see ManualResetEvent for an example using fds. @@ -112,14 +110,14 @@ // // In cases where the file descriptor may not be available the call may block // until either it is available or the |deadline| has elapsed. Use - // absl::InfinitePast() to prevent blocking. + // InfinitePast() to prevent blocking. // // Returns a valid file descriptor or kInvalidFd as an indication that the // object should not be waited on (already signaled, etc). Can return // kSignaledFd to indicate that it's already known that the handle has been // signaled and the caller should resolve as if it caused a wake normally. virtual StatusOr<std::pair<FdType, int>> AcquireFdForWait( - absl::Time deadline) = 0; + Time deadline_ns) = 0; // Tries to resolve the object with the given |fd|. // In many cases this will no-op, however some types may require additional @@ -159,12 +157,12 @@ // Returns DEADLINE_EXCEEDED if the |deadline| elapses without all handles // having been signaled. Note that a subset of the |wait_handles| may have // been signaled and each can be queried to see which one. - static Status WaitAll(WaitHandleSpan wait_handles, absl::Time deadline); - static Status WaitAll(WaitHandleSpan wait_handles, absl::Duration timeout) { - return WaitAll(wait_handles, RelativeTimeoutToDeadline(timeout)); + static Status WaitAll(WaitHandleSpan wait_handles, Time deadline_ns); + static Status WaitAll(WaitHandleSpan wait_handles, Duration timeout_ns) { + return WaitAll(wait_handles, RelativeTimeoutToDeadlineNanos(timeout_ns)); } static Status WaitAll(WaitHandleSpan wait_handles) { - return WaitAll(wait_handles, absl::InfiniteFuture()); + return WaitAll(wait_handles, InfiniteFuture()); } // Tries waiting on the handles and returns immediately if it would have @@ -184,14 +182,13 @@ // // Returns DEADLINE_EXCEEDED if the |deadline| elapses without any handles // having been signaled. + static StatusOr<int> WaitAny(WaitHandleSpan wait_handles, Time deadline_ns); static StatusOr<int> WaitAny(WaitHandleSpan wait_handles, - absl::Time deadline); - static StatusOr<int> WaitAny(WaitHandleSpan wait_handles, - absl::Duration timeout) { - return WaitAny(wait_handles, RelativeTimeoutToDeadline(timeout)); + Duration timeout_ns) { + return WaitAny(wait_handles, RelativeTimeoutToDeadlineNanos(timeout_ns)); } static StatusOr<int> WaitAny(WaitHandleSpan wait_handles) { - return WaitAny(wait_handles, absl::InfiniteFuture()); + return WaitAny(wait_handles, InfiniteFuture()); } // Tries waiting for at least one handle to complete and returns immediately @@ -242,11 +239,11 @@ // Returns success if the wait is successful and the |wait_handle| was // signaled. Returns DEADLINE_EXCEEDED if the timeout elapses without the // handle having been signaled. - Status Wait(absl::Time deadline) { return WaitAll({this}, deadline); } - Status Wait(absl::Duration timeout) { - return WaitAll({this}, RelativeTimeoutToDeadline(timeout)); + Status Wait(Time deadline_ns) { return WaitAll({this}, deadline); } + Status Wait(Duration timeout_ns) { + return WaitAll({this}, RelativeTimeoutToDeadlineNanos(timeout_ns)); } - Status Wait() { return WaitAll({this}, absl::InfiniteFuture()); } + Status Wait() { return WaitAll({this}, InfiniteFuture()); } // Tries waiting on the handle and returns immediately if it would have // waited. The caller will not be blocked even if the handle has not yet been @@ -304,8 +301,7 @@ void Initialize(); void Dispose(); - StatusOr<std::pair<FdType, int>> AcquireFdForWait( - absl::Time deadline) override { + StatusOr<std::pair<FdType, int>> AcquireFdForWait(Time deadline_ns) override { return std::make_pair(fd_type_, fd_); } StatusOr<bool> TryResolveWakeOnFd(int fd) override { return true; }
diff --git a/iree/base/wait_handle_test.cc b/iree/base/wait_handle_test.cc index ea4c7f1..a9f1ad1 100644 --- a/iree/base/wait_handle_test.cc +++ b/iree/base/wait_handle_test.cc
@@ -90,7 +90,7 @@ TEST(WaitHandleTest, SingleWait) { WaitHandle wh; ASSERT_OK(wh.Wait()); - ASSERT_OK(wh.Wait(absl::Now() + absl::Seconds(1))); + ASSERT_OK(wh.Wait(Now() + absl::Seconds(1))); ASSERT_OK(wh.Wait(absl::Seconds(1))); ASSERT_STATUSOR_TRUE(wh.TryWait()); } @@ -110,21 +110,21 @@ WaitHandle wh1 = fence1.OnSet(); // Poll; should return immediately with timeout. - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAll({&wh0, &wh1}, absl::InfinitePast()))); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAll({&wh0, &wh1}, InfinitePast()))); // Notify fence1. ASSERT_OK(fence1.Set()); // Poll; should return immediately with timeout as fence1 is not signaled. - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAll({&wh0, &wh1}, absl::InfinitePast()))); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAll({&wh0, &wh1}, InfinitePast()))); // Notify fence0. ASSERT_OK(fence0.Set()); // Poll again; should return immediately with success. - ASSERT_OK(WaitHandle::WaitAll({&wh0, &wh1}, absl::InfinitePast())); + ASSERT_OK(WaitHandle::WaitAll({&wh0, &wh1}, InfinitePast())); } // Tests waiting when the first file handle is invalid. This is to verify a @@ -134,14 +134,14 @@ WaitHandle wh = fence.OnSet(); // Poll; should return immediately with timeout as fence is not signaled. - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAll({nullptr, &wh}, absl::InfinitePast()))); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAll({nullptr, &wh}, InfinitePast()))); // Notify fence. ASSERT_OK(fence.Set()); // Poll again; should return immediately with success. - ASSERT_OK(WaitHandle::WaitAll({nullptr, &wh}, absl::InfinitePast())); + ASSERT_OK(WaitHandle::WaitAll({nullptr, &wh}, InfinitePast())); } // Tests exceeding the timeout deadline with WaitAll. @@ -151,25 +151,24 @@ // Wait with timeout on the unsignaled fence: // Via polling (should never block): - ASSERT_TRUE( - IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, absl::InfinitePast()))); + ASSERT_TRUE(IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, InfinitePast()))); ASSERT_STATUSOR_FALSE(WaitHandle::TryWaitAll({&wh})); // Via time in the near future (should block): ASSERT_TRUE( - IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, absl::Milliseconds(250)))); + IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, Milliseconds(250)))); // Via time in the past, should exceed deadline. ASSERT_TRUE( - IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, absl::Milliseconds(-250)))); + IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, Milliseconds(-250)))); // Notify and ensure no more timeouts. ASSERT_OK(fence.Set()); - ASSERT_OK(WaitHandle::WaitAll({&wh}, absl::InfinitePast())); + ASSERT_OK(WaitHandle::WaitAll({&wh}, InfinitePast())); ASSERT_STATUSOR_TRUE(WaitHandle::TryWaitAll({&wh})); - ASSERT_OK(WaitHandle::WaitAll({&wh}, absl::Milliseconds(250))); + ASSERT_OK(WaitHandle::WaitAll({&wh}, Milliseconds(250))); // Via time in the past, should exceed deadline even if signaled. ASSERT_TRUE( - IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, absl::Milliseconds(-250)))); + IsDeadlineExceeded(WaitHandle::WaitAll({&wh}, Milliseconds(-250)))); } // Tests using WaitAll to wait on other threads. @@ -177,12 +176,12 @@ // Spin up two threads. ManualResetEvent fence0; std::thread t0{[&]() { - ::usleep(absl::ToInt64Microseconds(absl::Milliseconds(250))); + ::usleep(absl::ToInt64Microseconds(Milliseconds(250))); ASSERT_OK(fence0.Set()); }}; ManualResetEvent fence1; std::thread t1{[&]() { - ::usleep(absl::ToInt64Microseconds(absl::Milliseconds(250))); + ::usleep(absl::ToInt64Microseconds(Milliseconds(250))); ASSERT_OK(fence1.Set()); }}; @@ -200,8 +199,8 @@ ManualResetEvent fence; WaitHandle wh0 = fence.OnSet(); WaitHandle wh1 = fence.OnSet(); - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAll({&wh0, &wh1}, absl::InfinitePast()))); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAll({&wh0, &wh1}, InfinitePast()))); ASSERT_OK(fence.Set()); ASSERT_OK(WaitHandle::WaitAll({&wh0, &wh1})); } @@ -210,8 +209,8 @@ TEST(WaitHandleTest, WaitAllSameHandle) { ManualResetEvent fence; WaitHandle wh = fence.OnSet(); - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAll({&wh, &wh}, absl::InfinitePast()))); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAll({&wh, &wh}, InfinitePast()))); ASSERT_OK(fence.Set()); ASSERT_OK(WaitHandle::WaitAll({&wh, &wh})); } @@ -243,14 +242,14 @@ // Poll; should return immediately with timeout. ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast()).status())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast()).status())); // Notify fence1. ASSERT_OK(fence1.Set()); // Poll; should return immediately with fence1 signaled. ASSERT_OK_AND_ASSIGN(int index, - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast())); EXPECT_EQ(1, index); // Notify fence0. @@ -258,7 +257,7 @@ // Poll again; should return immediately; which one is signaled is undefined. ASSERT_OK_AND_ASSIGN(index, - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast())); ASSERT_TRUE(index == 0 || index == 1); } @@ -272,41 +271,39 @@ // Wait with timeout on the unsignaled fences: // Via polling (should never block): ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast()).status())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast()).status())); ASSERT_OK_AND_ASSIGN(int index, WaitHandle::TryWaitAny({&wh0, &wh1})); ASSERT_EQ(-1, index); // Via time in the near future (should block): ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0, &wh1}, absl::Milliseconds(250)).status())); + WaitHandle::WaitAny({&wh0, &wh1}, Milliseconds(250)).status())); // Notify one of the fences. Should return immediately. ASSERT_OK(fence1.Set()); ASSERT_OK_AND_ASSIGN(index, - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast())); ASSERT_EQ(1, index); ASSERT_OK_AND_ASSIGN(index, WaitHandle::TryWaitAny({&wh0, &wh1})); ASSERT_EQ(1, index); - ASSERT_OK_AND_ASSIGN( - index, WaitHandle::WaitAny({&wh0, &wh1}, absl::Milliseconds(250))); + ASSERT_OK_AND_ASSIGN(index, + WaitHandle::WaitAny({&wh0, &wh1}, Milliseconds(250))); ASSERT_EQ(1, index); // The unnotified fence should still timeout. - ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0}, absl::InfinitePast()).status())); + ASSERT_TRUE( + IsDeadlineExceeded(WaitHandle::WaitAny({&wh0}, InfinitePast()).status())); ASSERT_OK_AND_ASSIGN(index, WaitHandle::TryWaitAny({&wh0})); ASSERT_EQ(-1, index); ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0}, absl::Milliseconds(250)).status())); + WaitHandle::WaitAny({&wh0}, Milliseconds(250)).status())); // Notify last fence and ensure complete. ASSERT_OK(fence0.Set()); - ASSERT_OK_AND_ASSIGN(index, - WaitHandle::WaitAny({&wh0}, absl::InfinitePast())); + ASSERT_OK_AND_ASSIGN(index, WaitHandle::WaitAny({&wh0}, InfinitePast())); ASSERT_EQ(0, index); ASSERT_OK_AND_ASSIGN(index, WaitHandle::TryWaitAny({&wh0})); ASSERT_EQ(0, index); - ASSERT_OK_AND_ASSIGN(index, - WaitHandle::WaitAny({&wh0}, absl::Milliseconds(250))); + ASSERT_OK_AND_ASSIGN(index, WaitHandle::WaitAny({&wh0}, Milliseconds(250))); ASSERT_EQ(0, index); } @@ -316,13 +313,13 @@ // t1 will wait on t0 such that they will act in sequence. ManualResetEvent fence0; std::thread t0{[&]() { - ::usleep(absl::ToInt64Microseconds(absl::Milliseconds(250))); + ::usleep(absl::ToInt64Microseconds(Milliseconds(250))); ASSERT_OK(fence0.Set()); }}; ManualResetEvent fence1; std::thread t1{[&]() { ASSERT_OK(fence0.OnSet().Wait()); - ::usleep(absl::ToInt64Microseconds(absl::Milliseconds(250))); + ::usleep(absl::ToInt64Microseconds(Milliseconds(250))); ASSERT_OK(fence1.Set()); }}; @@ -346,7 +343,7 @@ WaitHandle wh0 = fence.OnSet(); WaitHandle wh1 = fence.OnSet(); ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh0, &wh1}, absl::InfinitePast()).status())); + WaitHandle::WaitAny({&wh0, &wh1}, InfinitePast()).status())); ASSERT_OK(fence.Set()); ASSERT_OK_AND_ASSIGN(int index, WaitHandle::WaitAny({&wh0, &wh1})); ASSERT_TRUE(index == 0 || index == 1); @@ -357,7 +354,7 @@ ManualResetEvent fence; WaitHandle wh = fence.OnSet(); ASSERT_TRUE(IsDeadlineExceeded( - WaitHandle::WaitAny({&wh, &wh}, absl::InfinitePast()).status())); + WaitHandle::WaitAny({&wh, &wh}, InfinitePast()).status())); ASSERT_OK(fence.Set()); ASSERT_OK_AND_ASSIGN(int index, WaitHandle::WaitAny({&wh, &wh})); ASSERT_TRUE(index == 0 || index == 1); @@ -386,7 +383,7 @@ MOCK_METHOD(std::string, DebugString, (), (const, override)); MOCK_METHOD((StatusOr<std::pair<FdType, int>>), AcquireFdForWait, - (absl::Time deadline), (override)); + (Time deadline_ns), (override)); MOCK_METHOD(StatusOr<bool>, TryResolveWakeOnFd, (int fd), (override)); WaitHandle OnSomething() { return WaitHandle(add_ref(this)); } @@ -402,7 +399,7 @@ // Try waiting; we should see the AcquireFdForWait and then return because // the fd has not been resolved. - EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([&](absl::Time deadline) { + EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([&](Time deadline_ns) { // Return the valid FD from the MRE. return mre.AcquireFdForWait(deadline); }); @@ -413,7 +410,7 @@ // Try waiting again; we should get the AcquireFdForWait and then also get // the TryResolveWakeOnFd. - EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([&](absl::Time deadline) { + EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([&](Time deadline_ns) { // Return the valid (and now signaled) FD from the MRE. return mre.AcquireFdForWait(deadline); }); @@ -431,13 +428,13 @@ // Make the AcquireFdForWait take longer than the timeout. We should hit // deadline exceeded even though always_wait hasn't be signaled. - EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([](absl::Time deadline) { - ::usleep(absl::ToInt64Microseconds(absl::Milliseconds(10))); + EXPECT_CALL(mwo, AcquireFdForWait(_)).WillOnce([](Time deadline_ns) { + ::usleep(absl::ToInt64Microseconds(Milliseconds(10))); return std::make_pair(WaitableObject::FdType::kPermanent, WaitableObject::kInvalidFd); }); - ASSERT_TRUE(IsDeadlineExceeded(WaitHandle::WaitAll( - {&wh, &always_signal}, absl::Now() - absl::Milliseconds(250)))); + ASSERT_TRUE(IsDeadlineExceeded( + WaitHandle::WaitAll({&wh, &always_signal}, Now() - Milliseconds(250)))); } // Tests TryResolveWakeOnFd when a handle is a permanent kSignaledFd.
diff --git a/iree/compiler/Conversion/HLOToLinalg/HLOToLinalgOnBuffers.cpp b/iree/compiler/Conversion/HLOToLinalg/HLOToLinalgOnBuffers.cpp index 99f7eb1..90178fc 100644 --- a/iree/compiler/Conversion/HLOToLinalg/HLOToLinalgOnBuffers.cpp +++ b/iree/compiler/Conversion/HLOToLinalg/HLOToLinalgOnBuffers.cpp
@@ -27,6 +27,7 @@ #include "iree/compiler/Dialect/IREE/IR/IREEOps.h" #include "iree/compiler/Dialect/Shape/IR/ShapeOps.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "mlir/Dialect/Linalg/IR/LinalgOps.h" @@ -444,7 +445,7 @@ rewriter.getI64IntegerAttr(1), // args_out rewriter.getArrayAttr(indexingMaps), getParallelAndReductionIterAttrs(rewriter, nloops, nonParallelLoops), - /*doc=*/nullptr, /*library_call=*/nullptr); + /*doc=*/nullptr, /*library_call=*/nullptr, /*symbol_source=*/nullptr); // Add a block to the region. auto *region = &linalgOp.region(); @@ -523,11 +524,6 @@ LogicalResult PadOpConversion::apply( mhlo::PadOp op, ArrayRef<Value> inputBuffers, ArrayRef<Value> resultBuffers, ConversionPatternRewriter &rewriter) const { - if (llvm::any_of(op.interior_padding().getValues<IntegerAttr>(), - [](auto attr) { return attr.getInt() != 0; })) - return op.emitError( - "pad op with non-zero interiror_padding is not supported"); - mhlo::PadOp::Adaptor adaptor(inputBuffers); auto loc = op.getLoc(); @@ -535,84 +531,31 @@ Value paddingVal = paddingConstVal ? rewriter.create<ConstantOp>(loc, paddingConstVal).getResult() - : adaptor.padding_value(); + : rewriter.create<LoadOp>(loc, adaptor.padding_value()); - auto operandType = adaptor.operand().getType().cast<ShapedType>(); - int rank = operandType.getRank(); - - SmallVector<Attribute, 2> indexingMaps; - indexingMaps.emplace_back(getPadOpInputIndexingMap(op, rank, rewriter)); - if (!paddingConstVal) { - indexingMaps.emplace_back(AffineMapAttr::get( - AffineMap::get(rank, /*symbolCount=*/0, rewriter.getContext()))); - } - indexingMaps.emplace_back(AffineMapAttr::get( - AffineMap::getMultiDimIdentityMap(rank, rewriter.getContext()))); - - SmallVector<Type, 2> resultTypes = {}; - SmallVector<Value, 2> linalgOpArgs = {adaptor.operand()}; - if (!paddingConstVal) linalgOpArgs.push_back(adaptor.padding_value()); - linalgOpArgs.push_back(resultBuffers[0]); - auto linalgOp = rewriter.create<linalg::IndexedGenericOp>( - loc, resultTypes, linalgOpArgs, - rewriter.getI64IntegerAttr(linalgOpArgs.size() - 1), // args_in - rewriter.getI64IntegerAttr(1), // args_out - rewriter.getArrayAttr(indexingMaps), - getParallelAndReductionIterAttrs(rewriter, rank, /*nReduction=*/0), - /*doc=*/nullptr, /*library_call=*/nullptr); - - // Add a block to the region. - auto *region = &linalgOp.region(); - auto *block = rewriter.createBlock(region, region->end()); - SmallVector<Type, 4> bodyArgTypes; - bodyArgTypes.append(rank, rewriter.getIndexType()); - bodyArgTypes.append(linalgOpArgs.size(), operandType.getElementType()); - block->addArguments(bodyArgTypes); - rewriter.setInsertionPointToEnd(block); - - // If the `index` of the result at a particular dimension i, is d_i, check if - // - // (d_i >= edge_padding_low[i]) && - // (d_i < (edge_padding_low[i] + operand_shape[i])). - // - // If true, then use the value of the operand, otherwise use the padding - // value. const auto &edgePaddingLow = op.edge_padding_low(); - const auto &edgePaddingHigh = op.edge_padding_high(); - - Type indexType = rewriter.getIndexType(); - Value cond = nullptr; - auto applyAndOp = [&](Value val) { - cond = cond ? rewriter.create<AndOp>(loc, cond, val) : val; - }; - for (int i = 0; i < rank; ++i) { - Value dim = block->getArgument(i); - int64_t paddingLow = edgePaddingLow.getValue<IntegerAttr>(i).getInt(); - int64_t paddingHigh = edgePaddingHigh.getValue<IntegerAttr>(i).getInt(); - auto low = rewriter.create<ConstantOp>( - loc, indexType, rewriter.getIntegerAttr(indexType, paddingLow)); - - // d_i < (edge_padding_low[i] + operand_shape[i]) - if (paddingLow != 0 && paddingHigh != 0) { - auto operandExtent = rewriter.create<DimOp>(loc, adaptor.operand(), i); - auto bound = rewriter.create<AddIOp>(loc, low, operandExtent); - auto checkUb = - rewriter.create<CmpIOp>(loc, CmpIPredicate::slt, dim, bound); - applyAndOp(checkUb); - } - - if (paddingLow != 0) { - // d_i >= edge_padding_low[i] - auto checkLb = rewriter.create<CmpIOp>(loc, CmpIPredicate::sge, dim, low); - applyAndOp(checkLb); - } + const auto &interiorPadding = op.interior_padding(); + SmallVector<Value, 3> offsets, sizes, strides; + for (auto it : llvm::enumerate(llvm::zip(edgePaddingLow, interiorPadding))) { + Value startIndex = rewriter.create<ConstantIndexOp>( + loc, std::get<0>(it.value()).getZExtValue()); + offsets.push_back(startIndex); + Value size = rewriter.create<DimOp>(loc, resultBuffers[0], it.index()); + sizes.push_back(size); + Value stride = rewriter.create<ConstantIndexOp>( + loc, std::get<1>(it.value()).getZExtValue() + 1); + strides.push_back(stride); } - Value inputVal = block->getArgument(rank); - if (!paddingConstVal) paddingVal = block->getArgument(rank + 1); - Value result = - cond ? rewriter.create<SelectOp>(loc, cond, inputVal, paddingVal) - : inputVal; - rewriter.create<linalg::YieldOp>(loc, result); + + // TODO(hanchung): Move SubViewOp this down to before where it is used. + // The pass for splitting dispatch function for vulkan requires no other ops + // interleave with Linalg structured ops, so put the SubViewOp in the + // beginning. + auto subViewOp = rewriter.create<SubViewOp>(loc, resultBuffers[0], offsets, + sizes, strides); + rewriter.create<linalg::FillOp>(loc, resultBuffers[0], paddingVal); + rewriter.create<linalg::CopyOp>(loc, inputBuffers[0], subViewOp); + return success(); } @@ -691,8 +634,9 @@ int batch = op.batch_dims().getSExtValue(); auto indexShapeType = adaptor.index().getType().dyn_cast<ShapedType>(); int nIndices = indexShapeType.getRank(); - if (batch < 0) - return op.emitError("expected batch_dims is greater than or equal to zero"); + auto inputShapeType = adaptor.input().getType().dyn_cast<ShapedType>(); + if (axis < 0) axis += inputShapeType.getRank(); + if (batch < 0) batch += nIndices; Location loc = op.getLoc(); Value output = op.getResult(); @@ -715,7 +659,7 @@ rewriter.getI64IntegerAttr(1), // args_out rewriter.getArrayAttr(indexingMaps), getParallelAndReductionIterAttrs(rewriter, rank, /*nReduction=*/0), - /*doc=*/nullptr, /*library_call=*/nullptr); + /*doc=*/nullptr, /*library_call=*/nullptr, /*symbol_source=*/nullptr); // Add a block to the region. auto *region = &linalgOp.region(); @@ -1019,7 +963,7 @@ rewriter.getArrayAttr(indexingMaps), getParallelAndReductionIterAttrs(rewriter, nInputRank, reductionDims.size()), - /*doc=*/nullptr, /*library_call=*/nullptr); + /*doc=*/nullptr, /*library_call=*/nullptr, /*symbol_source=*/nullptr); linalgOp.region().takeBody(reduceOp.body()); { @@ -1095,7 +1039,8 @@ op.getLoc(), ArrayRef<Type>(), opArgs, op.args_in(), op.args_out(), op.indexing_maps(), op.iterator_types(), /*doc=*/nullptr, - /*library_call=*/nullptr); + /*library_call=*/nullptr, + /*symbol_source=*/nullptr); // Move the region from the replaced op into the new op. unsigned numTensorOperands = op.getNumOperands(); // indexed_generic op has arguments for each index. In the case of generic
diff --git a/iree/compiler/Conversion/HLOToLinalg/test/pad.mlir b/iree/compiler/Conversion/HLOToLinalg/test/pad.mlir index a167ef4..8d1d96d 100644 --- a/iree/compiler/Conversion/HLOToLinalg/test/pad.mlir +++ b/iree/compiler/Conversion/HLOToLinalg/test/pad.mlir
@@ -5,7 +5,8 @@ func @pad_cst() { %c0 = constant 0 : index %0 = hal.interface.load.tensor @legacy_io::@arg0, offset = %c0 : tensor<12x4xf32> - // CHECK: linalg.indexed_generic + // CHECK: linalg.fill + // CHECK: linalg.copy %1 = constant dense<0.0> : tensor<f32> %2 = "mhlo.pad"(%0, %1) { edge_padding_high = dense<[2, 3]> : tensor<2xi64>, @@ -29,7 +30,8 @@ %c0 = constant 0 : index %0 = hal.interface.load.tensor @legacy_io::@arg0, offset = %c0 : tensor<12x4xf32> %1 = hal.interface.load.tensor @legacy_io::@arg1, offset = %c0 : tensor<f32> - // CHECK: linalg.indexed_generic + // CHECK: linalg.fill + // CHECK: linalg.copy %2 = "mhlo.pad"(%0, %1) { edge_padding_high = dense<[2, 3]> : tensor<2xi64>, edge_padding_low = dense<[4, 5]> : tensor<2xi64>, @@ -52,7 +54,8 @@ func @pad_no_op() { %c0 = constant 0 : index %0 = hal.interface.load.tensor @legacy_io::@arg0, offset = %c0 : tensor<12x4xf32> - // CHECK: linalg.indexed_generic + // CHECK: linalg.fill + // CHECK: linalg.copy %1 = constant dense<0.0> : tensor<f32> %2 = "mhlo.pad"(%0, %1) { edge_padding_high = dense<0> : tensor<2xi64>,
diff --git a/iree/compiler/Conversion/LinalgToLLVM/BUILD b/iree/compiler/Conversion/LinalgToLLVM/BUILD index 41d9988..fcd9476 100644 --- a/iree/compiler/Conversion/LinalgToLLVM/BUILD +++ b/iree/compiler/Conversion/LinalgToLLVM/BUILD
@@ -22,7 +22,6 @@ name = "LinalgToLLVM", srcs = [ "ConvertToLLVM.cpp", - "HALInterfaceToMemrefArguments.cpp", "Passes.cpp", ], hdrs = [
diff --git a/iree/compiler/Conversion/LinalgToLLVM/CMakeLists.txt b/iree/compiler/Conversion/LinalgToLLVM/CMakeLists.txt index d21dc19..bc31e4e 100644 --- a/iree/compiler/Conversion/LinalgToLLVM/CMakeLists.txt +++ b/iree/compiler/Conversion/LinalgToLLVM/CMakeLists.txt
@@ -21,7 +21,6 @@ "Passes.h" SRCS "ConvertToLLVM.cpp" - "HALInterfaceToMemrefArguments.cpp" "Passes.cpp" DEPS MLIRAffineToStandard
diff --git a/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp b/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp index 193eb3c..8686dca 100644 --- a/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp +++ b/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp
@@ -124,6 +124,180 @@ } }; +/// Returns true if `aOp` has a desciptor (set, binding) pair smaller than +/// `bOp`. Note that this ignores the offset. +bool operator<(IREE::HAL::InterfaceBindingOp aOp, + IREE::HAL::InterfaceBindingOp bOp) { + if (aOp.set().getZExtValue() == bOp.set().getZExtValue()) + return aOp.binding().getZExtValue() < bOp.binding().getZExtValue(); + return aOp.set().getZExtValue() < bOp.set().getZExtValue(); +} + +// Change signature of entry function to func +// entry_func(%packed_buffers_arg_ptr: +// !<llvm.int8**>, %push_constant: !<llvm.int64*>) and lower IREE and HAL ops to +// corresponding LLVMIR ops to construct memref descriptors and load +// push_constant values. +class ConvertFuncWithHALInterface : public ConvertToLLVMPattern { + public: + explicit ConvertFuncWithHALInterface(MLIRContext *context, + LLVMTypeConverter &typeconverter) + : ConvertToLLVMPattern(FuncOp::getOperationName(), context, + typeconverter) {} + + LogicalResult matchAndRewrite( + Operation *op, ArrayRef<Value> operands, + ConversionPatternRewriter &rewriter) const override { + if (SymbolTable::getSymbolVisibility(op) != SymbolTable::Visibility::Public) + return failure(); + auto funcOp = dyn_cast_or_null<FuncOp>(op); + FunctionType fnType = funcOp.getType(); + if (fnType.getNumInputs() != 0) { + return rewriter.notifyMatchFailure( + funcOp, "entry function should not have inputs"); + } + + // Get interface buffers from all the blocks. + SmallVector<IREE::PlaceholderOp, 8> bufferOps; + SmallVector<IREE::HAL::InterfaceLoadConstantOp, 8> loadOps; + for (Block &block : funcOp.getBlocks()) { + for (Operation &op : block) { + if (auto phOp = dyn_cast<IREE::PlaceholderOp>(op)) + bufferOps.push_back(phOp); + if (auto phOp = dyn_cast<IREE::HAL::InterfaceLoadConstantOp>(op)) { + loadOps.push_back(phOp); + } + } + } + + if (bufferOps.empty()) return failure(); + + // A map from buffer ops to their corresponding interface binding ops. + llvm::DenseMap<Operation *, IREE::HAL::InterfaceBindingOp> bufferBindingMap; + for (auto bufferOp : bufferOps) { + auto symbol = SymbolTable::lookupNearestSymbolFrom( + bufferOp, bufferOp.getAttrOfType<SymbolRefAttr>("binding")); + bufferBindingMap[bufferOp] = cast<IREE::HAL::InterfaceBindingOp>(symbol); + } + + // Sort buffers according to their descriptor (set, binding) pair. + llvm::sort(bufferOps, [&bufferBindingMap](IREE::PlaceholderOp aBuffer, + IREE::PlaceholderOp bBuffer) { + return bufferBindingMap[aBuffer] < bufferBindingMap[bBuffer]; + }); + + // A map from buffer ops to their corresponding function argument indices. + llvm::DenseMap<Operation *, unsigned> bufferArgMap; + // A map from binding ops to their corresponding function argument indices. + llvm::DenseMap<Operation *, unsigned> bindingArgMap; + llvm::SmallVector<MemRefType, 4> inputMemRefTypes; + llvm::SmallVector<LLVM::LLVMType, 4> inputStructPtrs; + unsigned argIndex = 0; + for (auto bufferOp : bufferOps) { + auto binding = bufferBindingMap[bufferOp]; + auto it = bindingArgMap.find(binding); + if (it != bindingArgMap.end()) { + bufferArgMap[bufferOp] = it->second; + } else { + bindingArgMap[binding] = argIndex; + bufferArgMap[bufferOp] = argIndex; + ++argIndex; + } + + auto memrefType = bufferOp.getType().dyn_cast_or_null<MemRefType>(); + inputMemRefTypes.push_back(memrefType); + auto elementType = typeConverter.convertType(memrefType.getElementType()) + .dyn_cast<LLVM::LLVMType>(); + if (!elementType) return failure(); + inputStructPtrs.push_back( + elementType.getPointerTo(memrefType.getMemorySpace())); + } + + TypeConverter::SignatureConversion signatureConverter(/*numOrigInputs=*/0); + + // func foo(%packed_buffer_args: !llvm<i8**>, %push_constant: !llvm<i64*>) + auto packedBuffersArgsTy = + LLVM::LLVMType::getInt8PtrTy(typeConverter.getDialect()).getPointerTo(); + auto pushConstantArgTy = + LLVM::LLVMType::getInt64Ty(typeConverter.getDialect()).getPointerTo(); + signatureConverter.addInputs(packedBuffersArgsTy); + signatureConverter.addInputs(pushConstantArgTy); + + // Create the new function's signature. + Location loc = funcOp.getLoc(); + auto newFuncOp = rewriter.create<FuncOp>( + loc, funcOp.getName(), + rewriter.getFunctionType(signatureConverter.getConvertedTypes(), + llvm::None), + ArrayRef<NamedAttribute>()); + + // Move all ops in the old function's region to the new function. + rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(), + newFuncOp.end()); + rewriter.applySignatureConversion(&newFuncOp.getBody(), signatureConverter); + + auto builder = OpBuilder::atBlockBegin(&(newFuncOp.getBlocks().front())); + + // Cast and unpack input packed_buffer_arguments and construct memref + // descriptors. + Value packedBuffersArgsPtr = builder.create<LLVM::BitcastOp>( + loc, + LLVM::LLVMType::getStructTy(typeConverter.getDialect(), inputStructPtrs) + .getPointerTo(), + newFuncOp.getArgument(0)); + Value packedBuffersArgs = + builder.create<LLVM::LoadOp>(loc, packedBuffersArgsPtr); + for (auto bufferOp : bufferOps) { + MemRefType memrefType = bufferOp.getType().dyn_cast_or_null<MemRefType>(); + if (!memrefType) return failure(); + const auto index = bufferArgMap[bufferOp]; + Value bufferPtr = builder.create<LLVM::ExtractValueOp>( + loc, inputStructPtrs[index], packedBuffersArgs, + rewriter.getI64ArrayAttr(index)); + if (memrefType.hasStaticShape()) { + auto desc = MemRefDescriptor::fromStaticShape( + builder, loc, typeConverter, memrefType, bufferPtr); + rewriter.replaceOp(bufferOp, {desc}); + } else { + auto desc = MemRefDescriptor::undef( + builder, loc, typeConverter.convertType(memrefType)); + desc.setAllocatedPtr(builder, loc, bufferPtr); + desc.setAlignedPtr(builder, loc, bufferPtr); + rewriter.replaceOp(bufferOp, {desc}); + } + } + + // Lower hal.interface.load.constant ops into llvm.getelementptr, llvm.load + for (auto loadOp : loadOps) { + Value offset = builder.create<LLVM::ConstantOp>( + loc, LLVM::LLVMType::getInt64Ty(typeConverter.getDialect()), + builder.getI64IntegerAttr(loadOp.offset().getZExtValue())); + Value constPtr = builder.create<LLVM::GEPOp>(loc, pushConstantArgTy, + newFuncOp.getArgument(1), + ArrayRef<Value>({offset})); + Value dimConstant = builder.create<LLVM::LoadOp>(loc, constPtr); + rewriter.replaceOp(loadOp, dimConstant); + } + + rewriter.eraseOp(funcOp); + return success(); + } +}; + +class RemoveInterfaceOpPattern : public ConvertToLLVMPattern { + public: + explicit RemoveInterfaceOpPattern(MLIRContext *context, + LLVMTypeConverter &typeconverter) + : ConvertToLLVMPattern(IREE::HAL::InterfaceOp::getOperationName(), + context, typeconverter) {} + LogicalResult matchAndRewrite( + Operation *op, ArrayRef<Value> operands, + ConversionPatternRewriter &rewriter) const override { + rewriter.eraseOp(op); + return success(); + } +}; + namespace { struct ConvertToLLVMPass : public PassWrapper<ConvertToLLVMPass, OperationPass<ModuleOp>> { @@ -145,11 +319,12 @@ populateVectorToLLVMConversionPatterns(converter, patterns); populateLinalgToLLVMConversionPatterns(converter, patterns, &getContext()); // The following patterns resolves dynamic shapes by substituting tie_shape - // ops with an updated memref descriptors and replacing RankDimOp with actual - // index loaded from memref<?xi32> that holds all dynamic shapes - // push constants. - patterns.insert<ConvertRankedDimPattern, ConvertTieShapePattern, - RemoveMakeRankedShape>(&getContext(), converter); + // ops with an updated memref descriptors and replacing RankDimOp with + // actual index loaded from memref<?xi32> that holds all dynamic shapes push + // constants. + patterns.insert<ConvertFuncWithHALInterface, ConvertRankedDimPattern, + ConvertTieShapePattern, RemoveMakeRankedShape, + RemoveInterfaceOpPattern>(&getContext(), converter); LLVMConversionTarget target(getContext()); target.addLegalOp<ModuleOp, ModuleTerminatorOp>(); if (failed(applyPartialConversion(module, target, patterns))) @@ -162,7 +337,8 @@ static PassRegistration<ConvertToLLVMPass> pass( "iree-codegen-convert-to-llvm", - "Perform final conversion from Linalg/HAL/Shape/Vector/Standard to LLVMIR " + "Perform final conversion from Linalg/HAL/Shape/Vector/Standard to " + "LLVMIR " "dialect", [] { return std::make_unique<ConvertToLLVMPass>(); });
diff --git a/iree/compiler/Conversion/LinalgToLLVM/HALInterfaceToMemrefArguments.cpp b/iree/compiler/Conversion/LinalgToLLVM/HALInterfaceToMemrefArguments.cpp deleted file mode 100644 index ac968e4..0000000 --- a/iree/compiler/Conversion/LinalgToLLVM/HALInterfaceToMemrefArguments.cpp +++ /dev/null
@@ -1,231 +0,0 @@ -// Copyright 2020 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 <memory> - -#include "iree/compiler/Dialect/HAL/IR/HALDialect.h" -#include "iree/compiler/Dialect/HAL/IR/HALOps.h" -#include "iree/compiler/Dialect/IREE/IR/IREEOps.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" -#include "mlir/IR/Builders.h" -#include "mlir/Pass/Pass.h" -#include "mlir/Pass/PassRegistry.h" -#include "mlir/Transforms/DialectConversion.h" - -namespace mlir { -namespace iree_compiler { -namespace { - -/// Returns true if the given function contains interface related operations -/// that are used by other ops. -bool containsUsedInterfaceOp(FuncOp funcOp) { - for (Block& block : funcOp.getBlocks()) { - for (Operation& op : block) { - if (!op.getUses().empty() && - (isa<IREE::PlaceholderOp>(op) || - isa<IREE::HAL::InterfaceLoadConstantOp>(op))) { - return true; - } - } - } - return false; -} - -/// Returns true if `aOp` has a desciptor (set, binding) pair smaller than -/// `bOp`. Note that this ignores the offset. -bool operator<(IREE::HAL::InterfaceBindingOp aOp, - IREE::HAL::InterfaceBindingOp bOp) { - if (aOp.set().getZExtValue() == bOp.set().getZExtValue()) - return aOp.binding().getZExtValue() < bOp.binding().getZExtValue(); - return aOp.set().getZExtValue() < bOp.set().getZExtValue(); -} - -/// A pattern to process function interface. It replaces interface related ops -/// with function arguments to match LLVM's CodeGen's ABI contract. -/// -/// IREE scheduler passes interface ABI information via hal.interface.* ops to -/// all backends. We create iree.placeholder ops to represent buffers behind -/// those hal.interface.* ops. However the LLVM CodeGen uses function parameters -/// and memref descriptors for ABI. So we need to bridge the gap somewhere. -/// -/// This pass finds all interface buffers used in the function, sort them -/// according to the descriptor (set, binding) pair, and put unique ones as -/// function parameters in order. -/// Note: This should be kept consistent with LLVM's HAL backend. -struct ProcessFuncInterfacePattern : public OpConversionPattern<FuncOp> { - using OpConversionPattern::OpConversionPattern; - LogicalResult matchAndRewrite( - FuncOp funcOp, ArrayRef<Value> Operands, - ConversionPatternRewriter& rewriter) const override { - // Only process entry functions. - if (SymbolTable::getSymbolVisibility(funcOp) != - SymbolTable::Visibility::Public) - return failure(); - - FunctionType fnType = funcOp.getType(); - if (fnType.getNumInputs() != 0) - return rewriter.notifyMatchFailure( - funcOp, "entry function should not have inputs"); - - // Get interface buffers from all the blocks. - SmallVector<IREE::PlaceholderOp, 8> bufferOps; - SmallVector<IREE::HAL::InterfaceLoadConstantOp, 8> loadOps; - for (Block& block : funcOp.getBlocks()) { - for (Operation& op : block) { - if (auto phOp = dyn_cast<IREE::PlaceholderOp>(op)) - bufferOps.push_back(phOp); - if (auto phOp = dyn_cast<IREE::HAL::InterfaceLoadConstantOp>(op)) { - loadOps.push_back(phOp); - } - } - } - - if (bufferOps.empty()) return failure(); - - // A map from buffer ops to their corresponding interface binding ops. - llvm::DenseMap<Operation*, IREE::HAL::InterfaceBindingOp> bufferBindingMap; - for (auto bufferOp : bufferOps) { - auto symbol = SymbolTable::lookupNearestSymbolFrom( - bufferOp, bufferOp.getAttrOfType<SymbolRefAttr>("binding")); - bufferBindingMap[bufferOp] = cast<IREE::HAL::InterfaceBindingOp>(symbol); - } - - // Sort buffers according to their descriptor (set, binding) pair. - llvm::sort(bufferOps, [&bufferBindingMap](IREE::PlaceholderOp aBuffer, - IREE::PlaceholderOp bBuffer) { - return bufferBindingMap[aBuffer] < bufferBindingMap[bBuffer]; - }); - - // Create a function argument for each of the unique binding pointed by the - // buffer ops. - TypeConverter::SignatureConversion signatureConverter(/*numOrigInputs=*/0); - // A map from buffer ops to their corresponding function argument indices. - llvm::DenseMap<Operation*, unsigned> bufferArgMap; - // A map from binding ops to their corresponding function argument indices. - llvm::DenseMap<Operation*, unsigned> bindingArgMap; - unsigned argIndex = 0; - for (auto bufferOp : bufferOps) { - auto binding = bufferBindingMap[bufferOp]; - auto it = bindingArgMap.find(binding); - if (it != bindingArgMap.end()) { - bufferArgMap[bufferOp] = it->second; - } else { - bindingArgMap[binding] = argIndex; - bufferArgMap[bufferOp] = argIndex; - signatureConverter.addInputs(bufferOp.getType()); - ++argIndex; - } - } - Type dynamicDimsBufferType = - MemRefType::get(ShapedType::kDynamicSize, rewriter.getIntegerType(32)); - signatureConverter.addInputs(dynamicDimsBufferType); - - // Create the new function's signature. - Location loc = funcOp.getLoc(); - auto newFuncOp = rewriter.create<FuncOp>( - loc, funcOp.getName(), - rewriter.getFunctionType(signatureConverter.getConvertedTypes(), - llvm::None), - ArrayRef<NamedAttribute>()); - newFuncOp.setAttr("llvm.emit_c_interface", - mlir::UnitAttr::get(funcOp.getContext())); - - // Move all ops in the old function's region to the new function. - rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(), - newFuncOp.end()); - rewriter.applySignatureConversion(&newFuncOp.getBody(), signatureConverter); - - // Replace all buffer ops' uses with the newly created function arguments - // and erase them. - for (auto bufferOp : bufferOps) { - bufferOp.replaceAllUsesWith( - newFuncOp.getArgument(bufferArgMap[bufferOp])); - - rewriter.eraseOp(bufferOp); - } - - // Lower all hal.interface.load.constant ops into std.load - // from the last buffer holding all dynamic dimensions with the proper - // offset. - Type indexType = rewriter.getIndexType(); - auto builder = OpBuilder::atBlockBegin(&(newFuncOp.getBlocks().front())); - auto newLoc = newFuncOp.front().front().getLoc(); - for (auto loadOp : loadOps) { - SmallVector<Value, 1> indices; - Value constantOffset = builder.create<ConstantOp>( - newLoc, indexType, - rewriter.getIntegerAttr(indexType, loadOp.offset().getZExtValue())); - indices.push_back(constantOffset); - Value loadDim = builder.create<LoadOp>( - newLoc, newFuncOp.getArgument(newFuncOp.getNumArguments() - 1), - indices); - Value loadDimIndex = - builder.create<IndexCastOp>(newLoc, loadDim, indexType); - loadOp.replaceAllUsesWith(loadDimIndex); - rewriter.eraseOp(loadOp); - } - rewriter.eraseOp(funcOp); - return success(); - } -}; - -struct RemoveInterfaceOpPattern - : public OpRewritePattern<IREE::HAL::InterfaceOp> { - using OpRewritePattern::OpRewritePattern; - LogicalResult matchAndRewrite(IREE::HAL::InterfaceOp interfaceOp, - PatternRewriter& rewriter) const override { - rewriter.eraseOp(interfaceOp); - return success(); - } -}; - -/// Converting from Linalg to LLVM needs to run on a module and since it -/// applies a full conversion, make a module with jst the impl function. -struct HALInterfaceToMemrefArgumentsPass - : PassWrapper<HALInterfaceToMemrefArgumentsPass, OperationPass<ModuleOp>> { - void runOnOperation() override { - MLIRContext& context = getContext(); - - OwningRewritePatternList patterns; - patterns.insert<ProcessFuncInterfacePattern>(&context); - patterns.insert<RemoveInterfaceOpPattern>(&context); - - ConversionTarget target(context); - // Convert the interface related ops away. - target.addDynamicallyLegalOp<FuncOp>( - [](FuncOp funcOp) { return !containsUsedInterfaceOp(funcOp); }); - target.addIllegalOp<IREE::PlaceholderOp>(); - target.addIllegalDialect<IREE::HAL::HALDialect>(); - // Allow the rest. - target.markUnknownOpDynamicallyLegal([](Operation*) { return true; }); - - if (failed(applyFullConversion(getOperation(), target, patterns))) - return signalPassFailure(); - } -}; - -} // namespace - -std::unique_ptr<OperationPass<ModuleOp>> -createHALInterfaceToMemrefArgumentsPass() { - return std::make_unique<HALInterfaceToMemrefArgumentsPass>(); -} - -static PassRegistration<HALInterfaceToMemrefArgumentsPass> pass( - "iree-codegen-hal-interface-to-memref-arguments-pass", - "Convert a function with HAL bindings interface to memref arguments", - [] { return std::make_unique<HALInterfaceToMemrefArgumentsPass>(); }); - -} // namespace iree_compiler -} // namespace mlir
diff --git a/iree/compiler/Conversion/LinalgToLLVM/Passes.cpp b/iree/compiler/Conversion/LinalgToLLVM/Passes.cpp index e8c6d9c..8c8eb21 100644 --- a/iree/compiler/Conversion/LinalgToLLVM/Passes.cpp +++ b/iree/compiler/Conversion/LinalgToLLVM/Passes.cpp
@@ -35,10 +35,7 @@ passManager.addPass(createCanonicalizerPass()); passManager.addPass(createCSEPass()); - // Convert ExecuableOp entry function to use memref arguments. - passManager.addPass(createHALInterfaceToMemrefArgumentsPass()); - - // (Linalg, STD) -> LLVM + // (HAL, IREE, Linalg, STD) -> LLVM // OpPassManager& llvmPassManager = passManager.nest<ModuleOp>(); passManager.addPass(createConvertToLLVMPass()); passManager.addPass(createCanonicalizerPass());
diff --git a/iree/compiler/Conversion/LinalgToLLVM/Passes.h b/iree/compiler/Conversion/LinalgToLLVM/Passes.h index 5bfb893..fdad0e6 100644 --- a/iree/compiler/Conversion/LinalgToLLVM/Passes.h +++ b/iree/compiler/Conversion/LinalgToLLVM/Passes.h
@@ -20,11 +20,6 @@ namespace mlir { namespace iree_compiler { -/// Converts function signture type from hal interface op annotation to memref -/// argument. -std::unique_ptr<OperationPass<ModuleOp>> -createHALInterfaceToMemrefArgumentsPass(); - /// Pass to perform final conversion to LLVM dialect. std::unique_ptr<OperationPass<ModuleOp>> createConvertToLLVMPass();
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/ConvertToGPUPass.cpp b/iree/compiler/Conversion/LinalgToSPIRV/ConvertToGPUPass.cpp index c0d5135..81514ec 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/ConvertToGPUPass.cpp +++ b/iree/compiler/Conversion/LinalgToSPIRV/ConvertToGPUPass.cpp
@@ -17,6 +17,9 @@ // Partition computation within dispatch function to workgroups/workitems. // //===----------------------------------------------------------------------===// + +#include <array> + #include "iree/compiler/Conversion/LinalgToSPIRV/Attributes.h" #include "iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.h" #include "iree/compiler/Conversion/LinalgToSPIRV/Passes.h" @@ -425,7 +428,7 @@ unsigned numDims, MutableArrayRef<Value> id, MutableArrayRef<Value> count) { - ArrayRef<StringRef> dims = {"x", "y", "z"}; + std::array<StringRef, 3> dims{"x", "y", "z"}; assert(id.size() == numDims); assert(count.size() == numDims); for (unsigned i = 0; i < numDims; ++i) { @@ -560,7 +563,7 @@ ConversionPatternRewriter &rewriter) const override { // Check for marker that specifies that the linalg op is to be partitioned // across threads within a workgroup. - if (!hasWorkItemMarker(linalgOp)) return failure(); + if (!hasWorkGroupMarker(linalgOp)) return failure(); Optional<linalg::LinalgLoops> loops = linalg::linalgLowerOpToLoops<scf::ParallelOp>(rewriter, linalgOp); if (!loops) return failure(); @@ -584,7 +587,7 @@ LogicalResult matchAndRewrite( LinalgOpTy linalgOp, ArrayRef<Value> operands, ConversionPatternRewriter &rewriter) const override { - if (!hasWorkItemMarker(linalgOp)) return failure(); + if (!hasWorkGroupMarker(linalgOp)) return failure(); Optional<linalg::LinalgLoops> loops = linalg::linalgLowerOpToLoops<scf::ParallelOp>(rewriter, linalgOp); if (!loops) return failure();
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/LinalgTileAndFusePass.cpp b/iree/compiler/Conversion/LinalgToSPIRV/LinalgTileAndFusePass.cpp index e9dddd6..934e5ae 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/LinalgTileAndFusePass.cpp +++ b/iree/compiler/Conversion/LinalgToSPIRV/LinalgTileAndFusePass.cpp
@@ -314,7 +314,7 @@ LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const override { - if (!hasWorkItemMarker(op)) return failure(); + if (!hasWorkGroupMarker(op)) return failure(); return linalg::LinalgPromotionPattern<linalg::MatmulOp>::matchAndRewrite( op, rewriter); } @@ -365,7 +365,7 @@ .setLoopType(linalg::LinalgTilingLoopType::ParallelLoops), tileSizeCalculator.getWorkGroupSize(), linalg::LinalgMarker(ArrayRef<Identifier>(), - Identifier::get(getWorkItemMarker(), context))); + Identifier::get(getWorkGroupMarker(), context))); applyPatternsAndFoldGreedily(getOperation(), tilingPatterns); if (useWorkgroupMemory) { @@ -385,7 +385,7 @@ [&](OpBuilder &b, Value src, Value dst) -> LogicalResult { return copyToFromWorkgroupMemory(b, src, dst); }), - linalg::LinalgMarker(Identifier::get(getWorkItemMarker(), context), + linalg::LinalgMarker(Identifier::get(getWorkGroupMarker(), context), Identifier::get(PromotionMarker, context))); applyPatternsAndFoldGreedily(getOperation(), promotionPatterns); } @@ -394,7 +394,7 @@ OpBuilder builder(context); funcOp.walk([&builder](linalg::LinalgOp linalgOp) { if (hasMarker(linalgOp, PromotionMarker)) { - setWorkItemMarker(linalgOp); + setWorkGroupMarker(linalgOp); insertBarrierAfter(builder, linalgOp.getLoc(), linalgOp); } });
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.cpp b/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.cpp index c874234..47747de 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.cpp +++ b/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.cpp
@@ -36,8 +36,6 @@ StringRef getWorkGroupMarker() { return "workgroup"; } -StringRef getWorkItemMarker() { return "workitem"; } - bool hasMarker(Operation *op, StringRef marker) { return checkMarkerValue(op, marker); } @@ -46,10 +44,6 @@ return checkMarkerValue(op, getWorkGroupMarker()); } -bool hasWorkItemMarker(Operation *op) { - return checkMarkerValue(op, getWorkItemMarker()); -} - void setMarker(Operation *op, StringRef marker) { op->setAttr(linalg::LinalgTransforms::kLinalgTransformMarker, StringAttr::get(marker, op->getContext())); @@ -57,6 +51,5 @@ void setWorkGroupMarker(Operation *op) { setMarker(op, getWorkGroupMarker()); } -void setWorkItemMarker(Operation *op) { setMarker(op, getWorkItemMarker()); } } // namespace iree_compiler } // namespace mlir
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.h b/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.h index 36dccca..e512ead 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.h +++ b/iree/compiler/Conversion/LinalgToSPIRV/MarkerUtils.h
@@ -31,7 +31,7 @@ namespace iree_compiler { /// Marker to denote that a linalg operation is to be partitioned to workitems. -StringRef getWorkItemMarker(); +StringRef getWorkGroupMarker(); /// Returns true if an operation has the specified `marker`. When `marker` is /// empty, returns true if the operation has any marker. @@ -39,14 +39,14 @@ /// Returns true if an operation has marker to denote that it is to be /// partitioned to workitems. -bool hasWorkItemMarker(Operation *); +bool hasWorkGroupMarker(Operation *); /// Sets a given marker on an operation. void setMarker(Operation *, StringRef); /// Sets marker to denote that a linalg operation is to be partitioned to /// workitems. -void setWorkItemMarker(Operation *); +void setWorkGroupMarker(Operation *); } // namespace iree_compiler } // namespace mlir
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu.mlir b/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu.mlir index 679f523..64621f3 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu.mlir +++ b/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu.mlir
@@ -162,7 +162,7 @@ %12 = dim %arg2, %c1 : memref<?x?xf32> %13 = affine.min #map0(%arg4)[%12] %14 = subview %arg2[%arg3, %arg4] [%11, %13] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #map2> - linalg.matmul %5, %9, %14 {__internal_linalg_transform__ = "workitem"} : (memref<?x?xf32, #map2>, memref<?x?xf32, #map2>, memref<?x?xf32, #map2>) + linalg.matmul %5, %9, %14 {__internal_linalg_transform__ = "workgroup"} : (memref<?x?xf32, #map2>, memref<?x?xf32, #map2>, memref<?x?xf32, #map2>) } scf.yield } @@ -235,7 +235,7 @@ %13 = affine.min #map5(%arg5)[%4] %14 = dim %arg2, %c3 : memref<?x?x?x?xf32> %15 = subview %arg2[%arg3, %arg4, %arg5, 0] [%11, %12, %13, %14] [1, 1, 1, 1] : memref<?x?x?x?xf32> to memref<?x?x?x?xf32, #map3> - linalg.conv(%arg0, %9, %15) {__internal_linalg_transform__ = "workitem", dilations = [1, 1], strides = [1, 1]} : memref<?x?x?x?xf32>, memref<?x?x?x?xf32, #map3>, memref<?x?x?x?xf32, #map3> + linalg.conv(%arg0, %9, %15) {__internal_linalg_transform__ = "workgroup", dilations = [1, 1], strides = [1, 1]} : memref<?x?x?x?xf32>, memref<?x?x?x?xf32, #map3>, memref<?x?x?x?xf32, #map3> scf.yield } return @@ -364,7 +364,7 @@ %9 = affine.min #map3(%arg3)[%2] %10 = affine.min #map4(%arg4)[%3] %11 = subview %arg2[%arg3, %arg4] [%9, %10] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #map2> - linalg.pooling_max(%8, %arg1, %11) {__internal_linalg_transform__ = "workitem", dilations = [1, 1], strides = [1, 1]} : memref<?x?xf32, #map2>, memref<?x?xf32>, memref<?x?xf32, #map2> + linalg.pooling_max(%8, %arg1, %11) {__internal_linalg_transform__ = "workgroup", dilations = [1, 1], strides = [1, 1]} : memref<?x?xf32, #map2>, memref<?x?xf32>, memref<?x?xf32, #map2> scf.yield } return
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu_option.mlir b/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu_option.mlir index 1701535..63f8aa5 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu_option.mlir +++ b/iree/compiler/Conversion/LinalgToSPIRV/test/convert_to_gpu_option.mlir
@@ -32,7 +32,7 @@ %13 = affine.min #map5(%arg5)[%4] %14 = dim %arg2, %c3 : memref<?x?x?x?xf32> %15 = subview %arg2[%arg3, %arg4, %arg5, 0] [%11, %12, %13, %14] [1, 1, 1, 1] : memref<?x?x?x?xf32> to memref<?x?x?x?xf32, #map3> - linalg.conv(%arg0, %9, %15) {__internal_linalg_transform__ = "workitem", dilations = [1, 1], strides = [1, 1]} : memref<?x?x?x?xf32>, memref<?x?x?x?xf32, #map3>, memref<?x?x?x?xf32, #map3> + linalg.conv(%arg0, %9, %15) {__internal_linalg_transform__ = "workgroup", dilations = [1, 1], strides = [1, 1]} : memref<?x?x?x?xf32>, memref<?x?x?x?xf32, #map3>, memref<?x?x?x?xf32, #map3> scf.yield } return
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/test/cyclic_to_workgroup.mlir b/iree/compiler/Conversion/LinalgToSPIRV/test/cyclic_to_workgroup.mlir index 110ac24..cac18ab 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/test/cyclic_to_workgroup.mlir +++ b/iree/compiler/Conversion/LinalgToSPIRV/test/cyclic_to_workgroup.mlir
@@ -27,7 +27,7 @@ %12 = dim %arg2, %c1 : memref<?x?xf32> %13 = affine.min #map0(%arg4)[%12] %14 = subview %arg2[%arg3, %arg4] [%11, %13] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #map2> - linalg.matmul %5, %9, %14 {__internal_linalg_transform__ = "workitem"} : (memref<?x?xf32, #map2>, memref<?x?xf32, #map2>, memref<?x?xf32, #map2>) + linalg.matmul %5, %9, %14 {__internal_linalg_transform__ = "workgroup"} : (memref<?x?xf32, #map2>, memref<?x?xf32, #map2>, memref<?x?xf32, #map2>) } scf.yield }
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/test/linalg_tile_and_fuse.mlir b/iree/compiler/Conversion/LinalgToSPIRV/test/linalg_tile_and_fuse.mlir index 0e2fe6d..1728d35 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/test/linalg_tile_and_fuse.mlir +++ b/iree/compiler/Conversion/LinalgToSPIRV/test/linalg_tile_and_fuse.mlir
@@ -51,7 +51,7 @@ // CHECK: %[[VIEW2:.+]] = subview %[[ARG2]] // CHECK: linalg.conv // CHECK-SAME: %[[ARG0]], %[[VIEW1]], %[[VIEW2]] -// CHECK-SAME: "workitem" +// CHECK-SAME: "workgroup" // ----- @@ -81,7 +81,7 @@ // CHECK: %[[VIEW1:.+]] = subview %[[ARG1]] // CHECK: %[[VIEW2:.+]] = subview %[[ARG2]] // CHECK: linalg.matmul -// CHECK-SAME: "workitem" +// CHECK-SAME: "workgroup" // CHECK-SAME: %[[VIEW0]], %[[VIEW1]], %[[VIEW2]] // ----- @@ -111,4 +111,4 @@ // CHECK: %[[VIEW2:.+]] = subview %[[ARG2]] // CHECK: linalg.pooling_max // CHECK-SAME: %[[VIEW0]], %[[ARG1]], %[[VIEW2]] -// CHECK-SAME: "workitem" +// CHECK-SAME: "workgroup"
diff --git a/iree/compiler/Conversion/LinalgToSPIRV/test/workgroup_memory_promotion.mlir b/iree/compiler/Conversion/LinalgToSPIRV/test/workgroup_memory_promotion.mlir index 76cfcb8..a24c77b 100644 --- a/iree/compiler/Conversion/LinalgToSPIRV/test/workgroup_memory_promotion.mlir +++ b/iree/compiler/Conversion/LinalgToSPIRV/test/workgroup_memory_promotion.mlir
@@ -36,12 +36,12 @@ // CHECK: %[[ALLOC2:.+]] = alloc(%[[C4]], %[[C8]]) : memref<?x?xf32, 3> // CHECK: %[[SUBVIEW2:.+]] = subview %[[ALLOC2]] // CHECK: linalg.copy(%[[ARG0SV]], %[[SUBVIEW1]]) -// CHECK-SAME: "workitem" +// CHECK-SAME: "workgroup" // CHECK: spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" // CHECK: linalg.copy(%[[ARG1SV]], %[[SUBVIEW2]]) -// CHECK-SAME: "workitem" +// CHECK-SAME: "workgroup" // CHECK: spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" -// CHECK: linalg.matmul {{.*}}"workitem"{{.*}} %[[SUBVIEW1]], %[[SUBVIEW2]], %[[RET0SV]] +// CHECK: linalg.matmul {{.*}}"workgroup"{{.*}} %[[SUBVIEW1]], %[[SUBVIEW2]], %[[RET0SV]] // CHECK: spv.ControlBarrier "Workgroup", "Workgroup", "AcquireRelease" // CHECK-DAG: dealloc %[[ALLOC1]] : memref<?x?xf32, 3> // CHECK-DAG: dealloc %[[ALLOC2]] : memref<?x?xf32, 3>
diff --git a/iree/compiler/Conversion/init_conversions.h b/iree/compiler/Conversion/init_conversions.h index 7a190e7..259e3d5 100644 --- a/iree/compiler/Conversion/init_conversions.h +++ b/iree/compiler/Conversion/init_conversions.h
@@ -47,7 +47,6 @@ inline void registerLinalgToLLVMPasses() { static bool init_once = []() { // LinalgToLLVM - createHALInterfaceToMemrefArgumentsPass(); return true; }(); (void)init_once;
diff --git a/iree/compiler/Dialect/Flow/IR/FlowOps.td b/iree/compiler/Dialect/Flow/IR/FlowOps.td index 23bce9c..13ad2f1 100644 --- a/iree/compiler/Dialect/Flow/IR/FlowOps.td +++ b/iree/compiler/Dialect/Flow/IR/FlowOps.td
@@ -610,6 +610,17 @@ let hasFolder = 1; } +def FLOW_TensorTraceOp : FLOW_Op<"tensor.trace", []> { + let summary = [{trace value(s) operation}]; + let description = [{ + Trace point for dispatchable functions. + }]; + + let arguments = (ins Variadic<FLOW_Tensor>:$operands); + + let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; +} + //===----------------------------------------------------------------------===// // Streams //===----------------------------------------------------------------------===//
diff --git a/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp b/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp index 44a19d1..3281c6c 100644 --- a/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp +++ b/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp
@@ -25,6 +25,7 @@ #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Diagnostics.h" +#include "mlir/IR/StandardTypes.h" #include "mlir/IR/SymbolTable.h" #include "mlir/Pass/Pass.h" @@ -40,6 +41,11 @@ namespace { +static llvm::cl::opt<bool> traceDispatchTensors( + "iree-flow-trace-dispatch-tensors", + llvm::cl::desc("Trace input/output values for each dispatch function"), + llvm::cl::init(false)); + // Converts a dispatch_region into a dispatch to the outlined region function. LogicalResult convertToDispatchOp(DispatchRegionOp regionOp, ExecutableOp executableOp, @@ -57,11 +63,28 @@ return failure(); } + auto getTensorTypeArgs = [](auto args) { + SmallVector<Value, 4> res; + for (auto arg : args) { + if (arg.getType().template isa<TensorType>()) res.push_back(arg); + } + return res; + }; + if (traceDispatchTensors) { + builder.create<TensorTraceOp>(regionOp.getLoc(), + getTensorTypeArgs(newArgs)); + } + // Create the dispatch op to the executable function. auto dispatchOp = builder.create<DispatchOp>( regionOp.getLoc(), executableOp.getName(), entryPointOp.getName(), regionOp.workload(), outlinedFuncOp.getType().getResults(), newArgs); + if (traceDispatchTensors) { + builder.create<TensorTraceOp>(regionOp.getLoc(), + getTensorTypeArgs(dispatchOp.getResults())); + } + // Replace uses of the existing results with the new results. for (int i = 0; i < regionOp.getNumResults(); ++i) { regionOp.getResult(i).replaceAllUsesWith(dispatchOp.getResult(i));
diff --git a/iree/compiler/Dialect/HAL/Conversion/FlowToHAL/ConvertTensorOps.cpp b/iree/compiler/Dialect/HAL/Conversion/FlowToHAL/ConvertTensorOps.cpp index 2947b70..6fcadbd 100644 --- a/iree/compiler/Dialect/HAL/Conversion/FlowToHAL/ConvertTensorOps.cpp +++ b/iree/compiler/Dialect/HAL/Conversion/FlowToHAL/ConvertTensorOps.cpp
@@ -19,6 +19,7 @@ #include "iree/compiler/Dialect/HAL/Utils/TypeUtils.h" #include "iree/compiler/Dialect/IREE/IR/IREETypes.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BlockAndValueMapping.h" @@ -120,13 +121,36 @@ } }; +class TensorTraceOpConversion + : public OpConversionPattern<IREE::Flow::TensorTraceOp> { + public: + TensorTraceOpConversion(MLIRContext *ctx, TypeConverter &converter) + : OpConversionPattern(ctx) {} + + LogicalResult matchAndRewrite( + IREE::Flow::TensorTraceOp traceOp, llvm::ArrayRef<Value> rawOperands, + ConversionPatternRewriter &rewriter) const override { + Location loc = traceOp.getLoc(); + SmallVector<Value, 4> bufferViews; + for (auto operand : llvm::enumerate(rawOperands)) { + auto adaptor = IREE::HAL::TensorRewriteAdaptor::get( + loc, traceOp.getOperand(operand.index()), operand.value(), rewriter); + bufferViews.emplace_back(adaptor.getBufferView()); + } + rewriter.replaceOpWithNewOp<IREE::HAL::BufferViewTraceOp>(traceOp, + bufferViews); + return success(); + } +}; + } // namespace void populateFlowTensorToHALPatterns(MLIRContext *context, OwningRewritePatternList &patterns, TypeConverter &converter) { patterns.insert<ConstantTensorOpConversion, TensorLoadOpConversion, - TensorStoreOpConversion>(context, converter); + TensorStoreOpConversion, TensorTraceOpConversion>(context, + converter); } } // namespace iree_compiler
diff --git a/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferViewOps.cpp b/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferViewOps.cpp index 7212549..5abbfa4 100644 --- a/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferViewOps.cpp +++ b/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferViewOps.cpp
@@ -118,6 +118,8 @@ context, importSymbols, typeConverter, "hal.buffer_view.dim"); patterns.insert<BufferViewDimsOpConversion>( context, importSymbols, typeConverter, "hal.buffer_view.dims"); + patterns.insert<VMImportOpConversion<IREE::HAL::BufferViewTraceOp>>( + context, importSymbols, typeConverter, "hal.buffer_view.trace"); } } // namespace iree_compiler
diff --git a/iree/compiler/Dialect/HAL/IR/HALOps.td b/iree/compiler/Dialect/HAL/IR/HALOps.td index 0139ddb..9593647 100644 --- a/iree/compiler/Dialect/HAL/IR/HALOps.td +++ b/iree/compiler/Dialect/HAL/IR/HALOps.td
@@ -927,6 +927,17 @@ let assemblyFormat = [{$buffer_view attr-dict `:` type($result)}]; } +def HAL_BufferViewTraceOp : HAL_Op<"buffer_view.trace", []> { + let summary = [{trace value(s) operation}]; + let description = [{ + Trace point for dispatchable functions. + }]; + + let arguments = (ins Variadic<HAL_BufferView>:$operands); + + let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?"; +} + //===----------------------------------------------------------------------===// // iree::hal::CommandBuffer //===----------------------------------------------------------------------===//
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD index 2e322af..0f6be4a 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD +++ b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD
@@ -105,9 +105,7 @@ cc_library( name = "LLVMAOTTargetLinker", hdrs = ["LLVMAOTTargetLinker.h"], - deps = [ - "//iree/base:file_io", - ] + platform_trampoline_deps("LLVMAOTTargetLinker", "compiler/Dialect/HAL/Target/LLVM"), + deps = platform_trampoline_deps("LLVMAOTTargetLinker", "compiler/Dialect/HAL/Target/LLVM"), ) cc_library( @@ -115,6 +113,6 @@ hdrs = ["LLVMAOTTargetLinker.h"], deps = [ ":LLVMTargetOptions", - "//iree/base:file_io", + "//iree/base:status", ], )
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt index 4aa0ad3..0ee00e4 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt +++ b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
@@ -97,7 +97,6 @@ HDRS "LLVMAOTTargetLinker.h" DEPS - iree::base::file_io iree::compiler::Dialect::HAL::Target::LLVM::internal::LLVMAOTTargetLinker_internal PUBLIC ) @@ -109,6 +108,6 @@ "LLVMAOTTargetLinker.h" DEPS ::LLVMTargetOptions - iree::base::file_io + iree::base::status PUBLIC )
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp index 7269089..8cb47b5 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp
@@ -65,13 +65,10 @@ auto executableOp = cast<ExecutableOp>(targetOp.getParentOp()); auto entryPointOps = executableOp.getBlock().getOps<ExecutableEntryPointOp>(); - const bool addCInterface = true; + for (auto entryPointOp : entryPointOps) { - std::string funcName = - addCInterface ? "_mlir_ciface_" + std::string(entryPointOp.sym_name()) - : std::string(entryPointOp.sym_name()); - dyLibExecutableDef.entry_points.push_back("invoke_" + funcName); - createLLVMInvocationFunc(funcName, llvmModule.get()); + dyLibExecutableDef.entry_points.push_back( + std::string(entryPointOp.sym_name())); } // LLVMIR opt passes.
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h index 764ad02..669f17c 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h
@@ -18,7 +18,7 @@ #include <string> -#include "iree/base/file_io.h" +#include "iree/base/status.h" #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h" namespace mlir {
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp index cb2a526..e91441d 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp
@@ -44,44 +44,6 @@ return machine; } -void createLLVMInvocationFunc(const std::string& name, llvm::Module* module) { - // TODO(ataei): This is written as a stub in LLVM IR. It would be easier to - // have this using MLIR and lower it to LLVM like the dispatch function - // implementation is. - - auto& ctx = module->getContext(); - llvm::IRBuilder<> builder(ctx); - auto var_func = module->getFunction(name); - - auto new_type = llvm::FunctionType::get( - builder.getVoidTy(), builder.getInt8PtrTy()->getPointerTo(), - /*isVarArg=*/false); - - auto new_name = "invoke_" + name; - auto func_cst = module->getOrInsertFunction(new_name, new_type); - llvm::Function* interface_func = - llvm::cast<llvm::Function>(func_cst.getCallee()); - - auto bb = llvm::BasicBlock::Create(ctx); - bb->insertInto(interface_func); - builder.SetInsertPoint(bb); - llvm::Value* argList = interface_func->arg_begin(); - llvm::SmallVector<llvm::Value*, 8> args; - args.reserve(llvm::size(var_func->args())); - for (auto& indexedArg : llvm::enumerate(var_func->args())) { - llvm::Value* arg_index = llvm::Constant::getIntegerValue( - builder.getInt64Ty(), llvm::APInt(64, indexedArg.index())); - llvm::Value* arg_ptr_ptr = builder.CreateGEP(argList, arg_index); - llvm::Value* arg_ptr = builder.CreateLoad(arg_ptr_ptr); - arg_ptr = builder.CreateBitCast( - arg_ptr, indexedArg.value().getType()->getPointerTo()); - llvm::Value* arg = builder.CreateLoad(arg_ptr); - args.push_back(arg); - } - builder.CreateCall(var_func, args); - builder.CreateRetVoid(); -} - LogicalResult runLLVMIRPasses(const LLVMTargetOptions& options, llvm::TargetMachine* machine, llvm::Module* module) { @@ -91,7 +53,8 @@ llvm::ModuleAnalysisManager moduleAnalysisManager; llvm::PassInstrumentationCallbacks passInstrumentationCallbacks; - llvm::StandardInstrumentations standardInstrumentations; + llvm::StandardInstrumentations standardInstrumentations( + /*DebugLogging=*/false); standardInstrumentations.registerCallbacks(passInstrumentationCallbacks); llvm::PassBuilder passBuilder(machine, options.pipelineTuningOptions, {},
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h index 199e36f..37ee1ba 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h
@@ -31,9 +31,6 @@ std::unique_ptr<llvm::TargetMachine> createTargetMachine( const LLVMTargetOptions& options); -// Creates an invocation function in a module for the given function name. -void createLLVMInvocationFunc(const std::string& name, llvm::Module* module); - // Creates and runs LLVMIR optimization passes defined in LLVMTargetOptions. LogicalResult runLLVMIRPasses(const LLVMTargetOptions& options, llvm::TargetMachine* machine,
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp index 98c0bf4..96bb5ac 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp
@@ -58,13 +58,9 @@ auto executableOp = cast<IREE::HAL::ExecutableOp>(targetOp.getParentOp()); auto entryPointOps = executableOp.getBlock().getOps<IREE::HAL::ExecutableEntryPointOp>(); - const bool addCInterface = true; for (auto entryPointOp : entryPointOps) { - std::string funcName = - addCInterface ? "_mlir_ciface_" + std::string(entryPointOp.sym_name()) - : std::string(entryPointOp.sym_name()); - llvmIrExecutableDef.entry_points.push_back(funcName); - createLLVMInvocationFunc(funcName, llvmModule.get()); + llvmIrExecutableDef.entry_points.push_back( + std::string(entryPointOp.sym_name())); } // LLVMIR opt passes. @@ -74,8 +70,9 @@ options_.targetTriple); return failure(); } - if (failed( - runLLVMIRPasses(options_, targetMachine.get(), llvmModule.get()))) { + LogicalResult translationResult = + runLLVMIRPasses(options_, targetMachine.get(), llvmModule.get()); + if (failed(translationResult)) { return targetOp.emitError( "Can't build LLVMIR opt passes for ExecutableOp module"); }
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD b/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD index c3ba845..19c3372 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD
@@ -24,5 +24,6 @@ deps = [ "//iree/base:status", "//iree/compiler/Dialect/HAL/Target/LLVM:LLVMAOTTargetLinker_hdrs", + "@llvm-project//llvm:Support", ], )
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt index 18c9c7a..b91dae5 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt
@@ -20,6 +20,7 @@ SRCS "LLVMAOTTargetLinker.cpp" DEPS + LLVMSupport iree::base::status iree::compiler::Dialect::HAL::Target::LLVM::LLVMAOTTargetLinker_hdrs PUBLIC
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp index e5108d6..65d8e22 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp
@@ -15,6 +15,7 @@ #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h" #include "iree/base/status.h" +#include "llvm/Support/ToolOutputFile.h" namespace mlir { namespace iree_compiler { @@ -23,18 +24,47 @@ iree::StatusOr<std::string> linkLLVMAOTObjects( const std::string& linkerToolPath, const std::string& objData) { - std::string archiveFile, sharedLibFile; - ASSIGN_OR_RETURN(archiveFile, iree::file_io::GetTempFile("objfile")); - RETURN_IF_ERROR(iree::file_io::SetFileContents(archiveFile, objData)); - ASSIGN_OR_RETURN(sharedLibFile, iree::file_io::GetTempFile("dylibfile")); - std::string linkingCmd = - linkerToolPath + " -shared " + archiveFile + " -o " + sharedLibFile; + llvm::SmallString<32> objFilePath, dylibFilePath; + if (std::error_code error = llvm::sys::fs::createTemporaryFile( + "llvmaot_dylibs", "objfile", objFilePath)) { + return iree::InternalErrorBuilder(IREE_LOC) + << "Failed to generate temporary file for objfile : '" + << error.message() << "'"; + } + if (std::error_code error = llvm::sys::fs::createTemporaryFile( + "llvmaot_dylibs", "dylibfile", dylibFilePath)) { + return iree::InternalErrorBuilder(IREE_LOC) + << "Failed to generate temporary file for dylib : '" + << error.message() << "'"; + } + std::error_code error; + auto outputFile = std::make_unique<llvm::ToolOutputFile>( + objFilePath, error, llvm::sys::fs::F_None); + if (error) { + return iree::InternalErrorBuilder(IREE_LOC) + << "Failed to open temporary objfile '" << objFilePath.c_str() + << "' for dylib : '" << error.message() << "'"; + } + + outputFile->os() << objData; + outputFile->os().flush(); + + auto linkingCmd = + (linkerToolPath + " -shared " + objFilePath + " -o " + dylibFilePath) + .str(); int systemRet = system(linkingCmd.c_str()); if (systemRet != 0) { return iree::InternalErrorBuilder(IREE_LOC) << linkingCmd << " failed with exit code " << systemRet; } - return iree::file_io::GetFileContents(sharedLibFile); + + auto dylibData = llvm::MemoryBuffer::getFile(dylibFilePath); + if (!dylibData) { + return iree::InternalErrorBuilder(IREE_LOC) + << "Failed to read temporary dylib file '" << dylibFilePath.c_str() + << "'"; + } + return dylibData.get()->getBuffer().str(); } iree::StatusOr<std::string> linkLLVMAOTObjectsWithLLDElf(
diff --git a/iree/compiler/Dialect/HAL/hal.imports.mlir b/iree/compiler/Dialect/HAL/hal.imports.mlir index 224bb7b..f3d8c62 100644 --- a/iree/compiler/Dialect/HAL/hal.imports.mlir +++ b/iree/compiler/Dialect/HAL/hal.imports.mlir
@@ -214,6 +214,11 @@ ) -> (i32, i32, i32, i32) attributes {nosideeffects} +// Prints out the content of buffers. +vm.import @buffer_view.trace( + %operands : !vm.ref<!hal.buffer_view> ... +) + //===----------------------------------------------------------------------===// // iree::hal::CommandBuffer //===----------------------------------------------------------------------===//
diff --git a/iree/compiler/Dialect/IREE/Transforms/test/drop_compiler_hints.mlir b/iree/compiler/Dialect/IREE/Transforms/test/drop_compiler_hints.mlir index 9486f96..39c18ce 100644 --- a/iree/compiler/Dialect/IREE/Transforms/test/drop_compiler_hints.mlir +++ b/iree/compiler/Dialect/IREE/Transforms/test/drop_compiler_hints.mlir
@@ -1,6 +1,6 @@ // RUN: iree-opt -split-input-file -iree-drop-compiler-hints %s | IreeFileCheck --implicit-check-not="iree.do_not_optimize" %s -// This file is used as an example in docs/developer_overview.md. +// This file is used as an example in docs/developing_iree/developer_overview.md. // If you move or delete it, please update the documentation accordingly. // CHECK-LABEL: @constant
diff --git a/iree/compiler/Dialect/Shape/IR/ShapeInterface.h b/iree/compiler/Dialect/Shape/IR/ShapeInterface.h index a200bfd..b36890e 100644 --- a/iree/compiler/Dialect/Shape/IR/ShapeInterface.h +++ b/iree/compiler/Dialect/Shape/IR/ShapeInterface.h
@@ -58,7 +58,10 @@ } template <typename BuilderTy, typename... ConstructorArgs> - BuilderTy &make(ConstructorArgs &&... args) { + // TODO(suderman): Re-enable clang-format when new version migrates. + // clang-format off + BuilderTy &make(ConstructorArgs &&...args) { + // clang-format on auto instance = std::make_unique<BuilderTy>(std::forward<ConstructorArgs>(args)...); BuilderTy *unowned = instance.get();
diff --git a/iree/compiler/Dialect/Shape/Plugins/XLA/XlaHloShapeBuilder.cpp b/iree/compiler/Dialect/Shape/Plugins/XLA/XlaHloShapeBuilder.cpp index 8d37751..9024e88 100644 --- a/iree/compiler/Dialect/Shape/Plugins/XLA/XlaHloShapeBuilder.cpp +++ b/iree/compiler/Dialect/Shape/Plugins/XLA/XlaHloShapeBuilder.cpp
@@ -308,6 +308,130 @@ return builder.create<MakeRankedShapeOp>(loc, resultShape, dynamicDims); } +Value rewriteTorchIndexSelect(RankedShapeType resultShape, + TorchIndexSelectOp torchIndexSelectOp, + OpBuilder &builder) { + if (!torchIndexSelectOp) return nullptr; + auto loc = torchIndexSelectOp.getLoc(); + + int64_t resultShapeRank = resultShape.getRank(); + auto paramsType = + torchIndexSelectOp.input().getType().dyn_cast<RankedTensorType>(); + auto indicesType = + torchIndexSelectOp.index().getType().dyn_cast<RankedTensorType>(); + if (!paramsType || !indicesType) { + return nullptr; + } + + auto axis = torchIndexSelectOp.dim(); + auto batchDim = torchIndexSelectOp.batch_dims(); + int64_t paramsRank = paramsType.getRank(); + int64_t indicesRank = indicesType.getRank(); + + std::vector<int64_t> shape(paramsType.getShape()); + int64_t axisValue = axis.getSExtValue(); + int64_t batchDimValue = batchDim.getSExtValue(); + + // For neg axis values, we wrap around params, + // e.g. axis = -1 => params[:-1] + if (axisValue < 0) { + axisValue += paramsRank; + } + if (batchDimValue < 0) { + batchDimValue += indicesRank; + } + + // params must be at least rank axis + 1 + if (paramsRank < axisValue + 1) { + return nullptr; + } + + auto paramsShapeValue = builder.create<GetRankedShapeOp>( + loc, RankedShapeType::get(paramsType.getShape(), builder.getContext()), + torchIndexSelectOp.input()); + auto indicesShapeValue = builder.create<GetRankedShapeOp>( + loc, RankedShapeType::get(indicesType.getShape(), builder.getContext()), + torchIndexSelectOp.index()); + + SmallVector<Value, 4> dynamicDims; +#define GENERATE_RANKED_DIM_OP(value, index) \ + do { \ + auto dimValue = builder.create<RankedDimOp>( \ + loc, builder.getIndexType(), value, builder.getI64IntegerAttr(index)); \ + dynamicDims.push_back(dimValue); \ + } while (0) + + if (indicesRank == 0) { + // Scalar indices (output is rank(params) - 1). + if (resultShapeRank != paramsRank - 1) { + return nullptr; + } + + // params.shape[:axis] + params.shape[axis+1:] + for (int64_t i = 0; i < paramsRank; ++i) { + if ((i == axisValue) || (i < axisValue && !resultShape.isDimDynamic(i)) || + (i > axisValue && !resultShape.isDimDynamic(i - 1))) + continue; + GENERATE_RANKED_DIM_OP(paramsShapeValue, i); + } + } else if (indicesRank == 1) { + // Vector indices (output is rank(params)). + // Copy indices.shape into params.shape[axis] + if (resultShapeRank != paramsRank) { + return nullptr; + } + + // params.shape[:axis] + indices.shape[batch_dims:] + // + params.shape[indicesRank-batchDim+axisValue:] + int resultShapeIndex = 0; + // params.shape[:axis] + for (int64_t i = 0; i < axisValue; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(paramsShapeValue, i); + } + // indices.shape[:batchDim] + for (int64_t i = batchDimValue; + i < indicesRank && resultShapeIndex < resultShapeRank; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(indicesShapeValue, i); + } + // params.shape[indicesRank-batchDim+axisValue:] + // resultShapeIndex == indicesRank-batchDim+axisValue + for (int64_t i = resultShapeIndex; i < resultShapeRank; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(paramsShapeValue, i); + } + } else { + // params.shape[:axis] + indices.shape[batch_dims:] + params.shape[axis + + // 1:] + // The expected rank is (paramsRank-1) + (indicesRank-batchDim) + auto expectedRank = paramsRank - 1 + indicesRank - batchDimValue; + if (resultShapeRank != expectedRank) { + return nullptr; + } + + int resultShapeIndex = 0; + for (int64_t i = 0; i < axisValue; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(paramsShapeValue, i); + } + + for (int64_t i = batchDimValue; i < indicesRank; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(indicesShapeValue, i); + } + + for (int64_t i = axisValue + 1; + i < paramsRank && resultShapeIndex < resultShapeRank; ++i) { + if (!resultShape.isDimDynamic(resultShapeIndex++)) continue; + GENERATE_RANKED_DIM_OP(paramsShapeValue, i); + } + } +#undef GENERATE_RANKED_DIM_OP + + return builder.create<MakeRankedShapeOp>(loc, resultShape, dynamicDims); +} + } // namespace // Creates a custom op shape builder for XLA-HLO ops that are not otherwise @@ -340,6 +464,8 @@ b.insertOpRankedShapeBuilder<TransposeOp>(rewriteTranspose); b.insertOpRankedShapeBuilder<mhlo::DotGeneralOp>(rewriteDotGeneral); b.insertOpRankedShapeBuilder<mhlo::DynamicReshapeOp>(rewriteDynamicReshape); + b.insertOpRankedShapeBuilder<mhlo::TorchIndexSelectOp>( + rewriteTorchIndexSelect); } } // namespace mhlo
diff --git a/iree/compiler/Dialect/VM/IR/VMBase.td b/iree/compiler/Dialect/VM/IR/VMBase.td index b6c31df..9243cef 100644 --- a/iree/compiler/Dialect/VM/IR/VMBase.td +++ b/iree/compiler/Dialect/VM/IR/VMBase.td
@@ -56,15 +56,39 @@ // VM opcodes //===----------------------------------------------------------------------===// // Opcode ranges: -// 0x00-0x7F: core VM opcodes, reserved for this dialect -// 0x80-0xFF: unreserved, used by target-specific ops (like SIMD) +// 0x00-0x9F: core VM opcodes, reserved for this dialect +// 0xA0-0xFF: unreserved, used to prefix extension op sets // // Note that changing existing opcode assignments will invalidate all binaries // and should only be done when breaking changes are acceptable. We could add a // versioning system here to automatically switch between different encodings // but we are a long way out to stabilizing this format :) +// +// Some opcodes require an extension prefix to indicate that runtime support +// is optional. An op with the ExtI64 trait will require VM_OPC_ExtI64, for +// example. Ops that bridge extension sets have a canonical form that may +// require multiple prefix codes (for example, the i64<->f64 extensions). -class VM_OPC<int opcode, string name> : I32EnumAttrCase<name, opcode>; +class VM_OPC<int opcode, string name> : + IntEnumAttrCaseBase<I8, name, name, opcode>; + +class VM_OPC_EnumAttr<string name, string enumName, string enumTag, + string description, + VM_OPC prefix = ?, + list<VM_OPC> cases> : + IntEnumAttr<I8, name, description, cases> { + let cppNamespace = "IREE::VM"; + let returnType = cppNamespace # "::" # name; + let underlyingType = "uint8_t"; + let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())"; + let constBuilderCall = + "$_builder.getI8IntegerAttr(static_cast<int8_t>($0))"; + + // Used by VMOpTableGen: + string opcodeEnumName = enumName; + VM_OPC opcodePrefix = prefix; + string opcodeEnumTag = enumTag; +} // Globals: def VM_OPC_GlobalLoadI32 : VM_OPC<0x00, "GlobalLoadI32">; @@ -123,10 +147,12 @@ def VM_OPC_ShrI32U : VM_OPC<0x2F, "ShrI32U">; // Casting and type conversion/emulation: -def VM_OPC_TruncI8 : VM_OPC<0x31, "TruncI8">; -def VM_OPC_TruncI16 : VM_OPC<0x32, "TruncI16">; +def VM_OPC_TruncI32I8 : VM_OPC<0x31, "TruncI32I8">; +def VM_OPC_TruncI32I16 : VM_OPC<0x32, "TruncI32I16">; def VM_OPC_ExtI8I32S : VM_OPC<0x33, "ExtI8I32S">; -def VM_OPC_ExtI16I32S : VM_OPC<0x34, "ExtI16I32S">; +def VM_OPC_ExtI8I32U : VM_OPC<0x34, "ExtI8I32U">; +def VM_OPC_ExtI16I32S : VM_OPC<0x35, "ExtI16I32S">; +def VM_OPC_ExtI16I32U : VM_OPC<0x36, "ExtI16I32U">; // Reduction arithmetic: @@ -135,12 +161,6 @@ def VM_OPC_CmpNEI32 : VM_OPC<0x41, "CmpNEI32">; def VM_OPC_CmpLTI32S : VM_OPC<0x42, "CmpLTI32S">; def VM_OPC_CmpLTI32U : VM_OPC<0x43, "CmpLTI32U">; -def VM_OPC_CmpLTEI32S : VM_OPC<0x44, "CmpLTEI32S">; -def VM_OPC_CmpLTEI32U : VM_OPC<0x45, "CmpLTEI32U">; -def VM_OPC_CmpGTI32S : VM_OPC<0x46, "CmpGTI32S">; -def VM_OPC_CmpGTI32U : VM_OPC<0x47, "CmpGTI32U">; -def VM_OPC_CmpGTEI32S : VM_OPC<0x48, "CmpGTEI32S">; -def VM_OPC_CmpGTEI32U : VM_OPC<0x49, "CmpGTEI32U">; def VM_OPC_CmpNZI32 : VM_OPC<0x4D, "CmpNZI32">; def VM_OPC_CmpEQRef : VM_OPC<0x4A, "CmpEQRef">; def VM_OPC_CmpNERef : VM_OPC<0x4B, "CmpNERef">; @@ -163,8 +183,19 @@ def VM_OPC_CondBreak : VM_OPC<0x7E, "CondBreak">; def VM_OPC_Break : VM_OPC<0x7F, "Break">; -def VM_OpcodeAttr : I32EnumAttr<"Opcode", "valid VM operation encodings", [ - // Core VM opcodes (0x00-0x7F): +// Extension prefixes: +def VM_OPC_PrefixExtI64 : VM_OPC<0xA0, "PrefixExtI64">; +def VM_OPC_PrefixExtF32 : VM_OPC<0xA1, "PrefixExtF32">; +def VM_OPC_PrefixExtF64 : VM_OPC<0xA2, "PrefixExtF64">; + +// Runtime enum iree_vm_core_op_t: +def VM_CoreOpcodeAttr : + VM_OPC_EnumAttr<"Opcode", + "iree_vm_core_op_t", + "CORE", // IREE_VM_OP_CORE_* + "valid VM core operation encodings", + ?, [ + // Core VM opcodes (0x00-0x9F): VM_OPC_GlobalLoadI32, VM_OPC_GlobalStoreI32, VM_OPC_GlobalLoadIndirectI32, @@ -203,16 +234,16 @@ VM_OPC_ShlI32, VM_OPC_ShrI32S, VM_OPC_ShrI32U, + VM_OPC_TruncI32I8, + VM_OPC_TruncI32I16, + VM_OPC_ExtI8I32S, + VM_OPC_ExtI8I32U, + VM_OPC_ExtI16I32S, + VM_OPC_ExtI16I32U, VM_OPC_CmpEQI32, VM_OPC_CmpNEI32, VM_OPC_CmpLTI32S, VM_OPC_CmpLTI32U, - VM_OPC_CmpLTEI32S, - VM_OPC_CmpLTEI32U, - VM_OPC_CmpGTI32S, - VM_OPC_CmpGTI32U, - VM_OPC_CmpGTEI32S, - VM_OPC_CmpGTEI32U, VM_OPC_CmpNZI32, VM_OPC_CmpEQRef, VM_OPC_CmpNERef, @@ -229,11 +260,99 @@ VM_OPC_CondBreak, VM_OPC_Break, - // Extension opcodes (0x80-0xFF): - // TODO(benvanik): SIMD dialect. - ]> { - let cppNamespace = "IREE::VM"; -} + // Extension opcodes (0xA0-0xFF): + VM_OPC_PrefixExtI64, // VM_ExtI64OpcodeAttr + VM_OPC_PrefixExtF32, // VM_ExtF32OpcodeAttr + VM_OPC_PrefixExtF64, // VM_ExtF64OpcodeAttr + ]>; + +// i64 extension: +// (ops are encoded as a VM_OPC_ExtI64 + the opcode below) +def VM_OPC_GlobalLoadI64 : VM_OPC<0x00, "GlobalLoadI64">; +def VM_OPC_GlobalStoreI64 : VM_OPC<0x01, "GlobalStoreI64">; +def VM_OPC_GlobalLoadIndirectI64 : VM_OPC<0x02, "GlobalLoadIndirectI64">; +def VM_OPC_GlobalStoreIndirectI64: VM_OPC<0x03, "GlobalStoreIndirectI64">; +def VM_OPC_ConstI64Zero : VM_OPC<0x08, "ConstI64Zero">; +def VM_OPC_ConstI64 : VM_OPC<0x09, "ConstI64">; +def VM_OPC_ListGetI64 : VM_OPC<0x14, "ListGetI64">; +def VM_OPC_ListSetI64 : VM_OPC<0x15, "ListSetI64">; +def VM_OPC_SelectI64 : VM_OPC<0x1E, "SelectI64">; +def VM_OPC_SwitchI64 : VM_OPC<0x20, "SwitchI64">; +def VM_OPC_AddI64 : VM_OPC<0x22, "AddI64">; +def VM_OPC_SubI64 : VM_OPC<0x23, "SubI64">; +def VM_OPC_MulI64 : VM_OPC<0x24, "MulI64">; +def VM_OPC_DivI64S : VM_OPC<0x25, "DivI64S">; +def VM_OPC_DivI64U : VM_OPC<0x26, "DivI64U">; +def VM_OPC_RemI64S : VM_OPC<0x27, "RemI64S">; +def VM_OPC_RemI64U : VM_OPC<0x28, "RemI64U">; +def VM_OPC_NotI64 : VM_OPC<0x29, "NotI64">; +def VM_OPC_AndI64 : VM_OPC<0x2A, "AndI64">; +def VM_OPC_OrI64 : VM_OPC<0x2B, "OrI64">; +def VM_OPC_XorI64 : VM_OPC<0x2C, "XorI64">; +def VM_OPC_ShlI64 : VM_OPC<0x2D, "ShlI64">; +def VM_OPC_ShrI64S : VM_OPC<0x2E, "ShrI64S">; +def VM_OPC_ShrI64U : VM_OPC<0x2F, "ShrI64U">; +def VM_OPC_TruncI64I8 : VM_OPC<0x30, "TruncI64I8">; +def VM_OPC_TruncI64I16 : VM_OPC<0x31, "TruncI64I16">; +def VM_OPC_TruncI64I32 : VM_OPC<0x32, "TruncI64I32">; +def VM_OPC_ExtI8I64S : VM_OPC<0x33, "ExtI8I64S">; +def VM_OPC_ExtI8I64U : VM_OPC<0x34, "ExtI8I64U">; +def VM_OPC_ExtI16I64S : VM_OPC<0x35, "ExtI16I64S">; +def VM_OPC_ExtI16I64U : VM_OPC<0x36, "ExtI16I64U">; +def VM_OPC_ExtI32I64S : VM_OPC<0x37, "ExtI32I64S">; +def VM_OPC_ExtI32I64U : VM_OPC<0x38, "ExtI32I64U">; +def VM_OPC_CmpEQI64 : VM_OPC<0x40, "CmpEQI64">; +def VM_OPC_CmpNEI64 : VM_OPC<0x41, "CmpNEI64">; +def VM_OPC_CmpLTI64S : VM_OPC<0x42, "CmpLTI64S">; +def VM_OPC_CmpLTI64U : VM_OPC<0x43, "CmpLTI64U">; +def VM_OPC_CmpNZI64 : VM_OPC<0x4D, "CmpNZI64">; + +// Runtime enum iree_vm_ext_i64_op_t: +def VM_ExtI64OpcodeAttr : + VM_OPC_EnumAttr<"ExtI64Opcode", + "iree_vm_ext_i64_op_t", + "EXT_I64", // IREE_VM_OP_EXT_I64_* + "valid VM operation encodings in the i64 extension", + VM_OPC_PrefixExtI64, [ + VM_OPC_GlobalLoadI64, + VM_OPC_GlobalStoreI64, + VM_OPC_GlobalLoadIndirectI64, + VM_OPC_GlobalStoreIndirectI64, + VM_OPC_ConstI64Zero, + VM_OPC_ConstI64, + VM_OPC_ListGetI64, + VM_OPC_ListSetI64, + VM_OPC_SelectI64, + VM_OPC_SwitchI64, + VM_OPC_AddI64, + VM_OPC_SubI64, + VM_OPC_MulI64, + VM_OPC_DivI64S, + VM_OPC_DivI64U, + VM_OPC_RemI64S, + VM_OPC_RemI64U, + VM_OPC_NotI64, + VM_OPC_AndI64, + VM_OPC_OrI64, + VM_OPC_XorI64, + VM_OPC_ShlI64, + VM_OPC_ShrI64S, + VM_OPC_ShrI64U, + VM_OPC_TruncI64I8, + VM_OPC_TruncI64I16, + VM_OPC_TruncI64I32, + VM_OPC_ExtI8I64S, + VM_OPC_ExtI8I64U, + VM_OPC_ExtI16I64S, + VM_OPC_ExtI16I64U, + VM_OPC_ExtI32I64S, + VM_OPC_ExtI32I64U, + VM_OPC_CmpEQI64, + VM_OPC_CmpNEI64, + VM_OPC_CmpLTI64S, + VM_OPC_CmpLTI64U, + VM_OPC_CmpNZI64, + ]>; //===----------------------------------------------------------------------===// // Declarative encoding framework @@ -374,6 +493,40 @@ list<VM_EncEncodeExpr> encoding = ?; } +def VM_GlobalOpInterface : OpInterface<"VMGlobalOp"> { + let description = [{ + Interface used for VM ops that declare global values. + }]; + + let methods = [ + InterfaceMethod<[{ + Returns the storage type of this global such as i32. + }], + "Type", "getStorageType", (ins)>, + InterfaceMethod<[{ + Returns the size in bytes of the global when stored in rwdata. Valid only + for globals using primitive storage. + }], + "size_t", "getStorageSize", (ins), [{ + auto storageType = $_self.getStorageType(); + assert(storageType.isIntOrFloat()); + assert(storageType.getIntOrFloatBitWidth() % 8 == 0); + return storageType.getIntOrFloatBitWidth() / 8; + }]>, + InterfaceMethod<[{}], "StringRef", "getSymbolName", (ins)>, + InterfaceMethod<[{}], "bool", "isMutable", (ins)>, + InterfaceMethod<[{}], "Optional<StringRef>", "getInitializerAttr", (ins)>, + InterfaceMethod<[{}], "Optional<Attribute>", "getInitialValueAttr", (ins)>, + InterfaceMethod<[{}], "Optional<IntegerAttr>", "getOrdinalAttr", (ins)>, + InterfaceMethod<[{}], "int", "getOrdinal", (ins), [{ + return $_self.getOrdinalAttr().getValue().template cast<IntegerAttr>().getInt(); + }]>, + InterfaceMethod<[{}], "void", "makeMutable", (ins)>, + InterfaceMethod<[{}], "void", "clearInitializer", (ins)>, + InterfaceMethod<[{}], "void", "clearInitialValue", (ins)>, + ]; +} + //===----------------------------------------------------------------------===// // VM traits //===----------------------------------------------------------------------===// @@ -390,6 +543,13 @@ // that execution order before and after the barrier op remains the same. def VM_FullBarrier : NativeOpTrait<"IREE::VM::FullBarrier">; +// Operations with this trait require the VM i64 extension. +def VM_ExtI64 : NativeOpTrait<"IREE::VM::ExtI64">; +// Operations with this trait require the VM f32 extension. +def VM_ExtF32 : NativeOpTrait<"IREE::VM::ExtF32">; +// Operations with this trait require the VM f64 extension. +def VM_ExtF64 : NativeOpTrait<"IREE::VM::ExtF64">; + //===----------------------------------------------------------------------===// // ref<T> types //===----------------------------------------------------------------------===// @@ -471,13 +631,16 @@ def VM_AnyType : AnyTypeOf<[ I32, + I64, + F32, + F64, VM_CondValue, VM_AnyRef, ]>; def VM_PrimitiveType : AnyTypeOf<[ - AnyIntOfWidths<[8, 16, 32]>, - FloatOfWidths<[16, 32]>, + AnyIntOfWidths<[8, 16, 32, 64]>, + FloatOfWidths<[16, 32, 64]>, ]>; class VM_ConstIntValueAttr<I type> : Attr<
diff --git a/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp b/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp index 7ae855b..b3ceb17 100644 --- a/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp +++ b/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp
@@ -590,12 +590,12 @@ // Casting and type conversion/emulation //===----------------------------------------------------------------------===// -OpFoldResult TruncI8Op::fold(ArrayRef<Attribute> operands) { +OpFoldResult TruncI32I8Op::fold(ArrayRef<Attribute> operands) { return constFoldUnaryOp<IntegerAttr>( operands, [&](APInt a) { return a.trunc(8).zext(32); }); } -OpFoldResult TruncI16Op::fold(ArrayRef<Attribute> operands) { +OpFoldResult TruncI32I16Op::fold(ArrayRef<Attribute> operands) { return constFoldUnaryOp<IntegerAttr>( operands, [&](APInt a) { return a.trunc(16).zext(32); }); } @@ -605,11 +605,21 @@ operands, [&](APInt a) { return a.trunc(8).sext(32); }); } +OpFoldResult ExtI8I32UOp::fold(ArrayRef<Attribute> operands) { + return constFoldUnaryOp<IntegerAttr>( + operands, [&](APInt a) { return a.trunc(8).zext(32); }); +} + OpFoldResult ExtI16I32SOp::fold(ArrayRef<Attribute> operands) { return constFoldUnaryOp<IntegerAttr>( operands, [&](APInt a) { return a.trunc(16).sext(32); }); } +OpFoldResult ExtI16I32UOp::fold(ArrayRef<Attribute> operands) { + return constFoldUnaryOp<IntegerAttr>( + operands, [&](APInt a) { return a.trunc(16).zext(32); }); +} + //===----------------------------------------------------------------------===// // Native reduction (horizontal) arithmetic //===----------------------------------------------------------------------===// @@ -706,9 +716,7 @@ } void CmpLTI32SOp::getCanonicalizationPatterns(OwningRewritePatternList &results, - MLIRContext *context) { - results.insert<SwapInvertedCmpOps<CmpLTI32SOp, CmpGTEI32SOp>>(context); -} + MLIRContext *context) {} OpFoldResult CmpLTI32UOp::fold(ArrayRef<Attribute> operands) { if (lhs() == rhs()) { @@ -720,9 +728,27 @@ } void CmpLTI32UOp::getCanonicalizationPatterns(OwningRewritePatternList &results, - MLIRContext *context) { - results.insert<SwapInvertedCmpOps<CmpLTI32UOp, CmpGTEI32UOp>>(context); -} + MLIRContext *context) {} + +namespace { + +/// Rewrites a vm.cmp.lte.* pseudo op to a vm.cmp.lt.* op. +template <typename T, typename U> +struct RewritePseudoCmpLTEToLT : public OpRewritePattern<T> { + using OpRewritePattern<T>::OpRewritePattern; + LogicalResult matchAndRewrite(T op, + PatternRewriter &rewriter) const override { + // !(lhs > rhs) + auto condValue = + rewriter.createOrFold<U>(op.getLoc(), op.getType(), op.rhs(), op.lhs()); + rewriter.replaceOpWithNewOp<XorI32Op>( + op, op.getType(), condValue, + rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(), 1)); + return success(); + } +}; + +} // namespace OpFoldResult CmpLTEI32SOp::fold(ArrayRef<Attribute> operands) { if (lhs() == rhs()) { @@ -736,6 +762,7 @@ void CmpLTEI32SOp::getCanonicalizationPatterns( OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpLTEI32SOp, CmpGTI32SOp>>(context); + results.insert<RewritePseudoCmpLTEToLT<CmpLTEI32SOp, CmpLTI32SOp>>(context); } OpFoldResult CmpLTEI32UOp::fold(ArrayRef<Attribute> operands) { @@ -750,8 +777,25 @@ void CmpLTEI32UOp::getCanonicalizationPatterns( OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpLTEI32UOp, CmpGTI32UOp>>(context); + results.insert<RewritePseudoCmpLTEToLT<CmpLTEI32UOp, CmpLTI32UOp>>(context); } +namespace { + +/// Rewrites a vm.cmp.gt.* pseudo op to a vm.cmp.lt.* op. +template <typename T, typename U> +struct RewritePseudoCmpGTToLT : public OpRewritePattern<T> { + using OpRewritePattern<T>::OpRewritePattern; + LogicalResult matchAndRewrite(T op, + PatternRewriter &rewriter) const override { + // rhs < lhs + rewriter.replaceOpWithNewOp<U>(op, op.getType(), op.rhs(), op.lhs()); + return success(); + } +}; + +} // namespace + OpFoldResult CmpGTI32SOp::fold(ArrayRef<Attribute> operands) { if (lhs() == rhs()) { // x > x = false @@ -764,6 +808,7 @@ void CmpGTI32SOp::getCanonicalizationPatterns(OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpGTI32SOp, CmpLTEI32SOp>>(context); + results.insert<RewritePseudoCmpGTToLT<CmpGTI32SOp, CmpLTI32SOp>>(context); } OpFoldResult CmpGTI32UOp::fold(ArrayRef<Attribute> operands) { @@ -778,8 +823,29 @@ void CmpGTI32UOp::getCanonicalizationPatterns(OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpGTI32UOp, CmpLTEI32UOp>>(context); + results.insert<RewritePseudoCmpGTToLT<CmpGTI32UOp, CmpLTI32UOp>>(context); } +namespace { + +/// Rewrites a vm.cmp.gte.* pseudo op to a vm.cmp.lt.* op. +template <typename T, typename U> +struct RewritePseudoCmpGTEToLT : public OpRewritePattern<T> { + using OpRewritePattern<T>::OpRewritePattern; + LogicalResult matchAndRewrite(T op, + PatternRewriter &rewriter) const override { + // !(lhs < rhs) + auto condValue = + rewriter.createOrFold<U>(op.getLoc(), op.getType(), op.lhs(), op.rhs()); + rewriter.replaceOpWithNewOp<XorI32Op>( + op, op.getType(), condValue, + rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(), 1)); + return success(); + } +}; + +} // namespace + OpFoldResult CmpGTEI32SOp::fold(ArrayRef<Attribute> operands) { if (lhs() == rhs()) { // x >= x = true @@ -792,6 +858,7 @@ void CmpGTEI32SOp::getCanonicalizationPatterns( OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpGTEI32SOp, CmpLTI32SOp>>(context); + results.insert<RewritePseudoCmpGTEToLT<CmpGTEI32SOp, CmpLTI32SOp>>(context); } OpFoldResult CmpGTEI32UOp::fold(ArrayRef<Attribute> operands) { @@ -806,6 +873,7 @@ void CmpGTEI32UOp::getCanonicalizationPatterns( OwningRewritePatternList &results, MLIRContext *context) { results.insert<SwapInvertedCmpOps<CmpGTEI32UOp, CmpLTI32UOp>>(context); + results.insert<RewritePseudoCmpGTEToLT<CmpGTEI32UOp, CmpLTI32UOp>>(context); } OpFoldResult CmpNZI32Op::fold(ArrayRef<Attribute> operands) {
diff --git a/iree/compiler/Dialect/VM/IR/VMOps.td b/iree/compiler/Dialect/VM/IR/VMOps.td index c552347..b3a7a4e 100644 --- a/iree/compiler/Dialect/VM/IR/VMOps.td +++ b/iree/compiler/Dialect/VM/IR/VMOps.td
@@ -256,6 +256,7 @@ IsolatedFromAbove, HasParent<"IREE::VM::ModuleOp">, Symbol, + VM_GlobalOpInterface, ])> { let arguments = (ins StrAttr:$sym_name, @@ -291,9 +292,15 @@ ]; let extraClassDeclaration = [{ + StringRef getSymbolName() { return sym_name(); } + Type getStorageType() { return type(); } + bool isMutable() { return is_mutable(); } void makeMutable() { setAttr("is_mutable", UnitAttr::get(getContext())); } + Optional<StringRef> getInitializerAttr() { return initializer(); } void clearInitializer() { removeAttr("initializer"); } + Optional<Attribute> getInitialValueAttr() { return initial_valueAttr(); } void clearInitialValue() { removeAttr("initial_value"); } + Optional<IntegerAttr> getOrdinalAttr() { return ordinalAttr(); } }]; let parser = [{ return parseGlobalOp(parser, &result); }]; @@ -1248,7 +1255,7 @@ let encoding = [ VM_EncOpcode<opcode>, VM_EncOperand<"operand", 0>, - VM_EncIntAttr<"amount", type.bitwidth>, + VM_EncIntAttr<"amount", 8>, VM_EncResult<"result">, ]; } @@ -1272,12 +1279,12 @@ // Casting and type conversion/emulation //===----------------------------------------------------------------------===// -def VM_TruncI8Op : VM_UnaryArithmeticOp<I32, "trunc.i8", VM_OPC_TruncI8> { +def VM_TruncI32I8Op : VM_UnaryArithmeticOp<I32, "trunc.i32.i8", VM_OPC_TruncI32I8> { let summary = [{integer truncate to 8 bits}]; let hasFolder = 1; } -def VM_TruncI16Op : VM_UnaryArithmeticOp<I32, "trunc.i16", VM_OPC_TruncI16> { +def VM_TruncI32I16Op : VM_UnaryArithmeticOp<I32, "trunc.i32.i16", VM_OPC_TruncI32I16> { let summary = [{integer truncate to 16 bits}]; let hasFolder = 1; } @@ -1287,11 +1294,21 @@ let hasFolder = 1; } +def VM_ExtI8I32UOp : VM_UnaryArithmeticOp<I32, "ext.i8.i32.u", VM_OPC_ExtI8I32U> { + let summary = [{integer zero extend 8 bits to 32 bits}]; + let hasFolder = 1; +} + def VM_ExtI16I32SOp : VM_UnaryArithmeticOp<I32, "ext.i16.i32.s", VM_OPC_ExtI16I32S> { let summary = [{integer sign extend 16 bits to 32 bits}]; let hasFolder = 1; } +def VM_ExtI16I32UOp : VM_UnaryArithmeticOp<I32, "ext.i16.i32.u", VM_OPC_ExtI16I32U> { + let summary = [{integer zero extend 16 bits to 32 bits}]; + let hasFolder = 1; +} + //===----------------------------------------------------------------------===// // Native reduction (horizontal) arithmetic //===----------------------------------------------------------------------===// @@ -1355,6 +1372,27 @@ ]; } +class VM_BinaryComparisonPseudoOp<Type type, string mnemonic, + list<OpTrait> traits = []> : + VM_PureOp<mnemonic, !listconcat(traits, [ + AllTypesMatch<["lhs", "rhs"]>, + VM_PseudoOp, + ])> { + let description = [{ + Compares two operands with the specified predicate. + }]; + + let arguments = (ins + type:$lhs, + type:$rhs + ); + let results = (outs + I32:$result + ); + + let assemblyFormat = "operands attr-dict `:` type($lhs)"; +} + def VM_CmpEQI32Op : VM_BinaryComparisonOp<I32, "cmp.eq.i32", VM_OPC_CmpEQI32, [Commutative]> { let summary = [{integer equality comparison operation}]; @@ -1384,43 +1422,42 @@ } def VM_CmpLTEI32SOp : - VM_BinaryComparisonOp<I32, "cmp.lte.i32.s", VM_OPC_CmpLTEI32S> { + VM_BinaryComparisonPseudoOp<I32, "cmp.lte.i32.s"> { let summary = [{signed integer less-than-or-equal comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1; } def VM_CmpLTEI32UOp : - VM_BinaryComparisonOp<I32, "cmp.lte.i32.u", VM_OPC_CmpLTEI32U> { + VM_BinaryComparisonPseudoOp<I32, "cmp.lte.i32.u"> { let summary = [{unsigned integer less-than-or-equal comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1; } -// TODO(benvanik): drop these and rely on lt/lte only? def VM_CmpGTI32SOp : - VM_BinaryComparisonOp<I32, "cmp.gt.i32.s", VM_OPC_CmpGTI32S> { + VM_BinaryComparisonPseudoOp<I32, "cmp.gt.i32.s"> { let summary = [{signed integer greater-than comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1; } def VM_CmpGTI32UOp : - VM_BinaryComparisonOp<I32, "cmp.gt.i32.u", VM_OPC_CmpGTI32U> { + VM_BinaryComparisonPseudoOp<I32, "cmp.gt.i32.u"> { let summary = [{unsigned integer greater-than comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1; } def VM_CmpGTEI32SOp : - VM_BinaryComparisonOp<I32, "cmp.gte.i32.s", VM_OPC_CmpGTEI32S> { + VM_BinaryComparisonPseudoOp<I32, "cmp.gte.i32.s"> { let summary = [{signed integer greater-than-or-equal comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1; } def VM_CmpGTEI32UOp : - VM_BinaryComparisonOp<I32, "cmp.gte.i32.u", VM_OPC_CmpGTEI32U> { + VM_BinaryComparisonPseudoOp<I32, "cmp.gte.i32.u"> { let summary = [{unsigned integer greater-than-or-equal comparison operation}]; let hasCanonicalizer = 1; let hasFolder = 1;
diff --git a/iree/compiler/Dialect/VM/IR/VMTraits.h b/iree/compiler/Dialect/VM/IR/VMTraits.h index 7527383..330f75c 100644 --- a/iree/compiler/Dialect/VM/IR/VMTraits.h +++ b/iree/compiler/Dialect/VM/IR/VMTraits.h
@@ -49,6 +49,33 @@ } }; +template <typename ConcreteType> +class ExtI64 : public OpTrait::TraitBase<ConcreteType, ExtI64> { + public: + static LogicalResult verifyTrait(Operation *op) { + // TODO(benvanik): verify i64 ext is supported. + return success(); + } +}; + +template <typename ConcreteType> +class ExtF32 : public OpTrait::TraitBase<ConcreteType, ExtF32> { + public: + static LogicalResult verifyTrait(Operation *op) { + // TODO(benvanik): verify f32 ext is supported. + return success(); + } +}; + +template <typename ConcreteType> +class ExtF64 : public OpTrait::TraitBase<ConcreteType, ExtF64> { + public: + static LogicalResult verifyTrait(Operation *op) { + // TODO(benvanik): verify f64 ext is supported. + return success(); + } +}; + } // namespace VM } // namespace IREE } // namespace OpTrait
diff --git a/iree/compiler/Dialect/VM/IR/test/conversion_folding.mlir b/iree/compiler/Dialect/VM/IR/test/conversion_folding.mlir index 0f6222e..02a9ea3 100644 --- a/iree/compiler/Dialect/VM/IR/test/conversion_folding.mlir +++ b/iree/compiler/Dialect/VM/IR/test/conversion_folding.mlir
@@ -8,7 +8,7 @@ vm.func @trunc_i8_const() -> i32 { // CHECK: vm.const.i32 255 : i32 %c = vm.const.i32 0xFFFFFFFF : i32 - %0 = vm.trunc.i8 %c : i32 + %0 = vm.trunc.i32.i8 %c : i32 vm.return %0 : i32 } @@ -16,7 +16,7 @@ vm.func @trunc_i16_const() -> i32 { // CHECK: vm.const.i32 65535 : i32 %c = vm.const.i32 0xFFFFFFFF : i32 - %0 = vm.trunc.i16 %c : i32 + %0 = vm.trunc.i32.i16 %c : i32 vm.return %0 : i32 } } @@ -33,6 +33,14 @@ vm.return %0 : i32 } + // CHECK-LABEL: @ext_i8_i32_u_const + vm.func @ext_i8_i32_u_const() -> i32 { + // CHECK: vm.const.i32 255 : i32 + %c = vm.const.i32 0x000000FF : i32 + %0 = vm.ext.i8.i32.u %c : i32 + vm.return %0 : i32 + } + // CHECK-LABEL: @ext_i16_i32_s_const vm.func @ext_i16_i32_s_const() -> i32 { // CHECK: vm.const.i32 -1 : i32 @@ -40,4 +48,12 @@ %0 = vm.ext.i16.i32.s %c : i32 vm.return %0 : i32 } + + // CHECK-LABEL: @ext_i16_i32_u_const + vm.func @ext_i16_i32_u_const() -> i32 { + // CHECK: vm.const.i32 65535 : i32 + %c = vm.const.i32 0x0000FFFF : i32 + %0 = vm.ext.i16.i32.u %c : i32 + vm.return %0 : i32 + } }
diff --git a/iree/compiler/Dialect/VM/IR/test/conversion_ops.mlir b/iree/compiler/Dialect/VM/IR/test/conversion_ops.mlir index 5e94458..008c5d6 100644 --- a/iree/compiler/Dialect/VM/IR/test/conversion_ops.mlir +++ b/iree/compiler/Dialect/VM/IR/test/conversion_ops.mlir
@@ -5,10 +5,10 @@ // CHECK-LABEL: @trunc vm.module @my_module { vm.func @trunc(%arg0 : i32) -> i32 { - // CHECK: %0 = vm.trunc.i8 %arg0 : i32 - %0 = vm.trunc.i8 %arg0 : i32 - // CHECK-NEXT: %1 = vm.trunc.i16 %0 : i32 - %1 = vm.trunc.i16 %0 : i32 + // CHECK: %0 = vm.trunc.i32.i8 %arg0 : i32 + %0 = vm.trunc.i32.i8 %arg0 : i32 + // CHECK-NEXT: %1 = vm.trunc.i32.i16 %0 : i32 + %1 = vm.trunc.i32.i16 %0 : i32 vm.return %1 : i32 } } @@ -20,8 +20,12 @@ vm.func @ext(%arg0 : i32) -> i32 { // CHECK-NEXT: %0 = vm.ext.i8.i32.s %arg0 : i32 %0 = vm.ext.i8.i32.s %arg0 : i32 - // CHECK-NEXT: %1 = vm.ext.i16.i32.s %0 : i32 - %1 = vm.ext.i16.i32.s %0 : i32 - vm.return %1 : i32 + // CHECK-NEXT: %1 = vm.ext.i8.i32.u %0 : i32 + %1 = vm.ext.i8.i32.u %0 : i32 + // CHECK-NEXT: %2 = vm.ext.i16.i32.s %1 : i32 + %2 = vm.ext.i16.i32.s %1 : i32 + // CHECK-NEXT: %3 = vm.ext.i16.i32.u %2 : i32 + %3 = vm.ext.i16.i32.u %2 : i32 + vm.return %3 : i32 } }
diff --git a/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp b/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp index 314c6ea..2273286 100644 --- a/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp +++ b/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp
@@ -56,7 +56,7 @@ int importFuncs = 0; int exportFuncs = 0; int internalFuncs = 0; - int globalBytes = 0; + size_t globalBytes = 0; int globalRefs = 0; int rodatas = 0; int rwdatas = 0; @@ -85,12 +85,14 @@ ++counts.exportFuncs; } else if (isa<IREE::VM::ImportOp>(op)) { ++counts.importFuncs; - } else if (isa<IREE::VM::GlobalI32Op>(op)) { - counts.globalBytes += 4; - } else if (isa<IREE::VM::GlobalRefOp>(op)) { - ++counts.globalRefs; } else if (isa<IREE::VM::RodataOp>(op)) { ++counts.rodatas; + } else if (isa<IREE::VM::GlobalRefOp>(op)) { + ++counts.globalRefs; + } else if (auto globalOp = dyn_cast<VMGlobalOp>(op)) { + counts.globalBytes = + std::max(counts.globalBytes, + globalOp.getOrdinal() + globalOp.getStorageSize()); } } return counts;
diff --git a/iree/compiler/Dialect/VM/Tools/VMOpTableGen.cpp b/iree/compiler/Dialect/VM/Tools/VMOpTableGen.cpp index de17975..b3081c1 100644 --- a/iree/compiler/Dialect/VM/Tools/VMOpTableGen.cpp +++ b/iree/compiler/Dialect/VM/Tools/VMOpTableGen.cpp
@@ -29,47 +29,33 @@ using ::llvm::formatv; using ::llvm::Record; -// Finds all serializable ops and emits a enum and template table for their -// opcode and name. -bool emitOpTableDefs(const llvm::RecordKeeper &recordKeeper, raw_ostream &os) { - llvm::emitSourceFileHeader("IREE VM Operation Tables", os); - - std::vector<const Record *> opRecords(256); +void emitOpTable(const llvm::RecordKeeper &recordKeeper, const Record &tableDef, + raw_ostream &os) { std::vector<const Record *> opEncodings(256); - auto defs = recordKeeper.getAllDerivedDefinitions("VM_Op"); - for (const auto *def : defs) { - if (def->isValueUnset("encoding")) continue; - auto encodingExprs = def->getValueAsListOfDefs("encoding"); - for (auto encodingExpr : encodingExprs) { - if (encodingExpr->getType()->getAsString() == "VM_EncOpcode") { - auto *opcode = encodingExpr->getValueAsDef("opcode"); - opRecords[opcode->getValueAsInt("value")] = def; - opEncodings[opcode->getValueAsInt("value")] = opcode; - break; - } - } + for (auto *opcodeDef : tableDef.getValueAsListOfDefs("enumerants")) { + opEncodings[opcodeDef->getValueAsInt("value")] = opcodeDef; } os << "typedef enum {\n"; for (int i = 0; i < 256; ++i) { - auto *def = opRecords[i]; - if (def) { - auto *opcode = opEncodings[i]; - os << formatv(" IREE_VM_OP_{0} = {1}", + if (auto *opcode = opEncodings[i]) { + os << formatv(" IREE_VM_OP_{0}_{1} = {2}", + tableDef.getValueAsString("opcodeEnumTag"), opcode->getValueAsString("symbol"), format_hex(i, 4, true)); } else { - os << formatv(" IREE_VM_OP_RSV_{0}", format_hex(i, 4, true)); + os << formatv(" IREE_VM_OP_{0}_RSV_{1}", + tableDef.getValueAsString("opcodeEnumTag"), + format_hex(i, 4, true)); } os << ",\n"; } - os << "} iree_vm_op_t;\n"; + os << "} " << tableDef.getValueAsString("opcodeEnumName") << ";\n"; os << "\n"; - os << "#define IREE_VM_OP_TABLE(OPC, RSV) \\\n"; + os << formatv("#define IREE_VM_OP_{0}_TABLE(OPC, RSV) \\\n", + tableDef.getValueAsString("opcodeEnumTag")); for (int i = 0; i < 256; ++i) { - auto *def = opRecords[i]; - if (def) { - auto *opcode = opEncodings[i]; + if (auto *opcode = opEncodings[i]) { os << formatv(" OPC({0}, {1})", format_hex(i, 4, true), opcode->getValueAsString("symbol")); } else { @@ -80,6 +66,17 @@ } } os << "\n\n"; +} + +// Finds all opcode tables in VMBase.td and emits a enum and template table for +// their opcode and name. +bool emitOpTableDefs(const llvm::RecordKeeper &recordKeeper, raw_ostream &os) { + llvm::emitSourceFileHeader("IREE VM Operation Tables", os); + + auto defs = recordKeeper.getAllDerivedDefinitions("VM_OPC_EnumAttr"); + for (const auto *def : defs) { + emitOpTable(recordKeeper, *def, os); + } return false; }
diff --git a/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp b/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp index b87441d..6a30818 100644 --- a/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp +++ b/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
@@ -65,13 +65,13 @@ // could gather the ops, sort them (by some rule), and then build the // initialization function. for (auto &op : getOperation().getBlock().getOperations()) { - if (auto globalOp = dyn_cast<GlobalI32Op>(op)) { - if (failed(appendInitialization(globalOp, initBuilder))) { + if (auto globalOp = dyn_cast<GlobalRefOp>(op)) { + if (failed(appendRefInitialization(globalOp, initBuilder))) { globalOp.emitOpError() << "unable to be initialized"; return signalPassFailure(); } - } else if (auto globalOp = dyn_cast<GlobalRefOp>(op)) { - if (failed(appendInitialization(globalOp, initBuilder))) { + } else if (auto globalOp = dyn_cast<VMGlobalOp>(op)) { + if (failed(appendPrimitiveInitialization(globalOp, initBuilder))) { globalOp.emitOpError() << "unable to be initialized"; return signalPassFailure(); } @@ -96,27 +96,72 @@ } private: - LogicalResult appendInitialization(GlobalI32Op globalOp, OpBuilder &builder) { - if (globalOp.initial_value().hasValue()) { - auto constOp = builder.create<ConstI32Op>(globalOp.getLoc(), - globalOp.initial_valueAttr()); - builder.create<GlobalStoreI32Op>(globalOp.getLoc(), constOp.getResult(), - globalOp.sym_name()); + LogicalResult appendPrimitiveInitialization(VMGlobalOp globalOp, + OpBuilder &builder) { + auto initialValue = + globalOp.getInitialValueAttr().getValueOr<Attribute>({}); + Value value = {}; + if (initialValue) { + LogicalResult constResult = success(); + std::tie(constResult, value) = + createConst(globalOp.getLoc(), initialValue, builder); + if (failed(constResult)) { + return globalOp.emitOpError() + << "unable to create initializer constant for global"; + } globalOp.clearInitialValue(); - globalOp.makeMutable(); - } else if (globalOp.initializer().hasValue()) { + } else if (globalOp.getInitializerAttr().hasValue()) { auto callOp = builder.create<CallOp>( - globalOp.getLoc(), globalOp.initializerAttr(), - ArrayRef<Type>{globalOp.type()}, ArrayRef<Value>{}); - builder.create<GlobalStoreI32Op>(globalOp.getLoc(), callOp.getResult(0), - globalOp.sym_name()); + globalOp.getLoc(), globalOp.getInitializerAttr().getValue(), + ArrayRef<Type>{globalOp.getStorageType()}, ArrayRef<Value>{}); + value = callOp.getResult(0); globalOp.clearInitializer(); - globalOp.makeMutable(); } - return success(); + if (!value) { + // Globals are zero-initialized by default so we can just strip the + // initial value/initializer and avoid the work entirely. + return success(); + } + globalOp.makeMutable(); + return storePrimitiveGlobal(globalOp.getLoc(), globalOp.getSymbolName(), + value, builder); } - LogicalResult appendInitialization(GlobalRefOp globalOp, OpBuilder &builder) { + // Returns {} if the constant is zero. + std::pair<LogicalResult, Value> createConst(Location loc, Attribute value, + OpBuilder &builder) { + if (auto intValue = value.dyn_cast<IntegerAttr>()) { + if (intValue.getValue().isNullValue()) { + // Globals are zero-initialized by default. + return {success(), {}}; + } + switch (intValue.getValue().getBitWidth()) { + case 32: + return {success(), builder.createOrFold<ConstI32Op>(loc, intValue)}; + default: + return {failure(), {}}; + } + } + return {failure(), {}}; + } + + // Stores a value to a global; the global must be mutable. + LogicalResult storePrimitiveGlobal(Location loc, StringRef symName, + Value value, OpBuilder &builder) { + if (auto intType = value.getType().dyn_cast<IntegerType>()) { + switch (intType.getIntOrFloatBitWidth()) { + case 32: + builder.create<GlobalStoreI32Op>(loc, value, symName); + return success(); + default: + return failure(); + } + } + return failure(); + } + + LogicalResult appendRefInitialization(GlobalRefOp globalOp, + OpBuilder &builder) { if (globalOp.initializer().hasValue()) { auto callOp = builder.create<CallOp>( globalOp.getLoc(), globalOp.initializerAttr(),
diff --git a/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp b/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp index e75b918..6692c7a 100644 --- a/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp +++ b/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
@@ -49,9 +49,9 @@ int nextFuncOrdinal = 0; int nextImportOrdinal = 0; int nextExportOrdinal = 0; - int nextGlobalBytesOrdinal = 0; int nextGlobalRefOrdinal = 0; int nextRodataOrdinal = 0; + SmallVector<SmallVector<VMGlobalOp, 4>, 8> primitiveGlobalOps(8); for (auto &op : getOperation().getBlock().getOperations()) { Optional<int> ordinal = llvm::None; if (auto funcOp = dyn_cast<FuncOp>(op)) { @@ -60,19 +60,36 @@ ordinal = nextExportOrdinal++; } else if (isa<ImportOp>(op)) { ordinal = nextImportOrdinal++; - } else if (isa<GlobalI32Op>(op)) { - ordinal = nextGlobalBytesOrdinal; - nextGlobalBytesOrdinal += 4; - } else if (isa<GlobalRefOp>(op)) { - ordinal = nextGlobalRefOrdinal++; } else if (isa<RodataOp>(op)) { ordinal = nextRodataOrdinal++; + } else if (isa<GlobalRefOp>(op)) { + ordinal = nextGlobalRefOrdinal++; + } else if (auto globalOp = dyn_cast<VMGlobalOp>(op)) { + // Bucket the primitive global ops (like vm.global.i32) so we can + // run over all of them below. + primitiveGlobalOps[globalOp.getStorageSize()].push_back(globalOp); + continue; } if (ordinal.hasValue()) { op.setAttr("ordinal", builder.getI32IntegerAttr(ordinal.getValue())); } } + // Assign byte offset values to primitive globals, ensuring that we meet + // natural alignment requirements on each size type. + int nextGlobalBytesOrdinal = 0; + for (auto sizeGlobalOps : llvm::enumerate(primitiveGlobalOps)) { + size_t storageSize = sizeGlobalOps.index(); + if (sizeGlobalOps.value().empty()) continue; + nextGlobalBytesOrdinal = + llvm::alignTo(nextGlobalBytesOrdinal, storageSize); + for (auto &globalOp : sizeGlobalOps.value()) { + globalOp.setAttr("ordinal", + builder.getI32IntegerAttr(nextGlobalBytesOrdinal)); + nextGlobalBytesOrdinal += storageSize; + } + } + SymbolTable symbolTable(getOperation()); // Convert all global address pseudo-ops to constants referencing the
diff --git a/iree/hal/BUILD b/iree/hal/BUILD index f976cf0..ca34717 100644 --- a/iree/hal/BUILD +++ b/iree/hal/BUILD
@@ -157,7 +157,6 @@ "//iree/base:bitfield", "//iree/base:status", "//iree/base:time", - "@com_google_absl//absl/time", "@com_google_absl//absl/types:span", ], ) @@ -231,7 +230,6 @@ "//iree/base:status", "//iree/base:target_platform", "//iree/base:time", - "@com_google_absl//absl/time", ], ) @@ -262,7 +260,6 @@ "//iree/base:time", "//iree/base:tracing", "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", "@com_google_absl//absl/types:span", ], ) @@ -376,7 +373,6 @@ ":resource", "//iree/base:status", "//iree/base:time", - "@com_google_absl//absl/time", ], )
diff --git a/iree/hal/CMakeLists.txt b/iree/hal/CMakeLists.txt index 079f76e..5d22e3c 100644 --- a/iree/hal/CMakeLists.txt +++ b/iree/hal/CMakeLists.txt
@@ -163,7 +163,6 @@ ::command_buffer ::semaphore absl::span - absl::time iree::base::bitfield iree::base::status iree::base::time @@ -247,7 +246,6 @@ ::executable_cache ::executable_layout ::semaphore - absl::time iree::base::ref_ptr iree::base::status iree::base::target_platform @@ -284,7 +282,6 @@ ::semaphore absl::span absl::synchronization - absl::time iree::base::source_location iree::base::status iree::base::time @@ -432,7 +429,6 @@ "semaphore.h" DEPS ::resource - absl::time iree::base::status iree::base::time PUBLIC
diff --git a/iree/hal/api.cc b/iree/hal/api.cc index 088f055..c5dd130 100644 --- a/iree/hal/api.cc +++ b/iree/hal/api.cc
@@ -1795,11 +1795,11 @@ switch (wait_mode) { case IREE_HAL_WAIT_MODE_ALL: wait_status = - handle->WaitAllSemaphores(semaphore_values, ToAbslTime(deadline_ns)); + handle->WaitAllSemaphores(semaphore_values, Time(deadline_ns)); break; case IREE_HAL_WAIT_MODE_ANY: wait_status = std::move(handle->WaitAnySemaphore(semaphore_values, - ToAbslTime(deadline_ns))) + Time(deadline_ns))) .status(); break; default: @@ -1819,8 +1819,7 @@ iree_hal_device_t* device, iree_hal_wait_mode_t wait_mode, const iree_hal_semaphore_list_t* semaphore_list, iree_duration_t timeout_ns) { - iree_time_t deadline_ns = - FromAbslTime(iree::RelativeTimeoutToDeadline(ToAbslDuration(timeout_ns))); + iree_time_t deadline_ns = iree_relative_timeout_to_deadline_ns(timeout_ns); return iree_hal_device_wait_semaphores_with_deadline( device, wait_mode, semaphore_list, deadline_ns); } @@ -2161,7 +2160,7 @@ IREE_TRACE_SCOPE0("iree_hal_semaphore_wait_with_deadline"); auto* handle = reinterpret_cast<Semaphore*>(semaphore); if (!handle) return IREE_STATUS_INVALID_ARGUMENT; - return ToApiStatus(handle->Wait(value, ToAbslTime(deadline_ns))); + return ToApiStatus(handle->Wait(value, Time(deadline_ns))); } IREE_API_EXPORT iree_status_t IREE_API_CALL @@ -2171,7 +2170,7 @@ IREE_TRACE_SCOPE0("iree_hal_semaphore_wait_with_timeout"); auto* handle = reinterpret_cast<Semaphore*>(semaphore); if (!handle) return IREE_STATUS_INVALID_ARGUMENT; - return ToApiStatus(handle->Wait(value, ToAbslDuration(timeout_ns))); + return ToApiStatus(handle->Wait(value, Duration(timeout_ns))); } } // namespace hal
diff --git a/iree/hal/command_queue.h b/iree/hal/command_queue.h index 8e82e8f..7d068d7 100644 --- a/iree/hal/command_queue.h +++ b/iree/hal/command_queue.h
@@ -18,8 +18,6 @@ #include <cstdint> #include <string> -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "absl/types/span.h" #include "iree/base/bitfield.h" #include "iree/base/status.h" @@ -91,11 +89,11 @@ // // If the command queue has encountered an error during submission at any // point it will be returned here (repeatedly). - virtual Status WaitIdle(absl::Time deadline) = 0; - inline Status WaitIdle(absl::Duration timeout) { - return WaitIdle(RelativeTimeoutToDeadline(timeout)); + virtual Status WaitIdle(Time deadline_ns) = 0; + inline Status WaitIdle(Duration timeout_ns) { + return WaitIdle(RelativeTimeoutToDeadlineNanos(timeout_ns)); } - inline Status WaitIdle() { return WaitIdle(absl::InfiniteFuture()); } + inline Status WaitIdle() { return WaitIdle(InfiniteFuture()); } protected: CommandQueue(std::string name, CommandCategoryBitfield supported_categories)
diff --git a/iree/hal/cts/command_queue_test.cc b/iree/hal/cts/command_queue_test.cc index 94ce5d3..adae1df 100644 --- a/iree/hal/cts/command_queue_test.cc +++ b/iree/hal/cts/command_queue_test.cc
@@ -71,7 +71,7 @@ ASSERT_OK(command_queue->Submit( {{}, {command_buffer.get()}, {{semaphore.get(), 1ull}}})); - ASSERT_OK(semaphore->Wait(1ull, absl::InfiniteFuture())); + ASSERT_OK(semaphore->Wait(1ull, InfiniteFuture())); } // Tests waiting while work is pending/in-flight. @@ -91,12 +91,11 @@ // Work shouldn't start until the wait semaphore reaches its payload value. EXPECT_THAT(signal_semaphore->Query(), IsOkAndHolds(Eq(0ull))); - EXPECT_TRUE( - IsDeadlineExceeded(command_queue->WaitIdle(absl::Milliseconds(100)))); + EXPECT_TRUE(IsDeadlineExceeded(command_queue->WaitIdle(Milliseconds(100)))); // Signal the wait semaphore, work should begin and complete. ASSERT_OK(wait_semaphore->Signal(1ull)); - ASSERT_OK(signal_semaphore->Wait(1ull, absl::InfiniteFuture())); + ASSERT_OK(signal_semaphore->Wait(1ull, InfiniteFuture())); } // Tests using multiple wait and signal semaphores. @@ -120,8 +119,7 @@ EXPECT_THAT(signal_semaphore_1->Query(), IsOkAndHolds(Eq(0ull))); EXPECT_THAT(signal_semaphore_2->Query(), IsOkAndHolds(Eq(0ull))); // Note: This fails with Vulkan timeline semaphore emulation (returns OK) - EXPECT_TRUE( - IsDeadlineExceeded(command_queue->WaitIdle(absl::Milliseconds(100)))); + EXPECT_TRUE(IsDeadlineExceeded(command_queue->WaitIdle(Milliseconds(100)))); // Signal the wait semaphores, work should only begin after each is set. ASSERT_OK(wait_semaphore_1->Signal(1ull));
diff --git a/iree/hal/cts/semaphore_test.cc b/iree/hal/cts/semaphore_test.cc index 873837c..5b212aa 100644 --- a/iree/hal/cts/semaphore_test.cc +++ b/iree/hal/cts/semaphore_test.cc
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <thread> + #include "iree/hal/cts/cts_test_base.h" #include "iree/hal/driver_registry.h" #include "iree/testing/gtest.h" @@ -60,17 +62,17 @@ // Tests waiting on no semaphores. TEST_P(SemaphoreTest, EmptyWait) { - EXPECT_OK(device_->WaitAllSemaphores({}, absl::InfiniteFuture())); + EXPECT_OK(device_->WaitAllSemaphores({}, InfiniteFuture())); } // Tests waiting on a semaphore that has already been signaled. TEST_P(SemaphoreTest, WaitAlreadySignaled) { ASSERT_OK_AND_ASSIGN(auto semaphore, device_->CreateSemaphore(2u)); // Test both previous and current values. - EXPECT_OK(device_->WaitAllSemaphores({{semaphore.get(), 1u}}, - absl::InfiniteFuture())); - EXPECT_OK(device_->WaitAllSemaphores({{semaphore.get(), 2u}}, - absl::InfiniteFuture())); + EXPECT_OK( + device_->WaitAllSemaphores({{semaphore.get(), 1u}}, InfiniteFuture())); + EXPECT_OK( + device_->WaitAllSemaphores({{semaphore.get(), 2u}}, InfiniteFuture())); } // Tests waiting on a semaphore that has not been signaled. @@ -79,7 +81,7 @@ // NOTE: we don't actually block here because otherwise we'd lock up. // Result status is undefined - some backends may return DeadlineExceededError // while others may return success. - device_->WaitAllSemaphores({{semaphore.get(), 3u}}, absl::InfinitePast()) + device_->WaitAllSemaphores({{semaphore.get(), 3u}}, InfinitePast()) .IgnoreError(); } @@ -93,15 +95,12 @@ ASSERT_OK_AND_ASSIGN(auto b2a, device_->CreateSemaphore(0u)); std::thread thread([&]() { // Should advance right past this because the value is already set. - ASSERT_OK( - device_->WaitAllSemaphores({{a2b.get(), 0u}}, absl::InfiniteFuture())); + ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 0u}}, InfiniteFuture())); ASSERT_OK(b2a->Signal(1u)); // Jump ahead. - ASSERT_OK( - device_->WaitAllSemaphores({{a2b.get(), 4u}}, absl::InfiniteFuture())); + ASSERT_OK(device_->WaitAllSemaphores({{a2b.get(), 4u}}, InfiniteFuture())); }); - ASSERT_OK( - device_->WaitAllSemaphores({{b2a.get(), 1u}}, absl::InfiniteFuture())); + ASSERT_OK(device_->WaitAllSemaphores({{b2a.get(), 1u}}, InfiniteFuture())); ASSERT_OK(a2b->Signal(4u)); thread.join(); }
diff --git a/iree/hal/device.h b/iree/hal/device.h index 9bcf1db..4cd3696 100644 --- a/iree/hal/device.h +++ b/iree/hal/device.h
@@ -17,8 +17,6 @@ #include <memory> -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "iree/base/ref_ptr.h" #include "iree/base/status.h" #include "iree/base/target_platform.h" @@ -138,10 +136,11 @@ // having been signaled. Note that a subset of the |semaphores| may have been // signaled and each can be queried to see which ones. virtual Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) = 0; + Time deadline_ns) = 0; inline Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Duration timeout) { - return WaitAllSemaphores(semaphores, RelativeTimeoutToDeadline(timeout)); + Duration timeout_ns) { + return WaitAllSemaphores(semaphores, + RelativeTimeoutToDeadlineNanos(timeout_ns)); } // Blocks the caller until at least one of the |semaphores| reaches or exceeds @@ -156,20 +155,21 @@ // Returns DEADLINE_EXCEEDED if the |deadline| elapses without any semaphores // having been signaled. virtual StatusOr<int> WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) = 0; + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) = 0; inline StatusOr<int> WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Duration timeout) { - return WaitAnySemaphore(semaphores, RelativeTimeoutToDeadline(timeout)); + absl::Span<const SemaphoreValue> semaphores, Duration timeout_ns) { + return WaitAnySemaphore(semaphores, + RelativeTimeoutToDeadlineNanos(timeout_ns)); } // Blocks until all outstanding requests on all queues have been // completed. This is equivalent to having waited on all outstanding // semaphores. - virtual Status WaitIdle(absl::Time deadline) = 0; - inline Status WaitIdle(absl::Duration timeout) { - return WaitIdle(RelativeTimeoutToDeadline(timeout)); + virtual Status WaitIdle(Time deadline_ns) = 0; + inline Status WaitIdle(Duration timeout_ns) { + return WaitIdle(RelativeTimeoutToDeadlineNanos(timeout_ns)); } - inline Status WaitIdle() { return WaitIdle(absl::InfiniteFuture()); } + inline Status WaitIdle() { return WaitIdle(InfiniteFuture()); } protected: explicit Device(DeviceInfo device_info)
diff --git a/iree/hal/device_manager.cc b/iree/hal/device_manager.cc index 2646204..30f3c80 100644 --- a/iree/hal/device_manager.cc +++ b/iree/hal/device_manager.cc
@@ -178,7 +178,7 @@ Status DeviceManager::Submit(Device* device, CommandQueue* command_queue, absl::Span<const SubmissionBatch> batches, - absl::Time deadline) { + Time deadline_ns) { IREE_TRACE_SCOPE0("DeviceManager::Submit"); return command_queue->Submit(batches); } @@ -188,11 +188,11 @@ return OkStatus(); } -Status DeviceManager::WaitIdle(absl::Time deadline) { +Status DeviceManager::WaitIdle(Time deadline_ns) { IREE_TRACE_SCOPE0("DeviceManager::WaitIdle"); absl::MutexLock lock(&device_mutex_); for (const auto& device : devices_) { - RETURN_IF_ERROR(device->WaitIdle(deadline)); + RETURN_IF_ERROR(device->WaitIdle(deadline_ns)); } return OkStatus(); }
diff --git a/iree/hal/device_manager.h b/iree/hal/device_manager.h index faaddd9..492b824 100644 --- a/iree/hal/device_manager.h +++ b/iree/hal/device_manager.h
@@ -18,8 +18,6 @@ #include <vector> #include "absl/synchronization/mutex.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "absl/types/span.h" #include "iree/base/status.h" #include "iree/base/time.h" @@ -164,16 +162,16 @@ // Submissions may be made from any thread. Behavior is undefined // if a thread is performing a WaitIdle while another thread submits work. Status Submit(Device* device, CommandQueue* command_queue, - absl::Span<const SubmissionBatch> batches, absl::Time deadline); + absl::Span<const SubmissionBatch> batches, Time deadline_ns); Status Submit(Device* device, CommandQueue* command_queue, absl::Span<const SubmissionBatch> batches, - absl::Duration timeout) { + Duration timeout_ns) { return Submit(device, command_queue, batches, - RelativeTimeoutToDeadline(timeout)); + RelativeTimeoutToDeadlineNanos(timeout_ns)); } Status Submit(Device* device, CommandQueue* command_queue, absl::Span<const SubmissionBatch> batches) { - return Submit(device, command_queue, batches, absl::InfinitePast()); + return Submit(device, command_queue, batches, InfinitePast()); } // Flushes any requests that are pending in the scheduler and ensures they @@ -192,11 +190,11 @@ // // If any used device has encountered an error during submission at any // point it will be returned here (repeatedly). - Status WaitIdle(absl::Time deadline); - inline Status WaitIdle(absl::Duration timeout) { - return WaitIdle(RelativeTimeoutToDeadline(timeout)); + Status WaitIdle(Time deadline_ns); + inline Status WaitIdle(Duration timeout_ns) { + return WaitIdle(RelativeTimeoutToDeadlineNanos(timeout_ns)); } - inline Status WaitIdle() { return WaitIdle(absl::InfiniteFuture()); } + inline Status WaitIdle() { return WaitIdle(InfiniteFuture()); } private: mutable absl::Mutex device_mutex_;
diff --git a/iree/hal/dylib/BUILD b/iree/hal/dylib/BUILD index 25c08ea..fc3ccb9 100644 --- a/iree/hal/dylib/BUILD +++ b/iree/hal/dylib/BUILD
@@ -60,7 +60,6 @@ srcs = ["dylib_executable.cc"], hdrs = ["dylib_executable.h"], deps = [ - ":memref_runtime", "//iree/base:dynamic_library", "//iree/base:file_io", "//iree/base:status", @@ -89,10 +88,3 @@ "//iree/hal:executable_format", ], ) - -cc_library( - name = "memref_runtime", - hdrs = [ - "memref_runtime.h", - ], -)
diff --git a/iree/hal/dylib/CMakeLists.txt b/iree/hal/dylib/CMakeLists.txt index 7644d92..d720435 100644 --- a/iree/hal/dylib/CMakeLists.txt +++ b/iree/hal/dylib/CMakeLists.txt
@@ -65,7 +65,6 @@ SRCS "dylib_executable.cc" DEPS - ::memref_runtime absl::inlined_vector absl::span flatbuffers @@ -97,11 +96,3 @@ iree::hal::executable_format PUBLIC ) - -iree_cc_library( - NAME - memref_runtime - HDRS - "memref_runtime.h" - PUBLIC -)
diff --git a/iree/hal/dylib/dylib_executable.cc b/iree/hal/dylib/dylib_executable.cc index e06bb19..e58a003 100644 --- a/iree/hal/dylib/dylib_executable.cc +++ b/iree/hal/dylib/dylib_executable.cc
@@ -17,7 +17,6 @@ #include "flatbuffers/flatbuffers.h" #include "iree/base/file_io.h" #include "iree/base/tracing.h" -#include "iree/hal/dylib/memref_runtime.h" #include "iree/schemas/dylib_executable_def_generated.h" namespace iree { @@ -96,15 +95,9 @@ struct DyLibDispatchState : public HostExecutable::DispatchState { DyLibDispatchState() = default; - ~DyLibDispatchState() override { - for (int i = 0; i < descriptors.size(); ++i) { - freeUnrankedDescriptor(descriptors[i]); - } - } - void* entry_function = nullptr; - absl::InlinedVector<UnrankedMemRefType<uint32_t>*, 4> descriptors; absl::InlinedVector<void*, 4> args; + absl::InlinedVector<int64_t, 4> push_constant; }; StatusOr<ref_ptr<HostExecutable::DispatchState>> @@ -127,17 +120,14 @@ MemoryAccessBitfield::kWrite, io_binding.offset, io_binding.length)); auto data = memory.mutable_data(); - auto descriptor = allocUnrankedDescriptor<uint32_t>(data); - dispatch_state->descriptors.push_back(descriptor); - dispatch_state->args.push_back(&descriptor->descriptor); + + dispatch_state->args.push_back(data); } } - - auto push_constants_descriptor = allocUnrankedDescriptor<uint32_t>( - const_cast<uint32_t*>(params.push_constants->values.data()), - {static_cast<int64_t>(params.push_constants->values.size())}); - dispatch_state->descriptors.push_back(push_constants_descriptor); - dispatch_state->args.push_back(&push_constants_descriptor->descriptor); + // TODO(ataei): Consider moving this casting to codegen side ?! + for (int i = 0; i < params.push_constants->values.size(); ++i) { + dispatch_state->push_constant.push_back(params.push_constants->values[i]); + } return std::move(dispatch_state); } @@ -147,8 +137,10 @@ IREE_TRACE_SCOPE0("DyLibExecutable::DispatchTile"); auto* dispatch_state = static_cast<DyLibDispatchState*>(state); - auto entry_function = (void (*)(void**))dispatch_state->entry_function; - entry_function(dispatch_state->args.data()); + auto entry_function = + (void (*)(void**, int64_t*))dispatch_state->entry_function; + entry_function(dispatch_state->args.data(), + dispatch_state->push_constant.data()); return OkStatus(); }
diff --git a/iree/hal/dylib/memref_runtime.h b/iree/hal/dylib/memref_runtime.h deleted file mode 100644 index 50d3987..0000000 --- a/iree/hal/dylib/memref_runtime.h +++ /dev/null
@@ -1,177 +0,0 @@ -// Copyright 2020 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_HAL_DYLIB_MEMREF_RUNTIME_H_ -#define IREE_HAL_DYLIB_MEMREF_RUNTIME_H_ - -#include <assert.h> - -#include <cstdint> -#include <vector> - -namespace iree { -namespace hal { -namespace dylib { - -template <int N> -void dropFront(int64_t arr[N], int64_t *res) { - for (unsigned i = 1; i < N; ++i) *(res + i - 1) = arr[i]; -} - -/// StridedMemRef descriptor type with static rank. -template <typename T, int N> -struct StridedMemRefType { - T *basePtr; - T *data; - int64_t offset; - int64_t sizes[N]; - int64_t strides[N]; - // This operator[] is extremely slow and only for sugaring purposes. - StridedMemRefType<T, N - 1> operator[](int64_t idx) { - StridedMemRefType<T, N - 1> res; - res.basePtr = basePtr; - res.data = data; - res.offset = offset + idx * strides[0]; - dropFront<N>(sizes, res.sizes); - dropFront<N>(strides, res.strides); - return res; - } -}; - -/// StridedMemRef descriptor type specialized for rank 1. -template <typename T> -struct StridedMemRefType<T, 1> { - T *basePtr; - T *data; - int64_t offset; - int64_t sizes[1]; - int64_t strides[1]; - T &operator[](int64_t idx) { return *(data + offset + idx * strides[0]); } -}; - -/// StridedMemRef descriptor type specialized for rank 0. -template <typename T> -struct StridedMemRefType<T, 0> { - T *basePtr; - T *data; - int64_t offset; -}; - -// Unranked MemRef -template <typename T> -struct UnrankedMemRefType { - int64_t rank; - void *descriptor; -}; - -// Given a shape with sizes greater than 0 along all dimensions, -// returns the distance, in number of elements, between a slice in a dimension -// and the next slice in the same dimension. -// e.g. shape[3, 4, 5] -> strides[20, 5, 1] -inline std::vector<int64_t> makeStrides(const std::vector<int64_t> &shape) { - std::vector<int64_t> tmp; - if (shape.empty()) return tmp; - tmp.reserve(shape.size()); - int64_t running = 1; - for (auto rit = shape.rbegin(), reit = shape.rend(); rit != reit; ++rit) { - assert(*rit > 0 && - "size must be greater than 0 along all dimensions of shape"); - tmp.push_back(running); - running *= *rit; - } - return std::vector<int64_t>(tmp.rbegin(), tmp.rend()); -} - -// Mallocs a StridedMemRefDescriptor<T, N>* that matches the MLIR ABI. -// This is an implementation detail that is kept in sync with MLIR codegen -// conventions. -template <typename T, int N> -StridedMemRefType<T, N> *makeStridedMemRefDescriptor( - void *ptr, const std::vector<int64_t> &shape) { - StridedMemRefType<T, N> *descriptor = static_cast<StridedMemRefType<T, N> *>( - malloc(sizeof(StridedMemRefType<T, N>))); - descriptor->basePtr = static_cast<T *>(ptr); - descriptor->data = static_cast<T *>(ptr); - descriptor->offset = 0; - std::copy(shape.begin(), shape.end(), descriptor->sizes); - auto strides = makeStrides(shape); - std::copy(strides.begin(), strides.end(), descriptor->strides); - return descriptor; -} - -// Mallocs a StridedMemRefDescriptor<T, 0>* (i.e. a pointer to scalar) that -// matches the MLIR ABI. This is an implementation detail that is kept in sync -// with MLIR codegen conventions. -template <typename T> -StridedMemRefType<T, 0> *makeStridedMemRefDescriptor( - void *ptr, const std::vector<int64_t> &shape) { - StridedMemRefType<T, 0> *descriptor = static_cast<StridedMemRefType<T, 0> *>( - malloc(sizeof(StridedMemRefType<T, 0>))); - descriptor->basePtr = static_cast<T *>(ptr); - descriptor->data = static_cast<T *>(ptr); - descriptor->offset = 0; - return descriptor; -} - -// Mallocs an UnrankedMemRefType<T>* that contains a ranked -// StridedMemRefDescriptor<T, Rank>* and matches the MLIR ABI. This is an -// implementation detail that is kept in sync with MLIR codegen conventions. -template <typename T> -UnrankedMemRefType<T> *allocUnrankedDescriptor( - void *data, const std::vector<int64_t> &shape) { - UnrankedMemRefType<T> *res = static_cast<UnrankedMemRefType<T> *>( - malloc(sizeof(UnrankedMemRefType<T>))); - res->rank = shape.size(); - if (res->rank == 0) - res->descriptor = makeStridedMemRefDescriptor<T>(data, shape); - else if (res->rank == 1) - res->descriptor = makeStridedMemRefDescriptor<T, 1>(data, shape); - else if (res->rank == 2) - res->descriptor = makeStridedMemRefDescriptor<T, 2>(data, shape); - else if (res->rank == 3) - res->descriptor = makeStridedMemRefDescriptor<T, 3>(data, shape); - else if (res->rank == 4) - res->descriptor = makeStridedMemRefDescriptor<T, 4>(data, shape); - else if (res->rank == 5) - res->descriptor = makeStridedMemRefDescriptor<T, 5>(data, shape); - else if (res->rank == 6) - res->descriptor = makeStridedMemRefDescriptor<T, 6>(data, shape); - else - assert(false && "Unsupported 6+D memref descriptor"); - return res; -} - -// Shape and strides aren't used in the generated code (yet). -// TODO(ataei): Delete this version once we can pass shapes. -template <typename T> -UnrankedMemRefType<T> *allocUnrankedDescriptor(void *data) { - UnrankedMemRefType<T> *res = static_cast<UnrankedMemRefType<T> *>( - malloc(sizeof(UnrankedMemRefType<T>))); - res->descriptor = makeStridedMemRefDescriptor<T>(data, {}); - return res; -} - -// Frees an UnrankedMemRefType<T>* -template <typename T> -void freeUnrankedDescriptor(UnrankedMemRefType<T> *desc) { - free(desc->descriptor); - free(desc); -} - -} // namespace dylib -} // namespace hal -} // namespace iree - -#endif // IREE_HAL_DYLIB_MEMREF_RUNTIME_H_
diff --git a/iree/hal/host/BUILD b/iree/hal/host/BUILD index 3480cc4..9e25ffa 100644 --- a/iree/hal/host/BUILD +++ b/iree/hal/host/BUILD
@@ -41,10 +41,10 @@ srcs = ["condvar_semaphore_test.cc"], deps = [ ":condvar_semaphore", + "//iree/base:api", "//iree/base:status", "//iree/base:status_matchers", "//iree/testing:gtest_main", - "@com_google_absl//absl/time", ], )
diff --git a/iree/hal/host/CMakeLists.txt b/iree/hal/host/CMakeLists.txt index 06383f3..8b01d00 100644 --- a/iree/hal/host/CMakeLists.txt +++ b/iree/hal/host/CMakeLists.txt
@@ -39,7 +39,7 @@ "condvar_semaphore_test.cc" DEPS ::condvar_semaphore - absl::time + iree::base::api iree::base::status iree::base::status_matchers iree::testing::gtest_main
diff --git a/iree/hal/host/condvar_semaphore.cc b/iree/hal/host/condvar_semaphore.cc index 2a3fb0c..1f79a25 100644 --- a/iree/hal/host/condvar_semaphore.cc +++ b/iree/hal/host/condvar_semaphore.cc
@@ -60,7 +60,7 @@ // static Status CondVarSemaphore::WaitForSemaphores( absl::Span<const SemaphoreValue> semaphores, bool wait_all, - absl::Time deadline) { + Time deadline_ns) { IREE_TRACE_SCOPE0("CondVarSemaphore::WaitForSemaphores"); // Some of the semaphores may already be signaled; we only need to wait for @@ -94,7 +94,7 @@ semaphore_value->second; }, &semaphore_value), - deadline)) { + absl::FromUnixNanos(static_cast<int64_t>(deadline_ns)))) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline exceeded waiting for semaphores"; } @@ -106,8 +106,8 @@ return OkStatus(); } -Status CondVarSemaphore::Wait(uint64_t value, absl::Time deadline) { - return WaitForSemaphores({{this, value}}, /*wait_all=*/true, deadline); +Status CondVarSemaphore::Wait(uint64_t value, Time deadline_ns) { + return WaitForSemaphores({{this, value}}, /*wait_all=*/true, deadline_ns); } } // namespace host
diff --git a/iree/hal/host/condvar_semaphore.h b/iree/hal/host/condvar_semaphore.h index daf3825..44dd541 100644 --- a/iree/hal/host/condvar_semaphore.h +++ b/iree/hal/host/condvar_semaphore.h
@@ -37,7 +37,7 @@ // Waits for one or more (or all) semaphores to reach or exceed the given // values. static Status WaitForSemaphores(absl::Span<const SemaphoreValue> semaphores, - bool wait_all, absl::Time deadline); + bool wait_all, Time deadline_ns); explicit CondVarSemaphore(uint64_t initial_value); ~CondVarSemaphore() override; @@ -46,7 +46,7 @@ Status Signal(uint64_t value) override; void Fail(Status status) override; - Status Wait(uint64_t value, absl::Time deadline) override; + Status Wait(uint64_t value, Time deadline_ns) override; private: // The mutex is not required to query the value; this lets us quickly check if
diff --git a/iree/hal/host/condvar_semaphore_test.cc b/iree/hal/host/condvar_semaphore_test.cc index c3614f5..9846f29 100644 --- a/iree/hal/host/condvar_semaphore_test.cc +++ b/iree/hal/host/condvar_semaphore_test.cc
@@ -17,7 +17,6 @@ #include <cstdint> #include <thread> // NOLINT -#include "absl/time/time.h" #include "iree/base/status.h" #include "iree/base/status_matchers.h" #include "iree/testing/gtest.h" @@ -73,7 +72,7 @@ // Tests waiting on no semaphores. TEST(CondVarSemaphoreTest, EmptyWait) { EXPECT_OK(CondVarSemaphore::WaitForSemaphores({}, /*wait_all=*/true, - absl::InfiniteFuture())); + InfiniteFuture())); } // Tests waiting on a semaphore that has already been signaled. @@ -81,9 +80,9 @@ CondVarSemaphore semaphore(2u); // Test both previous and current values. EXPECT_OK(CondVarSemaphore::WaitForSemaphores( - {{&semaphore, 1u}}, /*wait_all=*/true, absl::InfiniteFuture())); + {{&semaphore, 1u}}, /*wait_all=*/true, InfiniteFuture())); EXPECT_OK(CondVarSemaphore::WaitForSemaphores( - {{&semaphore, 2u}}, /*wait_all=*/true, absl::InfiniteFuture())); + {{&semaphore, 2u}}, /*wait_all=*/true, InfiniteFuture())); } // Tests waiting on a semaphore that has not been signaled. @@ -91,7 +90,7 @@ CondVarSemaphore semaphore(2u); // NOTE: we don't actually block here because otherwise we'd lock up. EXPECT_TRUE(IsDeadlineExceeded(CondVarSemaphore::WaitForSemaphores( - {{&semaphore, 3u}}, /*wait_all=*/true, absl::InfinitePast()))); + {{&semaphore, 3u}}, /*wait_all=*/true, InfinitePast()))); } // Tests waiting on a failed semaphore (it should return the error on the @@ -100,7 +99,7 @@ CondVarSemaphore semaphore(2u); semaphore.Fail(UnknownErrorBuilder(IREE_LOC)); EXPECT_TRUE(IsUnknown(CondVarSemaphore::WaitForSemaphores( - {{&semaphore, 2u}}, /*wait_all=*/true, absl::InfinitePast()))); + {{&semaphore, 2u}}, /*wait_all=*/true, InfinitePast()))); } // Tests threading behavior by ping-ponging between the test main thread and @@ -111,14 +110,14 @@ std::thread thread([&]() { // Should advance right past this because the value is already set. ASSERT_OK(CondVarSemaphore::WaitForSemaphores( - {{&a2b, 0u}}, /*wait_all=*/true, absl::InfiniteFuture())); + {{&a2b, 0u}}, /*wait_all=*/true, InfiniteFuture())); ASSERT_OK(b2a.Signal(1u)); // Jump ahead. ASSERT_OK(CondVarSemaphore::WaitForSemaphores( - {{&a2b, 4u}}, /*wait_all=*/true, absl::InfiniteFuture())); + {{&a2b, 4u}}, /*wait_all=*/true, InfiniteFuture())); }); ASSERT_OK(CondVarSemaphore::WaitForSemaphores({{&b2a, 1u}}, /*wait_all=*/true, - absl::InfiniteFuture())); + InfiniteFuture())); ASSERT_OK(a2b.Signal(4u)); thread.join(); } @@ -131,10 +130,10 @@ std::thread thread([&]() { ASSERT_OK(b2a.Signal(1u)); got_failure = IsUnknown(CondVarSemaphore::WaitForSemaphores( - {{&a2b, 1u}}, /*wait_all=*/true, absl::InfiniteFuture())); + {{&a2b, 1u}}, /*wait_all=*/true, InfiniteFuture())); }); ASSERT_OK(CondVarSemaphore::WaitForSemaphores({{&b2a, 1u}}, /*wait_all=*/true, - absl::InfiniteFuture())); + InfiniteFuture())); a2b.Fail(UnknownErrorBuilder(IREE_LOC)); thread.join(); ASSERT_TRUE(got_failure);
diff --git a/iree/hal/host/host_local_device.cc b/iree/hal/host/host_local_device.cc index 5638b9a..1ca3c54 100644 --- a/iree/hal/host/host_local_device.cc +++ b/iree/hal/host/host_local_device.cc
@@ -77,20 +77,20 @@ } Status HostLocalDevice::WaitAllSemaphores( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { IREE_TRACE_SCOPE0("HostLocalDevice::WaitAllSemaphores"); - return scheduling_model_->WaitAllSemaphores(semaphores, deadline); + return scheduling_model_->WaitAllSemaphores(semaphores, deadline_ns); } StatusOr<int> HostLocalDevice::WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { IREE_TRACE_SCOPE0("HostLocalDevice::WaitAnySemaphore"); - return scheduling_model_->WaitAnySemaphore(semaphores, deadline); + return scheduling_model_->WaitAnySemaphore(semaphores, deadline_ns); } -Status HostLocalDevice::WaitIdle(absl::Time deadline) { +Status HostLocalDevice::WaitIdle(Time deadline_ns) { IREE_TRACE_SCOPE0("HostLocalDevice::WaitIdle"); - return scheduling_model_->WaitIdle(deadline); + return scheduling_model_->WaitIdle(deadline_ns); } } // namespace host
diff --git a/iree/hal/host/host_local_device.h b/iree/hal/host/host_local_device.h index de00d5f..8fc3b31 100644 --- a/iree/hal/host/host_local_device.h +++ b/iree/hal/host/host_local_device.h
@@ -63,11 +63,11 @@ StatusOr<ref_ptr<Semaphore>> CreateSemaphore(uint64_t initial_value) override; Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; + Time deadline_ns) override; StatusOr<int> WaitAnySemaphore(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; + Time deadline_ns) override; - Status WaitIdle(absl::Time deadline) override; + Status WaitIdle(Time deadline_ns) override; protected: explicit HostLocalDevice(DeviceInfo device_info,
diff --git a/iree/hal/host/scheduling_model.h b/iree/hal/host/scheduling_model.h index df56b51..38771ec 100644 --- a/iree/hal/host/scheduling_model.h +++ b/iree/hal/host/scheduling_model.h
@@ -71,7 +71,7 @@ // having been signaled. Note that a subset of the |semaphores| may have been // signaled and each can be queried to see which ones. virtual Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) = 0; + Time deadline_ns) = 0; // Blocks the caller until at least one of the |semaphores| reaches or exceeds // the specified payload value or the |deadline| elapses. All |semaphores| @@ -85,12 +85,12 @@ // Returns DEADLINE_EXCEEDED if the |deadline| elapses without any semaphores // having been signaled. virtual StatusOr<int> WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) = 0; + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) = 0; // Blocks until all outstanding requests on all queues have been // completed. This is equivalent to having waited on all outstanding // semaphores. - virtual Status WaitIdle(absl::Time deadline) = 0; + virtual Status WaitIdle(Time deadline_ns) = 0; }; } // namespace host
diff --git a/iree/hal/host/serial/BUILD b/iree/hal/host/serial/BUILD index 04281e4..b99ae45 100644 --- a/iree/hal/host/serial/BUILD +++ b/iree/hal/host/serial/BUILD
@@ -50,7 +50,6 @@ "//iree/hal/testing:mock_command_queue", "//iree/testing:gtest_main", "@com_google_absl//absl/memory", - "@com_google_absl//absl/time", ], )
diff --git a/iree/hal/host/serial/CMakeLists.txt b/iree/hal/host/serial/CMakeLists.txt index 93b5c73..954f988 100644 --- a/iree/hal/host/serial/CMakeLists.txt +++ b/iree/hal/host/serial/CMakeLists.txt
@@ -40,7 +40,6 @@ DEPS ::async_command_queue absl::memory - absl::time iree::base::status iree::base::status_matchers iree::base::time
diff --git a/iree/hal/host/serial/async_command_queue.cc b/iree/hal/host/serial/async_command_queue.cc index 8b789ca..e1b8fac 100644 --- a/iree/hal/host/serial/async_command_queue.cc +++ b/iree/hal/host/serial/async_command_queue.cc
@@ -103,7 +103,7 @@ return submission_queue_.Enqueue(batches); } -Status AsyncCommandQueue::WaitIdle(absl::Time deadline) { +Status AsyncCommandQueue::WaitIdle(Time deadline_ns) { IREE_TRACE_SCOPE0("AsyncCommandQueue::WaitIdle"); // Wait until the deadline, the thread exits, or there are no more pending @@ -115,7 +115,7 @@ return queue->empty() || !queue->permanent_error().ok(); }, &submission_queue_), - deadline)) { + absl::FromUnixNanos(static_cast<int64_t>(deadline_ns)))) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline exceeded waiting for submission thread to go idle"; }
diff --git a/iree/hal/host/serial/async_command_queue.h b/iree/hal/host/serial/async_command_queue.h index 76d4797..e474c23 100644 --- a/iree/hal/host/serial/async_command_queue.h +++ b/iree/hal/host/serial/async_command_queue.h
@@ -47,7 +47,7 @@ Status Submit(absl::Span<const SubmissionBatch> batches) override; - Status WaitIdle(absl::Time deadline) override; + Status WaitIdle(Time deadline_ns) override; private: // Thread entry point for the async worker thread.
diff --git a/iree/hal/host/serial/async_command_queue_test.cc b/iree/hal/host/serial/async_command_queue_test.cc index 06ca4ae..5aca399 100644 --- a/iree/hal/host/serial/async_command_queue_test.cc +++ b/iree/hal/host/serial/async_command_queue_test.cc
@@ -14,13 +14,13 @@ #include "iree/hal/host/serial/async_command_queue.h" +#include <chrono> #include <cstdint> #include <memory> +#include <thread> #include <utility> #include "absl/memory/memory.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "iree/base/status.h" #include "iree/base/status_matchers.h" #include "iree/base/time.h" @@ -40,6 +40,13 @@ using testing::MockCommandBuffer; using testing::MockCommandQueue; +// Suspends execution of the calling thread for the given |duration_ms|. +// Depending on platform this may have an extremely coarse resolution (upwards +// of several to dozens of milliseconds). +inline void Sleep(std::chrono::milliseconds duration_ms) { + std::this_thread::sleep_for(duration_ms); +} + struct AsyncCommandQueueTest : public ::testing::Test { MockCommandQueue* mock_target_queue; std::unique_ptr<CommandQueue> command_queue; @@ -75,7 +82,7 @@ CondVarSemaphore semaphore(0ull); ASSERT_OK( command_queue->Submit({{}, {cmd_buffer.get()}, {{&semaphore, 1ull}}})); - ASSERT_OK(semaphore.Wait(1ull, absl::InfiniteFuture())); + ASSERT_OK(semaphore.Wait(1ull, InfiniteFuture())); } // Tests that failure is propagated along the fence from the target queue. @@ -92,7 +99,7 @@ CondVarSemaphore semaphore(0ull); ASSERT_OK( command_queue->Submit({{}, {cmd_buffer.get()}, {{&semaphore, 1ull}}})); - EXPECT_TRUE(IsDataLoss(semaphore.Wait(1ull, absl::InfiniteFuture()))); + EXPECT_TRUE(IsDataLoss(semaphore.Wait(1ull, InfiniteFuture()))); } // Tests that waiting for idle is a no-op when nothing is queued. @@ -109,7 +116,7 @@ EXPECT_CALL(*mock_target_queue, Submit(_)) .WillOnce([](absl::Span<const SubmissionBatch> batches) { - Sleep(absl::Milliseconds(100)); + Sleep(std::chrono::milliseconds(100)); return OkStatus(); }); CondVarSemaphore semaphore(0ull); @@ -131,7 +138,7 @@ EXPECT_CALL(*mock_target_queue, Submit(_)) .WillRepeatedly([](absl::Span<const SubmissionBatch> batches) { - Sleep(absl::Milliseconds(100)); + Sleep(std::chrono::milliseconds(100)); return OkStatus(); }); @@ -164,7 +171,7 @@ // Fail. EXPECT_CALL(*mock_target_queue, Submit(_)) .WillOnce([](absl::Span<const SubmissionBatch> batches) { - Sleep(absl::Milliseconds(100)); + Sleep(std::chrono::milliseconds(100)); return DataLossErrorBuilder(IREE_LOC); }); auto cmd_buffer_0 = make_ref<MockCommandBuffer>(CommandBufferMode::kOneShot, @@ -172,7 +179,7 @@ CondVarSemaphore semaphore_0(0ull); ASSERT_OK( command_queue->Submit({{}, {cmd_buffer_0.get()}, {{&semaphore_0, 1u}}})); - EXPECT_TRUE(IsDataLoss(semaphore_0.Wait(1ull, absl::InfiniteFuture()))); + EXPECT_TRUE(IsDataLoss(semaphore_0.Wait(1ull, InfiniteFuture()))); // Future flushes/waits/etc should also fail. EXPECT_TRUE(IsDataLoss(command_queue->WaitIdle())); @@ -193,7 +200,7 @@ // Fail. EXPECT_CALL(*mock_target_queue, Submit(_)) .WillOnce([](absl::Span<const SubmissionBatch> batches) { - Sleep(absl::Milliseconds(100)); + Sleep(std::chrono::milliseconds(100)); return DataLossErrorBuilder(IREE_LOC); }); @@ -211,8 +218,8 @@ EXPECT_TRUE(IsDataLoss(command_queue->WaitIdle())); - EXPECT_TRUE(IsDataLoss(semaphore_0.Wait(1ull, absl::InfiniteFuture()))); - EXPECT_TRUE(IsDataLoss(semaphore_1.Wait(1ull, absl::InfiniteFuture()))); + EXPECT_TRUE(IsDataLoss(semaphore_0.Wait(1ull, InfiniteFuture()))); + EXPECT_TRUE(IsDataLoss(semaphore_1.Wait(1ull, InfiniteFuture()))); // Future flushes/waits/etc should also fail. EXPECT_TRUE(IsDataLoss(command_queue->WaitIdle()));
diff --git a/iree/hal/host/serial/serial_scheduling_model.cc b/iree/hal/host/serial/serial_scheduling_model.cc index e343cd6..41cbd9f 100644 --- a/iree/hal/host/serial/serial_scheduling_model.cc +++ b/iree/hal/host/serial/serial_scheduling_model.cc
@@ -58,7 +58,7 @@ return OkStatus(); } - Status WaitIdle(absl::Time deadline) override { + Status WaitIdle(Time deadline_ns) override { // No-op. return OkStatus(); } @@ -110,20 +110,20 @@ } Status SerialSchedulingModel::WaitAllSemaphores( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { return CondVarSemaphore::WaitForSemaphores(semaphores, /*wait_all=*/true, - deadline); + deadline_ns); } StatusOr<int> SerialSchedulingModel::WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { return CondVarSemaphore::WaitForSemaphores(semaphores, /*wait_all=*/false, - deadline); + deadline_ns); } -Status SerialSchedulingModel::WaitIdle(absl::Time deadline) { +Status SerialSchedulingModel::WaitIdle(Time deadline_ns) { for (auto& command_queue : command_queues_) { - RETURN_IF_ERROR(command_queue->WaitIdle(deadline)); + RETURN_IF_ERROR(command_queue->WaitIdle(deadline_ns)); } return OkStatus(); }
diff --git a/iree/hal/host/serial/serial_scheduling_model.h b/iree/hal/host/serial/serial_scheduling_model.h index 6aec21f..b065025 100644 --- a/iree/hal/host/serial/serial_scheduling_model.h +++ b/iree/hal/host/serial/serial_scheduling_model.h
@@ -50,10 +50,10 @@ StatusOr<ref_ptr<Semaphore>> CreateSemaphore(uint64_t initial_value) override; Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; + Time deadline_ns) override; StatusOr<int> WaitAnySemaphore(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; - Status WaitIdle(absl::Time deadline) override; + Time deadline_ns) override; + Status WaitIdle(Time deadline_ns) override; private: mutable absl::InlinedVector<std::unique_ptr<CommandQueue>, 4> command_queues_;
diff --git a/iree/hal/llvmjit/BUILD b/iree/hal/llvmjit/BUILD index 088bb8b..3ebd609 100644 --- a/iree/hal/llvmjit/BUILD +++ b/iree/hal/llvmjit/BUILD
@@ -64,7 +64,6 @@ srcs = ["llvmjit_executable.cc"], hdrs = ["llvmjit_executable.h"], deps = [ - ":memref_runtime", "//iree/base:status", "//iree/base:tracing", "//iree/hal:buffer", @@ -95,10 +94,3 @@ "//iree/hal:executable_format", ], ) - -cc_library( - name = "memref_runtime", - hdrs = [ - "memref_runtime.h", - ], -)
diff --git a/iree/hal/llvmjit/CMakeLists.txt b/iree/hal/llvmjit/CMakeLists.txt index 8418745..ca40941 100644 --- a/iree/hal/llvmjit/CMakeLists.txt +++ b/iree/hal/llvmjit/CMakeLists.txt
@@ -68,7 +68,6 @@ SRCS "llvmjit_executable.cc" DEPS - ::memref_runtime LLVMAsmParser LLVMCore LLVMOrcJIT @@ -102,11 +101,3 @@ iree::hal::executable_format PUBLIC ) - -iree_cc_library( - NAME - memref_runtime - HDRS - "memref_runtime.h" - PUBLIC -)
diff --git a/iree/hal/llvmjit/llvmjit_executable.cc b/iree/hal/llvmjit/llvmjit_executable.cc index 1596b9e..7d26ccd 100644 --- a/iree/hal/llvmjit/llvmjit_executable.cc +++ b/iree/hal/llvmjit/llvmjit_executable.cc
@@ -21,7 +21,6 @@ #include "iree/base/tracing.h" #include "iree/hal/buffer.h" #include "iree/hal/executable.h" -#include "iree/hal/llvmjit/memref_runtime.h" #include "iree/schemas/llvmir_executable_def_generated.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -82,13 +81,11 @@ make_ref<LLVMJITExecutable>(spec, std::move(ll_jit), allow_aliasing_data); for (const auto func_name : *entry_points) { - auto func_symbol = - executable->ll_jit_->lookup("invoke_" + func_name->str()); + auto func_symbol = executable->ll_jit_->lookup(func_name->str()); if (!func_symbol) { return NotFoundErrorBuilder(IREE_LOC) << "Can't JIT compile function : " << func_name; } - // Map function to its invoke_ symbol. executable->symbols_.push_back(func_symbol.get()); } @@ -111,15 +108,10 @@ struct LLVMJITDispatchState : public HostExecutable::DispatchState { LLVMJITDispatchState() = default; - ~LLVMJITDispatchState() override { - for (int i = 0; i < descriptors.size(); ++i) { - freeUnrankedDescriptor(descriptors[i]); - } - } llvm::JITEvaluatedSymbol symbol; - llvm::SmallVector<UnrankedMemRefType<uint32_t>*, 4> descriptors; llvm::SmallVector<void*, 4> args; + llvm::SmallVector<int64_t, 4> push_constant; }; StatusOr<ref_ptr<HostExecutable::DispatchState>> @@ -142,17 +134,13 @@ MemoryAccessBitfield::kWrite, io_binding.offset, io_binding.length)); auto data = memory.mutable_data(); - auto descriptor = allocUnrankedDescriptor<uint32_t>(data); - dispatch_state->descriptors.push_back(descriptor); - dispatch_state->args.push_back(&descriptor->descriptor); + dispatch_state->args.push_back(data); } } - - auto push_constants_descriptor = allocUnrankedDescriptor<uint32_t>( - const_cast<uint32_t*>(params.push_constants->values.data()), - {static_cast<int64_t>(params.push_constants->values.size())}); - dispatch_state->descriptors.push_back(push_constants_descriptor); - dispatch_state->args.push_back(&push_constants_descriptor->descriptor); + // TODO(ataei): Consider moving this casting to codegen side ?! + for (int i = 0; i < params.push_constants->values.size(); ++i) { + dispatch_state->push_constant.push_back(params.push_constants->values[i]); + } return std::move(dispatch_state); } @@ -162,8 +150,9 @@ IREE_TRACE_SCOPE0("LLVMJITExecutable::DispatchTile"); auto* dispatch_state = static_cast<LLVMJITDispatchState*>(state); - auto func_ptr = (void (*)(void**))dispatch_state->symbol.getAddress(); - func_ptr(dispatch_state->args.data()); + auto func_ptr = + (void (*)(void**, int64_t*))dispatch_state->symbol.getAddress(); + func_ptr(dispatch_state->args.data(), dispatch_state->push_constant.data()); return OkStatus(); }
diff --git a/iree/hal/llvmjit/memref_runtime.h b/iree/hal/llvmjit/memref_runtime.h deleted file mode 100644 index 6b94410..0000000 --- a/iree/hal/llvmjit/memref_runtime.h +++ /dev/null
@@ -1,177 +0,0 @@ -// Copyright 2020 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_HAL_LLVMJIT_LLVMJIT_MEMREF_RUNTIME_H_ -#define IREE_HAL_LLVMJIT_LLVMJIT_MEMREF_RUNTIME_H_ - -#include <assert.h> - -#include <cstdint> -#include <vector> - -namespace iree { -namespace hal { -namespace llvmjit { - -template <int N> -void dropFront(int64_t arr[N], int64_t *res) { - for (unsigned i = 1; i < N; ++i) *(res + i - 1) = arr[i]; -} - -/// StridedMemRef descriptor type with static rank. -template <typename T, int N> -struct StridedMemRefType { - T *basePtr; - T *data; - int64_t offset; - int64_t sizes[N]; - int64_t strides[N]; - // This operator[] is extremely slow and only for sugaring purposes. - StridedMemRefType<T, N - 1> operator[](int64_t idx) { - StridedMemRefType<T, N - 1> res; - res.basePtr = basePtr; - res.data = data; - res.offset = offset + idx * strides[0]; - dropFront<N>(sizes, res.sizes); - dropFront<N>(strides, res.strides); - return res; - } -}; - -/// StridedMemRef descriptor type specialized for rank 1. -template <typename T> -struct StridedMemRefType<T, 1> { - T *basePtr; - T *data; - int64_t offset; - int64_t sizes[1]; - int64_t strides[1]; - T &operator[](int64_t idx) { return *(data + offset + idx * strides[0]); } -}; - -/// StridedMemRef descriptor type specialized for rank 0. -template <typename T> -struct StridedMemRefType<T, 0> { - T *basePtr; - T *data; - int64_t offset; -}; - -// Unranked MemRef -template <typename T> -struct UnrankedMemRefType { - int64_t rank; - void *descriptor; -}; - -// Given a shape with sizes greater than 0 along all dimensions, -// returns the distance, in number of elements, between a slice in a dimension -// and the next slice in the same dimension. -// e.g. shape[3, 4, 5] -> strides[20, 5, 1] -inline std::vector<int64_t> makeStrides(const std::vector<int64_t> &shape) { - std::vector<int64_t> tmp; - if (shape.empty()) return tmp; - tmp.reserve(shape.size()); - int64_t running = 1; - for (auto rit = shape.rbegin(), reit = shape.rend(); rit != reit; ++rit) { - assert(*rit > 0 && - "size must be greater than 0 along all dimensions of shape"); - tmp.push_back(running); - running *= *rit; - } - return std::vector<int64_t>(tmp.rbegin(), tmp.rend()); -} - -// Mallocs a StridedMemRefDescriptor<T, N>* that matches the MLIR ABI. -// This is an implementation detail that is kept in sync with MLIR codegen -// conventions. -template <typename T, int N> -StridedMemRefType<T, N> *makeStridedMemRefDescriptor( - void *ptr, const std::vector<int64_t> &shape) { - StridedMemRefType<T, N> *descriptor = static_cast<StridedMemRefType<T, N> *>( - malloc(sizeof(StridedMemRefType<T, N>))); - descriptor->basePtr = static_cast<T *>(ptr); - descriptor->data = static_cast<T *>(ptr); - descriptor->offset = 0; - std::copy(shape.begin(), shape.end(), descriptor->sizes); - auto strides = makeStrides(shape); - std::copy(strides.begin(), strides.end(), descriptor->strides); - return descriptor; -} - -// Mallocs a StridedMemRefDescriptor<T, 0>* (i.e. a pointer to scalar) that -// matches the MLIR ABI. This is an implementation detail that is kept in sync -// with MLIR codegen conventions. -template <typename T> -StridedMemRefType<T, 0> *makeStridedMemRefDescriptor( - void *ptr, const std::vector<int64_t> &shape) { - StridedMemRefType<T, 0> *descriptor = static_cast<StridedMemRefType<T, 0> *>( - malloc(sizeof(StridedMemRefType<T, 0>))); - descriptor->basePtr = static_cast<T *>(ptr); - descriptor->data = static_cast<T *>(ptr); - descriptor->offset = 0; - return descriptor; -} - -// Mallocs an UnrankedMemRefType<T>* that contains a ranked -// StridedMemRefDescriptor<T, Rank>* and matches the MLIR ABI. This is an -// implementation detail that is kept in sync with MLIR codegen conventions. -template <typename T> -UnrankedMemRefType<T> *allocUnrankedDescriptor( - void *data, const std::vector<int64_t> &shape) { - UnrankedMemRefType<T> *res = static_cast<UnrankedMemRefType<T> *>( - malloc(sizeof(UnrankedMemRefType<T>))); - res->rank = shape.size(); - if (res->rank == 0) - res->descriptor = makeStridedMemRefDescriptor<T>(data, shape); - else if (res->rank == 1) - res->descriptor = makeStridedMemRefDescriptor<T, 1>(data, shape); - else if (res->rank == 2) - res->descriptor = makeStridedMemRefDescriptor<T, 2>(data, shape); - else if (res->rank == 3) - res->descriptor = makeStridedMemRefDescriptor<T, 3>(data, shape); - else if (res->rank == 4) - res->descriptor = makeStridedMemRefDescriptor<T, 4>(data, shape); - else if (res->rank == 5) - res->descriptor = makeStridedMemRefDescriptor<T, 5>(data, shape); - else if (res->rank == 6) - res->descriptor = makeStridedMemRefDescriptor<T, 6>(data, shape); - else - assert(false && "Unsupported 6+D memref descriptor"); - return res; -} - -// Shape and strides aren't used in the generated code (yet). -// TODO(ataei): Delete this version once we can pass shapes. -template <typename T> -UnrankedMemRefType<T> *allocUnrankedDescriptor(void *data) { - UnrankedMemRefType<T> *res = static_cast<UnrankedMemRefType<T> *>( - malloc(sizeof(UnrankedMemRefType<T>))); - res->descriptor = makeStridedMemRefDescriptor<T>(data, {}); - return res; -} - -// Frees an UnrankedMemRefType<T>* -template <typename T> -void freeUnrankedDescriptor(UnrankedMemRefType<T> *desc) { - free(desc->descriptor); - free(desc); -} - -} // namespace llvmjit -} // namespace hal -} // namespace iree - -#endif // IREE_HAL_LLVMJIT_LLVMJIT_MEMREF_RUNTIME_H_
diff --git a/iree/hal/semaphore.h b/iree/hal/semaphore.h index 3a8182c..255585c 100644 --- a/iree/hal/semaphore.h +++ b/iree/hal/semaphore.h
@@ -17,8 +17,6 @@ #include <cstdint> -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "iree/base/status.h" #include "iree/base/time.h" #include "iree/hal/resource.h" @@ -85,16 +83,16 @@ virtual void Fail(Status status) = 0; // Blocks the caller until the semaphore reaches or exceedes the specified - // payload value or the |deadline| elapses. + // payload value or the |deadline_ns| elapses. // // Returns success if the wait is successful and the semaphore has met or // exceeded the required payload value. // - // Returns DEADLINE_EXCEEDED if the |deadline| elapses without the semaphore - // reaching the required value. - virtual Status Wait(uint64_t value, absl::Time deadline) = 0; - inline Status Wait(uint64_t value, absl::Duration timeout) { - return Wait(value, RelativeTimeoutToDeadline(timeout)); + // Returns DEADLINE_EXCEEDED if the |deadline_ns| elapses without the + // semaphore reaching the required value. + virtual Status Wait(uint64_t value, Time deadline_ns) = 0; + inline Status Wait(uint64_t value, Duration timeout_ns) { + return Wait(value, RelativeTimeoutToDeadlineNanos(timeout_ns)); } };
diff --git a/iree/hal/testing/mock_command_queue.h b/iree/hal/testing/mock_command_queue.h index 4530753..c281026 100644 --- a/iree/hal/testing/mock_command_queue.h +++ b/iree/hal/testing/mock_command_queue.h
@@ -32,7 +32,7 @@ MOCK_METHOD(Status, Submit, (absl::Span<const SubmissionBatch> batches), (override)); - MOCK_METHOD(Status, WaitIdle, (absl::Time deadline), (override)); + MOCK_METHOD(Status, WaitIdle, (Time deadline_ns), (override)); }; } // namespace testing
diff --git a/iree/hal/vmla/BUILD b/iree/hal/vmla/BUILD index d966b7c..35e081a 100644 --- a/iree/hal/vmla/BUILD +++ b/iree/hal/vmla/BUILD
@@ -140,8 +140,8 @@ "//iree/vm:context", "//iree/vm:instance", "//iree/vm:invocation", + "//iree/vm:list", "//iree/vm:module", - "//iree/vm:variant_list", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/types:span", ],
diff --git a/iree/hal/vmla/CMakeLists.txt b/iree/hal/vmla/CMakeLists.txt index adb4626..cfa8cca 100644 --- a/iree/hal/vmla/CMakeLists.txt +++ b/iree/hal/vmla/CMakeLists.txt
@@ -150,8 +150,8 @@ iree::vm::context iree::vm::instance iree::vm::invocation + iree::vm::list iree::vm::module - iree::vm::variant_list PUBLIC )
diff --git a/iree/hal/vmla/vmla_executable.cc b/iree/hal/vmla/vmla_executable.cc index 2990219..489a215 100644 --- a/iree/hal/vmla/vmla_executable.cc +++ b/iree/hal/vmla/vmla_executable.cc
@@ -22,8 +22,8 @@ #include "iree/schemas/vmla_executable_def_generated.h" #include "iree/vm/bytecode_module.h" #include "iree/vm/invocation.h" +#include "iree/vm/list.h" #include "iree/vm/module.h" -#include "iree/vm/variant_list.h" namespace iree { namespace hal { @@ -133,8 +133,8 @@ auto dispatch_state = make_ref<VMLADispatchState>(); dispatch_state->function = entry_functions_[params.entry_point]; - dispatch_state->input_list_size = - iree_vm_variant_list_alloc_size(/*interface*/ 1 + /*workgroup_xyz[3]*/ 3); + dispatch_state->input_list_size = iree_vm_list_storage_size( + /*element_type=*/nullptr, /*interface*/ 1 + /*workgroup_xyz[3]*/ 3); auto* interface = &dispatch_state->interface; RETURN_IF_ERROR(interface->SetConstants(params.push_constants->values)); @@ -163,18 +163,20 @@ IREE_TRACE_SCOPE0("VMLAExecutable::DispatchTile"); auto* dispatch_state = static_cast<VMLADispatchState*>(state); - auto* input_list = reinterpret_cast<iree_vm_variant_list_t*>( - alloca(dispatch_state->input_list_size)); - iree_vm_variant_list_init(input_list, - /*interface*/ 1 + /*workgroup_xyz[3]*/ 3); - iree_vm_variant_list_append_ref_retain(input_list, - &dispatch_state->interface_ref); - iree_vm_variant_list_append_value(input_list, - iree_vm_value_make_i32(workgroup_xyz[0])); - iree_vm_variant_list_append_value(input_list, - iree_vm_value_make_i32(workgroup_xyz[1])); - iree_vm_variant_list_append_value(input_list, - iree_vm_value_make_i32(workgroup_xyz[2])); + auto* input_list_storage = alloca(dispatch_state->input_list_size); + iree_vm_list_t* input_list = nullptr; + RETURN_IF_ERROR( + FromApiStatus(iree_vm_list_initialize( + iree_make_byte_span(input_list_storage, + dispatch_state->input_list_size), + /*element_type=*/nullptr, + /*interface*/ 1 + /*workgroup_xyz[3]*/ 3, &input_list), + IREE_LOC)); + iree_vm_list_push_ref_retain(input_list, &dispatch_state->interface_ref); + for (int i = 0; i < workgroup_xyz.size(); ++i) { + iree_vm_value_t value = iree_vm_value_make_i32(workgroup_xyz[i]); + iree_vm_list_push_value(input_list, &value); + } auto status = FromApiStatus(iree_vm_invoke(context(), dispatch_state->function, @@ -182,7 +184,7 @@ /*outputs=*/nullptr, IREE_ALLOCATOR_SYSTEM), IREE_LOC); - iree_vm_variant_list_free(input_list); + iree_vm_list_deinitialize(input_list); return std::move(status); }
diff --git a/iree/hal/vmla/vmla_executable.h b/iree/hal/vmla/vmla_executable.h index d74b11a..0e79b36 100644 --- a/iree/hal/vmla/vmla_executable.h +++ b/iree/hal/vmla/vmla_executable.h
@@ -25,7 +25,6 @@ #include "iree/vm/context.h" #include "iree/vm/instance.h" #include "iree/vm/module.h" -#include "iree/vm/variant_list.h" namespace iree { namespace hal {
diff --git a/iree/hal/vulkan/BUILD b/iree/hal/vulkan/BUILD index b93167a..ca73211 100644 --- a/iree/hal/vulkan/BUILD +++ b/iree/hal/vulkan/BUILD
@@ -138,6 +138,7 @@ ":handle_util", ":native_timeline_semaphore", ":status_util", + "//iree/base:api", "//iree/base:arena", "//iree/base:memory", "//iree/base:source_location", @@ -146,7 +147,6 @@ "//iree/hal:command_queue", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", "@iree_vulkan_headers//:vulkan_headers_no_prototypes", ], ) @@ -194,15 +194,16 @@ ":handle_util", ":status_util", ":timepoint_util", + "//iree/base:api", "//iree/base:intrusive_list", "//iree/base:ref_ptr", "//iree/base:status", + "//iree/base:time", "//iree/base:tracing", "//iree/hal:semaphore", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", "@com_google_absl//absl/utility", "@iree_vulkan_headers//:vulkan_headers_no_prototypes", ], @@ -358,6 +359,7 @@ ":handle_util", ":status_util", ":timepoint_util", + "//iree/base:api", "//iree/base:intrusive_list", "//iree/base:memory", "//iree/base:ref_ptr", @@ -370,7 +372,6 @@ "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", "@com_google_absl//absl/types:span", ], ) @@ -396,10 +397,10 @@ "//iree/base:intrusive_list", "//iree/base:ref_ptr", "//iree/base:status", + "//iree/base:time", "//iree/base:tracing", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", "@com_google_absl//absl/utility", "@iree_vulkan_headers//:vulkan_headers_no_prototypes", ], @@ -468,6 +469,7 @@ "//iree/base:math", "//iree/base:memory", "//iree/base:status", + "//iree/base:time", "//iree/base:tracing", "//iree/hal:allocator", "//iree/hal:command_buffer_validation",
diff --git a/iree/hal/vulkan/CMakeLists.txt b/iree/hal/vulkan/CMakeLists.txt index e69846d..78e81f7 100644 --- a/iree/hal/vulkan/CMakeLists.txt +++ b/iree/hal/vulkan/CMakeLists.txt
@@ -141,10 +141,10 @@ DEPS absl::core_headers absl::synchronization - absl::time iree::base::arena iree::base::memory iree::base::status + iree::base::time iree::base::tracing iree::hal::command_queue iree::hal::vulkan::direct_command_buffer @@ -212,9 +212,9 @@ ::timepoint_util absl::inlined_vector absl::synchronization - absl::time iree::base::intrusive_list iree::base::status + iree::base::time iree::base::tracing iree::hal::semaphore Vulkan::Headers @@ -454,6 +454,7 @@ iree::base::intrusive_list iree::base::ref_ptr iree::base::status + iree::base::time iree::base::tracing Vulkan::Headers PUBLIC @@ -526,6 +527,7 @@ iree::base::math iree::base::memory iree::base::status + iree::base::time iree::base::tracing iree::hal::allocator iree::hal::command_buffer_validation
diff --git a/iree/hal/vulkan/direct_command_queue.cc b/iree/hal/vulkan/direct_command_queue.cc index 11a33cc..84f3876 100644 --- a/iree/hal/vulkan/direct_command_queue.cc +++ b/iree/hal/vulkan/direct_command_queue.cc
@@ -16,8 +16,6 @@ #include <cstdint> -#include "absl/time/clock.h" -#include "absl/time/time.h" #include "iree/base/memory.h" #include "iree/base/source_location.h" #include "iree/base/status.h" @@ -134,8 +132,8 @@ return OkStatus(); } -Status DirectCommandQueue::WaitIdle(absl::Time deadline) { - if (deadline == absl::InfiniteFuture()) { +Status DirectCommandQueue::WaitIdle(Time deadline_ns) { + if (deadline_ns == InfiniteFuture()) { // Fast path for using vkQueueWaitIdle, which is usually cheaper (as it // requires fewer calls into the driver). IREE_TRACE_SCOPE0("DirectCommandQueue::WaitIdle#vkQueueWaitIdle"); @@ -160,21 +158,21 @@ logical_device_->allocator()); }); - uint64_t timeout; - if (deadline == absl::InfinitePast()) { + uint64_t timeout_ns; + if (deadline_ns == InfinitePast()) { // Do not wait. - timeout = 0; - } else if (deadline == absl::InfiniteFuture()) { + timeout_ns = 0; + } else if (deadline_ns == InfiniteFuture()) { // Wait forever. - timeout = UINT64_MAX; + timeout_ns = UINT64_MAX; } else { // Convert to relative time in nanoseconds. // The implementation may not wait with this granularity (like, by 10000x). - absl::Time now = absl::Now(); - if (deadline < now) { + Time now_ns = Now(); + if (deadline_ns < now_ns) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline in the past"; } - timeout = static_cast<uint64_t>(absl::ToInt64Nanoseconds(deadline - now)); + timeout_ns = static_cast<uint64_t>(deadline_ns - now_ns); } { @@ -183,7 +181,7 @@ } VkResult result = - syms()->vkWaitForFences(*logical_device_, 1, &fence, VK_TRUE, timeout); + syms()->vkWaitForFences(*logical_device_, 1, &fence, VK_TRUE, timeout_ns); switch (result) { case VK_SUCCESS: return OkStatus();
diff --git a/iree/hal/vulkan/direct_command_queue.h b/iree/hal/vulkan/direct_command_queue.h index c080398..1921bfa 100644 --- a/iree/hal/vulkan/direct_command_queue.h +++ b/iree/hal/vulkan/direct_command_queue.h
@@ -22,9 +22,9 @@ #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" -#include "absl/time/time.h" #include "iree/base/arena.h" #include "iree/base/status.h" +#include "iree/base/time.h" #include "iree/hal/command_queue.h" #include "iree/hal/vulkan/dynamic_symbols.h" #include "iree/hal/vulkan/handle_util.h" @@ -48,7 +48,7 @@ Status Submit(absl::Span<const SubmissionBatch> batches) override; - Status WaitIdle(absl::Time deadline) override; + Status WaitIdle(Time deadline_ns) override; private: Status TranslateBatchInfo(const SubmissionBatch& batch,
diff --git a/iree/hal/vulkan/emulated_timeline_semaphore.cc b/iree/hal/vulkan/emulated_timeline_semaphore.cc index 9656310..a3e2c1e 100644 --- a/iree/hal/vulkan/emulated_timeline_semaphore.cc +++ b/iree/hal/vulkan/emulated_timeline_semaphore.cc
@@ -16,8 +16,8 @@ #include "absl/container/inlined_vector.h" #include "absl/synchronization/mutex.h" -#include "absl/time/time.h" #include "absl/utility/utility.h" +#include "iree/base/time.h" #include "iree/base/tracing.h" #include "iree/hal/vulkan/dynamic_symbols.h" #include "iree/hal/vulkan/status_util.h" @@ -82,7 +82,7 @@ return OkStatus(); } -Status EmulatedTimelineSemaphore::Wait(uint64_t value, absl::Time deadline) { +Status EmulatedTimelineSemaphore::Wait(uint64_t value, Time deadline_ns) { IREE_TRACE_SCOPE0("EmulatedTimelineSemaphore::Wait"); VkFence fence = VK_NULL_HANDLE; @@ -112,26 +112,18 @@ break; } // TODO(antiagainst): figure out a better way instead of the busy loop here. - } while (absl::Now() < deadline); + } while (Now() < deadline_ns); if (fence == VK_NULL_HANDLE) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline reached when waiting timeline semaphore"; } - uint64_t timeout_nanos; - if (deadline == absl::InfiniteFuture()) { - timeout_nanos = UINT64_MAX; - } else if (deadline == absl::InfinitePast()) { - timeout_nanos = 0; - } else { - auto relative_nanos = absl::ToInt64Nanoseconds(deadline - absl::Now()); - timeout_nanos = relative_nanos < 0 ? 0 : relative_nanos; - } - + uint64_t timeout_ns = + static_cast<uint64_t>(DeadlineToRelativeTimeoutNanos(deadline_ns)); VK_RETURN_IF_ERROR(logical_device_->syms()->vkWaitForFences( *logical_device_, /*fenceCount=*/1, &fence, /*waitAll=*/true, - timeout_nanos)); + timeout_ns)); RETURN_IF_ERROR(TryToAdvanceTimeline(value).status()); return OkStatus();
diff --git a/iree/hal/vulkan/emulated_timeline_semaphore.h b/iree/hal/vulkan/emulated_timeline_semaphore.h index cc13a09..d4d61c8 100644 --- a/iree/hal/vulkan/emulated_timeline_semaphore.h +++ b/iree/hal/vulkan/emulated_timeline_semaphore.h
@@ -144,7 +144,7 @@ Status Signal(uint64_t value) override; - Status Wait(uint64_t value, absl::Time deadline) override; + Status Wait(uint64_t value, Time deadline_ns) override; void Fail(Status status) override;
diff --git a/iree/hal/vulkan/native_timeline_semaphore.cc b/iree/hal/vulkan/native_timeline_semaphore.cc index c0898b4..2a9ba8b 100644 --- a/iree/hal/vulkan/native_timeline_semaphore.cc +++ b/iree/hal/vulkan/native_timeline_semaphore.cc
@@ -97,7 +97,7 @@ logical_device_->syms()->vkSignalSemaphore(*logical_device_, &signal_info); } -Status NativeTimelineSemaphore::Wait(uint64_t value, absl::Time deadline) { +Status NativeTimelineSemaphore::Wait(uint64_t value, Time deadline_ns) { IREE_TRACE_SCOPE0("NativeTimelineSemaphore::Wait"); VkSemaphoreWaitInfo wait_info; @@ -108,14 +108,15 @@ wait_info.pSemaphores = &handle_; wait_info.pValues = &value; - uint64_t timeout_nanos; - if (deadline == absl::InfiniteFuture()) { - timeout_nanos = UINT64_MAX; - } else if (deadline == absl::InfinitePast()) { - timeout_nanos = 0; + uint64_t timeout_ns; + if (deadline_ns == InfiniteFuture()) { + timeout_ns = UINT64_MAX; + } else if (deadline_ns == InfinitePast()) { + timeout_ns = 0; } else { - auto relative_nanos = absl::ToInt64Nanoseconds(deadline - absl::Now()); - timeout_nanos = relative_nanos < 0 ? 0 : relative_nanos; + Duration relative_ns = deadline_ns - Now(); + timeout_ns = static_cast<int64_t>( + relative_ns < ZeroDuration() ? ZeroDuration() : relative_ns); } // NOTE: this may fail with a timeout (VK_TIMEOUT) or in the case of a @@ -126,7 +127,7 @@ return UnknownErrorBuilder(IREE_LOC) << "vkWaitSemaphores not defined"; } VkResult result = logical_device_->syms()->vkWaitSemaphores( - *logical_device_, &wait_info, timeout_nanos); + *logical_device_, &wait_info, timeout_ns); if (result == VK_ERROR_DEVICE_LOST) { // Nothing we do now matters. return VkResultToStatus(result);
diff --git a/iree/hal/vulkan/native_timeline_semaphore.h b/iree/hal/vulkan/native_timeline_semaphore.h index 3f44351..a5d3a93 100644 --- a/iree/hal/vulkan/native_timeline_semaphore.h +++ b/iree/hal/vulkan/native_timeline_semaphore.h
@@ -44,7 +44,7 @@ Status Signal(uint64_t value) override; void Fail(Status status) override; - Status Wait(uint64_t value, absl::Time deadline) override; + Status Wait(uint64_t value, Time deadline_ns) override; private: ref_ptr<VkDeviceHandle> logical_device_;
diff --git a/iree/hal/vulkan/serializing_command_queue.cc b/iree/hal/vulkan/serializing_command_queue.cc index 563f4c7..3a49ba2 100644 --- a/iree/hal/vulkan/serializing_command_queue.cc +++ b/iree/hal/vulkan/serializing_command_queue.cc
@@ -16,8 +16,8 @@ #include <memory> -#include "absl/time/clock.h" #include "absl/types/span.h" +#include "iree/base/api.h" #include "iree/base/memory.h" #include "iree/base/source_location.h" #include "iree/base/tracing.h" @@ -266,10 +266,10 @@ return true; } -Status SerializingCommandQueue::WaitIdle(absl::Time deadline) { +Status SerializingCommandQueue::WaitIdle(Time deadline_ns) { absl::MutexLock lock(&mutex_); - if (deadline == absl::InfiniteFuture()) { + if (deadline_ns == InfiniteFuture()) { IREE_TRACE_SCOPE0("SerializingCommandQueue::WaitIdle#vkQueueWaitIdle"); // Fast path for using vkQueueWaitIdle, which is usually cheaper (as it // requires fewer calls into the driver). @@ -296,21 +296,21 @@ do { RETURN_IF_ERROR(ProcessDeferredSubmissions().status()); - uint64_t timeout_nanos; - if (deadline == absl::InfinitePast()) { - // Do not wait. - timeout_nanos = 0; + uint64_t timeout_ns; + if (deadline_ns == InfiniteFuture()) { + timeout_ns = UINT64_MAX; + } else if (deadline_ns == InfinitePast()) { + timeout_ns = 0; } else { // Convert to relative time in nanoseconds. // The implementation may not wait with this granularity (like, by // 10000x). - absl::Time now = absl::Now(); - if (deadline < now) { + Duration relative_ns = deadline_ns - Now(); + if (relative_ns < ZeroDuration()) { return DeadlineExceededErrorBuilder(IREE_LOC) << "Deadline exceeded waiting for idle"; } - timeout_nanos = - static_cast<uint64_t>(absl::ToInt64Nanoseconds(deadline - now)); + timeout_ns = static_cast<uint64_t>(relative_ns); } if (pending_fences_.empty()) continue; @@ -321,7 +321,7 @@ VkResult result = syms()->vkWaitForFences(*logical_device_, fences.size(), fences.data(), - /*waitAll=*/VK_TRUE, timeout_nanos); + /*waitAll=*/VK_TRUE, timeout_ns); switch (result) { case VK_SUCCESS:
diff --git a/iree/hal/vulkan/serializing_command_queue.h b/iree/hal/vulkan/serializing_command_queue.h index e38643b..92a811d 100644 --- a/iree/hal/vulkan/serializing_command_queue.h +++ b/iree/hal/vulkan/serializing_command_queue.h
@@ -23,10 +23,10 @@ #include "absl/base/thread_annotations.h" #include "absl/container/inlined_vector.h" #include "absl/synchronization/mutex.h" -#include "absl/time/time.h" #include "iree/base/intrusive_list.h" #include "iree/base/ref_ptr.h" #include "iree/base/status.h" +#include "iree/base/time.h" #include "iree/hal/command_buffer.h" #include "iree/hal/command_queue.h" #include "iree/hal/vulkan/dynamic_symbols.h" @@ -63,7 +63,7 @@ Status Submit(absl::Span<const SubmissionBatch> batches) override; - Status WaitIdle(absl::Time deadline) override; + Status WaitIdle(Time deadline_ns) override; // Releases all deferred submissions ready to submit to the GPU. Status AdvanceQueueSubmission();
diff --git a/iree/hal/vulkan/timepoint_util.cc b/iree/hal/vulkan/timepoint_util.cc index 98e9f96..7664f3b 100644 --- a/iree/hal/vulkan/timepoint_util.cc +++ b/iree/hal/vulkan/timepoint_util.cc
@@ -17,8 +17,8 @@ #include <memory> #include "absl/synchronization/mutex.h" -#include "absl/time/time.h" #include "absl/utility/utility.h" +#include "iree/base/time.h" #include "iree/base/tracing.h" #include "iree/hal/vulkan/dynamic_symbols.h" #include "iree/hal/vulkan/status_util.h"
diff --git a/iree/hal/vulkan/vulkan_device.cc b/iree/hal/vulkan/vulkan_device.cc index 55a4a4e..3209d5a 100644 --- a/iree/hal/vulkan/vulkan_device.cc +++ b/iree/hal/vulkan/vulkan_device.cc
@@ -24,6 +24,7 @@ #include "absl/synchronization/mutex.h" #include "iree/base/math.h" #include "iree/base/status.h" +#include "iree/base/time.h" #include "iree/base/tracing.h" #include "iree/hal/command_buffer_validation.h" #include "iree/hal/command_queue.h" @@ -736,20 +737,20 @@ } Status VulkanDevice::WaitAllSemaphores( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { IREE_TRACE_SCOPE0("VulkanDevice::WaitAllSemaphores"); - return WaitSemaphores(semaphores, deadline, /*wait_flags=*/0); + return WaitSemaphores(semaphores, deadline_ns, /*wait_flags=*/0); } StatusOr<int> VulkanDevice::WaitAnySemaphore( - absl::Span<const SemaphoreValue> semaphores, absl::Time deadline) { + absl::Span<const SemaphoreValue> semaphores, Time deadline_ns) { IREE_TRACE_SCOPE0("VulkanDevice::WaitAnySemaphore"); - return WaitSemaphores(semaphores, deadline, + return WaitSemaphores(semaphores, deadline_ns, /*wait_flags=*/VK_SEMAPHORE_WAIT_ANY_BIT); } Status VulkanDevice::WaitSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline, + Time deadline_ns, VkSemaphoreWaitFlags wait_flags) { IREE_TRACE_SCOPE0("VulkanDevice::WaitSemaphores"); @@ -762,7 +763,7 @@ for (int i = 0; i < semaphores.size(); ++i) { auto* semaphore = static_cast<EmulatedTimelineSemaphore*>(semaphores[i].semaphore); - RETURN_IF_ERROR(semaphore->Wait(semaphores[i].value, deadline)); + RETURN_IF_ERROR(semaphore->Wait(semaphores[i].value, deadline_ns)); if (wait_flags & VK_SEMAPHORE_WAIT_ANY_BIT) return OkStatus(); } @@ -786,22 +787,14 @@ wait_info.pSemaphores = semaphore_handles.data(); wait_info.pValues = semaphore_values.data(); - uint64_t timeout_nanos; - if (deadline == absl::InfiniteFuture()) { - timeout_nanos = UINT64_MAX; - } else if (deadline == absl::InfinitePast()) { - timeout_nanos = 0; - } else { - auto relative_nanos = absl::ToInt64Nanoseconds(deadline - absl::Now()); - timeout_nanos = relative_nanos < 0 ? 0 : relative_nanos; - } - // NOTE: this may fail with a timeout (VK_TIMEOUT) or in the case of a // device loss event may return either VK_SUCCESS *or* VK_ERROR_DEVICE_LOST. // We may want to explicitly query for device loss after a successful wait // to ensure we consistently return errors. + uint64_t timeout_ns = + static_cast<uint64_t>(DeadlineToRelativeTimeoutNanos(deadline_ns)); VkResult result = - syms()->vkWaitSemaphores(*logical_device_, &wait_info, timeout_nanos); + syms()->vkWaitSemaphores(*logical_device_, &wait_info, timeout_ns); if (result == VK_ERROR_DEVICE_LOST) { // Nothing we do now matters. return VkResultToStatus(result); @@ -813,8 +806,8 @@ return OkStatus(); } -Status VulkanDevice::WaitIdle(absl::Time deadline) { - if (deadline == absl::InfiniteFuture()) { +Status VulkanDevice::WaitIdle(Time deadline_ns) { + if (deadline_ns == InfiniteFuture()) { // Fast path for using vkDeviceWaitIdle, which is usually cheaper (as it // requires fewer calls into the driver). IREE_TRACE_SCOPE0("VulkanDevice::WaitIdle#vkDeviceWaitIdle"); @@ -824,7 +817,7 @@ IREE_TRACE_SCOPE0("VulkanDevice::WaitIdle#Semaphores"); for (auto& command_queue : command_queues_) { - RETURN_IF_ERROR(command_queue->WaitIdle(deadline)); + RETURN_IF_ERROR(command_queue->WaitIdle(deadline_ns)); } return OkStatus(); }
diff --git a/iree/hal/vulkan/vulkan_device.h b/iree/hal/vulkan/vulkan_device.h index 4032bbf..273d407 100644 --- a/iree/hal/vulkan/vulkan_device.h +++ b/iree/hal/vulkan/vulkan_device.h
@@ -106,11 +106,11 @@ StatusOr<ref_ptr<Semaphore>> CreateSemaphore(uint64_t initial_value) override; Status WaitAllSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; + Time deadline_ns) override; StatusOr<int> WaitAnySemaphore(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline) override; + Time deadline_ns) override; - Status WaitIdle(absl::Time deadline) override; + Status WaitIdle(Time deadline_ns) override; private: VulkanDevice( @@ -125,7 +125,7 @@ DebugCaptureManager* debug_capture_manager); Status WaitSemaphores(absl::Span<const SemaphoreValue> semaphores, - absl::Time deadline, VkSemaphoreWaitFlags wait_flags); + Time deadline_ns, VkSemaphoreWaitFlags wait_flags); bool emulating_timeline_semaphores() const { return semaphore_pool_ != nullptr;
diff --git a/iree/modules/check/BUILD b/iree/modules/check/BUILD index 863b189..f1e5cbf 100644 --- a/iree/modules/check/BUILD +++ b/iree/modules/check/BUILD
@@ -41,7 +41,6 @@ "//iree/testing:gtest_main", "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:ref", "//iree/vm:ref_cc", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings",
diff --git a/iree/modules/check/CMakeLists.txt b/iree/modules/check/CMakeLists.txt index 804b844..0a016be 100644 --- a/iree/modules/check/CMakeLists.txt +++ b/iree/modules/check/CMakeLists.txt
@@ -34,7 +34,6 @@ iree::testing::gtest_main iree::vm iree::vm::bytecode_module - iree::vm::ref iree::vm::ref_cc )
diff --git a/iree/modules/check/check_test.cc b/iree/modules/check/check_test.cc index c1cb470..ed84a71 100644 --- a/iree/modules/check/check_test.cc +++ b/iree/modules/check/check_test.cc
@@ -27,7 +27,6 @@ #include "iree/testing/gtest.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/ref.h" #include "iree/vm/ref_cc.h" namespace iree { @@ -71,8 +70,8 @@ } void TearDown() override { + inputs_.reset(); iree_vm_context_release(context_); - if (inputs_) iree_vm_variant_list_free(inputs_); } void CreateInt32BufferView(absl::Span<const int32_t> contents, @@ -173,7 +172,7 @@ // TODO(#2075): don't directly invoke native functions like this. return FromApiStatus( iree_vm_invoke(context_, function, - /*policy=*/nullptr, inputs_, + /*policy=*/nullptr, inputs_.get(), /*outputs=*/nullptr, IREE_ALLOCATOR_SYSTEM), IREE_LOC); } @@ -181,12 +180,12 @@ Status Invoke(absl::string_view function_name, std::vector<iree_vm_value> args) { RETURN_IF_ERROR( - FromApiStatus(iree_vm_variant_list_alloc( - args.size(), IREE_ALLOCATOR_SYSTEM, &inputs_), + FromApiStatus(iree_vm_list_create(/*element_type=*/nullptr, args.size(), + IREE_ALLOCATOR_SYSTEM, &inputs_), IREE_LOC)); for (iree_vm_value& arg : args) { RETURN_IF_ERROR(FromApiStatus( - iree_vm_variant_list_append_value(inputs_, arg), IREE_LOC)); + iree_vm_list_push_value(inputs_.get(), &arg), IREE_LOC)); } return Invoke(function_name); } @@ -194,13 +193,13 @@ Status Invoke(absl::string_view function_name, std::vector<vm::ref<iree_hal_buffer_view_t>> args) { RETURN_IF_ERROR( - FromApiStatus(iree_vm_variant_list_alloc( - args.size(), IREE_ALLOCATOR_SYSTEM, &inputs_), + FromApiStatus(iree_vm_list_create(/*element_type=*/nullptr, args.size(), + IREE_ALLOCATOR_SYSTEM, &inputs_), IREE_LOC)); for (auto& arg : args) { iree_vm_ref_t arg_ref = iree_hal_buffer_view_move_ref(arg.get()); RETURN_IF_ERROR(FromApiStatus( - iree_vm_variant_list_append_ref_retain(inputs_, &arg_ref), IREE_LOC)); + iree_vm_list_push_ref_retain(inputs_.get(), &arg_ref), IREE_LOC)); } return Invoke(function_name); } @@ -212,7 +211,7 @@ static iree_vm_module_t* hal_module_; iree_vm_context_t* context_ = nullptr; - iree_vm_variant_list_t* inputs_ = nullptr; + vm::ref<iree_vm_list_t> inputs_; iree_hal_allocator_t* allocator_ = nullptr; }; iree_hal_device_t* CheckTest::device_ = nullptr;
diff --git a/iree/modules/hal/hal_module.cc b/iree/modules/hal/hal_module.cc index 2b1d6db..e51938f 100644 --- a/iree/modules/hal/hal_module.cc +++ b/iree/modules/hal/hal_module.cc
@@ -457,6 +457,30 @@ return BufferViewDimsN<4>(std::move(buffer_view)); } + Status BufferViewTrace( + absl::Span<const vm::ref<iree_hal_buffer_view_t>> buffer_views) { + // TODO(hanchung): Have better information for each dump, eg, having StrAttr + // for each trace event so we can map the dump to dispatch functions easier. + fprintf(stderr, "=== DEBUG DUMP ===\n"); + for (auto& view : buffer_views) { + std::string result_str(4096, '\0'); + iree_status_t status; + do { + iree_host_size_t actual_length = 0; + status = iree_hal_buffer_view_format( + view.get(), /*max_element_count=*/1024, result_str.size() + 1, + &result_str[0], &actual_length); + result_str.resize(actual_length); + } while (iree_status_is_out_of_range(status)); + if (!iree_status_is_ok(status)) { + return FromApiStatus(status, IREE_LOC); + } + fprintf(stderr, "%s\n", result_str.c_str()); + } + fprintf(stderr, "\n"); + return OkStatus(); + } + //===--------------------------------------------------------------------===// // iree::hal::CommandBuffer //===--------------------------------------------------------------------===// @@ -876,6 +900,8 @@ &HALModuleState::BufferViewDims3), vm::MakeNativeFunction("buffer_view.dims.4", &HALModuleState::BufferViewDims4), + vm::MakeNativeFunction("buffer_view.trace", + &HALModuleState::BufferViewTrace), vm::MakeNativeFunction("command_buffer.create", &HALModuleState::CommandBufferCreate),
diff --git a/iree/modules/strings/BUILD b/iree/modules/strings/BUILD index 4d46042..d4e7053 100644 --- a/iree/modules/strings/BUILD +++ b/iree/modules/strings/BUILD
@@ -27,7 +27,6 @@ "//iree/vm:module", "//iree/vm:module_abi_cc", "//iree/vm:ref", - "//iree/vm:ref_cc", "//iree/vm:stack", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/strings", @@ -48,13 +47,10 @@ "//iree/hal/vmla:vmla_driver_module", "//iree/modules/hal", "//iree/testing:gtest_main", + "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:context", - "//iree/vm:instance", - "//iree/vm:module", - "//iree/vm:ref", + "//iree/vm:module_abi_cc", "//iree/vm:ref_cc", - "//iree/vm:stack", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/strings", "@com_google_benchmark//:benchmark",
diff --git a/iree/modules/strings/CMakeLists.txt b/iree/modules/strings/CMakeLists.txt index 0c898bb..6c6ac35 100644 --- a/iree/modules/strings/CMakeLists.txt +++ b/iree/modules/strings/CMakeLists.txt
@@ -38,7 +38,6 @@ iree::vm::module iree::vm::module_abi_cc iree::vm::ref - iree::vm::ref_cc iree::vm::stack PUBLIC ) @@ -60,13 +59,10 @@ iree::hal::vmla::vmla_driver_module iree::modules::hal iree::testing::gtest_main + iree::vm iree::vm::bytecode_module - iree::vm::context - iree::vm::instance - iree::vm::module - iree::vm::ref + iree::vm::module_abi_cc iree::vm::ref_cc - iree::vm::stack ) iree_bytecode_module(
diff --git a/iree/modules/strings/strings_module.cc b/iree/modules/strings/strings_module.cc index a52bac0..abd07ee 100644 --- a/iree/modules/strings/strings_module.cc +++ b/iree/modules/strings/strings_module.cc
@@ -28,10 +28,7 @@ #include "iree/modules/strings/api.h" #include "iree/modules/strings/api_detail.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/module.h" #include "iree/vm/module_abi_cc.h" -#include "iree/vm/ref.h" -#include "iree/vm/stack.h" static iree_vm_ref_type_descriptor_t strings_string_descriptor = {0}; static iree_vm_ref_type_descriptor_t strings_string_tensor_descriptor = {0};
diff --git a/iree/modules/strings/strings_module_test.cc b/iree/modules/strings/strings_module_test.cc index b3a3122..d5ee15d 100644 --- a/iree/modules/strings/strings_module_test.cc +++ b/iree/modules/strings/strings_module_test.cc
@@ -26,13 +26,9 @@ #include "iree/modules/strings/api_detail.h" #include "iree/modules/strings/strings_module_test_module.h" #include "iree/testing/gtest.h" +#include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/context.h" -#include "iree/vm/instance.h" -#include "iree/vm/module.h" -#include "iree/vm/ref.h" #include "iree/vm/ref_cc.h" -#include "iree/vm/stack.h" using testing::internal::CaptureStdout; using testing::internal::GetCapturedStdout; @@ -138,37 +134,33 @@ shape.data(), shape.size(), &input_string_tensor)); // Construct the input list for execution. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); // Add the string tensor to the input list. - iree_vm_ref_t input_string_tensor_ref = - strings_string_tensor_move_ref(input_string_tensor.get()); - IREE_ASSERT_OK(iree_vm_variant_list_append_ref_retain( - inputs, &input_string_tensor_ref)); + IREE_ASSERT_OK( + iree_vm_list_push_ref_retain(inputs.get(), input_string_tensor)); // Construct the output list for accepting results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Invoke the function. - IREE_ASSERT_OK(iree_vm_invoke( - context_, LookupFunction("string_tensor_to_string"), - /*policy=*/nullptr, inputs, outputs, IREE_ALLOCATOR_SYSTEM)); + IREE_ASSERT_OK(iree_vm_invoke(context_, + LookupFunction("string_tensor_to_string"), + /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM)); - // Retrieve and validate the string tensor; - strings_string_t* output_string = - strings_string_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + // Retrieve and validate the string tensor. + auto* output_string = + reinterpret_cast<strings_string_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, strings_string_get_descriptor())); ASSERT_EQ(output_string->value.size, expected_output.length()); EXPECT_EQ( absl::string_view(output_string->value.data, output_string->value.size), expected_output); - - // Free the lists. - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); } template <typename T, iree_hal_element_type_t E> @@ -179,33 +171,26 @@ CreateBufferView<T, E>(contents, shape, &input_buffer_view); // Construct the input list for execution. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); // Add the buffer view to the input list. - iree_vm_ref_t input_buffer_view_ref = - iree_hal_buffer_view_move_ref(input_buffer_view.get()); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &input_buffer_view_ref)); + iree_vm_list_push_ref_retain(inputs.get(), input_buffer_view)); // Construct the output list for accepting results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("to_string_tensor"), - /*policy=*/nullptr, inputs, outputs, - IREE_ALLOCATOR_SYSTEM)); + /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM)); // Compare the output to the expected result. CompareResults(expected, shape, outputs); - - // Free the lists. - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); } void TestGather(absl::Span<const iree_string_view_t> dict, @@ -219,43 +204,36 @@ dict_shape.size(), &dict_string_tensor)); // Construct the input list for execution. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(2, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 2, + IREE_ALLOCATOR_SYSTEM, &inputs)); // Add the dict to the input list. iree_vm_ref_t dict_string_tensor_ref = strings_string_tensor_move_ref(dict_string_tensor.get()); - IREE_ASSERT_OK(iree_vm_variant_list_append_ref_retain( - inputs, &dict_string_tensor_ref)); + IREE_ASSERT_OK( + iree_vm_list_push_ref_retain(inputs.get(), &dict_string_tensor_ref)); vm::ref<iree_hal_buffer_view_t> input_buffer_view; CreateBufferView<int32_t, IREE_HAL_ELEMENT_TYPE_SINT_32>( ids, ids_shape, &input_buffer_view); // Add the ids tensor to the input list. - iree_vm_ref_t input_buffer_view_ref = - iree_hal_buffer_view_move_ref(input_buffer_view.get()); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &input_buffer_view_ref)); + iree_vm_list_push_ref_retain(inputs.get(), input_buffer_view)); // Construct the output list for accepting results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("gather"), - /*policy=*/nullptr, inputs, outputs, - IREE_ALLOCATOR_SYSTEM)); + /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM)); // Compare the output to the expected result. - CompareResults(expected, ids_shape, outputs); - - // Free the lists. - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); + CompareResults(expected, ids_shape, std::move(outputs)); } void TestConcat(absl::Span<const iree_string_view_t> string_views, @@ -267,43 +245,37 @@ shape.data(), shape.size(), &string_tensor)); // Construct the input list for execution. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); // Add the dict to the input list. - iree_vm_ref_t string_tensor_ref = - strings_string_tensor_move_ref(string_tensor.get()); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &string_tensor_ref)); + IREE_ASSERT_OK(iree_vm_list_push_ref_retain(inputs.get(), string_tensor)); // Construct the output list for accepting results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("concat"), - /*policy=*/nullptr, inputs, outputs, - IREE_ALLOCATOR_SYSTEM)); + /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM)); // Remove the last dimension from the shape to get the expected shape shape.remove_suffix(1); // Compare the output to the expected result. - CompareResults(expected, shape, outputs); - - // Free the lists. - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); + CompareResults(expected, shape, std::move(outputs)); } void CompareResults(absl::Span<const iree_string_view_t> expected, absl::Span<const int32_t> expected_shape, - iree_vm_variant_list_t* outputs) { - // Retrieve and validate the string tensor; - strings_string_tensor_t* output_tensor = - strings_string_tensor_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + vm::ref<iree_vm_list_t> outputs) { + // Retrieve and validate the string tensor. + auto* output_tensor = + reinterpret_cast<strings_string_tensor_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, strings_string_tensor_get_descriptor())); // Validate the count. size_t count; @@ -348,26 +320,24 @@ std::string expected_output = "42\n"; // Construct the input list for execution. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); // Add the value parameter. iree_vm_value_t value = iree_vm_value_make_i32(input); - IREE_ASSERT_OK(iree_vm_variant_list_append_value(inputs, value)); + IREE_ASSERT_OK(iree_vm_list_push_value(inputs.get(), &value)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(0, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 0, + IREE_ALLOCATOR_SYSTEM, &outputs)); CaptureStdout(); IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("print_example_func"), - /*policy=*/nullptr, inputs, outputs, + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); EXPECT_EQ(GetCapturedStdout(), expected_output); - - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); } TEST_F(StringsModuleTest, StringTensorToString_Scalar) {
diff --git a/iree/modules/tensorlist/BUILD b/iree/modules/tensorlist/BUILD index 1bc2d81..4e7a784 100644 --- a/iree/modules/tensorlist/BUILD +++ b/iree/modules/tensorlist/BUILD
@@ -41,9 +41,7 @@ "//iree/testing:gtest_main", "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:ref", "//iree/vm:ref_cc", - "//iree/vm:variant_list", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/strings",
diff --git a/iree/modules/tensorlist/CMakeLists.txt b/iree/modules/tensorlist/CMakeLists.txt index eb2880a..affd749 100644 --- a/iree/modules/tensorlist/CMakeLists.txt +++ b/iree/modules/tensorlist/CMakeLists.txt
@@ -46,9 +46,7 @@ iree::testing::gtest_main iree::vm iree::vm::bytecode_module - iree::vm::ref iree::vm::ref_cc - iree::vm::variant_list ) iree_cc_library(
diff --git a/iree/modules/tensorlist/native_module.cc b/iree/modules/tensorlist/native_module.cc index c3fb8dd..9ca5c0a 100644 --- a/iree/modules/tensorlist/native_module.cc +++ b/iree/modules/tensorlist/native_module.cc
@@ -322,12 +322,14 @@ static iree_vm_ref_type_descriptor_t iree_tensorlist_descriptor = {0}; // Register our type with the vm::ref<T> static machinery. +namespace vm { template <> -struct ::iree::vm::ref_type_descriptor<TensorList> { +struct ref_type_descriptor<TensorList> { static const iree_vm_ref_type_descriptor_t* get() { return &iree_tensorlist_descriptor; } }; +} // namespace vm extern "C" iree_status_t iree_tensorlist_module_register_types() { static bool has_registered = false;
diff --git a/iree/modules/tensorlist/tensorlist_test.cc b/iree/modules/tensorlist/tensorlist_test.cc index e254a35..76227ee 100644 --- a/iree/modules/tensorlist/tensorlist_test.cc +++ b/iree/modules/tensorlist/tensorlist_test.cc
@@ -27,9 +27,7 @@ #include "iree/testing/gtest.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/ref.h" #include "iree/vm/ref_cc.h" -#include "iree/vm/variant_list.h" namespace iree { @@ -135,26 +133,27 @@ CreateBufferView(kBufferContents, shape, device_, &input_buffer_view); // Pass in the tensor as a HAL buffer view. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_buffer_view_ref = iree_hal_buffer_view_move_ref(input_buffer_view.get()); IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &input_buffer_view_ref)); + iree_vm_list_push_ref_retain(inputs.get(), &input_buffer_view_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke( context_, LookupFunction("identity_through_set_item_get_item"), - /*policy=*/nullptr, inputs, outputs, IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_hal_buffer_view_t* returned_buffer_view = - iree_hal_buffer_view_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + auto* returned_buffer_view = + reinterpret_cast<iree_hal_buffer_view_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_hal_buffer_view_get_descriptor())); ASSERT_NE(nullptr, returned_buffer_view); iree_hal_buffer_t* returned_buffer = iree_hal_buffer_view_buffer(returned_buffer_view); @@ -167,8 +166,6 @@ EXPECT_EQ(reinterpret_cast<float*>(mapped_memory.contents.data)[0], kBufferContents[0]); IREE_ASSERT_OK(iree_hal_buffer_unmap(returned_buffer, &mapped_memory)); - - iree_vm_variant_list_free(outputs); } TEST_F(TensorListModulesTest, IdentityThroughConcat) { @@ -179,26 +176,27 @@ CreateBufferView(kBufferContents, shape, device_, &input_buffer_view); // Pass in the tensor as a HAL buffer view. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_buffer_view_ref = iree_hal_buffer_view_move_ref(input_buffer_view.get()); IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &input_buffer_view_ref)); + iree_vm_list_push_ref_retain(inputs.get(), &input_buffer_view_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke( context_, LookupFunction("identity_through_concat"), - /*policy=*/nullptr, inputs, outputs, IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_hal_buffer_view_t* returned_buffer_view = - iree_hal_buffer_view_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + auto* returned_buffer_view = + reinterpret_cast<iree_hal_buffer_view_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_hal_buffer_view_get_descriptor())); ASSERT_NE(nullptr, returned_buffer_view); iree_hal_buffer_t* returned_buffer = iree_hal_buffer_view_buffer(returned_buffer_view); @@ -222,8 +220,6 @@ mapped_memory.contents.data_length), 0); IREE_ASSERT_OK(iree_hal_buffer_unmap(returned_buffer, &mapped_memory)); - - iree_vm_variant_list_free(outputs); } TEST_F(TensorListModulesTest, IdentityThroughStack) { @@ -234,26 +230,27 @@ CreateBufferView(kBufferContents, shape, device_, &input_buffer_view); // Pass in the tensor as a HAL buffer view. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_buffer_view_ref = iree_hal_buffer_view_move_ref(input_buffer_view.get()); IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_retain(inputs, &input_buffer_view_ref)); + iree_vm_list_push_ref_retain(inputs.get(), &input_buffer_view_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke( context_, LookupFunction("identity_through_stack"), - /*policy=*/nullptr, inputs, outputs, IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_hal_buffer_view_t* returned_buffer_view = - iree_hal_buffer_view_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + auto* returned_buffer_view = + reinterpret_cast<iree_hal_buffer_view_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_hal_buffer_view_get_descriptor())); ASSERT_NE(nullptr, returned_buffer_view); iree_hal_buffer_t* returned_buffer = iree_hal_buffer_view_buffer(returned_buffer_view); @@ -268,8 +265,6 @@ mapped_memory.contents.data_length), 0); IREE_ASSERT_OK(iree_hal_buffer_unmap(returned_buffer, &mapped_memory)); - - iree_vm_variant_list_free(outputs); } } // namespace
diff --git a/iree/samples/custom_modules/BUILD b/iree/samples/custom_modules/BUILD index 7a65e51..036f5b2 100644 --- a/iree/samples/custom_modules/BUILD +++ b/iree/samples/custom_modules/BUILD
@@ -42,7 +42,7 @@ "//iree/testing:gtest_main", "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:ref", + "//iree/vm:ref_cc", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings", ],
diff --git a/iree/samples/custom_modules/CMakeLists.txt b/iree/samples/custom_modules/CMakeLists.txt index 44224a4..b98d0f4 100644 --- a/iree/samples/custom_modules/CMakeLists.txt +++ b/iree/samples/custom_modules/CMakeLists.txt
@@ -46,7 +46,7 @@ iree::testing::gtest_main iree::vm iree::vm::bytecode_module - iree::vm::ref + iree::vm::ref_cc ) iree_cc_library(
diff --git a/iree/samples/custom_modules/custom_modules_test.cc b/iree/samples/custom_modules/custom_modules_test.cc index 2bb38ca..51a0176 100644 --- a/iree/samples/custom_modules/custom_modules_test.cc +++ b/iree/samples/custom_modules/custom_modules_test.cc
@@ -25,7 +25,7 @@ #include "iree/testing/gtest.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/ref.h" +#include "iree/vm/ref_cc.h" namespace { @@ -104,34 +104,32 @@ // Pass in the message and number of times to print it. // TODO(benvanik): make a macro/magic. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(2, IREE_ALLOCATOR_SYSTEM, &inputs)); + iree::vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 2, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_message_ref = iree_custom_message_move_ref(input_message); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_move(inputs, &input_message_ref)); - IREE_ASSERT_OK(iree_vm_variant_list_append_value(inputs, count)); + IREE_ASSERT_OK(iree_vm_list_push_ref_move(inputs.get(), &input_message_ref)); + IREE_ASSERT_OK(iree_vm_list_push_value(inputs.get(), &count)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + iree::vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("reverseAndPrint"), - /*policy=*/nullptr, inputs, outputs, + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); // Read back the message that we reversed inside of the module. iree_custom_message_t* reversed_message = - iree_custom_message_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + (iree_custom_message_t*)iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_custom_message_get_descriptor()); ASSERT_NE(nullptr, reversed_message); char result_buffer[256]; IREE_ASSERT_OK(iree_custom_message_read_value(reversed_message, result_buffer, ABSL_ARRAYSIZE(result_buffer))); EXPECT_STREQ("!dlrow olleh", result_buffer); - - iree_vm_variant_list_free(outputs); } TEST_F(CustomModulesTest, PrintTensor) { @@ -147,33 +145,31 @@ IREE_ALLOCATOR_SYSTEM, IREE_ALLOCATOR_SYSTEM, &buffer)); // Pass in the tensor as an expanded HAL buffer. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + iree::vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_buffer_ref = iree_hal_buffer_move_ref(buffer); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_move(inputs, &input_buffer_ref)); + IREE_ASSERT_OK(iree_vm_list_push_ref_move(inputs.get(), &input_buffer_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + iree::vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("printTensor"), - /*policy=*/nullptr, inputs, outputs, + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); // Read back the message that we printed inside of the module. iree_custom_message_t* printed_message = - iree_custom_message_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + (iree_custom_message_t*)iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_custom_message_get_descriptor()); ASSERT_NE(nullptr, printed_message); char result_buffer[256]; IREE_ASSERT_OK(iree_custom_message_read_value(printed_message, result_buffer, ABSL_ARRAYSIZE(result_buffer))); EXPECT_STREQ("2x4xf32=[0 1 2 3][4 5 6 7]", result_buffer); - - iree_vm_variant_list_free(outputs); } TEST_F(CustomModulesTest, RoundTripTensor) { @@ -189,33 +185,31 @@ IREE_ALLOCATOR_SYSTEM, IREE_ALLOCATOR_SYSTEM, &buffer)); // Pass in the tensor as an expanded HAL buffer. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &inputs)); + iree::vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &inputs)); iree_vm_ref_t input_buffer_ref = iree_hal_buffer_move_ref(buffer); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_move(inputs, &input_buffer_ref)); + IREE_ASSERT_OK(iree_vm_list_push_ref_move(inputs.get(), &input_buffer_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + iree::vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. IREE_ASSERT_OK(iree_vm_invoke(context_, LookupFunction("roundTripTensor"), - /*policy=*/nullptr, inputs, outputs, + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); // Read back the message that's been moved around. iree_custom_message_t* printed_message = - iree_custom_message_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + (iree_custom_message_t*)iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_custom_message_get_descriptor()); ASSERT_NE(nullptr, printed_message); char result_buffer[256]; IREE_ASSERT_OK(iree_custom_message_read_value(printed_message, result_buffer, ABSL_ARRAYSIZE(result_buffer))); EXPECT_STREQ("2x4xf32=[0 1 2 3][4 5 6 7]", result_buffer); - - iree_vm_variant_list_free(outputs); } } // namespace
diff --git a/iree/samples/simple_embedding/BUILD b/iree/samples/simple_embedding/BUILD index 7a9ad60..5dad5bf 100644 --- a/iree/samples/simple_embedding/BUILD +++ b/iree/samples/simple_embedding/BUILD
@@ -49,8 +49,9 @@ "//iree/base:logging", "//iree/hal:api", "//iree/modules/hal", - "//iree/vm:bytecode_module", "//iree/vm", + "//iree/vm:bytecode_module", + "//iree/vm:ref_cc", # These are the drivers we support running with and can produce # executables for from the source MLIR.
diff --git a/iree/samples/simple_embedding/CMakeLists.txt b/iree/samples/simple_embedding/CMakeLists.txt index 2e648e5..1001ec8 100644 --- a/iree/samples/simple_embedding/CMakeLists.txt +++ b/iree/samples/simple_embedding/CMakeLists.txt
@@ -49,6 +49,7 @@ iree::testing::gtest_main iree::vm iree::vm::bytecode_module + iree::vm::ref_cc LABELS "driver=vulkan" )
diff --git a/iree/samples/simple_embedding/simple_embedding_test.cc b/iree/samples/simple_embedding/simple_embedding_test.cc index 4e4cc9a..489ac33 100644 --- a/iree/samples/simple_embedding/simple_embedding_test.cc +++ b/iree/samples/simple_embedding/simple_embedding_test.cc
@@ -23,6 +23,7 @@ #include "iree/testing/gtest.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" +#include "iree/vm/ref_cc.h" // Compiled module embedded here to avoid file IO: #include "iree/samples/simple_embedding/simple_embedding_test_bytecode_module.h" @@ -144,31 +145,30 @@ // Setup call inputs with our buffers. // TODO(benvanik): make a macro/magic. - iree_vm_variant_list_t* inputs = nullptr; - IREE_ASSERT_OK(iree_vm_variant_list_alloc(2, IREE_ALLOCATOR_SYSTEM, &inputs)); + vm::ref<iree_vm_list_t> inputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 2, + IREE_ALLOCATOR_SYSTEM, &inputs)); auto arg0_buffer_ref = iree_hal_buffer_move_ref(arg0_buffer); auto arg1_buffer_ref = iree_hal_buffer_move_ref(arg1_buffer); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_move(inputs, &arg0_buffer_ref)); - IREE_ASSERT_OK( - iree_vm_variant_list_append_ref_move(inputs, &arg1_buffer_ref)); + IREE_ASSERT_OK(iree_vm_list_push_ref_move(inputs.get(), &arg0_buffer_ref)); + IREE_ASSERT_OK(iree_vm_list_push_ref_move(inputs.get(), &arg1_buffer_ref)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* outputs = nullptr; - IREE_ASSERT_OK( - iree_vm_variant_list_alloc(1, IREE_ALLOCATOR_SYSTEM, &outputs)); + vm::ref<iree_vm_list_t> outputs; + IREE_ASSERT_OK(iree_vm_list_create(/*element_type=*/nullptr, 1, + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. LOG(INFO) << "Calling " << kMainFunctionName << "..."; IREE_ASSERT_OK(iree_vm_invoke(context, main_function, - /*policy=*/nullptr, inputs, outputs, + /*policy=*/nullptr, inputs.get(), outputs.get(), IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(inputs); // Get the result buffers from the invocation. LOG(INFO) << "Retreiving results..."; - iree_hal_buffer_t* ret_buffer = - iree_hal_buffer_deref(&iree_vm_variant_list_get(outputs, 0)->ref); + auto* ret_buffer = + reinterpret_cast<iree_hal_buffer_t*>(iree_vm_list_get_ref_deref( + outputs.get(), 0, iree_hal_buffer_get_descriptor())); ASSERT_NE(nullptr, ret_buffer); // Read back the results and ensure we got the right values. @@ -183,8 +183,8 @@ ASSERT_API_OK(iree_hal_buffer_unmap(ret_buffer, &mapped_memory)); LOG(INFO) << "Results match!"; - iree_vm_variant_list_free(outputs); - + inputs.reset(); + outputs.reset(); iree_hal_device_release(device); iree_vm_context_release(context); iree_vm_instance_release(instance);
diff --git a/iree/samples/vulkan/BUILD b/iree/samples/vulkan/BUILD index 7bf6f7e..b684de7 100644 --- a/iree/samples/vulkan/BUILD +++ b/iree/samples/vulkan/BUILD
@@ -55,6 +55,7 @@ "//iree/modules/hal", "//iree/vm", "//iree/vm:bytecode_module", + "//iree/vm:ref_cc", "@com_google_absl//absl/base:core_headers", "@dear_imgui", "@dear_imgui//:imgui_sdl_vulkan",
diff --git a/iree/samples/vulkan/CMakeLists.txt b/iree/samples/vulkan/CMakeLists.txt index 17c7579..8d83188 100644 --- a/iree/samples/vulkan/CMakeLists.txt +++ b/iree/samples/vulkan/CMakeLists.txt
@@ -59,6 +59,7 @@ iree::samples::vulkan::simple_mul_bytecode_module_cc iree::vm iree::vm::bytecode_module + iree::vm::ref_cc SDL2-static Vulkan::Vulkan LINKOPTS
diff --git a/iree/samples/vulkan/vulkan_inference_gui.cc b/iree/samples/vulkan/vulkan_inference_gui.cc index b4b75ce..d939a76 100644 --- a/iree/samples/vulkan/vulkan_inference_gui.cc +++ b/iree/samples/vulkan/vulkan_inference_gui.cc
@@ -35,6 +35,7 @@ #include "iree/modules/hal/hal_module.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" +#include "iree/vm/ref_cc.h" // Other dependencies (helpers, etc.) #include "absl/base/macros.h" @@ -723,36 +724,34 @@ iree_hal_buffer_release(input0_buffer); iree_hal_buffer_release(input1_buffer); // Marshal input buffer views through a VM variant list. - iree_vm_variant_list_t* input_list = nullptr; - CHECK_IREE_OK( - iree_vm_variant_list_alloc(2, IREE_ALLOCATOR_SYSTEM, &input_list)); + vm::ref<iree_vm_list_t> inputs; + CHECK_IREE_OK(iree_vm_list_create(/*element_type=*/nullptr, 2, + IREE_ALLOCATOR_SYSTEM, &inputs)); auto input0_buffer_view_ref = iree_hal_buffer_view_move_ref(input0_buffer_view); auto input1_buffer_view_ref = iree_hal_buffer_view_move_ref(input1_buffer_view); - CHECK_IREE_OK(iree_vm_variant_list_append_ref_move( - input_list, &input0_buffer_view_ref)); - CHECK_IREE_OK(iree_vm_variant_list_append_ref_move( - input_list, &input1_buffer_view_ref)); + CHECK_IREE_OK( + iree_vm_list_push_ref_move(inputs.get(), &input0_buffer_view_ref)); + CHECK_IREE_OK( + iree_vm_list_push_ref_move(inputs.get(), &input1_buffer_view_ref)); // Prepare outputs list to accept results from the invocation. - iree_vm_variant_list_t* output_list = nullptr; - CHECK_IREE_OK(iree_vm_variant_list_alloc(kElementCount * sizeof(float), - IREE_ALLOCATOR_SYSTEM, - &output_list)); + vm::ref<iree_vm_list_t> outputs; + CHECK_IREE_OK(iree_vm_list_create(/*element_type=*/nullptr, + kElementCount * sizeof(float), + IREE_ALLOCATOR_SYSTEM, &outputs)); // Synchronously invoke the function. CHECK_IREE_OK(iree_vm_invoke(iree_context, main_function, - /*policy=*/nullptr, input_list, - output_list, IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(input_list); + /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM)); // Read back the results. DLOG(INFO) << "Reading back results..."; - iree_vm_variant_t* output_variant = - iree_vm_variant_list_get(output_list, 0); - auto* output_buffer_view = - iree_hal_buffer_view_deref(&output_variant->ref); + auto* output_buffer_view = reinterpret_cast<iree_hal_buffer_view_t*>( + iree_vm_list_get_ref_deref(outputs.get(), 0, + iree_hal_buffer_view_get_descriptor())); auto* output_buffer = iree_hal_buffer_view_buffer(output_buffer_view); iree_hal_mapped_memory_t mapped_memory; CHECK_IREE_OK(iree_hal_buffer_map(output_buffer, @@ -761,7 +760,6 @@ memcpy(&latest_output, mapped_memory.contents.data, mapped_memory.contents.data_length); iree_hal_buffer_unmap(output_buffer, &mapped_memory); - iree_vm_variant_list_free(output_list); dirty = false; }
diff --git a/iree/schemas/bytecode_module_def.fbs b/iree/schemas/bytecode_module_def.fbs index f431332..2394afb 100644 --- a/iree/schemas/bytecode_module_def.fbs +++ b/iree/schemas/bytecode_module_def.fbs
@@ -43,7 +43,7 @@ // Function level reflection attributes. // These are typically used to communicate additional ABI metadata needed // for dynamic invocation and host language mapping. - // See: docs/function_abi.md + // See: docs/design_docs/function_abi.md reflection_attrs:[ReflectionAttrDef]; }
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir new file mode 100644 index 0000000..ce42e31 --- /dev/null +++ b/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir
@@ -0,0 +1,58 @@ +// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2xi32=[6, 7] [8, 9]" -input-value="2x2x2x2xi32=[[[0, 1] [1, 0]] [[0, 0] [1, 1]]] [[[1, 1] [0, 0]] [[0, 1] [1, 0]]]" | IreeFileCheck %s + +// CHECK-LABEL: EXEC @torch_index_select1 +func @torch_index_select1(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?x?x?xi32>) -> tensor<?x?x?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 1 : i64, dim = 1 : i64} : (tensor<?x?xi32>, tensor<?x?x?x?xi32>) -> tensor<?x?x?x?xi32> + return %0 : tensor<?x?x?x?xi32> +} + +// CHECK: 2x2x2x2xi32=[ +// CHECK-SAME: [ +// CHECK-SAME: [6 7][7 6] +// CHECK-SAME: ][ +// CHECK-SAME: [6 6][7 7] +// CHECK-SAME: ] +// CHECK-SAME: ][ +// CHECK-SAME: [ +// CHECK-SAME: [9 9][8 8] +// CHECK-SAME: ][ +// CHECK-SAME: [8 9][9 8] +// CHECK-SAME: ] +// CHECK-SAME: ] + +// CHECK-LABEL: EXEC @torch_index_select2 +func @torch_index_select2(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?x?x?xi32>) -> tensor<?x?x?x?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 0 : i64, dim = 0 : i64} : (tensor<?x?xi32>, tensor<?x?x?x?xi32>) -> tensor<?x?x?x?x?xi32> + return %0 : tensor<?x?x?x?x?xi32> +} + +// CHECK: 2x2x2x2x2xi32=[ +// CHECK-SAME: [ +// CHECK-SAME: [ +// CHECK-SAME: [6 7][8 9] +// CHECK-SAME: ][ +// CHECK-SAME: [8 9][6 7] +// CHECK-SAME: ] +// CHECK-SAME: ][ +// CHECK-SAME: [ +// CHECK-SAME: [6 7][6 7] +// CHECK-SAME: ][ +// CHECK-SAME: [8 9][8 9] +// CHECK-SAME: ] +// CHECK-SAME: ] +// CHECK-SAME: ][ +// CHECK-SAME: [ +// CHECK-SAME: [ +// CHECK-SAME: [8 9][8 9] +// CHECK-SAME: ][ +// CHECK-SAME: [6 7][6 7] +// CHECK-SAME: ] +// CHECK-SAME: ][ +// CHECK-SAME: [ +// CHECK-SAME: [6 7][8 9] +// CHECK-SAME: ][ +// CHECK-SAME: [8 9][6 7] +// CHECK-SAME: ] +// CHECK-SAME: ] +// CHECK-SAME: ] +
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir new file mode 100644 index 0000000..0755b5c --- /dev/null +++ b/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir
@@ -0,0 +1,14 @@ +// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2x2xi32=[[100, 101] [110, 111]] [[200, 201] [210, 211]]" -input-value="2x2x2xi32=[[0, 1] [1, 0]] [[0, 0] [1, 1]]" | IreeFileCheck %s + +// CHECK-LABEL: EXEC @torch_index_select1 +func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<?x?x?xi32>) -> tensor<?x?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = -1 : i64, dim = -1 : i64} : (tensor<?x?x?xi32>, tensor<?x?x?xi32>) -> tensor<?x?x?xi32> + return %0 : tensor<?x?x?xi32> +} + +// CHECK: 2x2x2xi32=[ +// CHECK-SAME: [100 101][111 110] +// CHECK-SAME: ][ +// CHECK-SAME: [200 200][211 211] +// CHECK-SAME: ] +
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir new file mode 100644 index 0000000..8ccb4fa --- /dev/null +++ b/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir
@@ -0,0 +1,17 @@ +// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="5x1x5xi32=[[1,2,3,4,5]] [[6,7,8,9,10]] [[11,12,13,14,15]] [[16,17,18,19,20]] [[21,22,23,24,25]]" -input-value="i32=0" | IreeFileCheck %s + +// CHECK-LABEL: EXEC @torch_index_select1 +func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<i32>) -> tensor<?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 0 : i64, dim = 0 : i64} : (tensor<?x?x?xi32>, tensor<i32>) -> tensor<?x?xi32> + return %0 : tensor<?x?xi32> +} + +// CHECK: 1x5xi32=[1 2 3 4 5] + +// CHECK-LABEL: EXEC @torch_index_select2 +func @torch_index_select2(%arg0: tensor<?x?x?xi32>, %arg1: tensor<i32>) -> tensor<?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 0 : i64, dim = 1 : i64} : (tensor<?x?x?xi32>, tensor<i32>) -> tensor<?x?xi32> + return %0 : tensor<?x?xi32> +} + +// CHECK: 5x5xi32=[1 2 3 4 5][6 7 8 9 10][11 12 13 14 15][16 17 18 19 20][21 22 23 24 25]
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir new file mode 100644 index 0000000..d22ccc7 --- /dev/null +++ b/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir
@@ -0,0 +1,28 @@ +// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="3x2x2xi32=[[1, 2] [3, 4]] [[5, 6] [7, 8]] [[9, 10] [11, 12]]" -input-value="2xi32=[0, 1]" | IreeFileCheck %s + +// CHECK-LABEL: EXEC @torch_index_select1 +func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<?xi32>) -> tensor<?x?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 0 : i64, dim = 1 : i64} : (tensor<?x?x?xi32>, tensor<?xi32>) -> tensor<?x?x?xi32> + return %0 : tensor<?x?x?xi32> +} + +// CHECK: 3x2x2xi32=[ +// CHECK-SAME: [1 2][3 4] +// CHECK-SAME: ][ +// CHECK-SAME: [5 6][7 8] +// CHECK-SAME: ][ +// CHECK-SAME: [9 10][11 12] +// CHECK-SAME: ] + +// CHECK-LABEL: EXEC @torch_index_select2 +func @torch_index_select2(%arg0: tensor<?x?x?xi32>, %arg1: tensor<?xi32>) -> tensor<?x?x?xi32> attributes {iree.module.export} { + %0 = "mhlo.torch_index_select"(%arg0, %arg1) {batch_dims = 0 : i64, dim = 0 : i64} : (tensor<?x?x?xi32>, tensor<?xi32>) -> tensor<?x?x?xi32> + return %0 : tensor<?x?x?xi32> +} + +// CHECK: 2x2x2xi32=[ +// CHECK-SAME: [1 2][3 4] +// CHECK-SAME: ][ +// CHECK-SAME: [5 6][7 8] +// CHECK-SAME: ] +
diff --git a/iree/test/e2e/vulkan_specific/BUILD b/iree/test/e2e/vulkan_specific/BUILD index 0565a86..4d20c33 100644 --- a/iree/test/e2e/vulkan_specific/BUILD +++ b/iree/test/e2e/vulkan_specific/BUILD
@@ -29,38 +29,3 @@ driver = "vulkan", target_backend = "vulkan-spirv", ) - -# TODO(#2345): Merge two tests into one single file. -iree_check_single_backend_test_suite( - name = "check_vulkan-spirv-split-pad-conv_vulkan", - srcs = [ - "convolution1.mlir", - "convolution2.mlir", - ], - driver = "vulkan", - target_backend = "vulkan-spirv", -) - -# TODO(#2345): Merge two tests into one single file. -iree_check_single_backend_test_suite( - name = "check_vulkan-spirv-nosplit-pad-conv_vulkan", - srcs = [ - "convolution1.mlir", - "convolution2.mlir", - ], - compiler_flags = ["-iree-extract-pad-from-conv=false"], - driver = "vulkan", - target_backend = "vulkan-spirv", -) - -# TODO(#2345): Merge two tests into one single file. -iree_check_single_backend_test_suite( - name = "check_vulkan-spirv-conv-nocontrol_vulkan", - srcs = [ - "convolution1.mlir", - "convolution2.mlir", - ], - compiler_flags = ["-iree-codegen-use-legacy-conv-lowering=false"], - driver = "vulkan", - target_backend = "vulkan-spirv", -)
diff --git a/iree/test/e2e/vulkan_specific/CMakeLists.txt b/iree/test/e2e/vulkan_specific/CMakeLists.txt index cca6c58..32ee021 100644 --- a/iree/test/e2e/vulkan_specific/CMakeLists.txt +++ b/iree/test/e2e/vulkan_specific/CMakeLists.txt
@@ -25,43 +25,3 @@ DRIVER vulkan ) - -iree_check_single_backend_test_suite( - NAME - check_vulkan-spirv-split-pad-conv_vulkan - SRCS - "convolution1.mlir" - "convolution2.mlir" - TARGET_BACKEND - vulkan-spirv - DRIVER - vulkan -) - -iree_check_single_backend_test_suite( - NAME - check_vulkan-spirv-nosplit-pad-conv_vulkan - SRCS - "convolution1.mlir" - "convolution2.mlir" - TARGET_BACKEND - vulkan-spirv - DRIVER - vulkan - COMPILER_FLAGS - "-iree-extract-pad-from-conv=false" -) - -iree_check_single_backend_test_suite( - NAME - check_vulkan-spirv-conv-nocontrol_vulkan - SRCS - "convolution1.mlir" - "convolution2.mlir" - TARGET_BACKEND - vulkan-spirv - DRIVER - vulkan - COMPILER_FLAGS - "-iree-codegen-use-legacy-conv-lowering=false" -)
diff --git a/iree/test/e2e/vulkan_specific/convolution1.mlir b/iree/test/e2e/vulkan_specific/convolution1.mlir deleted file mode 100644 index d0fc606..0000000 --- a/iree/test/e2e/vulkan_specific/convolution1.mlir +++ /dev/null
@@ -1,66 +0,0 @@ -func @conv2d_nopadding() attributes { iree.module.export } { - %inputs = iree.unfoldable_constant dense<[[ - [[ 1.0, 2.0], [ 3.0, 4.0], [ 5.0, 6.0], [ 7.0, 8.0], [ 9.0, 10.0]], - [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [19.0, 20.0]], - [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0], [29.0, 30.0]], - [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0], [39.0, 40.0]]]]> : tensor<1x4x5x2xf32> - %weights = iree.unfoldable_constant dense<[ - [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]], - [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]], - [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32> - %res = "mhlo.convolution"(%inputs, %weights) { - batch_group_count = 1 : i64, - dimension_numbers = { - input_batch_dimension = 0 : i64, - input_feature_dimension = 3 : i64, - input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, - kernel_input_feature_dimension = 2 : i64, - kernel_output_feature_dimension = 3 : i64, - kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, - output_batch_dimension = 0 : i64, - output_feature_dimension = 3 : i64, - output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, - feature_group_count = 1 : i64, - rhs_dilation = dense<1> : tensor<2xi64>, - window_strides = dense<1> : tensor<2xi64>} : (tensor<1x4x5x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x2x3x1xf32> - check.expect_almost_eq_const(%res, dense<[[ - [[1310.0],[1466.0],[1622.0]], - [[2090.0],[2246.0],[2402.0]] - ]]> : tensor<1x2x3x1xf32>) : tensor<1x2x3x1xf32> - return -} - -func @conv2d_1452x3221_same() attributes { iree.module.export } { - %inputs = iree.unfoldable_constant dense<[[ - [[ 1.0, 2.0], [ 3.0, 4.0], [ 5.0, 6.0], [ 7.0, 8.0], [ 9.0, 10.0]], - [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [19.0, 20.0]], - [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0], [29.0, 30.0]], - [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0], [39.0, 40.0]]]]> : tensor<1x4x5x2xf32> - %weights = iree.unfoldable_constant dense<[ - [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]], - [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]], - [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32> - %res = "mhlo.convolution"(%inputs, %weights) { - batch_group_count = 1 : i64, - dimension_numbers = { - input_batch_dimension = 0 : i64, - input_feature_dimension = 3 : i64, - input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, - kernel_input_feature_dimension = 2 : i64, - kernel_output_feature_dimension = 3 : i64, - kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, - output_batch_dimension = 0 : i64, - output_feature_dimension = 3 : i64, - output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, - feature_group_count = 1 : i64, - padding = dense<[[1, 1], [0, 1]]> : tensor<2x2xi64>, - rhs_dilation = dense<1> : tensor<2xi64>, - window_strides = dense<1> : tensor<2xi64>} : - (tensor<1x4x5x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x4x5x1xf32> - check.expect_almost_eq_const(%res, dense<[[ - [[ 600.0], [ 736.0], [ 872.0], [1008.0], [ 476.0]], - [[1310.0], [1466.0], [1622.0], [1778.0], [ 805.0]], - [[2090.0], [2246.0], [2402.0], [2558.0], [1135.0]], - [[1080.0], [1152.0], [1224.0], [1296.0], [ 524.0]]]]> : tensor<1x4x5x1xf32>) : tensor<1x4x5x1xf32> - return -}
diff --git a/iree/test/e2e/vulkan_specific/convolution2.mlir b/iree/test/e2e/vulkan_specific/convolution2.mlir deleted file mode 100644 index ce88d5d..0000000 --- a/iree/test/e2e/vulkan_specific/convolution2.mlir +++ /dev/null
@@ -1,140 +0,0 @@ -func @conv2d_2451x2311_same() attributes { iree.module.export } { - %inputs = iree.unfoldable_constant dense<[ - [[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0]], - [[ 6.0], [ 7.0], [ 8.0], [ 9.0], [10.0]], - [[11.0], [12.0], [13.0], [14.0], [15.0]], - [[16.0], [17.0], [18.0], [19.0], [20.0]]], - [[[21.0], [22.0], [23.0], [24.0], [25.0]], - [[26.0], [27.0], [28.0], [29.0], [30.0]], - [[31.0], [32.0], [33.0], [34.0], [35.0]], - [[36.0], [37.0], [38.0], [39.0], [40.0]]]]> : tensor <2x4x5x1xf32> - %weights = iree.unfoldable_constant dense<[ - [[[1.0]], [[2.0]], [[3.0]]], - [[[4.0]], [[5.0]], [[6.0]]]]> : tensor <2x3x1x1xf32> - %res = "mhlo.convolution"(%inputs, %weights) { - batch_group_count = 1 : i64, - dimension_numbers = { - input_batch_dimension = 0 : i64, - input_feature_dimension = 3 : i64, - input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, - kernel_input_feature_dimension = 2 : i64, - kernel_output_feature_dimension = 3 : i64, - kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, - output_batch_dimension = 0 : i64, - output_feature_dimension = 3 : i64, - output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, - feature_group_count = 1 : i64, - padding = dense<[[0, 1], [1, 1]]> : tensor<2x2xi64>, - rhs_dilation = dense<1> : tensor<2xi64>, - window_strides = dense<1> : tensor<2xi64>} : - (tensor<2x4x5x1xf32>, tensor<2x3x1x1xf32>) -> tensor<2x4x5x1xf32> - check.expect_almost_eq_const(%res, dense<[ - [[[ 80.0], [121.0], [142.0], [163.0], [100.0]], - [[160.0], [226.0], [247.0], [268.0], [160.0]], - [[240.0], [331.0], [352.0], [373.0], [220.0]], - [[ 83.0], [104.0], [110.0], [116.0], [ 59.0]]], - [[[400.0], [541.0], [562.0], [583.0], [340.0]], - [[480.0], [646.0], [667.0], [688.0], [400.0]], - [[560.0], [751.0], [772.0], [793.0], [460.0]], - [[183.0], [224.0], [230.0], [236.0], [119.0]]]]> : tensor<2x4x5x1xf32>) : tensor<2x4x5x1xf32> - return -} - -func @conv2d_no_padding() attributes { iree.module.export } { - %inputs = iree.unfoldable_constant dense<[ - [[[ 1.0, 2.0, 3.0], - [ 4.0, 5.0, 6.0], - [ 7.0, 8.0, 9.0], - [ 10.0, 11.0, 12.0], - [ 13.0, 14.0, 15.0]], - [[ 16.0, 17.0, 18.0], - [ 19.0, 20.0, 21.0], - [ 22.0, 23.0, 24.0], - [ 25.0, 26.0, 27.0], - [ 28.0, 29.0, 30.0]], - [[ 31.0, 32.0, 33.0], - [ 34.0, 35.0, 36.0], - [ 37.0, 38.0, 39.0], - [ 40.0, 41.0, 42.0], - [ 43.0, 44.0, 45.0]], - [[ 46.0, 47.0, 48.0], - [ 49.0, 50.0, 51.0], - [ 52.0, 53.0, 54.0], - [ 55.0, 56.0, 57.0], - [ 58.0, 59.0, 60.0]]], - [[[ 61.0, 62.0, 63.0], - [ 64.0, 65.0, 66.0], - [ 67.0, 68.0, 69.0], - [ 70.0, 71.0, 72.0], - [ 73.0, 74.0, 75.0]], - [[ 76.0, 77.0, 78.0], - [ 79.0, 80.0, 81.0], - [ 82.0, 83.0, 84.0], - [ 85.0, 86.0, 87.0], - [ 88.0, 89.0, 90.0]], - [[ 91.0, 92.0, 93.0], - [ 94.0, 95.0, 96.0], - [ 97.0, 98.0, 99.0], - [100.0, 101.0, 102.0], - [103.0, 104.0, 105.0]], - [[106.0, 107.0, 108.0], - [109.0, 110.0, 111.0], - [112.0, 113.0, 114.0], - [115.0, 116.0, 117.0], - [118.0, 119.0, 120.0]]]]> : tensor<2x4x5x3xf32> - %weights = iree.unfoldable_constant dense<[ - [[[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0], - [ 7.0, 8.0, 9.0, 10.0, 11.0, 12.0], - [ 13.0, 14.0, 15.0, 16.0, 17.0, 18.0]], - [[ 19.0, 20.0, 21.0, 22.0, 23.0, 24.0], - [ 25.0, 26.0, 27.0, 28.0, 29.0, 30.0], - [ 31.0, 32.0, 33.0, 34.0, 35.0, 36.0]], - [[ 37.0, 38.0, 39.0, 40.0, 41.0, 42.0], - [ 43.0, 44.0, 45.0, 46.0, 47.0, 48.0], - [ 49.0, 50.0, 51.0, 52.0, 53.0, 54.0]]], - [[[ 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - [ 61.0, 62.0, 63.0, 64.0, 65.0, 66.0], - [ 67.0, 68.0, 69.0, 70.0, 71.0, 72.0]], - [[ 73.0, 74.0, 75.0, 76.0, 77.0, 78.0], - [ 79.0, 80.0, 81.0, 82.0, 83.0, 84.0], - [ 85.0, 86.0, 87.0, 88.0, 89.0, 90.0]], - [[ 91.0, 92.0, 93.0, 94.0, 95.0, 96.0], - [ 97.0, 98.0, 99.0, 100.0, 101.0, 102.0], - [103.0, 104.0, 105.0, 106.0, 107.0, 108.0]]]]> : tensor<2x3x3x6xf32> - %res = "mhlo.convolution"(%inputs, %weights) { - batch_group_count = 1 : i64, - dimension_numbers = { - input_batch_dimension = 0 : i64, - input_feature_dimension = 3 : i64, - input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, - kernel_input_feature_dimension = 2 : i64, - kernel_output_feature_dimension = 3 : i64, - kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, - output_batch_dimension = 0 : i64, - output_feature_dimension = 3 : i64, - output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, - feature_group_count = 1 : i64, - rhs_dilation = dense<1> : tensor<2xi64>, - window_strides = dense<1> : tensor<2xi64>} : - (tensor<2x4x5x3xf32>, tensor<2x3x3x6xf32>) -> tensor<2x3x3x6xf32> - check.expect_almost_eq_const(%res, dense<[ - [[[16065.0, 16290.0, 16515.0, 16740.0, 16965.0, 17190.0], - [18873.0, 19152.0, 19431.0, 19710.0, 19989.0, 20268.0], - [21681.0, 22014.0, 22347.0, 22680.0, 23013.0, 23346.0]], - [[30105.0, 30600.0, 31095.0, 31590.0, 32085.0, 32580.0], - [32913.0, 33462.0, 34011.0, 34560.0, 35109.0, 35658.0], - [35721.0, 36324.0, 36927.0, 37530.0, 38133.0, 38736.0]], - [[44145.0, 44910.0, 45675.0, 46440.0, 47205.0, 47970.0], - [46953.0, 47772.0, 48591.0, 49410.0, 50229.0, 51048.0], - [49761.0, 50634.0, 51507.0, 52380.0, 53253.0, 54126.0]]], - [[[72225.0, 73530.0, 74835.0, 76140.0, 77445.0, 78750.0], - [75033.0, 76392.0, 77751.0, 79110.0, 80469.0, 81828.0], - [77841.0, 79254.0, 80667.0, 82080.0, 83493.0, 84906.0]], - [[86265.0, 87840.0, 89415.0, 90990.0, 92565.0, 94140.0], - [89073.0, 90702.0, 92331.0, 93960.0, 95589.0, 97218.0], - [91881.0, 93564.0, 95247.0, 96930.0, 98613.0, 100296.0]], - [[100305.0, 102150.0, 103995.0, 105840.0, 107685.0, 109530.0], - [103113.0, 105012.0, 106911.0, 108810.0, 110709.0, 112608.0], - [105921.0, 107874.0, 109827.0, 111780.0, 113733.0, 115686.0]]]]> : tensor<2x3x3x6xf32>) : tensor<2x3x3x6xf32> - return -}
diff --git a/iree/test/e2e/xla_ops/convolution.mlir b/iree/test/e2e/xla_ops/convolution.mlir index 22c5258..6ac1719 100644 --- a/iree/test/e2e/xla_ops/convolution.mlir +++ b/iree/test/e2e/xla_ops/convolution.mlir
@@ -65,51 +65,47 @@ return } -// TODO(#2345): This test seems to fail when executed with another -// test from this file, but passes as a standalone test. Needs further -// investigation - -// func @conv2d_2451x2311_same() attributes { iree.module.export } { -// %inputs = iree.unfoldable_constant dense<[ -// [[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0]], -// [[ 6.0], [ 7.0], [ 8.0], [ 9.0], [10.0]], -// [[11.0], [12.0], [13.0], [14.0], [15.0]], -// [[16.0], [17.0], [18.0], [19.0], [20.0]]], -// [[[21.0], [22.0], [23.0], [24.0], [25.0]], -// [[26.0], [27.0], [28.0], [29.0], [30.0]], -// [[31.0], [32.0], [33.0], [34.0], [35.0]], -// [[36.0], [37.0], [38.0], [39.0], [40.0]]]]> : tensor <2x4x5x1xf32> -// %weights = iree.unfoldable_constant dense<[ -// [[[1.0]], [[2.0]], [[3.0]]], -// [[[4.0]], [[5.0]], [[6.0]]]]> : tensor <2x3x1x1xf32> -// %res = "mhlo.convolution"(%inputs, %weights) { -// batch_group_count = 1 : i64, -// dimension_numbers = { -// input_batch_dimension = 0 : i64, -// input_feature_dimension = 3 : i64, -// input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, -// kernel_input_feature_dimension = 2 : i64, -// kernel_output_feature_dimension = 3 : i64, -// kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, -// output_batch_dimension = 0 : i64, -// output_feature_dimension = 3 : i64, -// output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, -// feature_group_count = 1 : i64, -// padding = dense<[[0, 1], [1, 1]]> : tensor<2x2xi64>, -// rhs_dilation = dense<1> : tensor<2xi64>, -// window_strides = dense<1> : tensor<2xi64>} : -// (tensor<2x4x5x1xf32>, tensor<2x3x1x1xf32>) -> tensor<2x4x5x1xf32> -// check.expect_almost_eq_const(%res, dense<[ -// [[[ 80.0], [121.0], [142.0], [163.0], [100.0]], -// [[160.0], [226.0], [247.0], [268.0], [160.0]], -// [[240.0], [331.0], [352.0], [373.0], [220.0]], -// [[ 83.0], [104.0], [110.0], [116.0], [ 59.0]]], -// [[[400.0], [541.0], [562.0], [583.0], [340.0]], -// [[480.0], [646.0], [667.0], [688.0], [400.0]], -// [[560.0], [751.0], [772.0], [793.0], [460.0]], -// [[183.0], [224.0], [230.0], [236.0], [119.0]]]]> : tensor<2x4x5x1xf32>) : tensor<2x4x5x1xf32> -// return -// } +func @conv2d_2451x2311_same() attributes { iree.module.export } { + %inputs = iree.unfoldable_constant dense<[ + [[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0]], + [[ 6.0], [ 7.0], [ 8.0], [ 9.0], [10.0]], + [[11.0], [12.0], [13.0], [14.0], [15.0]], + [[16.0], [17.0], [18.0], [19.0], [20.0]]], + [[[21.0], [22.0], [23.0], [24.0], [25.0]], + [[26.0], [27.0], [28.0], [29.0], [30.0]], + [[31.0], [32.0], [33.0], [34.0], [35.0]], + [[36.0], [37.0], [38.0], [39.0], [40.0]]]]> : tensor <2x4x5x1xf32> + %weights = iree.unfoldable_constant dense<[ + [[[1.0]], [[2.0]], [[3.0]]], + [[[4.0]], [[5.0]], [[6.0]]]]> : tensor <2x3x1x1xf32> + %res = "mhlo.convolution"(%inputs, %weights) { + batch_group_count = 1 : i64, + dimension_numbers = { + input_batch_dimension = 0 : i64, + input_feature_dimension = 3 : i64, + input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, + kernel_input_feature_dimension = 2 : i64, + kernel_output_feature_dimension = 3 : i64, + kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, + output_batch_dimension = 0 : i64, + output_feature_dimension = 3 : i64, + output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, + feature_group_count = 1 : i64, + padding = dense<[[0, 1], [1, 1]]> : tensor<2x2xi64>, + rhs_dilation = dense<1> : tensor<2xi64>, + window_strides = dense<1> : tensor<2xi64>} : + (tensor<2x4x5x1xf32>, tensor<2x3x1x1xf32>) -> tensor<2x4x5x1xf32> + check.expect_almost_eq_const(%res, dense<[ + [[[ 80.0], [121.0], [142.0], [163.0], [100.0]], + [[160.0], [226.0], [247.0], [268.0], [160.0]], + [[240.0], [331.0], [352.0], [373.0], [220.0]], + [[ 83.0], [104.0], [110.0], [116.0], [ 59.0]]], + [[[400.0], [541.0], [562.0], [583.0], [340.0]], + [[480.0], [646.0], [667.0], [688.0], [400.0]], + [[560.0], [751.0], [772.0], [793.0], [460.0]], + [[183.0], [224.0], [230.0], [236.0], [119.0]]]]> : tensor<2x4x5x1xf32>) : tensor<2x4x5x1xf32> + return +} func @conv2d_no_padding2() attributes { iree.module.export } { %inputs = iree.unfoldable_constant dense<[
diff --git a/iree/test/e2e/xla_ops/iota.mlir b/iree/test/e2e/xla_ops/iota.mlir new file mode 100644 index 0000000..c3ff040 --- /dev/null +++ b/iree/test/e2e/xla_ops/iota.mlir
@@ -0,0 +1,16 @@ +func @iota_dim0() attributes { iree.module.export } { + %result = "mhlo.iota"() {iota_dimension = 0 : i64} : () -> tensor<2x3xf32> + check.expect_almost_eq_const(%result, dense<[ + [0.0, 0.0, 0.0], + [1.0, 1.0, 1.0]]> : tensor<2x3xf32>) : tensor<2x3xf32> + return +} + + +func @iota_dim1() attributes { iree.module.export } { + %result = "mhlo.iota"() {iota_dimension = 1 : i64} : () -> tensor<2x3xf32> + check.expect_almost_eq_const(%result, dense<[ + [0.0, 1.0, 2.0], + [0.0, 1.0, 2.0]]> : tensor<2x3xf32>) : tensor<2x3xf32> + return +}
diff --git a/iree/test/e2e/xla_ops/pad.mlir b/iree/test/e2e/xla_ops/pad.mlir index 7f6df37..537e684 100644 --- a/iree/test/e2e/xla_ops/pad.mlir +++ b/iree/test/e2e/xla_ops/pad.mlir
@@ -20,3 +20,19 @@ check.expect_eq(%res, %input) : tensor<2x3xi32> return } + +func @pad_with_interior_padding() attributes { iree.module.export } { + %input = iree.unfoldable_constant dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32> + %c0 = iree.unfoldable_constant dense<0> : tensor<i32> + %res = "mhlo.pad"(%input, %c0) { + edge_padding_low = dense<[0, 1]> : tensor<2xi64>, + edge_padding_high = dense<[1, 5]> : tensor<2xi64>, + interior_padding = dense<[1, 2]> : tensor<2xi64> + } : (tensor<2x3xi32>, tensor<i32>) -> tensor<4x13xi32> + check.expect_eq_const(%res, dense<[ + [0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]> : tensor<4x13xi32>) : tensor<4x13xi32> + return +}
diff --git a/iree/tools/BUILD b/iree/tools/BUILD index 0f59359..46ea8a9 100644 --- a/iree/tools/BUILD +++ b/iree/tools/BUILD
@@ -50,6 +50,7 @@ "//iree/base:tracing", "//iree/modules/hal", "//iree/testing:benchmark_main", + "//iree/vm", "//iree/vm:bytecode_module", ] + PLATFORM_VULKAN_DEPS + IREE_DRIVER_MODULES, ) @@ -254,7 +255,6 @@ "//iree/modules/hal", "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:value", "@llvm-project//llvm:Support", "@llvm-project//mlir:IR", "@llvm-project//mlir:SCFTransforms", @@ -282,6 +282,7 @@ "//iree/base:status", "//iree/base:tracing", "//iree/modules/hal", + "//iree/vm", "//iree/vm:bytecode_module", ] + PLATFORM_VULKAN_DEPS + IREE_DRIVER_MODULES, ) @@ -349,9 +350,9 @@ "//iree/base:status", "//iree/hal:api", "//iree/modules/hal", + "//iree/vm", "//iree/vm:bytecode_module", - "//iree/vm:module", - "//iree/vm:variant_list", + "//iree/vm:ref_cc", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], @@ -368,7 +369,6 @@ "//iree/hal/vmla:vmla_driver_module", "//iree/modules/hal", "//iree/testing:gtest_main", - "//iree/vm:value", - "//iree/vm:variant_list", + "//iree/vm", ], )
diff --git a/iree/tools/CMakeLists.txt b/iree/tools/CMakeLists.txt index a946695..93f0b2f 100644 --- a/iree/tools/CMakeLists.txt +++ b/iree/tools/CMakeLists.txt
@@ -44,6 +44,7 @@ iree::base::tracing iree::modules::hal iree::testing::benchmark_main + iree::vm iree::vm::bytecode_module ${IREE_HAL_DRIVER_MODULES} TESTONLY @@ -84,6 +85,7 @@ iree::base::status iree::base::tracing iree::modules::hal + iree::vm iree::vm::bytecode_module ${IREE_HAL_DRIVER_MODULES} ) @@ -330,7 +332,6 @@ iree::modules::hal iree::vm iree::vm::bytecode_module - iree::vm::value ${IREE_HAL_DRIVER_MODULES} HOSTONLY ) @@ -367,9 +368,9 @@ iree::base::status iree::hal::api iree::modules::hal + iree::vm iree::vm::bytecode_module - iree::vm::module - iree::vm::variant_list + iree::vm::ref_cc PUBLIC ) @@ -386,8 +387,7 @@ iree::hal::vmla::vmla_driver_module iree::modules::hal iree::testing::gtest_main - iree::vm::value - iree::vm::variant_list + iree::vm ) if(${IREE_ENABLE_MLIR})
diff --git a/iree/tools/benchmark_module_main.cc b/iree/tools/benchmark_module_main.cc index 6f11e4a..c6cc98f 100644 --- a/iree/tools/benchmark_module_main.cc +++ b/iree/tools/benchmark_module_main.cc
@@ -22,6 +22,7 @@ #include "iree/base/tracing.h" #include "iree/modules/hal/hal_module.h" #include "iree/tools/vm_util.h" +#include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" // TODO(gcmn): Allow stdin in a non-gross way. The benchmark framework invokes @@ -107,11 +108,11 @@ RETURN_IF_ERROR(ValidateFunctionAbi(function)); ASSIGN_OR_RETURN(auto input_descs, ParseInputSignature(function)); - iree_vm_variant_list_t* inputs; + vm::ref<iree_vm_list_t> inputs; if (!absl::GetFlag(FLAGS_inputs_file).empty()) { if (!absl::GetFlag(FLAGS_inputs).empty()) { return InvalidArgumentErrorBuilder(IREE_LOC) - << "Expected only one of inputs and inputs_flag to be set"; + << "Expected only one of inputs and inputs_file to be set"; } ASSIGN_OR_RETURN(inputs, ParseToVariantListFromFile( input_descs, iree_hal_device_allocator(device), @@ -124,32 +125,33 @@ ASSIGN_OR_RETURN(auto output_descs, ParseOutputSignature(function)); - iree_vm_variant_list_t* outputs = nullptr; - // Execute once to make sure any first-iteration outliers are eliminated (e.g. // JITing the SPIR-V) and clearly separate out benchmark-related problems in // future debugging. - RETURN_IF_ERROR( - FromApiStatus(iree_vm_variant_list_alloc(output_descs.size(), - IREE_ALLOCATOR_SYSTEM, &outputs), - IREE_LOC)); - RETURN_IF_ERROR( - FromApiStatus(iree_vm_invoke(context, function, /*policy=*/nullptr, - inputs, outputs, IREE_ALLOCATOR_SYSTEM), - IREE_LOC)); - iree_vm_variant_list_free(outputs); + { + vm::ref<iree_vm_list_t> outputs; + RETURN_IF_ERROR(FromApiStatus( + iree_vm_list_create(/*element_type=*/nullptr, output_descs.size(), + IREE_ALLOCATOR_SYSTEM, &outputs), + IREE_LOC)); + RETURN_IF_ERROR(FromApiStatus( + iree_vm_invoke(context, function, /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM), + IREE_LOC)); + } for (auto _ : state) { // No status conversions and conditional returns in the benchmarked inner // loop. - IREE_CHECK_OK(iree_vm_variant_list_alloc(output_descs.size(), - IREE_ALLOCATOR_SYSTEM, &outputs)); - IREE_CHECK_OK(iree_vm_invoke(context, function, /*policy=*/nullptr, inputs, - outputs, IREE_ALLOCATOR_SYSTEM)); - iree_vm_variant_list_free(outputs); + vm::ref<iree_vm_list_t> outputs; + IREE_CHECK_OK(iree_vm_list_create(/*element_type=*/nullptr, + output_descs.size(), + IREE_ALLOCATOR_SYSTEM, &outputs)); + IREE_CHECK_OK(iree_vm_invoke(context, function, /*policy=*/nullptr, + inputs.get(), outputs.get(), + IREE_ALLOCATOR_SYSTEM)); } - iree_vm_variant_list_free(inputs); iree_vm_module_release(hal_module); iree_vm_module_release(input_module); iree_hal_device_release(device);
diff --git a/iree/tools/run_mlir_main.cc b/iree/tools/run_mlir_main.cc index ed09735..8a4b2c2 100644 --- a/iree/tools/run_mlir_main.cc +++ b/iree/tools/run_mlir_main.cc
@@ -66,7 +66,6 @@ #include "iree/tools/vm_util.h" #include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/value.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" @@ -274,43 +273,40 @@ std::cout << "EXEC @" << export_name << std::endl; ASSIGN_OR_RETURN(auto input_descs, ParseInputSignature(function)); - iree_vm_variant_list_t* input_list; + vm::ref<iree_vm_list_t> inputs; if (!input_values_file_flag.empty()) { if (!input_values_flag.empty()) { return InvalidArgumentErrorBuilder(IREE_LOC) - << "Expected only one of input_values_file_flag and " - "input_values_flag to be set"; + << "Expected only one of input_values and " + "input_values_file to be set"; } - ASSIGN_OR_RETURN(input_list, + ASSIGN_OR_RETURN(inputs, ParseToVariantListFromFile(input_descs, allocator, input_values_file_flag)); } else { auto input_values_list = absl::MakeConstSpan( input_values_flag.empty() ? nullptr : &input_values_flag.front(), input_values_flag.size()); - ASSIGN_OR_RETURN(input_list, ParseToVariantList(input_descs, allocator, - input_values_list)); + ASSIGN_OR_RETURN( + inputs, ParseToVariantList(input_descs, allocator, input_values_list)); } ASSIGN_OR_RETURN(auto output_descs, ParseOutputSignature(function)); // Prepare outputs list to accept the results from the invocation. - iree_vm_variant_list_t* output_list = nullptr; + vm::ref<iree_vm_list_t> outputs; RETURN_IF_ERROR(FromApiStatus( - iree_vm_variant_list_alloc(output_descs.size(), IREE_ALLOCATOR_SYSTEM, - &output_list), + iree_vm_list_create(/*element_type=*/nullptr, output_descs.size(), + IREE_ALLOCATOR_SYSTEM, &outputs), IREE_LOC)); // Synchronously invoke the function. RETURN_IF_ERROR(FromApiStatus( - iree_vm_invoke(context, function, /*policy=*/nullptr, input_list, - output_list, IREE_ALLOCATOR_SYSTEM), + iree_vm_invoke(context, function, /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM), IREE_LOC)); - iree_vm_variant_list_free(input_list); - // Print outputs. - RETURN_IF_ERROR(PrintVariantList(output_descs, output_list)); - iree_vm_variant_list_free(output_list); + RETURN_IF_ERROR(PrintVariantList(output_descs, outputs.get())); return OkStatus(); }
diff --git a/iree/tools/run_module_main.cc b/iree/tools/run_module_main.cc index 45e2326..41baed1 100644 --- a/iree/tools/run_module_main.cc +++ b/iree/tools/run_module_main.cc
@@ -24,6 +24,7 @@ #include "iree/base/tracing.h" #include "iree/modules/hal/hal_module.h" #include "iree/tools/vm_util.h" +#include "iree/vm/api.h" #include "iree/vm/bytecode_module.h" ABSL_FLAG(std::string, input_file, "-", @@ -109,11 +110,11 @@ RETURN_IF_ERROR(ValidateFunctionAbi(function)); ASSIGN_OR_RETURN(auto input_descs, ParseInputSignature(function)); - iree_vm_variant_list_t* inputs; + vm::ref<iree_vm_list_t> inputs; if (!absl::GetFlag(FLAGS_inputs_file).empty()) { if (!absl::GetFlag(FLAGS_inputs).empty()) { return InvalidArgumentErrorBuilder(IREE_LOC) - << "Expected only one of inputs and inputs_flag to be set"; + << "Expected only one of inputs and inputs_file to be set"; } ASSIGN_OR_RETURN(inputs, ParseToVariantListFromFile( input_descs, iree_hal_device_allocator(device), @@ -125,24 +126,24 @@ } ASSIGN_OR_RETURN(auto output_descs, ParseOutputSignature(function)); - iree_vm_variant_list_t* outputs = nullptr; - RETURN_IF_ERROR( - FromApiStatus(iree_vm_variant_list_alloc(output_descs.size(), - IREE_ALLOCATOR_SYSTEM, &outputs), - IREE_LOC)); + vm::ref<iree_vm_list_t> outputs; + RETURN_IF_ERROR(FromApiStatus( + iree_vm_list_create(/*element_type=*/nullptr, output_descs.size(), + IREE_ALLOCATOR_SYSTEM, &outputs), + IREE_LOC)); std::cout << "EXEC @" << function_name << "\n"; - RETURN_IF_ERROR( - FromApiStatus(iree_vm_invoke(context, function, /*policy=*/nullptr, - inputs, outputs, IREE_ALLOCATOR_SYSTEM), - IREE_LOC)) + RETURN_IF_ERROR(FromApiStatus( + iree_vm_invoke(context, function, /*policy=*/nullptr, inputs.get(), + outputs.get(), IREE_ALLOCATOR_SYSTEM), + IREE_LOC)) << "invoking function " << function_name; - RETURN_IF_ERROR(PrintVariantList(output_descs, outputs)) + RETURN_IF_ERROR(PrintVariantList(output_descs, outputs.get())) << "printing results"; - iree_vm_variant_list_free(inputs); - iree_vm_variant_list_free(outputs); + inputs.reset(); + outputs.reset(); iree_vm_module_release(hal_module); iree_vm_module_release(input_module); iree_hal_device_release(device);
diff --git a/iree/tools/vm_util.cc b/iree/tools/vm_util.cc index e7c6e7a..24da00d 100644 --- a/iree/tools/vm_util.cc +++ b/iree/tools/vm_util.cc
@@ -28,8 +28,6 @@ #include "iree/hal/api.h" #include "iree/modules/hal/hal_module.h" #include "iree/vm/bytecode_module.h" -#include "iree/vm/module.h" -#include "iree/vm/variant_list.h" namespace iree { @@ -82,28 +80,19 @@ return output_descs; } -StatusOr<iree_vm_variant_list_t*> ParseToVariantListFromFile( - absl::Span<const RawSignatureParser::Description> descs, - iree_hal_allocator_t* allocator, const std::string& filename) { - ASSIGN_OR_RETURN(auto s, file_io::GetFileContents(filename)); - std::vector<std::string> input_strings = - absl::StrSplit(s, '\n', absl::SkipEmpty()); - return ParseToVariantList(descs, allocator, input_strings); -} - -StatusOr<iree_vm_variant_list_t*> ParseToVariantList( +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantList( absl::Span<const RawSignatureParser::Description> descs, iree_hal_allocator_t* allocator, - absl::Span<const std::string> input_strings) { + absl::Span<const absl::string_view> input_strings) { if (input_strings.size() != descs.size()) { return InvalidArgumentErrorBuilder(IREE_LOC) << "Signature mismatch; expected " << descs.size() << " buffer strings but received " << input_strings.size(); } - iree_vm_variant_list_t* variant_list = nullptr; + vm::ref<iree_vm_list_t> variant_list; RETURN_IF_ERROR(FromApiStatus( - iree_vm_variant_list_alloc(input_strings.size(), IREE_ALLOCATOR_SYSTEM, - &variant_list), + iree_vm_list_create(/*element_type=*/nullptr, input_strings.size(), + IREE_ALLOCATOR_SYSTEM, &variant_list), IREE_LOC)); for (int i = 0; i < input_strings.size(); ++i) { auto input_string = input_strings[i]; @@ -124,14 +113,14 @@ << "Parsing '" << input_string << "'. Has i32 descriptor but does not start with 'i32='"; } - int32_t val; - if (!absl::SimpleAtoi(input_view, &val)) { + iree_vm_value_t val = iree_vm_value_make_i32(0); + if (!absl::SimpleAtoi(input_view, &val.i32)) { return InvalidArgumentErrorBuilder(IREE_LOC) << "Converting '" << input_view << "' to i32 when parsing '" << input_string << "'"; } - iree_vm_variant_list_append_value(variant_list, - iree_vm_value_make_i32(val)); + RETURN_IF_ERROR(FromApiStatus( + iree_vm_list_push_value(variant_list.get(), &val), IREE_LOC)); break; } case RawSignatureParser::Type::kBuffer: { @@ -144,9 +133,9 @@ << "Parsing value '" << input_string << "'"; } auto buffer_view_ref = iree_hal_buffer_view_move_ref(buffer_view); - RETURN_IF_ERROR(FromApiStatus(iree_vm_variant_list_append_ref_move( - variant_list, &buffer_view_ref), - IREE_LOC)); + RETURN_IF_ERROR(FromApiStatus( + iree_vm_list_push_ref_move(variant_list.get(), &buffer_view_ref), + IREE_LOC)); break; } default: @@ -154,18 +143,36 @@ << "Unsupported signature type: " << desc_str; } } - return variant_list; + return variant_list.release(); +} + +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantList( + absl::Span<const RawSignatureParser::Description> descs, + iree_hal_allocator_t* allocator, + absl::Span<const std::string> input_strings) { + absl::InlinedVector<absl::string_view, 4> input_views(input_strings.size()); + for (int i = 0; i < input_strings.size(); ++i) { + input_views[i] = input_strings[i]; + } + return ParseToVariantList(descs, allocator, input_views); +} + +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantListFromFile( + absl::Span<const RawSignatureParser::Description> descs, + iree_hal_allocator_t* allocator, const std::string& filename) { + ASSIGN_OR_RETURN(auto file_string, file_io::GetFileContents(filename)); + absl::InlinedVector<absl::string_view, 4> input_views( + absl::StrSplit(file_string, '\n', absl::SkipEmpty())); + return ParseToVariantList(descs, allocator, input_views); } Status PrintVariantList(absl::Span<const RawSignatureParser::Description> descs, - iree_vm_variant_list_t* variant_list, - std::ostream* os) { - for (int i = 0; i < iree_vm_variant_list_size(variant_list); ++i) { - iree_vm_variant_t* variant = iree_vm_variant_list_get(variant_list, i); - if (!variant) { - return InvalidArgumentErrorBuilder(IREE_LOC) - << "variant " << i << "not present"; - } + iree_vm_list_t* variant_list, std::ostream* os) { + for (int i = 0; i < iree_vm_list_size(variant_list); ++i) { + iree_vm_variant_t variant = iree_vm_variant_empty(); + RETURN_IF_ERROR(FromApiStatus( + iree_vm_list_get_variant(variant_list, i, &variant), IREE_LOC)) + << "variant " << i << "not present"; const auto& desc = descs[i]; std::string desc_str; @@ -174,27 +181,27 @@ switch (desc.type) { case RawSignatureParser::Type::kScalar: { - if (variant->value_type != IREE_VM_VALUE_TYPE_I32) { + if (variant.type.value_type != IREE_VM_VALUE_TYPE_I32) { return InvalidArgumentErrorBuilder(IREE_LOC) << "variant " << i << " has value type " - << static_cast<int>(variant->value_type) + << static_cast<int>(variant.type.value_type) << " but descriptor information " << desc_str; } if (desc.scalar.type != AbiConstants::ScalarType::kSint32) { return UnimplementedErrorBuilder(IREE_LOC) << "Unsupported signature scalar type: " << desc_str; } - *os << "i32=" << variant->i32 << "\n"; + *os << "i32=" << variant.i32 << "\n"; break; } case RawSignatureParser::Type::kBuffer: { - if (variant->value_type != IREE_VM_VALUE_TYPE_NONE) { + if (!iree_vm_type_def_is_ref(&variant.type)) { return InvalidArgumentErrorBuilder(IREE_LOC) << "variant " << i << " has value type " - << static_cast<int>(variant->value_type) + << static_cast<int>(variant.type.value_type) << " but descriptor information " << desc_str; } - auto* buffer_view = iree_hal_buffer_view_deref(&variant->ref); + auto* buffer_view = iree_hal_buffer_view_deref(&variant.ref); if (!buffer_view) { return InvalidArgumentErrorBuilder(IREE_LOC) << "failed dereferencing variant " << i;
diff --git a/iree/tools/vm_util.h b/iree/tools/vm_util.h index c3f1c9c..ac8dbac 100644 --- a/iree/tools/vm_util.h +++ b/iree/tools/vm_util.h
@@ -22,8 +22,8 @@ #include "iree/base/signature_mangle.h" #include "iree/base/status.h" #include "iree/hal/api.h" -#include "iree/vm/module.h" -#include "iree/vm/variant_list.h" +#include "iree/vm/api.h" +#include "iree/vm/ref_cc.h" namespace iree { @@ -40,13 +40,6 @@ StatusOr<std::vector<RawSignatureParser::Description>> ParseOutputSignature( const iree_vm_function_t& function); -// Parses the content in |filename| into a variant list of VM scalars and -// buffers. See ParseToVariantList for the format of scalars and buffers. The -// inputs are expected to be newline-separated. -StatusOr<iree_vm_variant_list_t*> ParseToVariantListFromFile( - absl::Span<const RawSignatureParser::Description> descs, - iree_hal_allocator_t* allocator, const std::string& filename); - // Parses |input_strings| into a variant list of VM scalars and buffers. // Scalars should be in the format: // type=value @@ -57,11 +50,22 @@ // Uses |allocator| to allocate the buffers. // Uses descriptors in |descs| for type information and validation. // The returned variant list must be freed by the caller. -StatusOr<iree_vm_variant_list_t*> ParseToVariantList( +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantList( + absl::Span<const RawSignatureParser::Description> descs, + iree_hal_allocator_t* allocator, + absl::Span<const absl::string_view> input_strings); +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantList( absl::Span<const RawSignatureParser::Description> descs, iree_hal_allocator_t* allocator, absl::Span<const std::string> input_strings); +// Parses the content in |filename| into a variant list of VM scalars and +// buffers. See ParseToVariantList for the format of scalars and buffers. The +// inputs are expected to be newline-separated. +StatusOr<vm::ref<iree_vm_list_t>> ParseToVariantListFromFile( + absl::Span<const RawSignatureParser::Description> descs, + iree_hal_allocator_t* allocator, const std::string& filename); + // Prints a variant list of VM scalars and buffers to |os|. // Prints scalars in the format: // type=value @@ -71,7 +75,7 @@ // https://github.com/google/iree/tree/main/iree/hal/api.h // Uses descriptors in |descs| for type information and validation. Status PrintVariantList(absl::Span<const RawSignatureParser::Description> descs, - iree_vm_variant_list_t* variant_list, + iree_vm_list_t* variant_list, std::ostream* os = &std::cout); // Creates the default device for |driver| in |out_device|.
diff --git a/iree/tools/vm_util_test.cc b/iree/tools/vm_util_test.cc index 11a0092..2391fbb 100644 --- a/iree/tools/vm_util_test.cc +++ b/iree/tools/vm_util_test.cc
@@ -21,8 +21,7 @@ #include "iree/hal/api.h" #include "iree/modules/hal/hal_module.h" #include "iree/testing/gtest.h" -#include "iree/vm/value.h" -#include "iree/vm/variant_list.h" +#include "iree/vm/api.h" namespace iree { namespace { @@ -42,72 +41,64 @@ }; TEST_F(VmUtilTest, ParsePrintBuffer) { - auto buf_string = "2x2xi32=[42 43][44 45]"; + absl::string_view buf_string = "2x2xi32=[42 43][44 45]"; RawSignatureParser::Description desc; desc.type = RawSignatureParser::Type::kBuffer; desc.buffer.scalar_type = AbiConstants::ScalarType::kSint32; desc.dims = {2, 2}; - ASSERT_OK_AND_ASSIGN(auto* variant_list, + ASSERT_OK_AND_ASSIGN(auto variant_list, ParseToVariantList({desc}, allocator_, {buf_string})); std::stringstream os; - ASSERT_OK(PrintVariantList({desc}, variant_list, &os)); + ASSERT_OK(PrintVariantList({desc}, variant_list.get(), &os)); EXPECT_EQ(os.str(), absl::StrCat(buf_string, "\n")); - - iree_vm_variant_list_free(variant_list); } TEST_F(VmUtilTest, ParsePrintScalar) { - auto input_string = "i32=42"; + absl::string_view input_string = "i32=42"; RawSignatureParser::Description desc; desc.type = RawSignatureParser::Type::kScalar; desc.scalar.type = AbiConstants::ScalarType::kSint32; - ASSERT_OK_AND_ASSIGN(auto* variant_list, + ASSERT_OK_AND_ASSIGN(auto variant_list, ParseToVariantList({desc}, allocator_, {input_string})); std::stringstream os; - ASSERT_OK(PrintVariantList({desc}, variant_list, &os)); + ASSERT_OK(PrintVariantList({desc}, variant_list.get(), &os)); EXPECT_EQ(os.str(), absl::StrCat(input_string, "\n")); - - iree_vm_variant_list_free(variant_list); } TEST_F(VmUtilTest, ParsePrintRank0Buffer) { - auto buf_string = "i32=42"; + absl::string_view buf_string = "i32=42"; RawSignatureParser::Description desc; desc.type = RawSignatureParser::Type::kBuffer; desc.buffer.scalar_type = AbiConstants::ScalarType::kSint32; - ASSERT_OK_AND_ASSIGN(auto* variant_list, + ASSERT_OK_AND_ASSIGN(auto variant_list, ParseToVariantList({desc}, allocator_, {buf_string})); std::stringstream os; - ASSERT_OK(PrintVariantList({desc}, variant_list, &os)); + ASSERT_OK(PrintVariantList({desc}, variant_list.get(), &os)); EXPECT_EQ(os.str(), absl::StrCat(buf_string, "\n")); - - iree_vm_variant_list_free(variant_list); } TEST_F(VmUtilTest, ParsePrintMultipleBuffers) { - auto buf_string1 = "2x2xi32=[42 43][44 45]"; + absl::string_view buf_string1 = "2x2xi32=[42 43][44 45]"; RawSignatureParser::Description desc1; desc1.type = RawSignatureParser::Type::kBuffer; desc1.buffer.scalar_type = AbiConstants::ScalarType::kSint32; desc1.dims = {2, 2}; - auto buf_string2 = "2x3xf64=[1 2 3][4 5 6]"; + absl::string_view buf_string2 = "2x3xf64=[1 2 3][4 5 6]"; RawSignatureParser::Description desc2; desc2.type = RawSignatureParser::Type::kBuffer; desc2.buffer.scalar_type = AbiConstants::ScalarType::kIeeeFloat64; desc2.dims = {2, 3}; - ASSERT_OK_AND_ASSIGN(auto* variant_list, + ASSERT_OK_AND_ASSIGN(auto variant_list, ParseToVariantList({desc1, desc2}, allocator_, {buf_string1, buf_string2})); std::stringstream os; - ASSERT_OK(PrintVariantList({desc1, desc2}, variant_list, &os)); + ASSERT_OK(PrintVariantList({desc1, desc2}, variant_list.get(), &os)); EXPECT_EQ(os.str(), absl::StrCat(buf_string1, "\n", buf_string2, "\n")); - - iree_vm_variant_list_free(variant_list); } } // namespace
diff --git a/iree/vm/BUILD b/iree/vm/BUILD index c9350c5..93829d0 100644 --- a/iree/vm/BUILD +++ b/iree/vm/BUILD
@@ -92,6 +92,24 @@ ) cc_test( + name = "bytecode_module_size_benchmark", + srcs = ["bytecode_module_size_benchmark.cc"], + deps = [ + ":bytecode_module", + ":bytecode_module_size_benchmark_module_cc", + ":vm", + "//iree/base:api", + ], +) + +iree_bytecode_module( + name = "bytecode_module_size_benchmark_module", + src = "bytecode_module_size_benchmark.mlir", + cc_namespace = "iree::vm", + flags = ["-iree-vm-ir-to-bytecode-module"], +) + +cc_test( name = "bytecode_module_test", srcs = ["bytecode_module_test.cc"], deps = [ @@ -149,8 +167,8 @@ hdrs = ["invocation.h"], deps = [ ":context", + ":list", ":module", - ":variant_list", "//iree/base:api", "//iree/base:tracing", ], @@ -251,7 +269,6 @@ deps = [ ":module", ":ref", - ":variant_list", "//iree/base:alignment", "//iree/base:api", "//iree/base:tracing", @@ -285,16 +302,6 @@ ) cc_library( - name = "variant_list", - srcs = ["variant_list.c"], - hdrs = ["variant_list.h"], - deps = [ - ":ref", - ":value", - ], -) - -cc_library( name = "vm", hdrs = [ "api.h", @@ -310,7 +317,6 @@ ":stack", ":type_def", ":value", - ":variant_list", "//iree/base:api", ], )
diff --git a/iree/vm/CMakeLists.txt b/iree/vm/CMakeLists.txt index 45c96c6..ae91187 100644 --- a/iree/vm/CMakeLists.txt +++ b/iree/vm/CMakeLists.txt
@@ -106,6 +106,30 @@ iree_cc_test( NAME + bytecode_module_size_benchmark + SRCS + "bytecode_module_size_benchmark.cc" + DEPS + ::bytecode_module + ::bytecode_module_size_benchmark_module_cc + ::vm + iree::base::api +) + +iree_bytecode_module( + NAME + bytecode_module_size_benchmark_module + SRC + "bytecode_module_size_benchmark.mlir" + CC_NAMESPACE + "iree::vm" + FLAGS + "-iree-vm-ir-to-bytecode-module" + PUBLIC +) + +iree_cc_test( + NAME bytecode_module_test SRCS "bytecode_module_test.cc" @@ -165,8 +189,8 @@ "invocation.c" DEPS ::context + ::list ::module - ::variant_list iree::base::api iree::base::tracing PUBLIC @@ -283,7 +307,6 @@ DEPS ::module ::ref - ::variant_list iree::base::alignment iree::base::api iree::base::tracing @@ -324,19 +347,6 @@ iree_cc_library( NAME - variant_list - HDRS - "variant_list.h" - SRCS - "variant_list.c" - DEPS - ::ref - ::value - PUBLIC -) - -iree_cc_library( - NAME vm HDRS "api.h" @@ -351,7 +361,6 @@ ::stack ::type_def ::value - ::variant_list iree::base::api PUBLIC )
diff --git a/iree/vm/api.h b/iree/vm/api.h index 57331ae..e4f2f4e 100644 --- a/iree/vm/api.h +++ b/iree/vm/api.h
@@ -20,10 +20,11 @@ #include "iree/vm/context.h" #include "iree/vm/instance.h" #include "iree/vm/invocation.h" +#include "iree/vm/list.h" #include "iree/vm/module.h" #include "iree/vm/ref.h" #include "iree/vm/stack.h" +#include "iree/vm/type_def.h" #include "iree/vm/value.h" -#include "iree/vm/variant_list.h" #endif // IREE_VM_API_H_
diff --git a/iree/vm/bytecode_dispatch.c b/iree/vm/bytecode_dispatch.c index 01e5b2d..eab5136 100644 --- a/iree/vm/bytecode_dispatch.c +++ b/iree/vm/bytecode_dispatch.c
@@ -63,6 +63,13 @@ static_assert(offsetof(iree_vm_register_remap_list_t, pairs) == 2, "Expect no padding in the struct"); +// Maps a type ID to a type def with clamping for out of bounds values. +static inline const iree_vm_type_def_t* iree_vm_map_type( + iree_vm_bytecode_module_t* module, int32_t type_id) { + type_id = type_id >= module->type_count ? 0 : type_id; + return &module->type_table[type_id]; +} + // Remaps registers from a source set to a destination set within the same stack // frame. This is a way to perform a conditional multi-mov sequence instead of // requiring the additional bytecode representation of the conditional movs. @@ -103,6 +110,76 @@ } } +static const int kRegSize = sizeof(uint16_t); + +// Bytecode data access macros for reading values of a given type from a byte +// offset within the current function. +#if defined(IREE_IS_LITTLE_ENDIAN) +#define OP_I8(i) bytecode_data[pc + i] +#define OP_I16(i) *((uint16_t*)&bytecode_data[pc + i]) +#define OP_I32(i) *((uint32_t*)&bytecode_data[pc + i]) +#else +#define OP_I8(i) bytecode_data[pc + i] +#define OP_I16(i) \ + ((uint16_t)bytecode_data[pc + 0 + i]) | \ + ((uint16_t)bytecode_data[pc + 1 + i] << 8) +#define OP_I32(i) \ + ((uint32_t)bytecode_data[pc + 0 + i]) | \ + ((uint32_t)bytecode_data[pc + 1 + i] << 8) | \ + ((uint32_t)bytecode_data[pc + 2 + i] << 16) | \ + ((uint32_t)bytecode_data[pc + 3 + i] << 24) +#endif // IREE_IS_LITTLE_ENDIAN + +// These utilities match the VM_Enc* statements in VMBase.td 1:1, allowing us +// to have the inverse of the encoding which make things easier to read. +// +// Each macro will increment the pc by the number of bytes read and as such must +// be called in the same order the values are encoded. +#define VM_DecConstI8(name) \ + OP_I8(0); \ + ++pc; +#define VM_DecConstI32(name) \ + OP_I32(0); \ + pc += 4; +#define VM_DecOpcode(opcode) VM_DecConstI8(#opcode) +#define VM_DecFuncAttr(name) VM_DecConstI32(name) +#define VM_DecGlobalAttr(name) VM_DecConstI32(name) +#define VM_DecRodataAttr(name) VM_DecConstI32(name) +#define VM_DecType(name) \ + iree_vm_map_type(module, OP_I32(0)); \ + pc += 4; +#define VM_DecTypeOf(name) VM_DecType(name) +#define VM_DecIntAttr32(name) VM_DecConstI32(name) +#define VM_DecStrAttr(name, out_str) \ + (out_str)->size = (iree_host_size_t)OP_I16(0); \ + (out_str)->data = (const char*)&bytecode_data[pc + 2]; \ + pc += 2 + (out_str)->size; +#define VM_DecBranchTarget(block_name) VM_DecConstI32(name) +#define VM_DecBranchOperands(operands_name) \ + (const iree_vm_register_remap_list_t*)&bytecode_data[pc]; \ + pc += \ + kRegSize + ((const iree_vm_register_list_t*)&bytecode_data[pc])->size * \ + 2 * kRegSize; +#define VM_DecOperandRegI32(name) \ + regs.i32[OP_I16(0) & regs.i32_mask]; \ + pc += kRegSize; +#define VM_DecOperandRegRef(name, out_is_move) \ + ®s.ref[OP_I16(0) & regs.ref_mask]; \ + *(out_is_move) = OP_I16(0) & IREE_REF_REGISTER_MOVE_BIT; \ + pc += kRegSize; +#define VM_DecVariadicOperands(name) \ + (const iree_vm_register_list_t*)&bytecode_data[pc]; \ + pc += kRegSize + \ + ((const iree_vm_register_list_t*)&bytecode_data[pc])->size * kRegSize; +#define VM_DecResultRegI32(name) \ + ®s.i32[OP_I16(0) & regs.i32_mask]; \ + pc += kRegSize; +#define VM_DecResultRegRef(name, out_is_move) \ + ®s.ref[OP_I16(0) & regs.ref_mask]; \ + *(out_is_move) = OP_I16(0) & IREE_REF_REGISTER_MOVE_BIT; \ + pc += kRegSize; +#define VM_DecVariadicResults(name) VM_DecVariadicOperands(name) + iree_status_t iree_vm_bytecode_dispatch( iree_vm_bytecode_module_t* module, iree_vm_bytecode_module_state_t* module_state, iree_vm_stack_t* stack, @@ -132,7 +209,7 @@ #define DECLARE_DISPATCH_OPC(ordinal, name) &&_dispatch_##name, #define DECLARE_DISPATCH_RSV(ordinal) &&_dispatch_unhandled, static const void* kDispatchTable[256] = { - IREE_VM_OP_TABLE(DECLARE_DISPATCH_OPC, DECLARE_DISPATCH_RSV)}; + IREE_VM_OP_CORE_TABLE(DECLARE_DISPATCH_OPC, DECLARE_DISPATCH_RSV)}; #define DISPATCH_UNHANDLED() \ _dispatch_unhandled: \ @@ -161,35 +238,13 @@ return IREE_STATUS_UNIMPLEMENTED; #define DISPATCH_OP(op_name, body) \ - case IREE_VM_OP_##op_name: \ + case IREE_VM_OP_CORE_##op_name: \ IREE_DISPATCH_LOG_OPCODE(#op_name); \ body; \ break; #endif // IREE_DISPATCH_MODE_COMPUTED_GOTO - static const int kRegSize = sizeof(uint16_t); - -#if defined(IREE_IS_LITTLE_ENDIAN) -#define OP_I8(i) bytecode_data[pc + i] -#define OP_I16(i) *((uint16_t*)&bytecode_data[pc + i]) -#define OP_I32(i) *((uint32_t*)&bytecode_data[pc + i]) -#else -#define OP_I8(i) bytecode_data[pc + i] -#define OP_I16(i) \ - ((uint16_t)bytecode_data[pc + 0 + i]) | \ - ((uint16_t)bytecode_data[pc + 1 + i] << 8) -#define OP_I32(i) \ - ((uint32_t)bytecode_data[pc + 0 + i]) | \ - ((uint32_t)bytecode_data[pc + 1 + i] << 8) | \ - ((uint32_t)bytecode_data[pc + 2 + i] << 16) | \ - ((uint32_t)bytecode_data[pc + 3 + i] << 24) -#endif // IREE_IS_LITTLE_ENDIAN - -#define OP_R_I32(i) regs.i32[OP_I16(i) & regs.i32_mask] -#define OP_R_REF(i) regs.ref[OP_I16(i) & regs.ref_mask] -#define OP_R_REF_IS_MOVE(i) (OP_I16(i) & IREE_REF_REGISTER_MOVE_BIT) - // Primary dispatch state. This is our 'native stack frame' and really // just enough to make dereferencing common addresses (like the current // offset) faster. You can think of this like CPU state (like PC). @@ -208,159 +263,109 @@ memset(out_result, 0, sizeof(*out_result)); - // NOTE: we should generate this with tblgen, as it has the encoding info. - // TODO(benvanik): at least generate operand reading/writing and sizes. - // This could look something like: - // OP_GlobalLoadI32_value = OP_GlobalLoadI32_global; - // pc += OP_Size_GlobalLoadI32; - BEGIN_DISPATCH() { //===------------------------------------------------------------------===// // Globals //===------------------------------------------------------------------===// DISPATCH_OP(GlobalLoadI32, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalLoadI32>, - // VM_EncGlobalAttr<"global">, - // VM_EncResult<"value">, - // ]; - int byte_offset = OP_I32(0); + int32_t byte_offset = VM_DecGlobalAttr("global"); if (byte_offset < 0 || byte_offset >= module_state->rwdata_storage.data_length) { return IREE_STATUS_OUT_OF_RANGE; } + int32_t* value = VM_DecResultRegI32("value"); const int32_t* global_ptr = (const int32_t*)(module_state->rwdata_storage.data + byte_offset); - OP_R_I32(4) = *global_ptr; - pc += 4 + kRegSize; + *value = *global_ptr; }); + DISPATCH_OP(GlobalStoreI32, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalStoreI32>, - // VM_EncGlobalAttr<"global">, - // VM_EncOperand<"value", 0>, - // ]; - int byte_offset = OP_I32(0); + int32_t byte_offset = VM_DecGlobalAttr("global"); if (byte_offset < 0 || byte_offset >= module_state->rwdata_storage.data_length) { return IREE_STATUS_OUT_OF_RANGE; } + int32_t value = VM_DecOperandRegI32("value"); int32_t* global_ptr = (int32_t*)(module_state->rwdata_storage.data + byte_offset); - *global_ptr = OP_R_I32(4); - pc += 4 + kRegSize; + *global_ptr = value; }); DISPATCH_OP(GlobalLoadIndirectI32, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalLoadIndirectI32>, - // VM_EncOperand<"global", 0>, - // VM_EncResult<"value">, - // ]; - int byte_offset = OP_R_I32(0); + int32_t byte_offset = VM_DecOperandRegI32("global"); if (byte_offset < 0 || byte_offset >= module_state->rwdata_storage.data_length) { return IREE_STATUS_OUT_OF_RANGE; } + int32_t* value = VM_DecResultRegI32("value"); const int32_t* global_ptr = (const int32_t*)(module_state->rwdata_storage.data + byte_offset); - OP_R_I32(2) = *global_ptr; - pc += kRegSize + kRegSize; + *value = *global_ptr; }); + DISPATCH_OP(GlobalStoreIndirectI32, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalStoreIndirectI32>, - // VM_EncOperand<"global", 0>, - // VM_EncOperand<"value", 1>, - // ]; - int byte_offset = OP_R_I32(0); + int32_t byte_offset = VM_DecOperandRegI32("global"); if (byte_offset < 0 || byte_offset >= module_state->rwdata_storage.data_length) { return IREE_STATUS_OUT_OF_RANGE; } + int32_t value = VM_DecOperandRegI32("value"); int32_t* global_ptr = (int32_t*)(module_state->rwdata_storage.data + byte_offset); - *global_ptr = OP_R_I32(2); - pc += kRegSize + kRegSize; + *global_ptr = value; }); DISPATCH_OP(GlobalLoadRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalLoadRef>, - // VM_EncGlobalAttr<"global">, - // VM_EncTypeOf<"value">, - // VM_EncResult<"value">, - // ]; - int global = OP_I32(0); + int32_t global = VM_DecGlobalAttr("global"); if (global < 0 || global >= module_state->global_ref_count) { return IREE_STATUS_OUT_OF_RANGE; } - int type_id = OP_I32(4); - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; + const iree_vm_type_def_t* type_def = VM_DecTypeOf("value"); + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("value", &result_is_move); iree_vm_ref_t* global_ref = &module_state->global_ref_table[global]; - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(8), global_ref, - type_def->ref_type, &OP_R_REF(8)); - pc += 4 + 4 + kRegSize; + iree_vm_ref_retain_or_move_checked(result_is_move, global_ref, + type_def->ref_type, result); }); + DISPATCH_OP(GlobalStoreRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalStoreRef>, - // VM_EncGlobalAttr<"global">, - // VM_EncTypeOf<"value">, - // VM_EncOperand<"value", 0>, - // ]; - int global = OP_I32(0); + int32_t global = VM_DecGlobalAttr("global"); if (global < 0 || global >= module_state->global_ref_count) { return IREE_STATUS_OUT_OF_RANGE; } - int type_id = OP_I32(4); - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; + const iree_vm_type_def_t* type_def = VM_DecTypeOf("value"); + bool value_is_move; + iree_vm_ref_t* value = VM_DecOperandRegRef("value", &value_is_move); iree_vm_ref_t* global_ref = &module_state->global_ref_table[global]; - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(8), &OP_R_REF(8), + iree_vm_ref_retain_or_move_checked(value_is_move, value, type_def->ref_type, global_ref); - pc += 4 + 4 + kRegSize; }); DISPATCH_OP(GlobalLoadIndirectRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalLoadIndirectRef>, - // VM_EncOperand<"global", 0>, - // VM_EncTypeOf<"value">, - // VM_EncResult<"value">, - // ]; - int global = OP_R_I32(0); + int32_t global = VM_DecGlobalAttr("global"); if (global < 0 || global >= module_state->global_ref_count) { return IREE_STATUS_OUT_OF_RANGE; } - int type_id = OP_I32(2); - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; + const iree_vm_type_def_t* type_def = VM_DecTypeOf("value"); + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("value", &result_is_move); iree_vm_ref_t* global_ref = &module_state->global_ref_table[global]; - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(6), global_ref, - type_def->ref_type, &OP_R_REF(6)); - pc += kRegSize + 4 + kRegSize; + iree_vm_ref_retain_or_move_checked(result_is_move, global_ref, + type_def->ref_type, result); }); + DISPATCH_OP(GlobalStoreIndirectRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_GlobalStoreIndirectRef>, - // VM_EncOperand<"global", 0>, - // VM_EncTypeOf<"value">, - // VM_EncOperand<"value", 1>, - // ]; - int global = OP_R_I32(0); + int32_t global = VM_DecGlobalAttr("global"); if (global < 0 || global >= module_state->global_ref_count) { return IREE_STATUS_OUT_OF_RANGE; } - int type_id = OP_I32(2); - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; + const iree_vm_type_def_t* type_def = VM_DecTypeOf("value"); + bool value_is_move; + iree_vm_ref_t* value = VM_DecOperandRegRef("value", &value_is_move); iree_vm_ref_t* global_ref = &module_state->global_ref_table[global]; - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(6), &OP_R_REF(6), + iree_vm_ref_retain_or_move_checked(value_is_move, value, type_def->ref_type, global_ref); - pc += kRegSize + 4 + kRegSize; }); //===------------------------------------------------------------------===// @@ -368,48 +373,32 @@ //===------------------------------------------------------------------===// DISPATCH_OP(ConstI32, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncIntAttr<"value", type.bitwidth>, - // VM_EncResult<"result">, - // ]; - OP_R_I32(4) = OP_I32(0); - pc += 4 + kRegSize; + int32_t value = VM_DecIntAttr32("value"); + int32_t* result = VM_DecResultRegI32("result"); + *result = value; }); DISPATCH_OP(ConstI32Zero, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ConstI32Zero>, - // VM_EncResult<"result">, - // ]; - OP_R_I32(0) = 0; - pc += kRegSize; + int32_t* result = VM_DecResultRegI32("result"); + *result = 0; }); DISPATCH_OP(ConstRefZero, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ConstRefZero>, - // VM_EncResult<"result">, - // ]; - iree_vm_ref_release(&OP_R_REF(0)); - pc += kRegSize; + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("result", &result_is_move); + iree_vm_ref_release(result); }); DISPATCH_OP(ConstRefRodata, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ConstRefRodata>, - // VM_EncRodataAttr<"rodata">, - // VM_EncResult<"value">, - // ]; - int32_t rodata_ordinal = OP_I32(0); + int32_t rodata_ordinal = VM_DecRodataAttr("rodata"); if (rodata_ordinal < 0 || rodata_ordinal >= module_state->rodata_ref_count) { return IREE_STATUS_OUT_OF_RANGE; } - // TODO(benvanik): allow decompression callbacks to run now (if needed). + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("value", &result_is_move); iree_vm_ref_wrap_retain(&module_state->rodata_ref_table[rodata_ordinal], - iree_vm_ro_byte_buffer_type_id(), &OP_R_REF(4)); - pc += 4 + kRegSize; + iree_vm_ro_byte_buffer_type_id(), result); }); //===------------------------------------------------------------------===// @@ -417,120 +406,86 @@ //===------------------------------------------------------------------===// DISPATCH_OP(ListAlloc, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListAlloc>, - // VM_EncType<"{{element_type}}">, - // VM_EncOperand<"initial_capacity", 0>, - // VM_EncResult<"result">, - // ]; - int element_type_id = OP_I32(0); - element_type_id = - element_type_id >= module->type_count ? 0 : element_type_id; - const iree_vm_type_def_t* element_type_def = - &module->type_table[element_type_id]; - iree_host_size_t initial_capacity = (iree_host_size_t)OP_R_I32(4); + const iree_vm_type_def_t* element_type_def = VM_DecTypeOf("element_type"); + iree_host_size_t initial_capacity = + VM_DecOperandRegI32("initial_capacity"); + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("result", &result_is_move); iree_vm_list_t* list = NULL; IREE_RETURN_IF_ERROR(iree_vm_list_create( element_type_def, initial_capacity, module_state->allocator, &list)); - iree_vm_ref_wrap_assign(list, iree_vm_list_type_id(), &OP_R_REF(6)); - pc += 4 + kRegSize + kRegSize; + iree_vm_ref_wrap_assign(list, iree_vm_list_type_id(), result); }); DISPATCH_OP(ListReserve, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListReserve>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"minimum_capacity", 1>, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); + bool list_is_move; + iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); iree_vm_list_t* list = iree_vm_list_deref(list_ref); if (!list) return IREE_STATUS_INVALID_ARGUMENT; - IREE_RETURN_IF_ERROR(iree_vm_list_reserve(list, OP_R_I32(2))); - pc += kRegSize + kRegSize; + int32_t minimum_capacity = VM_DecOperandRegI32("minimum_capacity"); + IREE_RETURN_IF_ERROR(iree_vm_list_reserve(list, minimum_capacity)); }); DISPATCH_OP(ListSize, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListSize>, - // VM_EncOperand<"list", 0>, - // VM_EncResult<"result">, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); + bool list_is_move; + iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); iree_vm_list_t* list = iree_vm_list_deref(list_ref); if (!list) return IREE_STATUS_INVALID_ARGUMENT; - OP_R_I32(2) = (int32_t)iree_vm_list_size(list); - pc += kRegSize + kRegSize; + int32_t* result = VM_DecResultRegI32("result"); + *result = (int32_t)iree_vm_list_size(list); }); DISPATCH_OP(ListResize, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListResize>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"new_size", 1>, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); + bool list_is_move; + iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); iree_vm_list_t* list = iree_vm_list_deref(list_ref); if (!list) return IREE_STATUS_INVALID_ARGUMENT; - IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, OP_R_I32(2))); - pc += kRegSize + kRegSize; + int32_t new_size = VM_DecOperandRegI32("new_size"); + IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, new_size)); }); DISPATCH_OP(ListGetI32, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"index", 1>, - // VM_EncResult<"result">, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); + bool list_is_move; + iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); iree_vm_list_t* list = iree_vm_list_deref(list_ref); if (!list) return IREE_STATUS_INVALID_ARGUMENT; + int32_t index = VM_DecOperandRegI32("index"); + int32_t* result = VM_DecResultRegI32("result"); iree_vm_value_t value; IREE_RETURN_IF_ERROR(iree_vm_list_get_value_as( - list, OP_R_I32(2), IREE_VM_VALUE_TYPE_I32, &value)); - OP_R_I32(4) = value.i32; - pc += kRegSize + kRegSize + kRegSize; + list, index, IREE_VM_VALUE_TYPE_I32, &value)); + *result = value.i32; }); DISPATCH_OP(ListSetI32, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"index", 1>, - // VM_EncOperand<"value", 2>, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); + bool list_is_move; + iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); iree_vm_list_t* list = iree_vm_list_deref(list_ref); if (!list) return IREE_STATUS_INVALID_ARGUMENT; - iree_vm_value_t value = iree_vm_value_make_i32(OP_R_I32(4)); - IREE_RETURN_IF_ERROR(iree_vm_list_set_value(list, OP_R_I32(2), &value)); - pc += kRegSize + kRegSize + kRegSize; + int32_t index = VM_DecOperandRegI32("index"); + int32_t raw_value = VM_DecOperandRegI32("raw_value"); + iree_vm_value_t value = iree_vm_value_make_i32(raw_value); + IREE_RETURN_IF_ERROR(iree_vm_list_set_value(list, index, &value)); }); DISPATCH_OP(ListGetRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListGetRef>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"index", 1>, - // VM_EncTypeOf<"result">, - // VM_EncResult<"result">, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); - iree_vm_list_t* list = iree_vm_list_deref(list_ref); - if (!list) return IREE_STATUS_INVALID_ARGUMENT; + // bool list_is_move; + // iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); + // iree_vm_list_t* list = iree_vm_list_deref(list_ref); + // if (!list) return IREE_STATUS_INVALID_ARGUMENT; + // int32_t index = VM_DecOperandRegI32("index"); + // iree_vm_ref_t* result = VM_DecResultRegRef("result"); return IREE_STATUS_UNIMPLEMENTED; }); DISPATCH_OP(ListSetRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_ListSetRef>, - // VM_EncOperand<"list", 0>, - // VM_EncOperand<"index", 1>, - // VM_EncOperand<"value", 2>, - // ]; - iree_vm_ref_t* list_ref = &OP_R_REF(0); - iree_vm_list_t* list = iree_vm_list_deref(list_ref); - if (!list) return IREE_STATUS_INVALID_ARGUMENT; + // bool list_is_move; + // iree_vm_ref_t* list_ref = VM_DecOperandRegRef("list", &list_is_move); + // iree_vm_list_t* list = iree_vm_list_deref(list_ref); + // if (!list) return IREE_STATUS_INVALID_ARGUMENT; + // int32_t index = VM_DecOperandRegI32("index"); + // bool operand_is_move = VM_DecOperandRegRefIsMove("value"); + // iree_vm_ref_t* operand = VM_DecOperandRegRef("value"); return IREE_STATUS_UNIMPLEMENTED; }); @@ -539,122 +494,92 @@ //===------------------------------------------------------------------===// DISPATCH_OP(SelectI32, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"condition", 0>, - // VM_EncOperand<"true_value", 1>, - // VM_EncOperand<"false_value", 2>, - // VM_EncResult<"result">, - // ]; - OP_R_I32(6) = OP_R_I32(0) ? OP_R_I32(2) : OP_R_I32(4); - pc += kRegSize + kRegSize + kRegSize + kRegSize; + int32_t condition = VM_DecOperandRegI32("condition"); + int32_t true_value = VM_DecOperandRegI32("true_value"); + int32_t false_value = VM_DecOperandRegI32("false_value"); + int32_t* result = VM_DecResultRegI32("result"); + *result = condition ? true_value : false_value; }); DISPATCH_OP(SelectRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_SelectRef>, - // VM_EncOperand<"condition", 0>, - // VM_EncTypeOf<"true_value">, - // VM_EncOperand<"true_value", 1>, - // VM_EncOperand<"false_value", 2>, - // VM_EncResult<"result">, - // ]; + int32_t condition = VM_DecOperandRegI32("condition"); // TODO(benvanik): remove the type_id and use either LHS/RHS (if both are // null then output is always null so no need to know the type). - int type_id = OP_I32(2); - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; - if (OP_R_I32(0)) { - // Select LHS (+6). - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(6), &OP_R_REF(6), - type_def->ref_type, &OP_R_REF(10)); - if (OP_R_REF_IS_MOVE(10)) iree_vm_ref_release(&OP_R_REF(8)); + const iree_vm_type_def_t* type_def = VM_DecTypeOf("true_value"); + bool true_value_is_move; + iree_vm_ref_t* true_value = + VM_DecOperandRegRef("true_value", &true_value_is_move); + bool false_value_is_move; + iree_vm_ref_t* false_value = + VM_DecOperandRegRef("false_value", &false_value_is_move); + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("result", &result_is_move); + if (condition) { + // Select LHS. + iree_vm_ref_retain_or_move_checked(true_value_is_move, true_value, + type_def->ref_type, result); + if (false_value_is_move) iree_vm_ref_release(false_value); } else { - // Select RHS (+8). - iree_vm_ref_retain_or_move_checked(OP_R_REF_IS_MOVE(8), &OP_R_REF(8), - type_def->ref_type, &OP_R_REF(10)); - if (OP_R_REF_IS_MOVE(6)) iree_vm_ref_release(&OP_R_REF(6)); + // Select RHS. + iree_vm_ref_retain_or_move_checked(false_value_is_move, false_value, + type_def->ref_type, result); + if (true_value_is_move) iree_vm_ref_release(true_value); } - pc += kRegSize + 4 + kRegSize + kRegSize + kRegSize; }); DISPATCH_OP(SwitchI32, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"index", 0>, - // VM_EncIntAttr<"default_value", 32>, - // VM_EncVariadicOperands<"values">, - // VM_EncResult<"result">, - // ]; - int32_t index = OP_R_I32(0); - int32_t default_value = OP_I32(2); + int32_t index = VM_DecOperandRegI32("index"); + int32_t default_value = VM_DecIntAttr32("default_value"); const iree_vm_register_list_t* value_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc + 6]; - pc += kRegSize + 4 + kRegSize + value_reg_list->size * kRegSize; - int32_t new_value = default_value; + VM_DecVariadicOperands("values"); + int32_t* result = VM_DecResultRegI32("result"); if (index >= 0 && index < value_reg_list->size) { - new_value = regs.i32[value_reg_list->registers[index] & regs.i32_mask]; + *result = regs.i32[value_reg_list->registers[index] & regs.i32_mask]; + } else { + *result = default_value; } - OP_R_I32(0) = new_value; - pc += kRegSize; }); DISPATCH_OP(SwitchRef, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_SwitchRef>, - // VM_EncOperand<"index", 0>, - // VM_EncTypeOf<"result">, - // VM_EncOperand<"default_value", 1>, - // VM_EncVariadicOperands<"values">, - // VM_EncResult<"result">, - // ]; - int32_t index = OP_R_I32(0); - int32_t type_id = OP_I32(2); - iree_vm_ref_t* default_value = &OP_R_REF(6); - int is_move = OP_R_REF_IS_MOVE(6); + int32_t index = VM_DecOperandRegI32("index"); + const iree_vm_type_def_t* type_def = VM_DecTypeOf("result"); + bool default_is_move; + iree_vm_ref_t* default_value = + VM_DecOperandRegRef("default_value", &default_is_move); const iree_vm_register_list_t* value_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc + 8]; - // Skip over all operands. - pc += - kRegSize + 4 + kRegSize + kRegSize + value_reg_list->size * kRegSize; - iree_vm_ref_t* new_value = default_value; + VM_DecVariadicOperands("values"); + bool result_is_move; + iree_vm_ref_t* result = VM_DecResultRegRef("result", &result_is_move); if (index >= 0 && index < value_reg_list->size) { - new_value = ®s.ref[value_reg_list->registers[index] & regs.ref_mask]; - is_move = value_reg_list->registers[index] & IREE_REF_REGISTER_MOVE_BIT; + bool is_move = + value_reg_list->registers[index] & IREE_REF_REGISTER_MOVE_BIT; + iree_vm_ref_t* new_value = + ®s.ref[value_reg_list->registers[index] & regs.ref_mask]; + iree_vm_ref_retain_or_move_checked(is_move, new_value, + type_def->ref_type, result); + } else { + iree_vm_ref_retain_or_move_checked(default_is_move, default_value, + type_def->ref_type, result); } - iree_vm_ref_t* result_reg = &OP_R_REF(0); - pc += kRegSize; - type_id = type_id >= module->type_count ? 0 : type_id; - const iree_vm_type_def_t* type_def = &module->type_table[type_id]; - iree_vm_ref_retain_or_move_checked(is_move, new_value, type_def->ref_type, - result_reg); }); //===------------------------------------------------------------------===// // Native integer arithmetic //===------------------------------------------------------------------===// - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"operand", 0>, - // VM_EncResult<"result">, - // ]; -#define DISPATCH_OP_UNARY_ALU_I32(op_name, type, op) \ - DISPATCH_OP(op_name, { \ - OP_R_I32(2) = (int32_t)(op((type)OP_R_I32(0))); \ - pc += kRegSize + kRegSize; \ +#define DISPATCH_OP_UNARY_ALU_I32(op_name, type, op) \ + DISPATCH_OP(op_name, { \ + int32_t operand = VM_DecOperandRegI32("operand"); \ + int32_t* result = VM_DecResultRegI32("result"); \ + *result = (int32_t)(op((type)operand)); \ }); - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"lhs", 0>, - // VM_EncOperand<"rhs", 1>, - // VM_EncResult<"result">, - // ]; -#define DISPATCH_OP_BINARY_ALU_I32(op_name, type, op) \ - DISPATCH_OP(op_name, { \ - OP_R_I32(4) = (int32_t)(((type)OP_R_I32(0))op((type)OP_R_I32(2))); \ - pc += kRegSize + kRegSize + kRegSize; \ +#define DISPATCH_OP_BINARY_ALU_I32(op_name, type, op) \ + DISPATCH_OP(op_name, { \ + int32_t lhs = VM_DecOperandRegI32("lhs"); \ + int32_t rhs = VM_DecOperandRegI32("rhs"); \ + int32_t* result = VM_DecResultRegI32("result"); \ + *result = (int32_t)(((type)lhs)op((type)rhs)); \ }); DISPATCH_OP_BINARY_ALU_I32(AddI32, int32_t, +); @@ -673,36 +598,30 @@ // Casting and type conversion/emulation //===------------------------------------------------------------------===// - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"operand", 0>, - // VM_EncResult<"result">, - // ]; #define DISPATCH_OP_CAST_I32(op_name, src_type, dst_type) \ DISPATCH_OP(op_name, { \ - OP_R_I32(2) = (dst_type)((src_type)OP_R_I32(0)); \ - pc += kRegSize + kRegSize; \ + int32_t operand = VM_DecOperandRegI32("operand"); \ + int32_t* result = VM_DecResultRegI32("result"); \ + *result = (dst_type)((src_type)operand); \ }); - DISPATCH_OP_CAST_I32(TruncI8, uint8_t, uint32_t); - DISPATCH_OP_CAST_I32(TruncI16, uint16_t, uint32_t); + DISPATCH_OP_CAST_I32(TruncI32I8, uint8_t, uint32_t); + DISPATCH_OP_CAST_I32(TruncI32I16, uint16_t, uint32_t); DISPATCH_OP_CAST_I32(ExtI8I32S, int8_t, int32_t); + DISPATCH_OP_CAST_I32(ExtI8I32U, uint8_t, uint32_t); DISPATCH_OP_CAST_I32(ExtI16I32S, int16_t, int32_t); + DISPATCH_OP_CAST_I32(ExtI16I32U, uint16_t, uint32_t); //===------------------------------------------------------------------===// // Native bitwise shifts and rotates //===------------------------------------------------------------------===// - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"operand", 0>, - // VM_EncIntAttr<"amount", type.bitwidth>, - // VM_EncResult<"result">, - // ]; -#define DISPATCH_OP_SHIFT_I32(op_name, type, op) \ - DISPATCH_OP(op_name, { \ - OP_R_I32(4) = (int32_t)(((type)OP_R_I32(0))op OP_I8(2)); \ - pc += kRegSize + kRegSize + kRegSize; \ +#define DISPATCH_OP_SHIFT_I32(op_name, type, op) \ + DISPATCH_OP(op_name, { \ + int32_t operand = VM_DecOperandRegI32("operand"); \ + int32_t amount = VM_DecConstI8("amount"); \ + int32_t* result = VM_DecResultRegI32("result"); \ + *result = (int32_t)(((type)operand)op amount); \ }); DISPATCH_OP_SHIFT_I32(ShlI32, int32_t, <<); @@ -713,67 +632,50 @@ // Comparison ops //===------------------------------------------------------------------===// - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"lhs", 0>, - // VM_EncOperand<"rhs", 1>, - // VM_EncResult<"result">, - // ]; -#define DISPATCH_OP_CMP_I32(op_name, type, op) \ - DISPATCH_OP(op_name, { \ - OP_R_I32(4) = (((type)OP_R_I32(0))op((type)OP_R_I32(2))) ? 1 : 0; \ - pc += kRegSize + kRegSize + kRegSize; \ +#define DISPATCH_OP_CMP_I32(op_name, type, op) \ + DISPATCH_OP(op_name, { \ + int32_t lhs = VM_DecOperandRegI32("lhs"); \ + int32_t rhs = VM_DecOperandRegI32("rhs"); \ + int32_t* result = VM_DecResultRegI32("result"); \ + *result = (((type)lhs)op((type)rhs)) ? 1 : 0; \ }); DISPATCH_OP_CMP_I32(CmpEQI32, int32_t, ==); DISPATCH_OP_CMP_I32(CmpNEI32, int32_t, !=); DISPATCH_OP_CMP_I32(CmpLTI32S, int32_t, <); DISPATCH_OP_CMP_I32(CmpLTI32U, uint32_t, <); - DISPATCH_OP_CMP_I32(CmpLTEI32S, int32_t, <=); - DISPATCH_OP_CMP_I32(CmpLTEI32U, uint32_t, <=); - DISPATCH_OP_CMP_I32(CmpGTI32S, int32_t, >); - DISPATCH_OP_CMP_I32(CmpGTI32U, uint32_t, >); - DISPATCH_OP_CMP_I32(CmpGTEI32S, int32_t, >=); - DISPATCH_OP_CMP_I32(CmpGTEI32U, uint32_t, >=); DISPATCH_OP(CmpNZI32, { - OP_R_I32(2) = (OP_R_I32(0) != 0) ? 1 : 0; - pc += kRegSize + kRegSize; + int32_t operand = VM_DecOperandRegI32("operand"); + int32_t* result = VM_DecResultRegI32("result"); + *result = (operand != 0) ? 1 : 0; }); DISPATCH_OP(CmpEQRef, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"lhs", 0>, - // VM_EncOperand<"rhs", 1>, - // VM_EncResult<"result">, - // ]; - // TODO(benvanik): move refs. - OP_R_I32(4) = iree_vm_ref_equal(&OP_R_REF(0), &OP_R_REF(2)); - if (OP_R_REF_IS_MOVE(0)) iree_vm_ref_release(&OP_R_REF(0)); - if (OP_R_REF_IS_MOVE(2)) iree_vm_ref_release(&OP_R_REF(2)); - pc += kRegSize + kRegSize + kRegSize; + bool lhs_is_move; + iree_vm_ref_t* lhs = VM_DecOperandRegRef("lhs", &lhs_is_move); + bool rhs_is_move; + iree_vm_ref_t* rhs = VM_DecOperandRegRef("rhs", &rhs_is_move); + int32_t* result = VM_DecResultRegI32("result"); + *result = iree_vm_ref_equal(lhs, rhs); + if (lhs_is_move) iree_vm_ref_release(lhs); + if (rhs_is_move) iree_vm_ref_release(rhs); }); DISPATCH_OP(CmpNERef, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"lhs", 0>, - // VM_EncOperand<"rhs", 1>, - // VM_EncResult<"result">, - // ]; - OP_R_I32(4) = !iree_vm_ref_equal(&OP_R_REF(0), &OP_R_REF(2)); - if (OP_R_REF_IS_MOVE(0)) iree_vm_ref_release(&OP_R_REF(0)); - if (OP_R_REF_IS_MOVE(2)) iree_vm_ref_release(&OP_R_REF(2)); - pc += kRegSize + kRegSize + kRegSize; + bool lhs_is_move; + iree_vm_ref_t* lhs = VM_DecOperandRegRef("lhs", &lhs_is_move); + bool rhs_is_move; + iree_vm_ref_t* rhs = VM_DecOperandRegRef("rhs", &rhs_is_move); + int32_t* result = VM_DecResultRegI32("result"); + *result = !iree_vm_ref_equal(lhs, rhs); + if (lhs_is_move) iree_vm_ref_release(lhs); + if (rhs_is_move) iree_vm_ref_release(rhs); }); DISPATCH_OP(CmpNZRef, { - // let encoding = [ - // VM_EncOpcode<opcode>, - // VM_EncOperand<"operand", 0>, - // VM_EncResult<"result">, - // ]; - OP_R_I32(2) = OP_R_REF(0).ptr != NULL; - if (OP_R_REF_IS_MOVE(0)) iree_vm_ref_release(&OP_R_REF(0)); - pc += kRegSize + kRegSize; + bool operand_is_move; + iree_vm_ref_t* operand = VM_DecOperandRegRef("operand", &operand_is_move); + int32_t* result = VM_DecResultRegI32("result"); + *result = operand->ptr != NULL ? 1 : 0; + if (operand_is_move) iree_vm_ref_release(operand); }); //===------------------------------------------------------------------===// @@ -781,39 +683,22 @@ //===------------------------------------------------------------------===// DISPATCH_OP(Branch, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Branch>, - // VM_EncBranch<"dest", "operands">, - // ]; - - int32_t block_pc = OP_I32(0); + int32_t block_pc = VM_DecBranchTarget("dest"); const iree_vm_register_remap_list_t* remap_list = - (const iree_vm_register_remap_list_t*)&bytecode_data[pc + 4]; - pc += 4 + kRegSize + remap_list->size * 2 * kRegSize; + VM_DecBranchOperands("operands"); pc = block_pc; iree_vm_bytecode_dispatch_remap_branch_registers(regs, remap_list); }); DISPATCH_OP(CondBranch, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_CondBranch>, - // VM_EncOperand<"condition", 0>, - // VM_EncBranch<"getTrueDest", "getTrueOperands">, - // VM_EncBranch<"getFalseDest", "getFalseOperands">, - // ]; - - int32_t cond_value = OP_R_I32(0); - int32_t true_block_pc = OP_I32(2); + int32_t condition = VM_DecOperandRegI32("condition"); + int32_t true_block_pc = VM_DecBranchTarget("true_dest"); const iree_vm_register_remap_list_t* true_remap_list = - (const iree_vm_register_remap_list_t*)&bytecode_data[pc + kRegSize + - 4]; - pc += kRegSize + 4 + kRegSize + true_remap_list->size * 2 * kRegSize; - int32_t false_block_pc = OP_I32(0); + VM_DecBranchOperands("true_operands"); + int32_t false_block_pc = VM_DecBranchTarget("false_dest"); const iree_vm_register_remap_list_t* false_remap_list = - (const iree_vm_register_remap_list_t*)&bytecode_data[pc + 4]; - pc += 4 + kRegSize + false_remap_list->size * 2 * kRegSize; - - if (cond_value) { + VM_DecBranchOperands("false_operands"); + if (condition) { pc = true_block_pc; iree_vm_bytecode_dispatch_remap_branch_registers(regs, true_remap_list); } else { @@ -824,21 +709,11 @@ }); DISPATCH_OP(Call, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Call>, - // VM_EncFuncAttr<"callee">, - // VM_EncVariadicOperands<"operands">, - // VM_EncVariadicResults<"results">, - // ]; - - // Get argument and result register lists and flush the caller frame. - int32_t function_ordinal = OP_I32(0); + int32_t function_ordinal = VM_DecFuncAttr("callee"); const iree_vm_register_list_t* src_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc + 4]; - pc += 4 + kRegSize + src_reg_list->size * kRegSize; + VM_DecVariadicOperands("operands"); const iree_vm_register_list_t* dst_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + dst_reg_list->size * kRegSize; + VM_DecVariadicResults("results"); current_frame->pc = pc; // NOTE: we assume validation has ensured these functions exist. @@ -887,29 +762,15 @@ }); DISPATCH_OP(CallVariadic, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_CallVariadic>, - // VM_EncFuncAttr<"callee">, - // VM_EncIntArrayAttr<"segment_sizes", 16>, - // VM_EncVariadicOperands<"operands">, - // VM_EncVariadicResults<"results">, - // ]; - // TODO(benvanik): dedupe with above or merge and always have the seg size // list be present (but empty) for non-variadic calls. - - // Get argument and result register lists and flush the caller frame. - int32_t function_ordinal = OP_I32(0); - pc += 4; + int32_t function_ordinal = VM_DecFuncAttr("callee"); const iree_vm_register_list_t* seg_size_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + seg_size_list->size * kRegSize; + VM_DecVariadicOperands("segment_sizes"); const iree_vm_register_list_t* src_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + src_reg_list->size * kRegSize; + VM_DecVariadicOperands("operands"); const iree_vm_register_list_t* dst_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + dst_reg_list->size * kRegSize; + VM_DecVariadicResults("results"); current_frame->pc = pc; // NOTE: we assume validation has ensured these functions exist. @@ -940,15 +801,9 @@ }); DISPATCH_OP(Return, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Return>, - // VM_EncVariadicOperands<"operands">, - // ]; - - // Remap registers from callee to caller. const iree_vm_register_list_t* src_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - current_frame->pc = pc + kRegSize + src_reg_list->size * kRegSize; + VM_DecVariadicOperands("operands"); + current_frame->pc = pc; // Leave callee by cleaning up the stack. iree_vm_stack_function_leave(stack, src_reg_list, ¤t_frame); @@ -969,16 +824,9 @@ }); DISPATCH_OP(Fail, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Fail>, - // VM_EncOperand<"status", 0>, - // VM_EncStrAttr<"message">, - // ]; - uint32_t status_code = OP_R_I32(0); - iree_string_view_t str; - str.size = OP_I16(2); - str.data = (const char*)&bytecode_data[pc + 2 + 2]; - pc += 2 + 2 + str.size; + uint32_t status_code = VM_DecOperandRegI32("status"); + iree_string_view_t message; + VM_DecStrAttr("message", &message); // TODO(benvanik): attach string and stack. if (status_code == 0) { // Shouldn't happen; we expect to die here, so there's no way to no-op. @@ -992,9 +840,6 @@ //===------------------------------------------------------------------===// DISPATCH_OP(Yield, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Yield>, - // ]; // TODO(benvanik): yield with execution results. return IREE_STATUS_OK; }); @@ -1004,71 +849,54 @@ //===------------------------------------------------------------------===// DISPATCH_OP(Trace, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Trace>, - // VM_EncStrAttr<"event_name">, - // VM_EncVariadicOperands<"operands">, - // ]; - iree_string_view_t str; - str.size = OP_I16(0); - str.data = (const char*)&bytecode_data[pc + 2]; - pc += 2 + str.size; + iree_string_view_t event_name; + VM_DecStrAttr("event_name", &event_name); const iree_vm_register_list_t* src_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + src_reg_list->size * kRegSize; + VM_DecVariadicOperands("operands"); // TODO(benvanik): trace (if enabled). iree_vm_bytecode_dispatch_discard_registers(regs, src_reg_list); }); DISPATCH_OP(Print, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Print>, - // VM_EncStrAttr<"message">, - // VM_EncVariadicOperands<"operands">, - // ]; - iree_string_view_t str; - str.size = OP_I16(0); - str.data = (const char*)&bytecode_data[pc + 2]; - pc += 2 + str.size; + iree_string_view_t event_name; + VM_DecStrAttr("event_name", &event_name); const iree_vm_register_list_t* src_reg_list = - (const iree_vm_register_list_t*)&bytecode_data[pc]; - pc += kRegSize + src_reg_list->size * kRegSize; + VM_DecVariadicOperands("operands"); // TODO(benvanik): print. iree_vm_bytecode_dispatch_discard_registers(regs, src_reg_list); }); DISPATCH_OP(Break, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_Break>, - // VM_EncBranch<"dest", "operands">, - // ]; // TODO(benvanik): break unconditionally. - int32_t block_pc = OP_I32(0); + int32_t block_pc = VM_DecBranchTarget("dest"); const iree_vm_register_remap_list_t* remap_list = - (const iree_vm_register_remap_list_t*)&bytecode_data[pc + 4]; - pc += 4 + kRegSize + remap_list->size * 2 * kRegSize; + VM_DecBranchOperands("operands"); iree_vm_bytecode_dispatch_remap_branch_registers(regs, remap_list); pc = block_pc; }); DISPATCH_OP(CondBreak, { - // let encoding = [ - // VM_EncOpcode<VM_OPC_CondBreak>, - // VM_EncBranch<"dest", "operands">, - // ]; - int32_t cond_value = OP_R_I32(0); - if (cond_value) { + int32_t condition = VM_DecOperandRegI32("condition"); + if (condition) { // TODO(benvanik): cond break. } - int32_t block_pc = OP_I32(2); + int32_t block_pc = VM_DecBranchTarget("dest"); const iree_vm_register_remap_list_t* remap_list = - (const iree_vm_register_remap_list_t*)&bytecode_data[pc + kRegSize + - 4]; - pc += kRegSize + 4 + kRegSize + remap_list->size * 2 * kRegSize; + VM_DecBranchOperands("operands"); iree_vm_bytecode_dispatch_remap_branch_registers(regs, remap_list); pc = block_pc; }); + //===------------------------------------------------------------------===// + // Extension trampolines + //===------------------------------------------------------------------===// + + DISPATCH_OP(PrefixExtI64, { return IREE_STATUS_UNIMPLEMENTED; }); + + DISPATCH_OP(PrefixExtF32, { return IREE_STATUS_UNIMPLEMENTED; }); + + DISPATCH_OP(PrefixExtF64, { return IREE_STATUS_UNIMPLEMENTED; }); + // NOLINTNEXTLINE(misc-static-assert) DISPATCH_UNHANDLED(); }
diff --git a/iree/vm/bytecode_module_size_benchmark.cc b/iree/vm/bytecode_module_size_benchmark.cc new file mode 100644 index 0000000..969ef22 --- /dev/null +++ b/iree/vm/bytecode_module_size_benchmark.cc
@@ -0,0 +1,50 @@ +// Copyright 2020 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/base/api.h" +#include "iree/vm/api.h" +#include "iree/vm/bytecode_module.h" +#include "iree/vm/bytecode_module_size_benchmark_module.h" + +extern "C" int main(int argc, char** argv) { + iree_vm_instance_t* instance = nullptr; + iree_vm_instance_create(IREE_ALLOCATOR_SYSTEM, &instance); + + const auto* module_file_toc = + iree::vm::bytecode_module_size_benchmark_module_create(); + iree_vm_module_t* module = nullptr; + iree_vm_bytecode_module_create( + iree_const_byte_span_t{ + reinterpret_cast<const uint8_t*>(module_file_toc->data), + module_file_toc->size}, + IREE_ALLOCATOR_NULL, IREE_ALLOCATOR_SYSTEM, &module); + + iree_vm_context_t* context = nullptr; + iree_vm_context_create_with_modules(instance, &module, /*module_count=*/1, + IREE_ALLOCATOR_SYSTEM, &context); + + iree_vm_function_t function; + iree_vm_module_lookup_function_by_name( + module, IREE_VM_FUNCTION_LINKAGE_EXPORT, + iree_make_cstring_view("empty_func"), &function); + + iree_vm_invoke(context, function, /*policy=*/nullptr, /*inputs=*/nullptr, + /*outputs=*/nullptr, IREE_ALLOCATOR_SYSTEM); + + iree_vm_module_release(module); + iree_vm_context_release(context); + iree_vm_instance_release(instance); + + return 0; +}
diff --git a/iree/vm/bytecode_module_size_benchmark.mlir b/iree/vm/bytecode_module_size_benchmark.mlir new file mode 100644 index 0000000..84ad13c --- /dev/null +++ b/iree/vm/bytecode_module_size_benchmark.mlir
@@ -0,0 +1,6 @@ +vm.module @bytecode_module_size_benchmark { + vm.export @empty_func + vm.func @empty_func() { + vm.return + } +}
diff --git a/iree/vm/invocation.c b/iree/vm/invocation.c index e04d796..f8cf3f9 100644 --- a/iree/vm/invocation.c +++ b/iree/vm/invocation.c
@@ -22,45 +22,45 @@ // Marshals a variant list of values into callee registers. // The |out_dst_reg_list| will be populated with the register ordinals and must -// be preallocated to store iree_vm_variant_list_size inputs. -static void iree_vm_stack_frame_marshal_inputs( - iree_vm_variant_list_t* inputs, const iree_vm_registers_t dst_regs, +// be preallocated to store iree_vm_list_size inputs. +static iree_status_t iree_vm_stack_frame_marshal_inputs( + iree_vm_list_t* inputs, const iree_vm_registers_t dst_regs, iree_vm_register_list_t* out_dst_reg_list) { - iree_host_size_t count = iree_vm_variant_list_size(inputs); + iree_host_size_t count = iree_vm_list_size(inputs); uint16_t i32_reg = 0; uint16_t ref_reg = 0; out_dst_reg_list->size = (uint16_t)count; for (iree_host_size_t i = 0; i < count; ++i) { - iree_vm_variant_t* variant = iree_vm_variant_list_get(inputs, i); - if (IREE_VM_VARIANT_IS_REF(variant)) { + iree_vm_variant_t variant = iree_vm_variant_empty(); + IREE_RETURN_IF_ERROR(iree_vm_list_get_variant(inputs, i, &variant)); + if (iree_vm_type_def_is_ref(&variant.type)) { out_dst_reg_list->registers[i] = ref_reg | IREE_REF_REGISTER_TYPE_BIT | IREE_REF_REGISTER_MOVE_BIT; iree_vm_ref_t* reg_ref = &dst_regs.ref[ref_reg++]; memset(reg_ref, 0, sizeof(*reg_ref)); - iree_vm_ref_retain(&variant->ref, reg_ref); + iree_vm_ref_retain(&variant.ref, reg_ref); } else { out_dst_reg_list->registers[i] = i32_reg; - dst_regs.i32[i32_reg++] = variant->i32; + dst_regs.i32[i32_reg++] = variant.i32; } } + return IREE_STATUS_OK; } // Marshals callee return registers into a variant list. static iree_status_t iree_vm_stack_frame_marshal_outputs( const iree_vm_registers_t src_regs, - const iree_vm_register_list_t* src_reg_list, - iree_vm_variant_list_t* outputs) { + const iree_vm_register_list_t* src_reg_list, iree_vm_list_t* outputs) { for (int i = 0; i < src_reg_list->size; ++i) { uint16_t reg = src_reg_list->registers[i]; if (reg & IREE_REF_REGISTER_TYPE_BIT) { iree_vm_ref_t* value = &src_regs.ref[reg & src_regs.ref_mask]; - IREE_RETURN_IF_ERROR( - iree_vm_variant_list_append_ref_move(outputs, value)); + IREE_RETURN_IF_ERROR(iree_vm_list_push_ref_move(outputs, value)); } else { iree_vm_value_t value; value.type = IREE_VM_VALUE_TYPE_I32; value.i32 = src_regs.i32[reg & src_regs.i32_mask]; - IREE_RETURN_IF_ERROR(iree_vm_variant_list_append_value(outputs, value)); + IREE_RETURN_IF_ERROR(iree_vm_list_push_value(outputs, &value)); } } return IREE_STATUS_OK; @@ -70,13 +70,12 @@ static iree_status_t iree_vm_invoke_within( iree_vm_context_t* context, iree_vm_stack_t* stack, iree_vm_function_t function, const iree_vm_invocation_policy_t* policy, - iree_vm_variant_list_t* inputs, iree_vm_variant_list_t* outputs) { + iree_vm_list_t* inputs, iree_vm_list_t* outputs) { // TODO(#2075): disabled because check_test is invoking native methods. // These checks should be nice and simple as we don't support variadic // args/results in bytecode. - iree_host_size_t input_count = inputs ? iree_vm_variant_list_size(inputs) : 0; - iree_host_size_t output_count = - outputs ? iree_vm_variant_list_capacity(outputs) : 0; + iree_host_size_t input_count = inputs ? iree_vm_list_size(inputs) : 0; + iree_host_size_t output_count = outputs ? iree_vm_list_capacity(outputs) : 0; // iree_vm_function_signature_t signature = // iree_vm_function_signature(&function); // if (input_count != signature.argument_count) { @@ -112,8 +111,8 @@ // Marshal inputs into the external stack frame registers. if (inputs) { - iree_vm_stack_frame_marshal_inputs(inputs, external_frame->registers, - argument_registers); + IREE_RETURN_IF_ERROR(iree_vm_stack_frame_marshal_inputs( + inputs, external_frame->registers, argument_registers)); } // Perform execution. Note that for synchronous execution we expect this to @@ -139,8 +138,8 @@ IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_invoke( iree_vm_context_t* context, iree_vm_function_t function, - const iree_vm_invocation_policy_t* policy, iree_vm_variant_list_t* inputs, - iree_vm_variant_list_t* outputs, iree_allocator_t allocator) { + const iree_vm_invocation_policy_t* policy, iree_vm_list_t* inputs, + iree_vm_list_t* outputs, iree_allocator_t allocator) { IREE_TRACE_ZONE_BEGIN(z0); // Allocate a VM stack on the host stack and initialize it.
diff --git a/iree/vm/invocation.h b/iree/vm/invocation.h index fc80156..ba62172 100644 --- a/iree/vm/invocation.h +++ b/iree/vm/invocation.h
@@ -19,8 +19,8 @@ #include "iree/base/api.h" #include "iree/vm/context.h" +#include "iree/vm/list.h" #include "iree/vm/module.h" -#include "iree/vm/variant_list.h" #ifdef __cplusplus extern "C" { @@ -46,15 +46,14 @@ // caller. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_invoke( iree_vm_context_t* context, iree_vm_function_t function, - const iree_vm_invocation_policy_t* policy, iree_vm_variant_list_t* inputs, - iree_vm_variant_list_t* outputs, iree_allocator_t allocator); + const iree_vm_invocation_policy_t* policy, iree_vm_list_t* inputs, + iree_vm_list_t* outputs, iree_allocator_t allocator); // TODO(benvanik): document and implement. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_invocation_create( iree_vm_context_t* context, iree_vm_function_t function, - const iree_vm_invocation_policy_t* policy, - const iree_vm_variant_list_t* inputs, iree_allocator_t allocator, - iree_vm_invocation_t** out_invocation); + const iree_vm_invocation_policy_t* policy, const iree_vm_list_t* inputs, + iree_allocator_t allocator, iree_vm_invocation_t** out_invocation); // Retains the given |invocation| for the caller. IREE_API_EXPORT iree_status_t IREE_API_CALL @@ -80,7 +79,7 @@ // released. // // Returns NULL if the invocation did not complete successfully. -IREE_API_EXPORT const iree_vm_variant_list_t* IREE_API_CALL +IREE_API_EXPORT const iree_vm_list_t* IREE_API_CALL iree_vm_invocation_output(iree_vm_invocation_t* invocation); // Blocks the caller until the invocation completes (successfully or otherwise).
diff --git a/iree/vm/list.c b/iree/vm/list.c index 237f506..ac1785e 100644 --- a/iree/vm/list.c +++ b/iree/vm/list.c
@@ -66,38 +66,6 @@ IREE_VM_DEFINE_TYPE_ADAPTERS(iree_vm_list, iree_vm_list_t); -IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_create( - const iree_vm_type_def_t* element_type, iree_host_size_t initial_capacity, - iree_allocator_t allocator, iree_vm_list_t** out_list) { - iree_vm_list_t* list = NULL; - IREE_RETURN_IF_ERROR( - iree_allocator_malloc(allocator, sizeof(iree_vm_list_t), (void**)&list)); - memset(list, 0, sizeof(*list)); - iree_atomic_store(&list->ref_object.counter, 1); - list->allocator = allocator; - list->element_type = *element_type; - - if (iree_vm_type_def_is_value(element_type)) { - list->storage_mode = IREE_VM_LIST_STORAGE_MODE_VALUE; - list->element_size = kValueTypeSizes[element_type->value_type]; - } else if (iree_vm_type_def_is_ref(element_type)) { - list->storage_mode = IREE_VM_LIST_STORAGE_MODE_REF; - list->element_size = sizeof(iree_vm_ref_t); - } else { - list->storage_mode = IREE_VM_LIST_STORAGE_MODE_VARIANT; - list->element_size = sizeof(iree_vm_variant2_t); - } - - iree_status_t status = iree_vm_list_reserve(list, initial_capacity); - if (!iree_status_is_ok(status)) { - iree_allocator_free(allocator, list); - return status; - } - - *out_list = list; - return IREE_STATUS_OK; -} - static void iree_vm_list_reset_range(iree_vm_list_t* list, iree_host_size_t offset, iree_host_size_t length) { @@ -113,7 +81,7 @@ break; } case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant_storage = (iree_vm_variant2_t*)list->storage; + iree_vm_variant_t* variant_storage = (iree_vm_variant_t*)list->storage; for (iree_host_size_t i = offset; i < length; ++i) { if (iree_vm_type_def_is_ref(&variant_storage[i].type)) { iree_vm_ref_release(&variant_storage[i].ref); @@ -124,6 +92,102 @@ } } +IREE_API_EXPORT iree_host_size_t iree_vm_list_storage_size( + const iree_vm_type_def_t* element_type, iree_host_size_t capacity) { + iree_host_size_t element_size = sizeof(iree_vm_variant_t); + if (element_type) { + if (iree_vm_type_def_is_value(element_type)) { + element_size = kValueTypeSizes[element_type->value_type]; + } else if (iree_vm_type_def_is_ref(element_type)) { + element_size = sizeof(iree_vm_ref_t); + } else { + element_size = sizeof(iree_vm_variant_t); + } + } + return iree_align(sizeof(iree_vm_list_t), 8) + + iree_align(capacity * element_size, 8); +} + +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_initialize( + iree_byte_span_t storage, const iree_vm_type_def_t* element_type, + iree_host_size_t capacity, iree_vm_list_t** out_list) { + iree_vm_list_storage_mode_t storage_mode = IREE_VM_LIST_STORAGE_MODE_VARIANT; + iree_host_size_t element_size = sizeof(iree_vm_variant_t); + if (element_type) { + if (iree_vm_type_def_is_value(element_type)) { + storage_mode = IREE_VM_LIST_STORAGE_MODE_VALUE; + element_size = kValueTypeSizes[element_type->value_type]; + } else if (iree_vm_type_def_is_ref(element_type)) { + storage_mode = IREE_VM_LIST_STORAGE_MODE_REF; + element_size = sizeof(iree_vm_ref_t); + } else { + storage_mode = IREE_VM_LIST_STORAGE_MODE_VARIANT; + element_size = sizeof(iree_vm_variant_t); + } + } + + iree_host_size_t storage_offset = iree_align(sizeof(iree_vm_list_t), 8); + iree_host_size_t required_storage_size = + storage_offset + iree_align(capacity * element_size, 8); + if (storage.data_length < required_storage_size) { + return IREE_STATUS_OUT_OF_RANGE; + } + memset(storage.data, 0, required_storage_size); + + iree_vm_list_t* list = (iree_vm_list_t*)storage.data; + iree_atomic_store(&list->ref_object.counter, 1); + if (element_type) { + list->element_type = *element_type; + } + list->element_size = element_size; + list->storage_mode = storage_mode; + list->capacity = capacity; + list->storage = storage.data + storage_offset; + + *out_list = list; + return IREE_STATUS_OK; +} + +IREE_API_EXPORT void IREE_API_CALL +iree_vm_list_deinitialize(iree_vm_list_t* list) { + iree_vm_list_reset_range(list, 0, list->count); + list->count = 0; +} + +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_create( + const iree_vm_type_def_t* element_type, iree_host_size_t initial_capacity, + iree_allocator_t allocator, iree_vm_list_t** out_list) { + iree_vm_list_t* list = NULL; + IREE_RETURN_IF_ERROR( + iree_allocator_malloc(allocator, sizeof(iree_vm_list_t), (void**)&list)); + memset(list, 0, sizeof(*list)); + iree_atomic_store(&list->ref_object.counter, 1); + list->allocator = allocator; + if (element_type) { + list->element_type = *element_type; + } + + if (iree_vm_type_def_is_value(&list->element_type)) { + list->storage_mode = IREE_VM_LIST_STORAGE_MODE_VALUE; + list->element_size = kValueTypeSizes[element_type->value_type]; + } else if (iree_vm_type_def_is_ref(&list->element_type)) { + list->storage_mode = IREE_VM_LIST_STORAGE_MODE_REF; + list->element_size = sizeof(iree_vm_ref_t); + } else { + list->storage_mode = IREE_VM_LIST_STORAGE_MODE_VARIANT; + list->element_size = sizeof(iree_vm_variant_t); + } + + iree_status_t status = iree_vm_list_reserve(list, initial_capacity); + if (!iree_status_is_ok(status)) { + iree_allocator_free(allocator, list); + return status; + } + + *out_list = list; + return IREE_STATUS_OK; +} + static void iree_vm_list_destroy(void* ptr) { iree_vm_list_t* list = (iree_vm_list_t*)ptr; iree_vm_list_reset_range(list, 0, list->count); @@ -284,12 +348,13 @@ break; } case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant = (iree_vm_variant2_t*)element_ptr; + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; if (!iree_vm_type_def_is_value(&variant->type)) { return IREE_STATUS_FAILED_PRECONDITION; } out_value->type = variant->type.value_type; - out_value->i64 = variant->i64; + memcpy(out_value->value_storage, variant->value_storage, + sizeof(out_value->value_storage)); break; } default: @@ -326,12 +391,13 @@ break; } case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant = (iree_vm_variant2_t*)element_ptr; + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; if (!iree_vm_type_def_is_value(&variant->type)) { return IREE_STATUS_FAILED_PRECONDITION; } value.type = variant->type.value_type; - value.i64 = variant->i64; + memcpy(value.value_storage, variant->value_storage, + sizeof(value.value_storage)); break; } default: @@ -380,10 +446,58 @@ break; } case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant = (iree_vm_variant2_t*)element_ptr; + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; + if (variant->type.ref_type) { + iree_vm_ref_release(&variant->ref); + } variant->type.value_type = target_type; variant->type.ref_type = IREE_VM_REF_TYPE_NULL; - variant->i64 = converted_value.i64; + memcpy(variant->value_storage, converted_value.value_storage, + sizeof(variant->value_storage)); + break; + } + default: + return IREE_STATUS_FAILED_PRECONDITION; + } + return IREE_STATUS_OK; +} + +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_value(iree_vm_list_t* list, const iree_vm_value_t* value) { + iree_host_size_t i = iree_vm_list_size(list); + IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, i + 1)); + return iree_vm_list_set_value(list, i, value); +} + +IREE_API_EXPORT void* iree_vm_list_get_ref_deref( + const iree_vm_list_t* list, iree_host_size_t i, + const iree_vm_ref_type_descriptor_t* type_descriptor) { + iree_vm_ref_t value = {0}; + if (!iree_status_is_ok(iree_vm_list_get_ref_assign(list, i, &value))) { + return NULL; + } else if (!iree_status_is_ok( + iree_vm_ref_check(&value, type_descriptor->type))) { + return NULL; + } + return value.ptr; +} + +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_ref_assign( + const iree_vm_list_t* list, iree_host_size_t i, iree_vm_ref_t* out_value) { + if (i >= list->count) return IREE_STATUS_OUT_OF_RANGE; + uintptr_t element_ptr = (uintptr_t)list->storage + i * list->element_size; + switch (list->storage_mode) { + case IREE_VM_LIST_STORAGE_MODE_REF: { + iree_vm_ref_t* element_ref = (iree_vm_ref_t*)element_ptr; + iree_vm_ref_assign(element_ref, out_value); + break; + } + case IREE_VM_LIST_STORAGE_MODE_VARIANT: { + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; + if (!iree_vm_type_def_is_ref(&variant->type)) { + return IREE_STATUS_FAILED_PRECONDITION; + } + iree_vm_ref_assign(&variant->ref, out_value); break; } default: @@ -394,25 +508,8 @@ IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_ref_retain( const iree_vm_list_t* list, iree_host_size_t i, iree_vm_ref_t* out_value) { - if (i >= list->count) return IREE_STATUS_OUT_OF_RANGE; - uintptr_t element_ptr = (uintptr_t)list->storage + i * list->element_size; - switch (list->storage_mode) { - case IREE_VM_LIST_STORAGE_MODE_REF: { - iree_vm_ref_t* element_ref = (iree_vm_ref_t*)element_ptr; - iree_vm_ref_retain(element_ref, out_value); - break; - } - case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant = (iree_vm_variant2_t*)element_ptr; - if (!iree_vm_type_def_is_ref(&variant->type)) { - return IREE_STATUS_FAILED_PRECONDITION; - } - iree_vm_ref_retain(&variant->ref, out_value); - break; - } - default: - return IREE_STATUS_FAILED_PRECONDITION; - } + IREE_RETURN_IF_ERROR(iree_vm_list_get_ref_assign(list, i, out_value)); + iree_vm_ref_retain(out_value, out_value); return IREE_STATUS_OK; } @@ -430,7 +527,10 @@ break; } case IREE_VM_LIST_STORAGE_MODE_VARIANT: { - iree_vm_variant2_t* variant = (iree_vm_variant2_t*)element_ptr; + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; + if (variant->type.value_type) { + memset(&variant->ref, 0, sizeof(variant->ref)); + } variant->type.value_type = IREE_VM_VALUE_TYPE_NONE; variant->type.ref_type = value->type; iree_vm_ref_retain_or_move(is_move, value, &variant->ref); @@ -448,22 +548,72 @@ (iree_vm_ref_t*)value); } +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_ref_retain(iree_vm_list_t* list, const iree_vm_ref_t* value) { + iree_host_size_t i = iree_vm_list_size(list); + IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, i + 1)); + return iree_vm_list_set_ref_retain(list, i, value); +} + IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_ref_move( iree_vm_list_t* list, iree_host_size_t i, iree_vm_ref_t* value) { return iree_vm_list_set_ref(list, i, /*is_move=*/true, value); } IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_ref_move(iree_vm_list_t* list, iree_vm_ref_t* value) { + iree_host_size_t i = iree_vm_list_size(list); + IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, i + 1)); + return iree_vm_list_set_ref_move(list, i, value); +} + +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_variant(const iree_vm_list_t* list, iree_host_size_t i, - iree_vm_variant2_t* out_value) { - return IREE_STATUS_UNIMPLEMENTED; + iree_vm_variant_t* out_value) { + if (i >= list->count) return IREE_STATUS_OUT_OF_RANGE; + uintptr_t element_ptr = (uintptr_t)list->storage + i * list->element_size; + switch (list->storage_mode) { + case IREE_VM_LIST_STORAGE_MODE_VALUE: { + out_value->type = list->element_type; + memcpy(out_value->value_storage, (void*)element_ptr, list->element_size); + break; + } + case IREE_VM_LIST_STORAGE_MODE_REF: { + iree_vm_ref_t* element_ref = (iree_vm_ref_t*)element_ptr; + out_value->type.ref_type = element_ref->type; + out_value->type.value_type = IREE_VM_VALUE_TYPE_NONE; + iree_vm_ref_retain(element_ref, &out_value->ref); + break; + } + case IREE_VM_LIST_STORAGE_MODE_VARIANT: { + iree_vm_variant_t* variant = (iree_vm_variant_t*)element_ptr; + out_value->type = variant->type; + if (iree_vm_type_def_is_ref(&variant->type)) { + iree_vm_ref_assign(&variant->ref, &out_value->ref); + } else { + memcpy(out_value->value_storage, variant->value_storage, + sizeof(variant->value_storage)); + } + break; + } + default: + return IREE_STATUS_FAILED_PRECONDITION; + } + return IREE_STATUS_OK; } IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_variant( - iree_vm_list_t* list, iree_host_size_t i, const iree_vm_variant2_t* value) { + iree_vm_list_t* list, iree_host_size_t i, const iree_vm_variant_t* value) { return IREE_STATUS_UNIMPLEMENTED; } +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_push_variant( + iree_vm_list_t* list, const iree_vm_variant_t* value) { + iree_host_size_t i = iree_vm_list_size(list); + IREE_RETURN_IF_ERROR(iree_vm_list_resize(list, i + 1)); + return iree_vm_list_set_variant(list, i, value); +} + iree_status_t iree_vm_list_register_types() { iree_vm_list_descriptor.destroy = iree_vm_list_destroy; iree_vm_list_descriptor.offsetof_counter =
diff --git a/iree/vm/list.h b/iree/vm/list.h index d0700db..00fd046 100644 --- a/iree/vm/list.h +++ b/iree/vm/list.h
@@ -33,15 +33,46 @@ // ABI. It is not designed for efficiency: if you are performing large amounts // of work on the list type you should instead be representing that using the // HAL types so that you can get acceleration. +// +// This type the same performance characteristics as std::vector; pushes may +// grow the capacity of the list and to ensure minimal wastage it is always +// better to reserve the exact desired element count first. typedef struct iree_vm_list iree_vm_list_t; #ifndef IREE_API_NO_PROTOTYPES +// Returns the size in bytes required to store a list with the given element +// type and capacity. This storage size can be used to stack allocate or reserve +// memory that is then used by iree_vm_list_initialize to avoid dynamic +// allocations. +IREE_API_EXPORT iree_host_size_t iree_vm_list_storage_size( + const iree_vm_type_def_t* element_type, iree_host_size_t capacity); + +// Initializes a statically-allocated list in the |storage| memory. +// The storage capacity must be large enough to hold the list internals and +// its contents which may vary across compilers/platforms/etc; use +// iree_vm_list_storage_size to query the required capacity. +// +// Statically-allocated lists have their lifetime controlled by the caller and +// must be deinitialized with iree_vm_list_deinitialize only when there are no +// more users of the list. +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_initialize( + iree_byte_span_t storage, const iree_vm_type_def_t* element_type, + iree_host_size_t capacity, iree_vm_list_t** out_list); + +// Deinitializes a statically-allocated |list| previously initialized with +// iree_vm_list_initialize. +IREE_API_EXPORT void IREE_API_CALL +iree_vm_list_deinitialize(iree_vm_list_t* list); + // Creates a growable list containing the given |element_type|, which may either // be a primitive iree_vm_value_type_t value (like i32) or a ref type. When // storing ref types the list may either store a specific iree_vm_ref_type_t // and ensure that all elements set match the type or IREE_VM_REF_TYPE_ANY to // indicate that any ref type is allowed. +// +// |element_type| can be set to iree_vm_type_def_make_variant_type (or null) to +// indicate that the list stores variants (each element can differ in type). IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_create( const iree_vm_type_def_t* element_type, iree_host_size_t initial_capacity, iree_allocator_t allocator, iree_vm_list_t** out_list); @@ -95,6 +126,25 @@ IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_value( iree_vm_list_t* list, iree_host_size_t i, const iree_vm_value_t* value); +// Pushes the value of the element to the end of the list. +// If the specified |value| type differs from the list storage type the value +// will be converted using the value type semantics (such as sign/zero extend, +// etc). +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_value(iree_vm_list_t* list, const iree_vm_value_t* value); + +// Returns a dereferenced pointer to the given type if the element at the given +// index matches the type. Returns NULL on error. +IREE_API_EXPORT void* iree_vm_list_get_ref_deref( + const iree_vm_list_t* list, iree_host_size_t i, + const iree_vm_ref_type_descriptor_t* type_descriptor); + +// Returns the ref value of the element at the given index. +// The ref will not be retained and must be retained by the caller to extend +// its lifetime. +IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_ref_assign( + const iree_vm_list_t* list, iree_host_size_t i, iree_vm_ref_t* out_value); + // Returns the ref value of the element at the given index. // The ref will be retained and must be released by the caller. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_ref_retain( @@ -105,23 +155,41 @@ IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_ref_retain( iree_vm_list_t* list, iree_host_size_t i, const iree_vm_ref_t* value); +// Pushes the ref value of the element to the end of the list, retaining a +// reference in the list until the element is cleared or the list is disposed. +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_ref_retain(iree_vm_list_t* list, const iree_vm_ref_t* value); + // Sets the ref value of the element at the given index, moving ownership of the // |value| reference to the list. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_ref_move( iree_vm_list_t* list, iree_host_size_t i, iree_vm_ref_t* value); +// Pushes the ref value of the element to the end of the list, moving ownership +// of the |value| reference to the list. +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_ref_move(iree_vm_list_t* list, iree_vm_ref_t* value); + // Returns the value of the element at the given index. If the element contains -// a ref then it will be retained and must be released by the caller. +// a ref it will *not* be retained and the caller must retain it to extend its +// lifetime. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_get_variant(const iree_vm_list_t* list, iree_host_size_t i, - iree_vm_variant2_t* out_value); + iree_vm_variant_t* out_value); // Sets the value of the element at the given index. If the specified |value| // type differs from the list storage type the value will be converted using the // value type semantics (such as sign/zero extend, etc). If the variant is a ref // then it will be retained. IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_list_set_variant( - iree_vm_list_t* list, iree_host_size_t i, const iree_vm_variant2_t* value); + iree_vm_list_t* list, iree_host_size_t i, const iree_vm_variant_t* value); + +// Pushes the value of the element to the end of the list. If the specified +// |value| type differs from the list storage type the value will be converted +// using the value type semantics (such as sign/zero extend, etc). If the +// variant is a ref then it will be retained. +IREE_API_EXPORT iree_status_t IREE_API_CALL +iree_vm_list_push_variant(iree_vm_list_t* list, const iree_vm_variant_t* value); #endif // IREE_API_NO_PROTOTYPES
diff --git a/iree/vm/module.h b/iree/vm/module.h index e278992..3081e10 100644 --- a/iree/vm/module.h +++ b/iree/vm/module.h
@@ -210,7 +210,7 @@ // attributes. // Returns IREE_STATUS_NOT_FOUND if index >= the number of attributes for // the function. - // See: docs/function_abi.md + // See: docs/design_docs/function_abi.md iree_status_t(IREE_API_PTR* get_function_reflection_attr)( void* self, iree_vm_function_linkage_t linkage, int32_t ordinal, int32_t index, iree_string_view_t* key, iree_string_view_t* value); @@ -277,7 +277,7 @@ // Returns the empty string if the reflection data in general or the specific // key is not found. // -// See: docs/function_abi.md for documentation on the ABI. +// See: docs/design_docs/function_abi.md for documentation on the ABI. IREE_API_EXPORT iree_string_view_t IREE_API_CALL iree_vm_function_reflection_attr(const iree_vm_function_t* function, iree_string_view_t key); @@ -289,7 +289,7 @@ // attributes. // Returns IREE_STATUS_NOT_FOUND if index >= the number of attributes for // the function. -// See: docs/function_abi.md +// See: docs/design_docs/function_abi.md IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_get_function_reflection_attr(iree_vm_function_t function, int32_t index, iree_string_view_t* key,
diff --git a/iree/vm/ref_cc.h b/iree/vm/ref_cc.h index 8120f24..13006d1 100644 --- a/iree/vm/ref_cc.h +++ b/iree/vm/ref_cc.h
@@ -107,39 +107,55 @@ return ref_type_descriptor<T>::get()->type; } - ABSL_ATTRIBUTE_ALWAYS_INLINE ref() noexcept = default; - ABSL_ATTRIBUTE_ALWAYS_INLINE ref(std::nullptr_t) noexcept {} // NOLINT - ABSL_ATTRIBUTE_ALWAYS_INLINE ref(T* p) noexcept : px_(p) {} - ABSL_ATTRIBUTE_ALWAYS_INLINE ~ref() noexcept { - if (px_) ref_type_release<T>(px_); - } + ABSL_ATTRIBUTE_ALWAYS_INLINE ref() noexcept + : ref_({ + 0, + ref_type_descriptor<T>::get()->offsetof_counter, + ref_type_descriptor<T>::get()->type, + }) {} + ABSL_ATTRIBUTE_ALWAYS_INLINE ref(std::nullptr_t) noexcept + : ref_({ + 0, + ref_type_descriptor<T>::get()->offsetof_counter, + ref_type_descriptor<T>::get()->type, + }) {} + ABSL_ATTRIBUTE_ALWAYS_INLINE ref(T* p) noexcept + : ref_({ + p, + ref_type_descriptor<T>::get()->offsetof_counter, + ref_type_descriptor<T>::get()->type, + }) {} + ABSL_ATTRIBUTE_ALWAYS_INLINE ~ref() noexcept { ref_type_release<T>(get()); } // Don't use implicit ref copying; use retain_ref instead to make things more // readable. We can't delete the ctor (or, I couldn't find a way not to) // because the templated parameter packing magic needs it. - ref(const ref& rhs) noexcept : px_(rhs.get()) { - if (px_) ref_type_retain<T>(px_); - } + ref(const ref& rhs) noexcept : ref_(rhs.ref_) { ref_type_retain<T>(get()); } ref& operator=(const ref&) noexcept = delete; // Move support to transfer ownership from one ref to another. - ref(ref&& rhs) noexcept : px_(rhs.release()) {} + ref(ref&& rhs) noexcept : ref_(rhs.ref_) { rhs.release(); } ref& operator=(ref&& rhs) noexcept { - if (px_ != rhs.px_) { - if (px_) ref_type_release<T>(px_); - px_ = rhs.release(); + if (get() != rhs.get()) { + ref_type_release<T>(get()); + ref_ = rhs.ref_; + rhs.release(); } return *this; } // Move support from another compatible type. template <typename U> - ref(ref<U>&& rhs) noexcept : px_(rhs.release()) {} // NOLINT + ref(ref<U>&& rhs) noexcept { + ref_.ptr = static_cast<T*>(rhs.release()); + ref_.offsetof_counter = rhs.ref_.offsetof_counter; + ref_.type = rhs.ref_.type; + } template <typename U> ref& operator=(ref<U>&& rhs) noexcept { - if (px_ != rhs.get()) { - if (px_) ref_type_release<T>(px_); - px_ = rhs.release(); + if (get() != rhs.get()) { + ref_type_release<T>(get()); + ref_.ptr = static_cast<T*>(rhs.release()); } return *this; } @@ -147,10 +163,8 @@ // Resets the object to nullptr and decrements the reference count, possibly // deleting it. void reset() noexcept { - if (px_) { - ref_type_release<T>(px_); - px_ = nullptr; - } + ref_type_release<T>(get()); + ref_.ptr = nullptr; } // Releases a pointer. @@ -159,8 +173,8 @@ // Returns nullptr if the ref holds no value. // To re-wrap in a ref use either ref<T>(value) or assign(). ABSL_ATTRIBUTE_ALWAYS_INLINE T* release() noexcept { - T* p = px_; - px_ = nullptr; + T* p = get(); + ref_.ptr = nullptr; return p; } @@ -169,33 +183,42 @@ // not be incremented. ABSL_ATTRIBUTE_ALWAYS_INLINE void assign(T* value) noexcept { reset(); - px_ = value; + ref_.ptr = value; } // Gets the pointer referenced by this instance. // operator* and operator-> will assert() if there is no current object. - constexpr T* get() const noexcept { return px_; } - constexpr T& operator*() const noexcept { return *px_; } - constexpr T* operator->() const noexcept { return px_; } + constexpr T* get() const noexcept { return reinterpret_cast<T*>(ref_.ptr); } + constexpr T& operator*() const noexcept { return *get(); } + constexpr T* operator->() const noexcept { return get(); } // Returns a pointer to the inner pointer storage. // This allows passing a pointer to the ref as an output argument to C-style // creation functions. - constexpr T** operator&() noexcept { return &px_; } // NOLINT + constexpr T** operator&() noexcept { + return reinterpret_cast<T**>(&ref_.ptr); + } // Support boolean expression evaluation ala unique_ptr/shared_ptr: // https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool constexpr operator unspecified_bool_type() const noexcept { - return px_ ? &this_type::px_ : nullptr; + return get() ? reinterpret_cast<unspecified_bool_type>(&this_type::ref_.ptr) + : nullptr; } // Supports unary expression evaluation. - constexpr bool operator!() const noexcept { return !px_; } + constexpr bool operator!() const noexcept { return !get(); } // Swap support. - void swap(ref& rhs) { std::swap(px_, rhs.px_); } + void swap(ref& rhs) { std::swap(ref_.ptr, rhs.ref_.ptr); } + + // Allows directly passing the ref to a C-API function for creation. + // Example: + // iree::vm::ref<my_type_t> value; + // my_type_create(..., &value); + constexpr operator iree_vm_ref_t*() const noexcept { return &ref_; } private: - T* px_ = nullptr; + mutable iree_vm_ref_t ref_; }; // Adds a reference to the given ref and returns the same ref. @@ -206,7 +229,7 @@ // retain_ref(b); // ref count + 1 template <typename T> inline ref<T> retain_ref(const ref<T>& value) { - if (value) ref_type_retain<T>(value.get()); + ref_type_retain<T>(value.get()); return ref<T>(value.get()); } @@ -217,7 +240,7 @@ // ref<MyType> p = retain_ref(raw_ptr); // ref count + 1 template <typename T> inline ref<T> retain_ref(T* value) { - if (value) ref_type_retain<T>(value); + ref_type_retain<T>(value); return ref<T>(value); }
diff --git a/iree/vm/stack.c b/iree/vm/stack.c index dc4e405..d65659c 100644 --- a/iree/vm/stack.c +++ b/iree/vm/stack.c
@@ -499,8 +499,8 @@ const iree_vm_register_list_t* src_reg_list, const iree_vm_registers_t dst_regs, const iree_vm_register_list_t* dst_reg_list) { - VMCHECK(src_reg_list->size == dst_reg_list->size); - if (src_reg_list->size != dst_reg_list->size) return; + VMCHECK(src_reg_list->size <= dst_reg_list->size); + if (src_reg_list->size > dst_reg_list->size) return; for (int i = 0; i < src_reg_list->size; ++i) { // TODO(benvanik): change encoding to avoid this branching. // Could write two arrays: one for prims and one for refs. @@ -637,6 +637,7 @@ VMCHECK(external_registers->size >= callee_registers->size); uint16_t i32_reg_ordinal = 0; uint16_t ref_reg_ordinal = 0; + ((iree_vm_register_list_t*)external_registers)->size = callee_registers->size; uint16_t* dst_reg_list = (uint16_t*)external_registers->registers; for (int i = 0; i < callee_registers->size; ++i) { uint16_t src_reg = callee_registers->registers[i];
diff --git a/iree/vm/stack.h b/iree/vm/stack.h index ffbc1e0..7bd3535 100644 --- a/iree/vm/stack.h +++ b/iree/vm/stack.h
@@ -22,7 +22,6 @@ #include "iree/base/api.h" #include "iree/vm/module.h" #include "iree/vm/ref.h" -#include "iree/vm/variant_list.h" #ifdef __cplusplus extern "C" {
diff --git a/iree/vm/test/BUILD b/iree/vm/test/BUILD index 5018865..c33c07d 100644 --- a/iree/vm/test/BUILD +++ b/iree/vm/test/BUILD
@@ -25,6 +25,7 @@ name = "all_bytecode_modules_cc", srcs = [ ":arithmetic_ops.module", + ":comparison_ops.module", ":control_flow_ops.module", ":list_ops.module", ], @@ -41,6 +42,12 @@ ) iree_bytecode_module( + name = "comparison_ops", + src = "comparison_ops.mlir", + flags = ["-iree-vm-ir-to-bytecode-module"], +) + +iree_bytecode_module( name = "control_flow_ops", src = "control_flow_ops.mlir", flags = ["-iree-vm-ir-to-bytecode-module"],
diff --git a/iree/vm/test/CMakeLists.txt b/iree/vm/test/CMakeLists.txt index cb6951f..747595b 100644 --- a/iree/vm/test/CMakeLists.txt +++ b/iree/vm/test/CMakeLists.txt
@@ -19,6 +19,7 @@ all_bytecode_modules_cc GENERATED_SRCS "arithmetic_ops.module" + "comparison_ops.module" "control_flow_ops.module" "list_ops.module" CC_FILE_OUTPUT @@ -43,6 +44,16 @@ iree_bytecode_module( NAME + comparison_ops + SRC + "comparison_ops.mlir" + FLAGS + "-iree-vm-ir-to-bytecode-module" + PUBLIC +) + +iree_bytecode_module( + NAME control_flow_ops SRC "control_flow_ops.mlir"
diff --git a/iree/vm/test/comparison_ops.mlir b/iree/vm/test/comparison_ops.mlir new file mode 100644 index 0000000..7161cb6 --- /dev/null +++ b/iree/vm/test/comparison_ops.mlir
@@ -0,0 +1,172 @@ +vm.module @comparison_ops { + + //===--------------------------------------------------------------------===// + // vm.cmp.lt.i32.s + //===--------------------------------------------------------------------===// + + vm.export @test_cmp_lt_s_0 + vm.func @test_cmp_lt_s_0() { + %lhs = vm.const.i32 2 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 -2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.s %lhs_dno, %rhs_dno : i32 + %expected = vm.const.i32 0 : i32 + vm.check.eq %actual, %expected, "2 < -2" : i32 + vm.return + } + + vm.export @test_cmp_lt_s_1 + vm.func @test_cmp_lt_s_1() { + %lhs = vm.const.i32 -2 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.s %lhs_dno, %rhs_dno : i32 + %expected = vm.const.i32 1 : i32 + vm.check.eq %actual, %expected, "-2 < 2" : i32 + vm.return + } + + // Expect UINT_MAX to be interpreted as -1 when doing a signed compare. + vm.export @test_cmp_lt_s_2 + vm.func @test_cmp_lt_s_2() { + %lhs = vm.const.i32 4294967295 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.s %lhs_dno, %rhs_dno : i32 + %expected = vm.const.i32 1 : i32 + vm.check.eq %actual, %expected, "4294967295 (UINT_MAX) < 2" : i32 + vm.return + } + + //===--------------------------------------------------------------------===// + // vm.cmp.lt.i32.u + //===--------------------------------------------------------------------===// + + vm.export @test_cmp_lt_u_0 + vm.func @test_cmp_lt_u_0() { + %lhs = vm.const.i32 2 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 -2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.u %lhs_dno, %rhs_dno : i32 + %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 + vm.func @test_cmp_lt_u_1() { + %lhs = vm.const.i32 -2 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.u %lhs_dno, %rhs_dno : i32 + %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 + vm.func @test_cmp_lt_u_2() { + %lhs = vm.const.i32 4294967295 : i32 + %lhs_dno = iree.do_not_optimize(%lhs) : i32 + %rhs = vm.const.i32 2 : i32 + %rhs_dno = iree.do_not_optimize(%rhs) : i32 + %actual = vm.cmp.lt.i32.u %lhs_dno, %rhs_dno : i32 + %expected = vm.const.i32 0 : i32 + vm.check.eq %actual, %expected, "4294967295 (UINT_MAX) < 2 (as unsigned)" : i32 + vm.return + } + + //===--------------------------------------------------------------------===// + // vm.cmp.*.i32.* 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 + vm.func @test_cmp_lte() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i32 -2 : i32 + %cn2_dno = iree.do_not_optimize(%cn2) : i32 + %c2 = vm.const.i32 2 : i32 + %c2_dno = iree.do_not_optimize(%c2) : i32 + + %cmp_0 = vm.cmp.lte.i32.s %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_0, %true, "-2 <= 2" : i32 + %cmp_1 = vm.cmp.lte.i32.s %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_1, %false, "2 <= -2" : i32 + %cmp_2 = vm.cmp.lte.i32.s %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_2, %true, "2 <= 2" : i32 + + %cmp_3 = vm.cmp.lte.i32.u %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_3, %false, "-2 <= 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.lte.i32.u %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_4, %true, "2 <= -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.lte.i32.u %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_5, %true, "2 <= 2 (unsigned)" : i32 + + vm.return + } + + vm.export @test_cmp_gt + vm.func @test_cmp_gt() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i32 -2 : i32 + %cn2_dno = iree.do_not_optimize(%cn2) : i32 + %c2 = vm.const.i32 2 : i32 + %c2_dno = iree.do_not_optimize(%c2) : i32 + + %cmp_0 = vm.cmp.gt.i32.s %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_0, %false, "-2 > 2" : i32 + %cmp_1 = vm.cmp.gt.i32.s %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_1, %true, "2 > -2" : i32 + %cmp_2 = vm.cmp.gt.i32.s %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_2, %false, "2 > 2" : i32 + + %cmp_3 = vm.cmp.gt.i32.u %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_3, %true, "-2 > 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.gt.i32.u %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_4, %false, "2 > -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.gt.i32.u %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_5, %false, "2 > 2 (unsigned)" : i32 + + vm.return + } + + vm.export @test_cmp_gte + vm.func @test_cmp_gte() { + %true = vm.const.i32 1 : i32 + %false = vm.const.i32 0 : i32 + + %cn2 = vm.const.i32 -2 : i32 + %cn2_dno = iree.do_not_optimize(%cn2) : i32 + %c2 = vm.const.i32 2 : i32 + %c2_dno = iree.do_not_optimize(%c2) : i32 + + %cmp_0 = vm.cmp.gte.i32.s %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_0, %false, "-2 >= 2" : i32 + %cmp_1 = vm.cmp.gte.i32.s %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_1, %true, "2 >= -2" : i32 + %cmp_2 = vm.cmp.gte.i32.s %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_2, %true, "2 >= 2" : i32 + + %cmp_3 = vm.cmp.gte.i32.u %cn2_dno, %c2_dno : i32 + vm.check.eq %cmp_3, %true, "-2 >= 2 (unsigned)" : i32 + %cmp_4 = vm.cmp.gte.i32.u %c2_dno, %cn2_dno : i32 + vm.check.eq %cmp_4, %false, "2 >= -2 (unsigned)" : i32 + %cmp_5 = vm.cmp.gte.i32.u %c2_dno, %c2_dno : i32 + vm.check.eq %cmp_5, %true, "2 >= 2 (unsigned)" : i32 + + vm.return + } + +}
diff --git a/iree/vm/type_def.h b/iree/vm/type_def.h index 4874b3a..2055fa2 100644 --- a/iree/vm/type_def.h +++ b/iree/vm/type_def.h
@@ -84,8 +84,16 @@ int32_t i32; int64_t i64; iree_vm_ref_t ref; + + uint8_t value_storage[IREE_VM_VALUE_STORAGE_SIZE]; // max size of all value + // types }; -} iree_vm_variant2_t; +} iree_vm_variant_t; + +#define iree_vm_variant_empty() \ + { {IREE_VM_VALUE_TYPE_NONE, IREE_VM_REF_TYPE_NULL}, {0}, } +#define iree_vm_variant_is_value(v) iree_vm_type_def_is_value(&v.type) +#define iree_vm_variant_is_ref(v) iree_vm_type_def_is_ref(&v.type) #ifdef __cplusplus } // extern "C"
diff --git a/iree/vm/value.h b/iree/vm/value.h index bb7ecc7..92dc11f 100644 --- a/iree/vm/value.h +++ b/iree/vm/value.h
@@ -38,6 +38,9 @@ IREE_VM_VALUE_TYPE_COUNT = IREE_VM_VALUE_TYPE_MAX + 1, } iree_vm_value_type_t; +// Maximum size, in bytes, of any value type we can represent. +#define IREE_VM_VALUE_STORAGE_SIZE 8 + // A variant value type. typedef struct iree_vm_value { iree_vm_value_type_t type; @@ -46,6 +49,9 @@ int16_t i16; int32_t i32; int64_t i64; + + uint8_t value_storage[IREE_VM_VALUE_STORAGE_SIZE]; // max size of all value + // types }; } iree_vm_value_t;
diff --git a/iree/vm/variant_list.c b/iree/vm/variant_list.c deleted file mode 100644 index 1b6a1e6..0000000 --- a/iree/vm/variant_list.c +++ /dev/null
@@ -1,128 +0,0 @@ -// 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/vm/variant_list.h" - -struct iree_vm_variant_list { - iree_allocator_t allocator; - iree_host_size_t capacity; - iree_host_size_t count; - iree_vm_variant_t values[]; -}; - -IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_variant_list_alloc( - iree_host_size_t capacity, iree_allocator_t allocator, - iree_vm_variant_list_t** out_list) { - if (!out_list) { - return IREE_STATUS_INVALID_ARGUMENT; - } - *out_list = NULL; - - iree_host_size_t alloc_size = iree_vm_variant_list_alloc_size(capacity); - iree_vm_variant_list_t* list = NULL; - IREE_RETURN_IF_ERROR( - iree_allocator_malloc(allocator, alloc_size, (void**)&list)); - iree_vm_variant_list_init(list, capacity); - list->allocator = allocator; - *out_list = list; - return IREE_STATUS_OK; -} - -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_alloc_size(iree_host_size_t capacity) { - return sizeof(iree_vm_variant_list_t) + sizeof(iree_vm_variant_t) * capacity; -} - -IREE_API_EXPORT void IREE_API_CALL iree_vm_variant_list_init( - iree_vm_variant_list_t* list, iree_host_size_t capacity) { - memset(&list->allocator, 0, sizeof(list->allocator)); - list->capacity = capacity; - list->count = 0; - memset(list->values, 0, sizeof(list->values[0]) * capacity); -} - -IREE_API_EXPORT void IREE_API_CALL -iree_vm_variant_list_free(iree_vm_variant_list_t* list) { - for (iree_host_size_t i = 0; i < list->count; ++i) { - if (IREE_VM_VARIANT_IS_REF(&list->values[i])) { - iree_vm_ref_release(&list->values[i].ref); - } - } - iree_allocator_free(list->allocator, list); -} - -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_capacity(const iree_vm_variant_list_t* list) { - return list->capacity; -} - -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_size(const iree_vm_variant_list_t* list) { - return list->count; -} - -IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_variant_list_append_value( - iree_vm_variant_list_t* list, iree_vm_value_t value) { - if (list->count + 1 > list->capacity) { - return IREE_STATUS_OUT_OF_RANGE; - } - iree_host_size_t i = list->count++; - list->values[i].value_type = value.type; - list->values[i].ref_type = IREE_VM_REF_TYPE_NULL; - list->values[i].i32 = value.i32; - return IREE_STATUS_OK; -} - -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_ref_retain(iree_vm_variant_list_t* list, - iree_vm_ref_t* ref) { - if (list->count + 1 > list->capacity) { - return IREE_STATUS_OUT_OF_RANGE; - } - iree_host_size_t i = list->count++; - list->values[i].value_type = IREE_VM_VALUE_TYPE_NONE; - list->values[i].ref_type = ref->type; - iree_vm_ref_retain(ref, &list->values[i].ref); - return IREE_STATUS_OK; -} - -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_ref_move(iree_vm_variant_list_t* list, - iree_vm_ref_t* ref) { - if (list->count + 1 > list->capacity) { - return IREE_STATUS_OUT_OF_RANGE; - } - iree_host_size_t i = list->count++; - list->values[i].value_type = IREE_VM_VALUE_TYPE_NONE; - list->values[i].ref_type = ref->type; - iree_vm_ref_move(ref, &list->values[i].ref); - return IREE_STATUS_OK; -} - -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_null_ref(iree_vm_variant_list_t* list) { - if (list->count + 1 > list->capacity) { - return IREE_STATUS_OUT_OF_RANGE; - } - iree_host_size_t i = list->count++; - list->values[i].value_type = IREE_VM_VALUE_TYPE_NONE; - list->values[i].ref_type = IREE_VM_REF_TYPE_NULL; - return IREE_STATUS_OK; -} - -IREE_API_EXPORT iree_vm_variant_t* IREE_API_CALL -iree_vm_variant_list_get(iree_vm_variant_list_t* list, iree_host_size_t i) { - if (i < 0 || i > list->count) return NULL; - return &list->values[i]; -}
diff --git a/iree/vm/variant_list.h b/iree/vm/variant_list.h deleted file mode 100644 index 830efb8..0000000 --- a/iree/vm/variant_list.h +++ /dev/null
@@ -1,111 +0,0 @@ -// 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_VM_VARIANT_LIST_H_ -#define IREE_VM_VARIANT_LIST_H_ - -#include <stdint.h> - -#include "iree/vm/ref.h" -#include "iree/vm/value.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// A list able to hold both value and ref types, used for marshaling host -// language calls to VM calls. -// -// Lists may either be stack or heap allocated depending on how long they must -// live. Prefer stack allocations when APIs receiving the lists document -// themselves as copying the list values. -typedef struct iree_vm_variant_list iree_vm_variant_list_t; - -// An element of an iree_vm_variant_list_t. -typedef struct { - iree_vm_value_type_t value_type : 8; - iree_vm_ref_type_t ref_type : 24; - union { - int32_t i32; - iree_vm_ref_t ref; - }; -} iree_vm_variant_t; - -#define IREE_VM_VARIANT_IS_VALUE(v) ((v)->value_type != IREE_VM_VALUE_TYPE_NONE) -#define IREE_VM_VARIANT_IS_REF(v) !IREE_VM_VARIANT_IS_VALUE(v) - -#ifndef IREE_API_NO_PROTOTYPES - -// Allocates a list with the maximum |capacity|. -// The list must be freed with iree_vm_variant_list_free unless ownership is -// transferred to code that will perform the free as documented in its API. -IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_variant_list_alloc( - iree_host_size_t capacity, iree_allocator_t allocator, - iree_vm_variant_list_t** out_list); - -// Returns the size, in bytes, required to store a list of the given capacity. -// This can be used to stack-allocate the variant list and then wrap the memory -// for use as a list with iree_vm_variant_list_init. -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_alloc_size(iree_host_size_t capacity); - -// Initializes the allocated |list| with the given |capacity|. The list -// allocation must be at least the size returned by -// iree_vm_variant_list_alloc_size for the same |capacity|. -// The list must be freed with iree_vm_variant_list_free unless ownership is -// transferred to code that will perform the free as documented in its API. -IREE_API_EXPORT void IREE_API_CALL iree_vm_variant_list_init( - iree_vm_variant_list_t* list, iree_host_size_t capacity); - -// Frees the list using the allocator it was originally allocated from. -IREE_API_EXPORT void IREE_API_CALL -iree_vm_variant_list_free(iree_vm_variant_list_t* list); - -// Returns the capacity of the list in elements. -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_capacity(const iree_vm_variant_list_t* list); - -// Returns the total number of elements added to the list. -IREE_API_EXPORT iree_host_size_t IREE_API_CALL -iree_vm_variant_list_size(const iree_vm_variant_list_t* list); - -// Appends a primitive value to the list. -IREE_API_EXPORT iree_status_t IREE_API_CALL iree_vm_variant_list_append_value( - iree_vm_variant_list_t* list, iree_vm_value_t value); - -// Appends a ref object to the list by retaining it. -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_ref_retain(iree_vm_variant_list_t* list, - iree_vm_ref_t* ref); - -// Appends a ref object to the list by moving it. -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_ref_move(iree_vm_variant_list_t* list, - iree_vm_ref_t* ref); - -// Appends a null ref to the list. -IREE_API_EXPORT iree_status_t IREE_API_CALL -iree_vm_variant_list_append_null_ref(iree_vm_variant_list_t* list); - -// Returns a pointer to the variant element at the given index. -IREE_API_EXPORT iree_vm_variant_t* IREE_API_CALL -iree_vm_variant_list_get(iree_vm_variant_list_t* list, iree_host_size_t i); - -#endif // IREE_API_NO_PROTOTYPES - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // IREE_VM_VARIANT_LIST_H_
diff --git a/kokoro/gcp_ubuntu/bazel/bindings/common.cfg b/kokoro/gcp_ubuntu/bazel/bindings/common.cfg index d4a4e26..8a49430 100644 --- a/kokoro/gcp_ubuntu/bazel/bindings/common.cfg +++ b/kokoro/gcp_ubuntu/bazel/bindings/common.cfg
@@ -17,4 +17,4 @@ # Common configuration for Kokoro builds that run the bindings build with bazel # on linux. -build_file: "iree/kokoro/gcp_ubuntu/bazel/bindings/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/build_kokoro.sh"
diff --git a/kokoro/gcp_ubuntu/bazel/core/common.cfg b/kokoro/gcp_ubuntu/bazel/core/common.cfg index b8ccaa7..3a22d10 100755 --- a/kokoro/gcp_ubuntu/bazel/core/common.cfg +++ b/kokoro/gcp_ubuntu/bazel/core/common.cfg
@@ -17,4 +17,4 @@ # Common configuration for Kokoro builds that run the core build with bazel on # linux. -build_file: "iree/kokoro/gcp_ubuntu/bazel/core/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/build_kokoro.sh"
diff --git a/kokoro/gcp_ubuntu/bazel/integrations/common.cfg b/kokoro/gcp_ubuntu/bazel/integrations/common.cfg index 9331508..eb31e55 100644 --- a/kokoro/gcp_ubuntu/bazel/integrations/common.cfg +++ b/kokoro/gcp_ubuntu/bazel/integrations/common.cfg
@@ -17,4 +17,4 @@ # Common configuration for Kokoro builds that run the integrations build with # bazel on linux. -build_file: "iree/kokoro/gcp_ubuntu/bazel/integrations/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh"
diff --git a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg b/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg index 8159f36..1376e08 100644 --- a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg +++ b/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/common.cfg
@@ -17,4 +17,4 @@ # Common configuration for Kokoro builds that cross-compile IREE towards # Android arm64-v8a using CMake. -build_file: "iree/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/build_kokoro.sh"
diff --git a/kokoro/gcp_ubuntu/cmake/common.cfg b/kokoro/gcp_ubuntu/cmake/common.cfg index 838f4a5..49e6865 100644 --- a/kokoro/gcp_ubuntu/cmake/common.cfg +++ b/kokoro/gcp_ubuntu/cmake/common.cfg
@@ -16,4 +16,4 @@ # Common configuration for Kokoro builds that run cmake on linux. -build_file: "iree/kokoro/gcp_ubuntu/cmake/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/build_kokoro.sh"
diff --git a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg b/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg index 9e6847d..bdb9163 100644 --- a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg +++ b/kokoro/gcp_ubuntu/cmake/linux/x86-turing/common.cfg
@@ -16,4 +16,4 @@ # Common configuration for Kokoro builds that run cmake on linux. -build_file: "iree/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh" +build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/build_kokoro.sh"
diff --git a/packaging/python/common_setup.py b/packaging/python/common_setup.py index cbaf1d1..149dbdf 100644 --- a/packaging/python/common_setup.py +++ b/packaging/python/common_setup.py
@@ -16,6 +16,7 @@ import platform import setuptools import sys +import sysconfig from datetime import date @@ -99,15 +100,6 @@ } -def get_native_file_extension(): - if platform.system() == "Windows": - return "pyd" - elif platform.system() == "Darwin": - return "dylib" - else: - return "so" - - def setup(**kwargs): # See: https://stackoverflow.com/q/45150304 try: @@ -128,7 +120,7 @@ # Unfortunately, bazel is imprecise and scatters .so files around, so # need to be specific. package_data = { - "": ["*.%s" % (get_native_file_extension(),)], + "": ["*%s" % (sysconfig.get_config_var("EXT_SUFFIX"),)], } setuptools.setup( package_data=package_data,
diff --git a/packaging/python/setup_compiler.py b/packaging/python/setup_compiler.py index c33d7fd..ee9e87d 100644 --- a/packaging/python/setup_compiler.py +++ b/packaging/python/setup_compiler.py
@@ -39,7 +39,12 @@ print("Found packages:", packages) setup_kwargs = common_setup.get_setup_defaults( sub_project="compiler", description="IREE Generic Compiler") - common_setup.setup(packages=packages, **setup_kwargs) + common_setup.setup( + packages=packages, + ext_modules=[ + setuptools.Extension(name="pyiree.compiler.binding", sources=[]), + ], + **setup_kwargs) if __name__ == "__main__":
diff --git a/packaging/python/setup_rt.py b/packaging/python/setup_rt.py index ef39248..af30fd6 100644 --- a/packaging/python/setup_rt.py +++ b/packaging/python/setup_rt.py
@@ -35,7 +35,12 @@ setup_kwargs = common_setup.get_setup_defaults( sub_project="rt", description="IREE Runtime Components (for executing compiled programs)") - common_setup.setup(packages=packages, **setup_kwargs) + common_setup.setup( + packages=packages, + ext_modules=[ + setuptools.Extension(name="pyiree.rt.binding", sources=[]), + ], + **setup_kwargs) if __name__ == "__main__":
diff --git a/packaging/python/setup_tf.py b/packaging/python/setup_tf.py index 6f97d70..9eccf4f 100644 --- a/packaging/python/setup_tf.py +++ b/packaging/python/setup_tf.py
@@ -45,7 +45,12 @@ sub_project="tf", description="IREE TensorFlow Compiler", package_dir=package_dir) - common_setup.setup(packages=packages, **setup_kwargs) + common_setup.setup( + packages=packages, + ext_modules=[ + setuptools.Extension(name="pyiree.tf.compiler.binding", sources=[]), + ], + **setup_kwargs) if __name__ == "__main__":
diff --git a/scripts/prepare_doc_publication.py b/scripts/prepare_doc_publication.py index a4bbad9..cc396dc 100755 --- a/scripts/prepare_doc_publication.py +++ b/scripts/prepare_doc_publication.py
@@ -59,12 +59,8 @@ 'getting_started_android_cmake.md': 'Android with CMake', 'generic_vulkan_env_setup.md': 'Generic Vulkan Setup', 'getting_started_python.md': 'Python', - 'cmake_options_and_variables.md': 'CMake Options and Variables', - 'op_coverage.md': 'XLA HLO Operation Coverage', - 'e2e_coverage.md': 'TensorFlow E2E Coverage', - 'roadmap.md': 'Short-term Focus Areas', - 'roadmap_design.md': 'Long-term Design Roadmap', - 'iree_community.md': 'Community', + 'milestones.md': 'Short-term Focus Areas', + 'design_roadmap.md': 'Long-term Design Roadmap', } # A dictionary containing source file to permanent link mappings. @@ -75,25 +71,6 @@ # allows one to override the permanent link if necessary. PERMALINK_DICT = { 'index.md': '/', - 'getting_started_linux_bazel.md': 'GetStarted/LinuxBazel', - 'getting_started_linux_cmake.md': 'GetStarted/LinuxCMake', - 'getting_started_linux_vulkan.md': 'GetStarted/LinuxVulkan', - 'getting_started_windows_bazel.md': 'GetStarted/WindowsBazel', - 'getting_started_windows_cmake.md': 'GetStarted/WindowsCMake', - 'getting_started_windows_vulkan.md': 'GetStarted/WindowsVulkan', - 'getting_started_macos_cmake.md': 'GetStarted/macOSCMake', - 'getting_started_macos_vulkan.md': 'GetStarted/macOSVulkan', - 'getting_started_android_cmake.md': 'GetStarted/AndroidCMake', - 'generic_vulkan_env_setup.md': 'GetStarted/GenericVulkanSetup', - 'getting_started_python.md': 'GetStarted/Python', - 'cmake_options_and_variables.md': 'GetStarted/CMakeOptionsVariables', - 'developer_overview.md': 'DeveloperOverview', - 'testing_guide.md': 'TestingGuide', - 'op_coverage.md': 'HLOOpCoverage', - 'e2e_coverage.md': 'TensorFlowE2ECoverage', - 'roadmap.md': 'FocusAreas', - 'roadmap_design.md': 'DesignRoadmap', - 'iree_community.md': 'Community', } # A dictionary containing source file to navigation order mappings. @@ -102,15 +79,18 @@ # the left panel of https://google.github.io/iree website. This allows one # to specify an order for a specific doc. NAVI_ORDER_DICT = { + # Top level entries 'index.md': 1, - # 'Getting Started' is 2. - 'developer_overview.md': 3, - 'roadmap_design.md': 4, - 'roadmap.md': 5, - 'op_coverage.md': 6, - 'e2e_coverage.md': 7, - 'testing_guide.md': 8, + # 'Using IREE' is 2. + # 'Getting Started' is 3. + # 'Developing IREE' is 4. + 'design_roadmap.md': 5, + 'milestones.md': 6, + 'xla_op_coverage.md': 7, + 'tf_e2e_coverage.md': 8, 'iree_community.md': 9, + # 'Design Docs' is 10. + # 'Dialect Definitions' is 11. # Within 'Getting Started' use explicit ordering. # Alphabetical would put 'bazel' before 'cmake' and 'python' between 'linux' @@ -127,6 +107,16 @@ 'getting_started_python.md': 10, 'generic_vulkan_env_setup.md': 11, 'cmake_options_and_variables.md': 12, + + # Within 'Developing IREE' use explicit ordering. + 'developer_overview.md': 1, + 'contributor_tips.md': 2, + 'testing_guide.md': 3, + 'benchmarking.md': 4, + 'repository_management.md': 5, + + # Within 'Using IREE' use explicit ordering. + 'using_colab.md': 1, } # A dictionary containing source directory to section tile mappings. @@ -137,14 +127,17 @@ # Note that the title here must match with index.md file's title under the # subdirectory. DIRECTORY_TITLE_DICT = { + 'design_docs': 'Design Docs', + 'developing_iree': 'Developing IREE', 'Dialects': 'Dialect Definitions', - 'GetStarted': 'Getting Started', + 'get_started': 'Getting Started', + 'using_iree': 'Using IREE', } # A dictionary containing the supporting JavaScript files for each doc. JS_FILES_DICT = { - 'op_coverage.md': ['js/add_classes.js'], - 'e2e_coverage.md': ['js/add_classes.js'], + 'xla_op_coverage.md': ['js/add_classes.js'], + 'tf_e2e_coverage.md': ['js/add_classes.js'], } @@ -164,19 +157,20 @@ # Use the default layout for everything. front_matter['layout'] = 'default' # Use the base filename as permanent link. - front_matter['permalink'] = base_name + # Replace '_' with '-'. Underscores are not typical in URLs... + front_matter['permalink'] = base_name.replace('_', '-') # Organize each doc to a section matching its directory structure. if relpath and relpath != '.': - front_matter['parent'] = relpath - front_matter['permalink'] = f'{relpath}/{front_matter["permalink"]}' + hyphen_relpath = relpath.replace('_', '-') + front_matter['permalink'] = f'{hyphen_relpath}/{front_matter["permalink"]}' # Find the title and TOC. lines = content.splitlines() title_line_index = None toc_index = None for (index, line) in enumerate(lines): - if line.startswith('# '): + if line.startswith('# ') and title_line_index is None: title_line_index = index if line == '[TOC]': toc_index = index
diff --git a/scripts/update_e2e_coverage.py b/scripts/update_e2e_coverage.py index ea691e4..e9cf397 100755 --- a/scripts/update_e2e_coverage.py +++ b/scripts/update_e2e_coverage.py
@@ -64,6 +64,7 @@ - vulkan-spirv The table shows the supported TensorFlow functions and models on each backend. +It is auto-generated from IREE's test status. """ @@ -172,7 +173,7 @@ content.append(generate_table(test_suite)) content = '\n\n'.join(content) + '\n' # Trailing newline. - table_path = os.path.join(args.build_dir, 'doc', 'e2e_coverage.md') + table_path = os.path.join(args.build_dir, 'doc', 'tf_e2e_coverage.md') with open(table_path, 'w', encoding='utf-8') as f: f.write(E2E_COVERAGE_DESCRIPTION) f.write(content)
diff --git a/scripts/update_op_coverage.py b/scripts/update_op_coverage.py index b01b687..c2c6dd9 100755 --- a/scripts/update_op_coverage.py +++ b/scripts/update_op_coverage.py
@@ -30,14 +30,15 @@ E2E_XLA_OPS_PATH = 'iree/test/e2e/xla_ops' # TODO(scotttodd): LLVM AOT (dylib-llvm-aot) HAL target(s) -OP_COVERAGE_DESCRIPTION = """# HLO Op Coverage +OP_COVERAGE_DESCRIPTION = """# XLA HLO Op Coverage There are three backend [targets](https://github.com/google/iree/tree/main/iree/compiler/Dialect/HAL/Target) in IREE: - vmla - llvm-ir - vulkan-spirv -The table shows the supported XLA HLO ops on each backend. +The table shows the supported XLA HLO ops on each backend. It is auto-generated +from IREE's test status. """ @@ -117,7 +118,7 @@ if __name__ == '__main__': args = parse_arguments() content = generate_table(args.build_dir) - table_path = os.path.join(args.build_dir, 'doc', 'op_coverage.md') + table_path = os.path.join(args.build_dir, 'doc', 'xla_op_coverage.md') with open(table_path, 'w', encoding='utf-8') as f: f.write(OP_COVERAGE_DESCRIPTION) f.write(content)
diff --git a/third_party/flatcc b/third_party/flatcc new file mode 160000 index 0000000..4fb0ff7 --- /dev/null +++ b/third_party/flatcc
@@ -0,0 +1 @@ +Subproject commit 4fb0ff7069bd88ee85902f4d0bb62794e5f6d021
diff --git a/third_party/llvm-project b/third_party/llvm-project index de0c6bd..99ad956 160000 --- a/third_party/llvm-project +++ b/third_party/llvm-project
@@ -1 +1 @@ -Subproject commit de0c6bd56b41081f1b89a1c7a0bf2597fd6d0104 +Subproject commit 99ad956fdaee5398fdcf46fa49cb433cf52dc461
diff --git a/third_party/tensorflow b/third_party/tensorflow index e36aca0..e4a48da 160000 --- a/third_party/tensorflow +++ b/third_party/tensorflow
@@ -1 +1 @@ -Subproject commit e36aca0132fbcde0bc820d56185e3078f97a879d +Subproject commit e4a48da690fac3443825b535ec02cb31c5625337