|
|
|||
File indexing completed on 2026-05-10 08:48:20
0001 //===- polly/ScopBuilder.h --------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // Create a polyhedral description for a static control flow region. 0010 // 0011 // The pass creates a polyhedral description of the Scops detected by the SCoP 0012 // detection derived from their LLVM-IR code. 0013 // 0014 //===----------------------------------------------------------------------===// 0015 0016 #ifndef POLLY_SCOPBUILDER_H 0017 #define POLLY_SCOPBUILDER_H 0018 0019 #include "polly/ScopInfo.h" 0020 #include "polly/Support/ScopHelper.h" 0021 #include "llvm/ADT/ArrayRef.h" 0022 #include "llvm/ADT/SetVector.h" 0023 0024 namespace polly { 0025 using llvm::SmallSetVector; 0026 0027 class ScopDetection; 0028 0029 /// Command line switch whether to model read-only accesses. 0030 extern bool ModelReadOnlyScalars; 0031 0032 /// Build the Polly IR (Scop and ScopStmt) on a Region. 0033 class ScopBuilder final { 0034 0035 /// The AAResults to build AliasSetTracker. 0036 AAResults &AA; 0037 0038 /// Target data for element size computing. 0039 const DataLayout &DL; 0040 0041 /// DominatorTree to reason about guaranteed execution. 0042 DominatorTree &DT; 0043 0044 /// LoopInfo for information about loops. 0045 LoopInfo &LI; 0046 0047 /// Valid Regions for Scop 0048 ScopDetection &SD; 0049 0050 /// The ScalarEvolution to help building Scop. 0051 ScalarEvolution &SE; 0052 0053 /// An optimization diagnostic interface to add optimization remarks. 0054 OptimizationRemarkEmitter &ORE; 0055 0056 /// Set of instructions that might read any memory location. 0057 SmallVector<std::pair<ScopStmt *, Instruction *>, 16> GlobalReads; 0058 0059 /// Set of all accessed array base pointers. 0060 SmallSetVector<Value *, 16> ArrayBasePointers; 0061 0062 // The Scop 0063 std::unique_ptr<Scop> scop; 0064 0065 /// Collection to hold taken assumptions. 0066 /// 0067 /// There are two reasons why we want to record assumptions first before we 0068 /// add them to the assumed/invalid context: 0069 /// 1) If the SCoP is not profitable or otherwise invalid without the 0070 /// assumed/invalid context we do not have to compute it. 0071 /// 2) Information about the context are gathered rather late in the SCoP 0072 /// construction (basically after we know all parameters), thus the user 0073 /// might see overly complicated assumptions to be taken while they will 0074 /// only be simplified later on. 0075 RecordedAssumptionsTy RecordedAssumptions; 0076 0077 // Build the SCoP for Region @p R. 0078 void buildScop(Region &R, AssumptionCache &AC); 0079 0080 /// Adjust the dimensions of @p Dom that was constructed for @p OldL 0081 /// to be compatible to domains constructed for loop @p NewL. 0082 /// 0083 /// This function assumes @p NewL and @p OldL are equal or there is a CFG 0084 /// edge from @p OldL to @p NewL. 0085 isl::set adjustDomainDimensions(isl::set Dom, Loop *OldL, Loop *NewL); 0086 0087 /// Compute the domain for each basic block in @p R. 0088 /// 0089 /// @param R The region we currently traverse. 0090 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0091 /// region. 0092 /// 0093 /// @returns True if there was no problem and false otherwise. 0094 bool buildDomains(Region *R, 0095 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0096 0097 /// Compute the branching constraints for each basic block in @p R. 0098 /// 0099 /// @param R The region we currently build branching conditions 0100 /// for. 0101 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0102 /// region. 0103 /// 0104 /// @returns True if there was no problem and false otherwise. 0105 bool buildDomainsWithBranchConstraints( 0106 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0107 0108 /// Build the conditions sets for the terminator @p TI in the @p Domain. 0109 /// 0110 /// This will fill @p ConditionSets with the conditions under which control 0111 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 0112 /// have as many elements as @p TI has successors. 0113 bool buildConditionSets(BasicBlock *BB, Instruction *TI, Loop *L, 0114 __isl_keep isl_set *Domain, 0115 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 0116 SmallVectorImpl<__isl_give isl_set *> &ConditionSets); 0117 0118 /// Build the conditions sets for the branch condition @p Condition in 0119 /// the @p Domain. 0120 /// 0121 /// This will fill @p ConditionSets with the conditions under which control 0122 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 0123 /// have as many elements as @p TI has successors. If @p TI is nullptr the 0124 /// context under which @p Condition is true/false will be returned as the 0125 /// new elements of @p ConditionSets. 0126 bool buildConditionSets(BasicBlock *BB, Value *Condition, Instruction *TI, 0127 Loop *L, __isl_keep isl_set *Domain, 0128 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 0129 SmallVectorImpl<__isl_give isl_set *> &ConditionSets); 0130 0131 /// Build the conditions sets for the switch @p SI in the @p Domain. 0132 /// 0133 /// This will fill @p ConditionSets with the conditions under which control 0134 /// will be moved from @p SI to its successors. Hence, @p ConditionSets will 0135 /// have as many elements as @p SI has successors. 0136 bool buildConditionSets(BasicBlock *BB, SwitchInst *SI, Loop *L, 0137 __isl_keep isl_set *Domain, 0138 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 0139 SmallVectorImpl<__isl_give isl_set *> &ConditionSets); 0140 0141 /// Build condition sets for unsigned ICmpInst(s). 0142 /// Special handling is required for unsigned operands to ensure that if 0143 /// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst 0144 /// it should wrap around. 0145 /// 0146 /// @param IsStrictUpperBound holds information on the predicate relation 0147 /// between TestVal and UpperBound, i.e, 0148 /// TestVal < UpperBound OR TestVal <= UpperBound 0149 __isl_give isl_set *buildUnsignedConditionSets( 0150 BasicBlock *BB, Value *Condition, __isl_keep isl_set *Domain, 0151 const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound, 0152 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 0153 bool IsStrictUpperBound); 0154 0155 /// Propagate the domain constraints through the region @p R. 0156 /// 0157 /// @param R The region we currently build branching 0158 /// conditions for. 0159 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0160 /// region. 0161 /// 0162 /// @returns True if there was no problem and false otherwise. 0163 bool propagateDomainConstraints( 0164 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0165 0166 /// Propagate domains that are known due to graph properties. 0167 /// 0168 /// As a CFG is mostly structured we use the graph properties to propagate 0169 /// domains without the need to compute all path conditions. In particular, 0170 /// if a block A dominates a block B and B post-dominates A we know that the 0171 /// domain of B is a superset of the domain of A. As we do not have 0172 /// post-dominator information available here we use the less precise region 0173 /// information. Given a region R, we know that the exit is always executed 0174 /// if the entry was executed, thus the domain of the exit is a superset of 0175 /// the domain of the entry. In case the exit can only be reached from 0176 /// within the region the domains are in fact equal. This function will use 0177 /// this property to avoid the generation of condition constraints that 0178 /// determine when a branch is taken. If @p BB is a region entry block we 0179 /// will propagate its domain to the region exit block. Additionally, we put 0180 /// the region exit block in the @p FinishedExitBlocks set so we can later 0181 /// skip edges from within the region to that block. 0182 /// 0183 /// @param BB The block for which the domain is currently 0184 /// propagated. 0185 /// @param BBLoop The innermost affine loop surrounding @p BB. 0186 /// @param FinishedExitBlocks Set of region exits the domain was set for. 0187 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0188 /// region. 0189 void propagateDomainConstraintsToRegionExit( 0190 BasicBlock *BB, Loop *BBLoop, 0191 SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, 0192 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0193 0194 /// Propagate invalid domains of statements through @p R. 0195 /// 0196 /// This method will propagate invalid statement domains through @p R and at 0197 /// the same time add error block domains to them. Additionally, the domains 0198 /// of error statements and those only reachable via error statements will 0199 /// be replaced by an empty set. Later those will be removed completely. 0200 /// 0201 /// @param R The currently traversed region. 0202 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0203 /// region. 0204 // 0205 /// @returns True if there was no problem and false otherwise. 0206 bool propagateInvalidStmtDomains( 0207 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0208 0209 /// Compute the union of predecessor domains for @p BB. 0210 /// 0211 /// To compute the union of all domains of predecessors of @p BB this 0212 /// function applies similar reasoning on the CFG structure as described for 0213 /// @see propagateDomainConstraintsToRegionExit 0214 /// 0215 /// @param BB The block for which the predecessor domains are collected. 0216 /// @param Domain The domain under which BB is executed. 0217 /// 0218 /// @returns The domain under which @p BB is executed. 0219 isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain); 0220 0221 /// Add loop carried constraints to the header block of the loop @p L. 0222 /// 0223 /// @param L The loop to process. 0224 /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current 0225 /// region. 0226 /// 0227 /// @returns True if there was no problem and false otherwise. 0228 bool addLoopBoundsToHeaderDomain( 0229 Loop *L, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0230 0231 /// Compute the isl representation for the SCEV @p E in this BB. 0232 /// 0233 /// @param BB The BB for which isl representation is to be 0234 /// computed. 0235 /// @param InvalidDomainMap A map of BB to their invalid domains. 0236 /// @param E The SCEV that should be translated. 0237 /// @param NonNegative Flag to indicate the @p E has to be 0238 /// non-negative. 0239 /// 0240 /// Note that this function will also adjust the invalid context 0241 /// accordingly. 0242 __isl_give isl_pw_aff * 0243 getPwAff(BasicBlock *BB, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 0244 const SCEV *E, bool NonNegative = false); 0245 0246 /// Create equivalence classes for required invariant accesses. 0247 /// 0248 /// These classes will consolidate multiple required invariant loads from the 0249 /// same address in order to keep the number of dimensions in the SCoP 0250 /// description small. For each such class equivalence class only one 0251 /// representing element, hence one required invariant load, will be chosen 0252 /// and modeled as parameter. The method 0253 /// Scop::getRepresentingInvariantLoadSCEV() will replace each element from an 0254 /// equivalence class with the representing element that is modeled. As a 0255 /// consequence Scop::getIdForParam() will only return an id for the 0256 /// representing element of each equivalence class, thus for each required 0257 /// invariant location. 0258 void buildInvariantEquivalenceClasses(); 0259 0260 /// Try to build a multi-dimensional fixed sized MemoryAccess from the 0261 /// Load/Store instruction. 0262 /// 0263 /// @param Inst The Load/Store instruction that access the memory 0264 /// @param Stmt The parent statement of the instruction 0265 /// 0266 /// @returns True if the access could be built, False otherwise. 0267 bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt); 0268 0269 /// Try to build a multi-dimensional parametric sized MemoryAccess. 0270 /// from the Load/Store instruction. 0271 /// 0272 /// @param Inst The Load/Store instruction that access the memory 0273 /// @param Stmt The parent statement of the instruction 0274 /// 0275 /// @returns True if the access could be built, False otherwise. 0276 bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt); 0277 0278 /// Try to build a MemoryAccess for a memory intrinsic. 0279 /// 0280 /// @param Inst The instruction that access the memory 0281 /// @param Stmt The parent statement of the instruction 0282 /// 0283 /// @returns True if the access could be built, False otherwise. 0284 bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt); 0285 0286 /// Try to build a MemoryAccess for a call instruction. 0287 /// 0288 /// @param Inst The call instruction that access the memory 0289 /// @param Stmt The parent statement of the instruction 0290 /// 0291 /// @returns True if the access could be built, False otherwise. 0292 bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt); 0293 0294 /// Build a single-dimensional parametric sized MemoryAccess 0295 /// from the Load/Store instruction. 0296 /// 0297 /// @param Inst The Load/Store instruction that access the memory 0298 /// @param Stmt The parent statement of the instruction 0299 /// 0300 /// @returns True if the access could be built, False otherwise. 0301 bool buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt); 0302 0303 /// Finalize all access relations. 0304 /// 0305 /// When building up access relations, temporary access relations that 0306 /// correctly represent each individual access are constructed. However, these 0307 /// access relations can be inconsistent or non-optimal when looking at the 0308 /// set of accesses as a whole. This function finalizes the memory accesses 0309 /// and constructs a globally consistent state. 0310 void finalizeAccesses(); 0311 0312 /// Update access dimensionalities. 0313 /// 0314 /// When detecting memory accesses different accesses to the same array may 0315 /// have built with different dimensionality, as outer zero-values dimensions 0316 /// may not have been recognized as separate dimensions. This function goes 0317 /// again over all memory accesses and updates their dimensionality to match 0318 /// the dimensionality of the underlying ScopArrayInfo object. 0319 void updateAccessDimensionality(); 0320 0321 /// Fold size constants to the right. 0322 /// 0323 /// In case all memory accesses in a given dimension are multiplied with a 0324 /// common constant, we can remove this constant from the individual access 0325 /// functions and move it to the size of the memory access. We do this as this 0326 /// increases the size of the innermost dimension, consequently widens the 0327 /// valid range the array subscript in this dimension can evaluate to, and 0328 /// as a result increases the likelihood that our delinearization is 0329 /// correct. 0330 /// 0331 /// Example: 0332 /// 0333 /// A[][n] 0334 /// S[i,j] -> A[2i][2j+1] 0335 /// S[i,j] -> A[2i][2j] 0336 /// 0337 /// => 0338 /// 0339 /// A[][2n] 0340 /// S[i,j] -> A[i][2j+1] 0341 /// S[i,j] -> A[i][2j] 0342 /// 0343 /// Constants in outer dimensions can arise when the elements of a parametric 0344 /// multi-dimensional array are not elementary data types, but e.g., 0345 /// structures. 0346 void foldSizeConstantsToRight(); 0347 0348 /// Fold memory accesses to handle parametric offset. 0349 /// 0350 /// As a post-processing step, we 'fold' memory accesses to parametric 0351 /// offsets in the access functions. @see MemoryAccess::foldAccess for 0352 /// details. 0353 void foldAccessRelations(); 0354 0355 /// Assume that all memory accesses are within bounds. 0356 /// 0357 /// After we have built a model of all memory accesses, we need to assume 0358 /// that the model we built matches reality -- aka. all modeled memory 0359 /// accesses always remain within bounds. We do this as last step, after 0360 /// all memory accesses have been modeled and canonicalized. 0361 void assumeNoOutOfBounds(); 0362 0363 /// Build the alias checks for this SCoP. 0364 bool buildAliasChecks(); 0365 0366 /// A vector of memory accesses that belong to an alias group. 0367 using AliasGroupTy = SmallVector<MemoryAccess *, 4>; 0368 0369 /// A vector of alias groups. 0370 using AliasGroupVectorTy = SmallVector<AliasGroupTy, 4>; 0371 0372 /// Build a given alias group and its access data. 0373 /// 0374 /// @param AliasGroup The alias group to build. 0375 /// @param HasWriteAccess A set of arrays through which memory is not only 0376 /// read, but also written. 0377 // 0378 /// @returns True if __no__ error occurred, false otherwise. 0379 bool buildAliasGroup(AliasGroupTy &AliasGroup, 0380 DenseSet<const ScopArrayInfo *> HasWriteAccess); 0381 0382 /// Build all alias groups for this SCoP. 0383 /// 0384 /// @returns True if __no__ error occurred, false otherwise. 0385 bool buildAliasGroups(); 0386 0387 /// Build alias groups for all memory accesses in the Scop. 0388 /// 0389 /// Using the alias analysis and an alias set tracker we build alias sets 0390 /// for all memory accesses inside the Scop. For each alias set we then map 0391 /// the aliasing pointers back to the memory accesses we know, thus obtain 0392 /// groups of memory accesses which might alias. We also collect the set of 0393 /// arrays through which memory is written. 0394 /// 0395 /// @returns A pair consistent of a vector of alias groups and a set of arrays 0396 /// through which memory is written. 0397 std::tuple<AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>> 0398 buildAliasGroupsForAccesses(); 0399 0400 /// Split alias groups by iteration domains. 0401 /// 0402 /// We split each group based on the domains of the minimal/maximal accesses. 0403 /// That means two minimal/maximal accesses are only in a group if their 0404 /// access domains intersect. Otherwise, they are in different groups. 0405 /// 0406 /// @param AliasGroups The alias groups to split 0407 void splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups); 0408 0409 /// Build an instance of MemoryAccess from the Load/Store instruction. 0410 /// 0411 /// @param Inst The Load/Store instruction that access the memory 0412 /// @param Stmt The parent statement of the instruction 0413 void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt); 0414 0415 /// Analyze and extract the cross-BB scalar dependences (or, dataflow 0416 /// dependencies) of an instruction. 0417 /// 0418 /// @param UserStmt The statement @p Inst resides in. 0419 /// @param Inst The instruction to be analyzed. 0420 void buildScalarDependences(ScopStmt *UserStmt, Instruction *Inst); 0421 0422 /// Build the escaping dependences for @p Inst. 0423 /// 0424 /// Search for uses of the llvm::Value defined by @p Inst that are not 0425 /// within the SCoP. If there is such use, add a SCALAR WRITE such that 0426 /// it is available after the SCoP as escaping value. 0427 /// 0428 /// @param Inst The instruction to be analyzed. 0429 void buildEscapingDependences(Instruction *Inst); 0430 0431 /// Create MemoryAccesses for the given PHI node in the given region. 0432 /// 0433 /// @param PHIStmt The statement @p PHI resides in. 0434 /// @param PHI The PHI node to be handled 0435 /// @param NonAffineSubRegion The non affine sub-region @p PHI is in. 0436 /// @param IsExitBlock Flag to indicate that @p PHI is in the exit BB. 0437 void buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, 0438 Region *NonAffineSubRegion, bool IsExitBlock = false); 0439 0440 /// Build the access functions for the subregion @p SR. 0441 void buildAccessFunctions(); 0442 0443 /// Should an instruction be modeled in a ScopStmt. 0444 /// 0445 /// @param Inst The instruction to check. 0446 /// @param L The loop in which context the instruction is looked at. 0447 /// 0448 /// @returns True if the instruction should be modeled. 0449 bool shouldModelInst(Instruction *Inst, Loop *L); 0450 0451 /// Create one or more ScopStmts for @p BB. 0452 /// 0453 /// Consecutive instructions are associated to the same statement until a 0454 /// separator is found. 0455 void buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore = false); 0456 0457 /// Create one or more ScopStmts for @p BB using equivalence classes. 0458 /// 0459 /// Instructions of a basic block that belong to the same equivalence class 0460 /// are added to the same statement. 0461 void buildEqivClassBlockStmts(BasicBlock *BB); 0462 0463 /// Create ScopStmt for all BBs and non-affine subregions of @p SR. 0464 /// 0465 /// @param SR A subregion of @p R. 0466 /// 0467 /// Some of the statements might be optimized away later when they do not 0468 /// access any memory and thus have no effect. 0469 void buildStmts(Region &SR); 0470 0471 /// Build the access functions for the statement @p Stmt in or represented by 0472 /// @p BB. 0473 /// 0474 /// @param Stmt Statement to add MemoryAccesses to. 0475 /// @param BB A basic block in @p R. 0476 /// @param NonAffineSubRegion The non affine sub-region @p BB is in. 0477 void buildAccessFunctions(ScopStmt *Stmt, BasicBlock &BB, 0478 Region *NonAffineSubRegion = nullptr); 0479 0480 /// Create a new MemoryAccess object and add it to #AccFuncMap. 0481 /// 0482 /// @param Stmt The statement where the access takes place. 0483 /// @param Inst The instruction doing the access. It is not necessarily 0484 /// inside @p BB. 0485 /// @param AccType The kind of access. 0486 /// @param BaseAddress The accessed array's base address. 0487 /// @param ElemType The type of the accessed array elements. 0488 /// @param Affine Whether all subscripts are affine expressions. 0489 /// @param AccessValue Value read or written. 0490 /// @param Subscripts Access subscripts per dimension. 0491 /// @param Sizes The array dimension's sizes. 0492 /// @param Kind The kind of memory accessed. 0493 /// 0494 /// @return The created MemoryAccess, or nullptr if the access is not within 0495 /// the SCoP. 0496 MemoryAccess *addMemoryAccess(ScopStmt *Stmt, Instruction *Inst, 0497 MemoryAccess::AccessType AccType, 0498 Value *BaseAddress, Type *ElemType, bool Affine, 0499 Value *AccessValue, 0500 ArrayRef<const SCEV *> Subscripts, 0501 ArrayRef<const SCEV *> Sizes, MemoryKind Kind); 0502 0503 /// Create a MemoryAccess that represents either a LoadInst or 0504 /// StoreInst. 0505 /// 0506 /// @param Stmt The statement to add the MemoryAccess to. 0507 /// @param MemAccInst The LoadInst or StoreInst. 0508 /// @param AccType The kind of access. 0509 /// @param BaseAddress The accessed array's base address. 0510 /// @param ElemType The type of the accessed array elements. 0511 /// @param IsAffine Whether all subscripts are affine expressions. 0512 /// @param Subscripts Access subscripts per dimension. 0513 /// @param Sizes The array dimension's sizes. 0514 /// @param AccessValue Value read or written. 0515 /// 0516 /// @see MemoryKind 0517 void addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst, 0518 MemoryAccess::AccessType AccType, Value *BaseAddress, 0519 Type *ElemType, bool IsAffine, 0520 ArrayRef<const SCEV *> Subscripts, 0521 ArrayRef<const SCEV *> Sizes, Value *AccessValue); 0522 0523 /// Create a MemoryAccess for writing an llvm::Instruction. 0524 /// 0525 /// The access will be created at the position of @p Inst. 0526 /// 0527 /// @param Inst The instruction to be written. 0528 /// 0529 /// @see ensureValueRead() 0530 /// @see MemoryKind 0531 void ensureValueWrite(Instruction *Inst); 0532 0533 /// Ensure an llvm::Value is available in the BB's statement, creating a 0534 /// MemoryAccess for reloading it if necessary. 0535 /// 0536 /// @param V The value expected to be loaded. 0537 /// @param UserStmt Where to reload the value. 0538 /// 0539 /// @see ensureValueStore() 0540 /// @see MemoryKind 0541 void ensureValueRead(Value *V, ScopStmt *UserStmt); 0542 0543 /// Create a write MemoryAccess for the incoming block of a phi node. 0544 /// 0545 /// Each of the incoming blocks write their incoming value to be picked in the 0546 /// phi's block. 0547 /// 0548 /// @param PHI PHINode under consideration. 0549 /// @param IncomingStmt The statement to add the MemoryAccess to. 0550 /// @param IncomingBlock Some predecessor block. 0551 /// @param IncomingValue @p PHI's value when coming from @p IncomingBlock. 0552 /// @param IsExitBlock When true, uses the .s2a alloca instead of the 0553 /// .phiops one. Required for values escaping through a 0554 /// PHINode in the SCoP region's exit block. 0555 /// @see addPHIReadAccess() 0556 /// @see MemoryKind 0557 void ensurePHIWrite(PHINode *PHI, ScopStmt *IncomintStmt, 0558 BasicBlock *IncomingBlock, Value *IncomingValue, 0559 bool IsExitBlock); 0560 0561 /// Add user provided parameter constraints to context (command line). 0562 void addUserContext(); 0563 0564 /// Add user provided parameter constraints to context (source code). 0565 void addUserAssumptions(AssumptionCache &AC, 0566 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); 0567 0568 /// Add all recorded assumptions to the assumed context. 0569 void addRecordedAssumptions(); 0570 0571 /// Create a MemoryAccess for reading the value of a phi. 0572 /// 0573 /// The modeling assumes that all incoming blocks write their incoming value 0574 /// to the same location. Thus, this access will read the incoming block's 0575 /// value as instructed by this @p PHI. 0576 /// 0577 /// @param PHIStmt Statement @p PHI resides in. 0578 /// @param PHI PHINode under consideration; the READ access will be added 0579 /// here. 0580 /// 0581 /// @see ensurePHIWrite() 0582 /// @see MemoryKind 0583 void addPHIReadAccess(ScopStmt *PHIStmt, PHINode *PHI); 0584 0585 /// Wrapper function to calculate minimal/maximal accesses to each array. 0586 bool calculateMinMaxAccess(AliasGroupTy AliasGroup, 0587 Scop::MinMaxVectorTy &MinMaxAccesses); 0588 /// Build the domain of @p Stmt. 0589 void buildDomain(ScopStmt &Stmt); 0590 0591 /// Fill NestLoops with loops surrounding @p Stmt. 0592 void collectSurroundingLoops(ScopStmt &Stmt); 0593 0594 /// Check for reductions in @p Stmt. 0595 /// 0596 /// Iterate over all store memory accesses and check for valid binary 0597 /// reduction like chains. For all candidates we check if they have the same 0598 /// base address and there are no other accesses which overlap with them. The 0599 /// base address check rules out impossible reductions candidates early. The 0600 /// overlap check, together with the "only one user" check in 0601 /// collectCandidateReductionLoads, guarantees that none of the intermediate 0602 /// results will escape during execution of the loop nest. We basically check 0603 /// here that no other memory access can access the same memory as the 0604 /// potential reduction. 0605 void checkForReductions(ScopStmt &Stmt); 0606 0607 /// Verify that all required invariant loads have been hoisted. 0608 /// 0609 /// Invariant load hoisting is not guaranteed to hoist all loads that were 0610 /// assumed to be scop invariant during scop detection. This function checks 0611 /// for cases where the hoisting failed, but where it would have been 0612 /// necessary for our scop modeling to be correct. In case of insufficient 0613 /// hoisting the scop is marked as invalid. 0614 /// 0615 /// In the example below Bound[1] is required to be invariant: 0616 /// 0617 /// for (int i = 1; i < Bound[0]; i++) 0618 /// for (int j = 1; j < Bound[1]; j++) 0619 /// ... 0620 void verifyInvariantLoads(); 0621 0622 /// Hoist invariant memory loads and check for required ones. 0623 /// 0624 /// We first identify "common" invariant loads, thus loads that are invariant 0625 /// and can be hoisted. Then we check if all required invariant loads have 0626 /// been identified as (common) invariant. A load is a required invariant load 0627 /// if it was assumed to be invariant during SCoP detection, e.g., to assume 0628 /// loop bounds to be affine or runtime alias checks to be placeable. In case 0629 /// a required invariant load was not identified as (common) invariant we will 0630 /// drop this SCoP. An example for both "common" as well as required invariant 0631 /// loads is given below: 0632 /// 0633 /// for (int i = 1; i < *LB[0]; i++) 0634 /// for (int j = 1; j < *LB[1]; j++) 0635 /// A[i][j] += A[0][0] + (*V); 0636 /// 0637 /// Common inv. loads: V, A[0][0], LB[0], LB[1] 0638 /// Required inv. loads: LB[0], LB[1], (V, if it may alias with A or LB) 0639 void hoistInvariantLoads(); 0640 0641 /// Add invariant loads listed in @p InvMAs with the domain of @p Stmt. 0642 void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs); 0643 0644 /// Check if @p MA can always be hoisted without execution context. 0645 bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, 0646 bool MAInvalidCtxIsEmpty, 0647 bool NonHoistableCtxIsEmpty); 0648 0649 /// Return true if and only if @p LI is a required invariant load. 0650 bool isRequiredInvariantLoad(LoadInst *LI) const { 0651 return scop->getRequiredInvariantLoads().count(LI); 0652 } 0653 0654 /// Check if the base ptr of @p MA is in the SCoP but not hoistable. 0655 bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes); 0656 0657 /// Return the context under which the access cannot be hoisted. 0658 /// 0659 /// @param Access The access to check. 0660 /// @param Writes The set of all memory writes in the scop. 0661 /// 0662 /// @return Return the context under which the access cannot be hoisted or a 0663 /// nullptr if it cannot be hoisted at all. 0664 isl::set getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes); 0665 0666 /// Build the access relation of all memory accesses of @p Stmt. 0667 void buildAccessRelations(ScopStmt &Stmt); 0668 0669 /// Canonicalize arrays with base pointers from the same equivalence class. 0670 /// 0671 /// Some context: in our normal model we assume that each base pointer is 0672 /// related to a single specific memory region, where memory regions 0673 /// associated with different base pointers are disjoint. Consequently we do 0674 /// not need to compute additional data dependences that model possible 0675 /// overlaps of these memory regions. To verify our assumption we compute 0676 /// alias checks that verify that modeled arrays indeed do not overlap. In 0677 /// case an overlap is detected the runtime check fails and we fall back to 0678 /// the original code. 0679 /// 0680 /// In case of arrays where the base pointers are know to be identical, 0681 /// because they are dynamically loaded by accesses that are in the same 0682 /// invariant load equivalence class, such run-time alias check would always 0683 /// be false. 0684 /// 0685 /// This function makes sure that we do not generate consistently failing 0686 /// run-time checks for code that contains distinct arrays with known 0687 /// equivalent base pointers. It identifies for each invariant load 0688 /// equivalence class a single canonical array and canonicalizes all memory 0689 /// accesses that reference arrays that have base pointers that are known to 0690 /// be equal to the base pointer of such a canonical array to this canonical 0691 /// array. 0692 /// 0693 /// We currently do not canonicalize arrays for which certain memory accesses 0694 /// have been hoisted as loop invariant. 0695 void canonicalizeDynamicBasePtrs(); 0696 0697 /// Construct the schedule of this SCoP. 0698 void buildSchedule(); 0699 0700 /// A loop stack element to keep track of per-loop information during 0701 /// schedule construction. 0702 using LoopStackElementTy = struct LoopStackElement { 0703 // The loop for which we keep information. 0704 Loop *L; 0705 0706 // The (possibly incomplete) schedule for this loop. 0707 isl::schedule Schedule; 0708 0709 // The number of basic blocks in the current loop, for which a schedule has 0710 // already been constructed. 0711 unsigned NumBlocksProcessed; 0712 0713 LoopStackElement(Loop *L, isl::schedule S, unsigned NumBlocksProcessed) 0714 : L(L), Schedule(S), NumBlocksProcessed(NumBlocksProcessed) {} 0715 }; 0716 0717 /// The loop stack used for schedule construction. 0718 /// 0719 /// The loop stack keeps track of schedule information for a set of nested 0720 /// loops as well as an (optional) 'nullptr' loop that models the outermost 0721 /// schedule dimension. The loops in a loop stack always have a parent-child 0722 /// relation where the loop at position n is the parent of the loop at 0723 /// position n + 1. 0724 using LoopStackTy = SmallVector<LoopStackElementTy, 4>; 0725 0726 /// Construct schedule information for a given Region and add the 0727 /// derived information to @p LoopStack. 0728 /// 0729 /// Given a Region we derive schedule information for all RegionNodes 0730 /// contained in this region ensuring that the assigned execution times 0731 /// correctly model the existing control flow relations. 0732 /// 0733 /// @param R The region which to process. 0734 /// @param LoopStack A stack of loops that are currently under 0735 /// construction. 0736 void buildSchedule(Region *R, LoopStackTy &LoopStack); 0737 0738 /// Build Schedule for the region node @p RN and add the derived 0739 /// information to @p LoopStack. 0740 /// 0741 /// In case @p RN is a BasicBlock or a non-affine Region, we construct the 0742 /// schedule for this @p RN and also finalize loop schedules in case the 0743 /// current @p RN completes the loop. 0744 /// 0745 /// In case @p RN is a not-non-affine Region, we delegate the construction to 0746 /// buildSchedule(Region *R, ...). 0747 /// 0748 /// @param RN The RegionNode region traversed. 0749 /// @param LoopStack A stack of loops that are currently under 0750 /// construction. 0751 void buildSchedule(RegionNode *RN, LoopStackTy &LoopStack); 0752 0753 public: 0754 explicit ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, 0755 const DataLayout &DL, DominatorTree &DT, LoopInfo &LI, 0756 ScopDetection &SD, ScalarEvolution &SE, 0757 OptimizationRemarkEmitter &ORE); 0758 ScopBuilder(const ScopBuilder &) = delete; 0759 ScopBuilder &operator=(const ScopBuilder &) = delete; 0760 ~ScopBuilder() = default; 0761 0762 /// Try to build the Polly IR of static control part on the current 0763 /// SESE-Region. 0764 /// 0765 /// @return Give up the ownership of the scop object or static control part 0766 /// for the region 0767 std::unique_ptr<Scop> getScop() { return std::move(scop); } 0768 }; 0769 } // end namespace polly 0770 0771 #endif // POLLY_SCOPBUILDER_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|