From f86011c91f4a942bdce40cf068d163d827c31584 Mon Sep 17 00:00:00 2001
From: Yifan Zhao <yifanz16@illinois.edu>
Date: Thu, 1 Apr 2021 02:38:29 -0500
Subject: [PATCH] OpenCL pass compiles PTX on spot

---
 .../Transforms/DFG2LLVM_OpenCL/CMakeLists.txt |  1 +
 .../DFG2LLVM_OpenCL/DFG2LLVM_OpenCL.cpp       | 34 +++++++++++++------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/hpvm/lib/Transforms/DFG2LLVM_OpenCL/CMakeLists.txt b/hpvm/lib/Transforms/DFG2LLVM_OpenCL/CMakeLists.txt
index 4041df11ce..1e34f44f40 100644
--- a/hpvm/lib/Transforms/DFG2LLVM_OpenCL/CMakeLists.txt
+++ b/hpvm/lib/Transforms/DFG2LLVM_OpenCL/CMakeLists.txt
@@ -10,6 +10,7 @@ add_llvm_library( LLVMDFG2LLVM_OpenCL
 
   DEPENDS
   intrinsics_gen
+  llvm-cbe  # Called within the pass
   PLUGIN_TOOL
   opt
   )
diff --git a/hpvm/lib/Transforms/DFG2LLVM_OpenCL/DFG2LLVM_OpenCL.cpp b/hpvm/lib/Transforms/DFG2LLVM_OpenCL/DFG2LLVM_OpenCL.cpp
index 5a58f272b3..286bcdebd2 100644
--- a/hpvm/lib/Transforms/DFG2LLVM_OpenCL/DFG2LLVM_OpenCL.cpp
+++ b/hpvm/lib/Transforms/DFG2LLVM_OpenCL/DFG2LLVM_OpenCL.cpp
@@ -47,6 +47,8 @@
 #include "llvm/Support/ToolOutputFile.h"
 
 #include <sstream>
+#include <unistd.h>  // ".", nullptr() (POSIX-only)
+#include <cstdlib>  // std::system
 
 #ifndef LLVM_BUILD_DIR
 #error LLVM_BUILD_DIR is not defined
@@ -147,7 +149,7 @@ static void getExecuteNodeParams(Module &M, Value *&, Value *&, Value *&,
 static Value *genWorkGroupPtr(Module &M, std::vector<Value *>,
                               ValueToValueMapTy &, Instruction *,
                               const Twine &WGName = "WGSize");
-static std::string getPTXFilename(const Module &);
+static std::string getPTXFilePath(const Module &);
 static void changeDataLayout(Module &);
 static void changeTargetTriple(Module &);
 static void findReturnInst(Function *, std::vector<ReturnInst *> &);
@@ -258,7 +260,7 @@ public:
     DEBUG(errs() << *KernelM);
   }
 
-  void writeKernelsModule();
+  void writeKModCompilePTX();
 };
 
 // Initialize the HPVM runtime API. This makes it easier to insert these calls
@@ -846,7 +848,7 @@ void CGT_OpenCL::codeGen(DFInternalNode *N) {
     // Now the remaining nodes to be visited should be ignored
     KernelLaunchNode = NULL;
     DEBUG(errs() << "Insert Runtime calls\n");
-    insertRuntimeCalls(N, kernel, getPTXFilename(M));
+    insertRuntimeCalls(N, kernel, getPTXFilePath(M));
 
   } else {
     DEBUG(errs() << "Found intermediate node. Getting size parameters.\n");
@@ -1901,7 +1903,7 @@ bool DFG2LLVM_OpenCL::runOnModule(Module &M) {
     CGTVisitor->visit(rootNode);
   }
 
-  CGTVisitor->writeKernelsModule();
+  CGTVisitor->writeKModCompilePTX();
 
   // TODO: Edit module epilogue to remove the HPVM intrinsic declarations
   delete CGTVisitor;
@@ -2010,16 +2012,18 @@ void CGT_OpenCL::addCLMetadata(Function *F) {
   MDN_annotations->addOperand(MDNvvmAnnotationsNode);
 }
 
-void CGT_OpenCL::writeKernelsModule() {
+void CGT_OpenCL::writeKModCompilePTX() {
 
   // In addition to deleting all other functions, we also want to spiff it
   // up a little bit.  Do this now.
   legacy::PassManager Passes;
+  auto kmodName = getKernelsModuleName(M);
+  auto ptxPath = getPTXFilePath(M);
 
   DEBUG(errs() << "Writing to File --- ");
-  DEBUG(errs() << getKernelsModuleName(M).c_str() << "\n");
+  DEBUG(errs() << kmodName << "\n");
   std::error_code EC;
-  ToolOutputFile Out(getKernelsModuleName(M).c_str(), EC, sys::fs::F_None);
+  ToolOutputFile Out(kmodName.c_str(), EC, sys::fs::F_None);
   if (EC) {
     DEBUG(errs() << EC.message() << '\n');
   }
@@ -2030,6 +2034,13 @@ void CGT_OpenCL::writeKernelsModule() {
 
   // Declare success.
   Out.keep();
+
+  // Starts calling llvm-cbe.
+  auto llvmCBE = std::string(LLVM_BUILD_DIR_STR) + "/bin/llvm-cbe";
+  std::string command = llvmCBE + " " + kmodName + " -o " + ptxPath;
+  DEBUG(errs() << "Compiling PTX from kernel module:\n");
+  DEBUG(errs() << command);
+  std::system(command.c_str());
 }
 
 Function *CGT_OpenCL::transformFunctionToVoid(Function *F) {
@@ -2346,10 +2357,13 @@ static Value *genWorkGroupPtr(Module &M, std::vector<Value *> WGSize,
 }
 
 // Get generated PTX binary name
-static std::string getPTXFilename(const Module &M) {
+static std::string getPTXFilePath(const Module &M) {
   std::string moduleID = M.getModuleIdentifier();
-  moduleID.append(".kernels.cl");
-  return moduleID;
+  char *cwd_p = get_current_dir_name();
+  std::string cwd(cwd_p);
+  free(cwd_p);
+  std::string ptxPath = cwd + "/" + moduleID + ".kernels.cl";
+  return ptxPath;
 }
 
 // Changes the data layout of the Module to be compiled with OpenCL backend
-- 
GitLab