2234 lines
89 KiB
C++
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;
|
|
}
|