diff --git a/hpvm/lib/Transforms/CMakeLists.txt b/hpvm/lib/Transforms/CMakeLists.txt index bb044cd756883449dc775fd7742ac575aa5815a1..b18cd4551ba33e0c315a416164b45e6282098aeb 100644 --- a/hpvm/lib/Transforms/CMakeLists.txt +++ b/hpvm/lib/Transforms/CMakeLists.txt @@ -5,9 +5,6 @@ add_subdirectory(DFG2LLVM_CPU) add_subdirectory(GenHPVM) add_subdirectory(LocalMem) add_subdirectory(DFG2LLVM_WrapperAPI) -add_subdirectory(ReplaceIntrinsics) add_subdirectory(DFG2LLVM_CUDNN) -add_subdirectory(ExtractHPVMLeafNodes) add_subdirectory(FuseHPVMTensorNodes) -add_subdirectory(InlineTensorCalls) add_subdirectory(InPlaceDFG) diff --git a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt b/hpvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt deleted file mode 100644 index bb943f9100e628c87c865dfbdce80fc094ebb23e..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -if(WIN32 OR CYGWIN) - set(LLVM_LINK_COMPONENTS Core Support) -endif() - -add_llvm_library( ExtractHPVMLeafNodes - MODULE - ExtractHPVMLeafNodes.cpp - - DEPENDS - intrinsics_gen - PLUGIN_TOOL - opt - ) - diff --git a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp b/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp deleted file mode 100644 index 031503adeddd6c070ca06f3012fa0c2e5362f92c..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.cpp +++ /dev/null @@ -1,248 +0,0 @@ -//===------------------- 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 "SupportHPVM/DFGTreeTraversal.h" -#include "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(hpvm::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->hasCPUGenFuncForTarget(hpvm::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_hpvm")) { //TODO - if ((CallName.startswith("llvm_hpvm")) || (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 = dyn_cast<Function>((m->getOrInsertFunction(CallName, CalledFType)).getCallee()); - 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; - ToolOutputFile 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(hpvm::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->hasCPUGenFuncForTarget(hpvm::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 = dyn_cast<Function>(M.getOrInsertFunction(FName, FType).getCallee()); - 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/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.exports b/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.exports deleted file mode 100644 index 139597f9cb07c5d48bed18984ec4747f4b4f3438..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/ExtractHPVMLeafNodes.exports +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt b/hpvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt deleted file mode 100644 index 73ac540f06e86e9e7f0201b993d2c1e11270158e..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ExtractHPVMLeafNodes/LLVMBuild.txt +++ /dev/null @@ -1,21 +0,0 @@ -;===- ./lib/Transforms/DFG2LLVM_WrapperAPI/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 diff --git a/hpvm/lib/Transforms/InlineTensorCalls/CMakeLists.txt b/hpvm/lib/Transforms/InlineTensorCalls/CMakeLists.txt deleted file mode 100644 index 29dd2c8431362b28a1d5683eadb2c9eb867696ff..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/InlineTensorCalls/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -if(WIN32 OR CYGWIN) - set(LLVM_LINK_COMPONENTS Core Support) -endif() - -add_llvm_library( InlineTensorCalls - MODULE - InlineTensorCalls.cpp - - DEPENDS - intrinsics_gen - PLUGIN_TOOL - opt - ) - diff --git a/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.cpp b/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.cpp deleted file mode 100644 index d31434341cf65939768d0acb7a0051d453909971..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//=== InlineApproxHPVMCalls.cpp ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#define ENABLE_ASSERTS - -#define DEBUG_TYPE "INLINE_APPROXHPVM_CALLS" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" - -#include "llvm/IR/InstIterator.h" - -#include "llvm/Support/raw_ostream.h" -#include "llvm/Analysis/InlineCost.h" - -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/IR/CallSite.h" -#include "llvm/ADT/SetVector.h" -#include <sstream> - -using namespace llvm; - - -namespace { - - struct InlineApproxHPVMCalls : public ModulePass { - static char ID; // Pass identification, replacement for typeid - InlineApproxHPVMCalls() : ModulePass(ID) {} - - bool runOnModule(Module &M) override { - - InlineFunctionInfo IFI; - SmallSetVector<CallSite, 16> Calls; - bool Changed = false; - SmallVector<Function *, 16> InlinedFunctions; - for (Function &F : M){ - if (!F.isDeclaration() && F.getName().startswith("tensor") ) { - //errs()<<"Function = "<<*&F<<"\n"; - Calls.clear(); - - for (User *U : F.users()) - if (auto CS = CallSite(U)) - if (CS.getCalledFunction() == &F) - Calls.insert(CS); - - for (CallSite CS : Calls) - // FIXME: We really shouldn't be able to fail to inline at this point! - // We should do something to log or check the inline failures here. - Changed |= InlineFunction(CS, IFI); - - } - } - - return true; - } - - }; - - -} // End of namespace - -char InlineApproxHPVMCalls::ID = 0; -static RegisterPass<InlineApproxHPVMCalls> X("inline-tensor-calls", - "Inline ApproxHPVM tensor library function calls (CPU version)", - true /* modifies the CFG */, - true /* transformation, * - * not just analysis */); - diff --git a/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.exports b/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.exports deleted file mode 100644 index 139597f9cb07c5d48bed18984ec4747f4b4f3438..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/InlineTensorCalls/InlineTensorCalls.exports +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/hpvm/lib/Transforms/InlineTensorCalls/LLVMBuild.txt b/hpvm/lib/Transforms/InlineTensorCalls/LLVMBuild.txt deleted file mode 100644 index c160516a6477d367893495e39f5fd4d00366f6f0..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/InlineTensorCalls/LLVMBuild.txt +++ /dev/null @@ -1,21 +0,0 @@ -;===- ./lib/Transforms/DFG2LLVM_WrapperAPI/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 = InlineTensorCalls -parent = Transforms diff --git a/hpvm/lib/Transforms/ReplaceIntrinsics/CMakeLists.txt b/hpvm/lib/Transforms/ReplaceIntrinsics/CMakeLists.txt deleted file mode 100644 index 460aabcc27b51a2d94dabee3e9c4c60d14803ea9..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ReplaceIntrinsics/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -if(WIN32 OR CYGWIN) - set(LLVM_LINK_COMPONENTS Core Support) -endif() - -add_llvm_library( ReplaceIntrinsics - MODULE - ReplaceIntrinsics.cpp - - DEPENDS - intrinsics_gen - PLUGIN_TOOL - opt - ) - diff --git a/hpvm/lib/Transforms/ReplaceIntrinsics/LLVMBuild.txt b/hpvm/lib/Transforms/ReplaceIntrinsics/LLVMBuild.txt deleted file mode 100644 index 95739b3d4d1c3a68cc5014dc85fb26d3b1fc6ac5..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ReplaceIntrinsics/LLVMBuild.txt +++ /dev/null @@ -1,21 +0,0 @@ -;===- ./lib/Transforms/DFG2LLVM_WrapperAPI/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 = ReplaceIntrinsics -parent = Transforms diff --git a/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.cpp b/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.cpp deleted file mode 100644 index 45ad0ece23568a41fbf532b92918a582ebbae505..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.cpp +++ /dev/null @@ -1,495 +0,0 @@ -//=== ReplaceApproxHPVMIntrinsicsWithFCalls.cpp ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#define ENABLE_ASSERTS - -#define DEBUG_TYPE "REPLACE_APPROXHPVM_INTRINSICS_WITH_FCALLS" - -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/Transforms/Utils/ValueMapper.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/IR/Attributes.h" -#include "llvm-c/Core.h" - -#include "SupportHPVM/DFG2LLVM.h" -#include "InPlaceDFG/InPlaceDFGAnalysis.h" - -#include <sstream> - -using namespace llvm; -using namespace builddfg; -using namespace dfg2llvm; - -// TODO: We still need in place analysis, if calls have the same interface -using namespace inplacedfg; - -namespace { -// Helper class declarations - -// Replace ApproxHPVM intrinsics with LLVM function calls. -// aiming to go through the CPU backend code generation. - -struct DFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls : public DFG2LLVM { - static char ID; // Pass identification, replacement for typeid - DFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls() : DFG2LLVM(ID) {} - -private: -public: - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<BuildDFG>(); - AU.addRequired<InPlaceDFGAnalysisWrapper>(); - AU.addPreserved<BuildDFG>(); - AU.addPreserved<InPlaceDFGAnalysisWrapper>(); - } - - bool runOnModule(Module &M); -}; - -// Visitor for Code generation traversal (tree traversal for now) -class CGT_ReplaceApproxHPVMIntrinsicsWithFCalls : public CodeGenTraversal { - -private: - // Member variables - InPlaceDFGAnalysis::InPlaceDFGParameter *IPP; - - // VISC Runtime API and Tensor runtime API - - /* TODO: I believe that TensorRt is not needed, since we will have llvm - implementations linked in, so init and cleanup calls can be removed and - relevant code also, but I leave in in for now until verified. */ - FunctionCallee llvm_hpvm_initTensorRt; - FunctionCallee llvm_hpvm_cleanupTensorRt; - // Constant* hpvm_request_tensor; DONE: request tensor will not be used - - // Functions - bool isValidOperandForInPlaceOperation(Value *Op, Function *Fgen, DFNode *N); - - // Virtual Functions - void init(); - void initRuntimeAPI(); - void codeGen(DFInternalNode *N); - void codeGen(DFLeafNode *N); - -public: - // Constructor - CGT_ReplaceApproxHPVMIntrinsicsWithFCalls( - Module &_M, BuildDFG &_DFG, InPlaceDFGAnalysis::InPlaceDFGParameter &_IPP) - : CodeGenTraversal(_M, _DFG), IPP(&_IPP) { - initRuntimeAPI(); - } -}; - -bool CGT_ReplaceApproxHPVMIntrinsicsWithFCalls:: - isValidOperandForInPlaceOperation(Value *Op, Function *Fgen, DFNode *N) { - // We only expect the if branch to be taken - if (Argument *Arg = dyn_cast<Argument>(Op)) { - DEBUG(errs() << *Arg << "\t: argument, candidate for in place\n"); - assert((Arg->getParent() == Fgen) && - "Extra Parameter in body of Function\n"); - // Candidae parameter is a function argument - // In this case, consult the result of in place analysis - // Find position in arg list - unsigned pos = Arg->getArgNo(); - // If this parameter cannot be used for in place operation - // code gen cannot continue - if (IPP->at(N)[pos]) { - DEBUG(errs() << *Arg << "\t: argument, suitable for in place\n"); - return true; - } else { - DEBUG(errs() << *Arg << "\t: argument, not suitable for in place\n"); - return false; - } - } else { - // If it is not an argument, then it needs to be the result of - // another intrinsic. These are new objects that are allocated, - // and consumed by next intrinsic. Alternatively, the intrinsic - // could have been replaced by a call to an LLVM function. - // We do not expect a merge pass to have run before the replacement pass, - // therefore we do not expect to go in the else branch. - DEBUG(errs() << *Op << "\t: Test for result of intrinsic operation\n"); - if (dyn_cast<IntrinsicInst>(Op)) { - DEBUG(errs() << *Arg << "\t: local, suitable for in place\n"); - return true; - } else if (CallInst *CI = dyn_cast<CallInst>(Op)) { - if ((CI->getCalledFunction()->getName()).startswith("tensor")) - return true; - else - return false; - } else { - DEBUG(errs() << *Arg << "\t: local, not suitable for in place\n"); - return false; - } - } -} - -void CGT_ReplaceApproxHPVMIntrinsicsWithFCalls::init() {} - -// Initialize the VISC runtime API. This makes it easier to insert these calls -void CGT_ReplaceApproxHPVMIntrinsicsWithFCalls::initRuntimeAPI() { - - // Load Runtime API Module - SMDiagnostic Err; - runtimeModule = parseIRFile(TENSOR_RT_LL, Err, M.getContext()); - if (runtimeModule == nullptr) - DEBUG(errs() << Err.getMessage()); - else - DEBUG(errs() << "Successfully loaded hpvm-tensor-rt API module\n"); - - // Get or insert Global declarations for - // - initialization - // - cleanup - // - request a tensor - DECLARE(llvm_hpvm_initTensorRt); - DECLARE(llvm_hpvm_cleanupTensorRt); - // DECLARE(hpvm_request_tensor); - - // Find hpvm.init and visc.cleanup calls, and add placeholder methods - // for initialization and cleanup of the hpvm tensor runtime - - Function *VI = M.getFunction("llvm.hpvm.init"); - assert(VI->getNumUses() == 1 && "__hpvm__init should only be used once\n"); - InitCall = cast<Instruction>(*VI->user_begin()); - CallInst::Create( - llvm_hpvm_initTensorRt, - ArrayRef<Value *>(ConstantInt::get(Type::getInt32Ty(M.getContext()), 0)), - "", InitCall); - - Function *VC = M.getFunction("llvm.hpvm.cleanup"); - assert(VC->getNumUses() == 1 && "__hpvm__clear should only be used once\n"); - CleanupCall = cast<Instruction>(*VC->user_begin()); - CallInst::Create(llvm_hpvm_cleanupTensorRt, ArrayRef<Value *>(), "", - CleanupCall); -} - -void CGT_ReplaceApproxHPVMIntrinsicsWithFCalls::codeGen(DFInternalNode *N) { - errs() << "Inside node: " << N->getFuncPointer()->getName() << "\n"; - errs() << "Skipping internal node\n"; -} - -void CGT_ReplaceApproxHPVMIntrinsicsWithFCalls::codeGen(DFLeafNode *N) { - - // Skip if it is a dummy node - if (N->isDummyNode()) { - DEBUG(errs() << "Skipping dummy node\n"); - return; - } - - // Abort if it is an allocation node - if (N->isAllocationNode()) { - assert(false && "Allocation Node not expected in ApproxHPVM"); - return; - } - - // Search for intrinsic only if it has the right hint - if (!checkPreferredTarget(N, hpvm::CPU_TARGET)) { - errs() << "Skipping node: " << N->getFuncPointer()->getName() << "\n"; - return; - } - - // Get the function associated with the dataflow node - Function *F = N->getFuncPointer(); - errs() << "function name = " << F->getName() << "\n"; - - std::vector<IntrinsicInst *> IItoRemove; - - for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { - Instruction *I = &(*i); - if (BuildDFG::isHPVMIntrinsic(I)) { - IntrinsicInst *II = dyn_cast<IntrinsicInst>(I); - assert( - (II->getCalledFunction()->getName()).startswith("llvm.hpvm.tensor") && - "Only HPVM tensor intrinsics allowed in ApproxHPVM leaf nodes\n"); - /********************* Handle VISC Tensor intrinsics ********************/ - // We replace them with calls to functions with implementations at the - // LLVM level - switch (II->getIntrinsicID()) { - - case Intrinsic::hpvm_tensor_convolution: { /* llvm.hpvm.tensor.convolution - */ - DEBUG(errs() << F->getName() << "\t: Handling tensor convolution \n"); - - // Argument list for the runtime call - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - Args.push_back(II->getOperand(1)); - Args.push_back(II->getOperand(2)); - Args.push_back(II->getOperand(3)); - Args.push_back(II->getOperand(4)); - Args.push_back(II->getOperand(5)); - - Constant *conv_mode = - ConstantInt::get(Type::getInt32Ty(M.getContext()), 1); - Constant *conv_precision = - ConstantInt::get(Type::getInt32Ty(M.getContext()), 0); - - Args.push_back(conv_mode); - Args.push_back(conv_precision); - - // Create function call - FunctionCallee tensorConvolutionCPU; - DECLARE(tensorConvolutionCPU); - - CallInst *CI = CallInst::Create(tensorConvolutionCPU, Args, "", II); - // We can replace the call to hpvm.tensor.mul with the LLVM call - II->replaceAllUsesWith(CI); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - case Intrinsic::hpvm_tensor_mul: { /* llvm.hpvm.tensor.mul */ - DEBUG(errs() << F->getName() << "\t: Handling tensor mul\n"); - - // Argument list for the runtime call - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - Args.push_back(II->getOperand(1)); - - // Create function call - FunctionCallee tensorGemmCPU; - DECLARE(tensorGemmCPU); - - CallInst *CI = CallInst::Create(tensorGemmCPU, Args, "", II); - // We can replace the call to hpvm.tensor.mul with the LLVM call - II->replaceAllUsesWith(CI); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - case Intrinsic::hpvm_tensor_add: { /* llvm.hpvm.tensor.add */ - DEBUG(errs() << F->getName() << "\t: Handling tensor add\n"); - // Tensor add(a,b) is in place for argument a. - Value *Op = II->getOperand(0); - - // Test the intrinsic operand for in place operation. - bool inplace = isValidOperandForInPlaceOperation(Op, F, N); - // Code generation cannot continue if this is false, because the target - // only provides an in place operation - - // FIXME: remove this comment - must check for in-place - // assert(inplace && - // "Operand not valid for in place operation. Code gen - // aborted.\n"); - - // Argument list for the runtime call - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - Args.push_back(II->getOperand(1)); - - // Create function call - FunctionCallee tensorAddCPU; - DECLARE(tensorAddCPU); - CallInst::Create(tensorAddCPU, Args, "", II); - // We can replace the call to hpvm.tensor.add with the 1st argument - // that, due to in place operation, now contains the result - II->replaceAllUsesWith(II->getOperand(0)); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - case Intrinsic::hpvm_tensor_pool_max: - case Intrinsic::hpvm_tensor_pool_mean: { /* llvm.hpvm.tensor.relu */ - DEBUG(errs() << F->getName() << "\t: Handling tensor_pool_max\n"); - // Tensor relu(a) is in place for argument a. - Value *Op = II->getOperand(0); - - // Test the intrinsic operand for in place operation. - bool inplace = isValidOperandForInPlaceOperation(Op, F, N); - // Code generation cannot continue if this is false, because the target - // only provides an in place operation - assert(inplace && - "Operand not valid for in place operation. Code gen aborted.\n"); - - // Argument list - tensorPooling(input, poolFunction, window_height, - // window_width, vertical_pad, horizontal_pad, - // vertical_stride, horizontal_stride); - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - - int pool_type = 0; - if (II->getIntrinsicID() == Intrinsic::hpvm_tensor_pool_max) { - pool_type = 0; - } - if (II->getIntrinsicID() == Intrinsic::hpvm_tensor_pool_mean) { - pool_type = 1; - } - - Constant *constPoolType = - ConstantInt::get(Type::getInt32Ty(M.getContext()), pool_type); - Args.push_back(constPoolType); // ID for max pool. Min/Avg have - // different IDs (non-zero) - Args.push_back(II->getOperand(1)); - Args.push_back(II->getOperand(2)); - Args.push_back(II->getOperand(3)); - Args.push_back(II->getOperand(4)); - Args.push_back(II->getOperand(5)); - Args.push_back(II->getOperand(6)); - - // Create function call - FunctionCallee tensorPoolingCPU; - DECLARE(tensorPoolingCPU); - CallInst *CI = CallInst::Create(tensorPoolingCPU, Args, "", II); - - // Replacing intrinsic result uses with the result of the LLVM call - II->replaceAllUsesWith(CI); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - case Intrinsic::hpvm_tensor_relu: - case Intrinsic::hpvm_tensor_clipped_relu: - case Intrinsic::hpvm_tensor_tanh: { /* llvm.hpvm.tensor.relu */ - DEBUG(errs() << F->getName() - << "\t: Handling tensor activation functions \n"); - // Tensor relu(a) is in place for argument a. - Value *Op = II->getOperand(0); - - // Test the intrinsic operand for in place operation. - bool inplace = isValidOperandForInPlaceOperation(Op, F, N); - // Code generation cannot continue if this is false, because the target - // only provides an in place operation - assert(inplace && - "Operand not valid for in place operation. Code gen aborted.\n"); - - // Argument list for the runtime call - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - - if (II->getIntrinsicID() == Intrinsic::hpvm_tensor_relu) { - // Create function call - FunctionCallee tensorReluCPU; - DECLARE(tensorReluCPU); - CallInst::Create(tensorReluCPU, Args, "", II); - } else if (II->getIntrinsicID() == - Intrinsic::hpvm_tensor_clipped_relu) { - // Create function call - //-- FunctionCallee tensorClippedRelu; - FunctionCallee tensorRelu2CPU; - DECLARE(tensorRelu2CPU); - CallInst::Create(tensorRelu2CPU, Args, "", II); - } else if (II->getIntrinsicID() == Intrinsic::hpvm_tensor_tanh) { - // Create function call - FunctionCallee tensorTanhCPU; - errs() << "tensorTanh Call = \n\n"; - DECLARE(tensorTanhCPU); - // errs()<<"tensorTanh Call = "<<*tensorTanh<<"\l"; - CallInst::Create(tensorTanhCPU, Args, "", II); - } - - // We can replace the call to hpvm.tensor.relu with the 1st argument - // that, due to in place operation, now contains the result - II->replaceAllUsesWith(II->getOperand(0)); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - case Intrinsic::hpvm_tensor_softmax: { /* llvm.hpvm.tensor.softmax */ - DEBUG(errs() << F->getName() << "\t: Handling tensor softmax\n"); - // Tensor relu(a) is in place for argument a. - Value *Op = II->getOperand(0); - - // Test the intrinsic operand for in place operation. - bool inplace = isValidOperandForInPlaceOperation(Op, F, N); - // Code generation cannot continue if this is false, because the target - // only provides an in place operation - assert(inplace && - "Operand not valid for in place operation. Code gen aborted.\n"); - - // Argument list for the runtime call - std::vector<Value *> Args; - Args.push_back(II->getOperand(0)); - - // Create function call - FunctionCallee tensorSoftmaxCPU; - DECLARE(tensorSoftmaxCPU); - CallInst::Create(tensorSoftmaxCPU, Args, "", II); - // We can replace the call to hpvm.tensor.softmax with the 1st argument - // that, due to in place operation, now contains the result - II->replaceAllUsesWith(II->getOperand(0)); - - // Mark to remove at the end - IItoRemove.push_back(II); - } break; - - default: - llvm_unreachable("Unknown VISC Intrinsic!"); - break; - } - } - } - - // We need to do this explicitly: DCE pass may not remove them. - // Traverse the vector backwards, otherwise definitions are deleted while - // their subsequent uses are still around. - for (std::vector<IntrinsicInst *>::reverse_iterator ri = IItoRemove.rbegin(), - re = IItoRemove.rend(); - ri != re; ++ri) { - DEBUG(errs() << "Erasing: " << **ri << "\n"); - errs() << "Erasing: " << **ri << "\n"; - (*ri)->eraseFromParent(); - } - - return; -} - -bool DFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls::runOnModule(Module &M) { - errs() << "\nDFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls PASS\n"; - - // Get the BuildDFG Analysis Results: - // - Dataflow graph - BuildDFG &DFG = getAnalysis<BuildDFG>(); - - // Get the In Place Analysis Results - InPlaceDFGAnalysis::InPlaceDFGParameter IPP = - (getAnalysis<InPlaceDFGAnalysisWrapper>()).getIPP(); - // Print results - printInPlaceDFGParameter(IPP); - - std::vector<DFInternalNode *> Roots = DFG.getRoots(); - - // Visitor for Code Generation Graph Traversal - CGT_ReplaceApproxHPVMIntrinsicsWithFCalls *CGTVisitor = - new CGT_ReplaceApproxHPVMIntrinsicsWithFCalls(M, DFG, IPP); - - // Iterate over all the DFGs and produce code for each one of them - for (auto rootNode : Roots) { - // Initiate code generation for root DFNode - CGTVisitor->visit(rootNode); - } - - // TODO: Edit module epilogue to remove the VISC intrinsic declarations - delete CGTVisitor; - - return true; -} - -/****************************************************************************** - * Helper functions * - ******************************************************************************/ - -} // End of namespace - -char DFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls::ID = 0; -static RegisterPass<DFG2LLVM_ReplaceApproxHPVMIntrinsicsWithFCalls> X("replace-intrinsics", - "Replace ApproxHPVM intrinsics with LLVM calls", - false /* does not modify the CFG */, - true /* transformation, * - * not just analysis */); diff --git a/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.exports b/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.exports deleted file mode 100644 index 139597f9cb07c5d48bed18984ec4747f4b4f3438..0000000000000000000000000000000000000000 --- a/hpvm/lib/Transforms/ReplaceIntrinsics/ReplaceIntrinsics.exports +++ /dev/null @@ -1,2 +0,0 @@ - -