From 17c8d30d00af723ea242f833382c42919d751f59 Mon Sep 17 00:00:00 2001
From: Yifan Zhao <yifanz16@illinois.edu>
Date: Tue, 6 Apr 2021 03:57:55 -0500
Subject: [PATCH] CUDA is now optional; not having CUDA will disable all
 ApproxHPVM stuff

---
 hpvm/CMakeLists.txt                         | 30 ++++++++++-----
 hpvm/projects/CMakeLists.txt                | 16 ++++----
 hpvm/projects/hpvm-tensor-rt/CMakeLists.txt |  1 +
 hpvm/test/CMakeLists.txt                    | 12 +++---
 hpvm/tools/hpvm-clang/CMakeLists.txt        | 41 +++++++++++++++------
 hpvm/tools/hpvm-clang/main.py.in            | 18 ++++++---
 6 files changed, 78 insertions(+), 40 deletions(-)

diff --git a/hpvm/CMakeLists.txt b/hpvm/CMakeLists.txt
index 71e6de5999..abb85759a3 100644
--- a/hpvm/CMakeLists.txt
+++ b/hpvm/CMakeLists.txt
@@ -1,13 +1,25 @@
 cmake_minimum_required(VERSION 3.18)
-project(hpvm CUDA CXX)
-get_filename_component(
-  CUDA_TOOLKIT_ROOT_DIR "${CMAKE_CUDA_COMPILER}/../.." ABSOLUTE
-)  # Set CUDA_TOOLKIT_ROOT_DIR by our own, to the parent folder of cuda nvcc
-message(STATUS "CUDA Architecture: ${CMAKE_CUDA_ARCHITECTURES}")
-
-# find_package will use the auxillary cmake/Find*.cmake we provide
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-find_package(CUDNN 7 EXACT REQUIRED)  # CUDNN_INCLUDE_PATH, CUDNN_LIBRARY_DIR and CUDNN::cudnn
+project(hpvm CXX)
+
+include(CheckLanguage)
+check_language(CUDA)
+if(CMAKE_CUDA_COMPILER)
+  # Enable CUDA
+  set(HPVM_USE_CUDA 1)
+  enable_language(CUDA)
+  get_filename_component(
+    CUDA_TOOLKIT_ROOT_DIR "${CMAKE_CUDA_COMPILER}/../.." ABSOLUTE
+  )  # Set CUDA_TOOLKIT_ROOT_DIR by our own, to the parent folder of cuda nvcc
+  message(STATUS "CUDA Architecture: ${CMAKE_CUDA_ARCHITECTURES}")
+
+  # find_package will use the auxillary cmake/Find*.cmake we provide
+  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+  find_package(CUDNN 7 EXACT REQUIRED)  # CUDNN_INCLUDE_PATH, CUDNN_LIBRARY_DIR and CUDNN::cudnn
+else()
+  set(HPVM_USE_CUDA 0)
+  message(WARNING "CUDA is not found in this system; all ApproxHPVM features will be unavailable.")
+endif()
+
 find_package(OpenCL)  # Defines ${OpenCL_INCLUDE_DIRS} and ${OpenCL_LIBRARY}
 if(${OpenCL_FOUND})
   set(HPVM_USE_OPENCL 1)
diff --git a/hpvm/projects/CMakeLists.txt b/hpvm/projects/CMakeLists.txt
index 2a51c0b09e..4eaf1094e4 100644
--- a/hpvm/projects/CMakeLists.txt
+++ b/hpvm/projects/CMakeLists.txt
@@ -1,17 +1,15 @@
+# Add all entries automatically except hpvm-tensor-rt
 file(GLOB entries *)
 foreach(entry ${entries})
   if(IS_DIRECTORY ${entry} AND EXISTS ${entry}/CMakeLists.txt)
-    if((NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/compiler-rt) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/dragonegg) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/libcxx) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/libcxxabi) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/libunwind) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/test-suite) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/parallel-libs) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/openmp) AND
-       (NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/debuginfo-tests))
+    if(NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/hpvm-tensor-rt)
       get_filename_component(entry_name "${entry}" NAME)
       add_llvm_external_project(${entry_name})
     endif()
   endif()
 endforeach(entry)
+
+# Add hpvm-tensor-rt only if CUDA is found (HPVM_USE_CUDA is set to 1)
+if(HPVM_USE_CUDA)
+  add_llvm_external_project(hpvm-tensor-rt)
+endif()
diff --git a/hpvm/projects/hpvm-tensor-rt/CMakeLists.txt b/hpvm/projects/hpvm-tensor-rt/CMakeLists.txt
index c448ce9c37..3f88dad2d0 100644
--- a/hpvm/projects/hpvm-tensor-rt/CMakeLists.txt
+++ b/hpvm/projects/hpvm-tensor-rt/CMakeLists.txt
@@ -40,6 +40,7 @@ target_include_directories(soc_simulator PUBLIC soc_simulator/)
 find_package(OpenMP REQUIRED)  # Provides ${OpenMP_CXX_FLAGS} and OpenMP::OpenMP_CXX
 # This will use the CUDA found by CUDA language support in the root CMake,
 # but it exports the CUDA::* targets (used below) so we can freely add libraries to link to.
+# (If CUDA is unavailable then the higher-level CMakes will know to not compile this library at all.)
 find_package(CUDAToolkit REQUIRED)
 set(
   LINK_LIBS
diff --git a/hpvm/test/CMakeLists.txt b/hpvm/test/CMakeLists.txt
index 8b4185294f..e59e0959a3 100644
--- a/hpvm/test/CMakeLists.txt
+++ b/hpvm/test/CMakeLists.txt
@@ -6,9 +6,11 @@ set(CLANG_C ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/clang)
 set(CLANG_CXX ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/clang++)
 
 add_subdirectory(hpvm_pass)  # Passes test suite
-add_subdirectory(hpvm-tensor-rt)  # Unit tests of tensor_runtime
 add_subdirectory(benchmarks)  # HPVM benchmarks (no DNN)
-add_subdirectory(dnn_benchmarks/hpvm-c)  # HPVM-C DNN accuracy test suite
-add_subdirectory(dnn_benchmarks/keras)  # Keras frontend test suite
-add_subdirectory(dnn_benchmarks/pytorch)  # Torch frontend test suites (3 of them)
-add_subdirectory(dnn_benchmarks/tensor-rt-src)  # tensor_runtime DNN (build only, no tests)
+if(HPVM_USE_CUDA)  # Compile these only if CUDA exists.
+  add_subdirectory(hpvm-tensor-rt)  # Unit tests of tensor_runtime
+  add_subdirectory(dnn_benchmarks/hpvm-c)  # HPVM-C DNN accuracy test suite
+  add_subdirectory(dnn_benchmarks/keras)  # Keras frontend test suite
+  add_subdirectory(dnn_benchmarks/pytorch)  # Torch frontend test suites (3 of them)
+  add_subdirectory(dnn_benchmarks/tensor-rt-src)  # tensor_runtime DNN (build only, no tests)
+endif()
diff --git a/hpvm/tools/hpvm-clang/CMakeLists.txt b/hpvm/tools/hpvm-clang/CMakeLists.txt
index 3564b00d0a..fdd4de2557 100644
--- a/hpvm/tools/hpvm-clang/CMakeLists.txt
+++ b/hpvm/tools/hpvm-clang/CMakeLists.txt
@@ -7,18 +7,32 @@
 # ---[ Define variables for main.py.in
 # main.py.in requires the following variables:
 # LLVM_PROJECT_DIR, LLVM_BUILD_DIR
-# TRT_PATH, TRT_INCLUDE_DIRS, TRT_LINK_DIRS, TRT_LINK_LIBS
-# DIRECT_LINK_LIBS, HPVM_USE_OPENCL (defined globally)
+# INCLUDE_DIRS, LINK_DIRS, LINK_LIBS
+# DIRECT_LINK_LIBS, HPVM_USE_OPENCL (defined globally), HPVM_HAS_TRT
 # AVAILABLE_PASSES, HPVM_RT_PATH
 
 set(LLVM_PROJECT_DIR ${CMAKE_SOURCE_DIR})
 set(LLVM_BUILD_DIR ${CMAKE_BINARY_DIR})
+# CMake-dependency of hpvmpy:
+set(DEPS hpvm-rt-bc clang opt llvm-link)
 
-get_target_property(TRT_INCLUDE_DIRS tensor_runtime INCLUDE_DIRECTORIES)
-get_target_property(TRT_LINK_DIRS tensor_runtime TRT_LINK_DIRS)
-get_target_property(TRT_LINK_LIBS tensor_runtime TRT_LINK_LIBS)
+# Don't do the following if tensor_runtime won't be compiled
+# (which is due to CUDA not found).
+if(TARGET tensor_runtime)
+  set(HPVM_HAS_TRT 1)  # Has tensor runtime
 
-set(DIRECT_LINK_LIBS "$<TARGET_FILE:tensor_runtime>")
+  get_target_property(TRT_INCLUDE_DIRS tensor_runtime INCLUDE_DIRECTORIES)
+  get_target_property(TRT_LINK_DIRS tensor_runtime TRT_LINK_DIRS)
+  get_target_property(TRT_LINK_LIBS tensor_runtime TRT_LINK_LIBS)
+
+  list(APPEND INCLUDE_DIRS ${TRT_INCLUDE_DIRS})
+  list(APPEND LINK_DIRS ${TRT_LINK_DIRS})
+  list(APPEND LINK_LIBS ${TRT_LINK_LIBS})
+  list(APPEND DIRECT_LINK_LIBS "$<TARGET_FILE:tensor_runtime>")
+  list(APPEND DEPS tensor_runtime)
+else()
+  set(HPVM_HAS_TRT 0)  # Doesn't have tensor runtime
+endif()
 if(${HPVM_USE_OPENCL})
   # We need to link to OpenCL libs when hpvm uses opencl
   # because OpenCL functions may be injected by the OpenCL pass.
@@ -39,14 +53,20 @@ set(
     LLVMBuildDFG
     LLVMClearDFG
     LLVMDFG2LLVM_CPU
-    LLVMDFG2LLVM_CUDNN
     LLVMDFG2LLVM_OpenCL
-    LLVMDFG2LLVM_WrapperAPI
-    LLVMFuseHPVMTensorNodes
     LLVMGenHPVM
-    LLVMInPlaceDFGAnalysis
     LLVMLocalMem
 )
+if(TARGET tensor_runtime)
+  list(
+    APPEND AVAILABLE_PASSES
+    LLVMFuseHPVMTensorNodes
+    LLVMInPlaceDFGAnalysis
+    LLVMDFG2LLVM_CUDNN
+    LLVMDFG2LLVM_WrapperAPI
+  )
+endif()
+list(APPEND DEPS ${AVAILABLE_PASSES})
 
 # ---[ Create package folder structure
 # This sounds crazy but since main.py.in is generated into another file under build/ dir,
@@ -69,7 +89,6 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/main.py INPUT ${CMAKE_CURRENT_B
 # Delibrately create an extra step of moving file
 # which is carried out at build time (as a target)
 # so we can set these dependencies on it.
-set(DEPS tensor_runtime hpvm-rt-bc clang opt llvm-link ${AVAILABLE_PASSES})
 add_custom_command(
     OUTPUT ${init_path}
     COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/main.py ${init_path}
diff --git a/hpvm/tools/hpvm-clang/main.py.in b/hpvm/tools/hpvm-clang/main.py.in
index f20bae4df9..0f240ad04f 100644
--- a/hpvm/tools/hpvm-clang/main.py.in
+++ b/hpvm/tools/hpvm-clang/main.py.in
@@ -10,11 +10,12 @@ HPVM_PROJECT_DIR = Path("@LLVM_PROJECT_DIR@") / "tools/hpvm"
 LLVM_BUILD_BIN = Path("@LLVM_BUILD_DIR@") / "bin"
 
 # Directories to include
-TRT_INCLUDE_DIRS = "@TRT_INCLUDE_DIRS@".split(";")
-TRT_LINK_DIRS = [Path(s) for s in "@TRT_LINK_DIRS@".split(";")]
-TRT_LINK_LIBS = "@TRT_LINK_LIBS@".split(";")
+INCLUDE_DIRS = "@INCLUDE_DIRS@".split(";")
+LINK_DIRS = [Path(s) for s in "@LINK_DIRS@".split(";")]
+LINK_LIBS = "@LINK_LIBS@".split(";")
 DIRECT_LINK_LIBS = "@DIRECT_LINK_LIBS@".split(";")
 HPVM_USE_OPENCL = int("@HPVM_USE_OPENCL@")
+HPVM_HAS_TRT = int("@HPVM_HAS_TRT@")
 
 AVAILABLE_PASSES = "@AVAILABLE_PASSES@".split(";")
 HPVM_RT_PATH = "@HPVM_RT_PATH@"
@@ -103,7 +104,7 @@ def hpvm_c_to_ll(
     is_cpp: bool = True,  # otherwise is C
     std: str = None,  # --std=c++11
 ) -> List[str]:
-    includes = (extra_includes or []) + TRT_INCLUDE_DIRS
+    includes = (extra_includes or []) + INCLUDE_DIRS
     includes_s = [f"-I{path}" for path in includes]
     macros = [f"-D{macro}" for macro in (macros or [])]
     flags = [f"-f{flg}" for flg in (flags or [])]
@@ -155,8 +156,8 @@ def _link_args(extra_link_dirs: List[PathLike], extra_link_libs: List[str]):
         lib = Path(lib)
         link_dirs.append(lib.parent)
         link_libs.append(lib.name)
-    link_dirs += TRT_LINK_DIRS
-    link_libs += TRT_LINK_LIBS
+    link_dirs += LINK_DIRS
+    link_libs += LINK_LIBS
     link_libnames = [drop_suffix(s) for s in link_libs]
     return link_dirs, link_libnames
 
@@ -266,6 +267,11 @@ See option -b for that."""
         parser.error(f"Language mode {args.x} not supported yet -- only c or c++")
     if not HPVM_USE_OPENCL and args.opencl:
         parser.error(f"OpenCL is disabled for this build of HPVM.")
+    if not HPVM_HAS_TRT and args.tensor_target:
+        parser.error(
+            "Tensor domain support is disabled for this build of HPVM; "
+            "please check your CMake warnings during compilation."
+        )
     return args
 
 
-- 
GitLab