|
|
|||
File indexing completed on 2026-05-10 08:48:21
0001 //===------ ZoneAlgo.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 // Derive information about array elements between statements ("Zones"). 0010 // 0011 //===----------------------------------------------------------------------===// 0012 0013 #ifndef POLLY_ZONEALGO_H 0014 #define POLLY_ZONEALGO_H 0015 0016 #include "llvm/ADT/DenseMap.h" 0017 #include "llvm/ADT/DenseSet.h" 0018 #include "llvm/ADT/SmallPtrSet.h" 0019 #include "isl/isl-noexceptions.h" 0020 #include <memory> 0021 0022 namespace llvm { 0023 class Value; 0024 class LoopInfo; 0025 class Loop; 0026 class PHINode; 0027 class raw_ostream; 0028 } // namespace llvm 0029 0030 namespace polly { 0031 class Scop; 0032 class ScopStmt; 0033 class MemoryAccess; 0034 class ScopArrayInfo; 0035 0036 /// Return only the mappings that map to known values. 0037 /// 0038 /// @param UMap { [] -> ValInst[] } 0039 /// 0040 /// @return { [] -> ValInst[] } 0041 isl::union_map filterKnownValInst(const isl::union_map &UMap); 0042 0043 /// Base class for algorithms based on zones, like DeLICM. 0044 class ZoneAlgorithm { 0045 protected: 0046 /// The name of the pass this is used from. Used for optimization remarks. 0047 const char *PassName; 0048 0049 /// Hold a reference to the isl_ctx to avoid it being freed before we released 0050 /// all of the isl objects. 0051 /// 0052 /// This must be declared before any other member that holds an isl object. 0053 /// This guarantees that the shared_ptr and its isl_ctx is destructed last, 0054 /// after all other members free'd the isl objects they were holding. 0055 std::shared_ptr<isl_ctx> IslCtx; 0056 0057 /// Cached reaching definitions for each ScopStmt. 0058 /// 0059 /// Use getScalarReachingDefinition() to get its contents. 0060 llvm::DenseMap<ScopStmt *, isl::map> ScalarReachDefZone; 0061 0062 /// The analyzed Scop. 0063 Scop *S; 0064 0065 /// LoopInfo analysis used to determine whether values are synthesizable. 0066 llvm::LoopInfo *LI; 0067 0068 /// Parameter space that does not need realignment. 0069 isl::space ParamSpace; 0070 0071 /// Space the schedule maps to. 0072 isl::space ScatterSpace; 0073 0074 /// Cached version of the schedule and domains. 0075 isl::union_map Schedule; 0076 0077 /// Combined access relations of all MemoryKind::Array READ accesses. 0078 /// { DomainRead[] -> Element[] } 0079 isl::union_map AllReads; 0080 0081 /// The loaded values (llvm::LoadInst) of all reads. 0082 /// { [Element[] -> DomainRead[]] -> ValInst[] } 0083 isl::union_map AllReadValInst; 0084 0085 /// Combined access relations of all MemoryKind::Array, MAY_WRITE accesses. 0086 /// { DomainMayWrite[] -> Element[] } 0087 isl::union_map AllMayWrites; 0088 0089 /// Combined access relations of all MemoryKind::Array, MUST_WRITE accesses. 0090 /// { DomainMustWrite[] -> Element[] } 0091 isl::union_map AllMustWrites; 0092 0093 /// Combined access relations of all MK_Array write accesses (union of 0094 /// AllMayWrites and AllMustWrites). 0095 /// { DomainWrite[] -> Element[] } 0096 isl::union_map AllWrites; 0097 0098 /// The value instances written to array elements of all write accesses. 0099 /// { [Element[] -> DomainWrite[]] -> ValInst[] } 0100 isl::union_map AllWriteValInst; 0101 0102 /// All reaching definitions for MemoryKind::Array writes. 0103 /// { [Element[] -> Zone[]] -> DomainWrite[] } 0104 isl::union_map WriteReachDefZone; 0105 0106 /// Map llvm::Values to an isl identifier. 0107 /// Used with -polly-use-llvm-names=false as an alternative method to get 0108 /// unique ids that do not depend on pointer values. 0109 llvm::DenseMap<llvm::Value *, isl::id> ValueIds; 0110 0111 /// Set of array elements that can be reliably used for zone analysis. 0112 /// { Element[] } 0113 isl::union_set CompatibleElts; 0114 0115 /// List of PHIs that may transitively refer to themselves. 0116 /// 0117 /// Computing them would require a polyhedral transitive closure operation, 0118 /// for which isl may only return an approximation. For correctness, we always 0119 /// require an exact result. Hence, we exclude such PHIs. 0120 llvm::SmallPtrSet<llvm::PHINode *, 4> RecursivePHIs; 0121 0122 /// PHIs that have been computed. 0123 /// 0124 /// Computed PHIs are replaced by their incoming values using #NormalizeMap. 0125 llvm::DenseSet<llvm::PHINode *> ComputedPHIs; 0126 0127 /// For computed PHIs, contains the ValInst they stand for. 0128 /// 0129 /// To show an example, assume the following PHINode: 0130 /// 0131 /// Stmt: 0132 /// %phi = phi double [%val1, %bb1], [%val2, %bb2] 0133 /// 0134 /// It's ValInst is: 0135 /// 0136 /// { [Stmt[i] -> phi[]] } 0137 /// 0138 /// The value %phi will be either %val1 or %val2, depending on whether in 0139 /// iteration i %bb1 or %bb2 has been executed before. In SCoPs, this can be 0140 /// determined at compile-time, and the result stored in #NormalizeMap. For 0141 /// the previous example, it could be: 0142 /// 0143 /// { [Stmt[i] -> phi[]] -> [Stmt[0] -> val1[]]; 0144 /// [Stmt[i] -> phi[]] -> [Stmt[i] -> val2[]] : i > 0 } 0145 /// 0146 /// Only ValInsts in #ComputedPHIs are present in this map. Other values are 0147 /// assumed to represent themselves. This is to avoid adding lots of identity 0148 /// entries to this map. 0149 /// 0150 /// { PHIValInst[] -> IncomingValInst[] } 0151 isl::union_map NormalizeMap; 0152 0153 /// Cache for computePerPHI(const ScopArrayInfo *) 0154 llvm::SmallDenseMap<llvm::PHINode *, isl::union_map> PerPHIMaps; 0155 0156 /// A cache for getDefToTarget(). 0157 llvm::DenseMap<std::pair<ScopStmt *, ScopStmt *>, isl::map> DefToTargetCache; 0158 0159 /// Prepare the object before computing the zones of @p S. 0160 /// 0161 /// @param PassName Name of the pass using this analysis. 0162 /// @param S The SCoP to process. 0163 /// @param LI LoopInfo analysis used to determine synthesizable values. 0164 ZoneAlgorithm(const char *PassName, Scop *S, llvm::LoopInfo *LI); 0165 0166 private: 0167 /// Find the array elements that violate the zone analysis assumptions. 0168 /// 0169 /// What violates our assumptions: 0170 /// - A load after a write of the same location; we assume that all reads 0171 /// occur before the writes. 0172 /// - Two writes to the same location; we cannot model the order in which 0173 /// these occur. 0174 /// 0175 /// Scalar reads implicitly always occur before other accesses therefore never 0176 /// violate the first condition. There is also at most one write to a scalar, 0177 /// satisfying the second condition. 0178 /// 0179 /// @param Stmt The statement to be analyzed. 0180 /// @param[out] IncompatibleElts Receives the elements that are not 0181 /// zone-analysis compatible. 0182 /// @param[out] AllElts receives all encountered elements. 0183 void collectIncompatibleElts(ScopStmt *Stmt, isl::union_set &IncompatibleElts, 0184 isl::union_set &AllElts); 0185 0186 void addArrayReadAccess(MemoryAccess *MA); 0187 0188 /// Return the ValInst write by a (must-)write access. Returns the 'unknown' 0189 /// ValInst if there is no single ValInst[] the array element written to will 0190 /// have. 0191 /// 0192 /// @return { ValInst[] } 0193 isl::union_map getWrittenValue(MemoryAccess *MA, isl::map AccRel); 0194 0195 void addArrayWriteAccess(MemoryAccess *MA); 0196 0197 /// For an llvm::Value defined in @p DefStmt, compute the RAW dependency for a 0198 /// use in every instance of @p UseStmt. 0199 /// 0200 /// @param UseStmt Statement a scalar is used in. 0201 /// @param DefStmt Statement a scalar is defined in. 0202 /// 0203 /// @return { DomainUse[] -> DomainDef[] } 0204 isl::map computeUseToDefFlowDependency(ScopStmt *UseStmt, ScopStmt *DefStmt); 0205 0206 protected: 0207 isl::union_set makeEmptyUnionSet() const; 0208 0209 isl::union_map makeEmptyUnionMap() const; 0210 0211 /// For each 'execution' of a PHINode, get the incoming block that was 0212 /// executed before. 0213 /// 0214 /// For each PHI instance we can directly determine which was the incoming 0215 /// block, and hence derive which value the PHI has. 0216 /// 0217 /// @param SAI The ScopArrayInfo representing the PHI's storage. 0218 /// 0219 /// @return { DomainPHIRead[] -> DomainPHIWrite[] } 0220 isl::union_map computePerPHI(const polly::ScopArrayInfo *SAI); 0221 0222 /// Find the array elements that can be used for zone analysis. 0223 void collectCompatibleElts(); 0224 0225 /// Get the schedule for @p Stmt. 0226 /// 0227 /// The domain of the result is as narrow as possible. 0228 isl::map getScatterFor(ScopStmt *Stmt) const; 0229 0230 /// Get the schedule of @p MA's parent statement. 0231 isl::map getScatterFor(MemoryAccess *MA) const; 0232 0233 /// Get the schedule for the statement instances of @p Domain. 0234 isl::union_map getScatterFor(isl::union_set Domain) const; 0235 0236 /// Get the schedule for the statement instances of @p Domain. 0237 isl::map getScatterFor(isl::set Domain) const; 0238 0239 /// Get the domain of @p Stmt. 0240 isl::set getDomainFor(ScopStmt *Stmt) const; 0241 0242 /// Get the domain @p MA's parent statement. 0243 isl::set getDomainFor(MemoryAccess *MA) const; 0244 0245 /// Get the access relation of @p MA. 0246 /// 0247 /// The domain of the result is as narrow as possible. 0248 isl::map getAccessRelationFor(MemoryAccess *MA) const; 0249 0250 /// Get a domain translation map from a (scalar) definition to the statement 0251 /// where the definition is being moved to. 0252 /// 0253 /// @p TargetStmt can also be seen at an llvm::Use of an llvm::Value in 0254 /// @p DefStmt. In addition, we allow transitive uses: 0255 /// 0256 /// DefStmt -> MiddleStmt -> TargetStmt 0257 /// 0258 /// where an operand tree of instructions in DefStmt and MiddleStmt are to be 0259 /// moved to TargetStmt. To be generally correct, we also need to know all the 0260 /// intermediate statements. However, we make use of the fact that 0261 /// ForwardOpTree currently does not support a move from a loop body across 0262 /// its header such that only the first definition and the target statement 0263 /// are relevant. 0264 /// 0265 /// @param DefStmt Statement from where a definition might be moved from. 0266 /// @param TargetStmt Statement where the definition is potentially being 0267 /// moved to (should contain a use of that definition). 0268 /// 0269 /// @return { DomainDef[] -> DomainTarget[] } 0270 isl::map getDefToTarget(ScopStmt *DefStmt, ScopStmt *TargetStmt); 0271 0272 /// Get the reaching definition of a scalar defined in @p Stmt. 0273 /// 0274 /// Note that this does not depend on the llvm::Instruction, only on the 0275 /// statement it is defined in. Therefore the same computation can be reused. 0276 /// 0277 /// @param Stmt The statement in which a scalar is defined. 0278 /// 0279 /// @return { Scatter[] -> DomainDef[] } 0280 isl::map getScalarReachingDefinition(ScopStmt *Stmt); 0281 0282 /// Get the reaching definition of a scalar defined in @p DefDomain. 0283 /// 0284 /// @param DomainDef { DomainDef[] } 0285 /// The write statements to get the reaching definition for. 0286 /// 0287 /// @return { Scatter[] -> DomainDef[] } 0288 isl::map getScalarReachingDefinition(isl::set DomainDef); 0289 0290 /// Create a statement-to-unknown value mapping. 0291 /// 0292 /// @param Stmt The statement whose instances are mapped to unknown. 0293 /// 0294 /// @return { Domain[] -> ValInst[] } 0295 isl::map makeUnknownForDomain(ScopStmt *Stmt) const; 0296 0297 /// Create an isl_id that represents @p V. 0298 isl::id makeValueId(llvm::Value *V); 0299 0300 /// Create the space for an llvm::Value that is available everywhere. 0301 isl::space makeValueSpace(llvm::Value *V); 0302 0303 /// Create a set with the llvm::Value @p V which is available everywhere. 0304 isl::set makeValueSet(llvm::Value *V); 0305 0306 /// Create a mapping from a statement instance to the instance of an 0307 /// llvm::Value that can be used in there. 0308 /// 0309 /// Although LLVM IR uses single static assignment, llvm::Values can have 0310 /// different contents in loops, when they get redefined in the last 0311 /// iteration. This function tries to get the statement instance of the 0312 /// previous definition, relative to a user. 0313 /// 0314 /// Example: 0315 /// for (int i = 0; i < N; i += 1) { 0316 /// DEF: 0317 /// int v = A[i]; 0318 /// USE: 0319 /// use(v); 0320 /// } 0321 /// 0322 /// The value instance used by statement instance USE[i] is DEF[i]. Hence, 0323 /// makeValInst returns: 0324 /// 0325 /// { USE[i] -> [DEF[i] -> v[]] : 0 <= i < N } 0326 /// 0327 /// @param Val The value to get the instance of. 0328 /// @param UserStmt The statement that uses @p Val. Can be nullptr. 0329 /// @param Scope Loop the using instruction resides in. 0330 /// @param IsCertain Pass true if the definition of @p Val is a 0331 /// MUST_WRITE or false if the write is conditional. 0332 /// 0333 /// @return { DomainUse[] -> ValInst[] } 0334 isl::map makeValInst(llvm::Value *Val, ScopStmt *UserStmt, llvm::Loop *Scope, 0335 bool IsCertain = true); 0336 0337 /// Create and normalize a ValInst. 0338 /// 0339 /// @see makeValInst 0340 /// @see normalizeValInst 0341 /// @see #NormalizedPHI 0342 isl::union_map makeNormalizedValInst(llvm::Value *Val, ScopStmt *UserStmt, 0343 llvm::Loop *Scope, 0344 bool IsCertain = true); 0345 0346 /// Return whether @p MA can be used for transformations (e.g. OpTree load 0347 /// forwarding, DeLICM mapping). 0348 bool isCompatibleAccess(MemoryAccess *MA); 0349 0350 /// Compute the different zones. 0351 void computeCommon(); 0352 0353 /// Compute the normalization map that replaces PHIs by their incoming 0354 /// values. 0355 /// 0356 /// @see #NormalizeMap 0357 void computeNormalizedPHIs(); 0358 0359 /// Print the current state of all MemoryAccesses to @p. 0360 void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const; 0361 0362 /// Is @p MA a PHI READ access that can be normalized? 0363 /// 0364 /// @see #NormalizeMap 0365 bool isNormalizable(MemoryAccess *MA); 0366 0367 /// @{ 0368 /// Determine whether the argument does not map to any computed PHI. Those 0369 /// should have been replaced by their incoming values. 0370 /// 0371 /// @see #NormalizedPHI 0372 isl::boolean isNormalized(isl::map Map); 0373 isl::boolean isNormalized(isl::union_map Map); 0374 /// @} 0375 0376 public: 0377 /// Return the SCoP this object is analyzing. 0378 Scop *getScop() const { return S; } 0379 0380 /// A reaching definition zone is known to have the definition's written value 0381 /// if the definition is a MUST_WRITE. 0382 /// 0383 /// @return { [Element[] -> Zone[]] -> ValInst[] } 0384 isl::union_map computeKnownFromMustWrites() const; 0385 0386 /// A reaching definition zone is known to be the same value as any load that 0387 /// reads from that array element in that period. 0388 /// 0389 /// @return { [Element[] -> Zone[]] -> ValInst[] } 0390 isl::union_map computeKnownFromLoad() const; 0391 0392 /// Compute which value an array element stores at every instant. 0393 /// 0394 /// @param FromWrite Use stores as source of information. 0395 /// @param FromRead Use loads as source of information. 0396 /// 0397 /// @return { [Element[] -> Zone[]] -> ValInst[] } 0398 isl::union_map computeKnown(bool FromWrite, bool FromRead) const; 0399 }; 0400 0401 /// Create a domain-to-unknown value mapping. 0402 /// 0403 /// Value instances that do not represent a specific value are represented by an 0404 /// unnamed tuple of 0 dimensions. Its meaning depends on the context. It can 0405 /// either mean a specific but unknown value which cannot be represented by 0406 /// other means. It conflicts with itself because those two unknown ValInsts may 0407 /// have different concrete values at runtime. 0408 /// 0409 /// The other meaning is an arbitrary or wildcard value that can be chosen 0410 /// freely, like LLVM's undef. If matched with an unknown ValInst, there is no 0411 /// conflict. 0412 /// 0413 /// @param Domain { Domain[] } 0414 /// 0415 /// @return { Domain[] -> ValInst[] } 0416 isl::union_map makeUnknownForDomain(isl::union_set Domain); 0417 } // namespace polly 0418 0419 #endif /* POLLY_ZONEALGO_H */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|