Skip to content
Snippets Groups Projects
Commit b1183a10 authored by Hashim Sharif's avatar Hashim Sharif
Browse files

Adding barebones for ApproxScheduler

parent 5284f296
No related branches found
No related tags found
No related merge requests found
//===------------------------ InPlaceDFGAnalysis.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 "ApproxScheduler"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/InPlaceDFG/InPlaceDFGAnalysis.h"
#include "llvm/SupportVISC/DFG2LLVM.h"
#include "llvm/IR/InstrTypes.h"
#include <unordered_map>
#include <dirent.h>
#include <stdio.h>
#include <sstream>
#include <fstream>
using namespace llvm;
using namespace builddfg;
using namespace dfg2llvm;
using namespace inplacedfg;
namespace {
static cl::opt<std::string> category_input("category", cl::desc(" Hardware-agnostic ranking cateogy {log, linear, quad} "));
static cl::opt<int> rank_input("rank", cl::desc(" Hardware-agostic rank given by autotuner "));
struct ApproxMetrics{
std::string op_name;
std::string category;
unsigned int rank; // rank given by autotuner
double approx_level;
// Relative L-norm metrics
double relative_l1;
double relative_l2;
double relative_linf;
// Mean L-norm metrics
double mean_l1;
double mean_l2;
double mean_linf;
};
struct ApproxSchedulerWrapperPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
ApproxSchedulerWrapperPass() : ModulePass(ID) {}
public:
// Functions
bool runOnModule(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const;
};
// Visitor for Code generation traversal (tree traversal for now)
class ApproxScheduler : public CodeGenTraversal {
private:
int rank; // Rank to use for scheduling - ranks added in operand bundles
std::string category; // category = {log, linear, quad}
// Virtual Functions
void init() {}
void initRuntimeAPI() {}
void codeGen(DFInternalNode* N);
void codeGen(DFLeafNode* N);
bool rankMatches(OperandBundleUse opBundle, std::string category, int rank);
ApproxMetrics* getApproxInfo(Instruction* I);
ApproxMetrics* loadApproxMetrics(OperandBundleUse opBundle);
// Tracks the id of the tensor op processed
unsigned int currentID;
public:
// Constructor
ApproxScheduler(Module &_M, BuildDFG &_DFG, std::string category, int rank);
void run();
};
void ApproxSchedulerWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<BuildDFG>();
AU.addPreserved<BuildDFG>();
}
bool ApproxSchedulerWrapperPass::runOnModule(Module &M) {
BuildDFG &DFG = getAnalysis<BuildDFG>();
std::string category = category_input.getValue();
int rank = rank_input.getValue();
ApproxScheduler scheduler(M, DFG, category, rank);
scheduler.run();
return true;
}
ApproxScheduler::ApproxScheduler(Module &_M, BuildDFG &_DFG, std::string category, int rank) :
CodeGenTraversal(_M, _DFG){
this->category = category;
this->rank = rank;
}
void ApproxScheduler::run() {
errs() << "\n NOTE: Approximation-based scheduling transform \n";
std::vector<DFInternalNode*> Roots = DFG.getRoots();
// Iterate over all the DFGs
for (auto rootNode: Roots) {
this->visit(rootNode);
}
return;
}
/*** Analysis of internal node ***/
void ApproxScheduler::codeGen(DFInternalNode* N) {
DEBUG(errs() << "Analysing Node: " << N->getFuncPointer()->getName() << "\n");
}
ApproxMetrics* ApproxScheduler::loadApproxMetrics(OperandBundleUse opBundle){
}
bool ApproxScheduler::rankMatches(OperandBundleUse opBundle, std::string category_in, int rank_in){
// Extracting value of the 'category' attribute
GlobalVariable* gv = dyn_cast<GlobalVariable>(opBundle.Inputs[1].get());
ConstantDataArray* constString = dyn_cast<ConstantDataArray>(gv->getInitializer());
std::string category = std::string(constString->getAsCString().data());
errs()<<"*category = "<<category<<"\n";
int rank = dyn_cast<ConstantInt>(opBundle.Inputs[3].get())->getZExtValue();
errs()<<"-rank = "<<rank<<"\n";
if(category == category_in && rank == rank_in)
return true;
else
return false;
/*for(unsigned int j = 0; j < bundleUse.Inputs.size(); j++){
Value* bundleVal = bundleUse.Inputs[j].get();
errs()<<"Val = "<<*bundleVal<<"\n";
} */
}
ApproxMetrics* ApproxScheduler::getApproxInfo(Instruction* I){
CallSite* CS = new CallSite(I);
if(CS->hasOperandBundles()){
errs()<<"CallSite has OperandBundles \n";
for(unsigned int i = 0; i < CS->getNumOperandBundles(); i++){
OperandBundleUse bundleUse = CS->getOperandBundleAt(i);
errs()<<"bundleUse -> getTagName() = "<<bundleUse.getTagName()<<"\n";
if(rankMatches(bundleUse, category, rank)){
return loadApproxMetrics(bundleUse);
}
/*for(unsigned int j = 0; j < bundleUse.Inputs.size(); j++){
Value* bundleVal = bundleUse.Inputs[j].get();
errs()<<"Val = "<<*bundleVal<<"\n";
}
*/
}
}
else{
errs()<<"DOES NOT have OperandBundles \n";
}
assert("No Bundle Matched the provided rank and Category! \n");
}
/*** Analysis of leaf node ***/
void ApproxScheduler::codeGen(DFLeafNode* N) {
DEBUG(errs() << "Analysing Node: " << N->getFuncPointer()->getName() << "\n");
// Skip code generation if it is a dummy node
if(N->isDummyNode()) {
DEBUG(errs() << "Skipping dummy node\n");
return;
}
// Abort code generation if it is an allocation node
if(N->isAllocationNode()) {
assert(false && "Allocation Node not expected in ApproxHPVM");
return;
}
Function *F = N->getFuncPointer();
Module* M = F->getParent();
/**** Reading all tensor operations in the DFG Leaf Node ****/
for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
Instruction *I = &(*i);
errs()<<*I<<"\n";
if (BuildDFG::isViscIntrinsic(I)) {
IntrinsicInst* II = dyn_cast<IntrinsicInst>(I);
// FIXME: The assumption of only tensor instrinsics is restrictive
assert((II->getCalledFunction()->getName()).startswith("llvm.visc.tensor")
&& "Only HPVM tensor intrinsics allowed in ApproxHPVM leaf nodes\n");
// NOTE: Get tensorOp name - the scheduling decisions are made per-operation type
std::string intrinsic_id = std::string(II->getCalledFunction()->getName().data());
ApproxMetrics* approx_metrics = getApproxInfo(I);
}
}
}
char ApproxSchedulerWrapperPass::ID = 0;
static RegisterPass<ApproxSchedulerWrapperPass> X("approx-scheduler",
"Select target compute unit based on aprroximation metrics",
false /* does not modify the CFG */,
false /* not transformation, just analysis */);
} // End of namespace
if(WIN32 OR CYGWIN)
set(LLVM_LINK_COMPONENTS Core Support)
endif()
add_llvm_loadable_module( ApproxScheduler
ApproxScheduler.cpp
DEPENDS
intrinsics_gen
PLUGIN_TOOL
opt
)
;===- ./lib/Transforms/LocalMem/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 = ApproxScheduler
parent = Transforms
......@@ -17,6 +17,7 @@ add_subdirectory(DFG2LLVM_X86)
add_subdirectory(LocalMem)
add_subdirectory(InPlaceDFG)
add_subdirectory(InsertApproxInfo)
add_subdirectory(ApproxScheduler)
add_subdirectory(GenVISC)
add_subdirectory(MergeDFN)
add_subdirectory(FuseHPVMTensorNodes)
......@@ -16,17 +16,23 @@ num_flags = 14 # FIXME: Auto-extract the number of tensor ops from the bitcode f
error_range = 9
def change_dir():
os.chdir(bench_build_dir)
print os.getcwd()
def build_binaries():
def setup_env():
os.environ["LD_LIBRARY_PATH"] = os.environ["LD_LIBRARY_PATH"] + ":" + os.environ["LLVM_BUILD_ROOT"] + "/lib"
print os.environ["LD_LIBRARY_PATH"]
def build_binaries():
subprocess.call("make", shell=True)
def run_autotuner():
# Change build directory to benchmark build directory
os.chdir(bench_build_dir)
print os.getcwd()
change_dir()
LLVM_SRC_ROOT = os.environ["LLVM_SRC_ROOT"]
autotuner_cmd = "python " + LLVM_SRC_ROOT + "projects/hpvm-tensor-rt/opentuner/autotuner/approxhpvm_tuner.py " + \
......@@ -44,25 +50,38 @@ def run_autotuner():
def add_approx_info():
os.chdir(bench_build_dir)
print os.getcwd()
os.environ["LD_LIBRARY_PATH"] = os.environ["LD_LIBRARY_PATH"] + ":" + os.environ["LLVM_BUILD_ROOT"] + "/lib"
print os.environ["LD_LIBRARY_PATH"]
# Change directory and setup env variables
change_dir()
setup_env()
subprocess.call("which opt", shell=True)
approxinfo_cmd = "opt -load LLVMBuildDFG.so -load InsertApproxInfo.so -insert-approxinfo --results-dir " + \
result_dir + " " + " " + \
visc_file_name + " -o " + visc_file_name + "_approx"
visc_file_name + " -S -o " + visc_file_name + "_approx.ll"
print approxinfo_cmd
print approxinfo_cmd
subprocess.call(approxinfo_cmd, shell=True)
def run_scheduler():
change_dir()
setup_env()
sched_cmd = "opt -load LLVMBuildDFG.so -load ApproxScheduler.so -approx-scheduler --category quad --rank 4 " + \
visc_file_name + "_approx.ll" + " -S -o " + visc_file_name + "_sched_out.ll"
print sched_cmd
subprocess.call(sched_cmd, shell=True)
if __name__ == "__main__":
#build_binaries()
run_autotuner()
add_approx_info()
#run_autotuner()
#add_approx_info()
run_scheduler()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment