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