AstNodePtr ArrayInterface:: impl_access_array_length( CPPAstInterface& fa, const AstNodePtr& array, int dim, int plus) { SymbolicVal rval; ArrayOptDescriptor desc; if (get_array_opt(fa, array, desc)) { if (!desc.get_length(dim, rval)) assert(false); } else { ArrayDefineDescriptor desc1; if (!ArrayAnnotation::get_inst()->known_array( fa, array, &desc1)) return AST_NULL; if (! desc1.get_length(dim, rval)) assert(false); } ReplaceVal(rval, SymbolicVar("this",AST_NULL), SymbolicAstWrap(array)); if (plus != 0) rval = rval + plus; return rval.CodeGen(fa); }
SymbolicVal Min( const SymbolicVal &v1, const SymbolicVal &v2, MapObject<SymbolicVal, SymbolicBound>* f) { if (v1.IsNIL()) return v2; if (v2.IsNIL()) return v1; switch (CompareVal(v1,v2,f)) { case REL_NONE: case REL_UNKNOWN: case REL_NE: { SelectApplicator minOp(-1); return ApplyBinOP(minOp,v1,v2); } case REL_EQ: case REL_LT: case REL_LE: return v1; case REL_GT: case REL_GE: return v2; default: assert(0); } }
AstNodePtr SymbolicFunction :: CodeGen( AstInterface &_fa) const { AstInterface::AstNodeList l; for (const_iterator i = args.begin(); i != args.end(); ++i) { SymbolicVal cur = *i; AstNodePtr curast = cur.CodeGen(_fa); l.push_back(curast); } if (t == AstInterface::OP_NONE) { return _fa.CreateFunctionCall( op, l); } else if (t == AstInterface::OP_ARRAY_ACCESS) { AstNodePtr arr = l.front(); l.pop_front(); return _fa.CreateArrayAccess(arr, l); } else if (t == AstInterface::OP_ASSIGN && l.size() == 2) { return _fa.CreateAssignment(l.front(), l.back()); } else if (l.size() == 2) return _fa.CreateBinaryOP( t, l.front(), l.back()); else { assert(l.size() == 1); return _fa.CreateUnaryOP( t, l.front()); } }
CompareRel CompareVal(const SymbolicVal &v1, const SymbolicVal &v2, MapObject<SymbolicVal,SymbolicBound>* f) { if ( v1.IsNIL() && v2.IsNIL()) return REL_UNKNOWN; if (DebugCompareVal()) std::cerr << "comparing " << v1.toString() << " with " << v2.toString() << " under " << f << std::endl; comparetime = 0; return CompareValHelp(v1,v2,f); }
CompareRel CompareValHelp(const SymbolicVal &v1, const SymbolicVal &v2, MapObject<SymbolicVal,SymbolicBound>* f) { CompareRel r = REL_UNKNOWN; if (++comparetime < COMPARE_MAX) r = ValCompare(f)(v1,v2); if (DebugCompareVal()) std::cerr << v1.toString() << RelToString(r) << v2.toString() << " under " << f << std::endl; return r; }
virtual SymbolicVal operator()( const SymbolicVal& v) { SymbolicVal r; if (valmap != 0) r = (*valmap)(v); if (r.IsNIL()) { v.Visit(this); } return r; }
void Default1( const SymbolicVal &v1, const SymbolicVal &v2) { if (v1.IsSame(v2)) result = REL_EQ; else if (v1.IsNIL() || v2.IsNIL()) result = REL_UNKNOWN; else if (v1 == v2) result = REL_EQ; else result = REL_UNKNOWN; }
void VisitFunction( const SymbolicFunction &v) { if (target.GetValType() == VAL_FUNCTION && cur == target) result = true; else { for (SymbolicFunction::const_iterator p = v.args_begin(); p != v.args_end(); ++p) { SymbolicVal tmp = *p; cur = tmp; cur.Visit(this); if ( result) break; } } }
void VisitExpr( const SymbolicExpr &v) { if (target.GetValType() == VAL_EXPR && cur == target) result = true; else { for (SymbolicExpr::OpdIterator iter = v.GetOpdIterator(); !iter.ReachEnd(); iter.Advance()) { SymbolicVal tmp = v.Term2Val(iter.Current()); cur = tmp; cur.Visit(this); if (result) break; } } }
bool operator ()( const SymbolicVal &v, const SymbolicVal& _target) { target = _target; cur = v; result = false; v.Visit(this); return result; }
void Default0() { if (index == 1) { index = 2; v2.Visit(this); } else { CompareOperator::Default0(v1,v2); } }
bool operator()(const SymbolicVal& v, SymbolicVal* i, SymbolicVal* f) { inp = i; frp = f; if (inp != 0) *inp = 0; if (frp != 0) *frp = 0; hasfrac = false; v.Visit(this); return hasfrac; }
bool ArrayInterface :: GetArrayBound( AstInterface& _fa, const AstNodePtr& array, int dim, int &lb, int &ub) { CPPAstInterface& fa = static_cast<CPPAstInterface&>(_fa); SymbolicFunctionDeclarationGroup len; if (!is_array_exp( fa, array, 0, &len)) assert(false); std::vector<SymbolicVal> pars; pars.push_back( SymbolicConst(dim)); SymbolicVal rval; if (!len.get_val( pars, rval)) return false; if (!rval.isConstInt(ub)) return false; lb = 0; return true; }
bool SplitEquation( CoeffVec& cur, const SymbolicVal& cut, const BoundVec& bounds, BoundOp& boundop, CoeffVec& split) { int dim = cur.size()-1; SymbolicVal leftval = cur[dim]; // obtain the last coefficient, which is right side terms without using loop index variable if (leftval != 0) { CompareRel r1 = CompareVal(leftval,-cut, &boundop); CompareRel r2 = CompareVal(leftval,cut, &boundop); bool lt = ((r1 & REL_GT) && (r2 & REL_LT)) || ((r1 & REL_LT) && (r2 & REL_GT)); if (!lt) { // relation of r1 and r2 must be reversed pair, or error if (DebugDep()) std::cerr << "unable to split because " << leftval.toString() << " ? " << cut.toString() << std::endl; return false; } } bool succ = false; split.clear(); int j =0; for (; j < dim; ++j) { SymbolicVal left = cur[j] / cut; if (HasFraction(left)) split.push_back(0); else { split.push_back(left); succ = true; } } split.push_back(0); // right-hand side value if (succ) { SymbolicVal left = 0; for (j = 0; j < dim; ++j) { if (split[j]== 0) switch (CompareVal(cur[j],0,&boundop)) { case REL_LE: left = left + cur[j] * bounds[j].lb; break; case REL_GE: left = left + cur[j] * bounds[j].ub; break; default: break; } } if (j == dim && (left == 0 || (CompareVal(left,cut) & REL_LT))) { for (j = 0; j < dim; ++j) { if (split[j] != 0) cur[j] = 0; // clear some coefficency values } return true; } else if (DebugDep()) { if (j == dim) std::cerr << "unable to decide left " << left.toString() << " ? " << cut.toString() << std::endl; else std::cerr << "unable to decide cur[" << j << "] ? 0\n"; } } split.clear(); return false; }
LoopTreeNode* LoopBlocking:: ApplyBlocking( const CompSliceDepGraphNode::FullNestInfo& nestInfo, LoopTreeDepComp& comp, DependenceHoisting &op, LoopTreeNode *&top) { const CompSliceNest& slices = *nestInfo.GetNest(); if (DebugLoop()) { std::cerr << "\n Blocking slices: " << slices.toString() << "\n"; } LoopTreeNode *head = 0; AstInterface& fa = LoopTransformInterface::getAstInterface(); for (int j = FirstIndex(); j >= 0; j = NextIndex(j)) { top = op.Transform( comp, slices[j], top); SymbolicVal b = BlockSize(j); if (DebugLoop()) { std::cerr << "\n after slice " << j << " : \n"; //top->DumpTree(); comp.DumpTree(); comp.DumpDep(); std::cerr << "\n blocking size for this loop is " << b.toString() << "\n"; } if (!(b == 1)) { LoopTreeNode *n = LoopTreeBlockLoop()( top, SymbolicVar(fa.NewVar(fa.GetType("int")), AST_NULL), b); if (DebugLoop()) { std::cerr << "\n after tiling loop with size " << b.toString() << " : \n"; //top->DumpTree(); comp.DumpTree(); comp.DumpDep(); } if (head == 0) head = n; else { while (n->FirstChild() != head) LoopTreeSwapNodePos()( n->Parent(), n); } } } return head; }
static SymbolicVal GetDefaultBlockSize(const CompSlice* slice) { AstInterface& fa = LoopTransformInterface::getAstInterface(); LoopTransformOptions* opt = LoopTransformOptions::GetInstance(); if (!opt->DoDynamicTuning()) { return opt->GetDefaultBlockSize(); } else { int dt = opt->GetDynamicTuningIndex(); AstInterface::AstNodeList l; l.push_back(fa.CreateConstInt(dt)); CompSlice::ConstLoopIterator iter = slice->GetConstLoopIterator(); LoopTreeNode *loop = iter.Current(); SymbolicBound b = loop->GetLoopInfo()->GetBound(); SymbolicVal size = b.ub - b.lb + 1; l.push_back(fa.CreateConstInt(1)); l.push_back(size.CodeGen(fa)); AstNodePtr init = fa.CreateFunctionCall("getTuningValue", l); return SymbolicVar(fa.NewVar(fa.GetType("int"), "",true,AST_NULL, init),AST_NULL); } }
void Default0( const SymbolicVal &v1, const SymbolicVal &v2) { Default1(v1,v2); if (DebugCompareVal()) std::cerr << " in CompareOperator::Default \n"; if (result == REL_UNKNOWN) { int tmp = comparetime; SymbolicVal diff = v1 - v2; comparetime = tmp; if (diff.GetValType() == VAL_CONST) { int diffval = atoi( diff.toString().c_str()); if (diffval < 0) result = REL_LT; else if (diffval > 0) result = REL_GT; else result = REL_EQ; } else if (func != 0) { int tmp = comparetime; SymbolicBound b1 = GetValBound(v1,*func), b2 = GetValBound(v2,*func); comparetime = tmp; CompareRel ge1 = (b1.lb != v1)? CompareValHelp(b1.lb,v2,func) : REL_UNKNOWN; CompareRel le2 = (b2.ub != v2)? CompareValHelp(b2.ub,v1,func) : REL_UNKNOWN; CompareRel le1 = (b1.ub != v1)? CompareValHelp(b1.ub,v2,func) : REL_UNKNOWN; CompareRel ge2 = (b2.lb != v2)? CompareValHelp(b2.lb,v1,func) : REL_UNKNOWN; if (CountGT(ge1) || CountLT(le2)) result = REL_GT; else if (CountGE(ge1) || CountLE(le2)) result = REL_GE; else if (CountLT(le1) || CountGT(ge2)) result = REL_LT; else if (CountLE(le1) || CountGE(ge2)) result = REL_LE; } } }
SymbolicVal DecomposeAffineExpression( const SymbolicVal& exp, const VarVec& vars, CoeffVec& vec, int size) { // AstInterface& fa = la; SymbolicVal val = exp; // int coeff; for (int i = 0; i < size; ++i) { SymbolicVar ivar = vars[i]; SymbolicBound ivarbound; SymbolicVal coeff = UnwrapVarCond( SymbolicCond( REL_LE, val, 0), ivar, ivarbound); if (coeff.IsNIL()) return SymbolicVal(); if (!(coeff == 0)) { if (!ivarbound.ub.IsNIL()) val = -ivarbound.ub; else { val = ivarbound.lb; coeff = -coeff; } } vec.push_back(coeff); } return val; }
std::string HasValueCollection:: is_known_member_function( AstInterface& fa, const SymbolicVal& exp, AstNodePtr* objp, SymbolicFunction::Arguments* argsp , HasValueDescriptor* descp ) { std::string op1, op2; SymbolicFunction::Arguments arg1, arg2; if (!exp.isFunction(op1,&arg1)) return ""; if (op1 != "FunctionPtrCall" || !arg1.front().isFunction(op2,&arg2) || op2 != "." || arg2.size() != 2) return ""; AstNodePtr obj; if (!arg2.front().isAstWrap(obj) || !known_type(fa, obj, descp)) return ""; if (objp != 0) *objp = obj; if (argsp != 0) *argsp = arg1; return arg2.back().toString(); }
bool operator()(const SymbolicVal &_v1, const SymbolicVal &_v2) { result = false; v2 = _v2; _v1.Visit(this); return result; }
CompareRel operator() ( const SymbolicVal &_v2) { result = REL_UNKNOWN; v2 = _v2; v2.Visit(this); return result; }
SymbolicVal ApplyBinOP( SymOpType t, const SymbolicVal &v1, const SymbolicVal &v2) { SymbolicVal r; switch (t) { case SYMOP_PLUS: { PlusApplicator op; r = ApplyBinOP(op, v1, v2); if (DebugOp()) std::cerr << v1.toString() << " + " << v2.toString() << " = " << r.toString() << std::endl; return r; } case SYMOP_MULTIPLY: { MultiplyApplicator op; r = ApplyBinOP(op, v1, v2); if (DebugOp()) std::cerr << v1.toString() << " * " << v2.toString() << " = " << r.toString() << std::endl; return r; } case SYMOP_MIN: r = Min(v1,v2); if (DebugOp()) std::cerr << "Min( " << v1.toString() << " , " << v2.toString() << ") = " << r.toString() << std::endl; return r; case SYMOP_MAX: return Max(v1, v2); r = Max(v1,v2); if (DebugOp()) std::cerr << "Max( " << v1.toString() << " , " << v2.toString() << ") = " << r.toString() << std::endl; return r; case SYMOP_POW: { int val2; int vu1, vd1; if (!v2.isConstInt(val2)) assert(false); if (v1 == 1 || val2 == 1) r = v1; else if (val2 == -1 && v1.isConstInt(vu1, vd1)) r = new SymbolicConst(vd1, vu1); else r = new SymbolicPow(v1, val2); if (DebugOp()) std::cerr << "Pow( " << v1.toString() << " , " << v2.toString() << ") = " << r.toString() << std::endl; return r; } default: assert(false); } }
SymbolicVal HasValueMapReplace :: operator() ( const SymbolicVal& v) { repl = SymbolicVal(); v.Visit(this); return repl; }
CompareRel operator() ( const SymbolicVal& _v1, const SymbolicVal &_v2) { result = REL_UNKNOWN; v1= _v1; v2 = _v2; index = 1; v1.Visit(this); return result; }
bool LoopUnrolling::operator() ( AstInterface& fa, const AstNodePtr& s, AstNodePtr& r) { bool isLoop = false; if (enclosingloop == s || (enclosingloop == AST_NULL && (isLoop = fa.IsLoop(s)))) { for (enclosingloop = fa.GetParent(s); enclosingloop != AST_NULL && !fa.IsLoop(enclosingloop); enclosingloop = fa.GetParent(enclosingloop)); if (!isLoop) return false; } AstNodePtr body; SymbolicVal stepval, ubval, lbval; SymbolicVar ivar; if (!SymbolicValGenerator::IsFortranLoop(fa, s, &ivar, &lbval, &ubval, &stepval, &body)) return false; if (opt & POET_TUNING) { AutoTuningInterface* tune = LoopTransformInterface::getAutoTuningInterface(); if (tune == 0) { std::cerr << "ERROR: AutoTuning Interface not defined!\n"; assert(0); } tune->UnrollLoop(fa,s, unrollsize); } else { AstNodePtr r = s; SymbolicVal nstepval = stepval * unrollsize; SymbolicVal nubval = ubval; bool hasleft = true, negativeStep = (stepval < 0); std::vector<AstNodePtr> bodylist; AstNodePtr leftbody, lefthead; int stepnum=0, loopnum = 0; SymbolicVal loopval = ubval - lbval + 1; if (stepval.isConstInt(stepnum) && loopval.isConstInt(loopnum) && !(loopnum % stepnum)) { hasleft = false; } else { nubval = ubval - SymbolicVal(unrollsize - 1); if (opt & COND_LEFTOVER) { leftbody = fa.CreateBlock(); lefthead = leftbody; } else { leftbody = fa.CopyAstTree(body); lefthead = fa.CreateLoop( ivar.CodeGen(fa), AstNodePtr(), ubval.CodeGen(fa), stepval.CodeGen(fa), leftbody, negativeStep); } } fa.RemoveStmt(body); AstNodePtr s1 = fa.CreateLoop(ivar.CodeGen(fa), lbval.CodeGen(fa), nubval.CodeGen(fa), nstepval.CodeGen(fa), body, negativeStep); fa.ReplaceAst( s,s1); r = s1; AstNodePtr origbody = fa.CopyAstTree(body); std::string nvarname = ""; SymbolicVal nvar; if (opt & USE_NEWVAR) { nvarname = fa.NewVar(fa.GetType("int"),"",true,body, ivar.CodeGen(fa)); nvar = SymbolicVar(nvarname,body); } bodylist.push_back(body); for (int i = 1; i < unrollsize; ++i) { AstNodePtr bodycopy = fa.CopyAstTree(origbody); if (opt & USE_NEWVAR) { AstNodePtr nvarassign = fa.CreateAssignment(nvar.CodeGen(fa), (nvar+1).CodeGen(fa)); fa.BlockAppendStmt( body, nvarassign); AstTreeReplaceVar repl(ivar, nvar); repl( fa, bodycopy); } else { AstTreeReplaceVar repl(ivar, ivar+i); repl( fa, bodycopy); } fa.BlockAppendStmt( body, bodycopy); bodylist.push_back(bodycopy); if (hasleft && (opt & COND_LEFTOVER)) { AstNodePtr cond = fa.CreateBinaryOP( AstInterface::BOP_LE, ivar.CodeGen(fa), (ubval-(i-1)).CodeGen(fa)); AstNodePtr body1 = fa.CopyAstTree(bodylist[i-1]); AstNodePtr ifstmt = fa.CreateIf( cond, body1); fa.BlockAppendStmt( leftbody, ifstmt); leftbody = body1; } } if (hasleft) { fa.InsertStmt( r, lefthead, false, true); } r = s; return true; } return false; }
bool operator ()(SymbolicVal v) { result = false; v.Visit(this); return result; }
bool Equal(const SymbolicVal &v1, const SymbolicVal& v2) { return v1.IsSame(v2)? true : ValEQ()(v1,v2); }
bool AnalyzeEquation(const CoeffVec& vec, const BoundVec& bounds, BoundOp& boundop, Dep& result, const DepRel& rel) { int dim = vec.size()- 1; std::vector<int> signs; for (int index = 0; index < dim; ++index) { if (vec[index]==0) { signs.push_back(0); continue; } SymbolicBound cb = GetValBound(vec[index], boundop); assert(!cb.lb.IsNIL() && !cb.ub.IsNIL()); const SymbolicBound& b = bounds[index]; assert(!b.lb.IsNIL() && !b.ub.IsNIL()); if (b.lb >= 0) { if (cb.lb >= 0) signs.push_back(1); else if (cb.ub <= 0) signs.push_back(-1); else { if (DebugDep()) std::cerr << "unable to decide sign of coeff when lb >=0 for ivar[" << index << "]\n"; //return false; signs.push_back(2); } } else if (b.ub <= 0) { if (cb.lb >= 0) signs.push_back(-1); else if (cb.ub <= 0) signs.push_back(1); else { if (DebugDep()) std::cerr << "unable to decide sign of coeff when ub <=0 for ivar[" << index << "]\n"; //return false; signs.push_back(2); } } else { if (DebugDep()) std::cerr << "unable to decide sign of ivar[" << index << "]\n"; //return false; signs.push_back(2); } } if (vec[dim] == 0) signs.push_back(0); else { SymbolicVal leftval = vec[dim]; if (leftval.IsNIL()) { if (DebugDep()) std::cerr << "unable to decide sign of leftval\n"; return false; } SymbolicBound lb = GetValBound(vec[dim], boundop); if (lb.ub <= 0) signs.push_back(-1); else if (lb.lb >= 0) signs.push_back(1); else { if (DebugDep()) std::cerr << "unable to decide sign of leftval\n"; return false; //signs.push_back(2); } } for (int i = 0; i < dim ; ++i) { if (signs[i] == 0) continue; SymbolicVal coeff = vec[i]; assert(!coeff.IsNIL()); int j = 0; for ( j = i+1; j < dim; ++j) { if (signs[j] == 0 || coeff + vec[j] != 0) continue; int left = 0, k; for (k = 0; k < dim ; ++k) { if (k == i || k == j) continue; if (left == 0) left = signs[k]; else if (signs[k] == 2 || signs[k] * left < 0) break; } if ( k < dim || left == 2 || left * signs[dim] < 0) continue; int diff = 0, c = 1; bool hasdiff = false; if (left == 0 && vec[dim].isConstInt(diff) && (diff == 0 || coeff.isConstInt(c))) { if (diff != 0 && c != 1) { int odiff = diff; diff = diff / c; if (odiff != diff * c) { //DepStats.AddAdhocDV(DepStats.RoseToPlatoDV(DepRel(DEPDIR_NONE))); result[i][j] = DepRel(DEPDIR_NONE); return true; } } hasdiff = true; } if (hasdiff) { //DepStats.AddAdhocDV(DepStats.RoseToPlatoDV(DepRel(DEPDIR_EQ, diff))); result[i][j] = rel * DepRel(DEPDIR_EQ, diff); return true; // precise dependence } else if (signs[i] != 2) { if (signs[dim]* signs[i] > 0) { //DepStats.AddAdhocDV(DepStats.RoseToPlatoDV(DepRel(DEPDIR_GE, diff))); result[i][j] = rel * DepRel(DEPDIR_GE, diff); } else { //DepStats.AddAdhocDV(DepStats.RoseToPlatoDV(DepRel(DEPDIR_LE, diff))); result[i][j] = rel * DepRel(DEPDIR_LE, diff); } } } } return false; }
SymbolicVal ReplaceParams::operator()( const SymbolicVal& v) { cur = SymbolicVal(); v.Visit(this); return cur; }