bool LoopTransformInterface:: IsDynamicFusionConfig( const AstNodePtr& n, AstNodePtr* configvar, int* configID, AstInterface::AstNodeList* params) { assert(fa != 0); AstNodePtr invoc; if (!fa->IsAssignment(n, configvar, &invoc)) return false; AstInterface::AstNodeList args; std::string sig; AstNodePtr f; if (!fa->IsFunctionCall(invoc, &f, &args) || !fa->IsVarRef(f, 0, &sig) ) return false; if (sig == "DynamicFusionConfig") { if (configID != 0) { AstNodePtr idnode = args.front(); bool isconst = fa->IsConstInt( idnode, configID); assert(isconst); } if (params != 0) { *params = args; params->erase(params->begin()); params->erase(params->begin()); } return true; } return false; }
AstNodePtr LoopTransformInterface::CreateDynamicFusionEnd( int id) { assert(fa != 0); AstInterface::AstNodeList args; args.push_back( fa->CreateConstInt(id).get_ptr()); std::string funname = "DynamicFusionEnd"; return fa->CreateFunctionCall(funname, args.begin(), args.end()); }
CopyArrayConfig ComputeCopyConfig( const DepCompAstRefAnal& stmtorder, const DepCompCopyArrayCollect::CopyArrayUnit& unit, const DepCompAstRefGraphNode* initcut) { assert (unit.refs.size() > 0); AstInterface& ai = LoopTransformInterface::getAstInterface(); const DepCompAstRef& initInfo = initcut->GetInfo(); AstNodePtr lhs; bool is_init = ai.IsAssignment(initInfo.stmt->GetOrigStmt(), &lhs) && (lhs == initcut->GetInfo().orig); AstNodeType inittype; if (ai.IsExpression(initInfo.orig, &inittype)==AST_NULL) assert(false); bool has_write = false; AstNodePtr arr; std::string arrname, elemtypename; ai.GetTypeInfo(inittype, 0, &elemtypename); //QY: strip out ref info & AstNodeType elemtype = ai.GetType(elemtypename); AstInterface::AstNodeList initIndex; if (!LoopTransformInterface::IsArrayAccess(initInfo.orig, &arr, &initIndex) || !ai.IsVarRef(arr,0,&arrname)) assert(false); SelectArray cursel(elemtype, arrname, initIndex.size()); cursel.select(initInfo.stmt, unit.root, initIndex); for (DepCompCopyArrayCollect::CopyArrayUnit::NodeSet::const_iterator p = unit.refs.begin(); !p.ReachEnd(); ++p) { const DepCompAstRefGraphNode* curref = *p; const DepCompAstRef& curinfo = curref->GetInfo(); if (stmtorder.is_mod_ref(curinfo.orig)) has_write = true; AstInterface::AstNodeList curIndex; if (!LoopTransformInterface::IsArrayAccess(curinfo.orig, 0, &curIndex)) assert(false); if (cursel.select(curinfo.stmt, unit.root, curIndex)) is_init = false; } cursel.set_bufsize(ai); LoopTreeNode* shift = 0; if (unit.carrybyroot) shift = unit.root; int copyopt = 0; if (!is_init) copyopt |= INIT_COPY; if (has_write) copyopt |= SAVE_COPY; CopyArrayOpt opt = (CopyArrayOpt)copyopt; CopyArrayConfig curconfig(ai, cursel, opt, shift); return curconfig; }
AstNodePtr LoopTransformInterface:: CreateDynamicFusionConfig( const AstNodePtr& groupNum, AstInterface::AstNodeList& args, int &id) { assert(fa != 0); std::string name = "DynamicFusionConfig"; ++configIndex; args.push_front( fa->CreateConstInt( args.size() ) ); args.push_front( fa->CreateConstInt(configIndex) ); AstNodePtr invoc = fa->CreateFunctionCall( "DynamicFusionConfig", args); return fa->CreateAssignment ( groupNum, invoc) ; }
AstNodePtr LoopTransformInterface:: CreateDynamicFusionConfig( const AstNodePtr& groupNum, AstInterface::AstNodeList& args, int &id) { assert(fa != 0); std::string name = "DynamicFusionConfig"; ++configIndex; args.push_back( fa->CreateConstInt(configIndex).get_ptr() ); args.push_back( fa->CreateConstInt( args.size() ).get_ptr() ); std::string funname = "DynamicFusionConfig"; AstNodePtr invoc = fa->CreateFunctionCall( funname, args.begin(), args.end()); return fa->CreateAssignment ( groupNum, invoc) ; }
AstNodePtr ArrayUseAccessFunction:: CreateArrayAccess( AstInterface& fa, const AstNodePtr& arr, AstInterface::AstNodeList& index) { if (prev != 0) return prev->CreateArrayAccess(fa, arr, index); if (index.size() > 1) { AstInterface::AstNodeList tmp = index; tmp.push_front(arr); return fa.CreateFunctionCall(funcname, tmp); } else return fa.CreateArrayAccess(arr, index); }
AstNodePtr SymbolicSelect:: CodeGen( AstInterface &fa ) const { int size = 0; AstInterface::AstNodeList list; for (OpdIterator iter = GetOpdIterator(); !iter.ReachEnd(); iter.Advance()) { AstNodePtr p = Term2Val(iter.Current()).CodeGen(fa); list.push_back(p); ++size; } assert( size > 1); std::string func = (opt< 0)? "min" : "max"; return fa.CreateFunctionCall(func, list); }
ReplaceParams:: ReplaceParams ( const ParamDescriptor& decl, AstInterface::AstNodeList& args, Map2Object<AstInterface*,AstNodePtr,AstNodePtr>* codegen) { assert(decl.size() == args.size()); int index = 0; for (AstInterface::AstNodeList::iterator p1 = args.begin(); p1 != args.end(); ++p1, ++index) { AstNodePtr curAst = *p1; string curpar = decl[index]; SymbolicAstWrap curarg(curAst, codegen); parmap[curpar] = curarg; } }
AstNodePtr ArrayInterface:: impl_access_array_elem (CPPAstInterface& fa, const AstNodePtr& array, const AstInterface::AstNodeList& ivarAst) { SymbolicFunctionDeclarationGroup elem; ArrayOptDescriptor desc; if (get_array_opt(fa, array, desc)) { elem = desc.get_elem(); } else { ArrayDefineDescriptor desc1; if (!ArrayAnnotation::get_inst()->known_array( fa, array, &desc1)) assert(false); elem = desc1.get_elem(); } elem.replace_var("this", SymbolicAstWrap(array)); elem.replace_var( "dimension", ivarAst.size()); AstNodePtr r; if (! elem.get_val(fa, ivarAst, r)) assert(false); return r; }
AstNodePtr LoopTransformInterface:: CreateArrayAccess(const std::string& arrname, const std::vector<SymbolicVal>& arrindex) { assert(fa != 0); AstInterface::AstNodeList indexlist; for (std::vector<SymbolicVal>::const_iterator indexp = arrindex.begin(); indexp != arrindex.end(); ++indexp) { AstNodePtr cur = (*indexp).CodeGen(*fa); if (cur == AST_NULL) { std::cerr << "Empty AST from Symbolic Val: " << (*indexp).toString() << "\n"; assert(0); } indexlist.push_back(cur); } AstNodePtr res = CreateArrayAccess(fa->CreateVarRef(arrname),indexlist); return res; }
LoopTreeNode* DynamicSlicing:: Transform( LoopTreeDepComp& c, const CompSlice *_slice, LoopTreeNode *root) { AstInterface& fa = LoopTransformInterface::getAstInterface(); const DynamicCompSlice* slice = static_cast<const DynamicCompSlice*>(_slice); int num = slice->QuerySliceGroupNumber(); LoopTreeNode *nr = root; if (num > 1) { std::string groupVar = fa.NewVar(fa.GetType("int")), groupVarN = groupVar + "N"; fa.NewVar( fa.GetType("int"), groupVarN); LoopTreeCreate *tc = c.GetLoopTreeCreate(); nr = tc->CreateLoopNode( SymbolicVar(groupVar, AST_NULL), 1, SymbolicVar(groupVarN, AST_NULL), 1); LoopTreeTransform().InsertLoop( nr, root, -1); AstInterface::AstNodeList args; char buf[11]; for (int i = 1; i <= num; ++i) { sprintf(buf, "%1d", i); std::string name = groupVar + buf; fa.NewVar(fa.GetType("int"), name); args.push_back( fa.CreateVarRef( name) ); } int id; AstNodePtr config = LoopTransformInterface::CreateDynamicFusionConfig( fa.CreateVarRef(groupVarN), args, id); LoopTreeNode *configNode = tc->CreateStmtNode(config); configNode->Link( nr, LoopTreeNode::AsPrevSibling); AstNodePtr configEnd = LoopTransformInterface::CreateDynamicFusionEnd( id); LoopTreeNode *endNode = tc->CreateStmtNode(configEnd); endNode->Link( nr, LoopTreeNode::AsNextSibling); for (CompSlice::ConstStmtIterator p = slice->GetConstStmtIterator(); !p.ReachEnd(); ++p) { LoopTreeNode* stmt = p.Current(); sprintf(buf, "%1d", slice->QuerySliceStmtGroupIndex(stmt)); LoopTreeEmbedStmt()( nr, stmt, SymbolicVar(groupVar + buf, AST_NULL) ); } DependenceHoisting::Transform(c, slice, root); } else nr = DependenceHoisting::Transform(c, slice, root); return nr; }
bool ArrayUseAccessFunction::get_read(AstInterface& fa, const AstNodePtr& fc, CollectObject<AstNodePtr>* collect) { AstInterface::AstNodeList args; if (prev1 != 0 && prev1->get_read(fa, fc, collect)) return true; std::string sig; AstNodePtr f; if (fa.IsFunctionCall(fc, &f,&args) && fa.IsVarRef(f,0,&sig) && sig == funcname) { if (collect != 0) { AstInterface::AstNodeList::const_iterator argp = args.begin(); for ( ++argp; argp != args.end(); ++argp) { (*collect)(*argp); } } return true; } return false; }
bool ArrayUseAccessFunction:: IsArrayAccess( AstInterface& fa, const AstNodePtr& s, AstNodePtr* array, AstInterface::AstNodeList* index) { AstInterface::AstNodeList args; if (prev != 0 && prev->IsArrayAccess(fa, s, array, index)) return true; std::string sig; AstNodePtr f; if (fa.IsFunctionCall(s, &f,&args) && fa.IsVarRef(f,0,&sig) && sig == funcname) { AstInterface::AstNodeList::const_iterator p = args.begin(); if (array != 0) *array = *p; if (index != 0) { for (++p; p != args.end(); ++p) { index->push_back(*p); } } return true; } return false; }
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); } }
AstNodePtr ArrayInterface:: impl_reshape_array( CPPAstInterface& fa, const AstNodePtr& array, AstInterface::AstNodeList& ivarAst) { ArrayDefineDescriptor desc; if (!ArrayAnnotation::get_inst()->known_array( fa, array, &desc)) return AST_NULL; SymbolicFunctionDeclarationGroup reshape = desc.get_reshape(); reshape.replace_var( "this", SymbolicAstWrap(array)); reshape.replace_var( "dimension", ivarAst.size()); AstNodePtr r; if (!reshape.get_val( fa, ivarAst, r)) { std::cerr << "Error: cannot extract value from reshape spec: \n"; reshape.write(std::cerr); std::cerr << std::endl; assert(false); } return r; }
SymbolicVal SymbolicValGenerator :: GetSymbolicVal( AstInterface &fa, const AstNodePtr& exp) { std::string name; AstNodePtr scope; int val = 0; AstNodePtr s1, s2; AstInterface::AstNodeList l; AstInterface::OperatorEnum opr = (AstInterface::OperatorEnum)0; if (fa.IsVarRef(exp, 0, &name, &scope)) { return new SymbolicVar( name, scope ); } else if (fa.IsConstInt(exp, &val)) { return new SymbolicConst( val ); } else if (fa.IsBinaryOp(exp, &opr, &s1, &s2)) { SymbolicVal v1 = GetSymbolicVal( fa, s1 ), v2 = GetSymbolicVal(fa, s2); switch (opr) { case AstInterface::BOP_TIMES: return v1 * v2; case AstInterface::BOP_PLUS: return v1 + v2; case AstInterface::BOP_MINUS: return v1 - v2; case AstInterface::BOP_DOT_ACCESS: case AstInterface::BOP_ARROW_ACCESS: case AstInterface::BOP_DIVIDE: return new SymbolicFunction( opr, "/", v1,v2); case AstInterface::BOP_EQ: return new SymbolicFunction( opr, "==", v1,v2); case AstInterface::BOP_LE: return new SymbolicFunction( opr, "<=", v1,v2); case AstInterface::BOP_LT: return new SymbolicFunction( opr, "<", v1,v2); case AstInterface::BOP_NE: return new SymbolicFunction( opr, "!=", v1,v2); case AstInterface::BOP_GT: return new SymbolicFunction( opr, ">", v1,v2); case AstInterface::BOP_GE: return new SymbolicFunction( opr, ">=", v1,v2); case AstInterface::BOP_AND: return new SymbolicFunction( opr, "&&", v1,v2); case AstInterface::BOP_OR: return new SymbolicFunction( opr, "||", v1,v2); default: assert(false); } } else if (fa.IsUnaryOp(exp, &opr, &s1)) { SymbolicVal v = GetSymbolicVal( fa, s1); switch (opr) { case AstInterface::UOP_MINUS: return (-1) * v; case AstInterface::UOP_ADDR: return new SymbolicFunction( opr, "&", v); case AstInterface::UOP_DEREF: return new SymbolicFunction( opr, "*", v); case AstInterface::UOP_ALLOCATE: return new SymbolicFunction( opr, "new", v); case AstInterface::UOP_NOT: return new SymbolicFunction( opr, "!", v); case AstInterface::UOP_CAST: return new SymbolicFunction( opr, "cast", v); case AstInterface::UOP_DECR1: return new SymbolicFunction( opr, "--", v); case AstInterface::UOP_INCR1: return new SymbolicFunction( opr, "++", v); default: std::cerr << "Cannot handle " << AstToString(exp) << ":" << opr << "\n"; assert(false); } } else if (fa.IsFunctionCall(exp, &s1, &l)) { bool ismin = fa.IsMin(s1), ismax = fa.IsMax(s1); AstInterface::AstNodeList::const_iterator p = l.begin(); if (ismin || ismax) { AstNodePtr s = *p; SymbolicVal v = GetSymbolicVal( fa, s ); for ( ++p; p != l.end(); ++p ) { s = *p; v = (ismin)? Min(v, GetSymbolicVal(fa, s)) : Max(v, GetSymbolicVal(fa, s)); } return v; } if (fa.IsVarRef(exp, 0, &name)) { SymbolicFunction::Arguments args; for ( ; p != l.end(); ++p) { SymbolicVal cur = GetSymbolicVal(fa, *p); args.push_back( cur ); } return new SymbolicFunction( AstInterface::OP_NONE, name, args); } } return new SymbolicAstWrap(exp); }
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()); } }
bool ArrayInterface :: may_alias(AstInterface& _fa, const AstNodePtr& r1, const AstNodePtr& r2) { CPPAstInterface& fa = static_cast<CPPAstInterface&>(_fa); AstNodePtr array1, array2; ArrayAnnotation* annot = ArrayAnnotation::get_inst(); bool elem1 = annot->is_access_array_elem( fa, r1, &array1) ; bool len1 = annot->is_access_array_length( fa, r1, &array1); bool elem2 = annot->is_access_array_elem( fa, r2, &array2); bool len2 = annot->is_access_array_length( fa, r2, &array2); if ( (elem1 && len2) || (len1 && elem2)) { return false; } else if ( (elem1 && elem2) || (len1 && len2)) { if (may_alias(fa, array1, array2)) { if (DebugAliasAnal()) std::cerr << "has alias between " << AstInterface::AstToString(r1) << " and " << AstInterface::AstToString(r2) << std::endl; return true; } } else if (elem1 || len1) { if (may_alias(fa, array1, r2)) { if (DebugAliasAnal()) std::cerr << "has alias between " << AstInterface::AstToString(r1) << " and " << AstInterface::AstToString(r2) << std::endl; return true; } } else if (elem2 || len2) { if (may_alias(fa, r1, array2)) { if (DebugAliasAnal()) std::cerr << "has alias between " << AstInterface::AstToString(r1) << " and " << AstInterface::AstToString(r2) << std::endl; return true; } } else { AstInterface::AstNodeList args; if (annot->is_array_construct_op( fa, r1, &args)) { for (AstInterface::AstNodeList::iterator p = args.begin(); p != args.end(); ++p) { AstNodePtr cur = *p; if (may_alias( fa, cur, r2)) { if (DebugAliasAnal()) std::cerr << "has alias between " << AstInterface::AstToString(r1) << " and " << AstInterface::AstToString(r2) << std::endl; return true; } } return false; } else if (annot->is_array_construct_op( fa, r2, &args)) { for (AstInterface::AstNodeList::iterator p = args.begin(); p != args.end(); ++p) { AstNodePtr cur = *p; if (may_alias( fa, cur, r1)) { if (DebugAliasAnal()) std::cerr << "has alias between " << AstInterface::AstToString(r1) << " and " << AstInterface::AstToString(r2) << std::endl; return true; } } return false; } return aliasCollect.may_alias( fa, r1, r2); } return false; }
AstNodePtr LoopTransformInterface::CreateDynamicFusionEnd( int id) { assert(fa != 0); AstInterface::AstNodeList args; args.push_back( fa->CreateConstInt(id)); return fa->CreateFunctionCall("DynamicFusionEnd", args); }