bool SymbolicValGenerator:: IsFortranLoop(AstInterface& fa, const AstNodePtr& s, SymbolicVar* ivar , SymbolicVal* lb , SymbolicVal* ub, SymbolicVal* step, AstNodePtr* body) { AstNodePtr ivarast, lbast, ubast, stepast, ivarscope; if (!fa.IsFortranLoop(s, &ivarast, &lbast, &ubast, &stepast, body)) return false; std::string varname; if (! fa.IsVarRef(ivarast, 0, &varname, &ivarscope)) { return false; } if (ivar != 0) *ivar = SymbolicVar(varname, ivarscope); if (lb != 0) *lb = SymbolicValGenerator::GetSymbolicVal(fa,lbast); if (ub != 0) *ub = SymbolicValGenerator::GetSymbolicVal(fa,ubast); if (step != 0) { if (stepast != AST_NULL) *step = SymbolicValGenerator::GetSymbolicVal(fa,stepast); else *step = SymbolicVal(1); } return true; }
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); }
bool ArrayInterface:: get_array_opt(CPPAstInterface& fa, const AstNodePtr& array, ArrayOptDescriptor& r) { std::string name; if (!fa.IsVarRef(array, 0, &name)) return false; std::map <std::string, ArrayOptDescriptor>::const_iterator p = optmap.find(name); if (p != optmap.end()) { r = (*p).second; return true; } ArrayOptDescriptor desc; if (!ArrayAnnotation::get_inst()->has_array_opt( fa, array, &desc)) return false; for (ArrayOptDescriptor::InitVarIterator p = desc.init_var_begin(); p != desc.init_var_end(); ++p) { DefineVariableDescriptor& cur = *p; ExtendibleParamDescriptor &par = cur.get_var(); std::string parname = par.get_param_name(); par.get_param() = SymbolicVar( name + parname, AST_NULL); SymbolicVal newpar = new SymbolicVar(name + parname, AST_NULL); desc.replace_var(parname, newpar); } optmap[name] = desc; r = desc; return true; }
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; }
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; }
LoopTreeNode* LoopBlocking:: ApplyBlocking( const CompSliceDepGraphNode::FullNestInfo& nestInfo, LoopTreeDepComp& comp, DependenceHoisting &op, LoopTreeNode *&top) { const CompSliceNest& slices = *nestInfo.GetNest(); 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 (!(b == 1)) { LoopTreeNode *n = LoopTreeBlockLoop()( top, SymbolicVar(fa.NewVar(fa.GetType("int")), AST_NULL), b); 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); } }
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; }