#include "../Utils/leak_detector.h" #include #include #include #include #include #include #include #include #include #include "dvm.h" #include "../ParallelizationRegions/ParRegions.h" #include "array_assign_to_loop.h" #include "../Utils/SgUtils.h" #include "../ExpressionTransform/expr_transform.h" #include "../GraphCall/graph_calls_func.h" #include "../VerificationCode/verifications.h" using std::vector; using std::set; using std::map; using std::pair; using std::tuple; using std::make_pair; using std::make_tuple; using std::string; using std::to_string; using std::get; static void checkAlloc(SgExpression* toCheck, SgExpression*& alloc, const string& toFind) { if (toCheck->lhs()->symbol()->identifier() == toFind) alloc = toCheck->lhs()->lhs(); } static bool fillBounds(SgSymbol* symb, vector>& bounds) { SgStatement* decl = declaratedInStmt(symb); int consistInAllocates = 0; SgExpression* alloc = NULL; for (auto& data : getAttributes(decl, set{ ALLOCATE_STMT })) { SgExpression* list = data->expr(0); if (data->variant() != ALLOCATE_STMT) continue; while (list) { SgArrayRefExp* arrayRef = isSgArrayRefExp(list->lhs()); if (arrayRef != NULL) { if (string(OriginalSymbol(arrayRef->symbol())->identifier()) == string(symb->identifier())) { consistInAllocates++; alloc = list->lhs()->lhs(); break; } } list = list->rhs(); } } if (consistInAllocates > 1) return false; if (IS_ALLOCATABLE(symb) && consistInAllocates == 0) return false; bool symbFound = false; if (consistInAllocates == 0) { const string toFind = string(symb->identifier()); for (SgExpression* ex = decl->expr(0); ex && (alloc == NULL); ex = ex->rhs()) { if (ex->lhs()->variant() == ASSGN_OP) { if (ex->lhs()->lhs() && ex->lhs()->lhs()->symbol()) checkAlloc(ex->lhs(), alloc, toFind); } else if (ex->lhs() && ex->lhs()->symbol()) { symbFound |= (ex->lhs()->symbol()->identifier() == toFind); checkAlloc(ex, alloc, toFind); } } } if (symbFound && alloc == NULL) { for (SgExpression* ex = decl->expr(2); ex; ex = ex->rhs()) { if (ex->lhs() && ex->lhs()->variant() == DIMENSION_OP) { alloc = ex->lhs()->lhs(); break; } } } if (alloc == NULL) return false; for (; alloc; alloc = alloc->rhs()) { const int var = alloc->lhs()->variant(); if (var == DDOT) { if (alloc->lhs()->lhs() == NULL || alloc->lhs()->rhs() == NULL) return false; bounds.push_back(make_tuple(alloc->lhs()->lhs()->copyPtr(), alloc->lhs()->rhs()->copyPtr(), (SgExpression*)NULL)); } else if (var == STAR_RANGE) return false; else bounds.push_back(make_tuple(new SgValueExp(1), alloc->lhs()->copyPtr(), (SgExpression*)NULL)); } for (auto& bound : bounds) get<0>(bound) = CalculateInteger(get<0>(bound)); return true; } static bool fillSectionInfo(SgExpression* subs, tuple& section) { if (subs->lhs()) { if (subs->lhs()->variant() == DDOT) { if (subs->lhs()->lhs() && subs->lhs()->lhs()->variant() == DDOT) { if (subs->lhs()->lhs()->lhs() != NULL) // low section get<0>(section) = CalculateInteger(subs->lhs()->lhs()->lhs()->copyPtr()); if (subs->lhs()->lhs()->rhs() != NULL) // high section get<1>(section) = CalculateInteger(subs->lhs()->lhs()->rhs()->copyPtr()); if (subs->lhs()->rhs() != NULL) // step of section get<2>(section) = CalculateInteger(subs->lhs()->rhs()->copyPtr()); } else { if (subs->lhs()->lhs() != NULL) // low section get<0>(section) = CalculateInteger(subs->lhs()->lhs()->copyPtr()); if (subs->lhs()->rhs() != NULL) // high section get<1>(section) = CalculateInteger(subs->lhs()->rhs()->copyPtr()); } } else { // low and high sections get<0>(section) = CalculateInteger(subs->lhs()->copyPtr()); get<1>(section) = CalculateInteger(subs->lhs()->copyPtr()); } return true; } else return false; } static bool hasSections(SgArrayRefExp* array) { const int subs = array->numberOfSubscripts(); if (subs == 0) return true; else { for (int i = 0; i < subs; ++i) if (array->subscript(i)->variant() == DDOT) return true; } return false; } static map>>> cacheNameShiftAll; // by file and func -> [by base -> [old, new]] static map>* cacheNameShift; // by base -> [old, new] static string createNewName(const string& base, int num) { int nextNum = 0; if (cacheNameShift->count(base) && (*cacheNameShift)[base].count(num)) nextNum = (*cacheNameShift)[base][num]; else { nextNum = checkSymbNameAndCorrect(base, num); (*cacheNameShift)[base][num] = nextNum; } string ret = base + to_string(nextNum); return ret; } static void insertMainPart(SgExpression* subsL, SgFile* file, const int deep, SgExpression* shift, SgExpression* step, SgStatement* scope) { auto varRef = new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", deep), SgTypeInt(), scope)); bool isNull = false; if (shift->isInteger()) if (shift->valueInteger() == 0) isNull = true; if (step) { if (step->variant() == INT_VAL) { //TODO: move negative step to DO bounds /*const int stepVal = abs(step->valueInteger()); SgExpression *stepAbs = new SgValueExp(stepVal);*/ const int stepVal = step->valueInteger(); SgExpression* stepAbs = step; if (stepVal != 1) { if (isNull) subsL->setLhs(*varRef * *stepAbs); else subsL->setLhs(*varRef * *stepAbs + *shift); } else { if (isNull) subsL->setLhs(*varRef); else subsL->setLhs(*varRef + *shift); } } else { if (isNull) subsL->setLhs(*varRef * *step); else subsL->setLhs(*varRef * *step + *shift); } } else { if (isNull) subsL->setLhs(*varRef); else subsL->setLhs(*varRef + *shift); } } static bool isNonDistrArray(SgSymbol* symb, const map>& arrayLinksByFuncCalls) { SgStatement* decl = declaratedInStmt(symb); SgType* type = symb->type(); if (type && type->variant() == T_STRING) return false; DIST::Array* array = getArrayFromDeclarated(decl, OriginalSymbol(symb)->identifier()); checkNull(array, convertFileName(__FILE__).c_str(), __LINE__); set realRefs; getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls); bool fullNotDistr = true; for (auto& real : realRefs) fullNotDistr &= real->IsNotDistribute(); return fullNotDistr; } static void fillArgs(SgExpression* ref, vector>& bounds, const vector>& b) { for (int i = 0; ref; ref = ref->rhs(), ++i) { if (ref->lhs()->variant() == DDOT) { auto left = ref->lhs()->lhs(); auto right = ref->lhs()->rhs(); SgExpression* declLeft = (SgExpression*)get<0>(b[i]); SgExpression* declRight = (SgExpression*)get<1>(b[i]); if (left == NULL && right == NULL) bounds.push_back(make_tuple(declLeft, declRight, (SgExpression*)NULL)); else if (left == NULL && right != NULL) bounds.push_back(make_tuple(declLeft, right->copyPtr(), (SgExpression*)NULL)); else if (right == NULL && left != NULL) bounds.push_back(make_tuple(left->copyPtr(), declRight, (SgExpression*)NULL)); else if (left->variant() == DDOT) { if (left->lhs() == NULL && left->rhs() == NULL) bounds.push_back(make_tuple(declLeft, declRight, right)); else if (left->lhs() == NULL && left->rhs() != NULL) bounds.push_back(make_tuple(declLeft, left->rhs(), right)); else if (left->rhs() == NULL && left->lhs() != NULL) bounds.push_back(make_tuple(left->lhs(), declRight, right)); else bounds.push_back(make_tuple(left->copyPtr(), right->copyPtr(), right)); } else bounds.push_back(make_tuple(left->copyPtr(), right->copyPtr(), (SgExpression*)NULL)); } /*else if (ref->lhs()->variant() == INT_VAL) bounds.push_back(make_tuple(ref->lhs()->copyPtr(), ref->lhs()->copyPtr(), (SgExpression*)NULL)); else if (ref->lhs()->variant() == CONST_REF) bounds.push_back(make_tuple(ref->lhs()->copyPtr(), ref->lhs()->copyPtr(), (SgExpression*)NULL)); */ else bounds.push_back(make_tuple(ref->lhs()->copyPtr(), ref->lhs()->copyPtr(), (SgExpression*)NULL)); } for (auto& bound : bounds) get<0>(bound) = CalculateInteger(get<0>(bound)); } static SgExpression* changeNode(SgExpression* ex, const int i, SgExpression* right) { if (i == 0) { SgExpression* tmp = ex->lhs()->lhs(); ex->setLhs(*tmp); } else if (i == 1) { SgExpression* tmp = ex->rhs()->lhs(); ex->setRhs(*tmp); } else if (i == 2) { SgExpression* tmp = ex->lhs()->rhs(); ex->setLhs(*tmp); } else if (i == 4) { ex->lhs()->setLhs(new SgValueExp(1)); ex->lhs()->setRhs(right); } else if (i == 5) { ex->rhs()->setLhs(new SgValueExp(1)); ex->rhs()->setRhs(right); } else { SgExpression* tmp = ex->rhs()->rhs(); ex->setRhs(*tmp); } return ex; } static int constsInArgs(SgExpression* ex, int i, SgExpression* right) { if (i == 0) { while (ex) { if (ex->lhs()->variant() == INT_VAL || ex->lhs()->variant() == CONST_REF) { return 1; } else if (ex->lhs()->variant() == DDOT) { if (ex->lhs()->lhs() && ex->lhs()->rhs() && string(ex->lhs()->lhs()->unparse()) == string(ex->lhs()->rhs()->unparse())) { ex = changeNode(ex, 0, NULL); return 1; } else if (ex->lhs()->lhs() && ex->lhs()->rhs() == NULL && string(right->unparse()) == string(ex->lhs()->lhs()->unparse())) { ex = changeNode(ex, 0, NULL); return 1; } else if (ex->lhs()->lhs() == NULL && ex->lhs()->rhs() != NULL && ex->lhs()->rhs()->valueInteger() == 1) { ex = changeNode(ex, 2, NULL); return 1; } else if (ex->lhs()->lhs() == NULL && ex->lhs()->rhs() == NULL) { ex = changeNode(ex, 4, right); if (string(ex->lhs()->lhs()->unparse()) == string(ex->lhs()->rhs()->unparse())) return 1; else return 0; } return 0; } else if (ex->variant() == INT_VAL || ex->variant() == CONST_REF) return 1; ex = ex->rhs(); } } else { if (ex->rhs()->lhs() && ex->rhs()->rhs() && ex->rhs()->lhs()->valueInteger() - ex->rhs()->rhs()->valueInteger() == 0) { ex = changeNode(ex, 1, NULL); return 1; } else if (ex->rhs()->lhs() && ex->rhs()->rhs() == NULL && string(right->unparse()) == string(ex->lhs()->lhs()->unparse())) { ex = changeNode(ex, 1, NULL); return 1; } else if (ex->rhs()->lhs() == NULL && ex->lhs()->rhs() && ex->rhs()->rhs()->valueInteger() == 1) { ex = changeNode(ex, 3, NULL); return 1; } else if (ex->rhs()->lhs() == NULL && ex->rhs()->rhs() == NULL) { ex = changeNode(ex, 5, right); if (string(ex->rhs()->lhs()->unparse()) == string(ex->rhs()->rhs()->unparse())) return 1; else return 0; } return 0; } return 0; } static SgForStmt* constructDoBounds(const vector>& leftSections, const vector>& rightSections, SgStatement* copy, SgFile* file, SgStatement* scope, bool mainSymbolsAreEq = false, int* nestCount = NULL) { SgForStmt* retVal = NULL; SgStatement* body = NULL; vector> forBounds; const vector>& mainSection = leftSections.size() ? leftSections : rightSections; bool onlyRight = leftSections.size() == 0 && rightSections.size() != 0; for (int i = 0; i < mainSection.size(); ++i) { SgExpression* maxBound = NULL; if (get<2>(mainSection[i])) maxBound = &((*(get<1>(mainSection[i])) - *get<0>(mainSection[i])) / *get<2>(mainSection[i])); else maxBound = &(*(get<1>(mainSection[i])) - *get<0>(mainSection[i])); //TODO: dont calculate in parallel loops maxBound = CalculateInteger(maxBound); if (onlyRight) // for SUM, WHERE, forBounds.push_back(make_tuple(new SgValueExp(0), maxBound, (SgExpression*)NULL)); else { //TODO: if (mainSymbolsAreEq && get<1>(leftSections[i])->isInteger() && get<1>(rightSections[i])->isInteger() && get<1>(leftSections[i])->valueInteger() > get<1>(rightSections[i])->valueInteger()) forBounds.push_back(make_tuple(maxBound, new SgValueExp(0), new SgValueExp(-1))); else forBounds.push_back(make_tuple(new SgValueExp(0), maxBound, (SgExpression*)NULL)); } } int loopsCount = 0; for (int i = 0; i < forBounds.size(); ++i) { if (body == NULL) body = copy; else body = retVal; if (get<2>(forBounds[i])) // has step { SgExpression* step = get<2>(forBounds[i]); bool inverse = false; if (step->variant() == INT_VAL) if (step->valueInteger() < 0) inverse = true; ++loopsCount; retVal = new SgForStmt(*findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope), get<0>(forBounds[i])->copy(), get<1>(forBounds[i])->copy(), get<2>(forBounds[i])->copy(), *body); } else { ++loopsCount; retVal = new SgForStmt(*findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope), get<0>(forBounds[i])->copy(), get<1>(forBounds[i])->copy(), *body); } } if (nestCount) nestCount[0] = loopsCount; return retVal; } static bool hasArrayRef(SgExpression* ex) { bool result = false; if (ex) { if (isArrayRef(ex)) result = true; bool lR = hasArrayRef(ex->lhs()); bool rR = hasArrayRef(ex->rhs()); result = result || lR || rR; } return result; } static SgStatement* convertFromAssignExpressionToLoop(SgStatement* assign, SgFile* file, vector& messagesForFile, const map>& arrayLinksByFuncCalls) { SgStatement* result = NULL; SgArrayRefExp* leftPart = (SgArrayRefExp*)assign->expr(0); if (!hasSections(leftPart)) return result; if (isNonDistrArray(assign->expr(0)->symbol(), arrayLinksByFuncCalls)) return result; const int leftSubs = leftPart->numberOfSubscripts(); vector> leftBound; bool resL = fillBounds(OriginalSymbol(leftPart->symbol()), leftBound); if (!resL) { __spf_print(1, "WARN: can not convert array assign to loop on line %d\n", assign->lineNumber()); messagesForFile.push_back(Messages(WARR, assign->lineNumber(), R94, L"can not convert array assign to loop", 2001)); return result; } SgForStmt* retVal = NULL; SgStatement* copy = assign->copyPtr(); if (copy->label()) copy->deleteLabel(); SgArrayRefExp* leftArrayRef = (SgArrayRefExp*)copy->expr(0); vector> leftArgs; fillArgs(leftArrayRef->lhs(), leftArgs, leftBound); SgExpression* subsL = leftArrayRef->lhs(); int lIdx = 0; bool bodyInserted = false; SgStatement* scope = assign; while (true) { if (scope->variant() == PROG_HEDR || scope->variant() == FUNC_HEDR || scope->variant() == PROC_HEDR) break; scope = scope->controlParent(); } vector fixedLeft(leftBound.size()); for (int i = 0; i < leftBound.size(); ++i) fixedLeft[i] = false; vector> leftSections; SgExpression* ex = subsL; for (int i = 0; i < leftSubs; ++i) { tuple bounds = leftBound[i]; if (!fillSectionInfo(ex, bounds)) { printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedLeft[i] = true; if (!fixedLeft[i]) leftSections.push_back(bounds); ex = ex->rhs(); } //fill default if (leftSubs == 0) leftSections = leftBound; __spf_print(1, "was on line %d file %s\n", assign->lineNumber(), assign->fileName()); __spf_print(1, "%s", string(assign->unparse()).c_str()); // create DO bounds if (!leftSections.size()) leftSections = leftBound; retVal = constructDoBounds(leftSections, { }, copy, file, scope); if (leftSubs == 0) { // A = expr for (int i = 0; i < leftSections.size(); ++i) { SgExpression* shiftA = get<0>(leftBound[i]); shiftA = CalculateInteger(shiftA); leftArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftA); } } else if (leftSubs != 0 && !hasArrayRef(assign->expr(1))) { // A( : : : ) = expr ex = subsL; for (int i = 0, freeIdx = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { if (!fixedLeft[i]) { SgExpression* shiftA = get<0>(leftSections[freeIdx]); if (shiftA == NULL) shiftA = get<0>(leftBound[freeIdx]); shiftA = CalculateInteger(shiftA); SgExpression* stepA = get<2>(leftSections[freeIdx]); if (stepA != NULL) stepA = CalculateInteger(stepA); insertMainPart(subsL, file, freeIdx, shiftA, stepA, scope); ++freeIdx; } } } else { //A( : : : ) = B( : : : ) + C( : : :) ex = subsL; for (int i = 0, freeIdx = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { tuple leftSect = std::make_tuple((SgExpression*)NULL, (SgExpression*)NULL, (SgExpression*)NULL); if (freeIdx < leftSections.size()) leftSect = leftSections[freeIdx]; SgExpression* rightB = get<1>(leftArgs[i]); int flag = 0; if (!fillSectionInfo(subsL, leftSect)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgExpression* shiftA = get<0>(leftSect); if (shiftA == NULL) shiftA = get<0>(leftBound[freeIdx]); shiftA = CalculateInteger(shiftA); SgExpression* stepA = get<2>(leftSect); if (stepA != NULL) stepA = CalculateInteger(stepA); if (subsL->rhs() && subsL->rhs()->variant() != DDOT) flag = constsInArgs(subsL, 0, rightB); else if (subsL->rhs() && subsL->rhs()->variant() == DDOT) flag = constsInArgs(subsL, 1, rightB); if (flag != 1) { insertMainPart(subsL, file, freeIdx, shiftA, stepA, scope); ++freeIdx; } } } __spf_print(1, "%s", string(retVal->unparse()).c_str()); result = retVal; return result; } static vector fillSteps(SgExpression* subsL, int leftSubs, vector>& leftArgs, const vector>& leftSections, const vector>& leftBound) { vector steps; for (int i = 0, freeIdx = 0, j = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { if (!fillSectionInfo(subsL, leftArgs[i])) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgExpression* tmp1 = NULL; if (freeIdx < leftSections.size()) tmp1 = get<0>(leftSections[freeIdx]); SgExpression* rightB = get<1>(leftArgs[i]); if (tmp1 && string(get<0>(leftArgs[i])->unparse()) == string(tmp1->unparse()) && subsL->lhs()->variant() != INT_VAL) { SgExpression* shiftA = get<0>(leftSections[freeIdx]); if (shiftA == NULL) shiftA = get<0>(leftBound[freeIdx]); shiftA = CalculateInteger(shiftA); SgExpression* stepA = get<2>(leftSections[freeIdx]); if (stepA != NULL) stepA = CalculateInteger(stepA); steps.push_back(stepA); ++freeIdx; j++; } } return steps; } static vector insertPartOfAssign(SgFile* file, SgStatement* scope, SgExpression* subsL, int leftSubs, const vector>& leftArgs, const vector>& leftSections, const vector>& leftBound, const vector& stepsR, const bool symbsAreEq, const bool isRight, const vector& changeLoopSignLeft) { vector changeLoopSign; for (int i = 0, freeIdx = 0, j = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { SgExpression* tmp1 = NULL; if (freeIdx < leftSections.size()) tmp1 = get<0>(leftSections[freeIdx]); SgExpression* rightB = get<1>(leftArgs[i]); if (tmp1 && string(get<0>(leftArgs[i])->unparse()) == string(tmp1->unparse()) && subsL->lhs()->variant() != INT_VAL) { SgExpression* stepA = get<2>(leftSections[freeIdx]); if (stepA != NULL) stepA = CalculateInteger(stepA); bool needToChange = false; bool singChanged = false; if (!symbsAreEq) { bool stepEq = false; if (stepA && stepsR[j]) { string sA = stepA->unparse(); string sR = stepsR[j]->unparse(); if (sA == sR) { stepEq = true; if (stepA->isInteger() && stepA->valueInteger() < 0 && abs(stepA->valueInteger()) == 1) { stepA = new SgValueExp(stepA->valueInteger() * -1); needToChange = true; } } } if (!stepEq) { if (isRight) { if (stepA == NULL) { if (changeLoopSignLeft.size() && changeLoopSignLeft[j]) stepA = new SgValueExp(-1); } else if (stepA) { if (changeLoopSignLeft.size() && changeLoopSignLeft[j]) { singChanged = true; stepA = new SgValueExp(stepA->valueInteger() * -1); } } } else { if (stepA && stepA->isInteger() && stepA->valueInteger() < 0 && abs(stepA->valueInteger()) == 1) { stepA = new SgValueExp(stepA->valueInteger() * -1); needToChange = true; } } } } changeLoopSign.push_back(needToChange); if (isRight && changeLoopSignLeft.size() && changeLoopSignLeft[j]) needToChange = true; SgExpression* shiftA = needToChange ? get<1>(leftSections[freeIdx]) : get<0>(leftSections[freeIdx]); if (shiftA == NULL) shiftA = needToChange ? get<1>(leftBound[freeIdx]) : get<0>(leftBound[freeIdx]); if (isRight && needToChange && singChanged) { SgExpression* a = get<0>(leftSections[freeIdx]); SgExpression* b = get<1>(leftSections[freeIdx]); SgExpression* c = get<2>(leftSections[freeIdx]); checkNull(a, convertFileName(__FILE__).c_str(), __LINE__); checkNull(b, convertFileName(__FILE__).c_str(), __LINE__); checkNull(c, convertFileName(__FILE__).c_str(), __LINE__); SgExpression* ex = &(*a + ((*b - *a + *c) / *c - *new SgValueExp(1)) * *c - *get<1>(leftSections[freeIdx])); shiftA = &(*shiftA + *ex); } shiftA = CalculateInteger(shiftA); insertMainPart(subsL, file, j, shiftA, stepA, scope); ++freeIdx; j++; } else { if (subsL->rhs() && subsL->rhs()->variant() != DDOT) constsInArgs(subsL, 0, rightB); else if (subsL->rhs() && subsL->rhs()->variant() == DDOT) constsInArgs(subsL, 1, rightB); } } return changeLoopSign; } static void swapLoopBounds(SgForStmt* loop, const vector& changeLoopSign) { for (int z = 0; z < changeLoopSign.size(); ++z) { checkNull(loop, convertFileName(__FILE__).c_str(), __LINE__); if (changeLoopSign[z]) { if (loop->step() == NULL) loop->setStep(*new SgValueExp(-1)); else { auto step = loop->step(); if (!step->isInteger()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); loop->setStep(*new SgValueExp(-1 * step->valueInteger())); } loop->swapStartEnd(); } loop = isSgForStmt(loop->lexNext()); } } static void doReplace(SgExpression* prev, SgExpression* ex, bool isLeft, const string& s, SgExpression* with) { if (ex) { if (ex->variant() == VAR_REF && ex->symbol() && ex->symbol()->identifier() == s) { if (prev == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (isLeft) prev->setLhs(with->copyPtr()); else prev->setRhs(with->copyPtr()); } doReplace(ex, ex->lhs(), true, s, with); doReplace(ex, ex->rhs(), false, s, with); } } static SgStatement* removeOneCycleLoops(SgForStmt* retVal, const int nestCount) { vector needToDel(nestCount, false); vector> replace(nestCount); SgForStmt* loop = retVal; SgStatement* last = NULL; for (int z = 0; z < nestCount; ++z, loop = (SgForStmt*) loop->lexNext(), last = loop) { string start = loop->start()->unparse(); string end = loop->end()->unparse(); if (start == end) { needToDel[z] = true; replace[z] = make_pair(loop->doName()->identifier(), loop->start()->copyPtr()); } } checkNull(last, convertFileName(__FILE__).c_str(), __LINE__); for (int z = 0; z < nestCount; ++z) if (needToDel[z]) for (int p = 0; p < 3; ++p) doReplace(NULL, last->expr(p), true, replace[z].first, replace[z].second); return retVal; } static SgStatement* convertFromAssignToLoop(SgStatement* assign, SgFile* file, vector &messagesForFile, const map>& arrayLinksByFuncCalls) { SgStatement* result = NULL; if (assign->variant() != ASSIGN_STAT) return result; if (assign->expr(0) == NULL || assign->expr(1) == NULL) return result; if (assign->expr(1)->variant() == CONSTRUCTOR_REF) { __spf_print(1, "WARN: can not convert array assign to loop on line %d\n", assign->lineNumber()); messagesForFile.push_back(Messages(WARR, assign->lineNumber(), R94, L"can not convert array assign to loop", 2001)); return result; } if (isArrayRef(assign->expr(0)) && !isArrayRef(assign->expr(1))) { result = convertFromAssignExpressionToLoop(assign, file, messagesForFile, arrayLinksByFuncCalls); return result; } if (!isArrayRef(assign->expr(0)) || !isArrayRef(assign->expr(1))) return result; bool fullPrivate = true; if (isArrayRef(assign->expr(0)) && !isNonDistrArray(assign->expr(0)->symbol(), arrayLinksByFuncCalls)) fullPrivate = false; if (isArrayRef(assign->expr(1)) && !isNonDistrArray(assign->expr(1)->symbol(), arrayLinksByFuncCalls)) fullPrivate = false; if (fullPrivate) return result; SgArrayRefExp* leftPart = (SgArrayRefExp*)assign->expr(0); SgArrayRefExp* rightPart = (SgArrayRefExp*)assign->expr(1); if (!hasSections(leftPart) || !hasSections(rightPart)) return result; const int leftSubs = leftPart->numberOfSubscripts(); const int rightSubs = rightPart->numberOfSubscripts(); vector> leftBound; vector> rightBound; bool resL = fillBounds(OriginalSymbol(leftPart->symbol()), leftBound); bool resR = fillBounds(OriginalSymbol(rightPart->symbol()), rightBound); if (!resL || !resR) { __spf_print(1, "WARN: can not convert array assign to loop on line %d\n", assign->lineNumber()); messagesForFile.push_back(Messages(WARR, assign->lineNumber(), R94, L"can not convert array assign to loop", 2001)); return result; } SgForStmt* retVal = NULL; SgStatement* retValSt = NULL; SgStatement* copy = assign->copyPtr(); if (copy->label()) copy->deleteLabel(); SgArrayRefExp* leftArrayRef = (SgArrayRefExp*)copy->expr(0); SgArrayRefExp* rightArrayRef = (SgArrayRefExp*)copy->expr(1); SgExpression* subsL = leftArrayRef->lhs(); SgExpression* subsR = rightArrayRef->lhs(); vector> leftArgs; vector> rightArgs; fillArgs(subsL, leftArgs, leftBound); fillArgs(subsR, rightArgs, rightBound); int lIdx = 0; int rIdx = 0; bool bodyInserted = false; SgStatement* scope = assign; while (true) { if (scope->variant() == PROG_HEDR || scope->variant() == FUNC_HEDR || scope->variant() == PROC_HEDR) break; scope = scope->controlParent(); } vector fixedLeft(leftBound.size()), fixedRight(rightBound.size()); for (int i = 0; i < fixedLeft.size(); ++i) fixedLeft[i] = false; for (int i = 0; i < fixedRight.size(); ++i) fixedRight[i] = false; vector> leftSections, rightSections; SgExpression* ex = subsL; for (int i = 0; i < leftSubs; ++i) { tuple bounds = leftArgs[i]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); // fixed dimension value if (get<0>(bounds) && get<1>(bounds)) if ((string(get<0>(bounds)->unparse()) == get<1>(bounds)->unparse()) && ex->lhs()->variant() != DDOT) fixedLeft[i] = true; if (!fixedLeft[i]) leftSections.push_back(bounds); ex = ex->rhs(); } //fill default if (leftSubs == 0) leftSections = leftBound; ex = subsR; for (int i = 0; i < rightSubs; ++i) { tuple bounds = rightArgs[i]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); // fixed dimension value if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == get<1>(bounds)->unparse() && ex->lhs()->variant() != DDOT) fixedRight[i] = true; if (!fixedRight[i]) rightSections.push_back(bounds); ex = ex->rhs(); } //fill default if (rightSubs == 0) rightSections = rightBound; if (leftSections.size() != rightSections.size()) { __spf_print(1, "WARN: can not convert array assign to loop on line %d\n", assign->lineNumber()); messagesForFile.push_back(Messages(WARR, assign->lineNumber(), R94, L"can not convert array assign to loop", 2001)); } else { __spf_print(1, "was on line %d file %s\n", assign->lineNumber(), assign->fileName()); __spf_print(1, "%s", string(assign->unparse()).c_str()); bool symbsAreEq = false; if (leftPart->symbol() && rightPart->symbol()) symbsAreEq = strcmp(OriginalSymbol(leftPart->symbol())->identifier(), OriginalSymbol(rightPart->symbol())->identifier()) == 0; int nestCount = 0; retValSt = retVal = constructDoBounds(leftSections, rightSections, copy, file, scope, symbsAreEq, &nestCount); if (leftSubs == 0 && rightSubs == 0) { // A = B for (int i = 0; i < leftSections.size(); ++i) { SgExpression* shiftA = get<0>(leftBound[i]); shiftA = CalculateInteger(shiftA); leftArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftA); } for (int i = 0; i < rightSections.size(); ++i) { SgExpression* shiftB = get<0>(rightBound[i]); shiftB = CalculateInteger(shiftB); rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftB); } } else if (leftSubs == 0 && rightSubs != 0) { // A = B( : : : ) for (int i = 0; i < leftSections.size(); ++i) { SgExpression* shiftA = get<0>(leftBound[i]); shiftA = CalculateInteger(shiftA); leftArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftA); } ex = subsR; int flag; for (int i = 0, freeIdx = 0; i < rightSubs; ++i, subsR = subsR->rhs()) { flag = 0; if (!fixedRight[i]) { SgExpression* shiftB = get<0>(rightSections[freeIdx]); SgExpression* rightB = get<1>(rightArgs[freeIdx]); if (rightB == NULL) rightB = get<1>(rightBound[freeIdx]); if (shiftB == NULL) shiftB = get<0>(rightBound[freeIdx]); shiftB = CalculateInteger(shiftB); SgExpression* stepB = get<2>(rightSections[freeIdx]); if (stepB != NULL) stepB = CalculateInteger(stepB); if (subsR->rhs() && subsR->rhs()->variant() != DDOT) flag = constsInArgs(subsR, 0, rightB); else if (subsR->rhs() && subsR->rhs()->variant() == DDOT) flag = constsInArgs(subsR, 1, rightB); else flag = constsInArgs(subsR, 0, rightB); if (flag != 1) insertMainPart(subsR, file, freeIdx, shiftB, stepB, scope); ++freeIdx; } } } else if (leftSubs != 0 && rightSubs == 0) { // A( : : : ) = B ex = subsL; vector changeLoopSign; for (int i = 0, freeIdx = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { if (!fixedLeft[i]) { SgExpression* stepA = get<2>(leftSections[freeIdx]); if (stepA != NULL) stepA = CalculateInteger(stepA); bool needToChange = false; if (!symbsAreEq && stepA) if (stepA->isInteger() && stepA->valueInteger() < 0 && abs(stepA->valueInteger()) == 1) { stepA = new SgValueExp(stepA->valueInteger() * -1); needToChange = true; } changeLoopSign.push_back(needToChange); SgExpression* shiftA = needToChange ? get<1>(leftSections[freeIdx]) : get<0>(leftSections[freeIdx]); if (shiftA == NULL) shiftA = needToChange ? get<1>(leftBound[freeIdx]) : get<0>(leftBound[freeIdx]); shiftA = CalculateInteger(shiftA); insertMainPart(subsL, file, freeIdx, shiftA, stepA, scope); ++freeIdx; } } if (changeLoopSign.size() != rightSections.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < rightSections.size(); ++i) { bool invert = changeLoopSign[i]; SgExpression* shiftB = invert ? get<1>(rightBound[i]) : get<0>(rightBound[i]); shiftB = CalculateInteger(shiftB); if (invert) rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) * *new SgValueExp(-1) + *shiftB); else rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftB); } std::reverse(changeLoopSign.begin(), changeLoopSign.end()); swapLoopBounds(retVal, changeLoopSign); } else { //A( : : : ) = B( : : : ) auto stepsA = fillSteps(subsL, leftSubs, leftArgs, leftSections, leftBound); auto stepsB = fillSteps(subsR, rightSubs, rightArgs, rightSections, rightBound); if (stepsA.size() != stepsB.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto changeLoopSign = insertPartOfAssign(file, scope, subsL, leftSubs, leftArgs, leftSections, leftBound, stepsB, symbsAreEq, false, vector()); changeLoopSign = insertPartOfAssign(file, scope, subsR, rightSubs, rightArgs, rightSections, rightBound, stepsA, symbsAreEq, true, changeLoopSign); if (changeLoopSign.size() != nestCount) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); std::reverse(changeLoopSign.begin(), changeLoopSign.end()); swapLoopBounds(retVal, changeLoopSign); //bad solution //retValSt = removeOneCycleLoops(retVal, nestCount); } __spf_print(1, "%s", string(retValSt->unparse()).c_str()); } result = retValSt; return result; } static SgStatement* convertFromStmtToLoop(SgStatement* assign, SgFile* file, vector& messagesForFile, const map>& arrayLinksByFuncCalls) { SgStatement* result = NULL; if (assign->variant() != ASSIGN_STAT) return result; if (assign->expr(0) == NULL || assign->expr(1) == NULL) return result; if (assign->expr(1)->lhs() == NULL || assign->expr(1)->rhs() == NULL) return result; if (!isArrayRef(assign->expr(0)) || !isArrayRef(assign->expr(1)->rhs()) || !isArrayRef(assign->expr(1)->lhs())) return result; if (isNonDistrArray(assign->expr(0)->symbol(), arrayLinksByFuncCalls) && isNonDistrArray(assign->expr(1)->rhs()->symbol(), arrayLinksByFuncCalls) && isNonDistrArray(assign->expr(1)->lhs()->symbol(), arrayLinksByFuncCalls)) return result; SgArrayRefExp* leftPart = (SgArrayRefExp*)assign->expr(1)->lhs(); SgArrayRefExp* rightPart = (SgArrayRefExp*)assign->expr(1)->rhs(); SgArrayRefExp* assignPart = (SgArrayRefExp*)assign->expr(0); if (!hasSections(leftPart) || !hasSections(rightPart) || !hasSections(assignPart)) return result; vector> leftBound; vector> rightBound; vector> assignBound; bool resL = fillBounds(OriginalSymbol(leftPart->symbol()), leftBound); bool resR = fillBounds(OriginalSymbol(rightPart->symbol()), rightBound); bool resA = fillBounds(OriginalSymbol(assignPart->symbol()), assignBound); if (!resL || !resR || !resA) return result; SgForStmt* retVal = NULL; SgStatement* copy = assign->copyPtr(); if (copy->label()) copy->deleteLabel(); SgArrayRefExp* leftArrayRef = (SgArrayRefExp*)copy->expr(1)->lhs(); SgArrayRefExp* rightArrayRef = (SgArrayRefExp*)copy->expr(1)->rhs(); SgArrayRefExp* assignArrayRef = (SgArrayRefExp*)copy->expr(0); SgExpression* subsL = leftArrayRef->lhs(); SgExpression* subsR = rightArrayRef->lhs(); SgExpression* subsA = assignArrayRef->lhs(); int lIdx = 0; int rIdx = 0; int aIdx = 0; bool bodyInserted = false; SgStatement* scope = assign; const int leftSubs = leftPart->numberOfSubscripts(); const int rightSubs = rightPart->numberOfSubscripts(); const int assignSubs = assignPart->numberOfSubscripts(); while (true) { if (scope->variant() == PROG_HEDR || scope->variant() == FUNC_HEDR || scope->variant() == PROC_HEDR) break; scope = scope->controlParent(); } vector fixedLeft(leftBound.size()), fixedRight(rightBound.size()), fixedAssign(assignBound.size()); for (int i = 0; i < leftBound.size(); ++i) fixedLeft[i] = false; for (int i = 0; i < fixedRight.size(); ++i) fixedRight[i] = false; for (int i = 0; i < fixedAssign.size(); ++i) fixedAssign[i] = false; vector> leftSections, rightSections, assignSections; SgExpression* ex = subsL; for (int i = 0; i < leftSubs; ++i) { tuple bounds = leftBound[lIdx]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedLeft[i] = true; if (!fixedLeft[i]) leftSections.push_back(bounds); ex = ex->rhs(); } //fill default if (leftSubs == 0) leftSections = leftBound; ex = subsR; for (int i = 0; i < rightSubs; ++i) { tuple bounds = rightBound[rIdx]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedRight[i] = true; if (!fixedRight[i]) rightSections.push_back(bounds); ex = ex->rhs(); } //fill default if (rightSubs == 0) rightSections = rightBound; ex = subsA; for (int i = 0; i < assignSubs; ++i) { tuple bounds = assignBound[aIdx]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedAssign[i] = true; if (!fixedAssign[i]) assignSections.push_back(bounds); ex = ex->rhs(); } //fill default if (assignSubs == 0) assignSections = assignBound; if (leftSections.size() != rightSections.size() || leftSections.size() != assignSections.size() || rightSections.size() != assignSections.size()) { __spf_print(1, "WARN: can not convert array assign to loop on line %d\n", assign->lineNumber()); messagesForFile.push_back(Messages(WARR, assign->lineNumber(), R95, L"can not convert array assign to loop", 2001)); } else { __spf_print(1, "was on line %d file %s\n", assign->lineNumber(), assign->fileName()); __spf_print(1, "%s", string(assign->unparse()).c_str()); if (!leftSections.size()) leftSections = leftBound; if (!rightSections.size()) rightSections = rightBound; if (!assignSections.size()) assignSections = assignBound; bool symbsAreEq = false; if (leftPart->symbol() && rightPart->symbol()) symbsAreEq = strcmp(OriginalSymbol(leftPart->symbol())->identifier(), OriginalSymbol(rightPart->symbol())->identifier()) == 0; retVal = constructDoBounds(leftSections, rightSections, copy, file, scope, symbsAreEq); if (leftSubs == 0) { for (int i = 0; i < leftSections.size(); ++i) { SgExpression* shiftA = get<0>(leftBound[i]); shiftA = CalculateInteger(shiftA); leftArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftA); } } else { ex = subsL; for (int i = 0, freeIdx = 0; i < leftSubs; ++i, subsL = subsL->rhs()) { if (!fixedLeft[i]) { SgExpression* shiftA = get<0>(leftSections[freeIdx]); if (shiftA == NULL) shiftA = get<0>(leftBound[freeIdx]); shiftA = CalculateInteger(shiftA); SgExpression* stepA = get<2>(leftSections[freeIdx]); if (stepA != NULL) stepA = CalculateInteger(stepA); insertMainPart(subsL, file, freeIdx, shiftA, stepA, scope); ++freeIdx; } } } if (rightSubs == 0) { for (int i = 0; i < rightSections.size(); ++i) { SgExpression* shiftB = get<0>(rightBound[i]); shiftB = CalculateInteger(shiftB); rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftB); } } else { ex = subsR; for (int i = 0, freeIdx = 0; i < rightSubs; ++i, subsR = subsR->rhs()) { if (!fixedRight[i]) { SgExpression* shiftB = get<0>(rightSections[freeIdx]); if (shiftB == NULL) shiftB = get<0>(rightBound[freeIdx]); shiftB = CalculateInteger(shiftB); SgExpression* stepB = get<2>(rightSections[freeIdx]); if (stepB != NULL) stepB = CalculateInteger(stepB); insertMainPart(subsR, file, freeIdx, shiftB, stepB, scope); ++freeIdx; } } } if (assignSubs == 0) { for (int i = 0; i < assignSections.size(); ++i) { SgExpression* shiftC = get<0>(assignBound[i]); shiftC = CalculateInteger(shiftC); assignArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftC); } } else { ex = subsA; for (int i = 0, freeIdx = 0; i < assignSubs; ++i, subsA = subsA->rhs()) { if (!fixedAssign[i]) { SgExpression* shiftC = get<0>(assignSections[freeIdx]); if (shiftC == NULL) shiftC = get<0>(assignBound[freeIdx]); shiftC = CalculateInteger(shiftC); SgExpression* stepC = get<2>(assignSections[freeIdx]); if (stepC != NULL) stepC = CalculateInteger(stepC); insertMainPart(subsA, file, freeIdx, shiftC, stepC, scope); ++freeIdx; } } } } __spf_print(1, "%s", string(retVal->unparse()).c_str()); result = retVal; return result; } static SgStatement* convertFromSumToLoop(SgStatement * assign, SgFile * file, vector &messagesForFile, const map>& arrayLinksByFuncCalls) { SgStatement* result = NULL; if (assign->expr(0) == NULL || assign->expr(1) == NULL) return result; if (assign->expr(1)->lhs() == NULL || assign->expr(1)->lhs()->lhs() == NULL || isArrayRef(assign->expr(1)->lhs()->lhs())) return result; if (isNonDistrArray(assign->expr(1)->lhs()->lhs()->symbol(), arrayLinksByFuncCalls)) return result; SgForStmt* retVal = NULL; SgStatement* copy = assign->copyPtr(); if (copy->label()) copy->deleteLabel(); copy->setExpression(1, assign->expr(1)->lhs()->lhs()->copy()); SgExpression* leftPart = assign->expr(0); SgArrayRefExp* rightPart = (SgArrayRefExp*)assign->expr(1)->lhs()->lhs(); const int Subs = rightPart->numberOfSubscripts(); if (!hasSections(rightPart)) return result; vector> rightBound; bool resR = fillBounds(OriginalSymbol(rightPart->symbol()), rightBound); if (!resR) return result; SgArrayRefExp* rightArrayRef = (SgArrayRefExp*)copy->expr(1); SgExpression* subsR = rightArrayRef->lhs(); int rIdx = 0; bool bodyInserted = false; SgStatement* scope = assign; const int rightSubs = rightPart->numberOfSubscripts(); while (true) { if (scope->variant() == PROG_HEDR || scope->variant() == FUNC_HEDR || scope->variant() == PROC_HEDR) break; scope = scope->controlParent(); } vector fixedRight(rightBound.size()); for (int i = 0; i < fixedRight.size(); ++i) fixedRight[i] = false; vector> rightSections; SgExpression* ex = subsR; for (int i = 0; i < rightSubs; ++i) { tuple bounds = rightBound[rIdx]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedRight[i] = true; if (!fixedRight[i]) rightSections.push_back(bounds); ex = ex->rhs(); } //fill default if (rightSubs == 0) rightSections = rightBound; __spf_print(1, "was on line %d file %s\n", assign->lineNumber(), assign->fileName()); __spf_print(1, "%s", string(assign->unparse()).c_str()); if (!rightSections.size()) rightSections = rightBound; retVal = constructDoBounds({ }, rightSections, copy, file, scope); if (rightSubs == 0) { for (int i = 0; i < rightSections.size(); ++i) { SgExpression* shiftB = get<0>(rightBound[i]); shiftB = CalculateInteger(shiftB); rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftB); } } else { ex = subsR; for (int i = 0, freeIdx = 0; i < rightSubs; ++i, subsR = subsR->rhs()) { if (!fixedRight[i]) { SgExpression* shiftB = get<0>(rightSections[freeIdx]); if (shiftB == NULL) shiftB = get<0>(rightBound[freeIdx]); shiftB = CalculateInteger(shiftB); SgExpression* stepB = get<2>(rightSections[freeIdx]); if (stepB != NULL) stepB = CalculateInteger(stepB); insertMainPart(subsR, file, freeIdx, shiftB, stepB, scope); ++freeIdx; } } } SgAssignStmt* init = new SgAssignStmt(*(assign->expr(0)), *(new SgValueExp(0))); // sum = 0 SgExpression* newRightPart = new SgExpression(ADD_OP); newRightPart->setLhs(copy->expr(0)->copyPtr()); newRightPart->setRhs(copy->expr(1)); copy->setExpression(1, *newRightPart); result = new SgIfStmt(*new SgValueExp(true)); result->insertStmtAfter(*retVal, *result); result->insertStmtAfter(*init, *result); __spf_print(1, "%s\n", " ----------- "); __spf_print(1, "%s", string(result->unparse()).c_str()); // add SPF ANALYSIS REDUCTION(SUM()) after convertion SgStatement* redDir = new SgStatement(SPF_ANALYSIS_DIR); SgExpression* list = new SgExpression(EXPR_LIST, new SgExpression(REDUCTION_OP, new SgExpression(EXPR_LIST, new SgExpression(ARRAY_OP, new SgKeywordValExp("sum"), new SgVarRefExp(init->expr(0)->symbol()))))); redDir->setExpression(0, list); retVal->addAttribute(SPF_ANALYSIS_DIR, redDir, sizeof(SgStatement)); return result; } static SgStatement* convertFromWhereToLoop(SgStatement * assign, SgFile * file, vector &messagesForFile) { SgStatement* result = NULL; if (assign->expr(0) == NULL || assign->expr(1) == NULL) return result; if (assign->expr(0)->lhs() == NULL || isArrayRef(assign->expr(0)->lhs()) || isArrayRef(assign->expr(1))) return result; /* if (!strcmp(assign->expr(0)->lhs()->symbol()->identifier(), assign->expr(1)->symbol()->identifier())) return result; */ __spf_print(1, "%s\n", " ----------- "); SgForStmt* retVal = NULL; SgStatement* copy = assign->copyPtr(); if (copy->label()) copy->deleteLabel(); SgExpression* leftPart = assign->expr(0); SgArrayRefExp* rightPart = (SgArrayRefExp*)assign->expr(1); const int Subs = rightPart->numberOfSubscripts(); if (!hasSections(rightPart)) return result; vector> rightBound; bool resR = fillBounds(OriginalSymbol(rightPart->symbol()), rightBound); if (!resR) return result; SgArrayRefExp* rightArrayRef = (SgArrayRefExp*)copy->expr(1); SgExpression* subsR = rightArrayRef->lhs(); int rIdx = 0; bool bodyInserted = false; SgStatement* scope = assign; const int rightSubs = rightPart->numberOfSubscripts(); while (true) { if (scope->variant() == PROG_HEDR || scope->variant() == FUNC_HEDR || scope->variant() == PROC_HEDR) break; scope = scope->controlParent(); } vector fixedRight(rightBound.size()); for (int i = 0; i < fixedRight.size(); ++i) fixedRight[i] = false; vector> rightSections; SgExpression* ex = subsR; for (int i = 0; i < rightSubs; ++i) { tuple bounds = rightBound[rIdx]; if (!fillSectionInfo(ex, bounds)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (get<0>(bounds) && get<1>(bounds)) if (string(get<0>(bounds)->unparse()) == string(get<1>(bounds)->unparse())) // fixed dimension value fixedRight[i] = true; if (!fixedRight[i]) rightSections.push_back(bounds); ex = ex->rhs(); } //fill default if (rightSubs == 0) rightSections = rightBound; __spf_print(1, "was on line %d file %s\n", assign->lineNumber(), assign->fileName()); __spf_print(1, "%s", string(assign->unparse()).c_str()); if (!rightSections.size()) rightSections = rightBound; retVal = constructDoBounds({ }, rightSections, copy, file, scope); if (rightSubs == 0) { for (int i = 0; i < rightSections.size(); ++i) { SgExpression* shiftB = get<0>(rightBound[i]); shiftB = CalculateInteger(shiftB); rightArrayRef->addSubscript(*new SgVarRefExp(findSymbolOrCreate(file, createNewName("i_", i), SgTypeInt(), scope)) + *shiftB); } } else { ex = subsR; for (int i = 0, freeIdx = 0; i < rightSubs; ++i, subsR = subsR->rhs()) { if (!fixedRight[i]) { SgExpression* shiftB = get<0>(rightSections[freeIdx]); if (shiftB == NULL) shiftB = get<0>(rightBound[freeIdx]); shiftB = CalculateInteger(shiftB); SgExpression* stepB = get<2>(rightSections[freeIdx]); if (stepB != NULL) stepB = CalculateInteger(stepB); insertMainPart(subsR, file, freeIdx, shiftB, stepB, scope); ++freeIdx; } } } SgIfStmt* ret = (SgIfStmt*) new SgStatement(EXPR_IF); ret->setExpression(0, *retVal->lexNext()->expr(0)); ret->expr(0)->setLhs(retVal->lexNext()->expr(1)); ret->setExpression(1, *retVal->lexNext()->expr(1)); ret->setExpression(2, *retVal->lexNext()->expr(2)); retVal->setLexNext(*ret); __spf_print(1, "%s\n", " ----------- "); __spf_print(1, "%s", string(retVal->unparse()).c_str()); result = retVal; return result; } bool notDeletedVectorAssign(SgStatement* st) { if (!st) return false; SgExpression* rPart = st->expr(1); if (!rPart) return false; const int var = rPart->variant(); return (var == ADD_OP || var == MULT_OP || var == DIV_OP || var == INT_VAL || var == FLOAT_VAL || var == DOUBLE_VAL || var == BOOL_VAL || var == CHAR_VAL || var == STRING_VAL || var == COMPLEX_VAL || var == SUBT_OP || var == MINUS_OP || var == FUNC_CALL && !strcmp(rPart->symbol()->identifier(), "sum") || isArrayRef(rPart) || var == VAR_REF || var == CONST_REF); } static SgStatement* runConversion(SgStatement* st, SgFile* file, vector& messagesForFile, const map>& arrayLinksByFuncCalls) { int oldVar = st->variant(); st->setVariant(abs(st->variant())); SgStatement* conv = NULL; if (st->expr(1)->variant() == FUNC_CALL) { const string fName = st->expr(1)->symbol()->identifier(); if (fName == "sum") conv = convertFromSumToLoop(st, file, messagesForFile, arrayLinksByFuncCalls); } else { if ((st->expr(1)->variant() == ADD_OP || st->expr(1)->variant() == MULT_OP || st->expr(1)->variant() == SUBT_OP)) conv = convertFromStmtToLoop(st, file, messagesForFile, arrayLinksByFuncCalls); else { if (st->variant() == WHERE_NODE) conv = convertFromWhereToLoop(st, file, messagesForFile); else conv = convertFromAssignToLoop(st, file, messagesForFile, arrayLinksByFuncCalls); } } //move label if converted if (conv) moveLabelBefore(st); st->setVariant(oldVar); return conv; } // functionality: convert A[(...)] = B[(...)] to loop // move (create copy) init assigns in DECL before the first executable // move SPF ANALYSIS PARAMETER to assigns void convertFromAssignToLoop(SgFile *file, const vector& regions, vector &messagesForFile, const map>& arrayLinksByFuncCalls) { if (cacheNameShiftAll.find(file) == cacheNameShiftAll.end()) cacheNameShiftAll[file] = map>>(); int funcNum = file->numberOfFunctions(); auto useMapMod = createMapOfModuleUses(file); vector modules; findModulesInFile(file, modules); map modMap; for (auto& elem : modules) modMap[elem->symbol()->identifier()] = elem; for (int i = 0; i < funcNum; ++i) { SgStatement* st = file->functions(i); if (cacheNameShiftAll[file].find(st) == cacheNameShiftAll[file].end()) cacheNameShiftAll[file][st] = map>(); cacheNameShift = &cacheNameShiftAll[file][st]; SgStatement* lastNode = st->lastNodeOfStmt(); vector> toMove; SgStatement* firstExec = NULL; SgStatement* controlParFristExec = NULL; for (SgStatement* st1 = file->functions(i); st1 != lastNode && !firstExec; st1 = st1->lexNext()) { const int var = st1->variant(); if (isSgExecutableStatement(st1)) firstExec = st1; if ((var == CONTAINS_STMT || var == PROC_HEDR || var == FUNC_HEDR) && st1 != file->functions(i)) break; } if (firstExec) controlParFristExec = firstExec->controlParent(); set useMods; map> byUse = moduleRefsByUseInFunction(st); map derivedTypesDecl = createDerivedTypeDeclMap(st); bool isInTypeDecl = false; for (; st != lastNode; st = st->lexNext()) { if (st->variant() == CONTAINS_STMT) break; if (st->variant() == STRUCT_DECL) isInTypeDecl = true; if (st->variant() == CONTROL_END && st->controlParent()->variant() == STRUCT_DECL) isInTypeDecl = false; //move init assigns before the first statement // skip if in TYPE-END_TYPE construction if (firstExec && isSgDeclarationStatement(st) && !isInTypeDecl) { SgVarDeclStmt* declStat = (SgVarDeclStmt*)st; for (int k = 0; k < declStat->numberOfSymbols(); ++k) { SgExpression* completeInit = declStat->completeInitialValue(k); if (completeInit) { auto copyLeft = completeInit->lhs()->copyPtr(); auto copyRight = completeInit->rhs()->copyPtr(); SgStatement* toAdd = new SgStatement(ASSIGN_STAT, NULL, NULL, copyLeft, copyRight, NULL); if (isDerivedAssign(toAdd)) replaceDerivedAssigns(file, toAdd, firstExec, derivedTypesDecl); else { toAdd->setFileId(controlParFristExec->getFileId()); toAdd->setProject(controlParFristExec->getProject()); firstExec->insertStmtBefore(*toAdd, *controlParFristExec); toAdd->setlineNumber(getNextNegativeLineNumber()); toAdd->setLocalLineNumber(st->lineNumber()); } toMove.push_back(make_pair(st, toAdd)); } } } //move SPF ANALYSIS PARAMETER before current statement vector parameters; for (auto& attr : getAttributes(st, set{ SPF_ANALYSIS_DIR })) { SgExpression* exprList = attr->expr(0); while (exprList) { if (exprList->lhs()->variant() == SPF_PARAMETER_OP) { SgExpression* list = exprList->lhs()->lhs(); while (list) { if (list->lhs()->variant() != ASSGN_OP) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); parameters.push_back(new SgStatement(ASSIGN_STAT, NULL, NULL, list->lhs()->lhs()->copyPtr(), list->lhs()->rhs()->copyPtr(), NULL)); parameters.back()->setFileId(st->getFileId()); parameters.back()->setProject(st->getProject()); parameters.back()->setlineNumber(getNextNegativeLineNumber()); parameters.back()->setLocalLineNumber(attr->lineNumber()); list = list->rhs(); } } exprList = exprList->rhs(); } } for (auto& par : parameters) { st->insertStmtBefore(*par, *st->controlParent()); auto inserted = st->lexPrev(); inserted->setUnparseIgnore(true); inserted->addAttribute(SPF_PARAMETER_OP, st, sizeof(SgStatement*)); } if (firstExec && st->variant() == USE_STMT) useMods.insert(st); //TODO: change names by use //TODO: create init of decl for all USE map if (firstExec && isSgExecutableStatement(st)) { for (auto& elem : useMods) { auto it = modMap.find(elem->symbol()->identifier()); if (it == modMap.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (SgStatement* stM = it->second->lexNext(); stM != it->second->lastNodeOfStmt(); stM = stM->lexNext()) { if (isSgExecutableStatement(stM)) break; const int var = stM->variant(); if (var == PROC_HEDR || var == FUNC_HEDR) break; if (isSgDeclarationStatement(stM)) { SgVarDeclStmt* declStat = (SgVarDeclStmt*)stM; bool ifHasParameterAttr = false; for (int z = 0; z < declStat->numberOfAttributes(); ++z) if (declStat->attribute(z)->variant() == PARAMETER_OP) ifHasParameterAttr = true; if (ifHasParameterAttr) { for (int k = 0; k < declStat->numberOfSymbols(); ++k) { SgExpression* completeInit = declStat->completeInitialValue(k); if (completeInit) { SgStatement* toAdd = new SgStatement(ASSIGN_STAT, NULL, NULL, completeInit->lhs()->copyPtr(), completeInit->rhs()->copyPtr(), NULL); toAdd->setFileId(controlParFristExec->getFileId()); toAdd->setProject(controlParFristExec->getProject()); firstExec->insertStmtBefore(*toAdd, *controlParFristExec); toMove.push_back(make_pair(elem, toAdd)); toAdd->setlineNumber(getNextNegativeLineNumber()); toAdd->setLocalLineNumber(elem->lineNumber()); } } } } } } firstExec = NULL; } if (getRegionByLine(regions, st->fileName(), st->lineNumber()) && (st->variant() == ASSIGN_STAT || st->variant() == WHERE_NODE)) { SgStatement* conv = runConversion(st, file, messagesForFile, arrayLinksByFuncCalls); if (conv) { auto currFile = st->getFileId(); auto currProj = st->getProject(); st->insertStmtBefore(*conv, *st->controlParent()); toMove.push_back(make_pair(st, conv)); if (conv->variant() != ASSIGN_STAT) { SgStatement* end = conv->lastNodeOfStmt(); for (SgStatement* st1 = conv; st1 != end; st1 = st1->lexNext()) { st1->setlineNumber(getNextNegativeLineNumber()); st1->setLocalLineNumber(st->lineNumber()); st1->setFileId(currFile); st1->setProject(currProj); } end->setlineNumber(getNextNegativeLineNumber()); end->setLocalLineNumber(st->lineNumber()); end->setFileId(currFile); end->setProject(currProj); } else { conv->setlineNumber(getNextNegativeLineNumber()); conv->setLocalLineNumber(st->lineNumber()); conv->setFileId(currFile); conv->setProject(currProj); } //TODO: may be need to move more attributes //move only SPF_ANALYSIS_DIR attributes for (auto& attr : getAttributes(st, set{ SPF_ANALYSIS_DIR })) conv->addAttribute(SPF_ANALYSIS_DIR, attr, sizeof(SgStatement*)); } } } for (auto& move : toMove) { move.first->addAttribute(ASSIGN_STAT, move.second, sizeof(SgStatement*)); char* comments = move.first->comments(); if (comments) move.second->setComments(comments); } } } static bool isUnderParallelLoop(SgStatement * st) { bool isUnder = false; while (st) { const int var = st->variant(); if (var == FUNC_HEDR || var == PROG_HEDR || var == PROC_HEDR) break; if (var == FOR_NODE) { auto prev = st->lexPrev(); if (prev->variant() == DVM_PARALLEL_ON_DIR) { isUnder = true; break; } } st = st->controlParent(); } return isUnder; } static bool hasParallelDir(SgStatement * st) { bool has = false; SgStatement* last = st->lastNodeOfStmt(); while (st != last) { int var = st->variant(); if ((var == FOR_NODE || var == -FOR_NODE) && st->lexPrev()->variant() == DVM_PARALLEL_ON_DIR) has = true; st = st->lexNext(); } return has; } static void addToDeclSet(SgExpression* exp, set &symbolSet) { if (exp) { if (exp->symbol()) symbolSet.insert(OriginalSymbol(exp->symbol())->identifier()); if (exp->lhs()) addToDeclSet(exp->lhs(), symbolSet); if (exp->rhs()) addToDeclSet(exp->rhs(), symbolSet); } } void restoreConvertedLoopForParallelLoops(SgFile* file, const map>& arrayLinksByFuncCalls, bool reversed) { if (cacheNameShiftAll.find(file) == cacheNameShiftAll.end()) cacheNameShiftAll[file] = map>>(); int funcNum = file->numberOfFunctions(); for (int i = 0; i < funcNum; ++i) { SgStatement* st = file->functions(i); SgStatement* lastNode = st->lastNodeOfStmt(); if (cacheNameShiftAll[file].find(st) == cacheNameShiftAll[file].end()) cacheNameShiftAll[file][st] = map>(); cacheNameShift = &cacheNameShiftAll[file][st]; map newDeclarations; set declaratedInFunction; SgStatement* lastDeclarated = NULL; for (st = file->functions(i); st != lastNode; st = st->lexNext()) { if (isSgExecutableStatement(st)) break; if (st->variant() == CONTAINS_STMT) break; if (st->variant() != DATA_DECL && st->variant() != FORMAT_STAT) for (int i = 0; i < 3; ++i) addToDeclSet(st->expr(i), declaratedInFunction); if (st->fileName() == file->filename()) lastDeclarated = st; } vector toDel; vector messagesForFileTmp; for (st = file->functions(i); st != lastNode; st = st->lexNext()) { for (auto& data : getAttributes(st, set{ ASSIGN_STAT })) { if (reversed) { if (data->lineNumber() < 0) { data->setVariant(abs(data->variant())); auto secondConv = runConversion(st, file, messagesForFileTmp, arrayLinksByFuncCalls); if (secondConv && notDeletedVectorAssign(st)) st->setVariant(-abs(st->variant())); else st->setVariant(abs(st->variant())); } } else { if (data->lineNumber() < 0) { auto secondConv = runConversion(st, file, messagesForFileTmp, arrayLinksByFuncCalls); if (isUnderParallelLoop(st) || secondConv && notDeletedVectorAssign(st)) { st->setVariant(-abs(st->variant())); auto prev = st->lexPrev(); if (prev->variant() == DVM_REMOTE_ACCESS_DIR) toDel.push_back(prev); data->setVariant(abs(data->variant())); if (data->variant() == FOR_NODE || data->variant() == IF_NODE) { for (auto st_loc = data; st_loc != data->lastNodeOfStmt(); st_loc = st_loc->lexNext()) if (st_loc->variant() == FOR_NODE) newDeclarations[st_loc->symbol()->identifier()] = st_loc->symbol(); } else if (data->variant() == ASSIGN_STAT && data->lexNext()->variant() == FOR_NODE) { for (auto st_loc = data->lexNext(); st_loc != data->lexNext()->lastNodeOfStmt(); st_loc = st_loc->lexNext()) if (st_loc->variant() == FOR_NODE) newDeclarations[st_loc->symbol()->identifier()] = st_loc->symbol(); } } else data->setVariant(-abs(data->variant())); } } } } for (auto& elem : toDel) elem->extractStmt(); //insert new declaration of symbols for converted loops for (auto& toDecl : newDeclarations) { auto found = declaratedInFunction.find(toDecl.first); if (found == declaratedInFunction.end()) { declaratedInFunction.insert(toDecl.first); auto toInsert = toDecl.second->makeVarDeclStmt(); lastDeclarated->insertStmtAfter(*toInsert, *st->controlParent()); } } } } static map> newSymbDeclaredInFunction; bool needDeclare(SgStatement* start, SgStatement* end) { bool isImplicit = false; for (auto st = start; st != end && st; st = st->lexNext()) { if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st)) break; if (st->variant() == CONTAINS_STMT) break; if (st->variant() == IMPL_DECL) isImplicit = true; if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90) { SgExpression* list = st->expr(0); while (list) { if (list->lhs()->variant() == VAR_REF) newSymbDeclaredInFunction[start].insert(list->lhs()->symbol()->identifier()); list = list->rhs(); } } } return isImplicit; } set findLoopSymbolsToDecl(SgStatement* stat, const set& declared) { set retVal; set added; SgStatement* last = stat->lastNodeOfStmt(); for (auto st = stat; st != last; st = st->lexNext()) { auto isFor = isSgForStmt(st); if (isFor) { auto s = isFor->doName(); string ident = s->identifier(); if (ident.find("i_") != string::npos && s->type()->variant() == T_INT) { if (declared.find(ident) == declared.end() && added.find(ident) == added.end()) { retVal.insert(s); added.insert(ident); } } } } return retVal; } void restoreAssignsFromLoop(SgFile* file, const map>& arrayLinksByFuncCalls) { if (cacheNameShiftAll.find(file) == cacheNameShiftAll.end()) cacheNameShiftAll[file] = map>>(); int funcNum = file->numberOfFunctions(); for (int i = 0; i < funcNum; ++i) { SgStatement* currF = file->functions(i); if (cacheNameShiftAll[file].find(currF) == cacheNameShiftAll[file].end()) cacheNameShiftAll[file][currF] = map>(); cacheNameShift = &cacheNameShiftAll[file][currF]; SgStatement* lastNode = currF->lastNodeOfStmt(); bool needDecl = needDeclare(currF, lastNode); vector> toMove; for (auto st = file->functions(i); st != lastNode; st = st->lexNext()) { if (st->variant() == CONTAINS_STMT) break; for (auto& data : getAttributes(st, set{ ASSIGN_STAT })) if (data->lineNumber() < 0) toMove.push_back(make_pair(st, data)); } vector messagesForFileTmp; for (auto& move : toMove) { auto secondConv = runConversion(move.first, file, messagesForFileTmp, arrayLinksByFuncCalls); if (secondConv && notDeletedVectorAssign(move.first)) { move.first->setVariant(-abs(move.first->variant())); if (needDecl) // declare loops symbol { auto it = newSymbDeclaredInFunction.find(currF); set empty; set newDecl; if (it != newSymbDeclaredInFunction.end()) newDecl = findLoopSymbolsToDecl(secondConv, it->second); else newDecl = findLoopSymbolsToDecl(secondConv, empty); if (newDecl.size()) { vector newDeclV(newDecl.begin(), newDecl.end()); makeDeclaration(currF, newDeclV); for (auto& elem : newDecl) newSymbDeclaredInFunction[currF].insert(elem->identifier()); } } } else move.second->setVariant(-abs(move.second->variant())); } } }