Files
SAPFOR/Sapfor/_src/SageAnalysisTool/arrayRef.cpp
2025-03-12 12:37:19 +03:00

727 lines
19 KiB
C++

#include <stdio.h>
#include <set>
#include <string>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
#include "arrayRef.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
int NbLinearRef = 0;
int NbNonLinearRef = 0;
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
extern Set* getAllInductionVar(SgStatement *func, SgStatement *stmt, int level, int *num, int include);
using std::set;
using std::string;
//
// for an array ref build the linear representation
// return 0 if failed
//
int linearRepArray(SgExpression *ex1, SgSymbol **symb, int size, int linear[MAXDIMARRAY][MAXNESTEDLOOP], int *cst, int isLinear[MAXDIMARRAY])
{
SgArrayRefExp *ar;
SgExpression *lin;
int i;
int returnVal;
if (!ex1 || !symb || !cst)
return 0;
if (!(ar = isSgArrayRefExp(ex1)))
return 0;
returnVal = 1;
for (i = 0; i < ar->numberOfSubscripts(); i++)
{
lin = ar->subscript(i);
isLinear[i] = 1;
if (!lin)
{
returnVal = 0;
isLinear[i] = 0;
}
else
if (!lin->linearRepresentation(linear[i], symb, &cst[i], size))
{
returnVal = 0;
isLinear[i] = 0;
}
}
return returnVal;
}
//
// Set Operations
//
int arrayEqual(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_ACCESSARRAY el1, el2;
int i;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
el1 = (PT_ACCESSARRAY)e1;
el2 = (PT_ACCESSARRAY)e2;
ex1 = el1->var;
ex2 = el2->var;
if (el1->type != el2->type)
return 0;
if (ex1 && ex2 && (s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if (s1 != s2)
return 0;
// need to check more, at which condition, two sections are equal;
// pattern matching should be ok;
}
return 1;
}
void arrayPrint(void *e1)
{
SgExpression *ex1;
PT_ACCESSARRAY el1;
int i, j;
if (!e1)
return;
el1 = (PT_ACCESSARRAY)e1;
ex1 = el1->var;
printf("%d :", el1->level);
ex1->unparsestdout();
printf("\n");
if (el1->scalar)
printf("scalar variable\n");
if (el1->rw)
printf("written\n");
else
printf("read\n");
if (el1->type)
printf("Linear\n");
for (i = 0; i < MAXDIMARRAY; i++)
{
if (el1->isLinear[i])
{
printf("Linear (%d) :", i);
for (j = 0; j < el1->size; j++)
printf("%d ", el1->linear[i][j]);
printf(" cst = %d", el1->cst[i]);
printf("\n");
}
else
printf("NonLinear (%d) \n", i);
}
printf("\n");
}
// this function should be extended to handle non loop statement...
Set *loopArrayAccessAnalysis(SgStatement *func, SgStatement *stmt, SgSymbol **tsymb, Set **induc, const set<string> &privVars)
{
Set *inducvar, *cstset, *tpt, *arset;
SgStatement *temp1, *temp2, *last;
SgExpression *def1, *def2, *use1, *use2;
SgExpression *ex1, *ex2, *r1, *r2;
int linear1[MAXDIMARRAY][MAXNESTEDLOOP];
int i, j, size, res1, res2, cst1[MAXDIMARRAY];
int level, ptstack = 0, LevStack[MAXNESTEDLOOP], nbloop;
PT_INDUCVAR ind;
PT_ACCESSARRAY el;
int numloop = 0;
int isLinear[MAXDIMARRAY];
if (!isSgForStmt(stmt) || !func)
return NULL;
last = stmt->lastNodeOfStmt();
// get induction variables;
inducvar = getAllInductionVar(func, stmt, 1, &numloop, -1);
// add the constante to the induction set variable;
// cstset = computeConstanteInStmt(func,stmt);
// if (cstset)
// cstset->printSet();
// inducvar->unionSet(cstset);
// delete cstset;
if (!inducvar)
{
Message("no induction variables", stmt->lineNumber());
return NULL;
}
// load the array of symbol with induction var;
if (inducvar->size() >= MAXNESTEDLOOP)
{
Message("Too many induction variables\n", stmt->lineNumber());
return NULL;
}
tpt = inducvar;
inducvar = inducvar->compact();
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
*induc = inducvar;
arset = new Set(arrayEqual, NULL, arrayPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, arset, 1);
#endif
size = inducvar->size();
for (i = 0; i < inducvar->size(); i++)
{
ind = (PT_INDUCVAR)inducvar->getElement(i);
if (ex2 = ind->var)
{
tsymb[i] = ex2->symbol();
}
}
// get all array references, there are contained in the Defined Used set;
level = 0;
nbloop = 0;
for (temp1 = stmt; temp1 && (temp1 != last); temp1 = temp1->lexNext())
{
if (isSgForStmt(temp1))
{
nbloop++;
ptstack++;
if (ptstack >= MAXNESTEDLOOP)
Message("Stack out of bound in loopArrayAccessAnalysis", 0);
LevStack[ptstack] = nbloop;
level = nbloop;
}
if (isSgControlEndStmt(temp1) || isSgContinueStmt(temp1))
{
if (temp1->controlParent() && (temp1->controlParent()->variant() == FOR_NODE) && (temp1->controlParent()->lastNodeOfStmt() == temp1))
{
ptstack--;
if (ptstack <= 0)
Message("Stack out of bound in loopArrayAccessAnalysis", 0);
level = LevStack[ptstack];
}
}
for (def1 = (SgExpression *)temp1->attributeValue(0, DEFINEDLIST_ATTRIBUTE); def1; def1 = def1->rhs())
//Defined[temp1->id()]; def1; def1 = def1->rhs())
{
for (i = 0; i < MAXDIMARRAY; i++)
{
cst1[i] = 0;
isLinear[i] = 1;
for (j = 0; j < MAXNESTEDLOOP; j++)
linear1[i][j] = 0;
}
ex1 = def1->lhs();
if (isSgArrayRefExp(ex1))
{
if (privVars.find(ex1->symbol()->identifier()) == privVars.end())
{
res1 = linearRepArray(ex1, tsymb, size, linear1, cst1, isLinear);
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
for (i = 0; i < MAXDIMARRAY; i++)
{
el->isLinear[i] = isLinear[i];
for (j = 0; j < MAXNESTEDLOOP; j++)
el->linear[i][j] = linear1[i][j];
el->cst[i] = cst1[i];
}
// add the ref;
el->stmt = temp1;
el->nbdim = MAXDIMARRAY;
el->var = ex1;
el->type = res1;
if (res1)
NbLinearRef++;
else
NbNonLinearRef++;
el->size = size;
el->rw = 1; // this is a write;
el->scalar = 0; // not a scalar var;
el->level = level;
arset->addElement((void *)el);
}
}
else
{
SgSymbol *ssy;
int l, trouve;
// if non induction var ;
if (!isSgTypeExp(ex1))
{
ssy = ex1->symbol();
trouve = 0;
for (l = 0; l < size; l++)
{
if (ssy == tsymb[l])
{
trouve = 1;
break;
}
}
}
else
trouve = 1;
if (!trouve)
{
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = 0;
el->type = 0;
el->size = 0;
el->rw = 1; // this is a write;
el->level = level;
el->scalar = 1; // not a scalar var;
arset->addElement((void *)el);
}
}
}
for (use1 = (SgExpression *)temp1->attributeValue(0, USEDLIST_ATTRIBUTE); use1; use1 = use1->rhs())
// Used[temp1->id()]; use1; use1 = use1->rhs())
{
for (i = 0; i < MAXDIMARRAY; i++)
{
cst1[i] = 0;
isLinear[i] = 1;
for (j = 0; j < MAXNESTEDLOOP; j++)
linear1[i][j] = 0;
}
ex1 = use1->lhs();
if (isSgArrayRefExp(ex1))
{
if (privVars.find(ex1->symbol()->identifier()) == privVars.end())
{
res1 = linearRepArray(ex1, tsymb, size, linear1, cst1, isLinear);
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
for (i = 0; i < MAXDIMARRAY; i++)
{
el->isLinear[i] = isLinear[i];
for (j = 0; j < MAXNESTEDLOOP; j++)
el->linear[i][j] = linear1[i][j];
el->cst[i] = cst1[i];
}
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = MAXDIMARRAY;
el->type = res1;
if (res1)
NbLinearRef++;
else
NbNonLinearRef++;
el->size = size;
el->rw = 0; // this is a read;
el->scalar = 0; // not a scalar var;
el->level = level;
arset->addElement((void *)el);
}
}
else
{
SgSymbol *ssy;
int l, trouve;
if (!isSgTypeExp(ex1))
{
// if non induction var ;
ssy = ex1->symbol();
trouve = 0;
for (l = 0; l < size; l++)
{
if (ssy == tsymb[l])
{
trouve = 1;
break;
}
}
}
else
trouve = 1;
if (!trouve)
{
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = 0;
el->type = 0;
el->size = 0;
el->level = level;
el->rw = 0; // this is a read;
el->scalar = 1; // not a scalar var;
arset->addElement((void *)el);
}
}
}
}
return arset;
}
int
projectoPermut(PT_ACCESSARRAY el1)
{
SgSymbol *inducsy;
int i, j, k;
PT_INDUCVAR ind, cur;
int temp;
if (!el1)
return 0;
if (!el1->type)
return 0; // non linear;
for (j = 0; j < el1->size; j++)
{
temp = 0;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
if (temp)
return 0;
temp = 1;
}
}
}
for (k = 0; k < MAXDIMARRAY; k++)
{
temp = 0;
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != 0)
{
if (temp)
return 0;
temp = 1;
}
}
}
return 1;
}
//
// Between two references is there temporal locality. Limited to permutation o projection
//
int
temporalLocality(PT_ACCESSARRAY el1, SgSymbol **tsymb, Set *induc)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int temporal, temp;
if (!el1 || !induc || !tsymb)
return 0;
inducsy = NULL;
loopnum = el1->level;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == loopnum))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
temporal = 0;
// this is the induction var of the loop.
if (inducsy)
{
while (cur)
{
for (j = 0; j < el1->size; j++)
{
if (tsymb[j] == inducsy)
break;
} // we have the symbol;
if (j < el1->size)
{
temp = 1;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
temp = 0;
}
}
if (temp)
temporal = 1;
}
if (cur->include == -1)
break;
// compute the next one;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == cur->include))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
}
}
return temporal;
}
int
spatialLocality(PT_ACCESSARRAY el1, SgSymbol **tsymb, Set *induc, int CacheLIneSize)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
if (!el1 || !induc || !tsymb)
return 0;
inducsy = NULL;
loopnum = el1->level;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == loopnum))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
spatial = 0;
// this is the induction var of the loop.
if (inducsy)
{
// look at in the dimension where the variable appear;
spatial = 1;
// the first dimension is fine where is the column of the symbole;
for (j = 0; j < el1->size; j++)
{
if (tsymb[j] == inducsy)
break;
}
if (j < el1->size)
{
for (k = 1; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
spatial = 0;
break;
}
}
if (el1->linear[0][j] > CacheLIneSize)
spatial = 0;
}
else
{
spatial = 0;
}
}
return spatial;
}
int
spatialNonSelfLocality(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2, SgSymbol **tsymb, Set *induc, int CacheLIneSize)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
if (!el1 || !el2 || !induc || !tsymb)
return 0;
inducsy = NULL;
if (el1->level != el2->level)
return 0;
if (!el1->var || !el2->var)
return 0;
if (el1->var->symbol() != el2->var->symbol())
return 0;
// do they have the same function
for (k = 0; k < MAXDIMARRAY; k++)
{
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != el2->linear[k][j])
{
return 0;
}
}
}
for (k = 1; k < MAXDIMARRAY; k++)
{
if (el1->cst[k] != el2->cst[k])
{
return 0;
}
}
spatial = el1->cst[0] - el2->cst[0];
if (spatial < 0)
spatial = -spatial;
if (spatial >= CacheLIneSize)
return 0;
return 1;
}
int
TemporalNonSelfLocality(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2, SgSymbol **tsymb, Set *induc)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
int flag;
if (!el1 || !el2 || !induc || !tsymb)
return 0;
inducsy = NULL;
if (el1->level != el2->level)
return 0;
if (!el1->var || !el2->var)
return 0;
if (el1->var->symbol() != el2->var->symbol())
return 0;
// do they have the same function
for (k = 0; k < MAXDIMARRAY; k++)
{
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != el2->linear[k][j])
{
return 0;
}
}
}
// is there one reference with only one constant different
flag = 0;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->cst[k] != el2->cst[k])
{
if (flag)
return 0;
flag = k + 1;
}
}
if (flag)
{
// check first that the coefficient is not NULL;
for (j = 0; j < el1->size; j++)
{
if (el1->linear[flag - 1][j] != 0)
return 1;
}
return 0;
}
else
return 0; // that case is considered elsewhere
}
int
isLinearEqual(int size1, int size2, int linear1[MAXDIMARRAY][MAXNESTEDLOOP], int *cst1, int linear2[MAXDIMARRAY][MAXNESTEDLOOP], int *cst2)
{
int i, j;
if (!linear1 || !linear2 || !cst1 || !cst2)
return 0;
if (size1 != size2)
return 0;
for (i = 0; i < MAXDIMARRAY; i++)
{
if (cst1[i] != cst2[i])
return 0;
for (j = 0; j < size1; j++)
{
if (linear1[i][j] != linear2[i][j])
return 0;
}
}
return 1;
}
int
isLinearEqualNoCst(int size1, int size2, int linear1[MAXDIMARRAY][MAXNESTEDLOOP], int linear2[MAXDIMARRAY][MAXNESTEDLOOP])
{
int i, j;
if (!linear1 || !linear2)
return 0;
if (size1 != size2)
return 0;
for (i = 0; i < MAXDIMARRAY; i++)
{
for (j = 0; j < size1; j++)
{
if (linear1[i][j] != linear2[i][j])
return 0;
}
}
return 1;
}
int
isNull(int size, int linear[MAXNESTEDLOOP])
{
int i;
if (!linear)
return 1;
for (i = 0; i < size; i++)
{
if (linear[i] != 0)
return 0;
}
return 1;
}