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

Transformation of non-void functions to void in dfg2llvm_nvptx pass.

(more testing required).
parent e9d3cf98
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,8 @@
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/BuildDFG/BuildDFG.h"
#include <sstream>
using namespace llvm;
using namespace builddfg;
......@@ -58,6 +60,10 @@ namespace {
ValueMap<Function*, Function*> FMap;
//Functions
void addReturnValueArgs(Function* F);
Argument* getArgumentFromEnd(Function* F, unsigned offset);
Argument* getArgumentAt(Function* F, unsigned offset);
void codeGen(DFInternalNode* N);
void codeGen(DFLeafNode* N);
......@@ -104,27 +110,29 @@ namespace {
// Get the function associated with the dataflow node
Function *F = N->getFuncPointer();
// Look up if we have visited this function before. If we have, then just
// get the cloned function pointer from FMap. Otherwise, create the cloned
// function and add it to the FMap.
Function *F_nvptx;
if(FMap.count(F)) {
F_nvptx = FMap[F];
}
else {
// Clone the function
ValueToValueMapTy VMap;
F_nvptx = CloneFunction(F, VMap, true);
// Look up if we have visited this function before. If we have, then just
// get the cloned function pointer from FMap. Otherwise, create the cloned
// function and add it to the FMap.
Function *F_nvptx;
if(FMap.count(F)) {
F_nvptx = FMap[F];
}
else {
// Clone the function
ValueToValueMapTy VMap;
F_nvptx = CloneFunction(F, VMap, true);
// Insert the cloned function into the module
M.getFunctionList().push_back(F_nvptx);
// Insert the cloned function into the module
M.getFunctionList().push_back(F_nvptx);
DEBUG(errs() << *F_nvptx->getType());
DEBUG(errs() << *F_nvptx);
DEBUG(errs() << *F_nvptx->getType());
DEBUG(errs() << *F_nvptx);
//Add old func: new func pair to the FMap
FMap[F] = F_nvptx;
}
//Add old func: new func pair to the FMap
FMap[F] = F_nvptx;
}
addReturnValueArgs(F_nvptx);
// Go through all the instructions
for (inst_iterator i = inst_begin(F_nvptx), e = inst_end(F_nvptx); i != e; ++i) {
......@@ -373,6 +381,121 @@ namespace {
return true;
}
std::string convertInt(int number) {
std::stringstream ss;//create a stringstream
ss << number;//add number to the stream
return ss.str();//return a string with the contents of the stream
}
void findReturnInst(Function* F, std::vector<ReturnInst *> & ReturnInstVec) {
for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
Instruction *I = &(*i);
ReturnInst* RI = dyn_cast<ReturnInst>(I);
if (RI) {
ReturnInstVec.push_back(RI);
}
}
}
void CodeGenTraversal::addReturnValueArgs(Function* F) {
// FIXME: Maybe do that using the Node?
StructType* FRetTy = cast<StructType>(F->getReturnType());
assert(FRetTy && "Return Type is NULL, it should be a struct");
// Keeps return statements, because we will need to replace them
std::vector<ReturnInst *> RItoRemove;
findReturnInst(F, RItoRemove);
// Check for { } return struct, which means that the function returns void
if (FRetTy->getNumElements() == 0) {
DEBUG(errs() << "\tFunction output struct is void\n");
DEBUG(errs() << "\tNo parameters added\n");
// Replacing return statements with others returning void
for (std::vector<ReturnInst *>::iterator i = RItoRemove.begin(),
e = RItoRemove.end(); i != e; ++i) {
ReturnInst::Create((F->getContext()), 0, (*i));
(*i)->eraseFromParent();
}
DEBUG(errs() << "\tChanged return statements to return void\n");
return;
}
// The struct has return values that need to be converted to parameters
int initialNumParams = F->arg_size();
// Create the extra parameters with appropriate pointer types
for (unsigned i=0; i < FRetTy->getNumElements(); i++) {
Type* FieldType = FRetTy->getElementType(i);
Type* ArgType = FieldType->getPointerTo(); //TODO: AddressSpace
new Argument(ArgType, "ret_arg_" + convertInt(i), F);
}
DEBUG(errs() << "\tCreated parameters\n");
// Create the argument type list with added argument types
std::vector<Type*> ArgTypes;
for(Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
ai != ae; ++ai) {
ArgTypes.push_back(ai->getType());
}
// Find where the new parameters start in the header
Function::arg_iterator ai, ae;
int check = 0;
for (ai = F->arg_begin(), ae = F->arg_end();
ai != ae; ++ai) {
if (ai->getName().startswith("ret_arg_")) break;
check++;
}
DEBUG(errs() << "\tcheck = " << check << "\tinitialNumParams = " << initialNumParams << "\n");
assert(check == initialNumParams);
DEBUG(errs() << "\tReplacing Return statements\n");
// Replace return statements with extractValue and store instructions
for (std::vector<ReturnInst *>::iterator rii = RItoRemove.begin(),
rie = RItoRemove.end(); rii != rie; ++rii) {
ReturnInst* RI = (*rii);
Value* RetVal = RI->getReturnValue();
// assert(RetVal && "Return value should not be null at this point");
// StructType* RetType = cast<StructType>(RetVal->getType());
// assert(RetType && "Return type is not a struct");
Function::arg_iterator ret_ai = ai;
for (unsigned i=0; i < FRetTy->getNumElements(); i++, ++ret_ai) {
std::vector<unsigned> IndexList;
IndexList.push_back(i);
ExtractValueInst* EI = ExtractValueInst::Create(RetVal, IndexList, Twine(""), RI);
// StoreInst* SI = new StoreInst(EI, &(*ret_ai), RI);
new StoreInst(EI, &(*ret_ai), RI);
}
ReturnInst::Create((F->getContext()), 0, RI);
RI->eraseFromParent();
}
DEBUG(errs() << "\tReplaced return statements\n");
// Adding new arguments to the function argument list, would not change the
// function type. We need to change the type of this function to reflect the
// added arguments
Type* VoidRetType = Type::getVoidTy(F->getContext());
FunctionType* FTy = FunctionType::get(VoidRetType, ArgTypes, F->isVarArg());
PointerType* PTy = PointerType::get(FTy, cast<PointerType>(F->getType())->getAddressSpace());
// Change the function type
F->mutateType(PTy);
}
} // End of namespace
char DFG2LLVM_NVPTX::ID = 0;
......
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