366 lines
9.4 KiB
C++
366 lines
9.4 KiB
C++
#include <stdio.h>
|
|
#include "sage++user.h"
|
|
#include "definesValues.h"
|
|
#include "set.h"
|
|
#include "definitionSet.h"
|
|
#include "inducVar.h"
|
|
|
|
extern Set *genSet[MAXNODE];
|
|
extern Set *killSet[MAXNODE];
|
|
extern Set *inSet[MAXNODE];
|
|
extern Set *outSet[MAXNODE];
|
|
|
|
#ifdef __SPF
|
|
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
|
|
extern "C" void removeFromCollection(void *pointer);
|
|
#endif
|
|
//
|
|
// Here we compute the induction variables for a loop
|
|
// this use the result of recheing analysis and invariant computation in loop.
|
|
// we use as element of sets the following structure.
|
|
//
|
|
|
|
//
|
|
// Set Operation
|
|
//
|
|
int inducVarEqual(void *e1, void *e2)
|
|
{
|
|
SgExpression *ex1, *ex2;
|
|
SgSymbol *s1, *s2;
|
|
PT_INDUCVAR el1, el2;
|
|
if (!e1 && !e2)
|
|
return 1;
|
|
if (!e1 || !e2)
|
|
return 0;
|
|
|
|
el1 = (PT_INDUCVAR)e1;
|
|
el2 = (PT_INDUCVAR)e2;
|
|
if (el1->level != el2->level)
|
|
return 0;
|
|
if (el1->include != el2->include)
|
|
return 0;
|
|
if (el1->loopnum != el2->loopnum)
|
|
return 0;
|
|
if (el1->constante != el2->constante)
|
|
return 0;
|
|
|
|
ex1 = el1->var;
|
|
ex2 = el2->var;
|
|
|
|
if ((s1 = ex1->symbol()) && (s2 = ex2->symbol()))
|
|
{
|
|
if (s1 == s2)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
void inducVarPrint(void *e1)
|
|
{
|
|
SgExpression *ex1;
|
|
PT_INDUCVAR el1;
|
|
if (!e1)
|
|
return;
|
|
el1 = (PT_INDUCVAR)e1;
|
|
ex1 = el1->var;
|
|
if (el1->constante)
|
|
printf("Constante ");
|
|
if (ex1->symbol())
|
|
printf("%s (%d-%d-%d)", ex1->symbol()->identifier(), el1->level, el1->loopnum, el1->include);
|
|
else
|
|
ex1->unparsestdout();
|
|
printf(" = ");
|
|
ex1 = el1->lbound;
|
|
if (ex1)
|
|
ex1->unparsestdout();
|
|
printf(",");
|
|
ex1 = el1->ubound;
|
|
if (ex1)
|
|
ex1->unparsestdout();
|
|
printf(",");
|
|
ex1 = el1->stride;
|
|
if (ex1)
|
|
ex1->unparsestdout();
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
//
|
|
// Indicate if a variable is subject to modification in a stmt
|
|
// Based on the Definition for each statement....
|
|
// defvar is a varref;
|
|
//
|
|
|
|
int definitionInStmt(SgStatement *func, SgStatement *stmtin, SgExpression *defvar)
|
|
{
|
|
SgStatement *last, *stmt;
|
|
SgExpression *def, *expr;
|
|
|
|
if (!stmtin || !func)
|
|
return FALSE;
|
|
|
|
last = stmtin->lastNodeOfStmt();
|
|
|
|
for (stmt = stmtin; stmt; stmt = stmt->lexNext())
|
|
{
|
|
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
|
|
//Defined[stmt->id()];
|
|
while (def)
|
|
{
|
|
expr = def->lhs();
|
|
if (expr && expr->symbol() && defvar->symbol() &&
|
|
(expr->symbol() == defvar->symbol()))
|
|
{
|
|
return TRUE;
|
|
}
|
|
def = def->rhs();
|
|
}
|
|
if (stmt == last)
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//same as before but avoid the first statement (for instance the loop header)
|
|
// so can be used fo checking the basic induction variable;
|
|
int definitionOnlyInsideStmt(SgStatement *func, SgStatement *stmtin, SgExpression *defvar)
|
|
{
|
|
SgStatement *last, *stmt;
|
|
SgExpression *def, *expr;
|
|
|
|
if (!stmtin || !func)
|
|
return FALSE;
|
|
|
|
last = stmtin->lastNodeOfStmt();
|
|
|
|
for (stmt = stmtin->lexNext(); stmt; stmt = stmt->lexNext())
|
|
{
|
|
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
|
|
// Defined[stmt->id()];
|
|
while (def)
|
|
{
|
|
expr = def->lhs();
|
|
if (expr && expr->symbol() && defvar->symbol() &&
|
|
(expr->symbol() == defvar->symbol()))
|
|
{
|
|
return TRUE;
|
|
}
|
|
def = def->rhs();
|
|
}
|
|
if (stmt == last)
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// For a statement create an induction var set that contains the SCALAR constante
|
|
// based on the use set which have to be defined later
|
|
//
|
|
Set* computeConstanteInStmt(SgStatement *func, SgStatement *stmtin)
|
|
{
|
|
SgStatement *last, *stmt;
|
|
SgExpression *use, *expr;
|
|
Set *constante;
|
|
PT_INDUCVAR elin;
|
|
int cst;
|
|
|
|
if (!stmtin || !func)
|
|
return NULL;
|
|
last = stmtin->lastNodeOfStmt();
|
|
constante = new Set(inducVarEqual, NULL, inducVarPrint);
|
|
#ifdef __SPF
|
|
addToCollection(__LINE__, __FILE__, constante, 1);
|
|
#endif
|
|
for (stmt = stmtin; stmt; stmt = stmt->lexNext())
|
|
{
|
|
use = (SgExpression *)stmt->attributeValue(0, USEDLIST_ATTRIBUTE);
|
|
// Used[stmt->id()];
|
|
while (use)
|
|
{
|
|
expr = use->lhs();
|
|
if (definitionInStmt(func, stmtin, expr))
|
|
cst = 0;
|
|
else
|
|
cst = 1;
|
|
if (cst)
|
|
{
|
|
elin = new struct inducvar;
|
|
#ifdef __SPF
|
|
addToCollection(__LINE__, __FILE__, elin, 1);
|
|
#endif
|
|
elin->constante = TRUE;
|
|
elin->stmt = stmtin;
|
|
elin->var = use->lhs();
|
|
elin->lbound = NULL;
|
|
elin->ubound = NULL;
|
|
elin->stride = NULL;
|
|
elin->level = 0;
|
|
elin->loopnum = 0;
|
|
constante->addElement((void *)elin);
|
|
}
|
|
use = use->rhs();
|
|
}
|
|
if (stmt == last)
|
|
break;
|
|
}
|
|
if (constante)
|
|
constante->compact();
|
|
return constante;
|
|
}
|
|
|
|
//
|
|
// compute effectively induction variables (limited to basic induction variable for now)
|
|
//
|
|
Set* computeInductionVariables(SgStatement *func, SgStatement *stmt)
|
|
{
|
|
SgStatement *last, *first, *defreach, *temp, *cp;
|
|
SgForStmt *loop;
|
|
Set *induc, *reachdef;
|
|
SgExpression *use, *def, *pt, *defvar, *expr;
|
|
int change, id, inloop, inv, step;
|
|
PT_ELSET el;
|
|
PT_INDUCVAR elin;
|
|
int i, inducF;
|
|
if (!stmt || !func)
|
|
return NULL;
|
|
|
|
if (!(loop = isSgForStmt(stmt)))
|
|
return NULL;
|
|
|
|
induc = new Set(inducVarEqual, NULL, inducVarPrint);
|
|
#ifdef __SPF
|
|
addToCollection(__LINE__, __FILE__, induc, 1);
|
|
#endif
|
|
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
|
|
// Defined[stmt->id()];
|
|
if (def)
|
|
{ // basic induction var;
|
|
defvar = def->lhs(); // the loop modify the induction var only;
|
|
// check if it is constant;
|
|
if (!definitionOnlyInsideStmt(func, loop, defvar))
|
|
inducF = 1;
|
|
else
|
|
{
|
|
inducF = 1;
|
|
Message("Induction variable may be defined", stmt->lineNumber());
|
|
}
|
|
if (inducF)
|
|
{
|
|
elin = new struct inducvar;
|
|
#ifdef __SPF
|
|
addToCollection(__LINE__, __FILE__, elin, 1);
|
|
#endif
|
|
elin->constante = FALSE;
|
|
elin->stmt = stmt;
|
|
elin->var = def->lhs();
|
|
elin->lbound = loop->start();
|
|
elin->ubound = loop->end();
|
|
elin->stride = loop->step();
|
|
elin->level = 0;
|
|
elin->loopnum = 0;
|
|
induc->addElement((void *)elin);
|
|
}
|
|
else
|
|
Message("Basic Induction Var not Found: dependence Test will abort", loop->lineNumber());
|
|
// limited to basic induction variable for the moment...;
|
|
}
|
|
return induc;
|
|
}
|
|
|
|
|
|
|
|
|
|
//Get all induction var;
|
|
Set* getAllInductionVar(SgStatement *func, SgStatement *stmt, int level, int *num, int include)
|
|
{
|
|
SgStatement *temp, *child;
|
|
int i, newlevel;
|
|
Set *induc, *tpt;
|
|
PT_INDUCVAR el;
|
|
int tmpincl;
|
|
if (!stmt)
|
|
return NULL;
|
|
induc = NULL;
|
|
if (isSgForStmt(stmt))
|
|
{
|
|
*num = *num + 1;
|
|
tmpincl = *num;
|
|
induc = computeInductionVariables(func, stmt);
|
|
if (induc)
|
|
{
|
|
for (i = 0; i < induc->size(); i++)
|
|
{
|
|
el = (PT_INDUCVAR)induc->getElement(i);
|
|
if (el)
|
|
{
|
|
el->level = level;
|
|
el->loopnum = *num;
|
|
el->include = include;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
tmpincl = include;
|
|
|
|
i = 1;
|
|
temp = stmt;
|
|
child = temp->childList1(0);
|
|
while (child)
|
|
{
|
|
if (isSgForStmt(child))
|
|
newlevel = level + 1;
|
|
else
|
|
newlevel = level;
|
|
if (induc)
|
|
{
|
|
induc->unionSet(tpt = getAllInductionVar(func, child, newlevel, num, tmpincl));
|
|
if (tpt)
|
|
{
|
|
#ifdef __SPF
|
|
removeFromCollection(tpt);
|
|
#endif
|
|
delete tpt;
|
|
}
|
|
}
|
|
else
|
|
induc = getAllInductionVar(func, child, newlevel, num, tmpincl);
|
|
child = temp->childList1(i);
|
|
i++;
|
|
}
|
|
|
|
i = 1;
|
|
temp = stmt;
|
|
child = temp->childList2(0);
|
|
while (child)
|
|
{
|
|
if (isSgForStmt(child))
|
|
newlevel = level + 1;
|
|
else
|
|
newlevel = level;
|
|
if (induc)
|
|
{
|
|
induc->unionSet(tpt = getAllInductionVar(func, child, newlevel, num, tmpincl));
|
|
if (tpt)
|
|
{
|
|
#ifdef __SPF
|
|
removeFromCollection(tpt);
|
|
#endif
|
|
delete tpt;
|
|
}
|
|
}
|
|
else
|
|
induc = getAllInductionVar(func, child, newlevel, num, tmpincl);
|
|
child = temp->childList2(i);
|
|
i++;
|
|
}
|
|
return induc;
|
|
}
|