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