From ab576ce4c52a50274635fbb6fc00e89efd71a3c0 Mon Sep 17 00:00:00 2001
From: Dan Plyukhin <daniilp2@illinois.edu>
Date: Sun, 9 May 2021 13:11:13 -0500
Subject: [PATCH] Added a hack to delete all unreachable DFNodes

---
 .../DFG2LLVM_Remote/DFG2LLVM_Remote.cpp       | 131 ++++++++++++++++++
 hpvm/test/dhpvm/simple/build.sh               |  78 +++++------
 2 files changed, 170 insertions(+), 39 deletions(-)

diff --git a/hpvm/lib/Transforms/DFG2LLVM_Remote/DFG2LLVM_Remote.cpp b/hpvm/lib/Transforms/DFG2LLVM_Remote/DFG2LLVM_Remote.cpp
index 0301a2a57c..e8e2d8112f 100644
--- a/hpvm/lib/Transforms/DFG2LLVM_Remote/DFG2LLVM_Remote.cpp
+++ b/hpvm/lib/Transforms/DFG2LLVM_Remote/DFG2LLVM_Remote.cpp
@@ -500,6 +500,113 @@ namespace {
 
   };
 
+
+  /**
+   * Objects from this class traverse the DFG and partitions nodes into three
+   * categories:
+   * 1) Offload nodes: Nodes that have the Remote target
+   * 2) Worker nodes: Nodes that are descended from a node with the Remote target
+   * 3) Client nodes: All other nodes
+   */
+  class RemoteNodeDetector : public DFNodeVisitor {
+  private:
+  public:
+    std::set<StringRef> offloadNodes;
+    std::set<StringRef> workerNodes;
+    std::set<StringRef> clientNodes;
+    virtual ~RemoteNodeDetector() {}
+
+    void visitWorkerNode(DFInternalNode *N) {
+      if (N->isDummyNode())
+        return;
+      Function *F = N->getFuncPointer();
+      workerNodes.insert(F->getName());
+      DEBUG(errs() << "Found worker node" << F->getName() << "\n");
+
+      for (DFGraph::children_iterator i = N->getChildGraph()->begin(),
+             e = N->getChildGraph()->end();
+           i != e; ++i) {
+        DFNode *child = *i;
+        if (auto *internal = dyn_cast<DFInternalNode>(child)) {
+          visitWorkerNode(internal);
+        }
+        else if (auto *leaf = dyn_cast<DFLeafNode>(child)) {
+          visitWorkerNode(leaf);
+        }
+        else {
+          assert(false && "Unexpected DFNode: Neither a leaf, nor an internal node");
+        }
+      }
+    }
+
+    void visitWorkerNode(DFLeafNode *N) {
+      if (N->isDummyNode())
+        return;
+      Function *F = N->getFuncPointer();
+      workerNodes.insert(F->getName());
+      DEBUG(errs() << "Found worker node" << F->getName() << "\n");
+    }
+
+    virtual void visit(DFInternalNode *N) {
+      if (N->isDummyNode())
+        return;
+      Function *F = N->getFuncPointer();
+      if (hpvmUtils::getPreferredTarget(F) == hpvm::REMOTE_TARGET) {
+        offloadNodes.insert(F->getName());
+        DEBUG(errs() << "Found offload node" << F->getName() << "\n");
+
+        for (DFGraph::children_iterator i = N->getChildGraph()->begin(),
+             e = N->getChildGraph()->end();
+             i != e; ++i) {
+          DFNode *child = *i;
+          if (auto *internal = dyn_cast<DFInternalNode>(child)) {
+            visitWorkerNode(internal);
+          }
+          else if (auto *leaf = dyn_cast<DFLeafNode>(child)) {
+            visitWorkerNode(leaf);
+          }
+          else {
+            assert(false && "Unexpected DFNode: Neither a leaf, nor an internal node");
+          }
+        }
+      }
+      else {
+        clientNodes.insert(F->getName());
+        DEBUG(errs() << "Found client node" << F->getName() << "\n");
+
+        for (DFGraph::children_iterator i = N->getChildGraph()->begin(),
+               e = N->getChildGraph()->end();
+             i != e; ++i) {
+          DFNode *child = *i;
+          if (auto *internal = dyn_cast<DFInternalNode>(child)) {
+            visit(internal);
+          }
+          else if (auto *leaf = dyn_cast<DFLeafNode>(child)) {
+            visit(leaf);
+          }
+          else {
+            assert(false && "Unexpected DFNode: Neither a leaf, nor an internal node");
+          }
+        }
+      }
+    }
+
+    virtual void visit(DFLeafNode *N) {
+      if (N->isDummyNode())
+        return;
+      Function *F = N->getFuncPointer();
+      if (hpvmUtils::getPreferredTarget(F) == hpvm::REMOTE_TARGET) {
+        offloadNodes.insert(F->getName());
+        DEBUG(errs() << "Found offload node" << F->getName() << "\n");
+      }
+      else {
+        clientNodes.insert(F->getName());
+        DEBUG(errs() << "Found client node" << F->getName() << "\n");
+      }
+    }
+  };
+
+
   // Returns true if instruction I is a hpvm launch intrinsic, false otherwise
   bool isHPVMLaunchIntrinsic(Instruction *I) {
     if (!isa<IntrinsicInst>(I))
@@ -588,6 +695,7 @@ namespace {
       initWorkerModule();
     }
 
+    void deleteUnreachableNodes(std::set<StringRef> &clientNodes, std::set<StringRef> &workerNodes);
     void writeWorkerModule();
   };
 
@@ -995,15 +1103,21 @@ namespace {
     // DFInternalNode *Root = DFG.getRoot();
     std::vector<DFInternalNode *> Roots = DFG.getRoots();
 
+    // Top-down visitor for partitioning nodes between the client and the worker
+    RemoteNodeDetector *Partitioner = new RemoteNodeDetector();
+
     // Visitor for Code Generation Graph Traversal
     CGT_Remote *CGTVisitor = new CGT_Remote(M, DFG);
 
     // Iterate over all the DFGs and produce code for each one of them
     for (auto &rootNode : Roots) {
+      // Detect the partition before any hints are updated
+      Partitioner->visit(rootNode);
       // Initiate code generation for root DFNode
       CGTVisitor->visit(rootNode);
     }
 
+    CGTVisitor->deleteUnreachableNodes(Partitioner->clientNodes, Partitioner->workerNodes);
     CGTVisitor->writeWorkerModule();
 
     delete CGTVisitor;
@@ -1016,6 +1130,23 @@ namespace {
     return mid.append(".worker.ll");
   }
 
+  void CGT_Remote::deleteUnreachableNodes(std::set<StringRef> &clientNodes, std::set<StringRef> &workerNodes) {
+    for (auto FName : workerNodes) {
+      Function *F = M.getFunction(FName);
+      DEBUG(errs() << "Deleting worker node " << FName << " from the client module\n");
+      F->replaceAllUsesWith(UndefValue::get(F->getType()));
+      F->eraseFromParent();
+      F->dropAllReferences();
+    }
+    for (auto FName : clientNodes) {
+      Function *F = WorkerModule.get()->getFunction(FName);
+      DEBUG(errs() << "Deleting client node " << FName << " from the worker module\n");
+      F->replaceAllUsesWith(UndefValue::get(F->getType()));
+      F->eraseFromParent();
+      F->dropAllReferences();
+    }
+  }
+
   void CGT_Remote::writeWorkerModule() {
     DEBUG(errs() << "Writing to File --- ");
     DEBUG(errs() << getWorkerModuleName(M).c_str() << "\n");
diff --git a/hpvm/test/dhpvm/simple/build.sh b/hpvm/test/dhpvm/simple/build.sh
index 939000595c..1f1ba6f6aa 100644
--- a/hpvm/test/dhpvm/simple/build.sh
+++ b/hpvm/test/dhpvm/simple/build.sh
@@ -32,42 +32,42 @@ echo
 $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_Remote.so -dfg2llvm-remote -S main.hpvm.ll -o main.hpvm.ll.client.ll -debug
 # $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_Remote.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-remote -dfg2llvm-cpu -clearDFG -S main.hpvm.ll -o main.client.ll -debug
  
-### echo
-### echo
-### echo
-### echo
-### echo "Compiling worker HPVM into LLVM..."
-### echo
-### echo
-### echo
-### echo
-### $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.client.ll -o main.client.ll -debug
-### $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.worker.ll -o main.worker.ll -debug
-### # $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.worker.ll -o main.worker.ll -debug
-### 
-### 
-### echo
-### echo
-### echo
-### echo
-### echo "Linking to the runtime..."
-### echo
-### echo
-### echo
-### echo
-### 
-### $BUILD/bin/llvm-link -S main.client.ll $BUILD/tools/hpvm/projects/hpvm-rt/hpvm-rt.bc -o main.client.linked.ll
-### $BUILD/bin/llvm-link -S main.worker.ll $BUILD/tools/hpvm/projects/hpvm-rt/hpvm-rt.bc -o main.worker.linked.ll
-### 
-### echo
-### echo
-### echo
-### echo
-### echo "Generating binaries..."
-### echo
-### echo
-### echo
-### echo
-### 
-### $BUILD/bin/clang++ -O1 -lzmq -lOpenCL -L/usr/lib/x86_64-linux-gnu -lrt -lpthread main.client.linked.ll -o client
-### $BUILD/bin/clang++ -O1 -lzmq -lOpenCL -L/usr/lib/x86_64-linux-gnu -lrt -lpthread main.worker.linked.ll -o worker
+echo
+echo
+echo
+echo
+echo "Compiling worker HPVM into LLVM..."
+echo
+echo
+echo
+echo
+$BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.client.ll -o main.client.ll -debug
+$BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.worker.ll -o main.worker.ll -debug
+# $BUILD/bin/opt -load $BUILD/lib/LLVMBuildDFG.so -load $BUILD/lib/LLVMDFG2LLVM_CPU.so -load $BUILD/lib/LLVMClearDFG.so -dfg2llvm-cpu -clearDFG -S main.hpvm.ll.worker.ll -o main.worker.ll -debug
+
+
+echo
+echo
+echo
+echo
+echo "Linking to the runtime..."
+echo
+echo
+echo
+echo
+
+$BUILD/bin/llvm-link -S main.client.ll $BUILD/tools/hpvm/projects/hpvm-rt/hpvm-rt.bc -o main.client.linked.ll
+$BUILD/bin/llvm-link -S main.worker.ll $BUILD/tools/hpvm/projects/hpvm-rt/hpvm-rt.bc -o main.worker.linked.ll
+
+echo
+echo
+echo
+echo
+echo "Generating binaries..."
+echo
+echo
+echo
+echo
+
+$BUILD/bin/clang++ -O1 -lzmq -lOpenCL -L/usr/lib/x86_64-linux-gnu -lrt -lpthread main.client.linked.ll -o client
+$BUILD/bin/clang++ -O1 -lzmq -lOpenCL -L/usr/lib/x86_64-linux-gnu -lrt -lpthread main.worker.linked.ll -o worker
-- 
GitLab