in_list objectsAllocated(SgStatement *statement, StopCond stopCond) { in_list objs; SgStatement *parent; do { #if 0 in_list::iterator startOfCurrent = objs.end(); #endif parent = isSgStatement(statement->get_parent()); //cout << "parent = " << parent << endl; ROSE_ASSERT(parent); in_list blockObjs = blockObjectsAllocated(parent, statement); objs.insert(objs.end(), blockObjs.begin(), blockObjs.end()); #if 0 switch (parent->variantT()) { case V_SgBasicBlock: { SgBasicBlock *b = isSgBasicBlock(parent); ROSE_ASSERT(b); SgStatementPtrList &stmts = b->get_statements(); for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { if (*i == statement) break; addStmtVarsIfAny(objs, startOfCurrent, *i); } } break; case V_SgForStatement: { SgForStatement *fs = isSgForStatement(parent); SgStatementPtrList &stmts = fs->get_init_stmt(); bool done = false; if (!omitInit) { for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { if (*i == statement) { done = true; break; } addStmtVarsIfAny(objs, startOfCurrent, *i); } } if (!done) { if (fs->get_test() != statement) { addStmtVarsIfAny(objs, startOfCurrent, fs->get_test()); } } } break; default: break; } #endif statement = parent; } while (!stopCond(parent)); return objs; }
void MintCudaMidend::lowerMinttoCuda(SgSourceFile* file) { //Searches mint pragmas, and performs necessary transformation //We also check the mint pragmas syntactically //At this point, we only care parallel regions and for loops //But do not process forloops at this point (note that this is bottom-up) //We process forloops when we see a parallel region pragma because they are always //inside of a parallel region. //TODO: Sometimes a forloop is merged with a parallel region. Need to handle these. ROSE_ASSERT(file != NULL); //replaces all the occurrences of mint parallel with omp parallel replaceMintParallelWithOmpParallel(file); replaceMintForWithOmpFor(file); //adds the private and first private into private clause explicitly patchUpPrivateVariables(file); //uses ROSE's patchUpFirstprivateVariables(file); //uses ROSE's //insert openmp specific headers //insertRTLHeaders(file); //check if mint pragma declarations are correct mintPragmasFrontendProcessing(file); //the map has the mapping from the host variables to device variables //where we copy the data Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(file, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); switch (node->variantT()) { case V_SgOmpParallelStatement: { //first we handle data transfer pragmas MintHostSymToDevInitMap_t hostToDevVars; processDataTransferPragmas(node, hostToDevVars); #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Mint Parallel Statement" << endl << endl; #endif MintCudaMidend::transOmpParallel(node, hostToDevVars); break; } case V_SgOmpTaskStatement: { //transOmpTask(node); break; } case V_SgOmpForStatement: { //cout << "INFO-mint: Omp For Statement (skipped processing it)" << endl; //LoweringToCuda::transOmpFor(node); //OmpSupport::transOmpFor(node); break; } case V_SgOmpBarrierStatement: { #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Omp Barrier Statement" << endl; #endif transOmpBarrierToCudaBarrier(node); break; } case V_SgOmpFlushStatement: { cout << " INFO:Mint: Processing Omp Flush Statement" << endl; transOmpFlushToCudaBarrier(node); break; } case V_SgOmpThreadprivateStatement: { //transOmpThreadprivate(node); break; } case V_SgOmpTaskwaitStatement: { //transOmpTaskwait(node); break; } case V_SgOmpSingleStatement: { //TODO: we need to check if the loop body becomes a cuda kernel or not. MintCudaMidend::transOmpSingle(node); break; } case V_SgOmpMasterStatement: { //TODO: we need to check if the loop body becomes a cuda kernel or not. MintCudaMidend::transOmpMaster(node); break; } case V_SgOmpAtomicStatement: { //transOmpAtomic(node); break; } case V_SgOmpOrderedStatement: { //transOmpOrdered(node); break; } case V_SgOmpCriticalStatement: { //transOmpCritical(node); break; } default: { //This is any other statement in the source code which is not omp pragma //cout<< node->unparseToString()<<" at line:"<< (node->get_file_info())->get_line()<<endl; // do nothing here } }// switch } #if 0 //3. Special handling for files with main() // rename main() to user_main() SgFunctionDeclaration * mainFunc = findMain(cur_file); if (mainFunc) { renameMainToUserMain(mainFunc); } #endif }
void MPI_Code_Generator::lower_xomp (SgSourceFile* file) { ROSE_ASSERT(file != NULL); Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(file, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); //debug the order of the statements // cout<<"Debug lower_omp(). stmt:"<<node<<" "<<node->class_name() <<" "<< node->get_file_info()->get_line()<<endl; switch (node->variantT()) { #if 0 case V_SgOmpParallelStatement: { // check if this parallel region is under "omp target" SgNode* parent = node->get_parent(); ROSE_ASSERT (parent != NULL); if (isSgBasicBlock(parent)) // skip the padding block in between. parent= parent->get_parent(); if (isSgOmpTargetStatement(parent)) transOmpTargetParallel(node); else transOmpParallel(node); break; } case V_SgOmpForStatement: case V_SgOmpDoStatement: { // check if the loop is part of the combined "omp parallel for" under the "omp target" directive // TODO: more robust handling of this logic, not just fixed AST form bool is_target_loop = false; SgNode* parent = node->get_parent(); ROSE_ASSERT (parent != NULL); // skip a possible BB between omp parallel and omp for, especially when the omp parallel has multiple omp for loops if (isSgBasicBlock(parent)) parent = parent->get_parent(); SgNode* grand_parent = parent->get_parent(); ROSE_ASSERT (grand_parent != NULL); if (isSgOmpParallelStatement (parent) && isSgOmpTargetStatement(grand_parent) ) is_target_loop = true; if (is_target_loop) { // transOmpTargetLoop (node); // use round-robin scheduler for larger iteration space and better performance transOmpTargetLoop_RoundRobin(node); } else { transOmpLoop(node); } break; } #endif // transform combined "omp target parallel for", represented as separated three directives: omp target, omp parallel, and omp for case V_SgOmpForStatement: { SgOmpTargetStatement * omp_target; SgOmpParallelStatement* omp_parallel; if (isCombinedTargetParallelFor (isSgOmpForStatement(node),&omp_target, &omp_parallel )) { transOmpTargetParallelLoop (isSgOmpForStatement(node)); } break; } case V_SgOmpTargetStatement: { SgOmpTargetStatement* t_stmt = isSgOmpTargetStatement(node); ROSE_ASSERT (t_stmt != NULL); SgStatement* body_stmt = t_stmt->get_body(); SgBasicBlock * body_block = isSgBasicBlock (body_stmt); // transOmpTarget(node); if (isMPIAllBegin (t_stmt)) { // move all body statements to be after omp target if (body_block != NULL) { stripOffBasicBlock (body_block, t_stmt); } else { //TODO: ideally, the body_stmt should be normalized to be a BB even it is only a single statement removeStatement (body_stmt); insertStatementAfter (t_stmt, body_stmt, false); } // remove the pragma stmt after the translation removeStatement (t_stmt); } else if (isMPIMasterBegin (t_stmt)) { transMPIDeviceMaster (t_stmt); } else { // other target directive with followed omp parallel for will be handled when parallel for is translated // cerr<<"Error. Unhandled target directive:" <<t_stmt->unparseToString()<<endl; //ROSE_ASSERT (false); } break; } default: { // do nothing here } }// switch } // end for }
void MintCudaMidend::processLoopsInParallelRegion(SgNode* parallelRegionNode, MintHostSymToDevInitMap_t hostToDevVars, ASTtools::VarSymSet_t& deviceSyms, MintSymSizesMap_t& trfSizes, std::set<SgInitializedName*>& readOnlyVars, const SgVariableSymbol* dev_struct) { Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(parallelRegionNode, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); switch (node->variantT()) { case V_SgOmpForStatement: { #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Omp For Statement" << endl << endl; #endif //DataTransferSizes::findTransferSizes(node, trfSizes); bool isBoundaryCond = LoweringToCuda::isBoundaryConditionLoop(node); SgFunctionDeclaration* kernel; MintForClauses_t clauseList; //kernel= LoweringToCuda::transOmpFor(node, hostToDevVars, deviceSyms, readOnlyVars,clauseList, dev_struct) ; kernel= LoweringToCuda::transOmpFor(node, hostToDevVars, deviceSyms, clauseList, dev_struct) ; //swap anyways // x swapping is buggy, need to fix that before allowing x as well if(clauseList.chunksize.x == 1 && ( clauseList.chunksize.z != 1 || clauseList.chunksize.y != 1 )) { //if(MintOptions::GetInstance()->isSwapOpt()) CudaOptimizer::swapLoopAndIf(kernel, clauseList); } if (!isBoundaryCond && MintOptions::GetInstance()->optimize()) //if (MintOptions::GetInstance()->optimize()) { cout << "\n\n INFO:Mint: Optimization is ON. Optimizing ...\n\n" ; CudaOptimizer::optimize(kernel, clauseList); } // MintTools::printAllStatements(isSgNode(kernel)); //MintArrayInterface::linearizeArrays(kernel); break; } default: { //cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; //cout << " Currently we only handle for loops" << endl << endl; //do nothing //currently we only handle for loops break; } } } for (ASTtools::VarSymSet_t::const_iterator i = deviceSyms.begin (); i!= deviceSyms.end (); ++i) { SgVariableSymbol* sym= const_cast<SgVariableSymbol*> (*i); SgInitializedName* name = sym->get_declaration(); SgType* type = name->get_type(); if(isSgArrayType(type) || isSgPointerType(type)){ //Check if is of the fields of the struct if(hostToDevVars.find(sym) == hostToDevVars.end()) { string name_str = name->get_name().str(); cerr << " ERR:Mint: Ooops! Did you forget to insert a copy pragma for the variable ("<< name_str << ") ?"<< endl; cerr << " ERR:Mint: Please insert the copy pragma and compile again "<< endl; cerr << " INFO:Mint: Note that copy pragmas should appear right before and after a parallel region" << endl; ROSE_ABORT(); } } } }