Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===- polly/ScopBuilder.h --------------------------------------*- C++ -*-===// | 
| 2 | // | ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 6 | // | ||
| 7 | //===----------------------------------------------------------------------===// | ||
| 8 | // | ||
| 9 | // Create a polyhedral description for a static control flow region. | ||
| 10 | // | ||
| 11 | // The pass creates a polyhedral description of the Scops detected by the SCoP | ||
| 12 | // detection derived from their LLVM-IR code. | ||
| 13 | // | ||
| 14 | //===----------------------------------------------------------------------===// | ||
| 15 | |||
| 16 | #ifndef POLLY_SCOPBUILDER_H | ||
| 17 | #define POLLY_SCOPBUILDER_H | ||
| 18 | |||
| 19 | #include "polly/ScopInfo.h" | ||
| 20 | #include "polly/Support/ScopHelper.h" | ||
| 21 | #include "llvm/ADT/ArrayRef.h" | ||
| 22 | #include "llvm/ADT/SetVector.h" | ||
| 23 | |||
| 24 | namespace polly { | ||
| 25 | using llvm::SmallSetVector; | ||
| 26 | |||
| 27 | class ScopDetection; | ||
| 28 | |||
| 29 | /// Command line switch whether to model read-only accesses. | ||
| 30 | extern bool ModelReadOnlyScalars; | ||
| 31 | |||
| 32 | /// Build the Polly IR (Scop and ScopStmt) on a Region. | ||
| 33 | class ScopBuilder final { | ||
| 34 | |||
| 35 |   /// The AAResults to build AliasSetTracker. | ||
| 36 | AAResults &AA; | ||
| 37 | |||
| 38 |   /// Target data for element size computing. | ||
| 39 | const DataLayout &DL; | ||
| 40 | |||
| 41 |   /// DominatorTree to reason about guaranteed execution. | ||
| 42 | DominatorTree &DT; | ||
| 43 | |||
| 44 |   /// LoopInfo for information about loops. | ||
| 45 | LoopInfo &LI; | ||
| 46 | |||
| 47 |   /// Valid Regions for Scop | ||
| 48 | ScopDetection &SD; | ||
| 49 | |||
| 50 |   /// The ScalarEvolution to help building Scop. | ||
| 51 | ScalarEvolution &SE; | ||
| 52 | |||
| 53 |   /// An optimization diagnostic interface to add optimization remarks. | ||
| 54 | OptimizationRemarkEmitter &ORE; | ||
| 55 | |||
| 56 |   /// Set of instructions that might read any memory location. | ||
| 57 | SmallVector<std::pair<ScopStmt *, Instruction *>, 16> GlobalReads; | ||
| 58 | |||
| 59 |   /// Set of all accessed array base pointers. | ||
| 60 | SmallSetVector<Value *, 16> ArrayBasePointers; | ||
| 61 | |||
| 62 |   // The Scop | ||
| 63 | std::unique_ptr<Scop> scop; | ||
| 64 | |||
| 65 |   /// Collection to hold taken assumptions. | ||
| 66 |   /// | ||
| 67 |   /// There are two reasons why we want to record assumptions first before we | ||
| 68 |   /// add them to the assumed/invalid context: | ||
| 69 |   ///   1) If the SCoP is not profitable or otherwise invalid without the | ||
| 70 |   ///      assumed/invalid context we do not have to compute it. | ||
| 71 |   ///   2) Information about the context are gathered rather late in the SCoP | ||
| 72 |   ///      construction (basically after we know all parameters), thus the user | ||
| 73 |   ///      might see overly complicated assumptions to be taken while they will | ||
| 74 |   ///      only be simplified later on. | ||
| 75 |   RecordedAssumptionsTy RecordedAssumptions; | ||
| 76 | |||
| 77 |   // Build the SCoP for Region @p R. | ||
| 78 | void buildScop(Region &R, AssumptionCache &AC); | ||
| 79 | |||
| 80 |   /// Adjust the dimensions of @p Dom that was constructed for @p OldL | ||
| 81 |   ///        to be compatible to domains constructed for loop @p NewL. | ||
| 82 |   /// | ||
| 83 |   /// This function assumes @p NewL and @p OldL are equal or there is a CFG | ||
| 84 |   /// edge from @p OldL to @p NewL. | ||
| 85 | isl::set adjustDomainDimensions(isl::set Dom, Loop *OldL, Loop *NewL); | ||
| 86 | |||
| 87 |   /// Compute the domain for each basic block in @p R. | ||
| 88 |   /// | ||
| 89 |   /// @param R                The region we currently traverse. | ||
| 90 |   /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current | ||
| 91 |   ///                         region. | ||
| 92 |   /// | ||
| 93 |   /// @returns True if there was no problem and false otherwise. | ||
| 94 | bool buildDomains(Region *R, | ||
| 95 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 96 | |||
| 97 |   /// Compute the branching constraints for each basic block in @p R. | ||
| 98 |   /// | ||
| 99 |   /// @param R                The region we currently build branching conditions | ||
| 100 |   ///                         for. | ||
| 101 |   /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current | ||
| 102 |   ///                         region. | ||
| 103 |   /// | ||
| 104 |   /// @returns True if there was no problem and false otherwise. | ||
| 105 | bool buildDomainsWithBranchConstraints( | ||
| 106 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 107 | |||
| 108 |   /// Build the conditions sets for the terminator @p TI in the @p Domain. | ||
| 109 |   /// | ||
| 110 |   /// This will fill @p ConditionSets with the conditions under which control | ||
| 111 |   /// will be moved from @p TI to its successors. Hence, @p ConditionSets will | ||
| 112 |   /// have as many elements as @p TI has successors. | ||
| 113 | bool buildConditionSets(BasicBlock *BB, Instruction *TI, Loop *L, | ||
| 114 |                           __isl_keep isl_set *Domain, | ||
| 115 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, | ||
| 116 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); | ||
| 117 | |||
| 118 |   /// Build the conditions sets for the branch condition @p Condition in | ||
| 119 |   /// the @p Domain. | ||
| 120 |   /// | ||
| 121 |   /// This will fill @p ConditionSets with the conditions under which control | ||
| 122 |   /// will be moved from @p TI to its successors. Hence, @p ConditionSets will | ||
| 123 |   /// have as many elements as @p TI has successors. If @p TI is nullptr the | ||
| 124 |   /// context under which @p Condition is true/false will be returned as the | ||
| 125 |   /// new elements of @p ConditionSets. | ||
| 126 | bool buildConditionSets(BasicBlock *BB, Value *Condition, Instruction *TI, | ||
| 127 | Loop *L, __isl_keep isl_set *Domain, | ||
| 128 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, | ||
| 129 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); | ||
| 130 | |||
| 131 |   /// Build the conditions sets for the switch @p SI in the @p Domain. | ||
| 132 |   /// | ||
| 133 |   /// This will fill @p ConditionSets with the conditions under which control | ||
| 134 |   /// will be moved from @p SI to its successors. Hence, @p ConditionSets will | ||
| 135 |   /// have as many elements as @p SI has successors. | ||
| 136 | bool buildConditionSets(BasicBlock *BB, SwitchInst *SI, Loop *L, | ||
| 137 |                           __isl_keep isl_set *Domain, | ||
| 138 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, | ||
| 139 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); | ||
| 140 | |||
| 141 |   /// Build condition sets for unsigned ICmpInst(s). | ||
| 142 |   /// Special handling is required for unsigned operands to ensure that if | ||
| 143 |   /// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst | ||
| 144 |   /// it should wrap around. | ||
| 145 |   /// | ||
| 146 |   /// @param IsStrictUpperBound holds information on the predicate relation | ||
| 147 |   /// between TestVal and UpperBound, i.e, | ||
| 148 |   /// TestVal < UpperBound  OR  TestVal <= UpperBound | ||
| 149 | __isl_give isl_set *buildUnsignedConditionSets( | ||
| 150 | BasicBlock *BB, Value *Condition, __isl_keep isl_set *Domain, | ||
| 151 | const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound, | ||
| 152 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, | ||
| 153 | bool IsStrictUpperBound); | ||
| 154 | |||
| 155 |   /// Propagate the domain constraints through the region @p R. | ||
| 156 |   /// | ||
| 157 |   /// @param R                The region we currently build branching | ||
| 158 |   /// conditions for. | ||
| 159 |   /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current | ||
| 160 |   ///                         region. | ||
| 161 |   /// | ||
| 162 |   /// @returns True if there was no problem and false otherwise. | ||
| 163 | bool propagateDomainConstraints( | ||
| 164 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 165 | |||
| 166 |   /// Propagate domains that are known due to graph properties. | ||
| 167 |   /// | ||
| 168 |   /// As a CFG is mostly structured we use the graph properties to propagate | ||
| 169 |   /// domains without the need to compute all path conditions. In particular, | ||
| 170 |   /// if a block A dominates a block B and B post-dominates A we know that the | ||
| 171 |   /// domain of B is a superset of the domain of A. As we do not have | ||
| 172 |   /// post-dominator information available here we use the less precise region | ||
| 173 |   /// information. Given a region R, we know that the exit is always executed | ||
| 174 |   /// if the entry was executed, thus the domain of the exit is a superset of | ||
| 175 |   /// the domain of the entry. In case the exit can only be reached from | ||
| 176 |   /// within the region the domains are in fact equal. This function will use | ||
| 177 |   /// this property to avoid the generation of condition constraints that | ||
| 178 |   /// determine when a branch is taken. If @p BB is a region entry block we | ||
| 179 |   /// will propagate its domain to the region exit block. Additionally, we put | ||
| 180 |   /// the region exit block in the @p FinishedExitBlocks set so we can later | ||
| 181 |   /// skip edges from within the region to that block. | ||
| 182 |   /// | ||
| 183 |   /// @param BB                 The block for which the domain is currently | ||
| 184 |   ///                           propagated. | ||
| 185 |   /// @param BBLoop             The innermost affine loop surrounding @p BB. | ||
| 186 |   /// @param FinishedExitBlocks Set of region exits the domain was set for. | ||
| 187 |   /// @param InvalidDomainMap   BB to InvalidDomain map for the BB of current | ||
| 188 |   ///                           region. | ||
| 189 | void propagateDomainConstraintsToRegionExit( | ||
| 190 | BasicBlock *BB, Loop *BBLoop, | ||
| 191 | SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, | ||
| 192 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 193 | |||
| 194 |   /// Propagate invalid domains of statements through @p R. | ||
| 195 |   /// | ||
| 196 |   /// This method will propagate invalid statement domains through @p R and at | ||
| 197 |   /// the same time add error block domains to them. Additionally, the domains | ||
| 198 |   /// of error statements and those only reachable via error statements will | ||
| 199 |   /// be replaced by an empty set. Later those will be removed completely. | ||
| 200 |   /// | ||
| 201 |   /// @param R                The currently traversed region. | ||
| 202 |   /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current | ||
| 203 |   ///                         region. | ||
| 204 |   // | ||
| 205 |   /// @returns True if there was no problem and false otherwise. | ||
| 206 | bool propagateInvalidStmtDomains( | ||
| 207 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 208 | |||
| 209 |   /// Compute the union of predecessor domains for @p BB. | ||
| 210 |   /// | ||
| 211 |   /// To compute the union of all domains of predecessors of @p BB this | ||
| 212 |   /// function applies similar reasoning on the CFG structure as described for | ||
| 213 |   ///   @see propagateDomainConstraintsToRegionExit | ||
| 214 |   /// | ||
| 215 |   /// @param BB     The block for which the predecessor domains are collected. | ||
| 216 |   /// @param Domain The domain under which BB is executed. | ||
| 217 |   /// | ||
| 218 |   /// @returns The domain under which @p BB is executed. | ||
| 219 | isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain); | ||
| 220 | |||
| 221 |   /// Add loop carried constraints to the header block of the loop @p L. | ||
| 222 |   /// | ||
| 223 |   /// @param L                The loop to process. | ||
| 224 |   /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current | ||
| 225 |   ///                         region. | ||
| 226 |   /// | ||
| 227 |   /// @returns True if there was no problem and false otherwise. | ||
| 228 | bool addLoopBoundsToHeaderDomain( | ||
| 229 | Loop *L, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 230 | |||
| 231 |   /// Compute the isl representation for the SCEV @p E in this BB. | ||
| 232 |   /// | ||
| 233 |   /// @param BB               The BB for which isl representation is to be | ||
| 234 |   /// computed. | ||
| 235 |   /// @param InvalidDomainMap A map of BB to their invalid domains. | ||
| 236 |   /// @param E                The SCEV that should be translated. | ||
| 237 |   /// @param NonNegative      Flag to indicate the @p E has to be | ||
| 238 |   /// non-negative. | ||
| 239 |   /// | ||
| 240 |   /// Note that this function will also adjust the invalid context | ||
| 241 |   /// accordingly. | ||
| 242 |   __isl_give isl_pw_aff * | ||
| 243 | getPwAff(BasicBlock *BB, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, | ||
| 244 | const SCEV *E, bool NonNegative = false); | ||
| 245 | |||
| 246 |   /// Create equivalence classes for required invariant accesses. | ||
| 247 |   /// | ||
| 248 |   /// These classes will consolidate multiple required invariant loads from the | ||
| 249 |   /// same address in order to keep the number of dimensions in the SCoP | ||
| 250 |   /// description small. For each such class equivalence class only one | ||
| 251 |   /// representing element, hence one required invariant load, will be chosen | ||
| 252 |   /// and modeled as parameter. The method | ||
| 253 |   /// Scop::getRepresentingInvariantLoadSCEV() will replace each element from an | ||
| 254 |   /// equivalence class with the representing element that is modeled. As a | ||
| 255 |   /// consequence Scop::getIdForParam() will only return an id for the | ||
| 256 |   /// representing element of each equivalence class, thus for each required | ||
| 257 |   /// invariant location. | ||
| 258 | void buildInvariantEquivalenceClasses(); | ||
| 259 | |||
| 260 |   /// Try to build a multi-dimensional fixed sized MemoryAccess from the | ||
| 261 |   /// Load/Store instruction. | ||
| 262 |   /// | ||
| 263 |   /// @param Inst       The Load/Store instruction that access the memory | ||
| 264 |   /// @param Stmt       The parent statement of the instruction | ||
| 265 |   /// | ||
| 266 |   /// @returns True if the access could be built, False otherwise. | ||
| 267 | bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt); | ||
| 268 | |||
| 269 |   /// Try to build a multi-dimensional parametric sized MemoryAccess. | ||
| 270 |   ///        from the Load/Store instruction. | ||
| 271 |   /// | ||
| 272 |   /// @param Inst       The Load/Store instruction that access the memory | ||
| 273 |   /// @param Stmt       The parent statement of the instruction | ||
| 274 |   /// | ||
| 275 |   /// @returns True if the access could be built, False otherwise. | ||
| 276 | bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt); | ||
| 277 | |||
| 278 |   /// Try to build a MemoryAccess for a memory intrinsic. | ||
| 279 |   /// | ||
| 280 |   /// @param Inst       The instruction that access the memory | ||
| 281 |   /// @param Stmt       The parent statement of the instruction | ||
| 282 |   /// | ||
| 283 |   /// @returns True if the access could be built, False otherwise. | ||
| 284 | bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt); | ||
| 285 | |||
| 286 |   /// Try to build a MemoryAccess for a call instruction. | ||
| 287 |   /// | ||
| 288 |   /// @param Inst       The call instruction that access the memory | ||
| 289 |   /// @param Stmt       The parent statement of the instruction | ||
| 290 |   /// | ||
| 291 |   /// @returns True if the access could be built, False otherwise. | ||
| 292 | bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt); | ||
| 293 | |||
| 294 |   /// Build a single-dimensional parametric sized MemoryAccess | ||
| 295 |   ///        from the Load/Store instruction. | ||
| 296 |   /// | ||
| 297 |   /// @param Inst       The Load/Store instruction that access the memory | ||
| 298 |   /// @param Stmt       The parent statement of the instruction | ||
| 299 |   /// | ||
| 300 |   /// @returns True if the access could be built, False otherwise. | ||
| 301 | bool buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt); | ||
| 302 | |||
| 303 |   /// Finalize all access relations. | ||
| 304 |   /// | ||
| 305 |   /// When building up access relations, temporary access relations that | ||
| 306 |   /// correctly represent each individual access are constructed. However, these | ||
| 307 |   /// access relations can be inconsistent or non-optimal when looking at the | ||
| 308 |   /// set of accesses as a whole. This function finalizes the memory accesses | ||
| 309 |   /// and constructs a globally consistent state. | ||
| 310 | void finalizeAccesses(); | ||
| 311 | |||
| 312 |   /// Update access dimensionalities. | ||
| 313 |   /// | ||
| 314 |   /// When detecting memory accesses different accesses to the same array may | ||
| 315 |   /// have built with different dimensionality, as outer zero-values dimensions | ||
| 316 |   /// may not have been recognized as separate dimensions. This function goes | ||
| 317 |   /// again over all memory accesses and updates their dimensionality to match | ||
| 318 |   /// the dimensionality of the underlying ScopArrayInfo object. | ||
| 319 | void updateAccessDimensionality(); | ||
| 320 | |||
| 321 |   /// Fold size constants to the right. | ||
| 322 |   /// | ||
| 323 |   /// In case all memory accesses in a given dimension are multiplied with a | ||
| 324 |   /// common constant, we can remove this constant from the individual access | ||
| 325 |   /// functions and move it to the size of the memory access. We do this as this | ||
| 326 |   /// increases the size of the innermost dimension, consequently widens the | ||
| 327 |   /// valid range the array subscript in this dimension can evaluate to, and | ||
| 328 |   /// as a result increases the likelihood that our delinearization is | ||
| 329 |   /// correct. | ||
| 330 |   /// | ||
| 331 |   /// Example: | ||
| 332 |   /// | ||
| 333 |   ///    A[][n] | ||
| 334 |   ///    S[i,j] -> A[2i][2j+1] | ||
| 335 |   ///    S[i,j] -> A[2i][2j] | ||
| 336 |   /// | ||
| 337 |   ///    => | ||
| 338 |   /// | ||
| 339 |   ///    A[][2n] | ||
| 340 |   ///    S[i,j] -> A[i][2j+1] | ||
| 341 |   ///    S[i,j] -> A[i][2j] | ||
| 342 |   /// | ||
| 343 |   /// Constants in outer dimensions can arise when the elements of a parametric | ||
| 344 |   /// multi-dimensional array are not elementary data types, but e.g., | ||
| 345 |   /// structures. | ||
| 346 | void foldSizeConstantsToRight(); | ||
| 347 | |||
| 348 |   /// Fold memory accesses to handle parametric offset. | ||
| 349 |   /// | ||
| 350 |   /// As a post-processing step, we 'fold' memory accesses to parametric | ||
| 351 |   /// offsets in the access functions. @see MemoryAccess::foldAccess for | ||
| 352 |   /// details. | ||
| 353 | void foldAccessRelations(); | ||
| 354 | |||
| 355 |   /// Assume that all memory accesses are within bounds. | ||
| 356 |   /// | ||
| 357 |   /// After we have built a model of all memory accesses, we need to assume | ||
| 358 |   /// that the model we built matches reality -- aka. all modeled memory | ||
| 359 |   /// accesses always remain within bounds. We do this as last step, after | ||
| 360 |   /// all memory accesses have been modeled and canonicalized. | ||
| 361 | void assumeNoOutOfBounds(); | ||
| 362 | |||
| 363 |   /// Build the alias checks for this SCoP. | ||
| 364 | bool buildAliasChecks(); | ||
| 365 | |||
| 366 |   /// A vector of memory accesses that belong to an alias group. | ||
| 367 | using AliasGroupTy = SmallVector<MemoryAccess *, 4>; | ||
| 368 | |||
| 369 |   /// A vector of alias groups. | ||
| 370 | using AliasGroupVectorTy = SmallVector<AliasGroupTy, 4>; | ||
| 371 | |||
| 372 |   /// Build a given alias group and its access data. | ||
| 373 |   /// | ||
| 374 |   /// @param AliasGroup     The alias group to build. | ||
| 375 |   /// @param HasWriteAccess A set of arrays through which memory is not only | ||
| 376 |   ///                       read, but also written. | ||
| 377 |   // | ||
| 378 |   /// @returns True if __no__ error occurred, false otherwise. | ||
| 379 | bool buildAliasGroup(AliasGroupTy &AliasGroup, | ||
| 380 | DenseSet<const ScopArrayInfo *> HasWriteAccess); | ||
| 381 | |||
| 382 |   /// Build all alias groups for this SCoP. | ||
| 383 |   /// | ||
| 384 |   /// @returns True if __no__ error occurred, false otherwise. | ||
| 385 | bool buildAliasGroups(); | ||
| 386 | |||
| 387 |   /// Build alias groups for all memory accesses in the Scop. | ||
| 388 |   /// | ||
| 389 |   /// Using the alias analysis and an alias set tracker we build alias sets | ||
| 390 |   /// for all memory accesses inside the Scop. For each alias set we then map | ||
| 391 |   /// the aliasing pointers back to the memory accesses we know, thus obtain | ||
| 392 |   /// groups of memory accesses which might alias. We also collect the set of | ||
| 393 |   /// arrays through which memory is written. | ||
| 394 |   /// | ||
| 395 |   /// @returns A pair consistent of a vector of alias groups and a set of arrays | ||
| 396 |   ///          through which memory is written. | ||
| 397 | std::tuple<AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>> | ||
| 398 | buildAliasGroupsForAccesses(); | ||
| 399 | |||
| 400 |   ///  Split alias groups by iteration domains. | ||
| 401 |   /// | ||
| 402 |   ///  We split each group based on the domains of the minimal/maximal accesses. | ||
| 403 |   ///  That means two minimal/maximal accesses are only in a group if their | ||
| 404 |   ///  access domains intersect. Otherwise, they are in different groups. | ||
| 405 |   /// | ||
| 406 |   ///  @param AliasGroups The alias groups to split | ||
| 407 | void splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups); | ||
| 408 | |||
| 409 |   /// Build an instance of MemoryAccess from the Load/Store instruction. | ||
| 410 |   /// | ||
| 411 |   /// @param Inst       The Load/Store instruction that access the memory | ||
| 412 |   /// @param Stmt       The parent statement of the instruction | ||
| 413 | void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt); | ||
| 414 | |||
| 415 |   /// Analyze and extract the cross-BB scalar dependences (or, dataflow | ||
| 416 |   /// dependencies) of an instruction. | ||
| 417 |   /// | ||
| 418 |   /// @param UserStmt The statement @p Inst resides in. | ||
| 419 |   /// @param Inst     The instruction to be analyzed. | ||
| 420 | void buildScalarDependences(ScopStmt *UserStmt, Instruction *Inst); | ||
| 421 | |||
| 422 |   /// Build the escaping dependences for @p Inst. | ||
| 423 |   /// | ||
| 424 |   /// Search for uses of the llvm::Value defined by @p Inst that are not | ||
| 425 |   /// within the SCoP. If there is such use, add a SCALAR WRITE such that | ||
| 426 |   /// it is available after the SCoP as escaping value. | ||
| 427 |   /// | ||
| 428 |   /// @param Inst The instruction to be analyzed. | ||
| 429 | void buildEscapingDependences(Instruction *Inst); | ||
| 430 | |||
| 431 |   /// Create MemoryAccesses for the given PHI node in the given region. | ||
| 432 |   /// | ||
| 433 |   /// @param PHIStmt            The statement @p PHI resides in. | ||
| 434 |   /// @param PHI                The PHI node to be handled | ||
| 435 |   /// @param NonAffineSubRegion The non affine sub-region @p PHI is in. | ||
| 436 |   /// @param IsExitBlock        Flag to indicate that @p PHI is in the exit BB. | ||
| 437 | void buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, | ||
| 438 | Region *NonAffineSubRegion, bool IsExitBlock = false); | ||
| 439 | |||
| 440 |   /// Build the access functions for the subregion @p SR. | ||
| 441 | void buildAccessFunctions(); | ||
| 442 | |||
| 443 |   /// Should an instruction be modeled in a ScopStmt. | ||
| 444 |   /// | ||
| 445 |   /// @param Inst The instruction to check. | ||
| 446 |   /// @param L    The loop in which context the instruction is looked at. | ||
| 447 |   /// | ||
| 448 |   /// @returns True if the instruction should be modeled. | ||
| 449 | bool shouldModelInst(Instruction *Inst, Loop *L); | ||
| 450 | |||
| 451 |   /// Create one or more ScopStmts for @p BB. | ||
| 452 |   /// | ||
| 453 |   /// Consecutive instructions are associated to the same statement until a | ||
| 454 |   /// separator is found. | ||
| 455 | void buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore = false); | ||
| 456 | |||
| 457 |   /// Create one or more ScopStmts for @p BB using equivalence classes. | ||
| 458 |   /// | ||
| 459 |   /// Instructions of a basic block that belong to the same equivalence class | ||
| 460 |   /// are added to the same statement. | ||
| 461 | void buildEqivClassBlockStmts(BasicBlock *BB); | ||
| 462 | |||
| 463 |   /// Create ScopStmt for all BBs and non-affine subregions of @p SR. | ||
| 464 |   /// | ||
| 465 |   /// @param SR A subregion of @p R. | ||
| 466 |   /// | ||
| 467 |   /// Some of the statements might be optimized away later when they do not | ||
| 468 |   /// access any memory and thus have no effect. | ||
| 469 | void buildStmts(Region &SR); | ||
| 470 | |||
| 471 |   /// Build the access functions for the statement @p Stmt in or represented by | ||
| 472 |   /// @p BB. | ||
| 473 |   /// | ||
| 474 |   /// @param Stmt               Statement to add MemoryAccesses to. | ||
| 475 |   /// @param BB                 A basic block in @p R. | ||
| 476 |   /// @param NonAffineSubRegion The non affine sub-region @p BB is in. | ||
| 477 | void buildAccessFunctions(ScopStmt *Stmt, BasicBlock &BB, | ||
| 478 | Region *NonAffineSubRegion = nullptr); | ||
| 479 | |||
| 480 |   /// Create a new MemoryAccess object and add it to #AccFuncMap. | ||
| 481 |   /// | ||
| 482 |   /// @param Stmt        The statement where the access takes place. | ||
| 483 |   /// @param Inst        The instruction doing the access. It is not necessarily | ||
| 484 |   ///                    inside @p BB. | ||
| 485 |   /// @param AccType     The kind of access. | ||
| 486 |   /// @param BaseAddress The accessed array's base address. | ||
| 487 |   /// @param ElemType    The type of the accessed array elements. | ||
| 488 |   /// @param Affine      Whether all subscripts are affine expressions. | ||
| 489 |   /// @param AccessValue Value read or written. | ||
| 490 |   /// @param Subscripts  Access subscripts per dimension. | ||
| 491 |   /// @param Sizes       The array dimension's sizes. | ||
| 492 |   /// @param Kind        The kind of memory accessed. | ||
| 493 |   /// | ||
| 494 |   /// @return The created MemoryAccess, or nullptr if the access is not within | ||
| 495 |   ///         the SCoP. | ||
| 496 | MemoryAccess *addMemoryAccess(ScopStmt *Stmt, Instruction *Inst, | ||
| 497 | MemoryAccess::AccessType AccType, | ||
| 498 | Value *BaseAddress, Type *ElemType, bool Affine, | ||
| 499 |                                 Value *AccessValue, | ||
| 500 | ArrayRef<const SCEV *> Subscripts, | ||
| 501 | ArrayRef<const SCEV *> Sizes, MemoryKind Kind); | ||
| 502 | |||
| 503 |   /// Create a MemoryAccess that represents either a LoadInst or | ||
| 504 |   /// StoreInst. | ||
| 505 |   /// | ||
| 506 |   /// @param Stmt        The statement to add the MemoryAccess to. | ||
| 507 |   /// @param MemAccInst  The LoadInst or StoreInst. | ||
| 508 |   /// @param AccType     The kind of access. | ||
| 509 |   /// @param BaseAddress The accessed array's base address. | ||
| 510 |   /// @param ElemType    The type of the accessed array elements. | ||
| 511 |   /// @param IsAffine    Whether all subscripts are affine expressions. | ||
| 512 |   /// @param Subscripts  Access subscripts per dimension. | ||
| 513 |   /// @param Sizes       The array dimension's sizes. | ||
| 514 |   /// @param AccessValue Value read or written. | ||
| 515 |   /// | ||
| 516 |   /// @see MemoryKind | ||
| 517 | void addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst, | ||
| 518 | MemoryAccess::AccessType AccType, Value *BaseAddress, | ||
| 519 | Type *ElemType, bool IsAffine, | ||
| 520 | ArrayRef<const SCEV *> Subscripts, | ||
| 521 | ArrayRef<const SCEV *> Sizes, Value *AccessValue); | ||
| 522 | |||
| 523 |   /// Create a MemoryAccess for writing an llvm::Instruction. | ||
| 524 |   /// | ||
| 525 |   /// The access will be created at the position of @p Inst. | ||
| 526 |   /// | ||
| 527 |   /// @param Inst The instruction to be written. | ||
| 528 |   /// | ||
| 529 |   /// @see ensureValueRead() | ||
| 530 |   /// @see MemoryKind | ||
| 531 | void ensureValueWrite(Instruction *Inst); | ||
| 532 | |||
| 533 |   /// Ensure an llvm::Value is available in the BB's statement, creating a | ||
| 534 |   /// MemoryAccess for reloading it if necessary. | ||
| 535 |   /// | ||
| 536 |   /// @param V        The value expected to be loaded. | ||
| 537 |   /// @param UserStmt Where to reload the value. | ||
| 538 |   /// | ||
| 539 |   /// @see ensureValueStore() | ||
| 540 |   /// @see MemoryKind | ||
| 541 | void ensureValueRead(Value *V, ScopStmt *UserStmt); | ||
| 542 | |||
| 543 |   /// Create a write MemoryAccess for the incoming block of a phi node. | ||
| 544 |   /// | ||
| 545 |   /// Each of the incoming blocks write their incoming value to be picked in the | ||
| 546 |   /// phi's block. | ||
| 547 |   /// | ||
| 548 |   /// @param PHI           PHINode under consideration. | ||
| 549 |   /// @param IncomingStmt  The statement to add the MemoryAccess to. | ||
| 550 |   /// @param IncomingBlock Some predecessor block. | ||
| 551 |   /// @param IncomingValue @p PHI's value when coming from @p IncomingBlock. | ||
| 552 |   /// @param IsExitBlock   When true, uses the .s2a alloca instead of the | ||
| 553 |   ///                      .phiops one. Required for values escaping through a | ||
| 554 |   ///                      PHINode in the SCoP region's exit block. | ||
| 555 |   /// @see addPHIReadAccess() | ||
| 556 |   /// @see MemoryKind | ||
| 557 | void ensurePHIWrite(PHINode *PHI, ScopStmt *IncomintStmt, | ||
| 558 | BasicBlock *IncomingBlock, Value *IncomingValue, | ||
| 559 | bool IsExitBlock); | ||
| 560 | |||
| 561 |   /// Add user provided parameter constraints to context (command line). | ||
| 562 | void addUserContext(); | ||
| 563 | |||
| 564 |   /// Add user provided parameter constraints to context (source code). | ||
| 565 | void addUserAssumptions(AssumptionCache &AC, | ||
| 566 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); | ||
| 567 | |||
| 568 |   /// Add all recorded assumptions to the assumed context. | ||
| 569 | void addRecordedAssumptions(); | ||
| 570 | |||
| 571 |   /// Create a MemoryAccess for reading the value of a phi. | ||
| 572 |   /// | ||
| 573 |   /// The modeling assumes that all incoming blocks write their incoming value | ||
| 574 |   /// to the same location. Thus, this access will read the incoming block's | ||
| 575 |   /// value as instructed by this @p PHI. | ||
| 576 |   /// | ||
| 577 |   /// @param PHIStmt Statement @p PHI resides in. | ||
| 578 |   /// @param PHI     PHINode under consideration; the READ access will be added | ||
| 579 |   ///                here. | ||
| 580 |   /// | ||
| 581 |   /// @see ensurePHIWrite() | ||
| 582 |   /// @see MemoryKind | ||
| 583 | void addPHIReadAccess(ScopStmt *PHIStmt, PHINode *PHI); | ||
| 584 | |||
| 585 |   /// Wrapper function to calculate minimal/maximal accesses to each array. | ||
| 586 | bool calculateMinMaxAccess(AliasGroupTy AliasGroup, | ||
| 587 | Scop::MinMaxVectorTy &MinMaxAccesses); | ||
| 588 |   /// Build the domain of @p Stmt. | ||
| 589 | void buildDomain(ScopStmt &Stmt); | ||
| 590 | |||
| 591 |   /// Fill NestLoops with loops surrounding @p Stmt. | ||
| 592 | void collectSurroundingLoops(ScopStmt &Stmt); | ||
| 593 | |||
| 594 |   /// Check for reductions in @p Stmt. | ||
| 595 |   /// | ||
| 596 |   /// Iterate over all store memory accesses and check for valid binary | ||
| 597 |   /// reduction like chains. For all candidates we check if they have the same | ||
| 598 |   /// base address and there are no other accesses which overlap with them. The | ||
| 599 |   /// base address check rules out impossible reductions candidates early. The | ||
| 600 |   /// overlap check, together with the "only one user" check in | ||
| 601 |   /// collectCandidateReductionLoads, guarantees that none of the intermediate | ||
| 602 |   /// results will escape during execution of the loop nest. We basically check | ||
| 603 |   /// here that no other memory access can access the same memory as the | ||
| 604 |   /// potential reduction. | ||
| 605 | void checkForReductions(ScopStmt &Stmt); | ||
| 606 | |||
| 607 |   /// Verify that all required invariant loads have been hoisted. | ||
| 608 |   /// | ||
| 609 |   /// Invariant load hoisting is not guaranteed to hoist all loads that were | ||
| 610 |   /// assumed to be scop invariant during scop detection. This function checks | ||
| 611 |   /// for cases where the hoisting failed, but where it would have been | ||
| 612 |   /// necessary for our scop modeling to be correct. In case of insufficient | ||
| 613 |   /// hoisting the scop is marked as invalid. | ||
| 614 |   /// | ||
| 615 |   /// In the example below Bound[1] is required to be invariant: | ||
| 616 |   /// | ||
| 617 |   /// for (int i = 1; i < Bound[0]; i++) | ||
| 618 |   ///   for (int j = 1; j < Bound[1]; j++) | ||
| 619 |   ///     ... | ||
| 620 | void verifyInvariantLoads(); | ||
| 621 | |||
| 622 |   /// Hoist invariant memory loads and check for required ones. | ||
| 623 |   /// | ||
| 624 |   /// We first identify "common" invariant loads, thus loads that are invariant | ||
| 625 |   /// and can be hoisted. Then we check if all required invariant loads have | ||
| 626 |   /// been identified as (common) invariant. A load is a required invariant load | ||
| 627 |   /// if it was assumed to be invariant during SCoP detection, e.g., to assume | ||
| 628 |   /// loop bounds to be affine or runtime alias checks to be placeable. In case | ||
| 629 |   /// a required invariant load was not identified as (common) invariant we will | ||
| 630 |   /// drop this SCoP. An example for both "common" as well as required invariant | ||
| 631 |   /// loads is given below: | ||
| 632 |   /// | ||
| 633 |   /// for (int i = 1; i < *LB[0]; i++) | ||
| 634 |   ///   for (int j = 1; j < *LB[1]; j++) | ||
| 635 |   ///     A[i][j] += A[0][0] + (*V); | ||
| 636 |   /// | ||
| 637 |   /// Common inv. loads: V, A[0][0], LB[0], LB[1] | ||
| 638 |   /// Required inv. loads: LB[0], LB[1], (V, if it may alias with A or LB) | ||
| 639 | void hoistInvariantLoads(); | ||
| 640 | |||
| 641 |   /// Add invariant loads listed in @p InvMAs with the domain of @p Stmt. | ||
| 642 | void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs); | ||
| 643 | |||
| 644 |   /// Check if @p MA can always be hoisted without execution context. | ||
| 645 | bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, | ||
| 646 |                           bool MAInvalidCtxIsEmpty, | ||
| 647 | bool NonHoistableCtxIsEmpty); | ||
| 648 | |||
| 649 |   /// Return true if and only if @p LI is a required invariant load. | ||
| 650 | bool isRequiredInvariantLoad(LoadInst *LI) const { | ||
| 651 | return scop->getRequiredInvariantLoads().count(LI); | ||
| 652 |   } | ||
| 653 | |||
| 654 |   /// Check if the base ptr of @p MA is in the SCoP but not hoistable. | ||
| 655 | bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes); | ||
| 656 | |||
| 657 |   /// Return the context under which the access cannot be hoisted. | ||
| 658 |   /// | ||
| 659 |   /// @param Access The access to check. | ||
| 660 |   /// @param Writes The set of all memory writes in the scop. | ||
| 661 |   /// | ||
| 662 |   /// @return Return the context under which the access cannot be hoisted or a | ||
| 663 |   ///         nullptr if it cannot be hoisted at all. | ||
| 664 | isl::set getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes); | ||
| 665 | |||
| 666 |   /// Collect loads which might form a reduction chain with @p StoreMA. | ||
| 667 |   /// | ||
| 668 |   /// Check if the stored value for @p StoreMA is a binary operator with one or | ||
| 669 |   /// two loads as operands. If the binary operand is commutative & associative, | ||
| 670 |   /// used only once (by @p StoreMA) and its load operands are also used only | ||
| 671 |   /// once, we have found a possible reduction chain. It starts at an operand | ||
| 672 |   /// load and includes the binary operator and @p StoreMA. | ||
| 673 |   /// | ||
| 674 |   /// Note: We allow only one use to ensure the load and binary operator cannot | ||
| 675 |   ///       escape this block or into any other store except @p StoreMA. | ||
| 676 | void collectCandidateReductionLoads(MemoryAccess *StoreMA, | ||
| 677 | SmallVectorImpl<MemoryAccess *> &Loads); | ||
| 678 | |||
| 679 |   /// Build the access relation of all memory accesses of @p Stmt. | ||
| 680 | void buildAccessRelations(ScopStmt &Stmt); | ||
| 681 | |||
| 682 |   /// Canonicalize arrays with base pointers from the same equivalence class. | ||
| 683 |   /// | ||
| 684 |   /// Some context: in our normal model we assume that each base pointer is | ||
| 685 |   /// related to a single specific memory region, where memory regions | ||
| 686 |   /// associated with different base pointers are disjoint. Consequently we do | ||
| 687 |   /// not need to compute additional data dependences that model possible | ||
| 688 |   /// overlaps of these memory regions. To verify our assumption we compute | ||
| 689 |   /// alias checks that verify that modeled arrays indeed do not overlap. In | ||
| 690 |   /// case an overlap is detected the runtime check fails and we fall back to | ||
| 691 |   /// the original code. | ||
| 692 |   /// | ||
| 693 |   /// In case of arrays where the base pointers are know to be identical, | ||
| 694 |   /// because they are dynamically loaded by accesses that are in the same | ||
| 695 |   /// invariant load equivalence class, such run-time alias check would always | ||
| 696 |   /// be false. | ||
| 697 |   /// | ||
| 698 |   /// This function makes sure that we do not generate consistently failing | ||
| 699 |   /// run-time checks for code that contains distinct arrays with known | ||
| 700 |   /// equivalent base pointers. It identifies for each invariant load | ||
| 701 |   /// equivalence class a single canonical array and canonicalizes all memory | ||
| 702 |   /// accesses that reference arrays that have base pointers that are known to | ||
| 703 |   /// be equal to the base pointer of such a canonical array to this canonical | ||
| 704 |   /// array. | ||
| 705 |   /// | ||
| 706 |   /// We currently do not canonicalize arrays for which certain memory accesses | ||
| 707 |   /// have been hoisted as loop invariant. | ||
| 708 | void canonicalizeDynamicBasePtrs(); | ||
| 709 | |||
| 710 |   /// Construct the schedule of this SCoP. | ||
| 711 | void buildSchedule(); | ||
| 712 | |||
| 713 |   /// A loop stack element to keep track of per-loop information during | ||
| 714 |   ///        schedule construction. | ||
| 715 | using LoopStackElementTy = struct LoopStackElement { | ||
| 716 |     // The loop for which we keep information. | ||
| 717 | Loop *L; | ||
| 718 | |||
| 719 |     // The (possibly incomplete) schedule for this loop. | ||
| 720 | isl::schedule Schedule; | ||
| 721 | |||
| 722 |     // The number of basic blocks in the current loop, for which a schedule has | ||
| 723 |     // already been constructed. | ||
| 724 | unsigned NumBlocksProcessed; | ||
| 725 | |||
| 726 | LoopStackElement(Loop *L, isl::schedule S, unsigned NumBlocksProcessed) | ||
| 727 | : L(L), Schedule(S), NumBlocksProcessed(NumBlocksProcessed) {} | ||
| 728 | }; | ||
| 729 | |||
| 730 |   /// The loop stack used for schedule construction. | ||
| 731 |   /// | ||
| 732 |   /// The loop stack keeps track of schedule information for a set of nested | ||
| 733 |   /// loops as well as an (optional) 'nullptr' loop that models the outermost | ||
| 734 |   /// schedule dimension. The loops in a loop stack always have a parent-child | ||
| 735 |   /// relation where the loop at position n is the parent of the loop at | ||
| 736 |   /// position n + 1. | ||
| 737 | using LoopStackTy = SmallVector<LoopStackElementTy, 4>; | ||
| 738 | |||
| 739 |   /// Construct schedule information for a given Region and add the | ||
| 740 |   ///        derived information to @p LoopStack. | ||
| 741 |   /// | ||
| 742 |   /// Given a Region we derive schedule information for all RegionNodes | ||
| 743 |   /// contained in this region ensuring that the assigned execution times | ||
| 744 |   /// correctly model the existing control flow relations. | ||
| 745 |   /// | ||
| 746 |   /// @param R              The region which to process. | ||
| 747 |   /// @param LoopStack      A stack of loops that are currently under | ||
| 748 |   ///                       construction. | ||
| 749 | void buildSchedule(Region *R, LoopStackTy &LoopStack); | ||
| 750 | |||
| 751 |   /// Build Schedule for the region node @p RN and add the derived | ||
| 752 |   ///        information to @p LoopStack. | ||
| 753 |   /// | ||
| 754 |   /// In case @p RN is a BasicBlock or a non-affine Region, we construct the | ||
| 755 |   /// schedule for this @p RN and also finalize loop schedules in case the | ||
| 756 |   /// current @p RN completes the loop. | ||
| 757 |   /// | ||
| 758 |   /// In case @p RN is a not-non-affine Region, we delegate the construction to | ||
| 759 |   /// buildSchedule(Region *R, ...). | ||
| 760 |   /// | ||
| 761 |   /// @param RN             The RegionNode region traversed. | ||
| 762 |   /// @param LoopStack      A stack of loops that are currently under | ||
| 763 |   ///                       construction. | ||
| 764 | void buildSchedule(RegionNode *RN, LoopStackTy &LoopStack); | ||
| 765 | |||
| 766 | public: | ||
| 767 | explicit ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, | ||
| 768 | const DataLayout &DL, DominatorTree &DT, LoopInfo &LI, | ||
| 769 | ScopDetection &SD, ScalarEvolution &SE, | ||
| 770 | OptimizationRemarkEmitter &ORE); | ||
| 771 | ScopBuilder(const ScopBuilder &) = delete; | ||
| 772 | ScopBuilder &operator=(const ScopBuilder &) = delete; | ||
| 773 | ~ScopBuilder() = default; | ||
| 774 | |||
| 775 |   /// Try to build the Polly IR of static control part on the current | ||
| 776 |   /// SESE-Region. | ||
| 777 |   /// | ||
| 778 |   /// @return Give up the ownership of the scop object or static control part | ||
| 779 |   ///         for the region | ||
| 780 | std::unique_ptr<Scop> getScop() { return std::move(scop); } | ||
| 781 | }; | ||
| 782 | } // end namespace polly | ||
| 783 | |||
| 784 | #endif // POLLY_SCOPBUILDER_H |