diff --git a/llvm/include/llvm/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.h b/llvm/include/llvm/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.h new file mode 100644 index 0000000000000000000000000000000000000000..dfbd09402d7006dd7e42968fef387908b1928afc --- /dev/null +++ b/llvm/include/llvm/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.h @@ -0,0 +1,25 @@ +#ifndef __EXTRACT_HPVM_LEAF_NODE_FUNCTIONS_H__ + #define __EXTRACT_HPVM_LEAF_NODE_FUNCTIONS_H__ + + //===-------------------- ExtractHPVMLeafNodeFunctions.h ------------------===// + // + // The LLVM Compiler Infrastructure + // + // This file is distributed under the University of Illinois Open Source + // License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + + #include "llvm/IR/Module.h" + #include "llvm/BuildDFG/BuildDFG.h" + + namespace extracthpvmleaf { + + class ExtractHPVMLeafNodeFunctions { + public: + void run(Module &M, builddfg::BuildDFG &DFG); + }; + + } // end namespace extracthpvmleaf + + #endif \ No newline at end of file diff --git a/llvm/include/llvm/SupportVISC/DFGTreeTraversal.h b/llvm/include/llvm/SupportVISC/DFGTreeTraversal.h new file mode 100644 index 0000000000000000000000000000000000000000..c031c112fec67f6632db32efd6342018de923edd --- /dev/null +++ b/llvm/include/llvm/SupportVISC/DFGTreeTraversal.h @@ -0,0 +1,64 @@ +#ifndef __DFGTREETRAVERSAL_H__ +#define __DFGTREETRAVERSAL_H__ + +//=== DFGTreeTraversal.h - Header file for Tree Traversal of the HPVM DFG ====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include "llvm/BuildDFG/BuildDFG.h" + +using namespace llvm; +using namespace builddfg; + +namespace dfg2llvm { + + class DFGTreeTraversal : public DFNodeVisitor { + + protected: + //Member variables + Module &M; + BuildDFG &DFG; + + virtual void process(DFInternalNode* N) = 0; + virtual void process(DFLeafNode* N) = 0; + + virtual ~DFGTreeTraversal() {} + + public: + // Constructor + DFGTreeTraversal(Module &_M, BuildDFG &_DFG) : M(_M), DFG(_DFG) {} + + void visit(DFInternalNode* N) { + // May visit a nodemore than once, there is no marking it as visited + errs() << "Start: In Node (I) - " << N->getFuncPointer()->getName() << "\n"; + + // Follows a bottom-up approach. + for (DFGraph::children_iterator i = N->getChildGraph()->begin(), + e = N->getChildGraph()->end(); i != e; ++i) { + DFNode* child = *i; + child->applyDFNodeVisitor(*this); + } + + // Process this internal node now. + process(N); + errs() << "DONE: In Node (I) - " << N->getFuncPointer()->getName() << "\n"; + } + + void visit(DFLeafNode* N) { + errs() << "Start: In Node (L) - " << N->getFuncPointer()->getName() << "\n"; + process(N); + errs() << "DONE: In Node (L) - " << N->getFuncPointer()->getName() << "\n"; + } + }; + +} // end namespace dfg2llvm + +#endif diff --git a/llvm/lib/Transforms/CMakeLists.txt b/llvm/lib/Transforms/CMakeLists.txt index 9dd826ef4371298bb880fad5de9094335fb86779..96179638c5033e52b30cd5365cf9c3cfe4c330e9 100644 --- a/llvm/lib/Transforms/CMakeLists.txt +++ b/llvm/lib/Transforms/CMakeLists.txt @@ -24,3 +24,5 @@ add_subdirectory(FuseHPVMTensorNodes) add_subdirectory(ReplaceIntrinsics) add_subdirectory(DFG2LLVM_X86_dsoc) add_subdirectory(InlineTensorCalls) +add_subdirectory(ExtractHPVMLeafNodes) + diff --git a/llvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt b/llvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6421b528d766db0efc16e083c70d1d9328fcba84 --- /dev/null +++ b/llvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt @@ -0,0 +1,13 @@ +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Core Support) +endif() + +add_llvm_loadable_module( ExtractHPVMLeafNodes + ExtractHPVMLeafNodes.cpp + + DEPENDS + intrinsics_gen + PLUGIN_TOOL + opt + ) + diff --git a/llvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp b/llvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd7ead9f6cda5048d03d1b56b0684dcfba368c73 --- /dev/null +++ b/llvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp @@ -0,0 +1,246 @@ +//===------------------- ExtractHPVMLeafNodeGenFunctions.cpp -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ExtractHPVMLeafNodes" + +#include "llvm/Support/SourceMgr.h" +#include "llvm/Pass.h" +#include "llvm/SupportVISC/DFGTreeTraversal.h" +#include "llvm/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/FileSystem.h" + +using namespace llvm; +using namespace builddfg; +using namespace extracthpvmleaf; +using namespace dfg2llvm; + +namespace { + +class PrintLeafNodes : public DFGTreeTraversal { + public: + virtual void process(DFInternalNode* N) override; + virtual void process(DFLeafNode* N) override; + + // Constructor + PrintLeafNodes(Module &_M, BuildDFG &_DFG) : DFGTreeTraversal(_M, _DFG) {} + +}; + +} + +void PrintLeafNodes::process(DFInternalNode* N) { + DEBUG(errs() << "Analysing Node: " << N->getFuncPointer()->getName() << "\n"); + return; // nothing to do +} + +void PrintLeafNodes::process(DFLeafNode* N) { + DEBUG(errs() << "Analysing Node: " << N->getFuncPointer()->getName() << "\n"); + if((N->isDummyNode())) { + DEBUG(errs() << "Skipping Dummy Node: " << N->getFuncPointer()->getName() << "\n"); + return; + } + + // Find function generated for node + Function *F = N->getGenFuncForTarget(visc::CPU_TARGET); + assert(F != NULL + && "This pass is invoked after code generation for x86 is completed.\nFound leaf node for which code generation has not happened!\n"); + assert(N->hasX86GenFuncForTarget(visc::CPU_TARGET) && + "The generated function from x86 pass is not an x86 function\n"); + + std::string module_name = std::string("./build/") + std::string(F->getName().str().c_str()) + std::string("_module.ll"); + Twine tw(module_name); + // Create a new module for the node function + //Twine tw = Twine(F->getName()).concat(Twine("_module.ll")); + Module *m = new Module(tw.str(), F->getParent()->getContext()); + // Create a new function for F. It will be written to a new module. + ValueToValueMapTy VMap; + Function *ClonedF = CloneFunction(F, VMap); + // Remove it from current module + ClonedF->removeFromParent(); + // Insert it to the newly created module for it + m->getFunctionList().push_back(ClonedF); + + std::vector<Instruction*> ItoRemove; + + for (inst_iterator i = inst_begin(ClonedF), e = inst_end(ClonedF); i != e; ++i) { + Instruction *I = &(*i); + errs() << *I << "\n"; + + if (CallInst *CI = dyn_cast<CallInst>(I)) { + errs() << "Found call instruction\n"; + + Function *CalledF = CI->getCalledFunction(); + StringRef CallName = CalledF->getName(); + errs() << "CallName: " << CallName << "\n"; + +// if (CallName.startswith("llvm_visc")) { //TODO + if ((CallName.startswith("llvm_visc")) || (CallName.startswith("tensor"))) { //TODO +// errs() << "This is an HPVM runtime call. Include its declaration.\n"; + errs() << "This is an HPVM runtime call or tensor. Include its declaration.\n"; + + FunctionType *CalledFType = CalledF->getFunctionType(); + + std::vector<Value*> Fargs; + for (unsigned argno = 0; argno < CI->getNumArgOperands(); argno++) { + Fargs.push_back(CI->getArgOperand(argno)); + } + Function *FDecl = cast<Function>(m->getOrInsertFunction(CallName, CalledFType)); + CallInst *NewCI = CallInst::Create(CalledFType, FDecl, Fargs, CallName, CI); + errs() << "NewCI: " << *NewCI << "\n"; + CI->replaceAllUsesWith(NewCI); + ItoRemove.push_back(CI); + } + } + } + + for (unsigned i = 0; i < ItoRemove.size() ; i++) { + ItoRemove[i]->eraseFromParent(); + } + + ItoRemove.clear(); + + // Print new module + legacy::PassManager Passes; + + errs() << "Writing to File --- " << tw.str() << "\n"; + std::error_code EC; + tool_output_file Out(tw.str(), EC, sys::fs::F_None); + if (EC) { + errs() << EC.message() << '\n'; + } + + Passes.add(createPrintModulePass(Out.os())); + Passes.run(*m); + // Declare success. + Out.keep(); + + // Any call that is to F, needs to call the new external function + // Edit initial module to do so + // This is the name with which the function is called now + StringRef FName = ClonedF->getName(); + FunctionType *FType = F->getFunctionType(); + + // This is a node function, so it is only called through the dataflow graph + assert(F->hasOneUse() && "F is an HPVM node function\n"); + +/* + errs() << "F uses: " << F->getNumUses() << "\n" ; + for(Value::user_iterator ui = F->user_begin(), + ue = F->user_end(); ui!=ue; ++ui) { + errs() << "use : "<< **ui << "\n"; + } +*/ + + // Get the parent node's generated x86 function + DFInternalNode *ParentNode = N->getParent(); + Function *PGenF = ParentNode->getGenFuncForTarget(visc::CPU_TARGET); + assert(PGenF != NULL + && "This pass is invoked after code generation for x86 is completed.\nFound node for which code generation has not happened!\n"); + assert(ParentNode->hasX86GenFuncForTarget(visc::CPU_TARGET) && + "The generated function from x86 pass is not an x86 function\n"); + + for (inst_iterator i = inst_begin(PGenF), e = inst_end(PGenF); i != e; ++i) { + Instruction *I = &(*i); + errs() << *I << "\n"; + + if (CallInst *CI = dyn_cast<CallInst>(I)) { + errs() << "Found call instruction\n"; + + StringRef CallName = CI->getCalledFunction()->getName(); + errs() << "CallName: " << CallName << "\n"; + errs() << "F->getName(): " << F->getName() << "\n"; + + if (CallName == F->getName()) { + // Found the call to the leaf node function we moved to the other module. + // Replace the call + std::vector<Value*> Fargs; + for (unsigned argno = 0; argno < CI->getNumArgOperands(); argno++) { + Fargs.push_back(CI->getArgOperand(argno)); + } + Function *FDecl = cast<Function>(M.getOrInsertFunction(FName, FType)); + CallInst *NewCI = CallInst::Create(FType, FDecl, Fargs, FName, CI); + errs() << "NewCI: " << *NewCI << "\n"; + CI->replaceAllUsesWith(NewCI); + ItoRemove.push_back(CI); + } + } + } + + for (unsigned i = 0; i < ItoRemove.size() ; i++) { + ItoRemove[i]->eraseFromParent(); + } + + // Clean up + ClonedF->eraseFromParent(); + delete m; + + F->replaceAllUsesWith(UndefValue::get(F->getType())); + F->eraseFromParent(); + + return; +} + +void ExtractHPVMLeafNodeFunctions::run(Module &M, BuildDFG &DFG) { + + errs() << "\nEXTRACT HPVM LEAF NODE FUNCTIONS PASS\n"; + + std::vector<DFInternalNode*> Roots = DFG.getRoots(); + + // Visitor for Graph Traversal + PrintLeafNodes *LeafVisitor = new PrintLeafNodes(M, DFG); + + // Iterate over all the DFGs + // Analyse the edges for parameters that are valid to be used in place + for (auto rootNode: Roots) { + LeafVisitor->visit(rootNode); + } + + delete LeafVisitor; + return; +} + +namespace { +struct ExtractHPVMLeafNodeGenFunctionsWrapper : public ModulePass { + static char ID; + ExtractHPVMLeafNodeGenFunctionsWrapper() : ModulePass(ID) {} + + bool runOnModule(Module &) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; +} // end anonymous namespace + +void ExtractHPVMLeafNodeGenFunctionsWrapper::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<BuildDFG>(); + AU.addPreserved<BuildDFG>(); +} + +bool ExtractHPVMLeafNodeGenFunctionsWrapper::runOnModule(Module &M) { + // Get the BuildDFG Analysis Results: + // - Dataflow graph + BuildDFG &DFG = getAnalysis<BuildDFG>(); + + ExtractHPVMLeafNodeFunctions ELNF; + ELNF.run(M, DFG); + + return false; +} + +char ExtractHPVMLeafNodeGenFunctionsWrapper::ID = 0; +static RegisterPass<ExtractHPVMLeafNodeGenFunctionsWrapper> X( + "hpvm-extract-leaf-gen", + "Pass to extract leaf nodes to modules in HPVM", + false /* does not modify the CFG */, +true /* transformation, not just analysis */); diff --git a/llvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.exports b/llvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.exports new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/llvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt b/llvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt new file mode 100644 index 0000000000000000000000000000000000000000..9862f559e5d9e0ec6d47aa7eb3b8b811a79d8d79 --- /dev/null +++ b/llvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/Transforms/DFG2LLVM_NVPTX/LLVMBuild.txt ------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = ExtractHPVMLeafNodes +parent = Transforms +