• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=- IslNodeBuilder.cpp - Translate an isl AST into a LLVM-IR AST -*- 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 // This file contains the IslNodeBuilder, a class to translate an isl AST into
10 // a LLVM-IR AST.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef POLLY_ISLNODEBUILDER_H
15 #define POLLY_ISLNODEBUILDER_H
16 
17 #include "polly/CodeGen/BlockGenerators.h"
18 #include "polly/CodeGen/IslExprBuilder.h"
19 #include "polly/ScopDetectionDiagnostic.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/SmallSet.h"
22 #include "llvm/IR/InstrTypes.h"
23 #include "isl/ctx.h"
24 #include "isl/isl-noexceptions.h"
25 
26 using namespace llvm;
27 using namespace polly;
28 
29 namespace polly {
30 
31 struct InvariantEquivClassTy;
32 } // namespace polly
33 
34 struct SubtreeReferences {
35   LoopInfo &LI;
36   ScalarEvolution &SE;
37   Scop &S;
38   ValueMapT &GlobalMap;
39   SetVector<Value *> &Values;
40   SetVector<const SCEV *> &SCEVs;
41   BlockGenerator &BlockGen;
42   // In case an (optional) parameter space location is provided, parameter space
43   // information is collected as well.
44   isl::space *ParamSpace;
45 };
46 
47 /// Extract the out-of-scop values and SCEVs referenced from a ScopStmt.
48 ///
49 /// This includes the SCEVUnknowns referenced by the SCEVs used in the
50 /// statement and the base pointers of the memory accesses. For scalar
51 /// statements we force the generation of alloca memory locations and list
52 /// these locations in the set of out-of-scop values as well.
53 ///
54 /// We also collect an isl::space that includes all parameter dimensions
55 /// used in the statement's memory accesses, in case the ParamSpace pointer
56 /// is non-null.
57 ///
58 /// @param Stmt             The statement for which to extract the information.
59 /// @param UserPtr          A void pointer that can be casted to a
60 ///                         SubtreeReferences structure.
61 /// @param CreateScalarRefs Should the result include allocas of scalar
62 ///                         references?
63 void addReferencesFromStmt(const ScopStmt *Stmt, void *UserPtr,
64                            bool CreateScalarRefs = true);
65 
66 class IslNodeBuilder {
67 public:
IslNodeBuilder(PollyIRBuilder & Builder,ScopAnnotator & Annotator,const DataLayout & DL,LoopInfo & LI,ScalarEvolution & SE,DominatorTree & DT,Scop & S,BasicBlock * StartBlock)68   IslNodeBuilder(PollyIRBuilder &Builder, ScopAnnotator &Annotator,
69                  const DataLayout &DL, LoopInfo &LI, ScalarEvolution &SE,
70                  DominatorTree &DT, Scop &S, BasicBlock *StartBlock)
71       : S(S), Builder(Builder), Annotator(Annotator),
72         ExprBuilder(S, Builder, IDToValue, ValueMap, DL, SE, DT, LI,
73                     StartBlock),
74         BlockGen(Builder, LI, SE, DT, ScalarMap, EscapeMap, ValueMap,
75                  &ExprBuilder, StartBlock),
76         RegionGen(BlockGen), DL(DL), LI(LI), SE(SE), DT(DT),
77         StartBlock(StartBlock) {}
78 
79   virtual ~IslNodeBuilder() = default;
80 
81   void addParameters(__isl_take isl_set *Context);
82 
83   /// Create Values which hold the sizes of the outermost dimension of all
84   /// Fortran arrays in the current scop.
85   ///
86   /// @returns False, if a problem occurred and a Fortran array was not
87   /// materialized. True otherwise.
88   bool materializeFortranArrayOutermostDimension();
89 
90   /// Generate code that evaluates @p Condition at run-time.
91   ///
92   /// This function is typically called to generate the LLVM-IR for the
93   /// run-time condition of the scop, that verifies that all the optimistic
94   /// assumptions we have taken during scop modeling and transformation
95   /// hold at run-time.
96   ///
97   /// @param Condition The condition to evaluate
98   ///
99   /// @result An llvm::Value that is true if the condition holds and false
100   ///         otherwise.
101   Value *createRTC(isl_ast_expr *Condition);
102 
103   void create(__isl_take isl_ast_node *Node);
104 
105   /// Allocate memory for all new arrays created by Polly.
106   void allocateNewArrays(BBPair StartExitBlocks);
107 
108   /// Preload all memory loads that are invariant.
109   bool preloadInvariantLoads();
110 
111   /// Finalize code generation.
112   ///
113   /// @see BlockGenerator::finalizeSCoP(Scop &S)
finalize()114   virtual void finalize() { BlockGen.finalizeSCoP(S); }
115 
getExprBuilder()116   IslExprBuilder &getExprBuilder() { return ExprBuilder; }
117 
118   /// Get the associated block generator.
119   ///
120   /// @return A reference to the associated block generator.
getBlockGenerator()121   BlockGenerator &getBlockGenerator() { return BlockGen; }
122 
123   /// Return the parallel subfunctions that have been created.
getParallelSubfunctions()124   const ArrayRef<Function *> getParallelSubfunctions() const {
125     return ParallelSubfunctions;
126   }
127 
128 protected:
129   Scop &S;
130   PollyIRBuilder &Builder;
131   ScopAnnotator &Annotator;
132 
133   IslExprBuilder ExprBuilder;
134 
135   /// Maps used by the block and region generator to demote scalars.
136   ///
137   ///@{
138 
139   /// See BlockGenerator::ScalarMap.
140   BlockGenerator::AllocaMapTy ScalarMap;
141 
142   /// See BlockGenerator::EscapeMap.
143   BlockGenerator::EscapeUsersAllocaMapTy EscapeMap;
144 
145   ///@}
146 
147   /// The generator used to copy a basic block.
148   BlockGenerator BlockGen;
149 
150   /// The generator used to copy a non-affine region.
151   RegionGenerator RegionGen;
152 
153   const DataLayout &DL;
154   LoopInfo &LI;
155   ScalarEvolution &SE;
156   DominatorTree &DT;
157   BasicBlock *StartBlock;
158 
159   /// The current iteration of out-of-scop loops
160   ///
161   /// This map provides for a given loop a llvm::Value that contains the current
162   /// loop iteration.
163   MapVector<const Loop *, const SCEV *> OutsideLoopIterations;
164 
165   // This maps an isl_id* to the Value* it has in the generated program. For now
166   // on, the only isl_ids that are stored here are the newly calculated loop
167   // ivs.
168   IslExprBuilder::IDToValueTy IDToValue;
169 
170   /// A collection of all parallel subfunctions that have been created.
171   SmallVector<Function *, 8> ParallelSubfunctions;
172 
173   /// Generate code for a given SCEV*
174   ///
175   /// This function generates code for a given SCEV expression. It generated
176   /// code is emitted at the end of the basic block our Builder currently
177   /// points to and the resulting value is returned.
178   ///
179   /// @param Expr The expression to code generate.
180   Value *generateSCEV(const SCEV *Expr);
181 
182   /// A set of Value -> Value remappings to apply when generating new code.
183   ///
184   /// When generating new code for a ScopStmt this map is used to map certain
185   /// llvm::Values to new llvm::Values.
186   ValueMapT ValueMap;
187 
188   /// Materialize code for @p Id if it was not done before.
189   ///
190   /// @returns False, iff a problem occurred and the value was not materialized.
191   bool materializeValue(__isl_take isl_id *Id);
192 
193   /// Materialize parameters of @p Set.
194   ///
195   /// @returns False, iff a problem occurred and the value was not materialized.
196   bool materializeParameters(__isl_take isl_set *Set);
197 
198   /// Materialize all parameters in the current scop.
199   ///
200   /// @returns False, iff a problem occurred and the value was not materialized.
201   bool materializeParameters();
202 
203   // Extract the upper bound of this loop
204   //
205   // The isl code generation can generate arbitrary expressions to check if the
206   // upper bound of a loop is reached, but it provides an option to enforce
207   // 'atomic' upper bounds. An 'atomic upper bound is always of the form
208   // iv <= expr, where expr is an (arbitrary) expression not containing iv.
209   //
210   // This function extracts 'atomic' upper bounds. Polly, in general, requires
211   // atomic upper bounds for the following reasons:
212   //
213   // 1. An atomic upper bound is loop invariant
214   //
215   //    It must not be calculated at each loop iteration and can often even be
216   //    hoisted out further by the loop invariant code motion.
217   //
218   // 2. OpenMP needs a loop invariant upper bound to calculate the number
219   //    of loop iterations.
220   //
221   // 3. With the existing code, upper bounds have been easier to implement.
222   isl::ast_expr getUpperBound(isl::ast_node For, CmpInst::Predicate &Predicate);
223 
224   /// Return non-negative number of iterations in case of the following form
225   /// of a loop and -1 otherwise.
226   ///
227   /// for (i = 0; i <= NumIter; i++) {
228   ///   loop body;
229   /// }
230   ///
231   /// NumIter is a non-negative integer value. Condition can have
232   /// isl_ast_op_lt type.
233   int getNumberOfIterations(isl::ast_node For);
234 
235   /// Compute the values and loops referenced in this subtree.
236   ///
237   /// This function looks at all ScopStmts scheduled below the provided For node
238   /// and finds the llvm::Value[s] and llvm::Loops[s] which are referenced but
239   /// not locally defined.
240   ///
241   /// Values that can be synthesized or that are available as globals are
242   /// considered locally defined.
243   ///
244   /// Loops that contain the scop or that are part of the scop are considered
245   /// locally defined. Loops that are before the scop, but do not contain the
246   /// scop itself are considered not locally defined.
247   ///
248   /// @param For    The node defining the subtree.
249   /// @param Values A vector that will be filled with the Values referenced in
250   ///               this subtree.
251   /// @param Loops  A vector that will be filled with the Loops referenced in
252   ///               this subtree.
253   void getReferencesInSubtree(__isl_keep isl_ast_node *For,
254                               SetVector<Value *> &Values,
255                               SetVector<const Loop *> &Loops);
256 
257   /// Change the llvm::Value(s) used for code generation.
258   ///
259   /// When generating code certain values (e.g., references to induction
260   /// variables or array base pointers) in the original code may be replaced by
261   /// new values. This function allows to (partially) update the set of values
262   /// used. A typical use case for this function is the case when we continue
263   /// code generation in a subfunction/kernel function and need to explicitly
264   /// pass down certain values.
265   ///
266   /// @param NewValues A map that maps certain llvm::Values to new llvm::Values.
267   void updateValues(ValueMapT &NewValues);
268 
269   /// Return the most up-to-date version of the llvm::Value for code generation.
270   /// @param Original The Value to check for an up to date version.
271   /// @returns A remapped `Value` from ValueMap, or `Original` if no mapping
272   ///          exists.
273   /// @see IslNodeBuilder::updateValues
274   /// @see IslNodeBuilder::ValueMap
275   Value *getLatestValue(Value *Original) const;
276 
277   /// Generate code for a marker now.
278   ///
279   /// For mark nodes with an unknown name, we just forward the code generation
280   /// to its child. This is currently the only behavior implemented, as there is
281   /// currently not special handling for marker nodes implemented.
282   ///
283   /// @param Mark The node we generate code for.
284   virtual void createMark(__isl_take isl_ast_node *Marker);
285 
286   virtual void createFor(__isl_take isl_ast_node *For);
287 
288   /// Set to remember materialized invariant loads.
289   ///
290   /// An invariant load is identified by its pointer (the SCEV) and its type.
291   SmallSet<std::pair<const SCEV *, Type *>, 16> PreloadedPtrs;
292 
293   /// Preload the memory access at @p AccessRange with @p Build.
294   ///
295   /// @returns The preloaded value casted to type @p Ty
296   Value *preloadUnconditionally(__isl_take isl_set *AccessRange,
297                                 isl_ast_build *Build, Instruction *AccInst);
298 
299   /// Preload the memory load access @p MA.
300   ///
301   /// If @p MA is not always executed it will be conditionally loaded and
302   /// merged with undef from the same type. Hence, if @p MA is executed only
303   /// under condition C then the preload code will look like this:
304   ///
305   /// MA_preload = undef;
306   /// if (C)
307   ///   MA_preload = load MA;
308   /// use MA_preload
309   Value *preloadInvariantLoad(const MemoryAccess &MA,
310                               __isl_take isl_set *Domain);
311 
312   /// Preload the invariant access equivalence class @p IAClass
313   ///
314   /// This function will preload the representing load from @p IAClass and
315   /// map all members of @p IAClass to that preloaded value, potentially casted
316   /// to the required type.
317   ///
318   /// @returns False, iff a problem occurred and the load was not preloaded.
319   bool preloadInvariantEquivClass(InvariantEquivClassTy &IAClass);
320 
321   void createForVector(__isl_take isl_ast_node *For, int VectorWidth);
322   void createForSequential(isl::ast_node For, bool MarkParallel);
323 
324   /// Create LLVM-IR that executes a for node thread parallel.
325   ///
326   /// @param For The FOR isl_ast_node for which code is generated.
327   void createForParallel(__isl_take isl_ast_node *For);
328 
329   /// Create new access functions for modified memory accesses.
330   ///
331   /// In case the access function of one of the memory references in the Stmt
332   /// has been modified, we generate a new isl_ast_expr that reflects the
333   /// newly modified access function and return a map that maps from the
334   /// individual memory references in the statement (identified by their id)
335   /// to these newly generated ast expressions.
336   ///
337   /// @param Stmt  The statement for which to (possibly) generate new access
338   ///              functions.
339   /// @param Node  The ast node corresponding to the statement for us to extract
340   ///              the local schedule from.
341   /// @return A new hash table that contains remappings from memory ids to new
342   ///         access expressions.
343   __isl_give isl_id_to_ast_expr *
344   createNewAccesses(ScopStmt *Stmt, __isl_keep isl_ast_node *Node);
345 
346   /// Generate LLVM-IR that computes the values of the original induction
347   /// variables in function of the newly generated loop induction variables.
348   ///
349   /// Example:
350   ///
351   ///   // Original
352   ///   for i
353   ///     for j
354   ///       S(i)
355   ///
356   ///   Schedule: [i,j] -> [i+j, j]
357   ///
358   ///   // New
359   ///   for c0
360   ///     for c1
361   ///       S(c0 - c1, c1)
362   ///
363   /// Assuming the original code consists of two loops which are
364   /// transformed according to a schedule [i,j] -> [c0=i+j,c1=j]. The resulting
365   /// ast models the original statement as a call expression where each argument
366   /// is an expression that computes the old induction variables from the new
367   /// ones, ordered such that the first argument computes the value of induction
368   /// variable that was outermost in the original code.
369   ///
370   /// @param Expr The call expression that represents the statement.
371   /// @param Stmt The statement that is called.
372   /// @param LTS  The loop to SCEV map in which the mapping from the original
373   ///             loop to a SCEV representing the new loop iv is added. This
374   ///             mapping does not require an explicit induction variable.
375   ///             Instead, we think in terms of an implicit induction variable
376   ///             that counts the number of times a loop is executed. For each
377   ///             original loop this count, expressed in function of the new
378   ///             induction variables, is added to the LTS map.
379   void createSubstitutions(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
380                            LoopToScevMapT &LTS);
381   void createSubstitutionsVector(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
382                                  std::vector<LoopToScevMapT> &VLTS,
383                                  std::vector<Value *> &IVS,
384                                  __isl_take isl_id *IteratorID);
385   virtual void createIf(__isl_take isl_ast_node *If);
386   void createUserVector(__isl_take isl_ast_node *User,
387                         std::vector<Value *> &IVS,
388                         __isl_take isl_id *IteratorID,
389                         __isl_take isl_union_map *Schedule);
390   virtual void createUser(__isl_take isl_ast_node *User);
391   virtual void createBlock(__isl_take isl_ast_node *Block);
392 
393   /// Get the schedule for a given AST node.
394   ///
395   /// This information is used to reason about parallelism of loops or the
396   /// locality of memory accesses under a given schedule.
397   ///
398   /// @param Node The node we want to obtain the schedule for.
399   /// @return Return an isl_union_map that maps from the statements executed
400   ///         below this ast node to the scheduling vectors used to enumerate
401   ///         them.
402   ///
403   virtual __isl_give isl_union_map *
404   getScheduleForAstNode(__isl_take isl_ast_node *Node);
405 
406 private:
407   /// Create code for a copy statement.
408   ///
409   /// A copy statement is expected to have one read memory access and one write
410   /// memory access (in this very order). Data is loaded from the location
411   /// described by the read memory access and written to the location described
412   /// by the write memory access. @p NewAccesses contains for each access
413   /// the isl ast expression that describes the location accessed.
414   ///
415   /// @param Stmt The copy statement that contains the accesses.
416   /// @param NewAccesses The hash table that contains remappings from memory
417   ///                    ids to new access expressions.
418   void generateCopyStmt(ScopStmt *Stmt,
419                         __isl_keep isl_id_to_ast_expr *NewAccesses);
420 
421   /// Materialize a canonical loop induction variable for `L`, which is a loop
422   /// that is *not* present in the Scop.
423   ///
424   /// Note that this is materialized at the point where the `Builder` is
425   /// currently pointing.
426   /// We also populate the `OutsideLoopIterations` map with `L`s SCEV to keep
427   /// track of the induction variable.
428   /// See [Code generation of induction variables of loops outside Scops]
429   Value *materializeNonScopLoopInductionVariable(const Loop *L);
430 };
431 
432 #endif // POLLY_ISLNODEBUILDER_H
433