Files
SAPFOR/dvm/fdvm/trunk/fdvm/acc_across_analyzer.cpp
2023-09-14 19:43:13 +03:00

2234 lines
89 KiB
C++

#include "dvm.h"
#include "acc_across_analyzer.h"
using namespace std;
// special storages to avoid recomputing
map<string, SgExpression*> lhs;
map<string, SgExpression*> rhs;
map<SgExpression*, string> unparsedLhs;
map<SgExpression*, string> unparsedRhs;
template<typename InIt1, typename InIt2, typename OutIt>
static inline OutIt difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt dest)
{
for (; first1 != last1 && first2 != last2;)
{
if (*first1 < *first2)
{
*dest++ = *first1;
++first1;
}
else if (*first2 < *first1)
++first2;
else
{
++first1;
++first2;
}
}
return copy(first1, last1, dest);
}
template<typename InIt1, typename InIt2, typename OutIt>
static inline OutIt intersection(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt dest)
{
for (; first1 != last1 && first2 != last2;)
{
if (*first1 < *first2)
++first1;
else if (*first2 < *first1)
++first2;
else
{
*dest++ = *first1++;
++first2;
}
}
return dest;
}
static int replace(SgExpression* expr, SgStatement* parent, SgExpression* patt, SgExpression* subst)
{
if (ExpCompare(expr, patt) != 0)
{
*expr = subst->copy();
if (ExpCompare(parent->expr(0), expr) != 0)
parent->setExpression(0, *expr);
else if (ExpCompare(parent->expr(1), expr) != 0)
parent->setExpression(1, *expr);
return 1;
}
int count = 0;
vector<SgExpression*> subexprs;
subexprs.push_back(NULL);
subexprs.push_back(expr);
int k = 1;
vector<int> positions(2);
for (vector<SgExpression*>::iterator p = subexprs.begin() + 1; p != subexprs.end(); ++k, p = subexprs.begin() + k)
{
if (ExpCompare(*p, patt) == 0)
{
SgExpression* lhs = (*p)->lhs();
SgExpression* rhs = (*p)->rhs();
if (lhs != NULL)
{
subexprs.push_back(lhs);
positions.push_back(-k);
}
if (rhs != NULL)
{
subexprs.push_back(rhs);
positions.push_back(k);
}
}
else
{
if (positions[k] < 0)
subexprs[-positions[k]]->setLhs(subst->copyPtr());
else
subexprs[positions[k]]->setRhs(subst->copyPtr());
++count;
}
}
return count;
}
static int replaceInSubscripts(SgExpression* expr, SgStatement* parent, SgExpression* patt, SgExpression* subst)
{
if (expr == NULL)
return 0;
int count = 0;
vector<SgExpression*> subexprs;
subexprs.push_back(expr);
int k = 0;
for (vector<SgExpression*>::iterator p = subexprs.begin(); p != subexprs.end(); ++k, p = subexprs.begin() + k)
{
if ((*p)->variant() == ARRAY_REF)
{
for (SgExpression* tmp = ((SgArrayRefExp*)* p)->subscripts(); tmp != NULL; tmp = tmp->rhs())
count += replace(tmp->lhs(), parent, patt, subst);
}
else
{
SgExpression* lhs = (*p)->lhs();
SgExpression* rhs = (*p)->rhs();
if (lhs != NULL)
subexprs.push_back(lhs);
if (rhs != NULL)
subexprs.push_back(rhs);
}
}
return count;
}
#define add(a, b) (a) + (b)
#define subtract(a, b) (a) - (b)
#define multiply(a, b) (a) * (b)
#define divide(a, b) (a) / (b)
#define compute(lhs, rhs, parent, op, cast) \
switch (lhs->variant()) \
{ \
case BOOL_VAL: \
lhs = new SgValueExp(op(cast(((SgValueExp*)lhs)->boolValue() == true ? -1 : 0), rhs)); \
break; \
case INT_VAL: \
lhs = new SgValueExp(op(cast((SgValueExp*)lhs)->intValue(), rhs)); \
break; \
case FLOAT_VAL: \
lhs = new SgValueExp(op(cast strtod(((SgValueExp*)lhs)->floatValue(), NULL), rhs)); \
break; \
case DOUBLE_VAL: \
lhs = new SgValueExp(op(cast strtod(((SgValueExp*)lhs)->doubleValue(), NULL), rhs)); \
break; \
default: \
changed = false; \
lhs = parent; \
break; \
}
void Loop::getRPN(SgExpression* expr, list<SgExpression*>& rpn) const
{
if (expr == NULL)
return;
stack<SgExpression*> stack;
stack.push(expr);
while (stack.empty() == false)
{
SgExpression* expr = stack.top();
stack.pop();
switch (expr->variant())
{
case ARRAY_REF:
case FUNC_CALL:
break;
case SUBT_OP:
*expr = *expr->lhs() + *new SgExpression(MINUS_OP, expr->rhs(), NULL, NULL);
stack.push(expr->lhs());
stack.push(expr->rhs());
break;
default:
if (expr->lhs() != NULL)
stack.push(expr->lhs());
if (expr->rhs() != NULL)
stack.push(expr->rhs());
break;
}
rpn.push_front(expr);
}
}
void Loop::unrollRPN(list<SgExpression*>& rpn, map<SgExpression*, int>& arity) const
{
set<SgExpression*> visited;
for (list<SgExpression*>::iterator it = rpn.begin(); it != rpn.end();)
{
if (visited.find(*it) == visited.end())
visited.insert(*it);
else
{
++it;
continue;
}
switch ((*it)->variant())
{
case ARRAY_REF:
case FUNC_CALL:
for (SgExpression* tmp = (*it)->lhs(); tmp != NULL; tmp = tmp->rhs())
{
list<SgExpression*> subrpn;
getRPN(tmp->lhs(), subrpn);
optimizeRPN(subrpn, arity, false);
rpn.insert(it, subrpn.begin(), subrpn.end());
}
it = rpn.begin();
break;
default:
++it;
break;
}
}
}
void Loop::optimizeRPN(list<SgExpression*>& rpn, map<SgExpression*, int>& arity, bool unrolled) const
{
for (list<SgExpression*>::iterator it = rpn.begin(); it != rpn.end();)
{
if ((*it)->lhs() != NULL)
{
if ((*it)->rhs() != NULL)
{
int _arity = 2;
int variant = (*it)->variant();
switch (variant)
{
case ADD_OP:
case MULT_OP:
{
if (arity.find(*it) != arity.end())
{
++it;
break;
}
bool found = false;
list<SgExpression*>::iterator old = it, tmp = it;
for (++it; it != rpn.end(); ++it)
{
if ((*it)->variant() == variant && (((*it)->lhs() != NULL && (*it)->lhs()->variant() == variant) || ((*it)->rhs() != NULL && (*it)->rhs()->variant() == variant)))
{
rpn.erase(tmp);
tmp = it;
++_arity;
}
else if ((*it)->lhs() != NULL || (unrolled && ((*it)->variant() == ARRAY_REF || (*it)->variant() == FUNC_CALL)))
break;
else if (found == false)
{
old = it;
found = true;
}
}
arity[*tmp] = _arity;
if (found == true)
it = ++old;
break;
}
default:
arity[*it] = _arity;
++it;
break;
}
}
else
{
if ((*it)->variant() == FUNC_CALL || (*it)->variant() == ARRAY_REF)
arity[*it] = ((SgExprListExp*)(*it)->lhs())->length();
else
arity[*it] = 1;
++it;
}
}
else
++it;
}
}
SgExpression* Loop::simplify(SgExpression* expr) const
{
if (enable_opt == false || expr == NULL)
return expr;
list<SgExpression*> rpn;
map<SgExpression*, int> arity;
getRPN(expr, rpn);
optimizeRPN(rpn, arity, false);
unrollRPN(rpn, arity);
optimizeRPN(rpn, arity, true);
bool changed = true;
while (changed == true)
{
changed = false;
stack<SgExpression*> stack;
for (list<SgExpression*>::iterator it = rpn.begin(); it != rpn.end(); ++it)
{
if ((*it)->lhs() != NULL)
{
if ((*it)->rhs() != NULL)
{
int _arity = arity[*it];
vector<SgExpression*> args(_arity);
for (int i = _arity - 1; i >= 0; --i)
{
args[i] = stack.top();
stack.pop();
}
SgExpression* result = NULL;
switch ((*it)->variant())
{
case ADD_OP:
{
result = new SgValueExp(0);
list<SgExpression*> _args;
for (int i = 0; i < _arity; ++i)
{
switch (args[i]->variant())
{
case BOOL_VAL:
compute(result, ((SgValueExp*)args[i])->boolValue() == true ? -1 : 0, (*it), add, );
break;
case INT_VAL:
compute(result, ((SgValueExp*)args[i])->intValue(), (*it), add, );
break;
case FLOAT_VAL:
compute(result, (float)strtod(((SgValueExp*)args[i])->floatValue(), NULL), (*it), add, );
break;
case DOUBLE_VAL:
compute(result, strtod(((SgValueExp*)args[i])->doubleValue(), NULL), (*it), add, );
break;
default:
_args.push_back(args[i]);
break;
}
}
for (list<SgExpression*>::iterator it1 = _args.begin(); it1 != _args.end();)
{
bool cond = (*it1)->variant() == MINUS_OP;
bool changed = false;
for (list<SgExpression*>::iterator it2 = it1; it2 != _args.end();)
{
if (cond == true && ExpCompare((*it1)->lhs(), *it2) == 1 || cond == false && (*it2)->variant() == MINUS_OP && ExpCompare(*it1, (*it2)->lhs()) == 1)
{
it1 = _args.erase(it1);
if (it1 == it2)
{
it2 = _args.erase(it2);
it1 = it2;
}
else
it2 = _args.erase(it2);
changed = true;
}
else
++it2;
}
if (changed == false)
++it1;
}
if (_args.size() + 1 < args.size())
changed = true;
bool zero = false;
switch (result->variant())
{
case BOOL_VAL:
zero = ((SgValueExp*)result)->boolValue() == false;
break;
case INT_VAL:
zero = ((SgValueExp*)result)->intValue() == 0;
break;
case FLOAT_VAL:
zero = (float)strtod(((SgValueExp*)result)->floatValue(), NULL) == 0.0f;
break;
case DOUBLE_VAL:
zero = strtod(((SgValueExp*)result)->doubleValue(), NULL) == 0.0;
break;
default:
break;
}
if (zero == true)
{
if (_args.size() != 0)
{
result = *_args.begin();
for (list<SgExpression*>::iterator it = ++_args.begin(); it != _args.end(); ++it)
result = &(**it + *result);
}
}
else
for (list<SgExpression*>::iterator it = _args.begin(); it != _args.end(); ++it)
result = &(**it + *result);
break;
}
case MULT_OP:
{
result = new SgValueExp(1);
list<SgExpression*> _args;
for (int i = 0; i < _arity; ++i)
{
switch (args[i]->variant())
{
case BOOL_VAL:
compute(result, ((SgValueExp*)args[i])->boolValue() == true ? -1 : 0, (*it), multiply, );
break;
case INT_VAL:
compute(result, ((SgValueExp*)args[i])->intValue(), (*it), multiply, );
break;
case FLOAT_VAL:
compute(result, (float)strtod(((SgValueExp*)args[i])->floatValue(), NULL), (*it), multiply, );
break;
case DOUBLE_VAL:
compute(result, strtod(((SgValueExp*)args[i])->doubleValue(), NULL), (*it), multiply, );
break;
default:
_args.push_back(args[i]);
break;
}
}
if (_args.size() + 1 < args.size())
changed = true;
bool one = false;
switch (result->variant())
{
case BOOL_VAL:
one = ((SgValueExp*)result)->boolValue() == true;
break;
case INT_VAL:
one = ((SgValueExp*)result)->intValue() == 1;
break;
case FLOAT_VAL:
one = (float)strtod(((SgValueExp*)result)->floatValue(), NULL) == 1.0f;
break;
case DOUBLE_VAL:
one = strtod(((SgValueExp*)result)->doubleValue(), NULL) == 1.0;
break;
default:
break;
}
if (one == true)
{
if (_args.size() != 0)
{
result = *_args.begin();
for (list<SgExpression*>::iterator it = ++_args.begin(); it != _args.end(); ++it)
result = &(**it * *result);
}
}
else
{
for (list<SgExpression*>::iterator it = _args.begin(); it != _args.end(); ++it)
result = &(**it * *result);
}
break;
}
case DIV_OP:
{
SgExpression* lhs = args[0];
SgExpression* rhs = args[1];
changed = true;
if (ExpCompare(lhs, rhs) == 1)
{
result = new SgValueExp(1);
break;
}
else if (lhs->variant() == MINUS_OP && ExpCompare(lhs->lhs(), rhs) == 1 || rhs->variant() == MINUS_OP && ExpCompare(lhs, rhs->lhs()) == 1)
{
result = new SgValueExp(-1);
break;
}
result = new SgExpression(lhs->thellnd);
bool error = false;
switch (rhs->variant())
{
case BOOL_VAL:
{
bool value = ((SgValueExp*)rhs)->boolValue();
if (value == false)
{
error = true;
break;
}
compute(result, value == true ? -1 : 0, (*it), divide,);
break;
}
case INT_VAL:
{
int value = ((SgValueExp*)rhs)->intValue();
if (value == 0)
{
error = true;
break;
}
compute(result, value, (*it), divide,);
break;
}
case FLOAT_VAL:
{
float value = (float)strtod(((SgValueExp*)rhs)->floatValue(), NULL);
if (value == 0.0f)
{
error = true;
break;
}
compute(result, value, (*it), divide,);
break;
}
case DOUBLE_VAL:
{
double value = strtod(((SgValueExp*)rhs)->doubleValue(), NULL);
if (value == 0.0)
{
error = true;
break;
}
compute(result, value, (*it), divide,);
break;
}
default:
changed = false;
delete result;
result = *it;
break;
}
if (error == true)
{
changed = false;
delete result;
result = *it;
}
break;
}
case EXP_OP:
{
SgExpression* lhs = args[0];
SgExpression* rhs = args[1];
result = new SgExpression(lhs->thellnd);
changed = true;
switch (rhs->variant())
{
case BOOL_VAL:
compute(result, (((SgValueExp*)rhs)->boolValue() == true ? -1 : 0), (*it), pow, (float));
break;
case INT_VAL:
compute(result, ((SgValueExp*)rhs)->intValue(), (*it), pow, (float));
break;
case FLOAT_VAL:
compute(result, strtod(((SgValueExp*)rhs)->floatValue(), NULL), (*it), pow,);
break;
case DOUBLE_VAL:
compute(result, strtod(((SgValueExp*)rhs)->doubleValue(), NULL), (*it), pow,);
break;
default:
changed = false;
delete result;
result = *it;
break;
}
break;
}
default:
// unsupported node with two subtrees, let compiler deal with it
result = *it;
break;
}
stack.push(result);
}
else
{
switch ((*it)->variant())
{
case FUNC_CALL:
{
vector<SgExpression*> args(arity[*it]);
for (int i = arity[*it] - 1; i >= 0; --i)
{
args[i] = stack.top();
stack.pop();
}
for (unsigned int i = 0; i < args.size(); ++i)
*((SgFunctionCallExp*)*it)->arg(i) = *args[i];
// probably can be evaluated
stack.push(*it);
break;
}
case ARRAY_REF:
{
vector<SgExpression*> subscripts(arity[*it]);
for (int i = arity[*it] - 1; i >= 0; --i)
{
subscripts[i] = stack.top();
stack.pop();
}
for (unsigned int i = 0; i < subscripts.size(); ++i)
*((SgArrayRefExp*)*it)->subscript(i) = *subscripts[i];
stack.push(*it);
break;
}
case MINUS_OP:
{
SgExpression* arg = stack.top();
SgExpression* result;
stack.pop();
changed = true;
switch (arg->variant())
{
case BOOL_VAL:
result = new SgValueExp(((SgValueExp*)arg)->boolValue() == true ? 1 : 0);
break;
case INT_VAL:
result = new SgValueExp(-((SgValueExp*)arg)->intValue());
break;
case FLOAT_VAL:
result = new SgValueExp(-(float)strtod(((SgValueExp*)arg)->floatValue(), NULL));
break;
case DOUBLE_VAL:
result = new SgValueExp(-strtod(((SgValueExp*)arg)->doubleValue(), NULL));
break;
case MINUS_OP:
result = arg->lhs();
break;
case UNARY_ADD_OP:
result = new SgExpression(MINUS_OP, new SgExpression(arg->lhs()->thellnd), NULL, NULL);
default:
changed = false;
result = *it;
break;
}
stack.push(result);
break;
}
case UNARY_ADD_OP:
break;
default:
// unsupported node with one subtree, let compiler deal with it
stack.push(*it);
break;
}
}
}
else
stack.push(*it);
}
if (changed == true)
{
rpn.clear();
getRPN(stack.top(), rpn);
arity.clear();
optimizeRPN(rpn, arity, false);
unrollRPN(rpn, arity);
optimizeRPN(rpn, arity, true);
}
else
*expr = *stack.top();
}
return expr;
}
void Access::getReferences(SgExpression* expr,
set<SgExpression*>& references,
map<SgExpression*, string>& unparsedRefs,
map<string, SgExpression*>& refs) const
{
vector<SgExpression*> subexprs;
subexprs.push_back(expr);
int k = 0;
for (vector<SgExpression*>::iterator p = subexprs.begin(); p != subexprs.end(); ++k, p = subexprs.begin() + k)
{
if ((*p)->variant() != VAR_REF && (*p)->variant() != ARRAY_REF)
{
SgExpression* lhs = (*p)->lhs();
SgExpression* rhs = (*p)->rhs();
if (lhs != NULL)
subexprs.push_back(lhs);
if (rhs != NULL)
subexprs.push_back(rhs);
}
else
{
// array reference subscripts are not real dependencies on loop indices
if ((*p)->variant() == ARRAY_REF)
continue;
string s((*p)->symbol()->identifier());
refs[s] = *p;
unparsedRefs[*p] = s;
}
}
for (map<SgExpression*, string>::iterator it = unparsedRefs.begin(); it != unparsedRefs.end(); ++it)
references.insert(refs[it->second]);
}
void Access::analyze()
{
const Loop* loop = array->getLoop();
const vector<BasicBlock>& blocks = loop->getBlocks();
const map<SgStatement*, int>& blockIn = loop->getBlockIn();
const vector<SgSymbol*>& symbols = loop->getSymbols();
int dimension = array->getDimension();
alignment = new int [dimension];
for (int i = 0; i < dimension; ++i)
alignment[i] = -1;
int i = 0;
for (SgExpression* expr = this->expr; expr != NULL; ++i, expr = expr->rhs())
{
map<SgExpression*, string> unparsedRefs;
map<string, SgExpression*> refs;
set<SgExpression*> references, result;
getReferences(expr->lhs(), references, unparsedRefs, refs);
result = references;
map<SgExpression*, set<SgStatement*> > definitions;
definitions[expr->lhs()] = blocks[blockIndex].INrd;
bool changed = true;
while (changed == true)
{
changed = false;
set<SgExpression*> new_references;
map<SgExpression*, set<SgStatement*> > new_definitions;
for (set<SgExpression*>::iterator ref = references.begin(); ref != references.end(); ++ref)
{
bool found = false;
for (size_t j = 0; j < symbols.size(); ++j)
{
if (symbols[j] == (*ref)->symbol())
{
new_references.insert(*ref);
result.insert(*ref);
found = true;
break;
}
}
if (found == false)
{
for (set<SgStatement*>::iterator def = definitions[*ref].begin(); def != definitions[*ref].end(); ++def)
{
if (unparsedLhs[(*def)->expr(0)] == unparsedRefs[*ref])
{
getReferences(rhs[unparsedRhs[(*def)->expr(1)]], new_references, unparsedRefs, refs);
for (set<SgExpression*>::iterator it = new_references.begin(); it != new_references.end(); ++it)
new_definitions[*it].insert(blocks[blockIn.at(*def)].INrd.begin(), blocks[blockIn.at(*def)].INrd.end());
found = true;
}
}
if (found == true)
result.erase(*ref);
}
}
if (new_references != references)
{
references = new_references;
definitions = new_definitions;
changed = true;
}
}
references.clear();
for (set<SgExpression*>::iterator it = result.begin(); it != result.end(); ++it)
references.insert(refs[unparsedRefs[*it]]);
if (references.size() == 1)
{
for (size_t j = 0; j < symbols.size(); ++j)
{
if (symbols[j] == (*references.begin())->symbol())
alignment[i] = j;
}
}
else if (references.size() > 1)
alignment[i] = -2;
}
for (i = 0; i < symbols.size(); ++i)
{
int j;
for (j = 0; j < dimension; ++j)
{
if (alignment[j] == i)
break;
}
if (j == dimension)
break;
}
if (i != symbols.size())
{
for (int i = 0; i < dimension; ++i)
{
if (alignment[i] == -2)
err((string("array '") + array->getSymbol()->identifier() + "': dependence on multiple loop indices").c_str(), 421, first_do_par);
}
}
}
void Array::analyze()
{
alignment = new int [dimension];
for (int i = 0; i < dimension; ++i)
alignment[i] = -1;
if (accesses.size() == 0)
return;
for (map<string, Access*>::iterator it = accesses.begin(); it != accesses.end(); ++it)
it->second->analyze();
int* tmp = new int [dimension];
int* prev = new int [dimension];
for (int i = 0; i < dimension; ++i)
{
prev[i] = -2;
tmp[i] = accesses.begin()->second->getAlignment()[i];
}
for (map<string, Access*>::iterator it1 = accesses.begin(); it1 != accesses.end(); ++it1)
{
const int* alignment = it1->second->getAlignment();
for (int i = 0; i < dimension; ++i)
{
if (alignment[i] > tmp[i])
{
prev[i] = tmp[i];
tmp[i] = alignment[i];
}
}
}
bool success = true;
for (int i = 0; i < dimension; ++i)
{
if (prev[i] >= 0)
{
success = false;
break;
}
}
if (success == true)
{
for (int i = 0; i < dimension; ++i)
alignment[i] = tmp[i];
}
else
err((string("array '") + symbol->identifier() + "': accesses with different subscripts' dependencies were found").c_str(), 422, first_do_par);
}
void Array::analyzeTransformDimensions()
{
int dimension = loop->getDimension();
if (dimension <= 1 || loop->getAcrossType() <= 1)
return;
int symbols[] = { -1, -1 };
if (dimension == loop->getAcrossType())
{
symbols[0] = dimension - 1;
symbols[1] = dimension - 2;
}
else
{
for (size_t i = acrossDims.size() - 1, j = 0; i != 0 && j != 2; --i)
{
if (acrossDims[i] == 1)
symbols[j++] = i;
}
}
int indices[] = { -1, -1 };
for (int i = 0; i < this->dimension; ++i)
{
if (symbols[0] == alignment[i])
indices[0] = i;
else if (symbols[1] == alignment[i])
indices[1] = i;
}
if (indices[0] != -1 && indices[1] != -1)
{
indices[0] = this->dimension - indices[0];
indices[1] = this->dimension - indices[1];
}
tfmInfo.transformDims.push_back(indices[0]);
tfmInfo.transformDims.push_back(indices[1]);
}
SgSymbol* Array::findAccess(SgExpression* subscripts, string& expr)
{
size_t i = 0;
int j = 0;
string id;
for (SgExpression* tmp = subscripts; tmp != NULL && i < 2; ++j, tmp = tmp->rhs())
{
if (dimension - j == tfmInfo.transformDims[0] || dimension - j == tfmInfo.transformDims[1])
{
id.append(tmp->lhs()->unparse()).append("_");
++i;
}
}
SgSymbol* result = NULL;
for (i = 0; i < tfmInfo.exprs.size(); ++i)
{
if (tfmInfo.exprs[i].first == id)
{
result = tfmInfo.coefficients[i];
break;
}
}
if (result == NULL)
expr = id;
return result;
}
void Array::addCoefficient(SgExpression* subscripts, string& expr, SgSymbol* symbol)
{
int i = 0;
for (SgExpression* tmp = subscripts; tmp != NULL; ++i, tmp = tmp->rhs())
{
if (dimension - i == tfmInfo.transformDims[0])
tfmInfo.first.push_back(tmp->lhs());
else if (dimension - i == tfmInfo.transformDims[1])
tfmInfo.second.push_back(tmp->lhs());
}
tfmInfo.exprs.push_back(pair<string, string>(expr, subscripts->unparse()));
tfmInfo.coefficients.push_back(symbol);
}
void Loop::analyzeAcrossClause()
{
for (SgExpression* expr = dvm_parallel_dir->expr(1); expr != NULL; expr = expr->rhs())
{
SgExpression* tmp = expr->lhs();
if (tmp->variant() == ACROSS_OP)
{
vector<SgExpression*> toAnalyze;
SgExpression* list = tmp->lhs();
while (list)
{
if (list->lhs()->variant() == ARRAY_REF)
toAnalyze.push_back(list->lhs());
else if (list->lhs()->variant() == ARRAY_OP)
{
if (list->lhs()->lhs()->variant() == ARRAY_REF)
toAnalyze.push_back(list->lhs()->lhs());
}
list = list->rhs();
}
for (int k = 0; k < toAnalyze.size(); ++k)
{
tmp = toAnalyze[k];
if (arrays.find(tmp->symbol()) == arrays.end())
warn((string("array '") + tmp->symbol()->identifier() + "': unused").c_str(), 900, first_do_par);
else if (privateList.find(tmp->symbol()) != privateList.end())
err((string("array '") + tmp->symbol()->identifier() + "': incompatible qualifiers (ACROSS, PRIVATE)").c_str(), 423, first_do_par);
else
{
Array* array = arrays[tmp->symbol()];
SgExpression* dep = tmp->lhs();
int i = 0, raw, war, n = 0;
vector<int>& acrossDims = array->getAcrossDims();
while (dep != NULL)
{
raw = dep->lhs()->lhs()->valueInteger();
war = dep->lhs()->rhs()->valueInteger();
acrossDims[i] = (raw != 0 || war != 0) ? 1 : 0;
n += acrossDims[i];
i++;
dep = dep->rhs();
}
if (n != 0)
array->setAcrossType((1 << n) - 1);
for (int j = 0; j < abs(dimension - array->getDimension()); ++j)
acrossDims.push_back(-1);
}
}
}
}
}
void Loop::analyzeAcrossType()
{
acrossDims = new int [dimension];
for (int i = 0; i < dimension; ++i)
acrossDims[i] = -1;
for (map<SgSymbol*, Array*>::iterator it = arrays.begin(); it != arrays.end(); ++it)
{
const int* alignment = it->second->getAlignment();
vector<int>& _acrossDims = it->second->getAcrossDims();
if (alignment != NULL)
{
for (int i = 0; i < it->second->getDimension(); ++i)
{
if (alignment[i] != -1)
acrossDims[alignment[i]] = max(acrossDims[alignment[i]], _acrossDims[alignment[i]]);
}
}
}
for (int i = 0; i < dimension; ++i)
{
if (acrossDims[i] != -1)
++acrossType;
}
}
void Array::generateAssigns(SgVarRefExp* offsetX, SgVarRefExp* offsetY, SgVarRefExp* Rx, SgVarRefExp* Ry, SgVarRefExp* slash)
{
if (tfmInfo.ifCalls.size() == 0 && tfmInfo.elseCalls.size() == 0 && tfmInfo.zeroSt.size() == 0)
{
for (size_t i = 0; i < tfmInfo.coefficients.size(); ++i)
{
tfmInfo.zeroSt.push_back(AssignStatement(new SgVarRefExp(tfmInfo.coefficients[i]->copy()), new SgValueExp(0)));
SgFunctionCallExp* funcCallExpIf = createNewFCall(funcDvmhConvXYname);
SgFunctionCallExp* funcCallExpElse = createNewFCall(funcDvmhConvXYname);
funcCallExpIf->addArg(*new SgCastExp(*offsetX->type(), tfmInfo.first[i]->copy()) - *offsetX);
funcCallExpIf->addArg(*new SgCastExp(*offsetY->type(), tfmInfo.second[i]->copy()) - *offsetY);
funcCallExpIf->addArg(*Rx);
funcCallExpIf->addArg(*Ry);
funcCallExpIf->addArg(*slash);
funcCallExpIf->addArg(*new SgVarRefExp(tfmInfo.coefficients[i]->copy()));
funcCallExpElse->addArg(*new SgCastExp(*offsetX->type(), tfmInfo.second[i]->copy()) - *offsetX);
funcCallExpElse->addArg(*new SgCastExp(*offsetY->type(), tfmInfo.first[i]->copy()) - *offsetY);
funcCallExpElse->addArg(*Rx);
funcCallExpElse->addArg(*Ry);
funcCallExpElse->addArg(*slash);
funcCallExpElse->addArg(*new SgVarRefExp(tfmInfo.coefficients[i]->copy()));
SgStatement* stmt = NULL;
set<Access*> _accesses;
for (map<string, Access*>::iterator it = accesses.begin(); it != accesses.end(); ++it)
{
bool found[2] = { false, false };
string first(tfmInfo.first[i]->unparse());
string second(tfmInfo.second[i]->unparse());
for (SgExpression* tmp = it->second->getSubscripts(); tmp != NULL; tmp = tmp->rhs())
{
string s(tmp->lhs()->unparse());
if (s == first)
found[0] = true;
else if (s == second)
found[1] = true;
}
if (found[0] == true && found[1] == true)
_accesses.insert(it->second);
}
map<Access*, set<int> > blockIndices;
int minIndex = loop->getBlocks().size();
for (set<Access*>::iterator it = _accesses.begin(); it != _accesses.end(); ++it)
{
set<SgSymbol*> symbols;
int j = 0;
for (SgExpression* tmp = (*it)->getSubscripts(); tmp != NULL; tmp = tmp->rhs())
{
if (dimension - j != tfmInfo.transformDims[0] && dimension - j != tfmInfo.transformDims[1])
continue;
vector<SgExpression*> _subtrees;
_subtrees.push_back(tmp->lhs());
int k = 0;
for (vector<SgExpression*>::iterator p = _subtrees.begin(); p != _subtrees.end(); ++k, p = _subtrees.begin() + k)
{
if ((*p)->variant() == VAR_REF && (*p)->symbol() != NULL)
symbols.insert((*p)->symbol());
else
{
SgExpression* lhs = (*p)->lhs();
SgExpression* rhs = (*p)->rhs();
if (lhs != NULL)
_subtrees.push_back(lhs);
if (rhs != NULL)
_subtrees.push_back(rhs);
}
}
}
set<SgSymbol*> _symbols(loop->getSymbols().begin(), loop->getSymbols().end());
set<SgSymbol*> diff;
difference(symbols.begin(), symbols.end(), _symbols.begin(), _symbols.end(), inserter(diff, diff.end()));
const vector<BasicBlock>& blocks = loop->getBlocks();
if (diff.size() != 0)
{
set<int> preds(blocks[(*it)->getBlockIndex()].in.begin(), blocks[(*it)->getBlockIndex()].in.end());
bool changed = true;
while (changed == true)
{
changed = false;
set<int> new_preds(preds);
for (set<int>::iterator pred = preds.begin(); pred != preds.end(); ++pred)
new_preds.insert(blocks[*pred].in.begin(), blocks[*pred].in.end());
if (preds != new_preds)
{
preds = new_preds;
changed = true;
}
}
blockIndices[*it].insert(preds.begin(), preds.end());
}
else
blockIndices[*it].insert(0);
minIndex = min(minIndex, (*it)->getBlockIndex());
}
set<int> common_preds;
for (set<Access*>::iterator it = _accesses.begin(); it != _accesses.end(); ++it)
common_preds.insert(blockIndices[*it].begin(), blockIndices[*it].end());
for (set<Access*>::iterator it = _accesses.begin(); it != _accesses.end(); ++it)
{
if (blockIndices[*it].size() == 1 && *blockIndices[*it].begin() == 0)
continue;
else
{
set<int> tmp;
intersection(common_preds.begin(), common_preds.end(), blockIndices[*it].begin(), blockIndices[*it].end(), inserter(tmp, tmp.end()));
common_preds = tmp;
}
}
int max = 0;
for (set<int>::iterator it = common_preds.begin(); it != common_preds.end(); ++it)
{
if (*it < minIndex)
{
if (*it > max)
max = *it;
}
}
stmt = loop->getBlocks()[max].head;
tfmInfo.ifCalls[stmt].push_back(funcCallExpIf);
tfmInfo.elseCalls[stmt].push_back(funcCallExpElse);
}
}
}
bool Loop::irregularAnalysisIsOn() const
{
return do_irreg_opt;
}
static bool isOnlyParS(SgExpression* ex, SgSymbol* parS)
{
bool ret = true;
if (ex)
{
if (ex->variant() != VAR_REF || ex->variant() == CONST_REF)
return false;
if (ex->variant() == VAR_REF)
if (ex->symbol()->identifier() != string(parS->identifier()))
return false;
bool left = isOnlyParS(ex->lhs(), parS);
bool right = isOnlyParS(ex->rhs(), parS);
ret = left && right;
}
return ret;
}
static void analyzeExpr(SgExpression* ex, SgSymbol* parS, int arrayLvl, bool& needOpt, bool& wasInderectAccess)
{
if (ex)
{
if (ex->variant() == ARRAY_REF)
{
if (arrayLvl > 0)
wasInderectAccess = true;
arrayLvl++;
if (isOnlyParS(ex->lhs(), parS) == false)
needOpt = true;
}
analyzeExpr(ex->lhs(), parS, arrayLvl, needOpt, wasInderectAccess);
analyzeExpr(ex->rhs(), parS, arrayLvl, needOpt, wasInderectAccess);
}
}
void Loop::analyzeInderectAccess()
{
if (symbols.size() != 1)
return;
SgStatement* stmt = loop_body;
bool wasInderectAccess = false;
bool needOpt = false;
while (stmt)
{
for (int z = 0; z < 3; ++z)
analyzeExpr(stmt->expr(z), symbols[0], 0, needOpt, wasInderectAccess);
stmt = stmt->lexNext();
}
if (wasInderectAccess && needOpt)
do_irreg_opt = true;
}
Loop::Loop(SgStatement* loop_body, bool enable_opt, bool irreg_access) :
irregular_acc_opt(irreg_access), enable_opt(enable_opt), loop_body(loop_body),
dimension(0), acrossType(0), acrossDims(NULL), do_irreg_opt(false)
{
lhs.clear();
rhs.clear();
unparsedLhs.clear();
unparsedRhs.clear();
buildCFG();
setupSubstitutes();
for (int i = 2; i < blocks.size(); ++i)
if (blocks[i].head != NULL && (blocks[i].head->variant() == ASSIGN_STAT || blocks[i].head->variant() == PROC_STAT))
analyzeAssignments(blocks[i].index, blocks[i].head);
for (SgExpression* tmp = dvm_parallel_dir->expr(2); tmp != NULL; tmp = tmp->rhs())
{
symbols.push_back(tmp->lhs()->symbol());
++dimension;
}
for (SgExpression* tmp = dvm_parallel_dir->expr(1); tmp != NULL; tmp = tmp->rhs())
{
SgExpression* t = tmp->lhs();
if (t->variant() == ACC_PRIVATE_OP)
{
for (t = t->lhs(); t != NULL; t = t->rhs())
{
if (isSgArrayType(t->lhs()->symbol()->type()) != NULL)
privateList.insert(t->lhs()->symbol());
}
}
}
SgSymbol* symbol = NULL;
SgExpression* subscripts = NULL;
if (dvm_parallel_dir->expr(0))
{
symbol = dvm_parallel_dir->expr(0)->symbol();
subscripts = ((SgArrayRefExp*)dvm_parallel_dir->expr(0))->subscripts();
}
else // TIE
{
SgExpression* arc = findDirect(dvm_parallel_dir->expr(1), ACROSS_OP);
SgExpression* tie = findDirect(dvm_parallel_dir->expr(1), ACC_TIE_OP);
if (arc != NULL && tie == NULL)
{
err("internal error in across", 424, first_do_par);
exit(-1);
}
else if (arc && tie)
{
map<string, SgExpression*> acrossArrays, tieArrays;
SgExpression* ex = arc->lhs();
while (ex)
{
acrossArrays[ex->lhs()->symbol()->identifier()] = ex->lhs();
ex = ex->rhs();
}
ex = tie->lhs();
while (ex)
{
tieArrays[ex->lhs()->symbol()->identifier()] = ex->lhs();
ex = ex->rhs();
}
bool errM = false;
for (map<string, SgExpression*>::iterator acrA = acrossArrays.begin(); acrA != acrossArrays.end(); acrA++)
{
if (tieArrays.find(acrA->first) == tieArrays.end())
{
errM = true;
err((string("can not find array '") + acrA->first + "' in TIE clause").c_str(), 425, first_do_par);
}
}
if (errM)
exit(-1);
//TODO: multiple arrays
for (map<string, SgExpression*>::iterator acrA = acrossArrays.begin(); acrA != acrossArrays.end(); acrA++)
{
SgExpression* firstTie = tieArrays[acrA->first];
symbol = firstTie->symbol();
subscripts = ((SgArrayRefExp*)firstTie)->subscripts();
break;
}
}
else
{
if (irreg_access)
analyzeInderectAccess();
return;
}
}
//TODO: tmp is undefined in this scope
if (arrays.find(symbol) == arrays.end())
warn((string("array '") + symbol->identifier() + "': unused").c_str(), 900, first_do_par);
for (map<SgSymbol*, Array*>::iterator it1 = arrays.begin(); it1 != arrays.end(); ++it1)
{
if (privateList.find(it1->second->getSymbol()) == privateList.end())
it1->second->analyze();
}
// ACROSS_ANALYZER
if (WithAcrossClause() == 0)
{
if (irreg_access)
analyzeInderectAccess();
return;
}
analyzeAcrossClause();
vector<int> acrossDims(symbols.size(), -1);
if (arrays.find(symbol) != arrays.end())
acrossDims = arrays[symbol]->getAcrossDims();
size_t i;
for (i = 0; i < symbols.size(); ++i)
{
if (acrossDims[i] != -1)
break;
if (i == symbols.size())
err((string("array '") + symbol->identifier() + "': mapped on different template than corresponding parallel loop").c_str(), 424, first_do_par);
}
analyzeAcrossType();
if (acrossType > 1)
{
for (map<SgSymbol*, Array*>::iterator it1 = arrays.begin(); it1 != arrays.end(); ++it1)
{
if (privateList.find(it1->second->getSymbol()) == privateList.end())
it1->second->analyzeTransformDimensions();
}
}
#if 0
printf("Loop indices(%d):", dimension);
for (vector<SgSymbol*>::iterator it = symbols.begin(); it != symbols.end(); ++it)
printf(" %s", (*it)->identifier());
printf("\n");
printf("Private arrays:");
for (set<SgSymbol*>::iterator it = privateList.begin(); it != privateList.end(); ++it)
printf(" \"%s\"", (*it)->identifier());
printf("\n");
for (map<SgSymbol*, Array*>::iterator it1 = arrays.begin(); it1 != arrays.end(); ++it1)
{
if (privateList.find(it1->first) == privateList.end())
{
printf("Array %s:", it1->second->getSymbol()->identifier());
for (int i = 0; i < it1->second->getDimension(); ++i)
printf(" %d", it1->second->getAlignment()[i]);
printf("\n");
}
printf(" AcrossDims:");
for (vector<int>::iterator it2 = it1->second->getAcrossDims().begin(); it2 != it1->second->getAcrossDims().end(); ++it2)
printf(" %d", *it2);
printf("\n");
printf(" AcrossType: %d\n", it1->second->getAcrossType());
if (privateList.find(it1->first) == privateList.end())
{
printf(" TransformDims:");
for (vector<int>::iterator it2 = it1->second->getTfmInfo().transformDims.begin(); it2 != it1->second->getTfmInfo().transformDims.end(); ++it2)
printf(" %d", *it2);
printf("\n");
for (map<string, Access*>::iterator it2 = it1->second->getAccesses().begin(); it2 != it1->second->getAccesses().end(); ++it2)
{
printf(" Access:");
for (int i = 0; i < it1->second->getDimension(); ++i)
printf(" %d", it2->second->getAlignment()[i]);
printf("\n");
}
}
}
printf(" LoopAcrossType: %d\n", acrossType);
printf(" LoopAcrossDims:");
for (int i = 0; i < dimension; ++i)
printf(" %d", acrossDims[i]);
printf("\n");
char* scriptName = new char[64];
sprintf(scriptName, "cfg.loop_%d.gv", first_do_par->lineNumber());
visualize(scriptName);
delete[]scriptName;
printf("############################################################\n");
#endif
}
void Loop::analyzeAssignments(SgExpression* ex, const int blockIndex)
{
if (ex->variant() != ARRAY_REF)
{
SgExpression* lhs = ex->lhs();
SgExpression* rhs = ex->rhs();
if (lhs)
analyzeAssignments(lhs, blockIndex);
if (rhs)
analyzeAssignments(rhs, blockIndex);
}
else
{
SgSymbol* symbol = ex->symbol();
if (isSgArrayType(symbol->type()) != NULL)
{
SgExpression* subscripts = ((SgArrayRefExp*)(ex))->subscripts();
if (!subscripts)
return;
for (SgExpression* tmp = subscripts; tmp != NULL; tmp = tmp->rhs())
tmp->setLhs(simplify(tmp->lhs()));
string s(subscripts->unparse());
if (arrays.find(symbol) == arrays.end())
{
Array* array = new Array(symbol, isSgArrayType(symbol->type())->dimension(), this);
arrays[symbol] = array;
array->getAccesses()[s] = new Access(subscripts, s, array, blockIndex);
}
else
{
Array* array = arrays[symbol];
if (array->getAccesses().find(s) == array->getAccesses().end())
array->getAccesses()[s] = new Access(subscripts, s, array, blockIndex);
}
}
}
}
void Loop::analyzeAssignments(int blockIndex, SgStatement* stmt)
{
for (int i = 0; i < 3; ++i)
if (stmt->expr(i))
analyzeAssignments(stmt->expr(i), blockIndex);
}
inline bool Loop::IsTargetable(SgStatement* stmt) const
{
return stmt != NULL
&& stmt->variant() != ELSEIF_NODE
&& stmt->variant() != CASE_NODE
&& stmt->variant() != DEFAULT_NODE
&& stmt->variant() != CONTROL_END;
}
void Loop::buildCFG()
{
SgStatement* stmt = loop_body;
map<SgStatement*, SgStatement*> controlFlow;
map<int, vector<SgStatement*> > blockOut;
map<int, set<string> > GENae, KILLae, INae, OUTae;
map<string, vector<SgStatement*> > EXTRA;
map<int, set<SgStatement*> > GENrd, KILLrd;
map<int, map<string, SgStatement*> > blockAssignments;
map<SgStatement*, string> assignments;
set<string> allStmts;
BasicBlock entry;
entry.index = ENTRY;
BasicBlock exit;
exit.index = EXIT;
blockOut[ENTRY].push_back(stmt);
blockIn[NULL] = EXIT;
blocks.push_back(entry);
blocks.push_back(exit);
int i = 2;
while (stmt != NULL)
{
BasicBlock block;
block.index = i;
block.head = stmt;
blockIn[stmt] = i;
vector<SgStatement*>& out = blockOut[i];
list<string> stmts;
while (stmt != NULL)
{
bool tail = true;
switch (stmt->variant())
{
case WHERE_NODE:
break;
case WHERE_BLOCK_STMT:
break;
case ELSEWH_NODE:
break;
case SWITCH_NODE:
{
SgSwitchStmt* _stmt = (SgSwitchStmt*)stmt;
controlFlow[_stmt] = IsTargetable(_stmt->lastNodeOfStmt()->lexNext())
&& _stmt->lastNodeOfStmt()->lexNext()->controlParent() == _stmt->controlParent() ? _stmt->lastNodeOfStmt()->lexNext() : controlFlow[_stmt->controlParent()];
if (_stmt->caseOption(0) == NULL)
{
if (_stmt->defOption() == NULL)
out.push_back(controlFlow[_stmt]);
else
out.push_back(_stmt->defOption());
}
else
out.push_back(_stmt->caseOption(0));
break;
}
case CASE_NODE:
{
SgSwitchStmt* switchStmt = ((SgSwitchStmt*)stmt->controlParent());
controlFlow[stmt] = controlFlow[switchStmt];
int i;
for (i = 0; i < switchStmt->numberOfCaseOptions() && stmt != switchStmt->caseOption(i); i++);
SgStatement* nextStmt = stmt->lexNext();
if (nextStmt->variant() != CASE_NODE && nextStmt->variant() != DEFAULT_NODE && nextStmt->variant() != CONTROL_END)
out.push_back(nextStmt);
if (i == switchStmt->numberOfCaseOptions() - 1)
{
if (switchStmt->defOption() != NULL)
out.push_back(switchStmt->defOption());
else
out.push_back(controlFlow[stmt]);
}
else
out.push_back(switchStmt->caseOption(i + 1));
break;
}
case DEFAULT_NODE:
{
controlFlow[stmt] = controlFlow[stmt->controlParent()];
SgStatement* nextStmt = stmt->lexNext();
if (nextStmt->variant() != CASE_NODE && nextStmt->variant() != CONTROL_END)
out.push_back(nextStmt);
out.push_back(controlFlow[stmt]);
break;
}
case ARITHIF_NODE:
// something wrong with SgArithIfStmt::label(...) method, this seems ok
out.push_back(StmtWithLabel(((SgLabelRefExp*)LlndMapping(getPositionInExprList(BIF_LL2(stmt->thebif), 0)))->label()));
out.push_back(StmtWithLabel(((SgLabelRefExp*)LlndMapping(getPositionInExprList(BIF_LL2(stmt->thebif), 1)))->label()));
out.push_back(StmtWithLabel(((SgLabelRefExp*)LlndMapping(getPositionInExprList(BIF_LL2(stmt->thebif), 2)))->label()));
break;
case IF_NODE:
{
SgStatement* falseBody = ((SgIfStmt*)stmt)->falseBody();
SgStatement* _stmt = stmt;
while (falseBody != NULL && falseBody->variant() == ELSEIF_NODE)
{
_stmt = falseBody;
falseBody = ((SgIfStmt*)falseBody)->falseBody();
}
controlFlow[stmt] = IsTargetable(_stmt->lastNodeOfStmt()->lexNext())
&& _stmt->lastNodeOfStmt()->lexNext()->controlParent() == stmt->controlParent() ? _stmt->lastNodeOfStmt()->lexNext() : controlFlow[stmt->controlParent()];
SgStatement* trueBody = ((SgIfStmt*)stmt)->trueBody();
falseBody = ((SgIfStmt*)stmt)->falseBody();
bool trueBodyCond = trueBody != NULL && trueBody->variant() != CONTROL_END;
bool falseBodyCond = falseBody != NULL && falseBody->variant() != CONTROL_END;
if (trueBodyCond == true)
out.push_back(trueBody);
if (falseBodyCond == true)
out.push_back(falseBody);
if (trueBodyCond == false || falseBodyCond == false)
out.push_back(controlFlow[stmt]);
break;
}
case ELSEIF_NODE:
{
controlFlow[stmt] = controlFlow[stmt->controlParent()];
SgStatement* trueBody = ((SgIfStmt*)stmt)->trueBody();
SgStatement* falseBody = ((SgIfStmt*)stmt)->falseBody();
bool trueBodyCond = trueBody != NULL && trueBody->variant() != CONTROL_END;
bool falseBodyCond = falseBody != NULL && falseBody->variant() != CONTROL_END;
if (trueBodyCond == true)
out.push_back(trueBody);
if (falseBodyCond == true)
out.push_back(falseBody);
if (trueBodyCond == false || falseBodyCond == false)
out.push_back(controlFlow[stmt]);
break;
}
case LOGIF_NODE:
controlFlow[stmt] = IsTargetable(stmt->lastNodeOfStmt()->lexNext())
&& stmt->lastNodeOfStmt()->lexNext()->controlParent() == stmt->controlParent() ? stmt->lastNodeOfStmt()->lexNext() : controlFlow[stmt->controlParent()];
out.push_back(((SgLogIfStmt*)stmt)->body());
out.push_back(controlFlow[stmt]);
break;
case WHILE_NODE:
{
SgWhileStmt* _stmt = (SgWhileStmt*)stmt;
controlFlow[stmt] = stmt;
out.push_back(_stmt->body());
SgStatement* st = _stmt->body();
while (st != NULL && st->controlParent() != stmt->controlParent())
st = st->lexNext();
SgStatement* nextStmt = IsTargetable(st)
&& st->controlParent() == stmt->controlParent() ? st : controlFlow[stmt->controlParent()];
out.push_back(nextStmt);
break;
}
case COMGOTO_NODE:
{
SgComputedGotoStmt* _stmt = (SgComputedGotoStmt*)stmt;
controlFlow[_stmt] = IsTargetable(_stmt->lastNodeOfStmt()->lexNext())
&& _stmt->lastNodeOfStmt()->lexNext()->controlParent() == _stmt->controlParent() ? _stmt->lastNodeOfStmt()->lexNext() : controlFlow[_stmt->controlParent()];
SgExpression* labelList = _stmt->labelList();
for (int i = 0; i < _stmt->numberOfTargets(); i++, labelList = labelList->rhs())
out.push_back(StmtWithLabel(((SgLabelRefExp*)labelList->lhs())->label()));
out.push_back(controlFlow[_stmt]);
break;
}
case FOR_NODE:
{
SgForStmt* _stmt = (SgForStmt*)stmt;
controlFlow[_stmt] = _stmt;
out.push_back(_stmt->body());
SgStatement* st = _stmt->body();
while (st != NULL && st->controlParent() != _stmt->controlParent())
st = st->lexNext();
SgStatement* nextStmt = IsTargetable(st)
&& st->controlParent() == _stmt->controlParent() ? st : controlFlow[_stmt->controlParent()];
out.push_back(nextStmt);
if (_stmt->symbol() != NULL)
{
SgStatement* inc = new SgAssignStmt(*new SgVarRefExp(_stmt->symbol()), *new SgVarRefExp(_stmt->symbol()) + (_stmt->step() != NULL ? *new SgValueExp(_stmt->step()->valueInteger()) : *new SgValueExp(1)));
blockAssignments[i][inc->expr(0)->unparse()] = inc;
for (list<string>::iterator it = stmts.begin(); it != stmts.end();)
{
if (EXTRA[*it][0]->expr(1)->IsSymbolInExpression(*_stmt->symbol()) != NULL)
it = stmts.erase(it);
else
++it;
}
}
break;
}
case GOTO_NODE:
out.push_back(StmtWithLabel(((SgGotoStmt*)stmt)->branchLabel()));
break;
case EXIT_STMT:
{
SgExitStmt* _stmt = (SgExitStmt*)stmt;
SgSymbol* constructName = _stmt->constructName();
SgStatement* parent = _stmt->controlParent();
if (constructName != NULL)
while (parent != NULL && ((parent->variant() != FOR_NODE && parent->variant() != WHILE_NODE) || strcmp(LlndMapping(BIF_LL3(parent->thebif))->unparse(), constructName->identifier()) != 0))
parent = parent->controlParent();
else
while (parent != NULL && parent->variant() != FOR_NODE && parent->variant() != WHILE_NODE)
parent = parent->controlParent();
if (parent != NULL)
{
SgStatement* st = ((SgForStmt*)parent)->body();
while (st != NULL && st->controlParent() != parent->controlParent())
st = st->lexNext();
out.push_back((IsTargetable(st) && st->controlParent() == parent->controlParent()) ? st : controlFlow[parent->controlParent()]);
}
else
out.push_back(NULL);//jump to parallel DOs
break;
}
case CYCLE_STMT:
{
SgCycleStmt* _stmt = (SgCycleStmt*)stmt;
SgSymbol* constructName = _stmt->constructName();
SgStatement* parent = _stmt->controlParent();
if (constructName != NULL)
while (parent != NULL && ((parent->variant() != FOR_NODE && parent->variant() != WHILE_NODE) || strcmp(LlndMapping(BIF_LL3(parent->thebif))->unparse(), constructName->identifier()) != 0))
parent = parent->controlParent();
else
while (parent != NULL && parent->variant() != FOR_NODE && parent->variant() != WHILE_NODE)
parent = parent->controlParent();
out.push_back(parent);
break;
}
case ASSIGN_STAT:
{
string s0(simplify(stmt->expr(0))->unparse());
string s1(simplify(stmt->expr(1))->unparse());
unparsedLhs[stmt->expr(0)] = s0;
unparsedRhs[stmt->expr(1)] = s1;
lhs[s0] = stmt->expr(0);
rhs[s1] = stmt->expr(1);
if (s0 != s1)
{
if (stmt->expr(0)->variant() == ARRAY_REF)
{
bool success = true;
for (SgExpression* tmp = ((SgArrayRefExp*)stmt->expr(0))->subscripts(); tmp != NULL; tmp = tmp->rhs())
{
if (tmp->lhs()->variant() != CONST_REF)
{
success = false;
break;
}
}
if (success == true)
blockAssignments[i][s0] = stmt;
else
blockAssignments[i][stmt->expr(0)->symbol()->identifier()] = stmt;
}
else
blockAssignments[i][s0] = stmt;
GENrd[i].insert(stmt);
assignments[stmt] = s1;
EXTRA[s1].push_back(stmt);
stmts.push_back(s1);
allStmts.insert(s1);
for (list<string>::iterator it = stmts.begin(); it != stmts.end();)
{
if (FindInExpr(stmt->expr(0), EXTRA[*it][0]->expr(1)) != 0)
it = stmts.erase(it);
else
++it;
}
}
}
default:
{
if (stmt->hasLabel() == false)
tail = false;
else
{
SgStatement* parent = stmt->controlParent();
while (parent != NULL && (parent->variant() == FOR_NODE || parent->variant() == WHILE_NODE))
{
if (BIF_LABEL_USE(parent->thebif) != NULL && LABEL_STMTNO(BIF_LABEL_USE(parent->thebif)) == LABEL_STMTNO(stmt->label()->thelabel))
out.push_back(parent);
parent = parent->controlParent();
}
if (out.size() != 0)
break;
}
SgStatement* _stmt = stmt->lexNext();
if (_stmt != NULL)
{
switch (_stmt->variant())
{
case FOR_NODE:
case WHILE_NODE:
case WHERE_NODE:
case WHERE_BLOCK_STMT:
tail = true;
out.push_back(_stmt);
break;
case ELSEIF_NODE:
case ELSEWH_NODE:
case CASE_NODE:
case DEFAULT_NODE:
case CONTROL_END:
tail = true;
out.push_back(controlFlow[_stmt->controlParent()]);
break;
case FORMAT_STAT:
tail = false;
break;
default:
if (_stmt->hasLabel() == false)
{
//tail = false;break;// builds CFG of Extended Basic Blocks
tail = true;
out.push_back(_stmt);
break;
}
else
{
SgStatement* parent = _stmt->controlParent();
while (parent != NULL && (parent->variant() == FOR_NODE || parent->variant() == WHILE_NODE))
{
if (BIF_LABEL_USE(parent->thebif) != NULL && LABEL_STMTNO(BIF_LABEL_USE(parent->thebif)) == LABEL_STMTNO(_stmt->label()->thelabel))
{
tail = false;
break;
}
parent = parent->controlParent();
}
//can't find way to get stmts referencing this label
//just start new block even if label is not referenced
tail = true;
out.push_back(_stmt);
break;
}
break;
}
}
else
out.push_back(NULL);
break;
}
}
if (tail == true)
{
GENae[i].insert(stmts.begin(), stmts.end());
block.tail = stmt;
blocks.push_back(block);
}
stmt = stmt->lexNext();
while (stmt != NULL && stmt->variant() == CONTROL_END)
stmt = stmt->lexNext();
if (tail == true)
break;
}
i++;
}
for (map<int, vector<SgStatement*> >::iterator it1 = blockOut.begin(); it1 != blockOut.end(); ++it1)
{
for (vector<SgStatement*>::iterator it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
{
blocks[it1->first].out.push_back(blockIn[*it2]);
blocks[blockIn[*it2]].in.push_back(it1->first);
}
}
blockOut.clear();
controlFlow.clear();
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
map<string, SgStatement*>* bAssignments = &blockAssignments[block->index];
for (map<SgStatement*, string>::iterator it = assignments.begin(); it != assignments.end(); ++it)
{
SgStatement* stmt = NULL;
SgExpression* lhs = it->first->expr(0);
if (it->first->expr(0)->variant() == ARRAY_REF)
stmt = bAssignments->find(lhs->symbol()->identifier()) != bAssignments->end() ?
(*bAssignments)[lhs->symbol()->identifier()] : (*bAssignments)[unparsedLhs[lhs]];
else
stmt = (*bAssignments)[unparsedLhs[lhs]];
if (stmt != NULL && stmt != it->first && blockIn[it->first] != block->index)
KILLrd[block->index].insert(it->first);
}
for (SgStatement* stmt = block->head; stmt != block->tail->lexNext(); stmt = stmt->lexNext())
{
if (stmt == NULL)
continue;
if (stmt->variant() == ASSIGN_STAT || stmt->variant() == FOR_NODE)
{
SgExpression* expr = stmt->variant() == ASSIGN_STAT ? stmt->expr(0) : (*bAssignments)[stmt->symbol()->identifier()]->expr(0);
for (map<SgStatement*, string>::iterator it = assignments.begin(); it != assignments.end(); ++it)
if (FindInExpr(expr, it->first->expr(1)) != 0)
KILLae[block->index].insert(it->second);
}
}
block->OUTrd.swap(GENrd[block->index]);
difference(allStmts.begin(), allStmts.end(), KILLae[block->index].begin(), KILLae[block->index].end(), inserter(OUTae[block->index], OUTae[block->index].end()));
}
allStmts.clear();
assignments.clear();
blockAssignments.clear();
bool changed = true;
while (changed == true)
{
changed = false;
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
for (vector<int>::iterator it = block->in.begin(); it != block->in.end(); ++it)
block->INrd.insert(blocks[*it].OUTrd.begin(), blocks[*it].OUTrd.end());
set<SgStatement*> newOUTrd(GENrd[block->index].begin(), GENrd[block->index].end());
difference(block->INrd.begin(), block->INrd.end(), KILLrd[block->index].begin(), KILLrd[block->index].end(), inserter(newOUTrd, newOUTrd.end()));
if (newOUTrd != block->OUTrd)
{
block->OUTrd.swap(newOUTrd);
changed = true;
}
}
}
GENrd.clear();
KILLrd.clear();
changed = true;
while (changed == true)
{
changed = false;
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
if (block->in.size() != 0)
{
INae[block->index] = set<string>(OUTae[block->in[0]].begin(), OUTae[block->in[0]].end());
for (vector<int>::iterator it = block->in.begin() + 1; it != block->in.end(); ++it)
{
set<string> tmp;
intersection(INae[block->index].begin(), INae[block->index].end(), OUTae[*it].begin(), OUTae[*it].end(), inserter(tmp, tmp.end()));
INae[block->index].swap(tmp);
}
}
set<string> _union(GENae[block->index].begin(), GENae[block->index].end());
_union.insert(INae[block->index].begin(), INae[block->index].end());
set<string> newOUTae;
difference(_union.begin(), _union.end(), KILLae[block->index].begin(), KILLae[block->index].end(), inserter(newOUTae, newOUTae.end()));
if (newOUTae != OUTae[block->index])
{
OUTae[block->index].swap(newOUTae);
changed = true;
}
}
}
GENae.clear();
KILLae.clear();
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
for (set<string>::iterator it1 = INae[block->index].begin(); it1 != INae[block->index].end(); ++it1)
block->INae.insert(EXTRA[*it1].begin(), EXTRA[*it1].end());
for (set<string>::iterator it1 = OUTae[block->index].begin(); it1 != OUTae[block->index].end(); ++it1)
block->OUTae.insert(EXTRA[*it1].begin(), EXTRA[*it1].end());
}
}
Loop::Loop(SgStatement* stmt) : do_irreg_opt(false)
{
lhs.clear(); rhs.clear(); unparsedLhs.clear(); unparsedRhs.clear();
buildCFG();
}
set<SgStatement*> Loop::RDsAt(SgStatement* stmt) const
{
if (blockIn.find(stmt) == blockIn.end() || !(0 <= blockIn.at(stmt) && blockIn.at(stmt) < blocks.size()))
{
return set<SgStatement*>();
}
return blocks[blockIn.at(stmt)].INrd;
}
set<SgStatement*> Loop::AEsAt(SgStatement* stmt) const
{
if (blockIn.find(stmt) == blockIn.end() || !(0 <= blockIn.at(stmt) && blockIn.at(stmt) < blocks.size()))
{
return set<SgStatement*>();
}
return blocks[blockIn.at(stmt)].INae;
}
void Loop::setupSubstitutes()
{
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
set<SgStatement*> ss;
intersection(block->INrd.begin(), block->INrd.end(), block->INae.begin(), block->INae.end(), inserter(ss, ss.end()));
block->OUTae.clear();
block->OUTrd.clear();
for (set<SgStatement*>::iterator it = ss.begin(); it != ss.end();)
{
if (FindInExpr((*it)->expr(0), (*it)->expr(1)) != 0)
ss.erase(it++);
else
++it;
}
map<SgExpression*, SgStatement*> parent;
map<SgExpression*, set<SgExpression*> > INss;
for (set<SgStatement*>::iterator it = ss.begin(); it != ss.end(); ++it)
{
SgExpression* expr0 = lhs[unparsedLhs[(*it)->expr(0)]];
SgExpression* expr1 = rhs[unparsedRhs[(*it)->expr(1)]];
INss[expr0].insert(expr1);
parent[expr0] = *it;
parent[expr1] = *it;
}
for (map<SgExpression*, set<SgExpression*> >::iterator it1 = INss.begin(); it1 != INss.end(); ++it1)
{
for (set<SgExpression*>::iterator it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
{
SgExpression* rhs = (*it2)->copyPtr();
block->INss[it1->first].insert(rhs);
parent[rhs] = parent[*it2];
}
}
for (map<SgExpression*, set<SgExpression*> >::iterator it1 = block->INss.begin(); it1 != block->INss.end(); ++it1)
{
if (it1->second.size() != 1 || FindInExpr(it1->first, block->head->expr(1)) == 0)
continue;
bool changed = true;
SgExpression* expr = *it1->second.begin();
SgStatement* stmt = parent[it1->first];
while (changed == true)
{
changed = false;
for (map<SgExpression*, set<SgExpression*> >::iterator it3 = block->INss.begin(); it3 != block->INss.end(); ++it3)
if (it3->second.size() == 1 && it1->first != it3->first)
changed |= replace(expr, stmt, it3->first, *it3->second.begin()) != 0;
}
}
}
if (enable_opt == true)
{
for (vector<BasicBlock>::iterator block = blocks.begin() + 2; block != blocks.end(); ++block)
{
for (map<SgExpression*, set<SgExpression*> >::iterator it = block->INss.begin(); it != block->INss.end(); ++it)
{
if (it->second.size() == 1)
{
if (block->head->variant() == ASSIGN_STAT)
{
replaceInSubscripts(block->head->expr(0), block->head, it->first, *it->second.begin());
replaceInSubscripts(block->head->expr(1), block->head, it->first, *it->second.begin());
}
else if (block->head->variant() == PROC_CALL)
replaceInSubscripts(block->head->expr(0), block->head, it->first, *it->second.begin());
}
}
}
}
vector<bool> visited(blocks.size(), false);
visited[ENTRY] = true;
visited[EXIT] = true;
visited[2] = true;
vector<int> _blocks;
map<int, int> dfn;
dfn[ENTRY] = 0;
dfn[EXIT] = 1;
_blocks.push_back(2);
int k = 0;
int count = 2;
for (vector<int>::iterator p = _blocks.begin(); p != _blocks.end(); ++k, p = _blocks.begin() + k)
{
int index = *p;
visited[index] = true;
for (vector<int>::iterator it = blocks[index].out.begin(); it != blocks[index].out.end(); ++it)
{
if (visited[*it] == false)
{
visited[*it] = true;
_blocks.push_back(*it);
}
}
dfn[index] = count;
count++;
}
vector<BasicBlock> tmp(blocks.size());
for (vector<BasicBlock>::iterator block = blocks.begin(); block != blocks.end(); ++block)
{
block->index = dfn[block->index];
for (vector<int>::iterator it = block->out.begin(); it != block->out.end(); ++it)
*it = dfn[*it];
for (vector<int>::iterator it = block->in.begin(); it != block->in.end(); ++it)
*it = dfn[*it];
tmp[block->index] = *block;
}
blocks.swap(tmp);
}
// graphviz script, for debug
void Loop::visualize(const char* scriptName) const
{
FILE* f = fopen(scriptName, "w");
if (f == NULL)
{
printf("Failed to open file \"%s\"\n", scriptName);
return;
}
fprintf(f, "digraph\n{\n0[label=\"{Entry|<out>}\",shape=record]\n1[label=\"{<in>Exit|}\",shape=record]\n");
for (size_t i = 2; i < blocks.size(); ++i)
{
fprintf(f, "%d[label=\"{<in>B%d|<out>", blocks[i].index, blocks[i].index);
for (SgStatement* stmt = blocks[i].head; stmt != NULL && stmt != blocks[i].tail->lexNext(); stmt = stmt->lexNext())
{
switch (stmt->variant())
{
case SWITCH_NODE:
if (stmt->label())
fprintf(f, "%ld ", LABEL_STMTNO(stmt->label()->thelabel));
fprintf(f, "select case (%s)\\n", ((SgSwitchStmt*)stmt)->expr(0)->unparse());
break;
case IF_NODE:
if (stmt->label())
fprintf(f, "%ld ", LABEL_STMTNO(stmt->label()->thelabel));
fprintf(f, "if (%s) then\\n", ((SgIfStmt*)stmt)->conditional()->unparse());
break;
case ELSEIF_NODE:
fprintf(f, "elseif (%s) then\\n", ((SgIfStmt*)stmt)->conditional()->unparse());
break;
case LOGIF_NODE:
if (stmt->label())
fprintf(f, "%ld ", LABEL_STMTNO(stmt->label()->thelabel));
fprintf(f, "if (%s)\\n", ((SgLogIfStmt*)stmt)->conditional()->unparse());
break;
case WHILE_NODE:
{
SgForStmt* _stmt = (SgForStmt*)stmt;
if (_stmt->hasLabel() == TRUE)
fprintf(f, "%ld ", LABEL_STMTNO(_stmt->label()->thelabel));
if (LlndMapping(BIF_LL3(_stmt->thebif)) != NULL)
fprintf(f, "%s: ", LlndMapping(BIF_LL3(_stmt->thebif))->unparse());
fprintf(f, "do ");
if (BIF_LABEL_USE(_stmt->thebif) != NULL)
fprintf(f, "%ld ", LABEL_STMTNO(BIF_LABEL_USE(_stmt->thebif)));
fprintf(f, "while ");
if (((SgWhileStmt*)stmt)->conditional() != NULL)
fprintf(f, "(%s)\\n", ((SgWhileStmt*)stmt)->conditional()->unparse());
break;
}
case FOR_NODE:
{
SgForStmt* _stmt = (SgForStmt*)stmt;
if (_stmt->hasLabel() == TRUE)
fprintf(f, "%ld ", LABEL_STMTNO(_stmt->label()->thelabel));
if (LlndMapping(BIF_LL3(_stmt->thebif)) != NULL)
fprintf(f, "%s: ", LlndMapping(BIF_LL3(_stmt->thebif))->unparse());
fprintf(f, "do ");
if (BIF_LABEL_USE(_stmt->thebif) != NULL)
fprintf(f, "%ld ", LABEL_STMTNO(BIF_LABEL_USE(_stmt->thebif)));
#if __SPF
if (_stmt->doName()->identifier() != NULL)
fprintf(f, "%s = ", _stmt->doName()->identifier());
#else
if (_stmt->doName().identifier() != NULL)
fprintf(f, "%s = ", _stmt->doName().identifier());
#endif
if (_stmt->start() != NULL)
fprintf(f, "%s, ", _stmt->start()->unparse());
if (_stmt->end() != NULL)
fprintf(f, "%s", _stmt->end()->unparse());
if (_stmt->step() != NULL)
fprintf(f, ", %s\\n", _stmt->step()->unparse());
break;
}
default:
fprintf(f, "%s\\n", stmt->unparse());
break;
}
}
fprintf(f, "}\",shape=record]\n");
}
for (size_t i = 0; i < blocks.size(); ++i)
{
for (size_t j = 0; j < blocks[i].out.size(); ++j)
fprintf(f, "%d:out->%d:in\n", blocks[i].index, blocks[i].out[j]);
}
fprintf(f, "}");
fclose(f);
}
extern SgStatement* kernelScope;
SgExpression* analyzeArrayIndxs(SgSymbol* ar, SgExpression* subscripts)
{
static int count = 0;
SgSymbol* varName = NULL;
if (subscripts == NULL || options.isOn(AUTO_TFM) == false || dontGenConvertXY || oneCase)
return NULL;
map<SgSymbol*, Array*>& arrays = currentLoop->getArrays();
Array* array = NULL;
string toFind = OriginalSymbol(ar)->identifier();
for (map<SgSymbol*, Array*>::iterator it = arrays.begin(); it != arrays.end(); it++)
{
if (OriginalSymbol(it->first)->identifier() == toFind)
{
array = it->second;
break;
}
}
if (array != NULL)
{
string expr;
SgSymbol* symbol = array->findAccess(subscripts, expr);
if (symbol == NULL)
{
char* counter = new char[32];
sprintf(counter, "%d", count);
++count;
string name(ar->identifier() + string("_") + counter);
delete[] counter;
if (options.isOn(C_CUDA))
varName = new SgSymbol(VARIABLE_NAME, TestAndCorrectName(name.c_str()), *C_DvmType(), *kernelScope);
else
{
if (undefined_Tcuda)
varName = new SgSymbol(VARIABLE_NAME, TestAndCorrectName(name.c_str()), *new SgType(T_INT, new SgExpression(LEN_OP, new SgValueExp(8), NULL, NULL), SgTypeInt()), *kernelScope);
else
varName = new SgSymbol(VARIABLE_NAME, TestAndCorrectName(name.c_str()), *SgTypeInt(), *kernelScope);
}
array->addCoefficient(subscripts, expr, varName);
}
else
varName = symbol;
}
return varName ? new SgVarRefExp(varName) : NULL;
}