diff --git a/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt b/hpvm/test/dnn_benchmarks/hpvm-c/CMakeLists.txt index d429bca23cd56cafc70a84fe79a35fed38912bec..c3fa67b760a3a69e81b08f302454a1c358cc25b8 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 a0d2da10c2cf8e879dabd5b931e61c934436374c..81fbd29b27a5d403c7683b2c521990847eaf4c59 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)