bool Interchange::runOnScop(Scop &S) { if (std::distance(S.begin(), S.end()) != 2) // One statement besides the final statement return false; for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; if (!Stmt->isReduction()) continue; isl_map *Scattering = isl_map_copy(Stmt->getScattering()); const std::string MapString = "{scattering[i0, i1, i2, i3, i4] -> scattering[i0, i3, i2, i1, i4]}"; isl_map *Map = isl_map_read_from_str(Stmt->getIslContext(), MapString.c_str(), -1); isl_map_add_dims(Map, isl_dim_param, Stmt->getNumParams()); Scattering = isl_map_apply_range(Scattering, Map); Stmt->setScattering(Scattering); DEBUG( isl_printer *p = isl_printer_to_str(S.getCtx()); isl_printer_print_map(p, Scattering); dbgs() << isl_printer_get_str(p) << '\n'; isl_printer_flush(p); isl_printer_free(p); ); }
bool JSONExporter::runOnScop(Scop &S) { std::string FileName = ImportDir + "/" + getFileName(S); Json::Value jscop = getJSON(S); Json::StyledWriter writer; std::string fileContent = writer.write(jscop); // Write to file. std::error_code EC; tool_output_file F(FileName, EC, llvm::sys::fs::F_Text); std::string FunctionName = S.getFunction().getName(); errs() << "Writing JScop '" << S.getNameStr() << "' in function '" << FunctionName << "' to '" << FileName << "'.\n"; if (!EC) { F.os() << fileContent; F.os().close(); if (!F.os().has_error()) { errs() << "\n"; F.keep(); return false; } } errs() << " error opening file for writing!\n"; F.os().clear_error(); return false; }
void Dependences::collectInfo(Scop &S, isl_union_map **Read, isl_union_map **Write, isl_union_map **MayWrite, isl_union_map **Schedule) { isl_space *Space = S.getParamSpace(); *Read = isl_union_map_empty(isl_space_copy(Space)); *Write = isl_union_map_empty(isl_space_copy(Space)); *MayWrite = isl_union_map_empty(isl_space_copy(Space)); *Schedule = isl_union_map_empty(Space); for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; for (ScopStmt::memacc_iterator MI = Stmt->memacc_begin(), ME = Stmt->memacc_end(); MI != ME; ++MI) { isl_set *domcp = Stmt->getDomain(); isl_map *accdom = (*MI)->getAccessRelation(); accdom = isl_map_intersect_domain(accdom, domcp); if ((*MI)->isRead()) *Read = isl_union_map_add_map(*Read, accdom); else *Write = isl_union_map_add_map(*Write, accdom); } *Schedule = isl_union_map_add_map(*Schedule, Stmt->getScattering()); } }
CloogInput *Cloog::buildCloogInput() { // XXX: We do not copy the context of the scop, but use an unconstrained // context. This 'hack' is necessary as the context may contain bounds // on parameters such as [n] -> {:0 <= n < 2^32}. Those large // integers will cause CLooG to construct a clast that contains // expressions that include these large integers. Such expressions can // possibly not be evaluated correctly with i64 types. The cloog // based code generation backend, however, can not derive types // automatically and just assumes i64 types. Hence, it will break or // generate incorrect code. // This hack does not remove all possibilities of incorrectly generated // code, but it is ensures that for most problems the problems do not // show up. The correct solution, will be to automatically derive the // minimal types for each expression. This could be added to CLooG and it // will be available in the isl based code generation. isl_set *EmptyContext = isl_set_universe(S->getParamSpace()); CloogDomain *Context = cloog_domain_from_isl_set(EmptyContext); CloogUnionDomain *Statements = buildCloogUnionDomain(); isl_set *ScopContext = S->getContext(); for (unsigned i = 0; i < isl_set_dim(ScopContext, isl_dim_param); i++) { isl_id *id = isl_set_get_dim_id(ScopContext, isl_dim_param, i); Statements = cloog_union_domain_set_name(Statements, CLOOG_PARAM, i, isl_id_get_name(id)); isl_id_free(id); } isl_set_free(ScopContext); CloogInput *Input = cloog_input_alloc(Context, Statements); return Input; }
// Generate a unique name that is usable as a LLVM name for a scop to name its // performance counter. static std::string GetScopUniqueVarname(const Scop &S) { std::stringstream Name; std::string EntryString, ExitString; std::tie(EntryString, ExitString) = S.getEntryExitStr(); Name << "__polly_perf_in_" << std::string(S.getFunction().getName()) << "_from__" << EntryString << "__to__" << ExitString; return Name.str(); }
std::string JSONImporter::getFileName(Scop &S) const { std::string FunctionName = S.getFunction().getName(); std::string FileName = FunctionName + "___" + S.getNameStr() + ".jscop"; if (ImportPostfix != "") FileName += "." + ImportPostfix; return FileName; }
__isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt, const SCEV *Scev) { Scop *S = Stmt->getParent(); const Region *Reg = &S->getRegion(); S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE())); SCEVAffinator Affinator(Stmt); return Affinator.visit(Scev); }
/// Performs polyhedral dead iteration elimination by: /// o Assuming that the last write to each location is live. /// o Following each RAW dependency from a live iteration backwards and adding /// that iteration to the live set. /// /// To ensure the set of live iterations does not get too complex we always /// combine a certain number of precise steps with one approximating step that /// simplifies the life set with an affine hull. bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) { DependenceInfo &DI = getAnalysis<DependenceInfo>(); const Dependences &D = DI.getDependences(Dependences::AL_Statement); if (!D.hasValidDependences()) return false; isl_union_set *Live = getLiveOut(S); isl_union_map *Dep = D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED); Dep = isl_union_map_reverse(Dep); if (PreciseSteps == -1) Live = isl_union_set_affine_hull(Live); isl_union_set *OriginalDomain = S.getDomains(); int Steps = 0; while (true) { isl_union_set *Extra; Steps++; Extra = isl_union_set_apply(isl_union_set_copy(Live), isl_union_map_copy(Dep)); if (isl_union_set_is_subset(Extra, Live)) { isl_union_set_free(Extra); break; } Live = isl_union_set_union(Live, Extra); if (Steps > PreciseSteps) { Steps = 0; Live = isl_union_set_affine_hull(Live); } Live = isl_union_set_intersect(Live, isl_union_set_copy(OriginalDomain)); } isl_union_map_free(Dep); isl_union_set_free(OriginalDomain); bool Changed = S.restrictDomains(isl_union_set_coalesce(Live)); // FIXME: We can probably avoid the recomputation of all dependences by // updating them explicitly. if (Changed) DI.recomputeDependences(Dependences::AL_Statement); return Changed; }
void ScopAnnotator::buildAliasScopes(Scop &S) { SE = S.getSE(); LLVMContext &Ctx = SE->getContext(); AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain")); AliasScopeMap.clear(); OtherAliasScopeListMap.clear(); SetVector<Value *> BasePtrs; for (ScopStmt &Stmt : S) for (MemoryAccess *MA : Stmt) BasePtrs.insert(MA->getBaseAddr()); std::string AliasScopeStr = "polly.alias.scope."; for (Value *BasePtr : BasePtrs) AliasScopeMap[BasePtr] = getID( Ctx, AliasScopeDomain, MDString::get(Ctx, (AliasScopeStr + BasePtr->getName()).str().c_str())); for (Value *BasePtr : BasePtrs) { MDNode *AliasScopeList = MDNode::get(Ctx, {}); for (const auto &AliasScopePair : AliasScopeMap) { if (BasePtr == AliasScopePair.first) continue; Metadata *Args = {AliasScopePair.second}; AliasScopeList = MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args)); } OtherAliasScopeListMap[BasePtr] = AliasScopeList; } }
void JSONImporter::printScop(raw_ostream &OS, Scop &S) const { S.print(OS); for (std::vector<std::string>::const_iterator I = newAccessStrings.begin(), E = newAccessStrings.end(); I != E; I++) OS << "New access function '" << *I << "'detected in JSCOP file\n"; }
CloogInput *Cloog::buildCloogInput() { CloogDomain *Context = cloog_domain_from_isl_set(isl_set_copy(S->getContext())); CloogUnionDomain *Statements = buildCloogUnionDomain(); CloogInput *Input = cloog_input_alloc (Context, Statements); return Input; }
bool CloogInfo::runOnScop(Scop &S) { if (C) delete C; scop = &S; C = new Cloog(&S); Function *F = S.getRegion().getEntry()->getParent(); (void)F; DEBUG(dbgs() << ":: " << F->getName()); DEBUG(dbgs() << " : " << S.getRegion().getNameStr() << "\n"); DEBUG(C->pprint(dbgs())); return false; }
CloogUnionDomain *Cloog::buildCloogUnionDomain() { CloogUnionDomain *DU = cloog_union_domain_alloc(S->getNumParams()); for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; CloogScattering *Scattering; CloogDomain *Domain; Scattering = cloog_scattering_from_isl_map(Stmt->getScattering()); Domain = cloog_domain_from_isl_set(Stmt->getDomain()); std::string entryName = Stmt->getBaseName(); DU = cloog_union_domain_add_domain(DU, entryName.c_str(), Domain, Scattering, Stmt); } return DU; }
void IslScheduleOptimizer::extendScattering(Scop &S, unsigned NewDimensions) { for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; unsigned OldDimensions = Stmt->getNumScattering(); isl_space *Space; isl_map *Map, *New; Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions); Map = isl_map_universe(Space); for (unsigned i = 0; i < OldDimensions; i++) Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); for (unsigned i = OldDimensions; i < NewDimensions; i++) Map = isl_map_fix_si(Map, isl_dim_out, i, 0); Map = isl_map_align_params(Map, S.getParamSpace()); New = isl_map_apply_range(Stmt->getScattering(), Map); Stmt->setScattering(New); } }
bool polly::canSynthesize(const Value *V, const Scop &S, const llvm::LoopInfo *LI, ScalarEvolution *SE, Loop *Scope) { if (!V || !SE->isSCEVable(V->getType())) return false; if (const SCEV *Scev = SE->getSCEVAtScope(const_cast<Value *>(V), Scope)) if (!isa<SCEVCouldNotCompute>(Scev)) if (!hasScalarDepsInsideRegion(Scev, &S.getRegion(), Scope, false)) return true; return false; }
Json::Value JSONExporter::getJSON(Scop &S) const { Json::Value root; unsigned LineBegin, LineEnd; std::string FileName; getDebugLocation(&S.getRegion(), LineBegin, LineEnd, FileName); std::string Location; if (LineBegin != (unsigned)-1) Location = FileName + ":" + std::to_string(LineBegin) + "-" + std::to_string(LineEnd); root["name"] = S.getNameStr(); root["context"] = S.getContextStr(); if (LineBegin != (unsigned)-1) root["location"] = Location; root["statements"]; for (ScopStmt &Stmt : S) { Json::Value statement; statement["name"] = Stmt.getBaseName(); statement["domain"] = Stmt.getDomainStr(); statement["schedule"] = Stmt.getScheduleStr(); statement["accesses"]; for (MemoryAccess *MA : Stmt) { Json::Value access; access["kind"] = MA->isRead() ? "read" : "write"; access["relation"] = MA->getOriginalAccessRelationStr(); statement["accesses"].append(access); } root["statements"].append(statement); } return root; }
CloogUnionDomain *Cloog::buildCloogUnionDomain() { CloogUnionDomain *DU = cloog_union_domain_alloc(S->getNumParams()); for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; if (Stmt->isFinalRead()) continue; CloogScattering *Scattering= cloog_scattering_from_isl_map(isl_map_copy(Stmt->getScattering())); CloogDomain *Domain = cloog_domain_from_isl_set(isl_set_copy(Stmt->getDomain())); std::string entryName = Stmt->getBaseName(); char *Name = (char*)malloc(sizeof(char) * (entryName.size() + 1)); strcpy(Name, entryName.c_str()); DU = cloog_union_domain_add_domain(DU, Name, Domain, Scattering, Stmt); } return DU; }
__isl_give isl_pw_aff * SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) { assert(Expr->isAffine() && "Only affine AddRecurrences allowed"); // Directly generate isl_pw_aff for Expr if 'start' is zero. if (Expr->getStart()->isZero()) { assert(S->getRegion().contains(Expr->getLoop()) && "Scop does not contain the loop referenced in this AddRec"); isl_pw_aff *Start = visit(Expr->getStart()); isl_pw_aff *Step = visit(Expr->getOperand(1)); isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces); isl_local_space *LocalSpace = isl_local_space_from_space(Space); int loopDimension = getLoopDepth(Expr->getLoop()); isl_aff *LAff = isl_aff_set_coefficient_si( isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1); isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff); // TODO: Do we need to check for NSW and NUW? return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff)); } // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}' // if 'start' is not zero. ScalarEvolution &SE = *S->getSE(); const SCEV *ZeroStartExpr = SE.getAddRecExpr( SE.getConstant(Expr->getStart()->getType(), 0), Expr->getStepRecurrence(SE), Expr->getLoop(), SCEV::FlagAnyWrap); isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr); isl_pw_aff *Start = visit(Expr->getStart()); return isl_pw_aff_add(ZeroStartResult, Start); }
bool CloogExporter::runOnScop(Scop &S) { Region &R = S.getRegion(); CloogInfo &C = getAnalysis<CloogInfo>(); std::string FunctionName = R.getEntry()->getParent()->getNameStr(); std::string Filename = getFileName(&R); errs() << "Writing Scop '" << R.getNameStr() << "' in function '" << FunctionName << "' to '" << Filename << "'...\n"; FILE *F = fopen(Filename.c_str(), "w"); C.dump(F); fclose(F); return false; }
bool ScheduleTreeOptimizer::isProfitableSchedule( Scop &S, __isl_keep isl_union_map *NewSchedule) { // To understand if the schedule has been optimized we check if the schedule // has changed at all. // TODO: We can improve this by tracking if any necessarily beneficial // transformations have been performed. This can e.g. be tiling, loop // interchange, or ...) We can track this either at the place where the // transformation has been performed or, in case of automatic ILP based // optimizations, by comparing (yet to be defined) performance metrics // before/after the scheduling optimizer // (e.g., #stride-one accesses) isl_union_map *OldSchedule = S.getSchedule(); bool changed = !isl_union_map_is_equal(OldSchedule, NewSchedule); isl_union_map_free(OldSchedule); return changed; }
bool AliasCheckGenerator::runOnScop(Scop &S) { SD = &getAnalysis<ScopDetection>(); Region &ScopRegion = S.getRegion(); for (ScopDetection::reject_iterator RI = SD->reject_begin(), RE = SD->reject_end(); RI != RE; ++RI) { const Region *R = RI->first; RejectLog &Log = RI->second; // for (RejectReasonPtr RRPtr : Log) { // if (ReportAlias *AliasError = dyn_cast<ReportAlias>(RRPtr.get())) { // if (R == &ScopRegion) // } //} } return true; }
__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) { // In case the scev is a valid parameter, we do not further analyze this // expression, but create a new parameter in the isl_pw_aff. This allows us // to treat subexpressions that we cannot translate into an piecewise affine // expression, as constant parameters of the piecewise affine expression. if (isl_id *Id = S->getIdForParam(Expr)) { isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces); Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id); isl_set *Domain = isl_set_universe(isl_space_copy(Space)); isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space)); Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1); return isl_pw_aff_alloc(Domain, Affine); } return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr); }
void AliasCheckGenerator::printIslExpressions(const Scop &S) { BoundsMapT BoundsMap; unsigned int numAccs = 0; for (ScopStmt *Stmt : S) { for (MemoryAccess *Acc : *Stmt) { Map Access = isl::Map(Acc->getAccessRelation()); Set Domain = isl::Set(Stmt->getDomain()); const Set MemAccs = Domain.apply(Access); if (!BoundsMap.count(MemAccs)) { BoundsMap.insert(MemAccs); ++numAccs; } } } log(Debug, 2) << "Num Accesses: " << numAccs << " -> " << binomial_coefficient(numAccs, 2) << "\n"; BoundsMapT mapcp = BoundsMap; const Set ParamCtx = Set(S.getAssumedContext()); Set Cond = Set::universe(ParamCtx.getSpace()); for (const Set &s : BoundsMap) { BoundsMapT::iterator it = mapcp.find(s); if (it != mapcp.end()) { mapcp.erase(it); if (mapcp.size() > 0) { Cond = checkPairs(Cond, s, mapcp); } } } AstBuild Builder = AstBuild::fromContext(ParamCtx); PwAff Check = Cond.indicatorFunction(); AstExpr ExprCheck = Builder.exprFromPwAff(Check); log(Debug, 4) << "if (" << ExprCheck.toStr(Format::FC) << ")\n\n"; }
void IslAstInfo::printScop(raw_ostream &OS, Scop &S) const { isl_ast_print_options *Options; isl_ast_node *RootNode = getAst(); Function *F = S.getRegion().getEntry()->getParent(); OS << ":: isl ast :: " << F->getName() << " :: " << S.getRegion().getNameStr() << "\n"; if (!RootNode) { OS << ":: isl ast generation and code generation was skipped!\n\n"; OS << ":: This is either because no useful optimizations could be applied " "(use -polly-process-unprofitable to enforce code generation) or " "because earlier passes such as dependence analysis timed out (use " "-polly-dependences-computeout=0 to set dependence analysis timeout " "to infinity)\n\n"; return; } isl_ast_expr *RunCondition = getRunCondition(); char *RtCStr, *AstStr; Options = isl_ast_print_options_alloc(S.getIslCtx()); Options = isl_ast_print_options_set_print_for(Options, cbPrintFor, nullptr); isl_printer *P = isl_printer_to_str(S.getIslCtx()); P = isl_printer_print_ast_expr(P, RunCondition); RtCStr = isl_printer_get_str(P); P = isl_printer_flush(P); P = isl_printer_indent(P, 4); P = isl_printer_set_output_format(P, ISL_FORMAT_C); P = isl_ast_node_print(RootNode, P, Options); AstStr = isl_printer_get_str(P); isl_union_map *Schedule = isl_union_map_intersect_domain(S.getSchedule(), S.getDomains()); DEBUG({ dbgs() << S.getContextStr() << "\n"; dbgs() << stringFromIslObj(Schedule); });
void BlockGenerator::finalizeSCoP(Scop &S, ValueMapT &GlobalMap) { createScalarInitialization(S.getRegion(), GlobalMap); createScalarFinalization(S.getRegion()); }
bool IslScheduleOptimizer::runOnScop(Scop &S) { Dependences *D = &getAnalysis<Dependences>(); if (!D->hasValidDependences()) return false; isl_schedule_free(LastSchedule); LastSchedule = nullptr; // Build input data. int ValidityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; int ProximityKinds; if (OptimizeDeps == "all") ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; else if (OptimizeDeps == "raw") ProximityKinds = Dependences::TYPE_RAW; else { errs() << "Do not know how to optimize for '" << OptimizeDeps << "'" << " Falling back to optimizing all dependences.\n"; ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; } isl_union_set *Domain = S.getDomains(); if (!Domain) return false; isl_union_map *Validity = D->getDependences(ValidityKinds); isl_union_map *Proximity = D->getDependences(ProximityKinds); // Simplify the dependences by removing the constraints introduced by the // domains. This can speed up the scheduling time significantly, as large // constant coefficients will be removed from the dependences. The // introduction of some additional dependences reduces the possible // transformations, but in most cases, such transformation do not seem to be // interesting anyway. In some cases this option may stop the scheduler to // find any schedule. if (SimplifyDeps == "yes") { Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain)); Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain)); Proximity = isl_union_map_gist_domain(Proximity, isl_union_set_copy(Domain)); Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain)); } else if (SimplifyDeps != "no") { errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' " "or 'no'. Falling back to default: 'yes'\n"; } DEBUG(dbgs() << "\n\nCompute schedule from: "); DEBUG(dbgs() << "Domain := "; isl_union_set_dump(Domain); dbgs() << ";\n"); DEBUG(dbgs() << "Proximity := "; isl_union_map_dump(Proximity); dbgs() << ";\n"); DEBUG(dbgs() << "Validity := "; isl_union_map_dump(Validity); dbgs() << ";\n"); int IslFusionStrategy; if (FusionStrategy == "max") { IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX; } else if (FusionStrategy == "min") { IslFusionStrategy = ISL_SCHEDULE_FUSE_MIN; } else { errs() << "warning: Unknown fusion strategy. Falling back to maximal " "fusion.\n"; IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX; } int IslMaximizeBands; if (MaximizeBandDepth == "yes") { IslMaximizeBands = 1; } else if (MaximizeBandDepth == "no") { IslMaximizeBands = 0; } else { errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'" " or 'no'. Falling back to default: 'yes'\n"; IslMaximizeBands = 1; } isl_options_set_schedule_fuse(S.getIslCtx(), IslFusionStrategy); isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands); isl_options_set_schedule_max_constant_term(S.getIslCtx(), MaxConstantTerm); isl_options_set_schedule_max_coefficient(S.getIslCtx(), MaxCoefficient); isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE); isl_schedule_constraints *ScheduleConstraints; ScheduleConstraints = isl_schedule_constraints_on_domain(Domain); ScheduleConstraints = isl_schedule_constraints_set_proximity(ScheduleConstraints, Proximity); ScheduleConstraints = isl_schedule_constraints_set_validity( ScheduleConstraints, isl_union_map_copy(Validity)); ScheduleConstraints = isl_schedule_constraints_set_coincidence(ScheduleConstraints, Validity); isl_schedule *Schedule; Schedule = isl_schedule_constraints_compute_schedule(ScheduleConstraints); isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT); // In cases the scheduler is not able to optimize the code, we just do not // touch the schedule. if (!Schedule) return false; DEBUG(dbgs() << "Schedule := "; isl_schedule_dump(Schedule); dbgs() << ";\n"); isl_union_map *ScheduleMap = getScheduleMap(Schedule); for (ScopStmt *Stmt : S) { isl_map *StmtSchedule; isl_set *Domain = Stmt->getDomain(); isl_union_map *StmtBand; StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(ScheduleMap), isl_union_set_from_set(Domain)); if (isl_union_map_is_empty(StmtBand)) { StmtSchedule = isl_map_from_domain(isl_set_empty(Stmt->getDomainSpace())); isl_union_map_free(StmtBand); } else { assert(isl_union_map_n_map(StmtBand) == 1); StmtSchedule = isl_map_from_union_map(StmtBand); } Stmt->setScattering(StmtSchedule); } isl_union_map_free(ScheduleMap); LastSchedule = Schedule; unsigned MaxScatDims = 0; for (ScopStmt *Stmt : S) MaxScatDims = std::max(Stmt->getNumScattering(), MaxScatDims); extendScattering(S, MaxScatDims); return false; }
bool IslScheduleOptimizer::runOnScop(Scop &S) { // Skip empty SCoPs but still allow code generation as it will delete the // loops present but not needed. if (S.getSize() == 0) { S.markAsOptimized(); return false; } const Dependences &D = getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement); if (!D.hasValidDependences()) return false; isl_schedule_free(LastSchedule); LastSchedule = nullptr; // Build input data. int ValidityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; int ProximityKinds; if (OptimizeDeps == "all") ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; else if (OptimizeDeps == "raw") ProximityKinds = Dependences::TYPE_RAW; else { errs() << "Do not know how to optimize for '" << OptimizeDeps << "'" << " Falling back to optimizing all dependences.\n"; ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; } isl_union_set *Domain = S.getDomains(); if (!Domain) return false; isl_union_map *Validity = D.getDependences(ValidityKinds); isl_union_map *Proximity = D.getDependences(ProximityKinds); // Simplify the dependences by removing the constraints introduced by the // domains. This can speed up the scheduling time significantly, as large // constant coefficients will be removed from the dependences. The // introduction of some additional dependences reduces the possible // transformations, but in most cases, such transformation do not seem to be // interesting anyway. In some cases this option may stop the scheduler to // find any schedule. if (SimplifyDeps == "yes") { Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain)); Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain)); Proximity = isl_union_map_gist_domain(Proximity, isl_union_set_copy(Domain)); Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain)); } else if (SimplifyDeps != "no") { errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' " "or 'no'. Falling back to default: 'yes'\n"; } DEBUG(dbgs() << "\n\nCompute schedule from: "); DEBUG(dbgs() << "Domain := " << stringFromIslObj(Domain) << ";\n"); DEBUG(dbgs() << "Proximity := " << stringFromIslObj(Proximity) << ";\n"); DEBUG(dbgs() << "Validity := " << stringFromIslObj(Validity) << ";\n"); unsigned IslSerializeSCCs; if (FusionStrategy == "max") { IslSerializeSCCs = 0; } else if (FusionStrategy == "min") { IslSerializeSCCs = 1; } else { errs() << "warning: Unknown fusion strategy. Falling back to maximal " "fusion.\n"; IslSerializeSCCs = 0; } int IslMaximizeBands; if (MaximizeBandDepth == "yes") { IslMaximizeBands = 1; } else if (MaximizeBandDepth == "no") { IslMaximizeBands = 0; } else { errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'" " or 'no'. Falling back to default: 'yes'\n"; IslMaximizeBands = 1; } isl_options_set_schedule_serialize_sccs(S.getIslCtx(), IslSerializeSCCs); isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands); isl_options_set_schedule_max_constant_term(S.getIslCtx(), MaxConstantTerm); isl_options_set_schedule_max_coefficient(S.getIslCtx(), MaxCoefficient); isl_options_set_tile_scale_tile_loops(S.getIslCtx(), 0); isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE); isl_schedule_constraints *ScheduleConstraints; ScheduleConstraints = isl_schedule_constraints_on_domain(Domain); ScheduleConstraints = isl_schedule_constraints_set_proximity(ScheduleConstraints, Proximity); ScheduleConstraints = isl_schedule_constraints_set_validity( ScheduleConstraints, isl_union_map_copy(Validity)); ScheduleConstraints = isl_schedule_constraints_set_coincidence(ScheduleConstraints, Validity); isl_schedule *Schedule; Schedule = isl_schedule_constraints_compute_schedule(ScheduleConstraints); isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT); // In cases the scheduler is not able to optimize the code, we just do not // touch the schedule. if (!Schedule) return false; DEBUG({ auto *P = isl_printer_to_str(S.getIslCtx()); P = isl_printer_set_yaml_style(P, ISL_YAML_STYLE_BLOCK); P = isl_printer_print_schedule(P, Schedule); dbgs() << "NewScheduleTree: \n" << isl_printer_get_str(P) << "\n"; isl_printer_free(P); });
std::string JSONExporter::getFileName(Scop &S) const { std::string FunctionName = S.getFunction().getName(); std::string FileName = FunctionName + "___" + S.getNameStr() + ".jscop"; return FileName; }
void JSONExporter::printScop(raw_ostream &OS, Scop &S) const { S.print(OS); }
int SCEVAffinator::getLoopDepth(const Loop *L) { Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L)); assert(outerLoop && "Scop does not contain this loop"); return L->getLoopDepth() - outerLoop->getLoopDepth(); }