From 4fb3c458c836973d3d6d29b951c8a9721c89a12b Mon Sep 17 00:00:00 2001
From: Yifan Zhao <yifanz16@illinois.edu>
Date: Wed, 31 Mar 2021 21:40:39 -0500
Subject: [PATCH] Pass more flags from approxhpvm.py to clang++

---
 .../test/dnn_benchmarks/hpvm-c/CMakeLists.txt |   2 +-
 hpvm/tools/py-approxhpvm/main.py.in           | 111 +++++++++++++-----
 2 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt b/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt
index d429bca23c..c3fa67b760 100644
--- a/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt
+++ b/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt
@@ -14,7 +14,7 @@ function(compile_hpvm_c target_name src_filepath codegen_target)
     OUTPUT ${output_bin_path}
     DEPENDS ${generated_file_path} approxhpvm.py
     COMMAND ${APPROXHPVM_PY}
-      ${generated_file_path} ${output_bin_path}
+      ${generated_file_path} ${output_bin_path} -O3 -fno-exceptions
       -t ${codegen_target} -I ${CMAKE_CURRENT_SOURCE_DIR}/include ${ARGN}
   )
   add_custom_target(${target_name} DEPENDS ${output_bin_path})
diff --git a/hpvm/tools/py-approxhpvm/main.py.in b/hpvm/tools/py-approxhpvm/main.py.in
index a0d2da10c2..81fbd29b27 100644
--- a/hpvm/tools/py-approxhpvm/main.py.in
+++ b/hpvm/tools/py-approxhpvm/main.py.in
@@ -18,8 +18,6 @@ DIRECT_LINK_LIBS = "@DIRECT_LINK_LIBS@".split(";")
 AVAILABLE_PASSES = "@AVAILABLE_PASSES@".split(";")
 HPVM_RT_PATH = "@HPVM_RT_PATH@"
 
-COMPILE_FLAGS = ["fno-exceptions", "std=c++11", "O3"]
-
 
 def compile_hpvm_c(
     input_file: PathLike,
@@ -27,26 +25,32 @@ def compile_hpvm_c(
     tensor_target: Optional[str],
     opencl: bool,
     include: List[PathLike] = None,
+    macro: List[str] = None,
+    flags: List[str] = None,
+    optim_level: str = "0",  # -O0
+    std: str = "c++11",  # --std=c++11
+    link_dirs: List[PathLike] = None,
+    link_libs: List[str] = None,
     working_dir: PathLike = None,
     conf_file: PathLike = None,
 ):
     from subprocess import check_output
 
     passes = ["LLVMBuildDFG", "LLVMInPlaceDFGAnalysis"]
-    flags = ["buildDFG", "inplace"]
+    pass_flags = ["buildDFG", "inplace"]
     if tensor_target == "tensor":
         if conf_file is None:
             raise ValueError("conf_file must be defined when tensor_target=='tensor'.")
         passes += ["LLVMFuseHPVMTensorNodes", "LLVMDFG2LLVM_WrapperAPI"]
-        flags += ["hpvm-fuse", "dfg2llvm-wrapperapi", f"configuration-inputs-filename={conf_file}"]
+        pass_flags += ["hpvm-fuse", "dfg2llvm-wrapperapi", f"configuration-inputs-filename={conf_file}"]
     elif tensor_target == "cudnn":
         passes += ["LLVMDFG2LLVM_CUDNN"]
-        flags += ["dfg2llvm-cudnn"]
+        pass_flags += ["dfg2llvm-cudnn"]
     if opencl:
         passes += ["LLVMDFG2LLVM_OpenCL"]
-        flags += ["dfg2llvm-opencl"]
+        pass_flags += ["dfg2llvm-opencl"]
     passes += ["LLVMDFG2LLVM_CPU", "LLVMClearDFG", "LLVMGenHPVM"]
-    flags += ["dfg2llvm-cpu", "clearDFG"]
+    pass_flags += ["dfg2llvm-cpu", "clearDFG"]
 
     working_dir = Path(working_dir or ".")
     if not working_dir.is_dir():
@@ -58,11 +62,11 @@ def compile_hpvm_c(
     llvm_ll_file = working_dir / f"{name_stem}.llvm.ll"
     hpvm_rt_linked_file = working_dir / f"{name_stem}.linked.bc"
     commands = [
-        hpvm_c_to_ll(input_file, ll_file, extra_includes=include),
+        hpvm_c_to_ll(input_file, ll_file, include, macro, flags, optim_level, std),
         opt_codegen_hpvm(ll_file, hpvm_ll_file),
-        _run_opt(hpvm_ll_file, llvm_ll_file, passes, flags),
+        _run_opt(hpvm_ll_file, llvm_ll_file, passes, pass_flags),
         link_hpvm_rt(llvm_ll_file, hpvm_rt_linked_file),
-        link_binary(hpvm_rt_linked_file, output_file),
+        link_binary(hpvm_rt_linked_file, output_file, link_dirs, link_libs),
     ]
     for command in commands:
         print(" ".join(command))
@@ -72,14 +76,19 @@ def compile_hpvm_c(
 def hpvm_c_to_ll(
     src_file: PathLike,
     target_file: PathLike,
-    extra_includes: Optional[List[PathLike]] = None,
+    extra_includes: List[PathLike] = None,
+    macros: List[str] = None,
     flags: List[str] = None,
+    optim_level: str = "0",  # -O0
+    std: str = "c++11",  # --std=c++11
 ) -> List[str]:
-    extra_includes = extra_includes or []
-    includes = [f"-I{path}" for path in TRT_INCLUDE_DIRS + extra_includes]
-    flags = [f"-{flg}" for flg in (flags or []) + COMPILE_FLAGS]
+    includes = (extra_includes or []) + TRT_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 [])]
     return [
-        str(LLVM_BUILD_BIN / "clang++"), *includes, *flags, "-emit-llvm", "-S",
+        str(LLVM_BUILD_BIN / "clang++"), *includes_s, *flags,
+        f"-O{optim_level}", f"-std={std}", "-emit-llvm", "-S",
         str(src_file), "-o", str(target_file)
     ]
 
@@ -92,29 +101,39 @@ def link_hpvm_rt(src_file: PathLike, target_file: PathLike) -> List[str]:
     return [str(LLVM_BUILD_BIN / "llvm-link"), str(src_file), HPVM_RT_PATH, "-o", str(target_file)]
 
 
-def link_binary(src_file: PathLike, target_file: PathLike) -> List[str]:
+def link_binary(
+    src_file: PathLike,
+    target_file: PathLike,
+    extra_link_dirs: List[PathLike] = None,
+    extra_link_libs: List[str] = None
+) -> List[str]:
+    link_dirs, link_libs = _link_args(extra_link_dirs or [], extra_link_libs or [])
+    linker_dir_flags = []
+    for path in link_dirs:
+        linker_dir_flags.extend([f"-L{path}", f"-Wl,-rpath={path}"])
+    linker_lib_flags = [f"-l{lib}" for lib in link_libs]
+    return [
+        str(LLVM_BUILD_BIN / "clang++"), str(src_file),
+        "-o", str(target_file), *linker_dir_flags, *linker_lib_flags
+    ]
+
+
+def _link_args(extra_link_dirs: List[PathLike], extra_link_libs: List[str]):
     def drop_suffix(libname: str):
         import re
 
         match = re.match(r"lib(.*)\.so", libname)
         return libname if match is None else match.group(1)
 
-    link_dirs, link_libnames = [], []
+    link_dirs, link_libs = extra_link_dirs.copy(), extra_link_libs.copy()
     for lib in DIRECT_LINK_LIBS:
         lib = Path(lib)
         link_dirs.append(lib.parent)
-        link_libnames.append(drop_suffix(lib.name))
+        link_libs.append(lib.name)
     link_dirs += TRT_LINK_DIRS
-    link_libnames += TRT_LINK_LIBS
-
-    linker_dir_flags = []
-    for path in link_dirs:
-        linker_dir_flags.extend([f"-L{path}", f"-Wl,-rpath={path}"])
-    linker_lib_flags = [f"-l{drop_suffix(lib)}" for lib in link_libnames]
-    return [
-        str(LLVM_BUILD_BIN / "clang++"), str(src_file),
-        "-o", str(target_file), *linker_dir_flags, *linker_lib_flags
-    ]
+    link_libs += TRT_LINK_LIBS
+    link_libnames = [drop_suffix(s) for s in link_libs]
+    return link_dirs, link_libnames
 
 
 def _run_opt(
@@ -157,9 +176,35 @@ def parse_args():
     parser.add_argument(
         "-d", "--working-dir", type=Path, help="Directory to generate temp files in"
     )
+
+    # Relaying arguments for clang++ (source -> bitcode stage)
     parser.add_argument(
         "-I", "--include", type=Path, action="append",
-        help="Additional include directories to use"
+        help="[clang emit-llvm] Add directory to include search path"
+    )
+    parser.add_argument(
+        "-D", type=str, action="append",
+        help="[clang emit-llvm] Define macro"
+    )
+    parser.add_argument(
+        "-f", type=str, action="append",
+        help="[clang emit-llvm] clang++ flags (such as -ffastmath)"
+    )
+    parser.add_argument(
+        "-O", type=str, default="0",
+        help="[clang emit-llvm] Optimization level"
+    )
+    parser.add_argument(
+        "--std", type=str, default="c++11",
+        help="[clang emit-llvm] Language standard to compile for. Double dashes (--std, not -std)."
+    )
+
+    # Relaying arguments for clang++ (linking stage)
+    parser.add_argument(
+        "-L", type=Path, action="append", help="[clang linker] Add directory to library search path"
+    )
+    parser.add_argument(
+        "-l", type=str, action="append", help="[clang linker] Link library (such as -lpthread)"
     )
 
     args = parser.parse_args()
@@ -170,4 +215,10 @@ def parse_args():
 
 
 if __name__ == "__main__":
-    compile_hpvm_c(**vars(parse_args()))
+    args = vars(parse_args())
+    args["macro"] = args.pop("D")
+    args["flags"] = args.pop("f")
+    args["optim_level"] = args.pop("O")
+    args["link_dirs"] = args.pop("L")
+    args["link_libs"] = args.pop("l")
+    compile_hpvm_c(**args)
-- 
GitLab