Back to home page

EIC code displayed by LXR

 
 

    


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 &LTS);
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