1 //===- IslAst.cpp - isl code generator interface --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // The isl code generator interface takes a Scop and generates an isl_ast. This 11 // ist_ast can either be returned directly or it can be pretty printed to 12 // stdout. 13 // 14 // A typical isl_ast output looks like this: 15 // 16 // for (c2 = max(0, ceild(n + m, 2); c2 <= min(511, floord(5 * n, 3)); c2++) { 17 // bb2(c2); 18 // } 19 // 20 // An in-depth discussion of our AST generation approach can be found in: 21 // 22 // Polyhedral AST generation is more than scanning polyhedra 23 // Tobias Grosser, Sven Verdoolaege, Albert Cohen 24 // ACM Transations on Programming Languages and Systems (TOPLAS), 25 // 37(4), July 2015 26 // http://www.grosser.es/#pub-polyhedral-AST-generation 27 // 28 //===----------------------------------------------------------------------===// 29 30 #include "polly/CodeGen/CodeGeneration.h" 31 #include "polly/CodeGen/IslAst.h" 32 #include "polly/DependenceInfo.h" 33 #include "polly/LinkAllPasses.h" 34 #include "polly/Options.h" 35 #include "polly/ScopInfo.h" 36 #include "polly/Support/GICHelper.h" 37 #include "llvm/Analysis/RegionInfo.h" 38 #include "llvm/Support/Debug.h" 39 #include "isl/aff.h" 40 #include "isl/ast_build.h" 41 #include "isl/list.h" 42 #include "isl/map.h" 43 #include "isl/set.h" 44 #include "isl/union_map.h" 45 46 #define DEBUG_TYPE "polly-ast" 47 48 using namespace llvm; 49 using namespace polly; 50 51 using IslAstUserPayload = IslAstInfo::IslAstUserPayload; 52 53 static cl::opt<bool> 54 PollyParallel("polly-parallel", 55 cl::desc("Generate thread parallel code (isl codegen only)"), 56 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 57 58 static cl::opt<bool> PollyParallelForce( 59 "polly-parallel-force", 60 cl::desc( 61 "Force generation of thread parallel code ignoring any cost model"), 62 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 63 64 static cl::opt<bool> UseContext("polly-ast-use-context", 65 cl::desc("Use context"), cl::Hidden, 66 cl::init(false), cl::ZeroOrMore, 67 cl::cat(PollyCategory)); 68 69 static cl::opt<bool> DetectParallel("polly-ast-detect-parallel", 70 cl::desc("Detect parallelism"), cl::Hidden, 71 cl::init(false), cl::ZeroOrMore, 72 cl::cat(PollyCategory)); 73 74 namespace polly { 75 class IslAst { 76 public: 77 static IslAst *create(Scop *Scop, const Dependences &D); 78 ~IslAst(); 79 80 /// Print a source code representation of the program. 81 void pprint(llvm::raw_ostream &OS); 82 83 __isl_give isl_ast_node *getAst(); 84 85 /// @brief Get the run-time conditions for the Scop. 86 __isl_give isl_ast_expr *getRunCondition(); 87 88 private: 89 Scop *S; 90 isl_ast_node *Root; 91 isl_ast_expr *RunCondition; 92 93 IslAst(Scop *Scop); 94 void init(const Dependences &D); 95 96 void buildRunCondition(__isl_keep isl_ast_build *Build); 97 }; 98 } // End namespace polly. 99 100 /// @brief Free an IslAstUserPayload object pointed to by @p Ptr 101 static void freeIslAstUserPayload(void *Ptr) { 102 delete ((IslAstInfo::IslAstUserPayload *)Ptr); 103 } 104 105 IslAstInfo::IslAstUserPayload::~IslAstUserPayload() { 106 isl_ast_build_free(Build); 107 isl_pw_aff_free(MinimalDependenceDistance); 108 } 109 110 /// @brief Temporary information used when building the ast. 111 struct AstBuildUserInfo { 112 /// @brief Construct and initialize the helper struct for AST creation. 113 AstBuildUserInfo() 114 : Deps(nullptr), InParallelFor(false), LastForNodeId(nullptr) {} 115 116 /// @brief The dependence information used for the parallelism check. 117 const Dependences *Deps; 118 119 /// @brief Flag to indicate that we are inside a parallel for node. 120 bool InParallelFor; 121 122 /// @brief The last iterator id created for the current SCoP. 123 isl_id *LastForNodeId; 124 }; 125 126 /// @brief Print a string @p str in a single line using @p Printer. 127 static isl_printer *printLine(__isl_take isl_printer *Printer, 128 const std::string &str, 129 __isl_keep isl_pw_aff *PWA = nullptr) { 130 Printer = isl_printer_start_line(Printer); 131 Printer = isl_printer_print_str(Printer, str.c_str()); 132 if (PWA) 133 Printer = isl_printer_print_pw_aff(Printer, PWA); 134 return isl_printer_end_line(Printer); 135 } 136 137 /// @brief Return all broken reductions as a string of clauses (OpenMP style). 138 static const std::string getBrokenReductionsStr(__isl_keep isl_ast_node *Node) { 139 IslAstInfo::MemoryAccessSet *BrokenReductions; 140 std::string str; 141 142 BrokenReductions = IslAstInfo::getBrokenReductions(Node); 143 if (!BrokenReductions || BrokenReductions->empty()) 144 return ""; 145 146 // Map each type of reduction to a comma separated list of the base addresses. 147 std::map<MemoryAccess::ReductionType, std::string> Clauses; 148 for (MemoryAccess *MA : *BrokenReductions) 149 if (MA->isWrite()) 150 Clauses[MA->getReductionType()] += 151 ", " + MA->getBaseAddr()->getName().str(); 152 153 // Now print the reductions sorted by type. Each type will cause a clause 154 // like: reduction (+ : sum0, sum1, sum2) 155 for (const auto &ReductionClause : Clauses) { 156 str += " reduction ("; 157 str += MemoryAccess::getReductionOperatorStr(ReductionClause.first); 158 // Remove the first two symbols (", ") to make the output look pretty. 159 str += " : " + ReductionClause.second.substr(2) + ")"; 160 } 161 162 return str; 163 } 164 165 /// @brief Callback executed for each for node in the ast in order to print it. 166 static isl_printer *cbPrintFor(__isl_take isl_printer *Printer, 167 __isl_take isl_ast_print_options *Options, 168 __isl_keep isl_ast_node *Node, void *) { 169 170 isl_pw_aff *DD = IslAstInfo::getMinimalDependenceDistance(Node); 171 const std::string BrokenReductionsStr = getBrokenReductionsStr(Node); 172 const std::string KnownParallelStr = "#pragma known-parallel"; 173 const std::string DepDisPragmaStr = "#pragma minimal dependence distance: "; 174 const std::string SimdPragmaStr = "#pragma simd"; 175 const std::string OmpPragmaStr = "#pragma omp parallel for"; 176 177 if (DD) 178 Printer = printLine(Printer, DepDisPragmaStr, DD); 179 180 if (IslAstInfo::isInnermostParallel(Node)) 181 Printer = printLine(Printer, SimdPragmaStr + BrokenReductionsStr); 182 183 if (IslAstInfo::isExecutedInParallel(Node)) 184 Printer = printLine(Printer, OmpPragmaStr); 185 else if (IslAstInfo::isOutermostParallel(Node)) 186 Printer = printLine(Printer, KnownParallelStr + BrokenReductionsStr); 187 188 isl_pw_aff_free(DD); 189 return isl_ast_node_for_print(Node, Printer, Options); 190 } 191 192 /// @brief Check if the current scheduling dimension is parallel 193 /// 194 /// In case the dimension is parallel we also check if any reduction 195 /// dependences is broken when we exploit this parallelism. If so, 196 /// @p IsReductionParallel will be set to true. The reduction dependences we use 197 /// to check are actually the union of the transitive closure of the initial 198 /// reduction dependences together with their reveresal. Even though these 199 /// dependences connect all iterations with each other (thus they are cyclic) 200 /// we can perform the parallelism check as we are only interested in a zero 201 /// (or non-zero) dependence distance on the dimension in question. 202 static bool astScheduleDimIsParallel(__isl_keep isl_ast_build *Build, 203 const Dependences *D, 204 IslAstUserPayload *NodeInfo) { 205 if (!D->hasValidDependences()) 206 return false; 207 208 isl_union_map *Schedule = isl_ast_build_get_schedule(Build); 209 isl_union_map *Deps = D->getDependences( 210 Dependences::TYPE_RAW | Dependences::TYPE_WAW | Dependences::TYPE_WAR); 211 212 if (!D->isParallel(Schedule, Deps, &NodeInfo->MinimalDependenceDistance) && 213 !isl_union_map_free(Schedule)) 214 return false; 215 216 isl_union_map *RedDeps = D->getDependences(Dependences::TYPE_TC_RED); 217 if (!D->isParallel(Schedule, RedDeps)) 218 NodeInfo->IsReductionParallel = true; 219 220 if (!NodeInfo->IsReductionParallel && !isl_union_map_free(Schedule)) 221 return true; 222 223 // Annotate reduction parallel nodes with the memory accesses which caused the 224 // reduction dependences parallel execution of the node conflicts with. 225 for (const auto &MaRedPair : D->getReductionDependences()) { 226 if (!MaRedPair.second) 227 continue; 228 RedDeps = isl_union_map_from_map(isl_map_copy(MaRedPair.second)); 229 if (!D->isParallel(Schedule, RedDeps)) 230 NodeInfo->BrokenReductions.insert(MaRedPair.first); 231 } 232 233 isl_union_map_free(Schedule); 234 return true; 235 } 236 237 // This method is executed before the construction of a for node. It creates 238 // an isl_id that is used to annotate the subsequently generated ast for nodes. 239 // 240 // In this function we also run the following analyses: 241 // 242 // - Detection of openmp parallel loops 243 // 244 static __isl_give isl_id *astBuildBeforeFor(__isl_keep isl_ast_build *Build, 245 void *User) { 246 AstBuildUserInfo *BuildInfo = (AstBuildUserInfo *)User; 247 IslAstUserPayload *Payload = new IslAstUserPayload(); 248 isl_id *Id = isl_id_alloc(isl_ast_build_get_ctx(Build), "", Payload); 249 Id = isl_id_set_free_user(Id, freeIslAstUserPayload); 250 BuildInfo->LastForNodeId = Id; 251 252 // Test for parallelism only if we are not already inside a parallel loop 253 if (!BuildInfo->InParallelFor) 254 BuildInfo->InParallelFor = Payload->IsOutermostParallel = 255 astScheduleDimIsParallel(Build, BuildInfo->Deps, Payload); 256 257 return Id; 258 } 259 260 // This method is executed after the construction of a for node. 261 // 262 // It performs the following actions: 263 // 264 // - Reset the 'InParallelFor' flag, as soon as we leave a for node, 265 // that is marked as openmp parallel. 266 // 267 static __isl_give isl_ast_node * 268 astBuildAfterFor(__isl_take isl_ast_node *Node, __isl_keep isl_ast_build *Build, 269 void *User) { 270 isl_id *Id = isl_ast_node_get_annotation(Node); 271 assert(Id && "Post order visit assumes annotated for nodes"); 272 IslAstUserPayload *Payload = (IslAstUserPayload *)isl_id_get_user(Id); 273 assert(Payload && "Post order visit assumes annotated for nodes"); 274 275 AstBuildUserInfo *BuildInfo = (AstBuildUserInfo *)User; 276 assert(!Payload->Build && "Build environment already set"); 277 Payload->Build = isl_ast_build_copy(Build); 278 Payload->IsInnermost = (Id == BuildInfo->LastForNodeId); 279 280 // Innermost loops that are surrounded by parallel loops have not yet been 281 // tested for parallelism. Test them here to ensure we check all innermost 282 // loops for parallelism. 283 if (Payload->IsInnermost && BuildInfo->InParallelFor) { 284 if (Payload->IsOutermostParallel) 285 Payload->IsInnermostParallel = true; 286 else 287 Payload->IsInnermostParallel = 288 astScheduleDimIsParallel(Build, BuildInfo->Deps, Payload); 289 } 290 if (Payload->IsOutermostParallel) 291 BuildInfo->InParallelFor = false; 292 293 isl_id_free(Id); 294 return Node; 295 } 296 297 static __isl_give isl_ast_node *AtEachDomain(__isl_take isl_ast_node *Node, 298 __isl_keep isl_ast_build *Build, 299 void *User) { 300 assert(!isl_ast_node_get_annotation(Node) && "Node already annotated"); 301 302 IslAstUserPayload *Payload = new IslAstUserPayload(); 303 isl_id *Id = isl_id_alloc(isl_ast_build_get_ctx(Build), "", Payload); 304 Id = isl_id_set_free_user(Id, freeIslAstUserPayload); 305 306 Payload->Build = isl_ast_build_copy(Build); 307 308 return isl_ast_node_set_annotation(Node, Id); 309 } 310 311 // Build alias check condition given a pair of minimal/maximal access. 312 static __isl_give isl_ast_expr * 313 buildCondition(__isl_keep isl_ast_build *Build, const Scop::MinMaxAccessTy *It0, 314 const Scop::MinMaxAccessTy *It1) { 315 isl_ast_expr *NonAliasGroup, *MinExpr, *MaxExpr; 316 MinExpr = isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff( 317 Build, isl_pw_multi_aff_copy(It0->first))); 318 MaxExpr = isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff( 319 Build, isl_pw_multi_aff_copy(It1->second))); 320 NonAliasGroup = isl_ast_expr_le(MaxExpr, MinExpr); 321 MinExpr = isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff( 322 Build, isl_pw_multi_aff_copy(It1->first))); 323 MaxExpr = isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff( 324 Build, isl_pw_multi_aff_copy(It0->second))); 325 NonAliasGroup = 326 isl_ast_expr_or(NonAliasGroup, isl_ast_expr_le(MaxExpr, MinExpr)); 327 328 return NonAliasGroup; 329 } 330 331 void IslAst::buildRunCondition(__isl_keep isl_ast_build *Build) { 332 // The conditions that need to be checked at run-time for this scop are 333 // available as an isl_set in the runtime check context from which we can 334 // directly derive a run-time condition. 335 RunCondition = 336 isl_ast_build_expr_from_set(Build, S->getRuntimeCheckContext()); 337 338 // Create the alias checks from the minimal/maximal accesses in each alias 339 // group which consists of read only and non read only (read write) accesses. 340 // This operation is by construction quadratic in the read-write pointers and 341 // linear int the read only pointers in each alias group. 342 for (const Scop::MinMaxVectorPairTy &MinMaxAccessPair : S->getAliasGroups()) { 343 auto &MinMaxReadWrite = MinMaxAccessPair.first; 344 auto &MinMaxReadOnly = MinMaxAccessPair.second; 345 auto RWAccEnd = MinMaxReadWrite.end(); 346 347 for (auto RWAccIt0 = MinMaxReadWrite.begin(); RWAccIt0 != RWAccEnd; 348 ++RWAccIt0) { 349 for (auto RWAccIt1 = RWAccIt0 + 1; RWAccIt1 != RWAccEnd; ++RWAccIt1) 350 RunCondition = isl_ast_expr_and( 351 RunCondition, buildCondition(Build, RWAccIt0, RWAccIt1)); 352 for (const Scop::MinMaxAccessTy &ROAccIt : MinMaxReadOnly) 353 RunCondition = isl_ast_expr_and( 354 RunCondition, buildCondition(Build, RWAccIt0, &ROAccIt)); 355 } 356 } 357 } 358 359 /// @brief Simple cost analysis for a given SCoP 360 /// 361 /// TODO: Improve this analysis and extract it to make it usable in other 362 /// places too. 363 /// In order to improve the cost model we could either keep track of 364 /// performed optimizations (e.g., tiling) or compute properties on the 365 /// original as well as optimized SCoP (e.g., #stride-one-accesses). 366 static bool benefitsFromPolly(Scop *Scop, bool PerformParallelTest) { 367 368 if (PollyProcessUnprofitable) 369 return true; 370 371 // Check if nothing interesting happened. 372 if (!PerformParallelTest && !Scop->isOptimized() && 373 Scop->getAliasGroups().empty()) 374 return false; 375 376 // The default assumption is that Polly improves the code. 377 return true; 378 } 379 380 IslAst::IslAst(Scop *Scop) : S(Scop), Root(nullptr), RunCondition(nullptr) {} 381 382 void IslAst::init(const Dependences &D) { 383 bool PerformParallelTest = PollyParallel || DetectParallel || 384 PollyVectorizerChoice != VECTORIZER_NONE; 385 386 // Skip AST and code generation if there was no benefit achieved. 387 if (!benefitsFromPolly(S, PerformParallelTest)) 388 return; 389 390 isl_ctx *Ctx = S->getIslCtx(); 391 isl_options_set_ast_build_atomic_upper_bound(Ctx, true); 392 isl_ast_build *Build; 393 AstBuildUserInfo BuildInfo; 394 395 if (UseContext) 396 Build = isl_ast_build_from_context(S->getContext()); 397 else 398 Build = isl_ast_build_from_context(isl_set_universe(S->getParamSpace())); 399 400 Build = isl_ast_build_set_at_each_domain(Build, AtEachDomain, nullptr); 401 402 if (PerformParallelTest) { 403 BuildInfo.Deps = &D; 404 BuildInfo.InParallelFor = 0; 405 406 Build = isl_ast_build_set_before_each_for(Build, &astBuildBeforeFor, 407 &BuildInfo); 408 Build = 409 isl_ast_build_set_after_each_for(Build, &astBuildAfterFor, &BuildInfo); 410 } 411 412 buildRunCondition(Build); 413 414 Root = isl_ast_build_node_from_schedule(Build, S->getScheduleTree()); 415 416 isl_ast_build_free(Build); 417 } 418 419 IslAst *IslAst::create(Scop *Scop, const Dependences &D) { 420 auto Ast = new IslAst(Scop); 421 Ast->init(D); 422 return Ast; 423 } 424 425 IslAst::~IslAst() { 426 isl_ast_node_free(Root); 427 isl_ast_expr_free(RunCondition); 428 } 429 430 __isl_give isl_ast_node *IslAst::getAst() { return isl_ast_node_copy(Root); } 431 __isl_give isl_ast_expr *IslAst::getRunCondition() { 432 return isl_ast_expr_copy(RunCondition); 433 } 434 435 void IslAstInfo::releaseMemory() { 436 if (Ast) { 437 delete Ast; 438 Ast = nullptr; 439 } 440 } 441 442 bool IslAstInfo::runOnScop(Scop &Scop) { 443 if (Ast) 444 delete Ast; 445 446 S = &Scop; 447 448 const Dependences &D = getAnalysis<DependenceInfo>().getDependences(); 449 450 Ast = IslAst::create(&Scop, D); 451 452 DEBUG(printScop(dbgs(), Scop)); 453 return false; 454 } 455 456 __isl_give isl_ast_node *IslAstInfo::getAst() const { return Ast->getAst(); } 457 __isl_give isl_ast_expr *IslAstInfo::getRunCondition() const { 458 return Ast->getRunCondition(); 459 } 460 461 IslAstUserPayload *IslAstInfo::getNodePayload(__isl_keep isl_ast_node *Node) { 462 isl_id *Id = isl_ast_node_get_annotation(Node); 463 if (!Id) 464 return nullptr; 465 IslAstUserPayload *Payload = (IslAstUserPayload *)isl_id_get_user(Id); 466 isl_id_free(Id); 467 return Payload; 468 } 469 470 bool IslAstInfo::isInnermost(__isl_keep isl_ast_node *Node) { 471 IslAstUserPayload *Payload = getNodePayload(Node); 472 return Payload && Payload->IsInnermost; 473 } 474 475 bool IslAstInfo::isParallel(__isl_keep isl_ast_node *Node) { 476 return IslAstInfo::isInnermostParallel(Node) || 477 IslAstInfo::isOutermostParallel(Node); 478 } 479 480 bool IslAstInfo::isInnermostParallel(__isl_keep isl_ast_node *Node) { 481 IslAstUserPayload *Payload = getNodePayload(Node); 482 return Payload && Payload->IsInnermostParallel; 483 } 484 485 bool IslAstInfo::isOutermostParallel(__isl_keep isl_ast_node *Node) { 486 IslAstUserPayload *Payload = getNodePayload(Node); 487 return Payload && Payload->IsOutermostParallel; 488 } 489 490 bool IslAstInfo::isReductionParallel(__isl_keep isl_ast_node *Node) { 491 IslAstUserPayload *Payload = getNodePayload(Node); 492 return Payload && Payload->IsReductionParallel; 493 } 494 495 bool IslAstInfo::isExecutedInParallel(__isl_keep isl_ast_node *Node) { 496 497 if (!PollyParallel) 498 return false; 499 500 // Do not parallelize innermost loops. 501 // 502 // Parallelizing innermost loops is often not profitable, especially if 503 // they have a low number of iterations. 504 // 505 // TODO: Decide this based on the number of loop iterations that will be 506 // executed. This can possibly require run-time checks, which again 507 // raises the question of both run-time check overhead and code size 508 // costs. 509 if (!PollyParallelForce && isInnermost(Node)) 510 return false; 511 512 return isOutermostParallel(Node) && !isReductionParallel(Node); 513 } 514 515 isl_union_map *IslAstInfo::getSchedule(__isl_keep isl_ast_node *Node) { 516 IslAstUserPayload *Payload = getNodePayload(Node); 517 return Payload ? isl_ast_build_get_schedule(Payload->Build) : nullptr; 518 } 519 520 isl_pw_aff * 521 IslAstInfo::getMinimalDependenceDistance(__isl_keep isl_ast_node *Node) { 522 IslAstUserPayload *Payload = getNodePayload(Node); 523 return Payload ? isl_pw_aff_copy(Payload->MinimalDependenceDistance) 524 : nullptr; 525 } 526 527 IslAstInfo::MemoryAccessSet * 528 IslAstInfo::getBrokenReductions(__isl_keep isl_ast_node *Node) { 529 IslAstUserPayload *Payload = getNodePayload(Node); 530 return Payload ? &Payload->BrokenReductions : nullptr; 531 } 532 533 isl_ast_build *IslAstInfo::getBuild(__isl_keep isl_ast_node *Node) { 534 IslAstUserPayload *Payload = getNodePayload(Node); 535 return Payload ? Payload->Build : nullptr; 536 } 537 538 void IslAstInfo::printScop(raw_ostream &OS, Scop &S) const { 539 isl_ast_print_options *Options; 540 isl_ast_node *RootNode = getAst(); 541 Function *F = S.getRegion().getEntry()->getParent(); 542 543 OS << ":: isl ast :: " << F->getName() << " :: " << S.getRegion().getNameStr() 544 << "\n"; 545 546 if (!RootNode) { 547 OS << ":: isl ast generation and code generation was skipped!\n\n"; 548 OS << ":: This is either because no useful optimizations could be applied " 549 "(use -polly-process-unprofitable to enforce code generation) or " 550 "because earlier passes such as dependence analysis timed out (use " 551 "-polly-dependences-computeout=0 to set dependence analysis timeout " 552 "to infinity)\n\n"; 553 return; 554 } 555 556 isl_ast_expr *RunCondition = getRunCondition(); 557 char *RtCStr, *AstStr; 558 559 Options = isl_ast_print_options_alloc(S.getIslCtx()); 560 Options = isl_ast_print_options_set_print_for(Options, cbPrintFor, nullptr); 561 562 isl_printer *P = isl_printer_to_str(S.getIslCtx()); 563 P = isl_printer_print_ast_expr(P, RunCondition); 564 RtCStr = isl_printer_get_str(P); 565 P = isl_printer_flush(P); 566 P = isl_printer_indent(P, 4); 567 P = isl_printer_set_output_format(P, ISL_FORMAT_C); 568 P = isl_ast_node_print(RootNode, P, Options); 569 AstStr = isl_printer_get_str(P); 570 571 isl_union_map *Schedule = 572 isl_union_map_intersect_domain(S.getSchedule(), S.getDomains()); 573 574 DEBUG({ 575 dbgs() << S.getContextStr() << "\n"; 576 dbgs() << stringFromIslObj(Schedule); 577 }); 578 OS << "\nif (" << RtCStr << ")\n\n"; 579 OS << AstStr << "\n"; 580 OS << "else\n"; 581 OS << " { /* original code */ }\n\n"; 582 583 free(RtCStr); 584 free(AstStr); 585 586 isl_ast_expr_free(RunCondition); 587 isl_union_map_free(Schedule); 588 isl_ast_node_free(RootNode); 589 isl_printer_free(P); 590 } 591 592 void IslAstInfo::getAnalysisUsage(AnalysisUsage &AU) const { 593 // Get the Common analysis usage of ScopPasses. 594 ScopPass::getAnalysisUsage(AU); 595 AU.addRequired<ScopInfo>(); 596 AU.addRequired<DependenceInfo>(); 597 } 598 599 char IslAstInfo::ID = 0; 600 601 Pass *polly::createIslAstInfoPass() { return new IslAstInfo(); } 602 603 INITIALIZE_PASS_BEGIN(IslAstInfo, "polly-ast", 604 "Polly - Generate an AST of the SCoP (isl)", false, 605 false); 606 INITIALIZE_PASS_DEPENDENCY(ScopInfo); 607 INITIALIZE_PASS_DEPENDENCY(DependenceInfo); 608 INITIALIZE_PASS_END(IslAstInfo, "polly-ast", 609 "Polly - Generate an AST from the SCoP (isl)", false, false) 610