1 //===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- 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 is the internal state used for llvm translation for loop statement
10 // metadata.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
15 #define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/IR/DebugLoc.h"
20 #include "llvm/IR/Value.h"
21 #include "llvm/Support/Compiler.h"
22 
23 namespace llvm {
24 class BasicBlock;
25 class Instruction;
26 class MDNode;
27 } // end namespace llvm
28 
29 namespace clang {
30 class Attr;
31 class ASTContext;
32 class CodeGenOptions;
33 namespace CodeGen {
34 
35 /// Attributes that may be specified on loops.
36 struct LoopAttributes {
37   explicit LoopAttributes(bool IsParallel = false);
38   void clear();
39 
40   /// Generate llvm.loop.parallel metadata for loads and stores.
41   bool IsParallel;
42 
43   /// State of loop vectorization or unrolling.
44   enum LVEnableState { Unspecified, Enable, Disable, Full };
45 
46   /// Value for llvm.loop.vectorize.enable metadata.
47   LVEnableState VectorizeEnable;
48 
49   /// Value for llvm.loop.unroll.* metadata (enable, disable, or full).
50   LVEnableState UnrollEnable;
51 
52   /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
53   LVEnableState UnrollAndJamEnable;
54 
55   /// Value for llvm.loop.vectorize.predicate metadata
56   LVEnableState VectorizePredicateEnable;
57 
58   /// Value for llvm.loop.vectorize.width metadata.
59   unsigned VectorizeWidth;
60 
61   /// Value for llvm.loop.interleave.count metadata.
62   unsigned InterleaveCount;
63 
64   /// llvm.unroll.
65   unsigned UnrollCount;
66 
67   /// llvm.unroll.
68   unsigned UnrollAndJamCount;
69 
70   /// Value for llvm.loop.distribute.enable metadata.
71   LVEnableState DistributeEnable;
72 
73   /// Value for llvm.loop.pipeline.disable metadata.
74   bool PipelineDisabled;
75 
76   /// Value for llvm.loop.pipeline.iicount metadata.
77   unsigned PipelineInitiationInterval;
78 
79   /// Value for whether the loop is required to make progress.
80   bool MustProgress;
81 };
82 
83 /// Information used when generating a structured loop.
84 class LoopInfo {
85 public:
86   /// Construct a new LoopInfo for the loop with entry Header.
87   LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs,
88            const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
89            LoopInfo *Parent);
90 
91   /// Get the loop id metadata for this loop.
92   llvm::MDNode *getLoopID() const { return TempLoopID.get(); }
93 
94   /// Get the header block of this loop.
95   llvm::BasicBlock *getHeader() const { return Header; }
96 
97   /// Get the set of attributes active for this loop.
98   const LoopAttributes &getAttributes() const { return Attrs; }
99 
100   /// Return this loop's access group or nullptr if it does not have one.
101   llvm::MDNode *getAccessGroup() const { return AccGroup; }
102 
103   /// Create the loop's metadata. Must be called after its nested loops have
104   /// been processed.
105   void finish();
106 
107 private:
108   /// Loop ID metadata.
109   llvm::TempMDTuple TempLoopID;
110   /// Header block of this loop.
111   llvm::BasicBlock *Header;
112   /// The attributes for this loop.
113   LoopAttributes Attrs;
114   /// The access group for memory accesses parallel to this loop.
115   llvm::MDNode *AccGroup = nullptr;
116   /// Start location of this loop.
117   llvm::DebugLoc StartLoc;
118   /// End location of this loop.
119   llvm::DebugLoc EndLoc;
120   /// The next outer loop, or nullptr if this is the outermost loop.
121   LoopInfo *Parent;
122   /// If this loop has unroll-and-jam metadata, this can be set by the inner
123   /// loop's LoopInfo to set the llvm.loop.unroll_and_jam.followup_inner
124   /// metadata.
125   llvm::MDNode *UnrollAndJamInnerFollowup = nullptr;
126 
127   /// Create a LoopID without any transformations.
128   llvm::MDNode *
129   createLoopPropertiesMetadata(llvm::ArrayRef<llvm::Metadata *> LoopProperties);
130 
131   /// Create a LoopID for transformations.
132   ///
133   /// The methods call each other in case multiple transformations are applied
134   /// to a loop. The transformation first to be applied will use LoopID of the
135   /// next transformation in its followup attribute.
136   ///
137   /// @param Attrs             The loop's transformations.
138   /// @param LoopProperties    Non-transformation properties such as debug
139   ///                          location, parallel accesses and disabled
140   ///                          transformations. These are added to the returned
141   ///                          LoopID.
142   /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes
143   ///                          at least one transformation.
144   ///
145   /// @return A LoopID (metadata node) that can be used for the llvm.loop
146   ///         annotation or followup-attribute.
147   /// @{
148   llvm::MDNode *
149   createPipeliningMetadata(const LoopAttributes &Attrs,
150                            llvm::ArrayRef<llvm::Metadata *> LoopProperties,
151                            bool &HasUserTransforms);
152   llvm::MDNode *
153   createPartialUnrollMetadata(const LoopAttributes &Attrs,
154                               llvm::ArrayRef<llvm::Metadata *> LoopProperties,
155                               bool &HasUserTransforms);
156   llvm::MDNode *
157   createUnrollAndJamMetadata(const LoopAttributes &Attrs,
158                              llvm::ArrayRef<llvm::Metadata *> LoopProperties,
159                              bool &HasUserTransforms);
160   llvm::MDNode *
161   createLoopVectorizeMetadata(const LoopAttributes &Attrs,
162                               llvm::ArrayRef<llvm::Metadata *> LoopProperties,
163                               bool &HasUserTransforms);
164   llvm::MDNode *
165   createLoopDistributeMetadata(const LoopAttributes &Attrs,
166                                llvm::ArrayRef<llvm::Metadata *> LoopProperties,
167                                bool &HasUserTransforms);
168   llvm::MDNode *
169   createFullUnrollMetadata(const LoopAttributes &Attrs,
170                            llvm::ArrayRef<llvm::Metadata *> LoopProperties,
171                            bool &HasUserTransforms);
172   /// @}
173 
174   /// Create a LoopID for this loop, including transformation-unspecific
175   /// metadata such as debug location.
176   ///
177   /// @param Attrs             This loop's attributes and transformations.
178   /// @param LoopProperties    Additional non-transformation properties to add
179   ///                          to the LoopID, such as transformation-specific
180   ///                          metadata that are not covered by @p Attrs.
181   /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes
182   ///                          at least one transformation.
183   ///
184   /// @return A LoopID (metadata node) that can be used for the llvm.loop
185   ///         annotation.
186   llvm::MDNode *createMetadata(const LoopAttributes &Attrs,
187                                llvm::ArrayRef<llvm::Metadata *> LoopProperties,
188                                bool &HasUserTransforms);
189 };
190 
191 /// A stack of loop information corresponding to loop nesting levels.
192 /// This stack can be used to prepare attributes which are applied when a loop
193 /// is emitted.
194 class LoopInfoStack {
195   LoopInfoStack(const LoopInfoStack &) = delete;
196   void operator=(const LoopInfoStack &) = delete;
197 
198 public:
199   LoopInfoStack() {}
200 
201   /// Begin a new structured loop. The set of staged attributes will be
202   /// applied to the loop and then cleared.
203   void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc,
204             const llvm::DebugLoc &EndLoc);
205 
206   /// Begin a new structured loop. Stage attributes from the Attrs list.
207   /// The staged attributes are applied to the loop and then cleared.
208   void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
209             const clang::CodeGenOptions &CGOpts,
210             llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc,
211             const llvm::DebugLoc &EndLoc, bool MustProgress = false);
212 
213   /// End the current loop.
214   void pop();
215 
216   /// Return the top loop id metadata.
217   llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); }
218 
219   /// Return true if the top loop is parallel.
220   bool getCurLoopParallel() const {
221     return hasInfo() ? getInfo().getAttributes().IsParallel : false;
222   }
223 
224   /// Function called by the CodeGenFunction when an instruction is
225   /// created.
226   void InsertHelper(llvm::Instruction *I) const;
227 
228   /// Set the next pushed loop as parallel.
229   void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; }
230 
231   /// Set the next pushed loop 'vectorize.enable'
232   void setVectorizeEnable(bool Enable = true) {
233     StagedAttrs.VectorizeEnable =
234         Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
235   }
236 
237   /// Set the next pushed loop as a distribution candidate.
238   void setDistributeState(bool Enable = true) {
239     StagedAttrs.DistributeEnable =
240         Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
241   }
242 
243   /// Set the next pushed loop unroll state.
244   void setUnrollState(const LoopAttributes::LVEnableState &State) {
245     StagedAttrs.UnrollEnable = State;
246   }
247 
248   /// Set the next pushed vectorize predicate state.
249   void setVectorizePredicateState(const LoopAttributes::LVEnableState &State) {
250     StagedAttrs.VectorizePredicateEnable = State;
251   }
252 
253   /// Set the next pushed loop unroll_and_jam state.
254   void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) {
255     StagedAttrs.UnrollAndJamEnable = State;
256   }
257 
258   /// Set the vectorize width for the next loop pushed.
259   void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
260 
261   /// Set the interleave count for the next loop pushed.
262   void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; }
263 
264   /// Set the unroll count for the next loop pushed.
265   void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
266 
267   /// \brief Set the unroll count for the next loop pushed.
268   void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; }
269 
270   /// Set the pipeline disabled state.
271   void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; }
272 
273   /// Set the pipeline initiation interval.
274   void setPipelineInitiationInterval(unsigned C) {
275     StagedAttrs.PipelineInitiationInterval = C;
276   }
277 
278   /// Set no progress for the next loop pushed.
279   void setMustProgress(bool P) { StagedAttrs.MustProgress = P; }
280 
281 private:
282   /// Returns true if there is LoopInfo on the stack.
283   bool hasInfo() const { return !Active.empty(); }
284   /// Return the LoopInfo for the current loop. HasInfo should be called
285   /// first to ensure LoopInfo is present.
286   const LoopInfo &getInfo() const { return *Active.back(); }
287   /// The set of attributes that will be applied to the next pushed loop.
288   LoopAttributes StagedAttrs;
289   /// Stack of active loops.
290   llvm::SmallVector<std::unique_ptr<LoopInfo>, 4> Active;
291 };
292 
293 } // end namespace CodeGen
294 } // end namespace clang
295 
296 #endif
297