|
|
|||
File indexing completed on 2026-05-10 08:48:11
0001 //=- IslNodeBuilder.cpp - Translate an isl AST into a LLVM-IR AST -*- 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 // This file contains the IslNodeBuilder, a class to translate an isl AST into 0010 // a LLVM-IR AST. 0011 // 0012 //===----------------------------------------------------------------------===// 0013 0014 #ifndef POLLY_ISLNODEBUILDER_H 0015 #define POLLY_ISLNODEBUILDER_H 0016 0017 #include "polly/CodeGen/BlockGenerators.h" 0018 #include "polly/CodeGen/IslExprBuilder.h" 0019 #include "polly/ScopDetectionDiagnostic.h" 0020 #include "llvm/ADT/ArrayRef.h" 0021 #include "llvm/ADT/SmallSet.h" 0022 #include "llvm/IR/InstrTypes.h" 0023 #include "isl/ctx.h" 0024 #include "isl/isl-noexceptions.h" 0025 0026 namespace polly { 0027 using llvm::LoopInfo; 0028 using llvm::SmallSet; 0029 0030 struct InvariantEquivClassTy; 0031 0032 struct SubtreeReferences { 0033 LoopInfo &LI; 0034 ScalarEvolution &SE; 0035 Scop &S; 0036 ValueMapT &GlobalMap; 0037 SetVector<Value *> &Values; 0038 SetVector<const SCEV *> &SCEVs; 0039 BlockGenerator &BlockGen; 0040 // In case an (optional) parameter space location is provided, parameter space 0041 // information is collected as well. 0042 isl::space *ParamSpace; 0043 }; 0044 0045 /// Extract the out-of-scop values and SCEVs referenced from a ScopStmt. 0046 /// 0047 /// This includes the SCEVUnknowns referenced by the SCEVs used in the 0048 /// statement and the base pointers of the memory accesses. For scalar 0049 /// statements we force the generation of alloca memory locations and list 0050 /// these locations in the set of out-of-scop values as well. 0051 /// 0052 /// We also collect an isl::space that includes all parameter dimensions 0053 /// used in the statement's memory accesses, in case the ParamSpace pointer 0054 /// is non-null. 0055 /// 0056 /// @param Stmt The statement for which to extract the information. 0057 /// @param UserPtr A void pointer that can be casted to a 0058 /// SubtreeReferences structure. 0059 /// @param CreateScalarRefs Should the result include allocas of scalar 0060 /// references? 0061 void addReferencesFromStmt(ScopStmt *Stmt, void *UserPtr, 0062 bool CreateScalarRefs = true); 0063 0064 class IslNodeBuilder { 0065 public: 0066 IslNodeBuilder(PollyIRBuilder &Builder, ScopAnnotator &Annotator, 0067 const DataLayout &DL, LoopInfo &LI, ScalarEvolution &SE, 0068 DominatorTree &DT, Scop &S, BasicBlock *StartBlock) 0069 : S(S), Builder(Builder), Annotator(Annotator), 0070 ExprBuilder(S, Builder, IDToValue, ValueMap, DL, SE, DT, LI, 0071 StartBlock), 0072 BlockGen(Builder, LI, SE, DT, ScalarMap, EscapeMap, ValueMap, 0073 &ExprBuilder, StartBlock), 0074 RegionGen(BlockGen), DL(DL), LI(LI), SE(SE), DT(DT), 0075 StartBlock(StartBlock), GenDT(&DT), GenLI(&LI), GenSE(&SE) {} 0076 0077 virtual ~IslNodeBuilder() = default; 0078 0079 void addParameters(__isl_take isl_set *Context); 0080 0081 /// Generate code that evaluates @p Condition at run-time. 0082 /// 0083 /// This function is typically called to generate the LLVM-IR for the 0084 /// run-time condition of the scop, that verifies that all the optimistic 0085 /// assumptions we have taken during scop modeling and transformation 0086 /// hold at run-time. 0087 /// 0088 /// @param Condition The condition to evaluate 0089 /// 0090 /// @result An llvm::Value that is true if the condition holds and false 0091 /// otherwise. 0092 Value *createRTC(isl_ast_expr *Condition); 0093 0094 void create(__isl_take isl_ast_node *Node); 0095 0096 /// Allocate memory for all new arrays created by Polly. 0097 void allocateNewArrays(BBPair StartExitBlocks); 0098 0099 /// Preload all memory loads that are invariant. 0100 bool preloadInvariantLoads(); 0101 0102 /// Finalize code generation. 0103 /// 0104 /// @see BlockGenerator::finalizeSCoP(Scop &S) 0105 virtual void finalize() { BlockGen.finalizeSCoP(S); } 0106 0107 IslExprBuilder &getExprBuilder() { return ExprBuilder; } 0108 0109 /// Get the associated block generator. 0110 /// 0111 /// @return A reference to the associated block generator. 0112 BlockGenerator &getBlockGenerator() { return BlockGen; } 0113 0114 /// Return the parallel subfunctions that have been created. 0115 const ArrayRef<Function *> getParallelSubfunctions() const { 0116 return ParallelSubfunctions; 0117 } 0118 0119 protected: 0120 Scop &S; 0121 PollyIRBuilder &Builder; 0122 ScopAnnotator &Annotator; 0123 0124 IslExprBuilder ExprBuilder; 0125 0126 /// Maps used by the block and region generator to demote scalars. 0127 /// 0128 ///@{ 0129 0130 /// See BlockGenerator::ScalarMap. 0131 BlockGenerator::AllocaMapTy ScalarMap; 0132 0133 /// See BlockGenerator::EscapeMap. 0134 BlockGenerator::EscapeUsersAllocaMapTy EscapeMap; 0135 0136 ///@} 0137 0138 /// The generator used to copy a basic block. 0139 BlockGenerator BlockGen; 0140 0141 /// The generator used to copy a non-affine region. 0142 RegionGenerator RegionGen; 0143 0144 const DataLayout &DL; 0145 LoopInfo &LI; 0146 ScalarEvolution &SE; 0147 DominatorTree &DT; 0148 BasicBlock *StartBlock; 0149 0150 /// Relates to the region where the code is emitted into. 0151 /// @{ 0152 DominatorTree *GenDT; 0153 LoopInfo *GenLI; 0154 ScalarEvolution *GenSE; 0155 /// @} 0156 0157 /// The current iteration of out-of-scop loops 0158 /// 0159 /// This map provides for a given loop a llvm::Value that contains the current 0160 /// loop iteration. 0161 MapVector<const Loop *, const SCEV *> OutsideLoopIterations; 0162 0163 // This maps an isl_id* to the Value* it has in the generated program. For now 0164 // on, the only isl_ids that are stored here are the newly calculated loop 0165 // ivs. 0166 IslExprBuilder::IDToValueTy IDToValue; 0167 0168 /// A collection of all parallel subfunctions that have been created. 0169 SmallVector<Function *, 8> ParallelSubfunctions; 0170 0171 /// Generate code for a given SCEV* 0172 /// 0173 /// This function generates code for a given SCEV expression. It generated 0174 /// code is emitted at the end of the basic block our Builder currently 0175 /// points to and the resulting value is returned. 0176 /// 0177 /// @param Expr The expression to code generate. 0178 Value *generateSCEV(const SCEV *Expr); 0179 0180 /// A set of Value -> Value remappings to apply when generating new code. 0181 /// 0182 /// When generating new code for a ScopStmt this map is used to map certain 0183 /// llvm::Values to new llvm::Values. 0184 ValueMapT ValueMap; 0185 0186 /// Materialize code for @p Id if it was not done before. 0187 /// 0188 /// @returns False, iff a problem occurred and the value was not materialized. 0189 bool materializeValue(__isl_take isl_id *Id); 0190 0191 /// Materialize parameters of @p Set. 0192 /// 0193 /// @returns False, iff a problem occurred and the value was not materialized. 0194 bool materializeParameters(__isl_take isl_set *Set); 0195 0196 /// Materialize all parameters in the current scop. 0197 /// 0198 /// @returns False, iff a problem occurred and the value was not materialized. 0199 bool materializeParameters(); 0200 0201 // Extract the upper bound of this loop 0202 // 0203 // The isl code generation can generate arbitrary expressions to check if the 0204 // upper bound of a loop is reached, but it provides an option to enforce 0205 // 'atomic' upper bounds. An 'atomic upper bound is always of the form 0206 // iv <= expr, where expr is an (arbitrary) expression not containing iv. 0207 // 0208 // This function extracts 'atomic' upper bounds. Polly, in general, requires 0209 // atomic upper bounds for the following reasons: 0210 // 0211 // 1. An atomic upper bound is loop invariant 0212 // 0213 // It must not be calculated at each loop iteration and can often even be 0214 // hoisted out further by the loop invariant code motion. 0215 // 0216 // 2. OpenMP needs a loop invariant upper bound to calculate the number 0217 // of loop iterations. 0218 // 0219 // 3. With the existing code, upper bounds have been easier to implement. 0220 isl::ast_expr getUpperBound(isl::ast_node_for For, 0221 CmpInst::Predicate &Predicate); 0222 0223 /// Return non-negative number of iterations in case of the following form 0224 /// of a loop and -1 otherwise. 0225 /// 0226 /// for (i = 0; i <= NumIter; i++) { 0227 /// loop body; 0228 /// } 0229 /// 0230 /// NumIter is a non-negative integer value. Condition can have 0231 /// isl_ast_op_lt type. 0232 int getNumberOfIterations(isl::ast_node_for For); 0233 0234 /// Compute the values and loops referenced in this subtree. 0235 /// 0236 /// This function looks at all ScopStmts scheduled below the provided For node 0237 /// and finds the llvm::Value[s] and llvm::Loops[s] which are referenced but 0238 /// not locally defined. 0239 /// 0240 /// Values that can be synthesized or that are available as globals are 0241 /// considered locally defined. 0242 /// 0243 /// Loops that contain the scop or that are part of the scop are considered 0244 /// locally defined. Loops that are before the scop, but do not contain the 0245 /// scop itself are considered not locally defined. 0246 /// 0247 /// @param For The node defining the subtree. 0248 /// @param Values A vector that will be filled with the Values referenced in 0249 /// this subtree. 0250 /// @param Loops A vector that will be filled with the Loops referenced in 0251 /// this subtree. 0252 void getReferencesInSubtree(const isl::ast_node &For, 0253 SetVector<Value *> &Values, 0254 SetVector<const Loop *> &Loops); 0255 0256 /// Return the most up-to-date version of the llvm::Value for code generation. 0257 /// @param Original The Value to check for an up to date version. 0258 /// @returns A remapped `Value` from ValueMap, or `Original` if no mapping 0259 /// exists. 0260 /// @see IslNodeBuilder::updateValues 0261 /// @see IslNodeBuilder::ValueMap 0262 Value *getLatestValue(Value *Original) const; 0263 0264 /// Generate code for a marker now. 0265 /// 0266 /// For mark nodes with an unknown name, we just forward the code generation 0267 /// to its child. This is currently the only behavior implemented, as there is 0268 /// currently not special handling for marker nodes implemented. 0269 /// 0270 /// @param Mark The node we generate code for. 0271 virtual void createMark(__isl_take isl_ast_node *Marker); 0272 0273 virtual void createFor(__isl_take isl_ast_node *For); 0274 0275 /// Set to remember materialized invariant loads. 0276 /// 0277 /// An invariant load is identified by its pointer (the SCEV) and its type. 0278 SmallSet<std::pair<const SCEV *, Type *>, 16> PreloadedPtrs; 0279 0280 /// Preload the memory access at @p AccessRange with @p Build. 0281 /// 0282 /// @returns The preloaded value casted to type @p Ty 0283 Value *preloadUnconditionally(__isl_take isl_set *AccessRange, 0284 isl_ast_build *Build, Instruction *AccInst); 0285 0286 /// Preload the memory load access @p MA. 0287 /// 0288 /// If @p MA is not always executed it will be conditionally loaded and 0289 /// merged with undef from the same type. Hence, if @p MA is executed only 0290 /// under condition C then the preload code will look like this: 0291 /// 0292 /// MA_preload = undef; 0293 /// if (C) 0294 /// MA_preload = load MA; 0295 /// use MA_preload 0296 Value *preloadInvariantLoad(const MemoryAccess &MA, 0297 __isl_take isl_set *Domain); 0298 0299 /// Preload the invariant access equivalence class @p IAClass 0300 /// 0301 /// This function will preload the representing load from @p IAClass and 0302 /// map all members of @p IAClass to that preloaded value, potentially casted 0303 /// to the required type. 0304 /// 0305 /// @returns False, iff a problem occurred and the load was not preloaded. 0306 bool preloadInvariantEquivClass(InvariantEquivClassTy &IAClass); 0307 0308 void createForSequential(isl::ast_node_for For, bool MarkParallel); 0309 0310 /// Create LLVM-IR that executes a for node thread parallel. 0311 /// 0312 /// @param For The FOR isl_ast_node for which code is generated. 0313 void createForParallel(__isl_take isl_ast_node *For); 0314 0315 /// Create new access functions for modified memory accesses. 0316 /// 0317 /// In case the access function of one of the memory references in the Stmt 0318 /// has been modified, we generate a new isl_ast_expr that reflects the 0319 /// newly modified access function and return a map that maps from the 0320 /// individual memory references in the statement (identified by their id) 0321 /// to these newly generated ast expressions. 0322 /// 0323 /// @param Stmt The statement for which to (possibly) generate new access 0324 /// functions. 0325 /// @param Node The ast node corresponding to the statement for us to extract 0326 /// the local schedule from. 0327 /// @return A new hash table that contains remappings from memory ids to new 0328 /// access expressions. 0329 __isl_give isl_id_to_ast_expr * 0330 createNewAccesses(ScopStmt *Stmt, __isl_keep isl_ast_node *Node); 0331 0332 /// Generate LLVM-IR that computes the values of the original induction 0333 /// variables in function of the newly generated loop induction variables. 0334 /// 0335 /// Example: 0336 /// 0337 /// // Original 0338 /// for i 0339 /// for j 0340 /// S(i) 0341 /// 0342 /// Schedule: [i,j] -> [i+j, j] 0343 /// 0344 /// // New 0345 /// for c0 0346 /// for c1 0347 /// S(c0 - c1, c1) 0348 /// 0349 /// Assuming the original code consists of two loops which are 0350 /// transformed according to a schedule [i,j] -> [c0=i+j,c1=j]. The resulting 0351 /// ast models the original statement as a call expression where each argument 0352 /// is an expression that computes the old induction variables from the new 0353 /// ones, ordered such that the first argument computes the value of induction 0354 /// variable that was outermost in the original code. 0355 /// 0356 /// @param Expr The call expression that represents the statement. 0357 /// @param Stmt The statement that is called. 0358 /// @param LTS The loop to SCEV map in which the mapping from the original 0359 /// loop to a SCEV representing the new loop iv is added. This 0360 /// mapping does not require an explicit induction variable. 0361 /// Instead, we think in terms of an implicit induction variable 0362 /// that counts the number of times a loop is executed. For each 0363 /// original loop this count, expressed in function of the new 0364 /// induction variables, is added to the LTS map. 0365 void createSubstitutions(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt, 0366 LoopToScevMapT <S); 0367 void createSubstitutionsVector(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt, 0368 std::vector<LoopToScevMapT> &VLTS, 0369 std::vector<Value *> &IVS, 0370 __isl_take isl_id *IteratorID); 0371 virtual void createIf(__isl_take isl_ast_node *If); 0372 virtual void createUser(__isl_take isl_ast_node *User); 0373 virtual void createBlock(__isl_take isl_ast_node *Block); 0374 0375 /// Get the schedule for a given AST node. 0376 /// 0377 /// This information is used to reason about parallelism of loops or the 0378 /// locality of memory accesses under a given schedule. 0379 /// 0380 /// @param Node The node we want to obtain the schedule for. 0381 /// @return Return an isl_union_map that maps from the statements executed 0382 /// below this ast node to the scheduling vectors used to enumerate 0383 /// them. 0384 /// 0385 virtual isl::union_map getScheduleForAstNode(const isl::ast_node &Node); 0386 0387 private: 0388 /// Create code for a copy statement. 0389 /// 0390 /// A copy statement is expected to have one read memory access and one write 0391 /// memory access (in this very order). Data is loaded from the location 0392 /// described by the read memory access and written to the location described 0393 /// by the write memory access. @p NewAccesses contains for each access 0394 /// the isl ast expression that describes the location accessed. 0395 /// 0396 /// @param Stmt The copy statement that contains the accesses. 0397 /// @param NewAccesses The hash table that contains remappings from memory 0398 /// ids to new access expressions. 0399 void generateCopyStmt(ScopStmt *Stmt, 0400 __isl_keep isl_id_to_ast_expr *NewAccesses); 0401 0402 /// Materialize a canonical loop induction variable for `L`, which is a loop 0403 /// that is *not* present in the Scop. 0404 /// 0405 /// Note that this is materialized at the point where the `Builder` is 0406 /// currently pointing. 0407 /// We also populate the `OutsideLoopIterations` map with `L`s SCEV to keep 0408 /// track of the induction variable. 0409 /// See [Code generation of induction variables of loops outside Scops] 0410 Value *materializeNonScopLoopInductionVariable(const Loop *L); 0411 }; 0412 0413 } // namespace polly 0414 0415 #endif // POLLY_ISLNODEBUILDER_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|