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