Files
SAPFOR/Sapfor/_src/SageAnalysisTool/depGraph.cpp

1388 lines
40 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <algorithm>
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
#if __SPF && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
#include "../GraphCall/graph_calls.h"
#include "../Utils/errors.h"
#include "../VisualizerCalls/get_information.h"
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
#include "arrayRef.h"
#include "depGraph.h"
#include "intrinsic.h"
using std::vector;
using std::set;
using std::map;
using std::string;
using std::pair;
///////////////////////////////////////////////////////////////////////////////////////
// to link with the omega Test
///////////////////////////////////////////////////////////////////////////////////////
#include "OmegaForSage/include/portable.h"
#include "OmegaForSage/include/affine.h"
///////////////////////////////////////////////////////////////////////////////////////
// some global declarations
///////////////////////////////////////////////////////////////////////////////////////
depGraph *currentDepGraph = NULL;
extern SgStatement *currentStmtIn;
extern SgStatement *currentStmtOut;
extern SgExpression *currentVarIn;
extern SgExpression *currentVarOut;
///////////////////////////////////////////////////////////////////////////////////////
// for data dependence computation (uses omega Test) (dependence.C)
///////////////////////////////////////////////////////////////////////////////////////
extern Set* computeLoopDependencies(SgStatement *func, Set *inset, SgSymbol **tsymb, Set *induc);
extern int lexOrder(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2);
///////////////////////////////////////////////////////////////////////////////////////
// Part for computing array reference (arrayRef.C)
///////////////////////////////////////////////////////////////////////////////////////
extern Set* loopArrayAccessAnalysis(SgStatement *func, SgStatement *stmt, SgSymbol **tsymb, Set **induc, const set<string> &privVars);
///////////////////////////////////////////////////////////////////////////////////////
// declaration for defuse and reaching definition (defUse.C)
///////////////////////////////////////////////////////////////////////////////////////
extern void initDefUseTable(SgStatement *func, const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile);
extern Set *makeGenSet(SgStatement *func, SgStatement *stmt);
extern Set *makeKillSet(SgStatement *func, SgStatement *stmt);
extern int symbRefEqual(void *e1, void *e2);
extern void myPrint(void *e1);
///////////////////////////////////////////////////////////////////////////////////////
// declaration for the data flow framework
///////////////////////////////////////////////////////////////////////////////////////
extern void iterativeForwardFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*giveGenSet)(SgStatement *func, SgStatement *stmt),
Set *(*giveKillSet)(SgStatement *func, SgStatement *stmt),
int(*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void(*fp)(void *e1));
///////////////////////////////////////////////////////////////////////////////////////
// Utility Functions
///////////////////////////////////////////////////////////////////////////////////////
void convertContLoopToEnddo(SgStatement *stmt)
{
SgForStmt *doloop;
SgStatement *temp, *child;
int i;
if (!stmt)
return;
if (doloop = isSgForStmt(stmt))
{
doloop->convertLoop();
}
i = 1;
temp = stmt;
child = temp->childList1(0);
while (child)
{
convertContLoopToEnddo(child);
child = temp->childList1(i);
i++;
}
i = 1;
temp = stmt;
child = temp->childList2(0);
while (child)
{
convertContLoopToEnddo(child);
child = temp->childList2(i);
i++;
}
}
///////////////////////////////////////////////////////////////////////////////////////
// Here are the methods of depNode
///////////////////////////////////////////////////////////////////////////////////////
depNode::depNode(SgStatement *sin, SgStatement *sout,
SgExpression *vin, SgExpression *vout,
int tdep, int kdep, int *dist, int *kdist, int le)
{
int i;
stmtin = sin;
stmtout = sout;
varin = vin;
varout = vout;
typedep = tdep;
kinddep = kdep;
lenghtvect = le;
if (tdep == ARRAYDEP)
{
distance.resize(le + 1);
knowndist.resize(le + 1);
for (i = 0; i < le + 1; ++i)
{
distance[i] = dist[i];
knowndist[i] = kdist[i];
}
}
}
depNode::~depNode()
{
// Message("Delete depNode Not implemented yet",0);
}
pair<string, string> depNode::createDepMessagebetweenArrays() const
{
string retEng;
string retRus;
char buf[1024];
if (typedep == ARRAYDEP)
{
ddnature nature = (ddnature)kinddep;
switch (nature)
{
case ddflow:
retEng += "Flow dependence between ";
retRus += "Flow#";
break;
case ddanti:
retEng += "Anti dependence between ";
retRus += "Anti#";
break;
case ddoutput:
retEng += "Output dependence between ";
retRus += "Output#";
break;
case ddreduce:
retEng += "Reduce dependence between ";
retRus += "Reduce#";
break;
}
retEng += varin->unparse();
retRus += varin->unparse();
sprintf(buf, " (line %d)", stmtin->lineNumber());
retEng += buf;
sprintf(buf, "#%d", stmtin->lineNumber());
retRus += buf;
retEng += " and ";
retRus += "#";
retEng += varout->unparse();
retRus += varout->unparse();
sprintf(buf, " (line %d)", stmtout->lineNumber());
retEng += buf;
sprintf(buf, "#%d", stmtout->lineNumber());
retRus += buf;
}
return std::make_pair(retEng, retRus);
}
void depNode::displayDep(bool onlyDifferentLines) const
{
SgExpression *ex1, *ex2;
int i;
ddnature nature;
ex1 = varin;
ex2 = varout;
if (!typedep)
{
printf("UNKNOWN DATA DEPENDENCE\n");
return;
}
if (typedep == ARRAYDEP)
{
//skip
if (stmtin->lineNumber() == stmtout->lineNumber() && onlyDifferentLines)
return;
nature = (ddnature)kinddep;
printf("------> ");
switch (nature)
{
case ddflow:
printf("FLOW dependence between ");
break;
case ddanti:
printf("ANTI dependence between ");
break;
case ddoutput:
printf("OUTPUT dependence between ");
break;
case ddreduce:
printf("REDUCE dependence between ");
break;
}
ex1->unparsestdout();
printf(" (line %d) and ", stmtin->lineNumber());
ex2->unparsestdout();
printf(" (line %d) with vector (", stmtout->lineNumber());
for (i = 1; i <= lenghtvect; i++)
{
if (knowndist[i])
printf("%d", distance[i]);
else
{
if (distance[i] & DEPZERO)
{
printf("0");
}
if (distance[i] & DEPGREATER)
{
printf("+");
}
if (distance[i] & DEPLESS)
{
printf("-");
}
}
if (i < lenghtvect)
printf(", ");
}
printf(")\n");
}
else
{
printf("------> ");
printf("This is a Scalar Dep on ");
ex1->unparsestdout();
if (typedep == PRIVATEDEP)
printf(" and variable can be PRIVATE");
if (typedep == REDUCTIONDEP)
printf(" and variable can be REDUCTION with kind %d", kinddep);
printf("\n");
}
}
std::string depNode::displayDepToStr() const
{
std::string out = "";
SgExpression *ex1, *ex2;
int i;
ddnature nature;
ex1 = varin;
ex2 = varout;
if (!typedep)
{
out += "UNKNOWN DATA DEPENDENCE";
return out;
}
if (typedep == ARRAYDEP)
{
nature = (ddnature)kinddep;
switch (nature)
{
case ddflow:
out += "Flow dependence between ";
break;
case ddanti:
out += "Anti dependence between ";
break;
case ddoutput:
out += "Output dependence between ";
break;
case ddreduce:
out += "Reduce dependence between ";
break;
}
out += string(ex1->unparse());
out += " (line (" + std::to_string(stmtin->lineNumber()) + ") and ";
out += string(ex2->unparse());
out += " (line " + std::to_string(stmtout->lineNumber()) + ") with vector (";
for (i = 1; i <= lenghtvect; i++)
{
if (knowndist[i])
out += std::to_string(distance[i]);
else
{
if (distance[i] & DEPZERO)
out += "0";
if (distance[i] & DEPGREATER)
out += "+";
if (distance[i] & DEPLESS)
out += "-";
}
if (i < lenghtvect)
out += ", ";
}
out += ")";
}
else
{
out += "This is a Scalar Dep on ";
out += string(ex1->unparse());
if (typedep == PRIVATEDEP)
out += " and variable can be PRIVATE";
if (typedep == REDUCTIONDEP)
out += " and variable can be REDUCTION with kind " + std::to_string((int)kinddep);
}
return out;
}
///////////////////////////////////////////////////////////////////////////////////////
// Here are the methods of depGraph
///////////////////////////////////////////////////////////////////////////////////////
depGraph::depGraph(SgFile *fi, SgStatement *f, SgStatement *l, const set<string> &privVars) : privVars(privVars)
{
SgForStmt *doloop;
if (!l || !f)
{
Message("Cannot Create Dependence Graph", 0);
return;
}
if (doloop = isSgForStmt(l))
{
func = f;
loop = l;
file = fi;
tabstat = NULL;
nbstmt = 0;
tabtag = NULL;
loopnum = 0;
induc = NULL;
currentDepGraph = this;
perfectNestedLevel = doloop->isPerfectLoopNest();
// We now compute the dependence Graph;
arrayRef = loopArrayAccessAnalysis(func, loop, tsymb, &induc, privVars);
createNeededException();
computeLoopDependencies(func, arrayRef, tsymb, induc);
scalarRefAnalysis(loop);
}
else
{
Message("Cannot Create Dependence Graph; not a doloop", 0);
return;
}
}
depGraph::~depGraph()
{
//Message("Delete depGraph Not implemented yet", 0);
for (int i = 0; i < nodes.size(); ++i)
{
#ifdef __SPF
removeFromCollection(nodes[i]);
#endif
delete nodes[i];
}
}
void depGraph::addAnEdge(SgStatement *sin, SgStatement *sout,
SgExpression *vin, SgExpression *vout,
int tdep, int kdep, int *dist, int *kdist, int le)
{
depNode *datadep;
datadep = new depNode(sin, sout, vin, vout, tdep, kdep, dist, kdist, le);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, datadep, 1);
#endif
nodes.push_back(datadep);
}
depNode *depGraph::firstNode()
{
return nodes[0];
}
const std::vector<depNode*>& depGraph::getNodes() const
{
return nodes;
}
void depGraph::display(bool onlyDifferentLines)
{
printf("-------------------------------------------------------------------\n");
printf("----------------- Print Data Dependence Graph----------------------\n");
printf("-------------------------------------------------------------------\n");
//loop->unparsestdout();
for (unsigned i = 0; i < nodes.size(); ++i)
nodes[i]->displayDep(onlyDifferentLines);
printf("-------------------------------------------------------------------\n");
printf("----------------- End Data Dependence Graph----------------------\n");
printf("-------------------------------------------------------------------\n");
}
int stmtLexOrder(SgStatement *el1, SgStatement *el2)
{
SgStatement *stmt;
if (!el1 || !el2)
return FALSE;
if (el1 == el2)
return FALSE;
if (!el1 || !el2)
return FALSE;
stmt = el1;
while (stmt)
{
if (stmt == el2)
return TRUE;
stmt = stmt->lexNext();
}
return FALSE;
}
//
// Do the scalar analysis, try to recognize private and reductions variables
// leave induction variables (this is for known quite simple)
// uses also the arrayRef set that already contains references to scalar that are not
// induction variable.
//
//
// looking for patterns of the scalar analysis
// Look if there is a write that is before all the other use of the scalar
// variable;
int isItPrivate(int firstrefin, PT_ACCESSARRAY access1, Set *arrayset, SgStatement *loop)
{
PT_ACCESSARRAY writeaccess, access2;
int i, j, notFound;
int firstref = firstrefin;
int inifirstref;
SgForStmt *doloop;
SgStatement *forcheck;
if (!(doloop = isSgForStmt(loop)))
{
Message("No loop given in isItPrivate", 0);
return 0;
}
if (!access1)
{
Message("internal error in isItPrivate", 0);
return 0;
}
inifirstref = firstref;
while (firstref < arrayset->size())
{
writeaccess = NULL;
for (j = firstref; (j < arrayset->size()); j++)
{
access2 = (PT_ACCESSARRAY)arrayset->getElement(j);
if (access2 && access2->scalar && access2->stmt && loop->isIncludedInStmt(*(access2->stmt)) &&
(access1->var->symbol() == access2->var->symbol()))
{
if (access2->rw)
{
writeaccess = access2;
firstref = j + 1;
break;
}
}
}
if (!writeaccess)
break;
// now check that the write access is before, in lexical order;
notFound = 0;
for (j = inifirstref; (j < arrayset->size()) && !notFound; j++)
{
access2 = (PT_ACCESSARRAY)arrayset->getElement(j);
if ((access2 != writeaccess) && loop->isIncludedInStmt(*(access2->stmt)))
{
if (access2 && access2->scalar && (access1->var->symbol() == access2->var->symbol()))
{
if (!lexOrder(writeaccess, access2))
{
notFound = 1;
}
}
}
}
if (!notFound)
{
for (j = inifirstref; (j < arrayset->size()) && !notFound; j++)
{
access2 = (PT_ACCESSARRAY)arrayset->getElement(j);
if ((access2 != writeaccess) && loop->isIncludedInStmt(*(access2->stmt)))
{
if (access2 && access2->scalar && (access1->var->symbol() == access2->var->symbol()))
{
if (!access2->stmt || !writeaccess->stmt)
Message("Statement not set on array access; core dump is coming", 0);
if (access2->stmt->controlParent() != writeaccess->stmt->controlParent())
{
// check that the control parent is after;
if (!stmtLexOrder(writeaccess->stmt, access2->stmt->controlParent()))
{
notFound = 1;
}
}
}
}
}
}
if (!notFound)
return 1;
}
return 0;
}
//
// look for reduction var the type of the reduction op
//
SgExpression *lookForFather(SgExpression *root, SgExpression *expr)
{
SgExpression *temp;
if (!root || !expr)
return NULL;
if (root->rhs() == expr)
return root;
if (root->lhs() == expr)
return root;
if (temp = lookForFather(root->rhs(), expr))
return temp;
if (temp = lookForFather(root->lhs(), expr))
return temp;
return NULL;
}
#include "reductionCode.h"
int lookForOperationKind(PT_ACCESSARRAY access)
{
SgStatement *stmt;
SgSymbol *sy;
SgExpression *father;
if (!access)
return 0;
sy = access->var->symbol();
stmt = access->stmt;
if (!sy || !stmt)
return 0;
SgExpression* topOper = stmt->expr(1);
if (father = lookForFather(stmt->expr(1), access->var))
{
while (father && (father != access->var) && (father->variant() == EXPR_LIST))
father = lookForFather(stmt->expr(1), father);
if (!father)
return UNKNOWREDUCTION;
if (!sy->type())
return UNKNOWREDUCTION;
switch (father->variant())
{
case ADD_OP:
case SUBT_OP:
switch (sy->type()->variant())
{
case T_INT:
return IADDREDUCTION;
case T_COMPLEX:
case T_FLOAT:
return SADDREDUCTION;
case T_DCOMPLEX:
case T_DOUBLE:
return DADDREDUCTION;
default:
return UNKNOWREDUCTION;
}
case MULT_OP:
if (topOper != father)
return UNKNOWREDUCTION;
switch (sy->type()->variant())
{
case T_INT:
return IMULREDUCTION;
case T_COMPLEX:
case T_FLOAT:
return SMULREDUCTION;
case T_DCOMPLEX:
case T_DOUBLE:
return DMULREDUCTION;
default:
return UNKNOWREDUCTION;
}
case AND_OP:
if (topOper != father)
return UNKNOWREDUCTION;
switch (sy->type()->variant())
{
case T_BOOL:
return ANDREDUCTION;
default:
return UNKNOWREDUCTION;
}
case OR_OP:
if (topOper != father)
return UNKNOWREDUCTION;
switch (sy->type()->variant())
{
case T_BOOL:
return ORREDUCTION;
default:
return UNKNOWREDUCTION;
}
case EQV_OP:
if (topOper != father)
return UNKNOWREDUCTION;
switch (sy->type()->variant())
{
case T_BOOL:
return EQVREDUCTION;
default:
return UNKNOWREDUCTION;
}
case NEQV_OP:
if (topOper != father)
return UNKNOWREDUCTION;
switch (sy->type()->variant())
{
case T_BOOL:
return NEQVREDUCTION;
default:
return UNKNOWREDUCTION;
}
case FUNC_CALL://TODO with max and min
if (topOper != father)
return UNKNOWREDUCTION;
if (father->symbol() &&
(strcmp(father->symbol()->identifier(), "max") == 0 ||
strcmp(father->symbol()->identifier(), "dmax") == 0 ||
strcmp(father->symbol()->identifier(), "dmax1") == 0))
{
switch (sy->type()->variant())
{
case T_INT:
return IMAXREDUCTION;
case T_COMPLEX:
case T_FLOAT:
return SMAXREDUCTION;
case T_DCOMPLEX:
case T_DOUBLE:
return DMAXREDUCTION;
}
}
if (father->symbol() &&
(strcmp(father->symbol()->identifier(), "min") == 0 ||
strcmp(father->symbol()->identifier(), "dmin") == 0 ||
strcmp(father->symbol()->identifier(), "dmin1") == 0))
{
switch (sy->type()->variant())
{
case T_INT:
return IMINREDUCTION;
case T_COMPLEX:
case T_FLOAT:
return SMINREDUCTION;
case T_DCOMPLEX:
case T_DOUBLE:
return DMINREDUCTION;
}
}
return UNKNOWREDUCTION;
}
}
return UNKNOWREDUCTION;
}
//
// check if a scalar variable is a reduction variable
// does not compute yet the kind of the reduction
//
static bool setNewKind(int &reductionKind, const int newKind)
{
bool needBreak = false;
if (reductionKind == UNKNOWREDUCTION)
reductionKind = newKind;
else if (reductionKind != newKind)
{
reductionKind = UNKNOWREDUCTION;
needBreak = true;
}
return needBreak;
}
int isItReduction(int firstref, PT_ACCESSARRAY access1, Set *arrayset, SgStatement *loop)
{
PT_ACCESSARRAY access2, lastaccess, firstaccess;
int i, j;
if (!loop)
{
Message("No loop given in isItReduction", 0);
return UNKNOWREDUCTION;
}
if (!access1)
{
Message("internal error in isItReduction", 0);
return UNKNOWREDUCTION;
}
// check how many accesses to the variable;
std::map<SgStatement*, set<PT_ACCESSARRAY>> accessesForStat;
firstaccess = (PT_ACCESSARRAY)arrayset->getElement(firstref);
accessesForStat[firstaccess->stmt].insert(firstaccess);
lastaccess = NULL;
for (j = firstref + 1; (j < arrayset->size()); j++)
{
access2 = (PT_ACCESSARRAY)arrayset->getElement(j);
if (access2 && access2->scalar &&
loop->isIncludedInStmt(*(access2->stmt)) &&
(access1->var->symbol() == access2->var->symbol()))
{
lastaccess = access2;
accessesForStat[lastaccess->stmt].insert(lastaccess);
}
}
//united to controlParent (IF, LOGIF_NODE, ...)
bool changes = true;
while (changes)
{
changes = false;
bool done = false;
for (auto ACC = accessesForStat.begin(); ACC != accessesForStat.end(); ACC++)
{
for (auto ACC1 = accessesForStat.begin(); ACC1 != accessesForStat.end(); ACC1++)
{
if (ACC1->first == ACC->first)
continue;
if (ACC1->first->variant() == ASSIGN_STAT)
{
if (ACC1->first->controlParent() == ACC->first)
{
ACC->second.insert(ACC1->second.begin(), ACC1->second.end());
accessesForStat.erase(ACC1);
done = true;
changes = true;
break;
}
}
if (ACC1->first->variant() == ASSIGN_STAT)
{
if (ACC1->first->controlParent() == ACC1->first)
{
ACC1->second.insert(ACC->second.begin(), ACC->second.end());
accessesForStat.erase(ACC);
done = true;
changes = true;
break;
}
}
}
if (done)
break;
}
}
std::map<SgStatement*, set<PT_ACCESSARRAY>> newAccessesForStat;
for (auto &ACC : accessesForStat)
{
auto &elem = ACC.second;
bool isIfStat = ACC.first->variant() == IF_NODE || ACC.first->variant() == LOGIF_NODE;
// only read under IF stat was accepted
if (elem.size() == 1)
{
firstaccess = *elem.begin();
if (firstaccess->rw == 0 && isIfStat)
continue;
else
return UNKNOWREDUCTION;
} // more then 2 accesses in one statement
else if (elem.size() != 2)
return UNKNOWREDUCTION;
// must be an assign statement or IF/LOGIF_NODE;
if (ACC.first->variant() != ASSIGN_STAT && !isIfStat)
return UNKNOWREDUCTION;
firstaccess = *elem.begin();
lastaccess = *elem.rbegin();
// one of them must be read and another one - write
if (firstaccess->rw && lastaccess->rw)
return UNKNOWREDUCTION;
newAccessesForStat[ACC.first] = ACC.second;
}
accessesForStat = newAccessesForStat;
int reductionKind = UNKNOWREDUCTION;
for (auto &ACC : accessesForStat)
{
auto &elem = ACC.second;
firstaccess = *elem.begin();
lastaccess = *elem.rbegin();
if (ACC.first->variant() == ASSIGN_STAT)
{
int kind;
//look for the reduction operations;
if (firstaccess->rw)
kind = lookForOperationKind(lastaccess);
else
kind = lookForOperationKind(firstaccess);
if (setNewKind(reductionKind, kind))
break;
} // IF_NODE, LOGIF_NODE
else
{
if (firstaccess->stmt->variant() == ASSIGN_STAT)
std::swap(firstaccess, lastaccess);
SgExpression *cond = firstaccess->stmt->expr(0);
if (cond->lhs() == NULL || cond->rhs() == NULL)
return UNKNOWREDUCTION;
switch (cond->variant())
{
case LT_OP:
case LE_OP:
if (cond->lhs()->variant() == VAR_REF && cond->lhs()->symbol() == firstaccess->var->symbol())
{
if (setNewKind(reductionKind, IMAXREDUCTION))
return reductionKind;
}
else if (cond->rhs()->variant() == VAR_REF && cond->rhs()->symbol() == firstaccess->var->symbol())
{
if (setNewKind(reductionKind, IMINREDUCTION))
return reductionKind;
}
else
return UNKNOWREDUCTION;
break;
case GT_OP:
case GE_OP:
if (cond->lhs()->variant() == VAR_REF && cond->lhs()->symbol() == firstaccess->var->symbol())
{
if (setNewKind(reductionKind, IMINREDUCTION))
return reductionKind;
}
else if (cond->rhs()->variant() == VAR_REF && cond->rhs()->symbol() == firstaccess->var->symbol())
{
if (setNewKind(reductionKind, IMAXREDUCTION))
return reductionKind;
}
else
return UNKNOWREDUCTION;
break;
default:
return UNKNOWREDUCTION;
}
}
}
return reductionKind;
}
//
// main function for scalar analysis
//
void depGraph::scalarRefAnalysis(SgStatement *loop)
{
PT_ACCESSARRAY access1, access2;
int i, j;
int done, thereisawrite, thewrite;
if (!arrayRef)
{
Message("No reference to treat in scalarRefAnalysis", 0);
return;
}
if (!loop)
{
Message("No loop given in scalarRefAnalysis", 0);
return;
}
for (i = 0; i < arrayRef->size(); i++)
{
access1 = (PT_ACCESSARRAY)arrayRef->getElement(i);
if (loop->isIncludedInStmt(*(access1->stmt)))
{
if (access1 && access1->scalar)
{
// check if already done;
done = 0;
for (j = 0; (j < i) && (!done); j++)
{
access2 = (PT_ACCESSARRAY)arrayRef->getElement(j);
if (access2 && access2->scalar &&
loop->isIncludedInStmt(*(access2->stmt)) &&
(access1->var->symbol() == access2->var->symbol()))
done = 1;
}
if (!done)
{
// start to look at all the access to the variable;
thereisawrite = access1->rw;
thewrite = i;
for (j = i + 1; j < arrayRef->size(); j++)
{
access2 = (PT_ACCESSARRAY)arrayRef->getElement(j);
if (access2 && access2->scalar &&
loop->isIncludedInStmt(*(access2->stmt)) &&
(access1->var->symbol() == access2->var->symbol()))
{
if (access2->rw)
{
thewrite = j;
thereisawrite++;
}
}
}
// if there is a write try to recognize the patterns;
if (thereisawrite)
{
if (thereisawrite >= 1)
{
int tp;
if (tp = isItReduction(i, access1, arrayRef, loop))
addAnEdge(access1->stmt, NULL, access1->var, NULL, REDUCTIONDEP, tp, NULL, NULL, 0);
else if (isItPrivate(i, access1, arrayRef, loop))
addAnEdge(access1->stmt, NULL, access1->var, NULL, PRIVATEDEP, 0, NULL, NULL, 0);
else // scalar dep;
addAnEdge(access1->stmt, NULL, access1->var, NULL, SCALARDEP, 0, NULL, NULL, 0);
}
else //drop it;
addAnEdge(access1->stmt, NULL, access1->var, NULL, SCALARDEP, 0, NULL, NULL, 0);
}
// else nothing to do this is safe...;
}
}
}
}
}
//
// used to redo the scalar analysis of a given innermost loop
//
void depGraph::redoScalarRefAnalysis(SgStatement *loop)
{
if (!loop)
return;
//first remove the scalar dep already there;
// then call again the scalar analysis;
std::vector<int> idxToDel;
for (int i = 0; i < nodes.size(); ++i)
{
depNode *temp = nodes[i];
if (temp->typedep >= PRIVATEDEP)
{
idxToDel.push_back(i);
#ifdef __SPF
removeFromCollection(nodes[i]);
#endif
delete nodes[i];
}
}
for (int k = 0; k < idxToDel.size(); ++k)
nodes.erase(nodes.begin() + idxToDel[k]);
scalarRefAnalysis(loop);
}
depNode *depGraph::isThereAnEdge(SgStatement *stmt1, SgStatement *stmt2)
{
depNode *temp;
if (!stmt1 || !stmt2)
return NULL;
for (int i = 0; i < nodes.size(); ++i)
{
temp = nodes[i];
if ((temp->stmtin == stmt1) && (temp->stmtout == stmt2))
return temp;
}
return NULL;
}
// valid only for array;
int depGraph::isLoopCarryingTheDep(SgStatement *doloop, depNode *node)
{
int level;
int i, j;
PT_INDUCVAR ind;
if (!doloop || !node)
return FALSE;
if (node->typedep != ARRAYDEP)
return FALSE;
if (!doloop->isIncludedInStmt(*(node->stmtin)))
return FALSE;
if (!doloop->isIncludedInStmt(*(node->stmtout)))
return FALSE;
if (loop == doloop)
{
level = 0;
}
else
{
level = -1;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->stmt == doloop))
{ // gives the nested level;
level = ind->level;
break;
}
}
}
if (level == -1)
{
Message("Did not find the nested level in isLoopCarryingTheDep", loop->lineNumber());
return FALSE;
}
// now we can look at the dependence vector;
for (i = 1; (i <= node->lenghtvect) && (i <= level); i++)
{
if (node->knowndist[i])
{
if (node->distance[i] != 0)
{
return FALSE;
}
}
else
{
if (!(node->distance[i] & DEPZERO))
{
return FALSE;
}
}
}
return TRUE;
}
///////////////////////////////////////
// compute strongly connected component
////////////////////////////////////////
// look at if there is an edge in the dependence graph that link two statements;
// look only array reference for now....;
// not exactly that.......
int depGraph::isThereAnEdgeSCC(SgStatement *stmt1, SgStatement *stmt2, SgStatement *doloop)
{
int i, j, dir;
depNode *temp;
PT_ACCESSARRAY access1, access2;
if (!stmt1 || !stmt2 || !arrayRef)
return FALSE;
if (stmt1->isIncludedInStmt(*(stmt2)))
return TRUE;
if (stmt2->isIncludedInStmt(*(stmt1)))
return TRUE;
for (int i = 0; i < nodes.size(); ++i)
{
temp = nodes[i];
//need to check the dependence vector;
// may not be a dependence;
// is the loop carrying the depenendence?;
dir = isLoopCarryingTheDep(doloop, temp);
if (dir)
{
if (((temp->stmtin == stmt1) && (temp->stmtout == stmt2)) ||
(stmt1->isIncludedInStmt(*(temp->stmtin)) && stmt2->isIncludedInStmt(*(temp->stmtout))))
{
return TRUE;
}
}
}
// check now that the two statements are not refering to the same scalar var;
// if yes there is an edge;
for (i = 0; i < arrayRef->size(); i++)
{
access1 = (PT_ACCESSARRAY)arrayRef->getElement(i);
if (access1 && access1->scalar &&
((access1->stmt == stmt1) || stmt1->isIncludedInStmt(*(access1->stmt))))
{
for (j = 0; j < arrayRef->size(); j++)
{
access2 = (PT_ACCESSARRAY)arrayRef->getElement(j);
if (access2 && access2->scalar &&
((access2->stmt == stmt2) || stmt2->isIncludedInStmt(*(access2->stmt))) &&
access1->var->symbol() == access2->var->symbol())
{
return TRUE;
}
}
}
}
return FALSE;
}
//
// Routines to compute the Strongly connected component in the graph
//
static int MarkdepthTraversal = 0;
void depGraph::depthTraversal(int stmtid, SgStatement *stmt)
{
int i, j;
int serial;
if (tabtag[stmtid] != 0)
{
return;
}
tabtag[stmtid] = MarkdepthTraversal;
serial = MarkdepthTraversal;
MarkdepthTraversal++;
for (j = 0; j < nbstmt; j++)
{
// there is an edges, so it is a suc
if (j != stmtid)
{
if (isThereAnEdgeSCC(tabstat[stmtid], tabstat[j], stmt))
{
depthTraversal(j, stmt);
if ((tabtag[j] > 0) && (tabtag[j] < tabtag[stmtid]))
tabtag[stmtid] = tabtag[j];
}
}
}
}
int depGraph::getHigherMark()
{
int i;
int mark = -1, resul = -1;
for (i = 0; i < nbstmt; i++)
{
if (tabtag[i] >= mark)
{
mark = tabtag[i];
resul = i;
}
}
return resul;
}
int depGraph::getZeroMark()
{
int i;
for (i = 0; i < nbstmt; i++)
{
if (tabtag[i] == 0)
{
return i;
}
}
return -1;
}
//
// look for strongly connected components
// assumed to be
//
int depGraph::computeSCC(SgStatement *stmtin)
{
SgStatement *temp1, *temp2, *last;
int i, node, node1;
int mark;
int first_componante = -1;
SgStatement *stmt;
SgForStmt *doloop;
int nest;
// This algorithm is not working properly... (yet)
if (!(doloop = isSgForStmt(stmtin)) || !func)
return FALSE;
stmt = doloop;
nest = doloop->isPerfectLoopNest();
for (i = 1; i < nest; i++)
{
stmt = doloop->getNextLoop();
if (!(doloop = isSgForStmt(stmt)))
{
return FALSE;
}
}
if (tabstat)
{
#ifdef __SPF
removeFromCollection(tabstat);
#endif
delete[] tabstat;
}
if (tabtag)
{
#ifdef __SPF
removeFromCollection(tabtag);
#endif
delete[] tabtag;
}
// count the number of statement for allocations;
// nbstmt -1 because of the control end;
nbstmt = stmt->numberOfChildrenList1() - 1;
if (nbstmt < 1) // count the control end;
return FALSE;
tabstat = new SgStatement *[nbstmt];
tabtag = new int[nbstmt];
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tabstat, 2);
addToCollection(__LINE__, __FILE__, tabtag, 2);
#endif
for (i = 0; i < nbstmt; i++)
{
tabstat[i] = stmt->childList1(i);
tabtag[i] = 0;
}
MarkdepthTraversal = 1;
while (-1 != (node = getZeroMark()))
{
depthTraversal(node, doloop);
node1 = getHigherMark();
if (node1 != -1)
MarkdepthTraversal = tabtag[node1] + 1;
for (i = 0; i < nbstmt; i++)
{
if (tabtag[i] > 0)
tabtag[i] = -tabtag[i];
}
}
for (i = 0; i < nbstmt; i++)
{
tabtag[i] = -tabtag[i];
}
printf("SCC for the loop\n");
printf("----------------\n");
for (i = 0; i < nbstmt; i++)
{
printf("Statement %d is in SCC %d\n", i, tabtag[i]);
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function that make the link with the OmegaTest.... Called by the Omega Test
// function store_dependence
///////////////////////////////////////////////////////////////////////////////////////
extern int toBeCalledByOmegaTest(int tdep, int kdep, int *dist, int *kdist, int le, int from, int to)
{
if (!currentDepGraph)
{
Message("No current Dep Graph", 0);
return FALSE;
}
if (from == currentVarIn->id())
currentDepGraph->addAnEdge(currentStmtIn, currentStmtOut, currentVarIn, currentVarOut, tdep, kdep, dist, kdist, le);
else
currentDepGraph->addAnEdge(currentStmtOut, currentStmtIn, currentVarOut, currentVarIn, tdep, kdep, dist, kdist, le);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////
// Compute the data dependence Graph for a loop
// A call to initialize must be done so the data
// flow analysis is done for the function first
///////////////////////////////////////////////////////////////////////////////////////
// f is a function statement; file the file;
void initializeDepAnalysisForFunction(SgFile *file, SgStatement *f, const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile)
{
if (!f || !file)
{
Message("Cannot run initializeDepAnalysisForFunction; no function provided", 0);
return;
}
// convert the loops to be enddo loops; should help later????
convertContLoopToEnddo(f);
initDefUseTable(f, allFuncs, messagesForFile);
// Not Needed Yet;
//iterativeForwardFlowAnalysis(file,f,makeGenSet,makeKillSet,symbRefEqual,NULL,myPrint);
}