Files
SAPFOR/dvm/fdvm/trunk/fdvm/acc_rtc.cpp
2025-03-25 20:35:21 +03:00

391 lines
15 KiB
C++

#include "dvm.h"
#include "acc_data.h"
#include "calls.h"
//TMP:
extern symb_list *acc_call_list, *by_value_list;
// create comments of call procedures from each kernel in file _info.c
// if -FTN_Cuda option selected
void ACC_RTC_AddCalledProcedureComment(SgSymbol *symbK)
{
symb_list *sl;
int len = 0;
for (sl = acc_call_list; sl; sl = sl->next)
len = len + strlen(sl->symb->identifier()) + 1;
char *list_txt = new char[len + 1];
list_txt[0] = '\0';
for (sl = acc_call_list; sl; sl = sl->next)
{
strcat(list_txt, " ");
strcat(list_txt, sl->symb->identifier());
}
info_block->addComment(CalledProcedureComment(list_txt, symbK));
}
// complete rtc launch parameters from cuda-handlers
void ACC_RTC_CompleteAllParams()
{
for (unsigned fc = 0; fc < RTC_FCall.size(); ++fc)
{
SgFunctionCallExp *fCall = RTC_FKernelArgs[fc];
if (fCall->variant() == EXPR_LIST) // if Fortran CUDA
{
fCall = new SgFunctionCallExp(*createNewFunctionSymbol(""));
SgExpression *tmp = RTC_FKernelArgs[fc];
while (tmp)
{
fCall->addArg(*tmp->lhs());
tmp = tmp->rhs();
}
}
SgExpression *argList = RTC_FArgs[fc];
for (int k = 0; k < fCall->numberOfArgs(); ++k)
{
SgExpression *currArg = fCall->arg(k);
bool dontCast = false;
if (currArg->variant() == DEREF_OP)
currArg = currArg->lhs();
if (currArg->symbol() == NULL)
{
RTC_FCall[fc]->addArg(*new SgValueExp("<!!! NULL !!!>"));
argList = argList->rhs();
continue;
}
std::string tmpN = currArg->symbol()->identifier();
bool isarray = isSgArrayType(currArg->symbol()->type());
bool ispointer = isSgPointerType(currArg->symbol()->type());
bool notbyval = true;
symb_list *sl;
for (sl = by_value_list; sl; sl = sl->next)
{
if (strcmp(sl->symb->identifier(), currArg->symbol()->identifier()) == 0)
{
notbyval = false;
break;
}
}
bool isinuser = isInUsesListByChar(currArg->symbol()->identifier());
if (isarray || ispointer || notbyval && isinuser)
{
RTC_FCall[fc]->addArg(*new SgValueExp(""));
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_POINTER")));
RTC_FCall[fc]->addArg(*argList->lhs());
}
else
{
SgType *tmp = currArg->symbol()->type();
if (tmp->hasBaseType())
tmp->baseType();
unsigned UnFlag = ((SgDescriptType*)tmp)->modifierFlag() & BIT_UNSIGNED;
SgAttribute *attr = argList->lhs()->getAttribute(0);
bool toAdd = false;
if (attr != NULL)
{
if (attr->getAttributeType() == RTC_NOT_REPLACE)
RTC_FCall[fc]->addArg(*new SgValueExp(""));
else
toAdd = true;
}
else
toAdd = true;
if (toAdd)
{
if (options.isOn(C_CUDA))
RTC_FCall[fc]->addArg(*new SgValueExp(currArg->symbol()->identifier()));
else
{
// PGI adds to scalars n__V_ !!
std::string tmp = "n__V_";
tmp += aks_strlowr(currArg->symbol()->identifier());
RTC_FCall[fc]->addArg(*new SgValueExp(tmp.c_str()));
}
}
if (tmp->equivalentToType(C_Type(SgTypeChar())) || tmp->equivalentToType(SgTypeChar()))
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UCHAR")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_CHAR")));
}
else if (tmp->equivalentToType(C_Type(SgTypeInt())) || (tmp->equivalentToType(SgTypeInt())))
{
if (isSgDescriptType(tmp))
{
SgDescriptType *t = (SgDescriptType*)tmp;
int flag = t->modifierFlag();
if ((flag & BIT_LONG) != 0)
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULONG")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
}
else if ((flag & BIT_SHORT) != 0)
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_USHORT")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_SHORT")));
}
else
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UINT")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
}
}
else
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UINT")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
}
}
else if (tmp->equivalentToType(C_LongType()))
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULONG")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
}
else if (tmp->equivalentToType(C_LongLongType()))
{
if (UnFlag)
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULLONG")));
else
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LLONG")));
}
else if (tmp->equivalentToType(C_Type(SgTypeFloat())) || tmp->equivalentToType(SgTypeFloat()))
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_FLOAT")));
else if (tmp->equivalentToType(C_Type(SgTypeDouble())) || tmp->equivalentToType(SgTypeDouble()))
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_DOUBLE")));
else if (tmp->equivalentToType(indexTypeInKernel(rt_INT)))
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
else if (tmp->equivalentToType(indexTypeInKernel(rt_LONG)))
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
else if (tmp->equivalentToType(indexTypeInKernel(rt_LLONG)))
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LLONG")));
else if (tmp->equivalentToType(C_Derived_Type(s_cmplx)))
{
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_FLOAT_COMPLEX")));
SgSymbol *symb = createNewFunctionSymbol("real");
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
symb = createNewFunctionSymbol("imag");
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
dontCast = true;
}
else if (tmp->equivalentToType(C_Derived_Type(s_dcmplx)))
{
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_DOUBLE_COMPLEX")));
SgSymbol *symb = createNewFunctionSymbol("real");
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
symb = createNewFunctionSymbol("imag");
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
dontCast = true;
}
else
{
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UNKNOWN")));
fprintf(stderr, "Warning[-rtc]: unknown type with variant %d for kernel lauch\n", tmp->variant());
}
if (dontCast == false)
RTC_FCall[fc]->addArg(*new SgCastExp(*tmp, *argList->lhs()));
}
argList = argList->rhs();
}
}
RTC_FKernelArgs.clear();
RTC_FArgs.clear();
RTC_FCall.clear();
}
// convert unparse buffer for RTC call
char* _RTC_convertUnparse(const char* inBuf)
{
int count = 0;
for (unsigned i = 0; i < strlen(inBuf); ++i)
{
if (SpecialSymbols.find(inBuf[i]) != SpecialSymbols.end())
count += strlen(SpecialSymbols[inBuf[i]]);
}
std::string strBuf = "";
for (unsigned i = 0; i < strlen(inBuf); ++i)
{
if (SpecialSymbols.find(inBuf[i]) != SpecialSymbols.end())
{
const char *tmp = SpecialSymbols[inBuf[i]];
for (unsigned k1 = 0; k1 < strlen(tmp); ++k1)
strBuf.push_back(tmp[k1]);
}
else
strBuf.push_back(inBuf[i]);
}
strBuf += "#undef dcmplx2\\n\"\n\"#undef cmplx2\\n";
char *newBuf = new char[strlen(strBuf.c_str()) + 1];
strcpy(newBuf, strBuf.c_str());
return newBuf;
}
// convert cuda kernel to static const char*
void ACC_RTC_ConvertCudaKernel(SgStatement *cuda_kernel, const char *kernelName)
{
if (cuda_kernel != NULL)
{
cuda_kernel->addComment("#define dcmplx2 Complex<double>\n#define cmplx2 Complex<float>\nextern \"C\"\n");
char *buf = copyOfUnparse(UnparseBif_Char(cuda_kernel->thebif, C_LANG));
char *newBuf = _RTC_convertUnparse(buf);
SgPointerType *arrType = new SgPointerType(*C_Type(SgTypeChar()));
SgSymbol *cuda_kernel_code = new SgSymbol(VARIABLE_NAME, kernelName, arrType, mod_gpu);
SgStatement *decl = makeSymbolDeclarationWithInit(cuda_kernel_code, new SgValueExp(newBuf));
decl->addDeclSpec(BIT_CONST);
decl->addDeclSpec(BIT_STATIC);
cuda_kernel->insertStmtBefore(*decl);
if(acc_call_list)
{
symb_list **call_list = new (symb_list *);
*call_list = acc_call_list;
decl->addAttribute(RTC_CALLS, (void*)call_list, sizeof(symb_list *));
}
cuda_kernel->deleteStmt();
delete[] buf;
}
}
static symb_list *_RTC_addCalledToList(symb_list *call_list, graph_node *gnode)
{
edge *gedge;
for (gedge = gnode->to_called; gedge; gedge = gedge->next)
if(gedge->to->st_header)
{ call_list = AddNewToSymbList(call_list, gedge->to->symb);
call_list = _RTC_addCalledToList(call_list, gedge->to);
}
return call_list;
}
symb_list *ACC_RTC_ExpandCallList(symb_list *call_list)
{
symb_list *sl;
for (sl = call_list; sl; sl = sl->next)
{
if (!ATTR_NODE(sl->symb))
continue;
call_list = _RTC_addCalledToList(call_list, GRAPHNODE(sl->symb));
}
return call_list;
}
char* _RTC_PrototypesForKernel(symb_list *call_list)
{
SgStatement *st = NULL;
symb_list *sl = call_list;
st = FunctionPrototype(GRAPHNODE(sl->symb)->st_copy->symbol());
st->addDeclSpec(BIT_CUDA_DEVICE);
st->addDeclSpec(BIT_STATIC);
st->addComment("#define dcmplx2 Complex<double>\n#define cmplx2 Complex<float>\n");
char *buffer = copyOfUnparse(UnparseBif_Char(st->thebif, C_LANG));
for (sl = call_list->next; sl; sl = sl->next)
{
st = FunctionPrototype(GRAPHNODE(sl->symb)->st_copy->symbol());
st->addDeclSpec(BIT_CUDA_DEVICE);
st->addDeclSpec(BIT_STATIC);
char *unp_buf = UnparseBif_Char(st->thebif, C_LANG);
char *buf = new char[strlen(buffer) + strlen(unp_buf) + 1];
strcpy(buf, buffer);
strcat(buf, unp_buf);
delete[] buffer;
buffer = buf;
}
return (buffer);
}
void _RTC_UnparsedFunctionsToKernelConst(SgStatement *stmt)
{
if (CALLED_FUNCTIONS(stmt) == NULL)
return;
symb_list *call_list = *CALLED_FUNCTIONS(stmt);
graph_node * gnode = NULL;
char *buffer = _RTC_PrototypesForKernel(call_list);
for (; call_list; call_list = call_list->next)
{ SgStatement *stmt, *end_st;
gnode = GRAPHNODE(call_list->symb);
end_st = gnode->st_copy_first->lastNodeOfStmt()->lexNext();
stmt = gnode->st_copy;
while (stmt != end_st) //st_copy,...,st_copy_first
{
char *unp_buf = UnparseBif_Char(stmt->thebif, C_LANG);
char *buf = new char[strlen(unp_buf) + strlen(buffer) + 1];
//buf[0] = '\0';
strcpy(buf, buffer);
strcat(buf, unp_buf);
delete[] buffer;
buffer = buf;
stmt = stmt->lastNodeOfStmt()->lexNext();
}
}
buffer = _RTC_convertUnparse(buffer);
char *kernel_buf = ((SgValueExp *)((SgVarDeclStmt *)stmt)->initialValue(0))->stringValue();
char *allBuf = new char[strlen(kernel_buf) + strlen(buffer) + 1];
strcpy(allBuf, buffer);
strcat(allBuf, kernel_buf);
((SgVarDeclStmt *)stmt)->setInitialValue(0, *new SgValueExp(allBuf));
delete[] kernel_buf;
delete[] buffer;
}
void ACC_RTC_AddFunctionsToKernelConsts(SgStatement *first_kernel_const)
{
SgStatement *stmt = mod_gpu, *next = NULL;
for (stmt = first_kernel_const; stmt; stmt = stmt->lexNext())
_RTC_UnparsedFunctionsToKernelConst(stmt);
stmt = mod_gpu;
next = mod_gpu->lexNext();
// extracting function copies
//while(next->variant() != VAR_DECL)
while (next != first_kernel_const)
{
stmt = next;
next = next->lastNodeOfStmt()->lexNext();
stmt->extractStmt();
}
}