You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by tq...@apache.org on 2020/03/16 19:52:55 UTC

[incubator-tvm] branch master updated: Return empty CSourceModule when no lowered_funcs exists in Relay mod (#4847)

This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tvm.git


The following commit(s) were added to refs/heads/master by this push:
     new 11ee1a0  Return empty CSourceModule when no lowered_funcs exists in Relay mod (#4847)
11ee1a0 is described below

commit 11ee1a0e4fc684cc8fbbeba4b8a0682b0e4c6193
Author: Ruizhe Zhao <ku...@users.noreply.github.com>
AuthorDate: Mon Mar 16 19:52:45 2020 +0000

    Return empty CSourceModule when no lowered_funcs exists in Relay mod (#4847)
    
    * Use dummy func when no lowered_funcs exists in Relay mod
    
    * Dummy func -> CSourceModule with empty code str
    
    * Added comments describing the empty CSouceModule
    
    * Always import external modules w/o assertions
    
    * Use CSourceModule as a fallback for LLVMModule
    
    * Changed cond for target == llvm
    
    * Create an empty LLVM module w/o using dummy func
    
    * Avoid using IR str concat to create LLVM module
    
    * Improved comments for codegen.LLVMModuleCreate
    
    * Satisfy the linter for LLVMModuleCreate
---
 src/relay/backend/build_module.cc | 47 ++++++++++++++++++++++++++++++---------
 src/target/llvm/llvm_module.cc    | 22 ++++++++++++++++++
 2 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/src/relay/backend/build_module.cc b/src/relay/backend/build_module.cc
index 41833c4..d42cc27 100644
--- a/src/relay/backend/build_module.cc
+++ b/src/relay/backend/build_module.cc
@@ -28,8 +28,10 @@
 #include <tvm/relay/expr.h>
 #include <tvm/relay/transform.h>
 #include <tvm/relay/qnn/transform.h>
+#include <tvm/tir/ir_pass.h>
 #include <memory>
 
+#include "../../target/source/codegen_source_base.h"
 #include "utils.h"
 
 namespace tvm {
@@ -451,28 +453,51 @@ class RelayBuildModule : public runtime::ModuleNode {
     ret_.params = graph_codegen_->GetParams();
 
     auto lowered_funcs = graph_codegen_->GetLoweredFunc();
+
+    // When there is no lowered_funcs due to reasons such as optimization.
     if (lowered_funcs.size() == 0) {
-      LOG(WARNING) << "no lowered funcs exist in the compiled module";
+      Target target_host = GetTargetHost();
+
+      // If no target_host has been set, we choose a default one, which is
+      // llvm if "codegen.LLVMModuleCreate" is accessible.
+      const runtime::PackedFunc* pf = runtime::Registry::Get("codegen.LLVMModuleCreate");
+      if (!target_host.defined())
+        target_host = (pf != nullptr) ? target::llvm() : target::stackvm();
+
+      if (target_host.defined() && target_host->target_name == "llvm") {
+        // If we can decide the target is LLVM, we then create an empty LLVM module.
+        ret_.mod = (*pf)(target_host->str(), "empty_module");
+      } else {
+        // If we cannot decide the target is LLVM, we create an empty CSourceModule.
+        // The code content is initialized with ";" to prevent complaining
+        // from CSourceModuleNode::SaveToFile.
+        ret_.mod = tvm::codegen::CSourceModuleCreate(";", "");
+      }
     } else {
       ret_.mod = tvm::build(
         lowered_funcs,
         target_host_,
         BuildConfig::Current());
     }
+
     Array<tvm::runtime::Module> ext_mods = graph_codegen_->GetExternalModules();
-    if (!ext_mods.empty()) {
-      CHECK(lowered_funcs.size() > 0 || ext_mods.size() == 1)
-          << "Expect to have a TVM DSOModule when multiple external runtime modules exist";
-      if (lowered_funcs.size() == 0) {
-        // Execute the whole module using external runtime.
-        ret_.mod = ext_mods[0];
-      } else {
-        // Import all external runtime modules.
-        for (const auto& it : ext_mods) {
-          ret_.mod.Import(it);
+    // Import all external runtime modules.
+    for (const auto& it : ext_mods)
+      ret_.mod.Import(it);
+  }
+
+ private:
+  Target GetTargetHost() {
+    Target target_host = target_host_;
+    if (!target_host_.defined()) {
+      for (const auto &it : targets_) {
+        if (it.second->device_type == kDLCPU) {
+          target_host = it.second;
+          break;
         }
       }
     }
+    return target_host;
   }
 
  protected:
diff --git a/src/target/llvm/llvm_module.cc b/src/target/llvm/llvm_module.cc
index 7f46809..c04b257 100644
--- a/src/target/llvm/llvm_module.cc
+++ b/src/target/llvm/llvm_module.cc
@@ -356,6 +356,28 @@ TVM_REGISTER_GLOBAL("codegen.build_llvm")
     *rv = runtime::Module(n);
   });
 
+TVM_REGISTER_GLOBAL("codegen.LLVMModuleCreate")
+.set_body([](TVMArgs args, TVMRetValue *rv) {
+  auto n = make_object<LLVMModuleNode>();
+  auto target = args[0].operator std::string();
+  auto module_name = args[1].operator std::string();
+
+  // Generate a LLVM module from an input target string
+  InitializeLLVM();
+  auto tm = GetLLVMTargetMachine(target);
+  auto ctx = std::make_shared<llvm::LLVMContext>();
+  std::unique_ptr<llvm::Module> module(new llvm::Module(module_name, *ctx));
+
+  // Use a default data layout and target triple
+  auto triple = tm->getTargetTriple();
+  module->setTargetTriple(triple.str());
+  module->setDataLayout(tm->createDataLayout());
+
+  n->Init(std::move(module), ctx);
+
+  *rv = runtime::Module(n);
+});
+
 TVM_REGISTER_GLOBAL("target.llvm_lookup_intrinsic_id")
 .set_body([](TVMArgs args, TVMRetValue* rv) {
     *rv = static_cast<int64_t>(LookupLLVMIntrinsic(args[0]));