diff --git a/llvm/.svnignore b/llvm/.svnignore new file mode 100644 index 0000000000000000000000000000000000000000..52cf5b958f2d38c10c725ba9fd58d182ee54ffea --- /dev/null +++ b/llvm/.svnignore @@ -0,0 +1,2 @@ +Debug+Asserts +*.inc diff --git a/llvm/include/llvm/BuildDFG/BuildDFG.h b/llvm/include/llvm/BuildDFG/BuildDFG.h index 0d8bbbe2e6ed112cf9101a67311f823a8feafda8..c17f9ff743d937d70eca0895006d461c94b060b1 100644 --- a/llvm/include/llvm/BuildDFG/BuildDFG.h +++ b/llvm/include/llvm/BuildDFG/BuildDFG.h @@ -53,6 +53,7 @@ namespace builddfg { static bool isViscGraphIntrinsic(Instruction * I); static bool isViscQueryIntrinsic(Instruction* I); static bool isViscIntrinsic(Instruction* I); + static bool isTypeCongruent(Type *L, Type *R); //TODO: Maybe make these fields const DFInternalNode *getRoot(); diff --git a/llvm/include/llvm/IR/DFGraph.h b/llvm/include/llvm/IR/DFGraph.h index d8fc6c96a7d10bc47ac7e3fa7bbec326b2f87a3a..ae0bcd4f40d88fdf1d4fa440af30071a09578dbd 100644 --- a/llvm/include/llvm/IR/DFGraph.h +++ b/llvm/include/llvm/IR/DFGraph.h @@ -26,6 +26,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/GraphWriter.h" @@ -54,6 +55,7 @@ private: DFNodeListType ChildrenList; ///< List of children Dataflow Nodes DFEdgeListType DFEdgeList; ///< List of Dataflow edges among children + public: DFGraph(DFInternalNode* P) { // ChildrenList.push_back(llvm::DFLeafNode::Create(NULL, NULL, NULL)); @@ -128,6 +130,13 @@ public: class DFNode { +public: + // Discriminator for LLVM-style RTTI (dyn_cast et al.) + enum DFNodeKind { + InternalNode, + LeafNode + }; + private: typedef std::vector<DFNode*> DFNodeListType; typedef std::vector<DFEdge*> DFEdgeListType; @@ -147,8 +156,10 @@ private: DFEdgeListType OutDFEdges; ///< List of outgoing edges i.e., ///< DFEdges originating from this DFNode to ///< successor DFNodes + Type* OutputType; ///< Output Type int Level; ///< Distance to the top-level DFNode in the ///< hierarchy + const DFNodeKind Kind; ///< Kind of Node Internal/Leaf public: // Iterators @@ -213,13 +224,24 @@ public: //===--------------------------------------------------------------------===// // Functions + + DFNodeKind getKind() const { + return Kind; + } + DFNode(IntrinsicInst* _II, Function* _FuncPointer, DFNode* _Parent, - int _NumOfDim, std::vector<Value*> _DimLimits) : II(_II), + int _NumOfDim, std::vector<Value*> _DimLimits, DFNodeKind _K): II(_II), FuncPointer(_FuncPointer), Parent(_Parent), NumOfDim(_NumOfDim), - DimLimits(_DimLimits) { + DimLimits(_DimLimits), Kind(_K) { + + OutputType = FuncPointer->getFunctionType()->getReturnType(); Level = (_Parent) ? _Parent->getLevel() + 1 : 0 ; } + Type* getOutputType() { + return OutputType; + } + void addSuccessor(DFNode* N) { Successors.push_back(N); } @@ -259,14 +281,19 @@ public: class DFInternalNode : public DFNode { private: - DFGraph* childGraph; + DFGraph* childGraph; ///< Pointer to dataflow graph // Constructor DFInternalNode(IntrinsicInst* II, Function* FuncPointer, DFNode* Parent, int NumOfDim, std::vector<Value*> DimLimits) : - DFNode(II, FuncPointer, Parent, NumOfDim, DimLimits) { + DFNode(II, FuncPointer, Parent, NumOfDim, DimLimits, + InternalNode) { + childGraph = new DFGraph(this); - //childGraph->addChildDFNode(DFLeafNode::Create(NULL, NULL, this)); + + // Internal Node output type must always be a struct type. + assert(isa<StructType>(getOutputType()) + && "Invalid return type of internal dataflow node"); } public: @@ -276,6 +303,10 @@ public: return new DFInternalNode(II, FuncPointer, Parent, NumOfDim, DimLimits); } + static bool classof(const DFNode *N) { + return N->getKind() == InternalNode; + } + void addChildToDFGraph(DFNode* N) { childGraph->addChildDFNode(N); } @@ -298,7 +329,7 @@ private: // Constructor DFLeafNode(IntrinsicInst* II, Function* FuncPointer, DFNode* Parent, int NumOfDim = 0, std::vector<Value*> DimLimits = std::vector<Value*>()) - : DFNode(II, FuncPointer, Parent, NumOfDim, DimLimits) {} + : DFNode(II, FuncPointer, Parent, NumOfDim, DimLimits, LeafNode) {} public: @@ -308,6 +339,10 @@ public: return new DFLeafNode(II, FuncPointer, Parent, NumOfDim, DimLimits); } + static bool classof(const DFNode *N) { + return N->getKind() == LeafNode; + } + void applyDFNodeVisitor(DFNodeVisitor &V); /*virtual*/ // void applyDFEdgeVisitor(DFEdgeVisitor &V); /*virtual*/ @@ -463,7 +498,7 @@ public: //}; */ -/* + template <> struct GraphTraits<DFNode*> { typedef DFNode NodeType; typedef typename DFNode::successor_iterator ChildIteratorType; @@ -511,16 +546,16 @@ struct DOTGraphTraits<DFGraph*> : public DefaultDOTGraphTraits { return N->getFuncPointer()->getName(); } - void addCustomGraphFeatures(DFGraph* G, GraphWriter<DFGraph*> &GW) { - + static void addCustomGraphFeatures(DFGraph* G, GraphWriter<DFGraph*> &GW) { + } }; -*/ + void viewDFGraph(DFGraph *G) { - //llvm::WriteGraph(G, "DataflowGrpah"); - //llvm::ViewGraph(G, "DataflowGraph"); + llvm::WriteGraph(G, "DataflowGrpah"); + llvm::ViewGraph(G, "DataflowGraph"); } diff --git a/llvm/include/llvm/IR/IntrinsicsVISC.td b/llvm/include/llvm/IR/IntrinsicsVISC.td index 8028525a38c4d858f9a512a60b5ca23758e9b283..3d78b189606b6675fc00fc48f56e8678c9ec2b8f 100644 --- a/llvm/include/llvm/IR/IntrinsicsVISC.td +++ b/llvm/include/llvm/IR/IntrinsicsVISC.td @@ -49,11 +49,11 @@ let TargetPrefix = "visc" in { []>; /* Create dataflow edge intrinsic - - * i8* llvm.visc.createEdge(i8*, i8*, function*, function*, instr*); + * i8* llvm.visc.createEdge(i8*, i8*, i1, i32, i32); */ def int_visc_createEdge : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, - llvm_i1_ty, llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty], []>; + llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], + []>; /* Find associated dataflow node intrinsic - * i8* llvm.visc.getNode(); diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index af86eb88788b2532dbb1120ba8084e429f6cf425..8ecb4f43457825e591b913fac1de630f18b36af0 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -222,7 +222,7 @@ uint64_t Type::getArrayNumElements() const { } unsigned Type::getVectorNumElements() const { - if (const SymVectorType *SVT = dyn_cast<SymVectorType>(this)) + if (isa<SymVectorType>(this)) return 4; // FIXME: This is just to avoid error in current case. Add assert here. return cast<VectorType>(this)->getNumElements(); } diff --git a/llvm/lib/Transforms/BuildDFG/BuildDFG.cpp b/llvm/lib/Transforms/BuildDFG/BuildDFG.cpp index 0c9d907a0b0f3dcbe150e857fbc615edc2dc36ba..fbf30f87ac7e7bee2d445c326d9aee0fb17e645b 100644 --- a/llvm/lib/Transforms/BuildDFG/BuildDFG.cpp +++ b/llvm/lib/Transforms/BuildDFG/BuildDFG.cpp @@ -23,7 +23,7 @@ namespace builddfg { bool BuildDFG::runOnModule(Module &M) { - Function* f; // Root function, initialized later + Function* F; // Root function, initialized later bool foundRootFunction = false; // Loop over all of the global variables @@ -36,7 +36,7 @@ namespace builddfg { if((i->getName()).equals("llvm.visc.root")) { errs() << "----------- Found Root Function -------------\n\n"; foundRootFunction = true; - f = cast<Function>(i->getOperand(0)); + F = cast<Function>(i->getOperand(0)); } } @@ -44,7 +44,7 @@ namespace builddfg { // Root function has been initialized from this point on. - errs() << "-------- Searching for launch site ----------\n"; + /*errs() << "-------- Searching for launch site ----------\n"; bool foundLaunchSite = false; IntrinsicInst* II; @@ -63,8 +63,8 @@ namespace builddfg { // Intrinsic Instruction has been initialized from this point on. - Function* F = cast<Function>((II->getOperand(0))->stripPointerCasts()); - Root = DFInternalNode::Create(II, F); + Function* F = cast<Function>((II->getOperand(0))->stripPointerCasts());*/ + Root = DFInternalNode::Create(NULL, F); BuildGraph(Root, F); viewDFGraph(Root->getChildGraph()); @@ -130,6 +130,18 @@ namespace builddfg { return false; } + // Two types are "congruent" if they are identical, or if they are both + // pointer types with different pointee types and the same address space. + bool BuildDFG::isTypeCongruent(Type* L, Type* R) { + if(L == R) + return true; + PointerType *PL = dyn_cast<PointerType>(L); + PointerType *PR = dyn_cast<PointerType>(R); + if (!PL || !PR) + return false; + return PL->getAddressSpace() == PR->getAddressSpace(); + } + // Handles all the createNodeXX visc intrinsics. void BuildDFG::handleCreateNode(DFInternalNode* N, IntrinsicInst* II) { bool isInternalNode = false; @@ -182,20 +194,42 @@ namespace builddfg { bool EdgeType = !cast<ConstantInt>(II->getOperand(2))->isZero(); - int SourcePosition = - (int) cast<ConstantInt>(II->getOperand(3))->getSExtValue(); - int DestPosition = - (int) cast<ConstantInt>(II->getOperand(4))->getSExtValue(); + unsigned int SourcePosition = cast<ConstantInt>(II->getOperand(3))->getZExtValue(); + unsigned int DestPosition = cast<ConstantInt>(II->getOperand(4))->getZExtValue(); + + Type *SrcTy, *DestTy; + + // Get destination type + FunctionType *FT = DestDF->getFuncPointer()->getFunctionType(); + assert((FT->getNumParams() > DestPosition) + && "Invalid argument number for destination dataflow node!"); + DestTy = FT->getParamType(DestPosition); + + // Get source type + if(isa<DFInternalNode>(SrcDF)) { + // For Internal node, get the correct element type from the struct type + StructType* OutTy = cast<StructType>(SrcDF->getOutputType()); + assert((OutTy->getNumElements() > SourcePosition) + && "Invalid argument number for source dataflow node!"); + SrcTy = OutTy->getElementType(SourcePosition); + } + else { + // For Leaf node, there is just one outgoing edge + assert((SourcePosition == 0) + && "Invalid argument number for source dataflow node!"); + SrcTy = SrcDF->getOutputType(); + } - BitCastInst* BitCastI = cast<BitCastInst>((II->getOperand(5))->stripPointerCasts()); - Type* ArgType = BitCastI->getOperand(0)->getType(); + // check if the types are compatible + assert(isTypeCongruent(SrcTy, DestTy) + && "Source and destination type of edge do not match"); DFEdge* newDFEdge = DFEdge::Create(SrcDF, DestDF, EdgeType, SourcePosition, DestPosition, - ArgType); + DestTy); HandleToDFEdgeMap[II] = newDFEdge; diff --git a/llvm/lib/Transforms/BuildDFG/Makefile b/llvm/lib/Transforms/BuildDFG/Makefile index a1a9f46b9aa813533bd72ee8a0c4f0fec23e103f..870df19c30eaafd0471ebfcc5f45999cba93c0ed 100644 --- a/llvm/lib/Transforms/BuildDFG/Makefile +++ b/llvm/lib/Transforms/BuildDFG/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../../ LIBRARYNAME = LLVMBuildDFG -#LOADABLE_MODULE = 1 +LOADABLE_MODULE = 1 #SHARED_LIBRARY = 1 #BUILD_ARCHIVE = 1 #USEDLIBS = diff --git a/llvm/lib/Transforms/DFG2LLVM_X86/CMakeLists.txt b/llvm/lib/Transforms/DFG2LLVM_X86/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..70c3b1ddb1ba135359bf5552e344e756fb22216e --- /dev/null +++ b/llvm/lib/Transforms/DFG2LLVM_X86/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_loadable_module( LLVMBuildDFG + DFG2LLVM_X86.cpp + ) diff --git a/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp b/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee93bb926380dab7854dfc4da5bda20ca8c026fb --- /dev/null +++ b/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.cpp @@ -0,0 +1,342 @@ +//=== DFG2LLVM_X86.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 "DFG2LLVM_X86" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/InstIterator.h" + +#include "llvm/BuildDFG/BuildDFG.h" + +using namespace llvm; +using namespace builddfg; + +//STATISTIC(IntrinsicCounter, "Counts number of visc intrinsics greeted"); + +namespace { + // DFG2LLVM_X86 - The first implementation. + struct DFG2LLVM_X86 : public ModulePass { + static char ID; // Pass identification, replacement for typeid + DFG2LLVM_X86() : ModulePass(ID) {} + + private: + // Member variables + + // Functions + + public: + 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 codeGen(DFLeafNode* N); + 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"; + } + + }; + + class SuccessorTraversal : public DFNodeVisitor { + + private: + // Member Variables + // Functions + public: + // Constructor + SuccessorTraversal(Module &_M, BuildDFG &_DFG) : M(_M), DFG(_DFG) {} + + virtual void visit(DFInternalNode* 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. + * Choose the kind of traversal we want + * Do we do a DAG kind of traversal? + */ + } + } + + virtual void visit(DFLeafNode* N) { + errs() << "Visited Node (L) - " << N->getFuncPointer()->getName() << "\n"; + } + + }; + + bool DFG2LLVM_X86::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; + } + + void CodeGenTraversal::codeGen(DFInternalNode* N) { + std::vector<IntrinsicInst*> IItoRemove; + std::vector<std::pair<IntrinsicInst*, Value*>> IITtoReplace; + + + } + + // Code generation for leaf nodes + void CodeGenTraversal::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 = 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->getParent(); + IItoRemove.push_back(II); + } + break; +/*************************** llvm.visc.getNumDims() ***************************/ + case Intrinsic::visc_getNumDims: { + // get node from map + // get the appropriate field + ArgII = cast<IntrinsicInst>((II->getOperand(0))->stripPointerCasts()); + 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(); + + } + +} // End of namespace + +char DFG2LLVM_X86::ID = 0; +static RegisterPass<DFG2LLVM_X86> X("DFG2LLVM_X86", + "Dataflow Graph to LLVM for X86 backend", + false /* does not modify the CFG */, + true /* transformation, not just analysis */); + diff --git a/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.exports b/llvm/lib/Transforms/DFG2LLVM_X86/DFG2LLVM_X86.exports new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/llvm/lib/Transforms/DFG2LLVM_X86/Makefile b/llvm/lib/Transforms/DFG2LLVM_X86/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0451d134d6bbb870704a0c1b004810cb58bce61c --- /dev/null +++ b/llvm/lib/Transforms/DFG2LLVM_X86/Makefile @@ -0,0 +1,17 @@ +##===- lib/Transforms/BuildDFG/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../ +LIBRARYNAME = LLVMDFG2LLVM_X86 +#LOADABLE_MODULE = 1 +#SHARED_LIBRARY = 1 +BUILD_ARCHIVE = 1 +#USEDLIBS = + +include $(LEVEL)/Makefile.common