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