#include #include "sage++user.h" #include "definesValues.h" #include "set.h" #include "definitionSet.h" #include "inducVar.h" #include "depGraph.h" #ifdef __SPF extern "C" void addToCollection(const int line, const char *file, void *pointer, int type); extern "C" void removeFromCollection(void *pointer); #endif extern int countPerfectLoopNest(SgStatement*); /////////////////////////////////////////////////////////////////////////////////////// // some global declarations /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// // Loop Transformation Sets. (the validity checkings for the transformations // are in the depGraph method. /////////////////////////////////////////////////////////////////////////////////////// // // b is the outer loopm // permut specify the loop permutations // the n outermost loops must be perfectly nested // permut start at 0; Example // do i = 0 // do j = 8 // do k = 1 // .... // permut = [2,1,0] // gives // do k = 1 // do j = 8 // do i = 0 // .... // int loopInterchange(SgStatement *b, int *permut, int n) { SgSymbol *tab_symb[MAXNESTEDLOOP]; SgExpression *tab_bf[MAXNESTEDLOOP]; SgExpression * tab_bi[MAXNESTEDLOOP]; SgExpression * tab_step[MAXNESTEDLOOP]; SgForStmt *loop, *tloop; int i; if (!(loop = isSgForStmt(b))) return 0; if (n > countPerfectLoopNest(loop)) { Message("Interchange loop error, loops are not perfectly nested", loop->lineNumber()); return 0; } tloop = loop; for (i = 0; (i < n); i++) { tab_symb[i] = tloop->symbol(); tab_bf[i] = tloop->start(); tab_bi[i] = tloop->end(); tab_step[i] = tloop->step(); tloop = isSgForStmt(tloop->getNextLoop()); } tloop = loop; for (i = 0; (i < n); i++) { if (tab_symb[permut[i]]) tloop->setSymbol(*tab_symb[permut[i]]); if (tab_bf[permut[i]]) tloop->setStart(*tab_bf[permut[i]]); if (tab_bi[permut[i]]) tloop->setEnd(*tab_bi[permut[i]]); if (tab_step[permut[i]]) tloop->setStep(*tab_step[permut[i]]); tloop = isSgForStmt(tloop->getNextLoop()); } return 1; } // // Tile a loop. // assumed to be perfectly nested. // size is NO_STEP we do not want it to be tiled // int tileLoops(SgStatement *func, SgStatement *b, int *size, int nb) { int i, j; SgSymbol *tab_symb[MAXNESTEDLOOP]; SgStatement *body, *ptstmt; SgForStmt *internal_loop, *temp, *last_loop; SgForStmt *loop, *temloo; SgExpression *borne_inf[MAXNESTEDLOOP]; SgExpression *borne_sup[MAXNESTEDLOOP]; SgExpression *step[MAXNESTEDLOOP]; SgType *typint; SgSymbol *min_fonc; char strfoname[256]; if (!(loop = isSgForStmt(b)) || !func) return 0; if (nb > countPerfectLoopNest(loop)) { Message("loop Tilling error, loops are not perfectly nested", loop->lineNumber()); return 0; } if (nb == 0) return 0; if (nb >= MAXNESTEDLOOP) { Message("Too many nested level", b->lineNumber()); return 0; } for (i = 0; i < MAXNESTEDLOOP; i++) { tab_symb[i] = NULL; borne_inf[i] = NULL; borne_sup[i] = NULL; step[i] = NULL; } last_loop = loop; for (i = 0; i < nb; i++) { if (size[i] != NO_STEP) { if (last_loop->step()) { Message("Cannot tile loop, there is already a step", last_loop->lineNumber()); return 0; } } last_loop = isSgForStmt(last_loop->getNextLoop()); } // Get integer type; typint = SgTypeInt(); // get the indexes of the loops; temloo = loop; for (i = 0; i < nb; i++) { tab_symb[i] = temloo->symbol(); internal_loop = temloo; temloo = isSgForStmt(temloo->getNextLoop()); } if (!internal_loop) { Message("Internal loop not found", loop->lineNumber()); return 0; } // generate the new symbol and declare them for (i = 0; i < nb; i++) { sprintf(strfoname, "iT%d_%d", loop->id(), i); tab_symb[i + nb] = new SgVariableSymb(strfoname); #ifdef __SPF addToCollection(__LINE__, __FILE__, tab_symb[i + nb], 1); #endif tab_symb[i + nb]->declareTheSymbol(*func); } last_loop = loop; for (i = 0; i < nb; i++) { if (size[i] != NO_STEP) { SgValueExp *tmp = (new SgValueExp(size[i] + 1)); last_loop->setStep(*tmp); #ifdef __SPF addToCollection(__LINE__, __FILE__, tmp, 1); #endif } last_loop = isSgForStmt(last_loop->getNextLoop()); } // create a min function; min_fonc = new SgSymbol(FUNCTION_NAME, "min", *typint, *(loop->controlParent())); #ifdef __SPF addToCollection(__LINE__, __FILE__, min_fonc, 1); #endif // creation of the bound expressions; last_loop = loop; for (i = 0; i < nb; i++) { if (size[i] != NO_STEP) { SgFunctionCallExp *cexp; borne_inf[i + nb] = new SgValueExp(0); cexp = new SgFunctionCallExp(*min_fonc); borne_sup[i + nb] = cexp; SgValueExp *tmp = (new SgValueExp(size[i])); SgVarRefExp *tmp1 = (new SgVarRefExp(*tab_symb[i])); cexp->addArg(((last_loop->end())->copy()) - *tmp1); cexp->addArg(*tmp); #ifdef __SPF addToCollection(__LINE__, __FILE__, borne_inf[i + nb], 1); addToCollection(__LINE__, __FILE__, cexp, 1); addToCollection(__LINE__, __FILE__, tmp, 1); addToCollection(__LINE__, __FILE__, tmp1, 1); #endif } else { borne_inf[i + nb] = new SgValueExp(1); borne_sup[i + nb] = &((last_loop->end())->copy()); #ifdef __SPF addToCollection(__LINE__, __FILE__, borne_inf[i + nb], 1); #endif } step[i + nb] = NULL; last_loop = isSgForStmt(last_loop->getNextLoop()); } // remove the loop body; // update the steps; body = internal_loop->extractStmtBody(); // upper bound for NO_STEP loops last_loop = loop; for (i = 0; i < nb; i++) { if (size[i] == NO_STEP) { SgValueExp *tmp = (new SgValueExp(1)); last_loop->setEnd(*tmp); #ifdef __SPF addToCollection(__LINE__, __FILE__, tmp, 1); #endif } last_loop = isSgForStmt(last_loop->getNextLoop()); } // create the new loop; last_loop = internal_loop; for (i = 0; i < nb; i++) { loop = new SgForStmt(tab_symb[i + nb], borne_inf[i + nb], borne_sup[i + nb], step[i + nb], NULL); #ifdef __SPF addToCollection(__LINE__, __FILE__, loop, 1); #endif last_loop->insertStmtAfter(*loop, *last_loop); last_loop = loop; } // update the loop body; if (!body || !last_loop) { Message("The loop may not have a body or internal error", 0); return 0; } last_loop->insertStmtAfter(*body, *last_loop); for (j = 0; j < last_loop->numberOfChildrenList1(); j++) { ptstmt = last_loop->childList1(j); if (ptstmt) { for (i = 0; i < nb; i++) { if (size[i] != NO_STEP) { SgVarRefExp *tmp = (new SgVarRefExp(*tab_symb[i])); SgVarRefExp *tmp1 = (new SgVarRefExp(*tab_symb[i + nb])); ptstmt->replaceSymbByExp(*tab_symb[i], *tmp + *tmp1); #ifdef __SPF addToCollection(__LINE__, __FILE__, tmp, 1); addToCollection(__LINE__, __FILE__, tmp1, 1); #endif } else { SgVarRefExp *tmp = (new SgVarRefExp(*tab_symb[i])); ptstmt->replaceSymbByExp(*tab_symb[i], *tmp); #ifdef __SPF addToCollection(__LINE__, __FILE__, tmp, 1); #endif } } } } return 1; } // // distribute the loops according to the // table of SCC. // for instance consider the following loop // // do i= 1,100 //[1] x = 2 //[2] do j= 1,100 // D(j+i) = A(i,j) // D(j+i) = A(i,j) // enddo //[3] x = 2 // enddo // and the following content of the // [[1,3],2] scc table index // int distributeLoopSCC(SgStatement *b, int *sccTable, int leadingdim, int numSCC) { int i, j; SgStatement *last, **sccloop, **sccextracted, *ptstm; SgStatement *previous, *cp, *copl; SgForStmt *loop; int nbstat; if (!(loop = isSgForStmt(b)) || !sccTable) return 0; nbstat = loop->numberOfChildrenList1() - 1; // does not remove the controlend; sccloop = new SgStatement *[numSCC]; sccextracted = new SgStatement *[nbstat]; #ifdef __SPF addToCollection(__LINE__, __FILE__, sccloop, 2); addToCollection(__LINE__, __FILE__, sccextracted, 2); #endif for (j = 0; j < nbstat; j++) { ptstm = loop->childList1(j); sccextracted[j] = ptstm; } for (j = 0; j < nbstat; j++) { if (sccextracted[j]) sccextracted[j]->extractStmt(); } // now creates the loop; previous = loop->nodeBefore(); cp = loop->controlParent(); loop->extractStmt(); copl = &(loop->copy()); previous->insertStmtAfter(*loop, *cp); sccloop[0] = loop; last = loop->lastNodeOfStmt(); // need to extractloop before doing the copy; for (j = 1; j < numSCC; j++) { if (j == numSCC - 1) sccloop[j] = copl; else sccloop[j] = &(copl->copy()); last->insertStmtAfter(*(sccloop[j]), *cp); last = sccloop[j]->lastNodeOfStmt(); } for (j = 0; j < numSCC; j++) { for (i = leadingdim - 1; i >= 0; i--) { // insert in the right body the statement; // go revserse order; simpler; if (sccTable[j*leadingdim + i]) if (sccextracted[sccTable[j*leadingdim + i] - 1]) sccloop[j]->insertStmtAfter(*sccextracted[sccTable[j*leadingdim + i] - 1], *sccloop[j]); } } #ifdef __SPF removeFromCollection(sccloop); removeFromCollection(sccextracted); #endif delete []sccloop; delete []sccextracted; return 1; } // // Takes two loops and fusion the bodies // int loopFusion(SgStatement *loop1, SgStatement *loop2) { SgForStmt *doloop1; SgForStmt *doloop2; SgStatement *body, *last; if (!(doloop1 = isSgForStmt(loop1))) return 0; if (!(doloop2 = isSgForStmt(loop2))) return 0; if (!doloop1->symbol()) return 0; SgVarRefExp *tmp = (new SgVarRefExp(*doloop1->symbol())); doloop2->replaceSymbByExp(*doloop2->symbol(), *tmp); #ifdef __SPF addToCollection(__LINE__, __FILE__, tmp, 1); #endif body = doloop2->extractStmtBody(); if (!body) return 0; last = doloop1->lastNodeOfStmt(); if (!last) return 0; last = last->nodeBefore(); if (!last) return 0; last->insertStmtAfter(*body, *doloop1); doloop2->extractStmt(); return 1; }