Skip to content
Snippets Groups Projects
Commit 973995ac authored by kotsifa2's avatar kotsifa2
Browse files

DFG2LLVM Pass for leaf nodes (need to add the way of replacing the

intrinsic instructions with appropriate instructions/values).
parent 910aeefb
No related branches found
No related tags found
No related merge requests found
......@@ -40,19 +40,24 @@ namespace builddfg {
// Functions
bool isViscLaunchIntrinsic(Instruction * I);
bool isViscGraphIntrinsic(Instruction * I);
void handleCreateNode (DFInternalNode* N, IntrinsicInst* II);
void handleCreateEdge (DFInternalNode* N, IntrinsicInst* II);
void BuildGraph (DFInternalNode* N, Function* F);
public:
// Functions
virtual bool runOnModule(Module &M);
const DFInternalNode *getRoot();
const HandleToDFNode &getHandleToDFNodeMap();
const HandleToDFEdge &getHandleToDFEdgeMap();
static bool isViscLaunchIntrinsic(Instruction * I);
static bool isViscGraphIntrinsic(Instruction * I);
static bool isViscQueryIntrinsic(Instruction* I);
static bool isViscIntrinsic(Instruction* I);
//TODO: Maybe make these fields const
DFInternalNode *getRoot();
HandleToDFNode &getHandleToDFNodeMap();
HandleToDFEdge &getHandleToDFEdgeMap();
};
......
......@@ -238,6 +238,15 @@ public:
return FuncPointer;
}
//TODO: make this DFInternalNode
DFNode* getParent() {
return Parent;
}
int getNumOfDim() {
return NumOfDim;
}
int getLevel() {
return Level;
}
......@@ -372,7 +381,7 @@ class DFTreeTraversal : public DFNodeVisitor {
public:
virtual void visit(DFInternalNode* N){
errs() << "Visted Node (I) - " << N->getFuncPointer()->getName() << "\n";
errs() << "Visited Node (I) - " << N->getFuncPointer()->getName() << "\n";
for(DFGraph::children_iterator i = N->getChildGraph()->begin(),
e = N->getChildGraph()->end(); i != e; ++i) {
DFNode* child = *i;
......@@ -381,7 +390,7 @@ public:
}
virtual void visit(DFLeafNode* N) {
errs() << "Visted Node (L) - " << N->getFuncPointer()->getName() << "\n";
errs() << "Visited Node (L) - " << N->getFuncPointer()->getName() << "\n";
}
};
......@@ -390,7 +399,7 @@ class FollowSuccessors : public DFNodeVisitor {
public:
virtual void visit(DFInternalNode* N) {
errs() << "Visted Node (I) - " << N->getFuncPointer()->getName() << "\n";
errs() << "Visited Node (I) - " << N->getFuncPointer()->getName() << "\n";
for(DFInternalNode::successor_iterator i = N->successors_begin(),
e = N->successors_end(); i != e; ++i) {
/* Traverse the graph.
......@@ -401,7 +410,7 @@ public:
}
virtual void visit(DFLeafNode* N) {
errs() << "Visted Node (L) - " << N->getFuncPointer()->getName() << "\n";
errs() << "Visited Node (L) - " << N->getFuncPointer()->getName() << "\n";
}
};
/*
......
......@@ -71,15 +71,18 @@ namespace builddfg {
return false; //TODO: What does returning "false" mean?
}
const DFInternalNode *BuildDFG::getRoot() {
//TODO: Maybe make this const
DFInternalNode *BuildDFG::getRoot() {
return Root;
}
const BuildDFG::HandleToDFNode &BuildDFG::getHandleToDFNodeMap() {
//TODO: Maybe make this const
BuildDFG::HandleToDFNode &BuildDFG::getHandleToDFNodeMap() {
return HandleToDFNodeMap;
}
const BuildDFG::HandleToDFEdge &BuildDFG::getHandleToDFEdgeMap() {
//TODO: Maybe make this const
BuildDFG::HandleToDFEdge &BuildDFG::getHandleToDFEdgeMap() {
return HandleToDFEdgeMap;
}
......@@ -105,6 +108,28 @@ namespace builddfg {
return false;
}
// Returns true if instruction I is a visc query intrinsic, false otherwise
bool BuildDFG::isViscQueryIntrinsic(Instruction* I) {
if (IntrinsicInst* II = dyn_cast<IntrinsicInst>(I)) {
if (((II->getCalledFunction()->getName()).startswith("llvm.visc.get"))) {
// It is a visc query intrinsic
return true;
}
}
return false;
}
// Returns true if instruction I is a visc intrinsic, false otherwise
bool BuildDFG::isViscIntrinsic(Instruction* I) {
if (IntrinsicInst* II = dyn_cast<IntrinsicInst>(I)) {
if (((II->getCalledFunction()->getName()).startswith("llvm.visc"))) {
// It is a visc query intrinsic
return true;
}
}
return false;
}
// Handles all the createNodeXX visc intrinsics.
void BuildDFG::handleCreateNode(DFInternalNode* N, IntrinsicInst* II) {
bool isInternalNode = false;
......
......@@ -10,6 +10,8 @@
#define DEBUG_TYPE "DFG2LLVM"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/BuildDFG/BuildDFG.h"
using namespace llvm;
......@@ -29,22 +31,280 @@ namespace {
// Functions
public:
virtual bool runOnModule(Module &M) {
bool runOnModule(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<BuildDFG>();
}
};
// Visitor for Code generation traversal (tree traversal for now)
class CodeGenTraversal : public DFNodeVisitor {
private:
//Member variables
Module &M;
BuildDFG &DFG;
//Functions
void codeGen(DFInternalNode* N) {
}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<BuildDFG>();
// Code generation for leaf nodes
void codeGen(DFLeafNode* N) {
std::vector<IntrinsicInst *> IItoRemove;
std::vector<std::pair<IntrinsicInst *, Value *> > IItoReplace;
BuildDFG::HandleToDFNode Leaf_HandleToDFNodeMap;
// Get the function associated woth the dataflow node
Function *F = N->getFuncPointer();
// Go through all the instructions
for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
Instruction *I = &(*i);
// Leaf nodes should not contain VISC graph intrinsics or launch
assert(!BuildDFG::isViscLaunchIntrinsic(I) && "Launch intrinsic within a dataflow graph!");
assert(!BuildDFG::isViscGraphIntrinsic(I) && "VISC graph intrinsic within a leaf dataflow node!");
if (BuildDFG::isViscQueryIntrinsic(I)) {
IntrinsicInst* II = dyn_cast<IntrinsicInst>(I);
IntrinsicInst* ArgII;
DFNode* ArgDFNode;
/******************************************************************************
* Handle VISC Query intrinsics *
******************************************************************************/
switch (II->getIntrinsicID()) {
/**************************** llvm.visc.getNode() *****************************/
case Intrinsic::visc_getNode: {
// add mapping <intrinsic, this node> to the node-specific map
Leaf_HandleToDFNodeMap[II] = N;
IItoRemove.push_back(II);
}
break;
/************************* llvm.visc.getParentNode() **************************/
case Intrinsic::visc_getParentNode: {
// get the parent node of the arg node
// get argument node
ArgII = cast<IntrinsicInst>((II->getOperand(0))->stripPointerCasts());
// get the parent node of the arg node
ArgDFNode = Leaf_HandleToDFNodeMap[ArgII];
// Add mapping <intrinsic, parent node> to the node-specific map
// the argument node must have been added to the map, orelse the
// code could not refer to it
Leaf_HandleToDFNodeMap[II] = ArgDFNode;
IItoRemove.push_back(II);
}
break;
/*************************** llvm.visc.getNumDims() ***************************/
case Intrinsic::visc_getNumDims: {
// get node from map
// get the appropriate field
int numOfDim = Leaf_HandleToDFNodeMap[ArgII]->getNumOfDim();
IntegerType* IntTy = Type::getInt32Ty(getGlobalContext());
ConstantInt* numOfDimConstant = ConstantInt::getSigned(IntTy, (int64_t) numOfDim);
IItoReplace.push_back(std::make_pair(II,numOfDimConstant));
}
break;
/*********************** llvm.visc.getNodeInstanceID() ************************/
case Intrinsic::visc_getNodeInstanceID: {
ArgII = cast<IntrinsicInst>((II->getOperand(0))->stripPointerCasts());
ArgDFNode = Leaf_HandleToDFNodeMap[ArgII];
// A leaf node always has a parent
DFNode* ParentDFNode = DFG.getHandleToDFNodeMap()[ArgII];
// Get specified dimension
// (dim = 0) => x
// (dim = 1) => y
// (dim = 2) => z
ConstantInt * DimConstant = cast<ConstantInt>(II->getOperand(1));
int dim = (int) DimConstant->getSExtValue();
assert((dim >= 0) && (dim < 3) && "Invalid dimension argument");
// Argument of the function to be called
ArrayRef<Value *> Args(DimConstant);
// The following is to find which function to call
Function * OpenCLFunction;
int parentLevel = ParentDFNode->getLevel();
if (!parentLevel) {
// We only have one level in the hierarchy, but still need to
// specify a global id
assert((dim != 2) && "Invalid dimension argument");
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_global_id"), FT));
} else if (Leaf_HandleToDFNodeMap[ArgII] == Leaf_HandleToDFNodeMap[II]) {
// We are asking for this node's id with respect to its parent
// this is a local id call
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_local_id"), FT));
} else if (Leaf_HandleToDFNodeMap[ArgII] == N->getParent()) {
// We are asking for this node's parent's id with respect to its
// parent: this is a group id call
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_group_id"), FT));
} else {
assert(false && "Unable to translate this intrinsic");
}
CallInst* CI = CallInst::Create(OpenCLFunction, Args);
IItoReplace.push_back(std::make_pair(II,CI));
}
break;
/********************** llvm.visc.getNumNodeInstances() ***********************/
case Intrinsic::visc_getNumNodeInstances: {
//TODO: think about whether this is the best way to go
// there are hw specific registers. therefore it is good to have the intrinsic
// but then, why do we need to keep that info in the graph?
// (only for the kernel configuration during the call)
ArgII = cast<IntrinsicInst>((II->getOperand(0))->stripPointerCasts());
ArgDFNode = Leaf_HandleToDFNodeMap[ArgII];
// A leaf node always has a parent
DFNode* ParentDFNode = DFG.getHandleToDFNodeMap()[ArgII];
// Get specified dimension
ConstantInt * DimConstant = cast<ConstantInt>(II->getOperand(1));
int dim = (int) DimConstant->getSExtValue();
assert((dim >= 0) && (dim < 3) && "Invalid dimension argument");
// Argument of the function to be called
ArrayRef<Value *> Args(DimConstant);
// The following is to find which function to call
Function * OpenCLFunction;
int parentLevel = ParentDFNode->getLevel();
if (!parentLevel) {
// We only have one level in the hierarchy, thus the node
// instances are global_size (gridDim x blockDim)
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_global_size"), FT));
} else if (Leaf_HandleToDFNodeMap[ArgII] == Leaf_HandleToDFNodeMap[II]) {
// We are asking for this node's instances
// this is a local size (block dim) call
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_local_size"), FT));
} else if (Leaf_HandleToDFNodeMap[ArgII] == N->getParent()) {
// We are asking for this node's parent's instances
// this is a (global_size/local_size) (grid dim) call
FunctionType* FT =
FunctionType::get(Type::getInt32Ty(getGlobalContext()),
std::vector<Type*>(1, Type::getInt32Ty(getGlobalContext())),
false);
OpenCLFunction = cast<Function>
(M.getOrInsertFunction(StringRef("get_num_groups"), FT));
} else {
assert(false && "Unable to translate this intrinsic");
}
CallInst* CI = CallInst::Create(OpenCLFunction, Args);
IItoReplace.push_back(std::make_pair(II,CI));
}
break;
default:
assert(false && "Unknown VISC Intrinsic!");
break;
}
} else {
//TODO: how to handle address space qualifiers in load/store
}
}
//TODO:
// When to replace the uses?
// In which order is it safe to replace the instructions in
// IItoReplace?
// Probably in the reverse order in the vectors
// It is a good idea to have them in one vector and chech the type
// using dyn_cast in order to determine if we replace with inst or value
//TODO: maybe leave these instructions to be removed by a later DCE pass
for (std::vector<IntrinsicInst *>::iterator i = IItoRemove.begin();
i != IItoRemove.end(); ++i)
(*i)->eraseFromParent();
}
public:
// Constructor
CodeGenTraversal(Module &_M, BuildDFG &_DFG) : M(_M), DFG(_DFG) { }
virtual void visit(DFInternalNode* N) {
errs() << "Generating Code for Node (I) - " << N->getFuncPointer()->getName() << "\n";
codeGen(N);
errs() << "DONE" << "\n";
for(DFGraph::children_iterator i = N->getChildGraph()->begin(),
e = N->getChildGraph()->end(); i != e; ++i) {
DFNode* child = *i;
child->applyDFNodeVisitor(*this);
}
}
virtual void visit(DFLeafNode* N) {
errs() << "Generating Code for Node (L) - " << N->getFuncPointer()->getName() << "\n";
codeGen(N);
errs() << "DONE" << "\n";
}
};
bool DFG2LLVM::runOnModule(Module &M) {
// Get the BuildDFG Analysis Results:
// - Dataflow graph
// - Maps from i8* hansles to DFNode and DFEdge
BuildDFG &DFG = getAnalysis<BuildDFG>();
DFInternalNode *Root = DFG.getRoot();
// BuildDFG::HandleToDFNode &HandleToDFNodeMap = DFG.getHandleToDFNodeMap();
// BuildDFG::HandleToDFEdge &HandleToDFEdgeMap = DFG.getHandleToDFEdgeMap();
// Visitor for Code Generation Graph Traversal
CodeGenTraversal *CGTVisitor = new CodeGenTraversal(M, DFG);
// Initiate code generation for root DFNode
CGTVisitor->visit(Root);
return true;
}
} // End of namespace
char DFG2LLVM::ID = 0;
static RegisterPass<DFG2LLVM> X("DFG2LLVM", "Dataflow Graph to LLVM for nvptx Pass", false, true);
static RegisterPass<DFG2LLVM> X("DFG2LLVM",
"Dataflow Graph to LLVM for nvptx Pass",
false /* does not modify the CFG */,
true /* transformation, not just analysis */);
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